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.

Files changed (241) hide show
  1. checksums.yaml +6 -6
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +3 -0
  4. data/.autotest +6 -3
  5. data/History.txt +137 -63
  6. data/LICENSE.txt +1 -5
  7. data/Manifest.txt +69 -32
  8. data/README.rdoc +11 -9
  9. data/Rakefile +24 -38
  10. data/bin/gem +0 -9
  11. data/bin/update_rubygems +1 -0
  12. data/lib/rubygems.rb +193 -405
  13. data/lib/rubygems/available_set.rb +95 -0
  14. data/lib/rubygems/command.rb +88 -45
  15. data/lib/rubygems/command_manager.rb +67 -40
  16. data/lib/rubygems/commands/build_command.rb +5 -23
  17. data/lib/rubygems/commands/cert_command.rb +199 -57
  18. data/lib/rubygems/commands/check_command.rb +14 -39
  19. data/lib/rubygems/commands/cleanup_command.rb +9 -1
  20. data/lib/rubygems/commands/contents_command.rb +30 -12
  21. data/lib/rubygems/commands/dependency_command.rb +3 -8
  22. data/lib/rubygems/commands/environment_command.rb +13 -8
  23. data/lib/rubygems/commands/fetch_command.rb +3 -16
  24. data/lib/rubygems/commands/generate_index_command.rb +7 -47
  25. data/lib/rubygems/commands/help_command.rb +1 -1
  26. data/lib/rubygems/commands/install_command.rb +69 -36
  27. data/lib/rubygems/commands/list_command.rb +6 -4
  28. data/lib/rubygems/commands/lock_command.rb +1 -1
  29. data/lib/rubygems/commands/mirror_command.rb +17 -0
  30. data/lib/rubygems/commands/outdated_command.rb +6 -3
  31. data/lib/rubygems/commands/owner_command.rb +13 -5
  32. data/lib/rubygems/commands/pristine_command.rb +19 -4
  33. data/lib/rubygems/commands/push_command.rb +12 -1
  34. data/lib/rubygems/commands/query_command.rb +43 -27
  35. data/lib/rubygems/commands/rdoc_command.rb +23 -28
  36. data/lib/rubygems/commands/search_command.rb +4 -18
  37. data/lib/rubygems/commands/server_command.rb +1 -1
  38. data/lib/rubygems/commands/setup_command.rb +124 -38
  39. data/lib/rubygems/commands/sources_command.rb +16 -16
  40. data/lib/rubygems/commands/specification_command.rb +11 -13
  41. data/lib/rubygems/commands/uninstall_command.rb +24 -7
  42. data/lib/rubygems/commands/unpack_command.rb +7 -3
  43. data/lib/rubygems/commands/update_command.rb +22 -36
  44. data/lib/rubygems/commands/yank_command.rb +98 -0
  45. data/lib/rubygems/compatibility.rb +51 -0
  46. data/lib/rubygems/config_file.rb +82 -54
  47. data/lib/rubygems/core_ext/kernel_gem.rb +53 -0
  48. data/lib/rubygems/core_ext/kernel_require.rb +119 -0
  49. data/lib/rubygems/defaults.rb +10 -21
  50. data/lib/rubygems/dependency.rb +61 -10
  51. data/lib/rubygems/dependency_installer.rb +157 -69
  52. data/lib/rubygems/dependency_list.rb +11 -19
  53. data/lib/rubygems/dependency_resolver.rb +562 -0
  54. data/lib/rubygems/deprecate.rb +40 -40
  55. data/lib/rubygems/errors.rb +77 -24
  56. data/lib/rubygems/exceptions.rb +25 -7
  57. data/lib/rubygems/ext/builder.rb +20 -23
  58. data/lib/rubygems/ext/configure_builder.rb +2 -2
  59. data/lib/rubygems/ext/ext_conf_builder.rb +5 -45
  60. data/lib/rubygems/ext/rake_builder.rb +2 -2
  61. data/lib/rubygems/gem_runner.rb +3 -16
  62. data/lib/rubygems/gemcutter_utilities.rb +22 -7
  63. data/lib/rubygems/indexer.rb +6 -159
  64. data/lib/rubygems/install_message.rb +12 -0
  65. data/lib/rubygems/install_update_options.rb +56 -18
  66. data/lib/rubygems/installer.rb +244 -134
  67. data/lib/rubygems/installer_test_case.rb +71 -19
  68. data/lib/rubygems/mock_gem_ui.rb +17 -0
  69. data/lib/rubygems/name_tuple.rb +110 -0
  70. data/lib/rubygems/package.rb +514 -43
  71. data/lib/rubygems/package/digest_io.rb +64 -0
  72. data/lib/rubygems/package/old.rb +147 -0
  73. data/lib/rubygems/package/tar_header.rb +18 -55
  74. data/lib/rubygems/package/tar_reader.rb +20 -3
  75. data/lib/rubygems/package/tar_writer.rb +63 -7
  76. data/lib/rubygems/package_task.rb +3 -4
  77. data/lib/rubygems/path_support.rb +14 -7
  78. data/lib/rubygems/platform.rb +19 -26
  79. data/lib/rubygems/rdoc.rb +316 -0
  80. data/lib/rubygems/remote_fetcher.rb +117 -54
  81. data/lib/rubygems/request_set.rb +182 -0
  82. data/lib/rubygems/requirement.rb +63 -26
  83. data/lib/rubygems/security.rb +295 -555
  84. data/lib/rubygems/security/policies.rb +115 -0
  85. data/lib/rubygems/security/policy.rb +227 -0
  86. data/lib/rubygems/security/signer.rb +136 -0
  87. data/lib/rubygems/security/trust_dir.rb +104 -0
  88. data/lib/rubygems/server.rb +45 -55
  89. data/lib/rubygems/source.rb +144 -0
  90. data/lib/rubygems/source_list.rb +87 -0
  91. data/lib/rubygems/source_local.rb +92 -0
  92. data/lib/rubygems/source_specific_file.rb +28 -0
  93. data/lib/rubygems/spec_fetcher.rb +116 -184
  94. data/lib/rubygems/specification.rb +731 -335
  95. data/lib/rubygems/ssl_certs/AddTrustExternalCARoot.pem +88 -30
  96. data/lib/rubygems/ssl_certs/Entrust_net-Secure-Server-Certification-Authority.pem +90 -0
  97. data/lib/rubygems/ssl_certs/VerisignClass3PublicPrimaryCertificationAuthority-G2.pem +57 -0
  98. data/lib/rubygems/syck_hack.rb +2 -0
  99. data/lib/rubygems/test_case.rb +199 -109
  100. data/lib/rubygems/test_utilities.rb +25 -5
  101. data/lib/rubygems/uninstaller.rb +62 -20
  102. data/lib/rubygems/user_interaction.rb +10 -0
  103. data/lib/rubygems/validator.rb +33 -40
  104. data/lib/rubygems/version.rb +19 -8
  105. data/setup.rb +8 -1
  106. data/test/rubygems/alternate_cert.pem +9 -0
  107. data/test/rubygems/alternate_cert_32.pem +9 -0
  108. data/test/rubygems/alternate_key.pem +9 -0
  109. data/test/rubygems/bad_rake.rb +1 -0
  110. data/test/rubygems/child_cert.pem +9 -0
  111. data/test/rubygems/child_cert_32.pem +9 -0
  112. data/test/rubygems/child_key.pem +9 -0
  113. data/test/rubygems/data/null-type.gemspec.rz +0 -0
  114. data/test/rubygems/expired_cert.pem +9 -0
  115. data/test/rubygems/future_cert.pem +9 -0
  116. data/test/rubygems/future_cert_32.pem +9 -0
  117. data/test/rubygems/good_rake.rb +1 -0
  118. data/test/rubygems/grandchild_cert.pem +9 -0
  119. data/test/rubygems/grandchild_cert_32.pem +9 -0
  120. data/test/rubygems/grandchild_key.pem +9 -0
  121. data/test/rubygems/invalid_issuer_cert.pem +9 -0
  122. data/test/rubygems/invalid_issuer_cert_32.pem +9 -0
  123. data/test/rubygems/invalid_key.pem +9 -0
  124. data/test/rubygems/invalid_signer_cert.pem +9 -0
  125. data/test/rubygems/invalid_signer_cert_32.pem +9 -0
  126. data/test/rubygems/invalidchild_cert.pem +9 -0
  127. data/test/rubygems/invalidchild_cert_32.pem +9 -0
  128. data/test/rubygems/invalidchild_key.pem +9 -0
  129. data/test/rubygems/plugin/exception/rubygems_plugin.rb +1 -1
  130. data/test/rubygems/plugin/standarderror/rubygems_plugin.rb +1 -1
  131. data/test/rubygems/private_key.pem +7 -25
  132. data/test/rubygems/public_cert.pem +8 -18
  133. data/test/rubygems/public_cert_32.pem +10 -0
  134. data/test/rubygems/public_key.pem +4 -0
  135. data/test/rubygems/rubygems/commands/crash_command.rb +1 -1
  136. data/test/rubygems/test_config.rb +4 -6
  137. data/test/rubygems/test_deprecate.rb +76 -0
  138. data/test/rubygems/test_gem.rb +318 -83
  139. data/test/rubygems/test_gem_available_set.rb +106 -0
  140. data/test/rubygems/test_gem_command.rb +10 -0
  141. data/test/rubygems/test_gem_command_manager.rb +55 -9
  142. data/test/rubygems/test_gem_commands_build_command.rb +11 -19
  143. data/test/rubygems/test_gem_commands_cert_command.rb +441 -42
  144. data/test/rubygems/test_gem_commands_cleanup_command.rb +29 -1
  145. data/test/rubygems/test_gem_commands_contents_command.rb +23 -0
  146. data/test/rubygems/test_gem_commands_dependency_command.rb +5 -0
  147. data/test/rubygems/test_gem_commands_fetch_command.rb +19 -20
  148. data/test/rubygems/test_gem_commands_generate_index_command.rb +2 -83
  149. data/test/rubygems/test_gem_commands_help_command.rb +2 -1
  150. data/test/rubygems/test_gem_commands_install_command.rb +647 -48
  151. data/test/rubygems/test_gem_commands_mirror.rb +32 -0
  152. data/test/rubygems/test_gem_commands_owner_command.rb +4 -8
  153. data/test/rubygems/test_gem_commands_pristine_command.rb +99 -4
  154. data/test/rubygems/test_gem_commands_push_command.rb +62 -8
  155. data/test/rubygems/test_gem_commands_query_command.rb +51 -0
  156. data/test/rubygems/test_gem_commands_search_command.rb +25 -0
  157. data/test/rubygems/test_gem_commands_setup_command.rb +45 -0
  158. data/test/rubygems/test_gem_commands_sources_command.rb +21 -6
  159. data/test/rubygems/test_gem_commands_specification_command.rb +33 -1
  160. data/test/rubygems/test_gem_commands_uninstall_command.rb +91 -31
  161. data/test/rubygems/test_gem_commands_unpack_command.rb +3 -3
  162. data/test/rubygems/test_gem_commands_update_command.rb +56 -38
  163. data/test/rubygems/test_gem_commands_which_command.rb +4 -4
  164. data/test/rubygems/test_gem_commands_yank_command.rb +97 -0
  165. data/test/rubygems/test_gem_config_file.rb +66 -21
  166. data/test/rubygems/test_gem_dependency.rb +46 -0
  167. data/test/rubygems/test_gem_dependency_installer.rb +228 -18
  168. data/test/rubygems/test_gem_dependency_list.rb +0 -9
  169. data/test/rubygems/test_gem_dependency_resolver.rb +327 -0
  170. data/test/rubygems/test_gem_ext_configure_builder.rb +4 -4
  171. data/test/rubygems/test_gem_ext_ext_conf_builder.rb +21 -49
  172. data/test/rubygems/test_gem_ext_rake_builder.rb +13 -13
  173. data/test/rubygems/test_gem_gem_runner.rb +27 -5
  174. data/test/rubygems/test_gem_gemcutter_utilities.rb +19 -0
  175. data/test/rubygems/test_gem_indexer.rb +14 -227
  176. data/test/rubygems/test_gem_install_update_options.rb +83 -3
  177. data/test/rubygems/test_gem_installer.rb +211 -236
  178. data/test/rubygems/test_gem_local_remote_options.rb +8 -2
  179. data/test/rubygems/test_gem_name_tuple.rb +15 -0
  180. data/test/rubygems/test_gem_package.rb +547 -0
  181. data/test/rubygems/test_gem_package_old.rb +37 -0
  182. data/test/rubygems/test_gem_package_tar_reader.rb +32 -0
  183. data/test/rubygems/test_gem_package_tar_writer.rb +84 -1
  184. data/test/rubygems/test_gem_path_support.rb +4 -30
  185. data/test/rubygems/test_gem_platform.rb +3 -6
  186. data/test/rubygems/test_gem_rdoc.rb +245 -0
  187. data/test/rubygems/test_gem_remote_fetcher.rb +51 -5
  188. data/test/rubygems/test_gem_request_set.rb +70 -0
  189. data/test/rubygems/test_gem_requirement.rb +53 -24
  190. data/test/rubygems/test_gem_security.rb +189 -43
  191. data/test/rubygems/test_gem_security_policy.rb +376 -0
  192. data/test/rubygems/test_gem_security_signer.rb +184 -0
  193. data/test/rubygems/test_gem_security_trust_dir.rb +94 -0
  194. data/test/rubygems/test_gem_server.rb +31 -36
  195. data/test/rubygems/test_gem_silent_ui.rb +2 -2
  196. data/test/rubygems/test_gem_source.rb +188 -0
  197. data/test/rubygems/test_gem_source_list.rb +87 -0
  198. data/test/rubygems/test_gem_source_local.rb +83 -0
  199. data/test/rubygems/test_gem_source_specific_file.rb +33 -0
  200. data/test/rubygems/test_gem_spec_fetcher.rb +91 -255
  201. data/test/rubygems/test_gem_specification.rb +293 -39
  202. data/test/rubygems/test_gem_uninstaller.rb +136 -13
  203. data/test/rubygems/test_gem_validator.rb +14 -41
  204. data/test/rubygems/test_gem_version.rb +15 -21
  205. data/test/rubygems/test_require.rb +193 -0
  206. data/test/rubygems/wrong_key_cert.pem +9 -0
  207. data/test/rubygems/wrong_key_cert_32.pem +9 -0
  208. metadata +171 -83
  209. metadata.gz.sig +1 -0
  210. data/CVE-2013-4287.txt +0 -36
  211. data/CVE-2013-4363.txt +0 -45
  212. data/ci_build.sh +0 -27
  213. data/cruise_config.rb +0 -32
  214. data/lib/rbconfig/datadir.rb +0 -13
  215. data/lib/rubygems/builder.rb +0 -99
  216. data/lib/rubygems/custom_require.rb +0 -69
  217. data/lib/rubygems/doc_manager.rb +0 -243
  218. data/lib/rubygems/format.rb +0 -82
  219. data/lib/rubygems/gem_openssl.rb +0 -90
  220. data/lib/rubygems/gem_path_searcher.rb +0 -172
  221. data/lib/rubygems/old_format.rb +0 -153
  222. data/lib/rubygems/package/f_sync_dir.rb +0 -23
  223. data/lib/rubygems/package/tar_input.rb +0 -234
  224. data/lib/rubygems/package/tar_output.rb +0 -146
  225. data/lib/rubygems/require_paths_builder.rb +0 -18
  226. data/lib/rubygems/source_index.rb +0 -406
  227. data/lib/rubygems/ssl_certs/AddTrustExternalCARoot-2048.pem +0 -25
  228. data/lib/rubygems/ssl_certs/Class3PublicPrimaryCertificationAuthority.pem +0 -14
  229. data/lib/rubygems/ssl_certs/DigiCertHighAssuranceEVRootCA.pem +0 -23
  230. data/lib/rubygems/ssl_certs/EntrustnetSecureServerCertificationAuthority.pem +0 -28
  231. data/lib/rubygems/ssl_certs/GeoTrustGlobalCA.pem +0 -20
  232. data/test/rubygems/test_bundled_ca.rb +0 -59
  233. data/test/rubygems/test_gem_builder.rb +0 -44
  234. data/test/rubygems/test_gem_doc_manager.rb +0 -32
  235. data/test/rubygems/test_gem_ext_builder.rb +0 -58
  236. data/test/rubygems/test_gem_format.rb +0 -88
  237. data/test/rubygems/test_gem_gem_path_searcher.rb +0 -94
  238. data/test/rubygems/test_gem_package_tar_input.rb +0 -129
  239. data/test/rubygems/test_gem_package_tar_output.rb +0 -101
  240. data/test/rubygems/test_gem_source_index.rb +0 -250
  241. 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
+