ruby-sslyze 0.2.1 → 1.0.0

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.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +6 -4
  3. data/.travis.yml +15 -7
  4. data/ChangeLog.md +29 -12
  5. data/Gemfile +3 -2
  6. data/LICENSE.txt +1 -1
  7. data/README.md +5 -5
  8. data/Rakefile +1 -1
  9. data/lib/sslyze/cipher_suites.rb +176 -0
  10. data/lib/sslyze/program.rb +8 -8
  11. data/lib/sslyze/task.rb +40 -33
  12. data/lib/sslyze/version.rb +1 -1
  13. data/lib/sslyze/{certificate/domain_name.rb → x509/domain.rb} +5 -3
  14. data/lib/sslyze/x509/extension.rb +15 -0
  15. data/lib/sslyze/x509/extension_set.rb +140 -0
  16. data/lib/sslyze/x509/extensions.rb +6 -0
  17. data/lib/sslyze/x509/extensions/basic_constraints.rb +41 -0
  18. data/lib/sslyze/x509/extensions/certificate_policies.rb +108 -0
  19. data/lib/sslyze/x509/extensions/crl_distribution_points.rb +47 -0
  20. data/lib/sslyze/x509/extensions/extended_key_usage.rb +58 -0
  21. data/lib/sslyze/x509/extensions/key_usage.rb +66 -0
  22. data/lib/sslyze/x509/extensions/subject_alt_name.rb +144 -0
  23. data/lib/sslyze/x509/name.rb +194 -0
  24. data/lib/sslyze/x509/public_key.rb +53 -0
  25. data/lib/sslyze/xml.rb +26 -37
  26. data/lib/sslyze/xml/attributes.rb +5 -0
  27. data/lib/sslyze/xml/attributes/error.rb +30 -0
  28. data/lib/sslyze/xml/attributes/exception.rb +30 -0
  29. data/lib/sslyze/xml/attributes/is_supported.rb +29 -0
  30. data/lib/sslyze/xml/attributes/is_vulnerable.rb +29 -0
  31. data/lib/sslyze/xml/attributes/title.rb +31 -0
  32. data/lib/sslyze/xml/certinfo.rb +67 -0
  33. data/lib/sslyze/xml/certinfo/certificate.rb +202 -0
  34. data/lib/sslyze/xml/certinfo/certificate_validation.rb +69 -0
  35. data/lib/sslyze/xml/certinfo/certificate_validation/hostname_validation.rb +54 -0
  36. data/lib/sslyze/xml/certinfo/certificate_validation/path_validation.rb +84 -0
  37. data/lib/sslyze/xml/certinfo/certificate_validation/verified_certificate_chain.rb +41 -0
  38. data/lib/sslyze/xml/certinfo/has_certificates.rb +102 -0
  39. data/lib/sslyze/xml/certinfo/ocsp_stapling.rb +45 -0
  40. data/lib/sslyze/xml/certinfo/ocsp_stapling/ocsp_response.rb +87 -0
  41. data/lib/sslyze/xml/certinfo/received_certificate_chain.rb +48 -0
  42. data/lib/sslyze/xml/compression.rb +33 -0
  43. data/lib/sslyze/xml/compression/compression_method.rb +38 -0
  44. data/lib/sslyze/xml/fallback.rb +34 -0
  45. data/lib/sslyze/xml/fallback/tls_fallback_scsv.rb +27 -0
  46. data/lib/sslyze/xml/heartbleed.rb +38 -0
  47. data/lib/sslyze/xml/heartbleed/openssl_heartbleed.rb +29 -0
  48. data/lib/sslyze/xml/http_headers.rb +42 -0
  49. data/lib/sslyze/xml/http_headers/http_public_key_pinning.rb +121 -0
  50. data/lib/sslyze/xml/http_headers/http_strict_transport_security.rb +59 -0
  51. data/lib/sslyze/xml/invalid_target.rb +33 -0
  52. data/lib/sslyze/xml/openssl_ccs.rb +34 -0
  53. data/lib/sslyze/xml/openssl_ccs/openssl_ccs_injection.rb +26 -0
  54. data/lib/sslyze/xml/plugin.rb +27 -0
  55. data/lib/sslyze/xml/protocol.rb +143 -0
  56. data/lib/sslyze/xml/protocol/cipher_suite.rb +93 -0
  57. data/lib/sslyze/xml/protocol/cipher_suite/key_exchange.rb +127 -0
  58. data/lib/sslyze/xml/reneg.rb +28 -0
  59. data/lib/sslyze/xml/reneg/session_renegotiation.rb +51 -0
  60. data/lib/sslyze/xml/resum.rb +42 -0
  61. data/lib/sslyze/xml/resum/session_resumption_with_session_ids.rb +94 -0
  62. data/lib/sslyze/xml/resum/session_resumption_with_tls_tickets.rb +69 -0
  63. data/lib/sslyze/xml/resum_rate.rb +30 -0
  64. data/lib/sslyze/xml/target.rb +371 -0
  65. data/lib/sslyze/xml/types.rb +19 -0
  66. data/ruby-sslyze.gemspec +3 -3
  67. data/spec/spec_helper.rb +2 -4
  68. data/spec/sslyze.xml +2356 -2580
  69. data/spec/x509/domain_spec.rb +125 -0
  70. data/spec/x509/extension_set_spec.rb +208 -0
  71. data/spec/x509/extension_spec.rb +58 -0
  72. data/spec/x509/extensions/basic_constraints_spec.rb +41 -0
  73. data/spec/x509/extensions/certificate_policies_spec.rb +38 -0
  74. data/spec/x509/extensions/crl_distribution_points_spec.rb +38 -0
  75. data/spec/x509/extensions/extended_key_usage_spec.rb +58 -0
  76. data/spec/x509/extensions/key_usage_spec.rb +84 -0
  77. data/spec/x509/extensions/subject_alt_name_spec.rb +146 -0
  78. data/spec/x509/name_spec.rb +85 -0
  79. data/spec/x509/public_key_spec.rb +113 -0
  80. data/spec/xml/certinfo/certificate_spec.rb +166 -0
  81. data/spec/xml/certinfo/certificate_validation/hostname_validation_spec.rb +23 -0
  82. data/spec/xml/certinfo/certificate_validation/path_validation_spec.rb +107 -0
  83. data/spec/xml/certinfo/certificate_validation/verified_certificate_chain_spec.rb +163 -0
  84. data/spec/xml/certinfo/certificate_validation_spec.rb +40 -0
  85. data/spec/xml/certinfo/ocsp_stapling/ocsp_response_spec.rb +61 -0
  86. data/spec/xml/certinfo/ocsp_stapling_spec.rb +31 -0
  87. data/spec/xml/certinfo/received_certificate_chain_spec.rb +165 -0
  88. data/spec/xml/certinfo_spec.rb +45 -0
  89. data/spec/xml/compression/compression_method_spec.rb +23 -0
  90. data/spec/xml/compression_spec.rb +23 -0
  91. data/spec/xml/heartbleed/openssl_heartbleed_spec.rb +17 -0
  92. data/spec/xml/heartbleed_spec.rb +37 -0
  93. data/spec/xml/http_headers/http_public_key_pinning_spec.rb +73 -0
  94. data/spec/xml/http_headers/http_strict_transport_security_spec.rb +107 -0
  95. data/spec/xml/http_headers_spec.rb +63 -0
  96. data/spec/xml/invalid_target_spec.rb +23 -0
  97. data/spec/xml/plugin_examples.rb +14 -0
  98. data/spec/{key_exchange_spec.rb → xml/protocol/cipher_suite/key_exchange_spec.rb} +9 -3
  99. data/spec/xml/protocol/cipher_suite_spec.rb +66 -0
  100. data/spec/xml/protocol_spec.rb +115 -0
  101. data/spec/xml/reneg/session_renegotiation_spec.rb +23 -0
  102. data/spec/xml/reneg_spec.rb +35 -0
  103. data/spec/xml/resum/session_resumption_with_session_ids_spec.rb +103 -0
  104. data/spec/xml/resum/session_resumption_with_tls_tickets_spec.rb +121 -0
  105. data/spec/xml/resum_rate_spec.rb +30 -0
  106. data/spec/xml/resum_spec.rb +47 -0
  107. data/spec/{target_spec.rb → xml/target_spec.rb} +73 -27
  108. data/spec/xml_spec.rb +13 -21
  109. metadata +138 -61
  110. data/lib/sslyze/cert_info.rb +0 -57
  111. data/lib/sslyze/certificate.rb +0 -139
  112. data/lib/sslyze/certificate/extensions.rb +0 -127
  113. data/lib/sslyze/certificate/extensions/authority_information_access.rb +0 -38
  114. data/lib/sslyze/certificate/extensions/extension.rb +0 -26
  115. data/lib/sslyze/certificate/extensions/x509v3_basic_constraints.rb +0 -60
  116. data/lib/sslyze/certificate/extensions/x509v3_certificate_policies.rb +0 -50
  117. data/lib/sslyze/certificate/extensions/x509v3_crl_distribution_points.rb +0 -32
  118. data/lib/sslyze/certificate/extensions/x509v3_extended_key_usage.rb +0 -32
  119. data/lib/sslyze/certificate/extensions/x509v3_key_usage.rb +0 -50
  120. data/lib/sslyze/certificate/extensions/x509v3_subject_alternative_name.rb +0 -71
  121. data/lib/sslyze/certificate/issuer.rb +0 -56
  122. data/lib/sslyze/certificate/public_key.rb +0 -9
  123. data/lib/sslyze/certificate/subject.rb +0 -117
  124. data/lib/sslyze/certificate/subject_public_key_info.rb +0 -53
  125. data/lib/sslyze/certificate/validity.rb +0 -9
  126. data/lib/sslyze/certificate_chain.rb +0 -89
  127. data/lib/sslyze/certificate_validation.rb +0 -70
  128. data/lib/sslyze/cipher_suite.rb +0 -237
  129. data/lib/sslyze/invalid_target.rb +0 -35
  130. data/lib/sslyze/key_exchange.rb +0 -106
  131. data/lib/sslyze/ocsp_response.rb +0 -87
  132. data/lib/sslyze/protocol.rb +0 -133
  133. data/lib/sslyze/target.rb +0 -312
  134. data/lib/sslyze/types.rb +0 -17
  135. data/spec/cert_info_spec.rb +0 -29
  136. data/spec/certificate/subject_name_spec.rb +0 -72
  137. data/spec/certificate_chain_spec.rb +0 -61
  138. data/spec/certificate_spec.rb +0 -330
  139. data/spec/certificate_validation_spec.rb +0 -39
  140. data/spec/cipher_suite_spec.rb +0 -50
  141. data/spec/invalid_target_spec.rb +0 -21
  142. data/spec/issuer_spec.rb +0 -33
  143. data/spec/ocsp_response_spec.rb +0 -59
  144. data/spec/protocol_spec.rb +0 -99
  145. data/spec/subject_public_key_info_spec.rb +0 -35
  146. data/spec/subject_spec.rb +0 -69
