rubygems-update 1.8.30 → 2.0.0.preview2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rubygems-update might be problematic. Click here for more details.
- checksums.yaml +6 -6
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +3 -0
- data/.autotest +6 -3
- data/History.txt +137 -63
- data/LICENSE.txt +1 -5
- data/Manifest.txt +69 -32
- data/README.rdoc +11 -9
- data/Rakefile +24 -38
- data/bin/gem +0 -9
- data/bin/update_rubygems +1 -0
- data/lib/rubygems.rb +193 -405
- data/lib/rubygems/available_set.rb +95 -0
- data/lib/rubygems/command.rb +88 -45
- data/lib/rubygems/command_manager.rb +67 -40
- data/lib/rubygems/commands/build_command.rb +5 -23
- data/lib/rubygems/commands/cert_command.rb +199 -57
- data/lib/rubygems/commands/check_command.rb +14 -39
- data/lib/rubygems/commands/cleanup_command.rb +9 -1
- data/lib/rubygems/commands/contents_command.rb +30 -12
- data/lib/rubygems/commands/dependency_command.rb +3 -8
- data/lib/rubygems/commands/environment_command.rb +13 -8
- data/lib/rubygems/commands/fetch_command.rb +3 -16
- data/lib/rubygems/commands/generate_index_command.rb +7 -47
- data/lib/rubygems/commands/help_command.rb +1 -1
- data/lib/rubygems/commands/install_command.rb +69 -36
- data/lib/rubygems/commands/list_command.rb +6 -4
- data/lib/rubygems/commands/lock_command.rb +1 -1
- data/lib/rubygems/commands/mirror_command.rb +17 -0
- data/lib/rubygems/commands/outdated_command.rb +6 -3
- data/lib/rubygems/commands/owner_command.rb +13 -5
- data/lib/rubygems/commands/pristine_command.rb +19 -4
- data/lib/rubygems/commands/push_command.rb +12 -1
- data/lib/rubygems/commands/query_command.rb +43 -27
- data/lib/rubygems/commands/rdoc_command.rb +23 -28
- data/lib/rubygems/commands/search_command.rb +4 -18
- data/lib/rubygems/commands/server_command.rb +1 -1
- data/lib/rubygems/commands/setup_command.rb +124 -38
- data/lib/rubygems/commands/sources_command.rb +16 -16
- data/lib/rubygems/commands/specification_command.rb +11 -13
- data/lib/rubygems/commands/uninstall_command.rb +24 -7
- data/lib/rubygems/commands/unpack_command.rb +7 -3
- data/lib/rubygems/commands/update_command.rb +22 -36
- data/lib/rubygems/commands/yank_command.rb +98 -0
- data/lib/rubygems/compatibility.rb +51 -0
- data/lib/rubygems/config_file.rb +82 -54
- data/lib/rubygems/core_ext/kernel_gem.rb +53 -0
- data/lib/rubygems/core_ext/kernel_require.rb +119 -0
- data/lib/rubygems/defaults.rb +10 -21
- data/lib/rubygems/dependency.rb +61 -10
- data/lib/rubygems/dependency_installer.rb +157 -69
- data/lib/rubygems/dependency_list.rb +11 -19
- data/lib/rubygems/dependency_resolver.rb +562 -0
- data/lib/rubygems/deprecate.rb +40 -40
- data/lib/rubygems/errors.rb +77 -24
- data/lib/rubygems/exceptions.rb +25 -7
- data/lib/rubygems/ext/builder.rb +20 -23
- data/lib/rubygems/ext/configure_builder.rb +2 -2
- data/lib/rubygems/ext/ext_conf_builder.rb +5 -45
- data/lib/rubygems/ext/rake_builder.rb +2 -2
- data/lib/rubygems/gem_runner.rb +3 -16
- data/lib/rubygems/gemcutter_utilities.rb +22 -7
- data/lib/rubygems/indexer.rb +6 -159
- data/lib/rubygems/install_message.rb +12 -0
- data/lib/rubygems/install_update_options.rb +56 -18
- data/lib/rubygems/installer.rb +244 -134
- data/lib/rubygems/installer_test_case.rb +71 -19
- data/lib/rubygems/mock_gem_ui.rb +17 -0
- data/lib/rubygems/name_tuple.rb +110 -0
- data/lib/rubygems/package.rb +514 -43
- data/lib/rubygems/package/digest_io.rb +64 -0
- data/lib/rubygems/package/old.rb +147 -0
- data/lib/rubygems/package/tar_header.rb +18 -55
- data/lib/rubygems/package/tar_reader.rb +20 -3
- data/lib/rubygems/package/tar_writer.rb +63 -7
- data/lib/rubygems/package_task.rb +3 -4
- data/lib/rubygems/path_support.rb +14 -7
- data/lib/rubygems/platform.rb +19 -26
- data/lib/rubygems/rdoc.rb +316 -0
- data/lib/rubygems/remote_fetcher.rb +117 -54
- data/lib/rubygems/request_set.rb +182 -0
- data/lib/rubygems/requirement.rb +63 -26
- data/lib/rubygems/security.rb +295 -555
- data/lib/rubygems/security/policies.rb +115 -0
- data/lib/rubygems/security/policy.rb +227 -0
- data/lib/rubygems/security/signer.rb +136 -0
- data/lib/rubygems/security/trust_dir.rb +104 -0
- data/lib/rubygems/server.rb +45 -55
- data/lib/rubygems/source.rb +144 -0
- data/lib/rubygems/source_list.rb +87 -0
- data/lib/rubygems/source_local.rb +92 -0
- data/lib/rubygems/source_specific_file.rb +28 -0
- data/lib/rubygems/spec_fetcher.rb +116 -184
- data/lib/rubygems/specification.rb +731 -335
- data/lib/rubygems/ssl_certs/AddTrustExternalCARoot.pem +88 -30
- data/lib/rubygems/ssl_certs/Entrust_net-Secure-Server-Certification-Authority.pem +90 -0
- data/lib/rubygems/ssl_certs/VerisignClass3PublicPrimaryCertificationAuthority-G2.pem +57 -0
- data/lib/rubygems/syck_hack.rb +2 -0
- data/lib/rubygems/test_case.rb +199 -109
- data/lib/rubygems/test_utilities.rb +25 -5
- data/lib/rubygems/uninstaller.rb +62 -20
- data/lib/rubygems/user_interaction.rb +10 -0
- data/lib/rubygems/validator.rb +33 -40
- data/lib/rubygems/version.rb +19 -8
- data/setup.rb +8 -1
- data/test/rubygems/alternate_cert.pem +9 -0
- data/test/rubygems/alternate_cert_32.pem +9 -0
- data/test/rubygems/alternate_key.pem +9 -0
- data/test/rubygems/bad_rake.rb +1 -0
- data/test/rubygems/child_cert.pem +9 -0
- data/test/rubygems/child_cert_32.pem +9 -0
- data/test/rubygems/child_key.pem +9 -0
- data/test/rubygems/data/null-type.gemspec.rz +0 -0
- data/test/rubygems/expired_cert.pem +9 -0
- data/test/rubygems/future_cert.pem +9 -0
- data/test/rubygems/future_cert_32.pem +9 -0
- data/test/rubygems/good_rake.rb +1 -0
- data/test/rubygems/grandchild_cert.pem +9 -0
- data/test/rubygems/grandchild_cert_32.pem +9 -0
- data/test/rubygems/grandchild_key.pem +9 -0
- data/test/rubygems/invalid_issuer_cert.pem +9 -0
- data/test/rubygems/invalid_issuer_cert_32.pem +9 -0
- data/test/rubygems/invalid_key.pem +9 -0
- data/test/rubygems/invalid_signer_cert.pem +9 -0
- data/test/rubygems/invalid_signer_cert_32.pem +9 -0
- data/test/rubygems/invalidchild_cert.pem +9 -0
- data/test/rubygems/invalidchild_cert_32.pem +9 -0
- data/test/rubygems/invalidchild_key.pem +9 -0
- data/test/rubygems/plugin/exception/rubygems_plugin.rb +1 -1
- data/test/rubygems/plugin/standarderror/rubygems_plugin.rb +1 -1
- data/test/rubygems/private_key.pem +7 -25
- data/test/rubygems/public_cert.pem +8 -18
- data/test/rubygems/public_cert_32.pem +10 -0
- data/test/rubygems/public_key.pem +4 -0
- data/test/rubygems/rubygems/commands/crash_command.rb +1 -1
- data/test/rubygems/test_config.rb +4 -6
- data/test/rubygems/test_deprecate.rb +76 -0
- data/test/rubygems/test_gem.rb +318 -83
- data/test/rubygems/test_gem_available_set.rb +106 -0
- data/test/rubygems/test_gem_command.rb +10 -0
- data/test/rubygems/test_gem_command_manager.rb +55 -9
- data/test/rubygems/test_gem_commands_build_command.rb +11 -19
- data/test/rubygems/test_gem_commands_cert_command.rb +441 -42
- data/test/rubygems/test_gem_commands_cleanup_command.rb +29 -1
- data/test/rubygems/test_gem_commands_contents_command.rb +23 -0
- data/test/rubygems/test_gem_commands_dependency_command.rb +5 -0
- data/test/rubygems/test_gem_commands_fetch_command.rb +19 -20
- data/test/rubygems/test_gem_commands_generate_index_command.rb +2 -83
- data/test/rubygems/test_gem_commands_help_command.rb +2 -1
- data/test/rubygems/test_gem_commands_install_command.rb +647 -48
- data/test/rubygems/test_gem_commands_mirror.rb +32 -0
- data/test/rubygems/test_gem_commands_owner_command.rb +4 -8
- data/test/rubygems/test_gem_commands_pristine_command.rb +99 -4
- data/test/rubygems/test_gem_commands_push_command.rb +62 -8
- data/test/rubygems/test_gem_commands_query_command.rb +51 -0
- data/test/rubygems/test_gem_commands_search_command.rb +25 -0
- data/test/rubygems/test_gem_commands_setup_command.rb +45 -0
- data/test/rubygems/test_gem_commands_sources_command.rb +21 -6
- data/test/rubygems/test_gem_commands_specification_command.rb +33 -1
- data/test/rubygems/test_gem_commands_uninstall_command.rb +91 -31
- data/test/rubygems/test_gem_commands_unpack_command.rb +3 -3
- data/test/rubygems/test_gem_commands_update_command.rb +56 -38
- data/test/rubygems/test_gem_commands_which_command.rb +4 -4
- data/test/rubygems/test_gem_commands_yank_command.rb +97 -0
- data/test/rubygems/test_gem_config_file.rb +66 -21
- data/test/rubygems/test_gem_dependency.rb +46 -0
- data/test/rubygems/test_gem_dependency_installer.rb +228 -18
- data/test/rubygems/test_gem_dependency_list.rb +0 -9
- data/test/rubygems/test_gem_dependency_resolver.rb +327 -0
- data/test/rubygems/test_gem_ext_configure_builder.rb +4 -4
- data/test/rubygems/test_gem_ext_ext_conf_builder.rb +21 -49
- data/test/rubygems/test_gem_ext_rake_builder.rb +13 -13
- data/test/rubygems/test_gem_gem_runner.rb +27 -5
- data/test/rubygems/test_gem_gemcutter_utilities.rb +19 -0
- data/test/rubygems/test_gem_indexer.rb +14 -227
- data/test/rubygems/test_gem_install_update_options.rb +83 -3
- data/test/rubygems/test_gem_installer.rb +211 -236
- data/test/rubygems/test_gem_local_remote_options.rb +8 -2
- data/test/rubygems/test_gem_name_tuple.rb +15 -0
- data/test/rubygems/test_gem_package.rb +547 -0
- data/test/rubygems/test_gem_package_old.rb +37 -0
- data/test/rubygems/test_gem_package_tar_reader.rb +32 -0
- data/test/rubygems/test_gem_package_tar_writer.rb +84 -1
- data/test/rubygems/test_gem_path_support.rb +4 -30
- data/test/rubygems/test_gem_platform.rb +3 -6
- data/test/rubygems/test_gem_rdoc.rb +245 -0
- data/test/rubygems/test_gem_remote_fetcher.rb +51 -5
- data/test/rubygems/test_gem_request_set.rb +70 -0
- data/test/rubygems/test_gem_requirement.rb +53 -24
- data/test/rubygems/test_gem_security.rb +189 -43
- data/test/rubygems/test_gem_security_policy.rb +376 -0
- data/test/rubygems/test_gem_security_signer.rb +184 -0
- data/test/rubygems/test_gem_security_trust_dir.rb +94 -0
- data/test/rubygems/test_gem_server.rb +31 -36
- data/test/rubygems/test_gem_silent_ui.rb +2 -2
- data/test/rubygems/test_gem_source.rb +188 -0
- data/test/rubygems/test_gem_source_list.rb +87 -0
- data/test/rubygems/test_gem_source_local.rb +83 -0
- data/test/rubygems/test_gem_source_specific_file.rb +33 -0
- data/test/rubygems/test_gem_spec_fetcher.rb +91 -255
- data/test/rubygems/test_gem_specification.rb +293 -39
- data/test/rubygems/test_gem_uninstaller.rb +136 -13
- data/test/rubygems/test_gem_validator.rb +14 -41
- data/test/rubygems/test_gem_version.rb +15 -21
- data/test/rubygems/test_require.rb +193 -0
- data/test/rubygems/wrong_key_cert.pem +9 -0
- data/test/rubygems/wrong_key_cert_32.pem +9 -0
- metadata +171 -83
- metadata.gz.sig +1 -0
- data/CVE-2013-4287.txt +0 -36
- data/CVE-2013-4363.txt +0 -45
- data/ci_build.sh +0 -27
- data/cruise_config.rb +0 -32
- data/lib/rbconfig/datadir.rb +0 -13
- data/lib/rubygems/builder.rb +0 -99
- data/lib/rubygems/custom_require.rb +0 -69
- data/lib/rubygems/doc_manager.rb +0 -243
- data/lib/rubygems/format.rb +0 -82
- data/lib/rubygems/gem_openssl.rb +0 -90
- data/lib/rubygems/gem_path_searcher.rb +0 -172
- data/lib/rubygems/old_format.rb +0 -153
- data/lib/rubygems/package/f_sync_dir.rb +0 -23
- data/lib/rubygems/package/tar_input.rb +0 -234
- data/lib/rubygems/package/tar_output.rb +0 -146
- data/lib/rubygems/require_paths_builder.rb +0 -18
- data/lib/rubygems/source_index.rb +0 -406
- data/lib/rubygems/ssl_certs/AddTrustExternalCARoot-2048.pem +0 -25
- data/lib/rubygems/ssl_certs/Class3PublicPrimaryCertificationAuthority.pem +0 -14
- data/lib/rubygems/ssl_certs/DigiCertHighAssuranceEVRootCA.pem +0 -23
- data/lib/rubygems/ssl_certs/EntrustnetSecureServerCertificationAuthority.pem +0 -28
- data/lib/rubygems/ssl_certs/GeoTrustGlobalCA.pem +0 -20
- data/test/rubygems/test_bundled_ca.rb +0 -59
- data/test/rubygems/test_gem_builder.rb +0 -44
- data/test/rubygems/test_gem_doc_manager.rb +0 -32
- data/test/rubygems/test_gem_ext_builder.rb +0 -58
- data/test/rubygems/test_gem_format.rb +0 -88
- data/test/rubygems/test_gem_gem_path_searcher.rb +0 -94
- data/test/rubygems/test_gem_package_tar_input.rb +0 -129
- data/test/rubygems/test_gem_package_tar_output.rb +0 -101
- data/test/rubygems/test_gem_source_index.rb +0 -250
- data/util/update_bundled_ca_certificates.rb +0 -103
@@ -0,0 +1,376 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
|
3
|
+
require 'rubygems/test_case'
|
4
|
+
|
5
|
+
class TestGemSecurityPolicy < Gem::TestCase
|
6
|
+
|
7
|
+
ALTERNATE_KEY = load_key 'alternate'
|
8
|
+
INVALID_KEY = load_key 'invalid'
|
9
|
+
CHILD_KEY = load_key 'child'
|
10
|
+
GRANDCHILD_KEY = load_key 'grandchild'
|
11
|
+
INVALIDCHILD_KEY = load_key 'invalidchild'
|
12
|
+
|
13
|
+
ALTERNATE_CERT = load_cert 'alternate'
|
14
|
+
CHILD_CERT = load_cert 'child'
|
15
|
+
EXPIRED_CERT = load_cert 'expired'
|
16
|
+
FUTURE_CERT = load_cert 'future'
|
17
|
+
GRANDCHILD_CERT = load_cert 'grandchild'
|
18
|
+
INVALIDCHILD_CERT = load_cert 'invalidchild'
|
19
|
+
INVALID_ISSUER_CERT = load_cert 'invalid_issuer'
|
20
|
+
INVALID_SIGNER_CERT = load_cert 'invalid_signer'
|
21
|
+
WRONG_KEY_CERT = load_cert 'wrong_key'
|
22
|
+
|
23
|
+
def setup
|
24
|
+
super
|
25
|
+
|
26
|
+
@spec = quick_gem 'a' do |s|
|
27
|
+
s.description = 'π'
|
28
|
+
s.files = %w[lib/code.rb]
|
29
|
+
end
|
30
|
+
|
31
|
+
@sha1 = OpenSSL::Digest::SHA1
|
32
|
+
@trust_dir = Gem::Security.trust_dir.dir # HACK use the object
|
33
|
+
|
34
|
+
@almost_no = Gem::Security::AlmostNoSecurity
|
35
|
+
@low = Gem::Security::LowSecurity
|
36
|
+
@high = Gem::Security::HighSecurity
|
37
|
+
|
38
|
+
@chain = Gem::Security::Policy.new(
|
39
|
+
'Chain',
|
40
|
+
:verify_data => true,
|
41
|
+
:verify_signer => true,
|
42
|
+
:verify_chain => true,
|
43
|
+
:verify_root => false,
|
44
|
+
:only_trusted => false,
|
45
|
+
:only_signed => false
|
46
|
+
)
|
47
|
+
|
48
|
+
@root = Gem::Security::Policy.new(
|
49
|
+
'Root',
|
50
|
+
:verify_data => true,
|
51
|
+
:verify_signer => true,
|
52
|
+
:verify_chain => true,
|
53
|
+
:verify_root => true,
|
54
|
+
:only_trusted => false,
|
55
|
+
:only_signed => false
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_check_data
|
60
|
+
data = digest 'hello'
|
61
|
+
|
62
|
+
signature = sign data
|
63
|
+
|
64
|
+
assert @almost_no.check_data(PUBLIC_KEY, @sha1, signature, data)
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_check_data_invalid
|
68
|
+
data = digest 'hello'
|
69
|
+
|
70
|
+
signature = sign data
|
71
|
+
|
72
|
+
invalid = digest 'hello!'
|
73
|
+
|
74
|
+
e = assert_raises Gem::Security::Exception do
|
75
|
+
@almost_no.check_data PUBLIC_KEY, @sha1, signature, invalid
|
76
|
+
end
|
77
|
+
|
78
|
+
assert_equal 'invalid signature', e.message
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_check_chain
|
82
|
+
chain = [PUBLIC_CERT, CHILD_CERT, GRANDCHILD_CERT]
|
83
|
+
|
84
|
+
assert @chain.check_chain chain, Time.now
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_check_chain_invalid
|
88
|
+
chain = [PUBLIC_CERT, CHILD_CERT, INVALIDCHILD_CERT]
|
89
|
+
|
90
|
+
e = assert_raises Gem::Security::Exception do
|
91
|
+
@chain.check_chain chain, Time.now
|
92
|
+
end
|
93
|
+
|
94
|
+
assert_equal "invalid signing chain: " \
|
95
|
+
"certificate #{INVALIDCHILD_CERT.subject} " \
|
96
|
+
"was not issued by #{CHILD_CERT.subject}", e.message
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_check_cert
|
100
|
+
assert @low.check_cert(PUBLIC_CERT, nil, Time.now)
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_check_cert_expired
|
104
|
+
e = assert_raises Gem::Security::Exception do
|
105
|
+
@low.check_cert EXPIRED_CERT, nil, Time.now
|
106
|
+
end
|
107
|
+
|
108
|
+
assert_equal "certificate #{EXPIRED_CERT.subject} " \
|
109
|
+
"not valid after #{EXPIRED_CERT.not_after}",
|
110
|
+
e.message
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_check_cert_future
|
114
|
+
e = assert_raises Gem::Security::Exception do
|
115
|
+
@low.check_cert FUTURE_CERT, nil, Time.now
|
116
|
+
end
|
117
|
+
|
118
|
+
assert_equal "certificate #{FUTURE_CERT.subject} " \
|
119
|
+
"not valid before #{FUTURE_CERT.not_before}",
|
120
|
+
e.message
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_check_cert_invalid_issuer
|
124
|
+
e = assert_raises Gem::Security::Exception do
|
125
|
+
@low.check_cert INVALID_ISSUER_CERT, PUBLIC_CERT, Time.now
|
126
|
+
end
|
127
|
+
|
128
|
+
assert_equal "certificate #{INVALID_ISSUER_CERT.subject} " \
|
129
|
+
"was not issued by #{PUBLIC_CERT.subject}",
|
130
|
+
e.message
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_check_cert_issuer
|
134
|
+
assert @low.check_cert(CHILD_CERT, PUBLIC_CERT, Time.now)
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_check_key
|
138
|
+
assert @almost_no.check_key(PUBLIC_CERT, PRIVATE_KEY)
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_check_key_wrong_key
|
142
|
+
e = assert_raises Gem::Security::Exception do
|
143
|
+
@almost_no.check_key(PUBLIC_CERT, ALTERNATE_KEY)
|
144
|
+
end
|
145
|
+
|
146
|
+
assert_equal "certificate #{PUBLIC_CERT.subject} " \
|
147
|
+
"does not match the signing key", e.message
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_check_root
|
151
|
+
chain = [PUBLIC_CERT, CHILD_CERT, INVALIDCHILD_CERT]
|
152
|
+
|
153
|
+
assert @chain.check_root chain, Time.now
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_check_root_invalid_signer
|
157
|
+
chain = [INVALID_SIGNER_CERT]
|
158
|
+
|
159
|
+
e = assert_raises Gem::Security::Exception do
|
160
|
+
@chain.check_root chain, Time.now
|
161
|
+
end
|
162
|
+
|
163
|
+
assert_equal "certificate #{INVALID_SIGNER_CERT.subject} " \
|
164
|
+
"was not issued by #{INVALID_SIGNER_CERT.issuer}",
|
165
|
+
e.message
|
166
|
+
end
|
167
|
+
|
168
|
+
def test_check_root_not_self_signed
|
169
|
+
chain = [INVALID_ISSUER_CERT]
|
170
|
+
|
171
|
+
e = assert_raises Gem::Security::Exception do
|
172
|
+
@chain.check_root chain, Time.now
|
173
|
+
end
|
174
|
+
|
175
|
+
assert_equal "root certificate #{INVALID_ISSUER_CERT.subject} " \
|
176
|
+
"is not self-signed (issuer #{INVALID_ISSUER_CERT.issuer})",
|
177
|
+
e.message
|
178
|
+
end
|
179
|
+
|
180
|
+
def test_check_trust
|
181
|
+
Gem::Security.trust_dir.trust_cert PUBLIC_CERT
|
182
|
+
|
183
|
+
assert @high.check_trust [PUBLIC_CERT], @sha1, @trust_dir
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_check_trust_child
|
187
|
+
Gem::Security.trust_dir.trust_cert PUBLIC_CERT
|
188
|
+
|
189
|
+
assert @high.check_trust [PUBLIC_CERT, CHILD_CERT], @sha1, @trust_dir
|
190
|
+
end
|
191
|
+
|
192
|
+
def test_check_trust_mismatch
|
193
|
+
Gem::Security.trust_dir.trust_cert PUBLIC_CERT
|
194
|
+
|
195
|
+
e = assert_raises Gem::Security::Exception do
|
196
|
+
@high.check_trust [WRONG_KEY_CERT], @sha1, @trust_dir
|
197
|
+
end
|
198
|
+
|
199
|
+
assert_equal "trusted root certificate #{PUBLIC_CERT.subject} checksum " \
|
200
|
+
"does not match signing root certificate checksum", e.message
|
201
|
+
end
|
202
|
+
|
203
|
+
def test_check_trust_no_trust
|
204
|
+
e = assert_raises Gem::Security::Exception do
|
205
|
+
@high.check_trust [PUBLIC_CERT], @sha1, @trust_dir
|
206
|
+
end
|
207
|
+
|
208
|
+
assert_equal "root cert #{PUBLIC_CERT.subject} is not trusted", e.message
|
209
|
+
end
|
210
|
+
|
211
|
+
def test_check_trust_no_trust_child
|
212
|
+
e = assert_raises Gem::Security::Exception do
|
213
|
+
@high.check_trust [PUBLIC_CERT, CHILD_CERT], @sha1, @trust_dir
|
214
|
+
end
|
215
|
+
|
216
|
+
assert_equal "root cert #{PUBLIC_CERT.subject} is not trusted " \
|
217
|
+
"(root of signing cert #{CHILD_CERT.subject})", e.message
|
218
|
+
end
|
219
|
+
|
220
|
+
def test_verify
|
221
|
+
Gem::Security.trust_dir.trust_cert PUBLIC_CERT
|
222
|
+
|
223
|
+
assert @almost_no.verify [PUBLIC_CERT]
|
224
|
+
end
|
225
|
+
|
226
|
+
def test_verify_chain_signatures
|
227
|
+
Gem::Security.trust_dir.trust_cert PUBLIC_CERT
|
228
|
+
|
229
|
+
data = digest 'hello'
|
230
|
+
digest = { 'SHA1' => { 0 => data } }
|
231
|
+
signature = { 0 => sign(data, PRIVATE_KEY) }
|
232
|
+
|
233
|
+
assert @high.verify [PUBLIC_CERT], nil, digest, signature
|
234
|
+
end
|
235
|
+
|
236
|
+
def test_verify_chain_key
|
237
|
+
assert @almost_no.verify [PUBLIC_CERT], PRIVATE_KEY
|
238
|
+
end
|
239
|
+
|
240
|
+
def test_verify_signatures_chain
|
241
|
+
data = digest 'hello'
|
242
|
+
digest = { 'SHA1' => { 0 => data } }
|
243
|
+
signature = { 0 => sign(data, CHILD_KEY) }
|
244
|
+
|
245
|
+
@spec.cert_chain = [PUBLIC_CERT, CHILD_CERT]
|
246
|
+
|
247
|
+
assert @chain.verify_signatures @spec, digest, signature
|
248
|
+
end
|
249
|
+
|
250
|
+
def test_verify_signatures_data
|
251
|
+
data = digest 'hello'
|
252
|
+
digest = { 'SHA1' => { 0 => data } }
|
253
|
+
signature = { 0 => sign(data) }
|
254
|
+
|
255
|
+
@spec.cert_chain = [PUBLIC_CERT]
|
256
|
+
|
257
|
+
@almost_no.verify_signatures @spec, digest, signature
|
258
|
+
end
|
259
|
+
|
260
|
+
def test_verify_signatures_root
|
261
|
+
data = digest 'hello'
|
262
|
+
digest = { 'SHA1' => { 0 => data } }
|
263
|
+
signature = { 0 => sign(data, CHILD_KEY) }
|
264
|
+
|
265
|
+
@spec.cert_chain = [PUBLIC_CERT, CHILD_CERT]
|
266
|
+
|
267
|
+
assert @root.verify_signatures @spec, digest, signature
|
268
|
+
end
|
269
|
+
|
270
|
+
def test_verify_signatures_signer
|
271
|
+
data = digest 'hello'
|
272
|
+
digest = { 'SHA1' => { 0 => data } }
|
273
|
+
signature = { 0 => sign(data) }
|
274
|
+
|
275
|
+
@spec.cert_chain = [PUBLIC_CERT]
|
276
|
+
|
277
|
+
assert @low.verify_signatures @spec, digest, signature
|
278
|
+
end
|
279
|
+
|
280
|
+
def test_verify_signatures_trust
|
281
|
+
Gem::Security.trust_dir.trust_cert PUBLIC_CERT
|
282
|
+
|
283
|
+
data = digest 'hello'
|
284
|
+
digest = { 'SHA1' => { 0 => data } }
|
285
|
+
signature = { 0 => sign(data, PRIVATE_KEY) }
|
286
|
+
|
287
|
+
@spec.cert_chain = [PUBLIC_CERT]
|
288
|
+
|
289
|
+
assert @high.verify_signatures @spec, digest, signature
|
290
|
+
end
|
291
|
+
|
292
|
+
def test_verify_signatures
|
293
|
+
Gem::Security.trust_dir.trust_cert PUBLIC_CERT
|
294
|
+
|
295
|
+
@spec.cert_chain = [PUBLIC_CERT.to_s]
|
296
|
+
|
297
|
+
metadata_gz = Gem.gzip @spec.to_yaml
|
298
|
+
|
299
|
+
package = Gem::Package.new 'nonexistent.gem'
|
300
|
+
package.checksums['SHA1'] = {}
|
301
|
+
|
302
|
+
s = StringIO.new metadata_gz
|
303
|
+
def s.full_name() 'metadata.gz' end
|
304
|
+
|
305
|
+
digests = package.digest s
|
306
|
+
metadata_gz_digest = digests['SHA1']['metadata.gz']
|
307
|
+
|
308
|
+
signatures = {}
|
309
|
+
signatures['metadata.gz'] =
|
310
|
+
PRIVATE_KEY.sign @sha1.new, metadata_gz_digest.digest
|
311
|
+
|
312
|
+
assert @high.verify_signatures @spec, digests, signatures
|
313
|
+
end
|
314
|
+
|
315
|
+
def test_verify_signatures_missing
|
316
|
+
Gem::Security.trust_dir.trust_cert PUBLIC_CERT
|
317
|
+
|
318
|
+
@spec.cert_chain = [PUBLIC_CERT.to_s]
|
319
|
+
|
320
|
+
metadata_gz = Gem.gzip @spec.to_yaml
|
321
|
+
|
322
|
+
package = Gem::Package.new 'nonexistent.gem'
|
323
|
+
package.checksums['SHA1'] = {}
|
324
|
+
|
325
|
+
s = StringIO.new metadata_gz
|
326
|
+
def s.full_name() 'metadata.gz' end
|
327
|
+
|
328
|
+
digests = package.digest s
|
329
|
+
digests['SHA1']['data.tar.gz'] = OpenSSL::Digest.new 'SHA1', 'hello'
|
330
|
+
|
331
|
+
metadata_gz_digest = digests['SHA1']['metadata.gz']
|
332
|
+
|
333
|
+
signatures = {}
|
334
|
+
signatures['metadata.gz'] =
|
335
|
+
PRIVATE_KEY.sign @sha1.new, metadata_gz_digest.digest
|
336
|
+
|
337
|
+
e = assert_raises Gem::Security::Exception do
|
338
|
+
@high.verify_signatures @spec, digests, signatures
|
339
|
+
end
|
340
|
+
|
341
|
+
assert_equal 'missing signature for data.tar.gz', e.message
|
342
|
+
end
|
343
|
+
|
344
|
+
def test_verify_signatures_none
|
345
|
+
Gem::Security.trust_dir.trust_cert PUBLIC_CERT
|
346
|
+
|
347
|
+
@spec.cert_chain = [PUBLIC_CERT.to_s]
|
348
|
+
|
349
|
+
metadata_gz = Gem.gzip @spec.to_yaml
|
350
|
+
|
351
|
+
package = Gem::Package.new 'nonexistent.gem'
|
352
|
+
package.checksums['SHA1'] = {}
|
353
|
+
|
354
|
+
s = StringIO.new metadata_gz
|
355
|
+
def s.full_name() 'metadata.gz' end
|
356
|
+
|
357
|
+
digests = package.digest s
|
358
|
+
digests['SHA1']['data.tar.gz'] = OpenSSL::Digest.new 'SHA1', 'hello'
|
359
|
+
|
360
|
+
assert_raises Gem::Security::Exception do
|
361
|
+
@almost_no.verify_signatures @spec, digests, {}
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
def digest data
|
366
|
+
digester = @sha1.new
|
367
|
+
digester << data
|
368
|
+
digester
|
369
|
+
end
|
370
|
+
|
371
|
+
def sign data, key = PRIVATE_KEY
|
372
|
+
key.sign @sha1.new, data.digest
|
373
|
+
end
|
374
|
+
|
375
|
+
end
|
376
|
+
|
@@ -0,0 +1,184 @@
|
|
1
|
+
require 'rubygems/test_case'
|
2
|
+
|
3
|
+
class TestGemSecuritySigner < Gem::TestCase
|
4
|
+
|
5
|
+
ALTERNATE_KEY = load_key 'alternate'
|
6
|
+
CHILD_KEY = load_key 'child'
|
7
|
+
GRANDCHILD_KEY = load_key 'grandchild'
|
8
|
+
|
9
|
+
CHILD_CERT = load_cert 'child'
|
10
|
+
GRANDCHILD_CERT = load_cert 'grandchild'
|
11
|
+
EXPIRED_CERT = load_cert 'expired'
|
12
|
+
|
13
|
+
def setup
|
14
|
+
super
|
15
|
+
|
16
|
+
@cert_file = PUBLIC_CERT
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_initialize
|
20
|
+
signer = Gem::Security::Signer.new nil, nil
|
21
|
+
|
22
|
+
assert_nil signer.key
|
23
|
+
assert_nil signer.cert_chain
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_initialize_cert_chain_empty
|
27
|
+
signer = Gem::Security::Signer.new PUBLIC_KEY, []
|
28
|
+
|
29
|
+
assert_empty signer.cert_chain
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_initialize_cert_chain_mixed
|
33
|
+
signer = Gem::Security::Signer.new nil, [@cert_file, CHILD_CERT]
|
34
|
+
|
35
|
+
assert_equal [PUBLIC_CERT, CHILD_CERT].map { |c| c.to_pem },
|
36
|
+
signer.cert_chain.map { |c| c.to_pem }
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_initialize_cert_chain_invalid
|
40
|
+
assert_raises OpenSSL::X509::CertificateError do
|
41
|
+
Gem::Security::Signer.new nil, ['garbage']
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_initialize_cert_chain_path
|
46
|
+
signer = Gem::Security::Signer.new nil, [@cert_file]
|
47
|
+
|
48
|
+
assert_equal [PUBLIC_CERT].map { |c| c.to_pem },
|
49
|
+
signer.cert_chain.map { |c| c.to_pem }
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_initialize_default
|
53
|
+
private_key_path = File.join Gem.user_home, 'gem-private_key.pem'
|
54
|
+
Gem::Security.write PRIVATE_KEY, private_key_path
|
55
|
+
|
56
|
+
public_cert_path = File.join Gem.user_home, 'gem-public_cert.pem'
|
57
|
+
Gem::Security.write PUBLIC_CERT, public_cert_path
|
58
|
+
|
59
|
+
signer = Gem::Security::Signer.new nil, nil
|
60
|
+
|
61
|
+
assert_equal PRIVATE_KEY.to_pem, signer.key.to_pem
|
62
|
+
assert_equal [PUBLIC_CERT.to_pem], signer.cert_chain.map { |c| c.to_pem }
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_initialize_key_path
|
66
|
+
key_file = PRIVATE_KEY_PATH
|
67
|
+
|
68
|
+
signer = Gem::Security::Signer.new key_file, nil
|
69
|
+
|
70
|
+
assert_equal PRIVATE_KEY.to_s, signer.key.to_s
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_load_cert_chain
|
74
|
+
Gem::Security.trust_dir.trust_cert PUBLIC_CERT
|
75
|
+
|
76
|
+
signer = Gem::Security::Signer.new nil, []
|
77
|
+
signer.cert_chain.replace [CHILD_CERT]
|
78
|
+
|
79
|
+
signer.load_cert_chain
|
80
|
+
|
81
|
+
assert_equal [PUBLIC_CERT.to_pem, CHILD_CERT.to_pem],
|
82
|
+
signer.cert_chain.map { |c| c.to_pem }
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_load_cert_chain_broken
|
86
|
+
Gem::Security.trust_dir.trust_cert CHILD_CERT
|
87
|
+
|
88
|
+
signer = Gem::Security::Signer.new nil, []
|
89
|
+
signer.cert_chain.replace [GRANDCHILD_CERT]
|
90
|
+
|
91
|
+
signer.load_cert_chain
|
92
|
+
|
93
|
+
assert_equal [CHILD_CERT.to_pem, GRANDCHILD_CERT.to_pem],
|
94
|
+
signer.cert_chain.map { |c| c.to_pem }
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_sign
|
98
|
+
signer = Gem::Security::Signer.new PRIVATE_KEY, [PUBLIC_CERT]
|
99
|
+
|
100
|
+
signature = signer.sign 'hello'
|
101
|
+
|
102
|
+
expected = <<-EXPECTED
|
103
|
+
oZXzQRdq0mJpAghICQvjvlB7ZyZtE4diL5jce0Fa20PkLjOvDgpuZCs6Ppu5
|
104
|
+
LtG89EQMMBHsAyc8NMCd4oWm6Q==
|
105
|
+
EXPECTED
|
106
|
+
|
107
|
+
assert_equal expected, [signature].pack('m')
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_sign_expired
|
111
|
+
signer = Gem::Security::Signer.new PRIVATE_KEY, [EXPIRED_CERT]
|
112
|
+
|
113
|
+
assert_raises Gem::Security::Exception do
|
114
|
+
signer.sign 'hello'
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_sign_expired_auto_update
|
119
|
+
FileUtils.mkdir_p Gem.user_home, :mode => 0700
|
120
|
+
|
121
|
+
private_key_path = File.join(Gem.user_home, 'gem-private_key.pem')
|
122
|
+
Gem::Security.write PRIVATE_KEY, private_key_path
|
123
|
+
|
124
|
+
cert_path = File.join Gem.user_home, 'gem-public_cert.pem'
|
125
|
+
Gem::Security.write EXPIRED_CERT, cert_path
|
126
|
+
|
127
|
+
signer = Gem::Security::Signer.new PRIVATE_KEY, [EXPIRED_CERT]
|
128
|
+
|
129
|
+
signer.sign 'hello'
|
130
|
+
|
131
|
+
cert = OpenSSL::X509::Certificate.new File.read cert_path
|
132
|
+
|
133
|
+
refute_equal EXPIRED_CERT.to_pem, cert.to_pem
|
134
|
+
assert_in_delta Time.now, cert.not_before, 10
|
135
|
+
|
136
|
+
expiry = EXPIRED_CERT.not_after.strftime "%Y%m%d%H%M%S"
|
137
|
+
|
138
|
+
expired_path =
|
139
|
+
File.join Gem.user_home, "gem-public_cert.pem.expired.#{expiry}"
|
140
|
+
|
141
|
+
assert_path_exists expired_path
|
142
|
+
assert_equal EXPIRED_CERT.to_pem, File.read(expired_path)
|
143
|
+
end
|
144
|
+
|
145
|
+
def test_sign_expired_auto_update_exists
|
146
|
+
FileUtils.mkdir_p Gem.user_home, :mode => 0700
|
147
|
+
|
148
|
+
expiry = EXPIRED_CERT.not_after.strftime "%Y%m%d%H%M%S"
|
149
|
+
expired_path =
|
150
|
+
File.join Gem.user_home, "gem-public_cert.pem.expired.#{expiry}"
|
151
|
+
|
152
|
+
Gem::Security.write EXPIRED_CERT, expired_path
|
153
|
+
|
154
|
+
private_key_path = File.join(Gem.user_home, 'gem-private_key.pem')
|
155
|
+
Gem::Security.write PRIVATE_KEY, private_key_path
|
156
|
+
|
157
|
+
cert_path = File.join Gem.user_home, 'gem-public_cert.pem'
|
158
|
+
Gem::Security.write EXPIRED_CERT, cert_path
|
159
|
+
|
160
|
+
signer = Gem::Security::Signer.new PRIVATE_KEY, [EXPIRED_CERT]
|
161
|
+
|
162
|
+
e = assert_raises Gem::Security::Exception do
|
163
|
+
signer.sign 'hello'
|
164
|
+
end
|
165
|
+
|
166
|
+
assert_match %r%certificate /CN=nobody/DC=example not valid%, e.message
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_sign_no_key
|
170
|
+
signer = Gem::Security::Signer.new nil, nil
|
171
|
+
|
172
|
+
assert_nil signer.sign 'stuff'
|
173
|
+
end
|
174
|
+
|
175
|
+
def test_sign_wrong_key
|
176
|
+
signer = Gem::Security::Signer.new ALTERNATE_KEY, [PUBLIC_CERT]
|
177
|
+
|
178
|
+
assert_raises Gem::Security::Exception do
|
179
|
+
signer.sign 'hello'
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
|