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,40 @@
1
+ require 'spec_helper'
2
+ require 'xml_examples'
3
+ require 'sslyze/xml/certinfo/certificate_validation'
4
+
5
+ describe SSLyze::XML::Certinfo::CertificateValidation do
6
+ include_examples "XML specs"
7
+
8
+ subject do
9
+ described_class.new(xml.at('/document/results/target/certinfo/certificateValidation'))
10
+ end
11
+
12
+ describe "#hostname_validation" do
13
+ it do
14
+ expect(subject.hostname_validation).to be_kind_of(described_class::HostnameValidation)
15
+ end
16
+ end
17
+
18
+ describe "#each_path_validation" do
19
+ it "should yield successive PathValidation objects" do
20
+ expect { |b|
21
+ subject.each_path_validation(&b)
22
+ }.to yield_successive_args(
23
+ described_class::PathValidation,
24
+ described_class::PathValidation,
25
+ described_class::PathValidation,
26
+ described_class::PathValidation,
27
+ described_class::PathValidation
28
+ )
29
+ end
30
+ end
31
+
32
+ describe "#path_validations" do
33
+ subject { super().path_validations }
34
+
35
+ it do
36
+ expect(subject).to_not be_empty
37
+ expect(subject).to all(be_kind_of(described_class::PathValidation))
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+ require 'xml_examples'
3
+ require 'sslyze/xml/certinfo/ocsp_stapling/ocsp_response'
4
+
5
+ describe SSLyze::XML::Certinfo::OCSPStapling::OCSPResponse do
6
+ include_examples "XML specs"
7
+
8
+ let(:xpath) { '/document/results/target/certinfo/ocspStapling/ocspResponse' }
9
+
10
+ subject { described_class.new(xml.at(xpath)) }
11
+
12
+ describe "#is_trusted_by_mozilla_ca_store?" do
13
+ it "should query @isTrustedByMozillaCAStore" do
14
+ expect(subject.is_trusted_by_mozilla_ca_store?).to be true
15
+ end
16
+ end
17
+
18
+ describe "#responder_id" do
19
+ let(:expected_responder_id) { '5168FF90AF0207753CCCD9656462A212B859723B' }
20
+
21
+ let(:xpath) { "#{super()}[responderID/text()='#{expected_responder_id}']" }
22
+
23
+ it "should parse the 'responderID' XML element" do
24
+ expect(subject.responder_id).to be == expected_responder_id
25
+ end
26
+ end
27
+
28
+ describe "#status" do
29
+ let(:xpath) { "#{super()}[@status='SUCCESSFUL']" }
30
+
31
+ it "should parse the status attribute" do
32
+ expect(subject.status).to be == :successful
33
+ end
34
+ end
35
+
36
+ describe "#successful?" do
37
+ context "when responseStatus is 'successful'" do
38
+ let(:xpath) { "#{super()}[@status='SUCCESSFUL']" }
39
+
40
+ specify { expect(subject.successful?).to be true }
41
+ end
42
+
43
+ context "when status is not :successful" do
44
+ before do
45
+ expect(subject).to receive(:status).and_return(:failed)
46
+ end
47
+
48
+ specify { expect(subject.successful?).to be false }
49
+ end
50
+ end
51
+
52
+ describe "#produced_at" do
53
+ let(:expected_time) { 'Feb 28 19:34:58 2018 GMT' }
54
+
55
+ let(:xpath) { "#{super()}[producedAt/text()='#{expected_time}']" }
56
+
57
+ it "should query producedAt and return a Time object" do
58
+ expect(subject.produced_at).to be == Time.parse(expected_time)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+ require 'xml_examples'
3
+ require 'sslyze/xml/certinfo'
4
+
5
+ describe SSLyze::XML::Certinfo::OCSPStapling do
6
+ include_examples "XML specs"
7
+
8
+ subject do
9
+ described_class.new(xml.at('/document/results/target/certinfo/ocspStapling'))
10
+ end
11
+
12
+ describe "#ocsp_response" do
13
+ context "when the 'ocspResponse' element is present" do
14
+ subject do
15
+ described_class.new(xml.at('/document/results/target/certinfo/ocspStapling[ocspResponse]'))
16
+ end
17
+
18
+ it do
19
+ expect(subject.ocsp_response).to be_kind_of(described_class::OCSPResponse)
20
+ end
21
+ end
22
+
23
+ context "when the 'ocspResponse' element is missing" do
24
+ subject do
25
+ described_class.new(xml.at('/document/results/target/certinfo/ocspStapling[not(ocspResponse)]'))
26
+ end
27
+
28
+ it { expect(subject.ocsp_response).to be nil }
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,165 @@
1
+ require 'spec_helper'
2
+ require 'xml_examples'
3
+ require 'sslyze/xml/certinfo/received_certificate_chain'
4
+
5
+ describe SSLyze::XML::Certinfo::ReceivedCertificateChain do
6
+ include_examples "XML specs"
7
+
8
+ let(:xpath) { '/document/results/target/certinfo/receivedCertificateChain' }
9
+
10
+ subject do
11
+ described_class.new(xml.at(xpath))
12
+ end
13
+
14
+ describe "#each_certificate" do
15
+ context "when 'certificate' XML children are present" do
16
+ let(:xpath) { "#{super()}[certificate]" }
17
+ let(:xpath_count) { xml.xpath(xpath).count }
18
+
19
+ it "should yield successive Certificate objects" do
20
+ expect { |b|
21
+ subject.each_certificate(&b)
22
+ }.to yield_successive_args(
23
+ SSLyze::XML::Certinfo::Certificate,
24
+ SSLyze::XML::Certinfo::Certificate
25
+ )
26
+ end
27
+ end
28
+ end
29
+
30
+ describe "#certificates" do
31
+ context "when 'certificate' XML children are present" do
32
+ let(:xpath) { "#{super()}[certificate]" }
33
+
34
+ it do
35
+ expect(subject.certificates).to be_a(Array).and(
36
+ all(be_kind_of(SSLyze::XML::Certinfo::Certificate))
37
+ )
38
+ end
39
+ end
40
+ end
41
+
42
+ describe "#leaf" do
43
+ context "when at least one 'certificate' XML child exists" do
44
+ let(:xpath) { "#{super()}[certificate]" }
45
+
46
+ it do
47
+ expect(subject.leaf).to be_a(SSLyze::XML::Certinfo::Certificate)
48
+ end
49
+
50
+ it "should select the first 'certificate' XML child" do
51
+ expect(subject.leaf).to be == \
52
+ SSLyze::XML::Certinfo::Certificate.new(xml.at("#{xpath}/certificate[1]"))
53
+ end
54
+ end
55
+
56
+ context "when no 'certificate' XML children exist" do
57
+ let(:xpath) { "#{super()}[not(./certificate)]" }
58
+
59
+ it do
60
+ pending "need an example with no 'certificate' XML children"
61
+
62
+ expect(subject.leaf).to be nil
63
+ end
64
+ end
65
+ end
66
+
67
+ describe "#each_intermediate" do
68
+ context "when there are more than two 'certificate' XML children" do
69
+ let(:xpath) { "#{super()}[count(certificate) > 2]" }
70
+ let(:xpath_count) { xml.at(xpath).xpath('certificate').count - 2 }
71
+
72
+ it "should yield the intermediate certificates" do
73
+ pending "<receivedCertificateChain/> always has at most two <certificate/> children"
74
+
75
+ expect { |b|
76
+ subject.each_intermediate(&b)
77
+ }.to yield_successive_args(
78
+ *Array.new(xpath_count,SSLyze::XML::Certinfo::Certificate)
79
+ )
80
+ end
81
+ end
82
+
83
+ context "when there are two or fewer 'certificate' XML children" do
84
+ let(:xpath) { "#{super()}[count(certificate) <= 2]" }
85
+
86
+ it "should not yield anything" do
87
+ expect { |b|
88
+ subject.each_intermediate(&b)
89
+ }.to_not yield_control
90
+ end
91
+ end
92
+ end
93
+
94
+ describe "#intermediates" do
95
+ context "when there are more than two 'certificate' XML children" do
96
+ let(:xpath) { "#{super()}[count(certificate) > 2]" }
97
+ let(:xpath_count) { xml.at(xpath).xpath('certificate').count - 2 }
98
+
99
+ it "should yield the intermediate certificates" do
100
+ pending "<receivedCertificateChain/> always has at most two <certificate/> children"
101
+
102
+ expect(subject.intermediates).to be_a(Array).and(all(be_kind_of(SSLyze::XML::Certinfo::Certificate)))
103
+ end
104
+ end
105
+
106
+ context "when there are two or fewer 'certificate' XML children" do
107
+ let(:xpath) { "#{super()}[count(certificate) <= 2]" }
108
+
109
+ it "should not yield anything" do
110
+ expect(subject.intermediates).to be_empty
111
+ end
112
+ end
113
+ end
114
+
115
+ describe "#root" do
116
+ context "when at least one 'certificate' XML child exists" do
117
+ let(:xpath) { "#{super()}[certificate]" }
118
+
119
+ it do
120
+ expect(subject.root).to be_a(SSLyze::XML::Certinfo::Certificate)
121
+ end
122
+
123
+ it "should select the last 'certificate' XML child" do
124
+ expect(subject.root).to be == \
125
+ SSLyze::XML::Certinfo::Certificate.new(xml.at("#{xpath}/certificate[last()]"))
126
+ end
127
+ end
128
+
129
+ context "when no 'certificate' XML children exist" do
130
+ let(:xpath) { "#{super()}[not(./certificate)]" }
131
+
132
+ it do
133
+ pending "need an example with no 'certificate' XML children"
134
+
135
+ expect(subject.root).to be nil
136
+ end
137
+ end
138
+ end
139
+
140
+ describe "#is_chain_order_valid?" do
141
+ it "should return a Boolean value" do
142
+ expect(subject.is_chain_order_valid?).to be(true).or(be(false))
143
+ end
144
+ end
145
+
146
+ describe "#contains_anchor_certificate?" do
147
+ context "when the 'containsAnchorCertificate' XML attribute is present" do
148
+ let(:xpath) { "#{super()}[@containsAnchorCertificate]" }
149
+
150
+ it "should return a Boolean value" do
151
+ expect(subject.contains_anchor_certificate?).to be(true).or(be(false))
152
+ end
153
+ end
154
+
155
+ context "when the 'containsAnchorCertificate' XML attribute is omitted" do
156
+ let(:xpath) { "#{super()}[not(@containsAnchorCertificate)]" }
157
+
158
+ it do
159
+ pending "need an example where 'containsAnchorCertificate' is missing"
160
+
161
+ expect(subject.contains_anchor_certificate?).to be nil
162
+ end
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+ require 'xml_examples'
3
+ require 'sslyze/xml/certinfo'
4
+
5
+ describe SSLyze::XML::Certinfo do
6
+ include_examples "XML specs"
7
+
8
+ let(:xpath) { '/document/results/target/certinfo' }
9
+
10
+ subject do
11
+ described_class.new(xml.at(xpath))
12
+ end
13
+
14
+ describe "#received_certificate_chain" do
15
+ it "should return a ReceivedCertificateChain object" do
16
+ expect(subject.received_certificate_chain).to be_a(described_class::ReceivedCertificateChain)
17
+ end
18
+ end
19
+
20
+ describe "#certificate_validation" do
21
+ subject do
22
+ described_class.new(xml.at("#{xpath}[receivedCertificateChain]"))
23
+ end
24
+
25
+ it "should return a CertificateValidation element" do
26
+ expect(subject.certificate_validation).to be_kind_of(described_class::CertificateValidation)
27
+ end
28
+ end
29
+
30
+ describe "#verified_certificate_chain" do
31
+ it "should return the #verified_certificate_chain from within one of the #certificate_validation.path_validations" do
32
+ expect(subject.verified_certificate_chain).to be_kind_of(described_class::CertificateValidation::VerifiedCertificateChain)
33
+ end
34
+ end
35
+
36
+ describe "#ocsp_stapling" do
37
+ subject do
38
+ described_class.new(xml.at("#{xpath}[ocspStapling]"))
39
+ end
40
+
41
+ it "should return a OCSPStapling object" do
42
+ expect(subject.ocsp_stapling).to be_kind_of(described_class::OCSPStapling)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+ require 'xml_examples'
3
+ require 'sslyze/xml/compression/compression_method'
4
+
5
+ describe SSLyze::XML::Compression::CompressionMethod do
6
+ include_examples "XML specs"
7
+
8
+ subject do
9
+ described_class.new(xml.at('/document/results/target/compression/compressionMethod'))
10
+ end
11
+
12
+ describe "#is_supported??" do
13
+ it "should prase the 'isSupported' attribute" do
14
+ expect(subject.is_supported?).to be(true).or(be(false))
15
+ end
16
+ end
17
+
18
+ describe "#type" do
19
+ it "should parse the 'type' attribute" do
20
+ expect(subject.type).to be :DEFLATE
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+ require 'xml_examples'
3
+ require 'xml/plugin_examples'
4
+ require 'sslyze/xml/compression'
5
+
6
+ describe SSLyze::XML::Compression do
7
+ include_examples "XML specs"
8
+ include_examples "Plugin element"
9
+
10
+ let(:xpath) { '/document/results/target/compression' }
11
+
12
+ subject { described_class.new(xml.at(xpath)) }
13
+
14
+ describe "#deflate" do
15
+ it do
16
+ expect(subject.deflate).to be_kind_of(described_class::CompressionMethod)
17
+ end
18
+
19
+ it "should parse the DEFLATE compressionMethod" do
20
+ expect(subject.deflate.type).to be :DEFLATE
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+ require 'xml_examples'
3
+ require 'sslyze/xml/heartbleed/openssl_heartbleed'
4
+
5
+ describe SSLyze::XML::Heartbleed::OpenSSLHeartbleed do
6
+ include_examples "XML specs"
7
+
8
+ subject do
9
+ described_class.new(xml.at('/document/results/target/heartbleed/openSslHeartbleed'))
10
+ end
11
+
12
+ describe "#is_vulnerable?" do
13
+ it "should prase the 'isVulnerable' attribute" do
14
+ expect(subject.is_vulnerable?).to be(true).or(be(false))
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+ require 'xml_examples'
3
+ require 'xml/plugin_examples'
4
+ require 'sslyze/xml/heartbleed'
5
+
6
+ describe SSLyze::XML::Heartbleed do
7
+ include_examples "XML specs"
8
+ include_examples "Plugin element"
9
+
10
+ let(:xpath) { '/document/results/target/heartbleed' }
11
+
12
+ subject { described_class.new(xml.at(xpath)) }
13
+
14
+ describe "#openssl_heartbleed" do
15
+ context "when the '<openSslHeartbleed/>' XML element is present" do
16
+ subject do
17
+ described_class.new(xml.at("#{xpath}[openSslHeartbleed]"))
18
+ end
19
+
20
+ it do
21
+ expect(subject.openssl_heartbleed).to be_kind_of(described_class::OpenSSLHeartbleed)
22
+ end
23
+ end
24
+
25
+ context "when the '<openSslHeartbleed/>' XML element is missing" do
26
+ subject do
27
+ described_class.new(xml.at("#{xpath}[not(./openSslHeartbleed)]"))
28
+ end
29
+
30
+ it do
31
+ pending "need to find a host where <openSslHeartbleed/> is omitted"
32
+
33
+ expect(subject.openssl_heartbleed).to be nil
34
+ end
35
+ end
36
+ end
37
+ end