@@ -0,0 +1,125 @@
1
+ require 'spec_helper'
2
+ require 'sslyze/x509/domain'
3
+
4
+ describe SSLyze::X509::Domain do
5
+ let(:domain_name) { 'example.com' }
6
+ let(:wildcard_name) { "*.#{domain_name}" }
7
+
8
+ subject { described_class.new(domain_name) }
9
+
10
+ describe "#initialize" do
11
+ context "when given a fully qualified domain name" do
12
+ subject { described_class.new(domain_name) }
13
+
14
+ it "should set #name" do
15
+ expect(subject.name).to be == domain_name
16
+ end
17
+
18
+ it "should not set #suffix" do
19
+ expect(subject.suffix).to be nil
20
+ end
21
+
22
+ it "should not set #domain to #name" do
23
+ expect(subject.domain).to be == domain_name
24
+ end
25
+ end
26
+
27
+ context "when given a wildcard domain name" do
28
+ subject { described_class.new(wildcard_name) }
29
+
30
+ it "should set #name" do
31
+ expect(subject.name).to be == wildcard_name
32
+ end
33
+
34
+ it "should set #suffix" do
35
+ expect(subject.suffix).to be == ".#{domain_name}"
36
+ end
37
+
38
+ it "should set #domain" do
39
+ expect(subject.domain).to be == domain_name
40
+ end
41
+ end
42
+ end
43
+
44
+ describe "#==" do
45
+ context "when given another #{described_class}" do
46
+ subject { described_class.new(domain_name) }
47
+
48
+ context "and it matches the domain name" do
49
+ let(:other) { described_class.new(domain_name) }
50
+
51
+ it { expect(subject == other).to be true }
52
+ end
53
+
54
+ context "but it doesn't match" do
55
+ let(:other) { described_class.new('foo.com') }
56
+
57
+ it { expect(subject == other).to be false }
58
+ end
59
+ end
60
+
61
+ context "when given a non-#{described_class}" do
62
+ let(:other) { Object.new }
63
+
64
+ subject { described_class.new(domain_name) }
65
+
66
+ it "should return false" do
67
+ expect(subject == other).to be false
68
+ end
69
+ end
70
+ end
71
+
72
+ describe "#include?" do
73
+ context "when given another #{described_class}" do
74
+ context "when the other domain name is fully qualified" do
75
+ subject { described_class.new(domain_name) }
76
+
77
+ context "and it matches the domain name" do
78
+ it { expect(subject.include?(domain_name)).to be true }
79
+ end
80
+
81
+ context "but it doesn't match" do
82
+ it { expect(subject.include?('foo.com')).to be false }
83
+ end
84
+ end
85
+
86
+ context "when the other domain name is a wildcard" do
87
+ subject { described_class.new(wildcard_name) }
88
+
89
+ context "and it matches the wildcard domain name" do
90
+ it { expect(subject.include?(wildcard_name)).to be true }
91
+ end
92
+
93
+ context "and shares the same domain name" do
94
+ it { expect(subject.include?(domain_name)).to be true }
95
+ end
96
+
97
+ context "and it is a subdomain of the wildcard domain name" do
98
+ it { expect(subject.include?("foo.#{domain_name}")).to be true }
99
+ end
100
+
101
+ context "but it doesn't match" do
102
+ it { expect(subject.include?("foo.com")).to be false }
103
+ end
104
+ end
105
+ end
106
+ end
107
+
108
+ describe "#to_s" do
109
+ it "should return the #name" do
110
+ expect(subject.to_s).to be subject.name
111
+ end
112
+ end
113
+
114
+ describe "#to_str" do
115
+ it "should return the #name" do
116
+ expect(subject.to_str).to be subject.name
117
+ end
118
+ end
119
+
120
+ describe "#inspect" do
121
+ it "should include the class name and #name" do
122
+ expect(subject.inspect).to be == "#<#{described_class}: #{subject.name}>"
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,208 @@
1
+ require 'spec_helper'
2
+ require 'openssl'
3
+
4
+ require 'sslyze/x509/extension_set'
5
+
6
+ describe SSLyze::X509::ExtensionSet do
7
+ let(:authority_key_identifier) do
8
+ OpenSSL::X509::Extension.new("authorityKeyIdentifier", "keyid:3D:D3:50:A5:D6:A0:AD:EE:F3:4A:60:0A:65:D3:21:D4:F8:F8:D6:0F\n")
9
+ end
10
+ let(:subject_key_identifier) do
11
+ OpenSSL::X509::Extension.new("subjectKeyIdentifier", "9F:62:7B:B2:88:0E:EE:1B:79:E0:69:24:E5:BA:3F:47:A6:0B:02:F0")
12
+ end
13
+ let(:subject_alt_name) do
14
+ OpenSSL::X509::Extension.new("subjectAltName", "DNS:twitter.com, DNS:www.twitter.com")
15
+ end
16
+ let(:key_usage) do
17
+ OpenSSL::X509::Extension.new("keyUsage", "Digital Signature, Key Encipherment", true)
18
+ end
19
+ let(:extended_key_usage) do
20
+ OpenSSL::X509::Extension.new("extendedKeyUsage", "TLS Web Server Authentication, TLS Web Client Authentication")
21
+ end
22
+ let(:crl_distribution_points) do
23
+ OpenSSL::X509::Extension.new("crlDistributionPoints", "\nFull Name:\n URI:http://crl3.digicert.com/sha2-ev-server-g1.crl\n\nFull Name:\n URI:http://crl4.digicert.com/sha2-ev-server-g1.crl\n")
24
+ end
25
+ let(:certificate_policies) do
26
+ OpenSSL::X509::Extension.new("certificatePolicies", "Policy: 2.16.840.1.114412.2.1\n CPS: https://www.digicert.com/CPS\nPolicy: 2.23.140.1.1\n")
27
+ end
28
+ let(:authority_info_access) do
29
+ OpenSSL::X509::Extension.new("authorityInfoAccess", "OCSP - URI:http://ocsp.digicert.com\nCA Issuers - URI:http://cacerts.digicert.com/DigiCertSHA2ExtendedValidationServerCA.crt\n")
30
+ end
31
+ let(:basic_constraints) do
32
+ OpenSSL::X509::Extension.new("basicConstraints", "CA:FALSE", true)
33
+ end
34
+
35
+ let(:openssl_x509_extensions) do
36
+ [
37
+ authority_key_identifier,
38
+ subject_key_identifier,
39
+ subject_alt_name,
40
+ key_usage,
41
+ extended_key_usage,
42
+ crl_distribution_points,
43
+ certificate_policies,
44
+ authority_info_access,
45
+ basic_constraints
46
+ ]
47
+ end
48
+
49
+ subject { described_class.new(openssl_x509_extensions) }
50
+
51
+ describe "#each" do
52
+ context "when given a block" do
53
+ it "must iterate over each wrapped Extension" do
54
+ expect { |b|
55
+ subject.each(&b)
56
+ }.to yield_successive_args(*openssl_x509_extensions)
57
+ end
58
+ end
59
+
60
+ context "when no block is given" do
61
+ it "should return an Enumerator object" do
62
+ expect(subject.each).to be_kind_of(Enumerator)
63
+ end
64
+ end
65
+ end
66
+
67
+ describe "#has?" do
68
+ context "when the given key matches an extension's OID" do
69
+ let(:key) { 'subjectAltName' }
70
+
71
+ it { expect(subject.has?(key)).to be true }
72
+ end
73
+
74
+ context "when the given key matches no extension's OID" do
75
+ it { expect(subject.has?("foo")).to be false }
76
+ end
77
+ end
78
+
79
+ describe "#[]" do
80
+ context "when the given key matches an extension's OID" do
81
+ let(:key) { 'subjectAltName' }
82
+
83
+ it "must return that extension" do
84
+ expect(subject[key].oid).to be == key
85
+ end
86
+ end
87
+
88
+ context "when the given key matches no extension's OID" do
89
+ it "must return nil" do
90
+ expect(subject["foo"]).to be nil
91
+ end
92
+ end
93
+ end
94
+
95
+ describe "#to_a" do
96
+ it "should return the Array of extensions" do
97
+ expect(subject.to_a).to be == openssl_x509_extensions
98
+ end
99
+ end
100
+
101
+ describe "#basic_constraints" do
102
+ context "when there is a 'basiConstraints' extension" do
103
+ it do
104
+ expect(subject.basic_constraints).to be_kind_of(SSLyze::X509::Extensions::BasicConstraints)
105
+ end
106
+
107
+ it "should find the extensions with the 'basicConstraints' OID" do
108
+ expect(subject.basic_constraints.oid).to be == 'basicConstraints'
109
+ end
110
+ end
111
+
112
+ context "when there is no 'basicConstraints' extension" do
113
+ let(:openssl_x509_extensions) { super() - [basic_constraints] }
114
+
115
+ it { expect(subject.basic_constraints).to be nil }
116
+ end
117
+ end
118
+
119
+ describe "#certificate_policies" do
120
+ context "when there is a 'certificatePolicies' extension" do
121
+ it do
122
+ expect(subject.certificate_policies).to be_kind_of(SSLyze::X509::Extensions::CertificatePolicies)
123
+ end
124
+
125
+ it "should find the extensions with the 'certificatePolicies' OID" do
126
+ expect(subject.certificate_policies.oid).to be == 'certificatePolicies'
127
+ end
128
+ end
129
+
130
+ context "when there is no 'certificatePolicies' extension" do
131
+ let(:openssl_x509_extensions) { super() - [certificate_policies] }
132
+
133
+ it { expect(subject.certificate_policies).to be nil }
134
+ end
135
+ end
136
+
137
+ describe "#crl_distribution_points" do
138
+ context "when there is a 'crlDistributionPoints' extension" do
139
+ it do
140
+ expect(subject.crl_distribution_points).to be_kind_of(SSLyze::X509::Extensions::CRLDistributionPoints)
141
+ end
142
+
143
+ it "should find the extensions with the 'crlDistributionPoints' OID" do
144
+ expect(subject.crl_distribution_points.oid).to be == 'crlDistributionPoints'
145
+ end
146
+ end
147
+
148
+ context "when there is no 'crlDistributionPoints' extension" do
149
+ let(:openssl_x509_extensions) { super() - [crl_distribution_points] }
150
+
151
+ it { expect(subject.crl_distribution_points).to be nil }
152
+ end
153
+ end
154
+
155
+ describe "#extended_key_usage" do
156
+ context "when there is a 'extendedKeyUsage' extension" do
157
+ it do
158
+ expect(subject.extended_key_usage).to be_kind_of(SSLyze::X509::Extensions::ExtendedKeyUsage)
159
+ end
160
+
161
+ it "should find the extensions with the 'extendedKeyUsage' OID" do
162
+ expect(subject.extended_key_usage.oid).to be == 'extendedKeyUsage'
163
+ end
164
+ end
165
+
166
+ context "when there is no 'extendedKeyUsage' extension" do
167
+ let(:openssl_x509_extensions) { super() - [extended_key_usage] }
168
+
169
+ it { expect(subject.extended_key_usage).to be nil }
170
+ end
171
+ end
172
+
173
+ describe "#key_usage" do
174
+ context "when there is a 'keyUsage' extension" do
175
+ it do
176
+ expect(subject.key_usage).to be_kind_of(SSLyze::X509::Extensions::KeyUsage)
177
+ end
178
+
179
+ it "should find the extensions with the 'keyUsage' OID" do
180
+ expect(subject.key_usage.oid).to be == 'keyUsage'
181
+ end
182
+ end
183
+
184
+ context "when there is no 'keyUsage' extension" do
185
+ let(:openssl_x509_extensions) { super() - [key_usage] }
186
+
187
+ it { expect(subject.key_usage).to be nil }
188
+ end
189
+ end
190
+
191
+ describe "#subject_alt_name" do
192
+ context "when there is a 'subjectAltName' extension" do
193
+ it do
194
+ expect(subject.subject_alt_name).to be_kind_of(SSLyze::X509::Extensions::SubjectAltName)
195
+ end
196
+
197
+ it "should find the extensions with the 'subjectAltName' OID" do
198
+ expect(subject.subject_alt_name.oid).to be == 'subjectAltName'
199
+ end
200
+ end
201
+
202
+ context "when there is no 'subjectAltName' extension" do
203
+ let(:openssl_x509_extensions) { super() - [subject_alt_name] }
204
+
205
+ it { expect(subject.subject_alt_name).to be nil }
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+ require 'openssl'
3
+
4
+ require 'sslyze/x509/extension'
5
+
6
+ describe SSLyze::X509::Extension do
7
+ let(:oid) { 'basicConstraints' }
8
+ let(:value) { 'CA:FALSE' }
9
+ let(:critical) { true }
10
+
11
+ let(:openssl_x509_extension) do
12
+ OpenSSL::X509::Extension.new(oid,value,critical)
13
+ end
14
+
15
+ subject { described_class.new(openssl_x509_extension) }
16
+
17
+ describe "#critical?" do
18
+ it "should return the underlying #critical? value" do
19
+ expect(subject.critical?).to be == openssl_x509_extension.critical?
20
+ end
21
+ end
22
+
23
+ describe "#oid" do
24
+ it "should return the underlying #oid value" do
25
+ expect(subject.oid).to be == openssl_x509_extension.oid
26
+ end
27
+ end
28
+
29
+ describe "#value" do
30
+ it "should return the underlying #value value" do
31
+ expect(subject.value).to be == openssl_x509_extension.value
32
+ end
33
+ end
34
+
35
+ describe "#to_a" do
36
+ it "should return the underlying #to_a value" do
37
+ expect(subject.to_a).to be == openssl_x509_extension.to_a
38
+ end
39
+ end
40
+
41
+ describe "#to_der" do
42
+ it "should return the underlying #to_der value" do
43
+ expect(subject.to_der).to be == openssl_x509_extension.to_der
44
+ end
45
+ end
46
+
47
+ describe "#to_h" do
48
+ it "should return the underlying #to_h value" do
49
+ expect(subject.to_h).to be == openssl_x509_extension.to_h
50
+ end
51
+ end
52
+
53
+ describe "#to_s" do
54
+ it "should return the underlying #to_s value" do
55
+ expect(subject.to_s).to be == openssl_x509_extension.to_s
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+ require 'openssl'
3
+
4
+ require 'sslyze/x509/extensions/basic_constraints'
5
+
6
+ describe SSLyze::X509::Extensions::BasicConstraints do
7
+ let(:ca) { 'TRUE' }
8
+ let(:pathlen) { 1 }
9
+ let(:value) { "CA:#{ca}, pathlen:#{pathlen}" }
10
+ let(:openssl_x509_extension) do
11
+ OpenSSL::X509::Extension.new('basicConstraints', value, true)
12
+ end
13
+
14
+ subject { described_class.new(openssl_x509_extension) }
15
+
16
+ describe "#ca?" do
17
+ context "when 'CA:TRUE' is present" do
18
+ let(:ca) { 'TRUE' }
19
+
20
+ it { expect(subject.ca?).to be true }
21
+ end
22
+
23
+ context "when 'CA:FALSE' is present" do
24
+ let(:ca) { 'FALSE' }
25
+
26
+ it { expect(subject.ca?).to be false }
27
+ end
28
+
29
+ context "when 'CA:' is omitted" do
30
+ let(:value) { 'pathlen:0' }
31
+
32
+ it { expect(subject.ca?).to be nil }
33
+ end
34
+ end
35
+
36
+ describe "#path_length" do
37
+ it "should parse the decimal following 'pathlen:'" do
38
+ expect(subject.path_length).to be == pathlen
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+ require 'openssl'
3
+
4
+ require 'sslyze/x509/extensions/certificate_policies'
5
+
6
+ describe SSLyze::X509::Extensions::CertificatePolicies do
7
+ let(:policy) { 'X509v3 Any Policy' }
8
+ let(:cps) { URI('https://www.digicert.com/CPS') }
9
+ let(:value) { "Policy: #{policy}\n CPS: #{cps}\n" }
10
+
11
+ let(:openssl_x509_extension) do
12
+ OpenSSL::X509::Extension.new('certificatePolicies', value)
13
+ end
14
+
15
+ subject { described_class.new(openssl_x509_extension) }
16
+
17
+ describe "#policies" do
18
+ it "must yield #{described_class::Policy} objects" do
19
+ expect(subject.policies).to all(be_kind_of(described_class::Policy))
20
+ end
21
+
22
+ it "should capture the text following 'Policy: '" do
23
+ expect(subject.policies.first.policy).to be == policy
24
+ end
25
+
26
+ it "should capture the URI following ' CPS: '" do
27
+ expect(subject.policies.first.cps).to be == cps
28
+ end
29
+ end
30
+
31
+ describe "#each" do
32
+ it "should yield #{described_class::Policy} objects" do
33
+ expect { |b|
34
+ subject.each(&b)
35
+ }.to yield_successive_args(*Array.new(subject.length,described_class::Policy))
36
+ end
37
+ end
38
+ end