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.
- checksums.yaml +4 -4
- data/.gitignore +6 -4
- data/.travis.yml +15 -7
- data/ChangeLog.md +29 -12
- data/Gemfile +3 -2
- data/LICENSE.txt +1 -1
- data/README.md +5 -5
- data/Rakefile +1 -1
- data/lib/sslyze/cipher_suites.rb +176 -0
- data/lib/sslyze/program.rb +8 -8
- data/lib/sslyze/task.rb +40 -33
- data/lib/sslyze/version.rb +1 -1
- data/lib/sslyze/{certificate/domain_name.rb → x509/domain.rb} +5 -3
- data/lib/sslyze/x509/extension.rb +15 -0
- data/lib/sslyze/x509/extension_set.rb +140 -0
- data/lib/sslyze/x509/extensions.rb +6 -0
- data/lib/sslyze/x509/extensions/basic_constraints.rb +41 -0
- data/lib/sslyze/x509/extensions/certificate_policies.rb +108 -0
- data/lib/sslyze/x509/extensions/crl_distribution_points.rb +47 -0
- data/lib/sslyze/x509/extensions/extended_key_usage.rb +58 -0
- data/lib/sslyze/x509/extensions/key_usage.rb +66 -0
- data/lib/sslyze/x509/extensions/subject_alt_name.rb +144 -0
- data/lib/sslyze/x509/name.rb +194 -0
- data/lib/sslyze/x509/public_key.rb +53 -0
- data/lib/sslyze/xml.rb +26 -37
- data/lib/sslyze/xml/attributes.rb +5 -0
- data/lib/sslyze/xml/attributes/error.rb +30 -0
- data/lib/sslyze/xml/attributes/exception.rb +30 -0
- data/lib/sslyze/xml/attributes/is_supported.rb +29 -0
- data/lib/sslyze/xml/attributes/is_vulnerable.rb +29 -0
- data/lib/sslyze/xml/attributes/title.rb +31 -0
- data/lib/sslyze/xml/certinfo.rb +67 -0
- data/lib/sslyze/xml/certinfo/certificate.rb +202 -0
- data/lib/sslyze/xml/certinfo/certificate_validation.rb +69 -0
- data/lib/sslyze/xml/certinfo/certificate_validation/hostname_validation.rb +54 -0
- data/lib/sslyze/xml/certinfo/certificate_validation/path_validation.rb +84 -0
- data/lib/sslyze/xml/certinfo/certificate_validation/verified_certificate_chain.rb +41 -0
- data/lib/sslyze/xml/certinfo/has_certificates.rb +102 -0
- data/lib/sslyze/xml/certinfo/ocsp_stapling.rb +45 -0
- data/lib/sslyze/xml/certinfo/ocsp_stapling/ocsp_response.rb +87 -0
- data/lib/sslyze/xml/certinfo/received_certificate_chain.rb +48 -0
- data/lib/sslyze/xml/compression.rb +33 -0
- data/lib/sslyze/xml/compression/compression_method.rb +38 -0
- data/lib/sslyze/xml/fallback.rb +34 -0
- data/lib/sslyze/xml/fallback/tls_fallback_scsv.rb +27 -0
- data/lib/sslyze/xml/heartbleed.rb +38 -0
- data/lib/sslyze/xml/heartbleed/openssl_heartbleed.rb +29 -0
- data/lib/sslyze/xml/http_headers.rb +42 -0
- data/lib/sslyze/xml/http_headers/http_public_key_pinning.rb +121 -0
- data/lib/sslyze/xml/http_headers/http_strict_transport_security.rb +59 -0
- data/lib/sslyze/xml/invalid_target.rb +33 -0
- data/lib/sslyze/xml/openssl_ccs.rb +34 -0
- data/lib/sslyze/xml/openssl_ccs/openssl_ccs_injection.rb +26 -0
- data/lib/sslyze/xml/plugin.rb +27 -0
- data/lib/sslyze/xml/protocol.rb +143 -0
- data/lib/sslyze/xml/protocol/cipher_suite.rb +93 -0
- data/lib/sslyze/xml/protocol/cipher_suite/key_exchange.rb +127 -0
- data/lib/sslyze/xml/reneg.rb +28 -0
- data/lib/sslyze/xml/reneg/session_renegotiation.rb +51 -0
- data/lib/sslyze/xml/resum.rb +42 -0
- data/lib/sslyze/xml/resum/session_resumption_with_session_ids.rb +94 -0
- data/lib/sslyze/xml/resum/session_resumption_with_tls_tickets.rb +69 -0
- data/lib/sslyze/xml/resum_rate.rb +30 -0
- data/lib/sslyze/xml/target.rb +371 -0
- data/lib/sslyze/xml/types.rb +19 -0
- data/ruby-sslyze.gemspec +3 -3
- data/spec/spec_helper.rb +2 -4
- data/spec/sslyze.xml +2356 -2580
- data/spec/x509/domain_spec.rb +125 -0
- data/spec/x509/extension_set_spec.rb +208 -0
- data/spec/x509/extension_spec.rb +58 -0
- data/spec/x509/extensions/basic_constraints_spec.rb +41 -0
- data/spec/x509/extensions/certificate_policies_spec.rb +38 -0
- data/spec/x509/extensions/crl_distribution_points_spec.rb +38 -0
- data/spec/x509/extensions/extended_key_usage_spec.rb +58 -0
- data/spec/x509/extensions/key_usage_spec.rb +84 -0
- data/spec/x509/extensions/subject_alt_name_spec.rb +146 -0
- data/spec/x509/name_spec.rb +85 -0
- data/spec/x509/public_key_spec.rb +113 -0
- data/spec/xml/certinfo/certificate_spec.rb +166 -0
- data/spec/xml/certinfo/certificate_validation/hostname_validation_spec.rb +23 -0
- data/spec/xml/certinfo/certificate_validation/path_validation_spec.rb +107 -0
- data/spec/xml/certinfo/certificate_validation/verified_certificate_chain_spec.rb +163 -0
- data/spec/xml/certinfo/certificate_validation_spec.rb +40 -0
- data/spec/xml/certinfo/ocsp_stapling/ocsp_response_spec.rb +61 -0
- data/spec/xml/certinfo/ocsp_stapling_spec.rb +31 -0
- data/spec/xml/certinfo/received_certificate_chain_spec.rb +165 -0
- data/spec/xml/certinfo_spec.rb +45 -0
- data/spec/xml/compression/compression_method_spec.rb +23 -0
- data/spec/xml/compression_spec.rb +23 -0
- data/spec/xml/heartbleed/openssl_heartbleed_spec.rb +17 -0
- data/spec/xml/heartbleed_spec.rb +37 -0
- data/spec/xml/http_headers/http_public_key_pinning_spec.rb +73 -0
- data/spec/xml/http_headers/http_strict_transport_security_spec.rb +107 -0
- data/spec/xml/http_headers_spec.rb +63 -0
- data/spec/xml/invalid_target_spec.rb +23 -0
- data/spec/xml/plugin_examples.rb +14 -0
- data/spec/{key_exchange_spec.rb → xml/protocol/cipher_suite/key_exchange_spec.rb} +9 -3
- data/spec/xml/protocol/cipher_suite_spec.rb +66 -0
- data/spec/xml/protocol_spec.rb +115 -0
- data/spec/xml/reneg/session_renegotiation_spec.rb +23 -0
- data/spec/xml/reneg_spec.rb +35 -0
- data/spec/xml/resum/session_resumption_with_session_ids_spec.rb +103 -0
- data/spec/xml/resum/session_resumption_with_tls_tickets_spec.rb +121 -0
- data/spec/xml/resum_rate_spec.rb +30 -0
- data/spec/xml/resum_spec.rb +47 -0
- data/spec/{target_spec.rb → xml/target_spec.rb} +73 -27
- data/spec/xml_spec.rb +13 -21
- metadata +138 -61
- data/lib/sslyze/cert_info.rb +0 -57
- data/lib/sslyze/certificate.rb +0 -139
- data/lib/sslyze/certificate/extensions.rb +0 -127
- data/lib/sslyze/certificate/extensions/authority_information_access.rb +0 -38
- data/lib/sslyze/certificate/extensions/extension.rb +0 -26
- data/lib/sslyze/certificate/extensions/x509v3_basic_constraints.rb +0 -60
- data/lib/sslyze/certificate/extensions/x509v3_certificate_policies.rb +0 -50
- data/lib/sslyze/certificate/extensions/x509v3_crl_distribution_points.rb +0 -32
- data/lib/sslyze/certificate/extensions/x509v3_extended_key_usage.rb +0 -32
- data/lib/sslyze/certificate/extensions/x509v3_key_usage.rb +0 -50
- data/lib/sslyze/certificate/extensions/x509v3_subject_alternative_name.rb +0 -71
- data/lib/sslyze/certificate/issuer.rb +0 -56
- data/lib/sslyze/certificate/public_key.rb +0 -9
- data/lib/sslyze/certificate/subject.rb +0 -117
- data/lib/sslyze/certificate/subject_public_key_info.rb +0 -53
- data/lib/sslyze/certificate/validity.rb +0 -9
- data/lib/sslyze/certificate_chain.rb +0 -89
- data/lib/sslyze/certificate_validation.rb +0 -70
- data/lib/sslyze/cipher_suite.rb +0 -237
- data/lib/sslyze/invalid_target.rb +0 -35
- data/lib/sslyze/key_exchange.rb +0 -106
- data/lib/sslyze/ocsp_response.rb +0 -87
- data/lib/sslyze/protocol.rb +0 -133
- data/lib/sslyze/target.rb +0 -312
- data/lib/sslyze/types.rb +0 -17
- data/spec/cert_info_spec.rb +0 -29
- data/spec/certificate/subject_name_spec.rb +0 -72
- data/spec/certificate_chain_spec.rb +0 -61
- data/spec/certificate_spec.rb +0 -330
- data/spec/certificate_validation_spec.rb +0 -39
- data/spec/cipher_suite_spec.rb +0 -50
- data/spec/invalid_target_spec.rb +0 -21
- data/spec/issuer_spec.rb +0 -33
- data/spec/ocsp_response_spec.rb +0 -59
- data/spec/protocol_spec.rb +0 -99
- data/spec/subject_public_key_info_spec.rb +0 -35
- data/spec/subject_spec.rb +0 -69
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'xml_examples'
|
|
3
|
+
require 'sslyze/xml/http_headers/http_public_key_pinning'
|
|
4
|
+
|
|
5
|
+
describe SSLyze::XML::HTTPHeaders::HTTPPublicKeyPinning do
|
|
6
|
+
include_examples "XML specs"
|
|
7
|
+
|
|
8
|
+
let(:xpath) { '/document/results/target/http_headers/httpPublicKeyPinning' }
|
|
9
|
+
|
|
10
|
+
subject do
|
|
11
|
+
described_class.new(xml.at(xpath))
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe "#include_sub_domains?" do
|
|
15
|
+
context "when the 'includeSubDomains' attribute is present" do
|
|
16
|
+
let(:xpath) { "#{super()}[@includeSubDomains]" }
|
|
17
|
+
|
|
18
|
+
context "and it is 'True'" do
|
|
19
|
+
let(:xpath) { "#{super()}[@includeSubDomains='True']" }
|
|
20
|
+
|
|
21
|
+
it do
|
|
22
|
+
pending "find domain where includeSubDomains='True'"
|
|
23
|
+
|
|
24
|
+
expect(subject.include_sub_domains?).to be(true)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context "but it is 'False'" do
|
|
29
|
+
let(:xpath) { "#{super()}[@includeSubDomains='False']" }
|
|
30
|
+
|
|
31
|
+
it do
|
|
32
|
+
expect(subject.include_sub_domains?).to be(false)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
context "when the 'includeSubDomains' attribute is not present" do
|
|
38
|
+
let(:xpath) { "#{super()}[not(@includeSubDomains)]" }
|
|
39
|
+
|
|
40
|
+
it { expect(subject.include_sub_domains?).to be nil }
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe "#is_supported?" do
|
|
45
|
+
context "when the 'isSupported' attribute is 'True'" do
|
|
46
|
+
let(:xpath) { "#{super()}[@isSupported='True']" }
|
|
47
|
+
|
|
48
|
+
it { expect(subject.is_supported?).to be true }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
context "when the 'isSupported' attribute is 'False'" do
|
|
52
|
+
let(:xpath) { "#{super()}[@isSupported='False']" }
|
|
53
|
+
|
|
54
|
+
it { expect(subject.is_supported?).to be false }
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe "#max_age" do
|
|
59
|
+
context "when the 'maxAge' attribute is present" do
|
|
60
|
+
let(:xpath) { "#{super()}[@maxAge]" }
|
|
61
|
+
|
|
62
|
+
it "should return the 'maxAge' attribute" do
|
|
63
|
+
expect(subject.max_age).to be > 0
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context "when the 'maxAge' attribute is not present" do
|
|
68
|
+
let(:xpath) { "#{super()}[not(@maxAge)]" }
|
|
69
|
+
|
|
70
|
+
it { expect(subject.max_age).to be nil }
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'xml_examples'
|
|
3
|
+
require 'sslyze/xml/http_headers/http_strict_transport_security'
|
|
4
|
+
|
|
5
|
+
describe SSLyze::XML::HTTPHeaders::HTTPStrictTransportSecurity do
|
|
6
|
+
include_examples "XML specs"
|
|
7
|
+
|
|
8
|
+
let(:xpath) { '/document/results/target/http_headers/httpStrictTransportSecurity' }
|
|
9
|
+
|
|
10
|
+
subject do
|
|
11
|
+
described_class.new(xml.at(xpath))
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe "#include_sub_domains?" do
|
|
15
|
+
context "when the 'includeSubDomains' attribute is present" do
|
|
16
|
+
subject do
|
|
17
|
+
described_class.new(xml.at("#{xpath}[@includeSubDomains]"))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "should return a Boolean value" do
|
|
21
|
+
expect(subject.include_sub_domains?).to be(true).or(be(false))
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context "when the 'includeSubDomains' attribute is not present" do
|
|
26
|
+
subject do
|
|
27
|
+
described_class.new(xml.at("#{xpath}[not(@includeSubDomains)]"))
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it do
|
|
31
|
+
pending "need an example with no 'includeSubDomains' attribute"
|
|
32
|
+
|
|
33
|
+
expect(subject.include_sub_domains?).to be nil
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
describe "#is_supported?" do
|
|
39
|
+
context "when the 'isSupported' attribute is 'True'" do
|
|
40
|
+
subject do
|
|
41
|
+
described_class.new(xml.at("#{xpath}[@isSupported=\"True\"]"))
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it { expect(subject.is_supported?).to be true }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
context "when the 'isSupported' attribute is 'False'" do
|
|
48
|
+
subject do
|
|
49
|
+
described_class.new(xml.at("#{xpath}[@isSupported=\"False\"]"))
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it do
|
|
53
|
+
pending "need an example where 'isSupported' is 'False'"
|
|
54
|
+
|
|
55
|
+
expect(subject.is_supported?).to be false
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
describe "#max_age" do
|
|
61
|
+
context "when the 'maxAge' attribute is present" do
|
|
62
|
+
subject do
|
|
63
|
+
described_class.new(xml.at("#{xpath}[@maxAge]"))
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "should return the 'maxAge' attribute" do
|
|
67
|
+
expect(subject.max_age).to be > 0
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
context "when the 'maxAge' attribute is not present" do
|
|
72
|
+
subject do
|
|
73
|
+
described_class.new(xml.at("#{xpath}[not(@maxAge)]"))
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it do
|
|
77
|
+
pending "need an example with no 'maxAge' attribute"
|
|
78
|
+
|
|
79
|
+
expect(subject.max_age).to be nil
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
describe "#preload?" do
|
|
85
|
+
context "when the 'preload' attribute is present" do
|
|
86
|
+
subject do
|
|
87
|
+
described_class.new(xml.at("#{xpath}[@preload]"))
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "should return a Boolean value" do
|
|
91
|
+
expect(subject.preload?).to be(true).or(be(false))
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
context "when the 'preload' attribute is not present" do
|
|
96
|
+
subject do
|
|
97
|
+
described_class.new(xml.at("#{xpath}[not(@preload)]"))
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it do
|
|
101
|
+
pending "need an example with no 'preload' attribute"
|
|
102
|
+
|
|
103
|
+
expect(subject.preload?).to be nil
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'xml_examples'
|
|
3
|
+
require 'xml/plugin_examples'
|
|
4
|
+
require 'sslyze/xml/http_headers'
|
|
5
|
+
|
|
6
|
+
describe SSLyze::XML::HTTPHeaders do
|
|
7
|
+
include_examples "XML specs"
|
|
8
|
+
include_examples "Plugin element"
|
|
9
|
+
|
|
10
|
+
let(:xpath) { '/document/results/target/http_headers' }
|
|
11
|
+
|
|
12
|
+
subject { described_class.new(xml.at(xpath)) }
|
|
13
|
+
|
|
14
|
+
describe "#http_strict_transport_security" do
|
|
15
|
+
context "when the '<httpStrictTransportSecurity/>' XML element is present" do
|
|
16
|
+
subject do
|
|
17
|
+
described_class.new(xml.at("#{xpath}[httpStrictTransportSecurity]"))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it do
|
|
21
|
+
expect(subject.http_strict_transport_security).to \
|
|
22
|
+
be_kind_of(described_class::HTTPStrictTransportSecurity)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context "when the '<httpStrictTransportSecurity/>' XML element is omitted" do
|
|
27
|
+
subject do
|
|
28
|
+
described_class.new(xml.at("#{xpath}[not(./httpStrictTransportSecurity)]"))
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it do
|
|
32
|
+
pending "need an example with no '<httpStrictTransportSecurity/>'"
|
|
33
|
+
|
|
34
|
+
expect(subject.http_strict_transport_security).to be nil
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe "#http_public_key_pinning" do
|
|
40
|
+
context "when the '<httpPublicKeyPinning/>' XML element is present" do
|
|
41
|
+
subject do
|
|
42
|
+
described_class.new(xml.at("#{xpath}[httpPublicKeyPinning]"))
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it do
|
|
46
|
+
expect(subject.http_public_key_pinning).to \
|
|
47
|
+
be_kind_of(described_class::HTTPPublicKeyPinning)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
context "when the '<httpPublicKeyPinning/>' XML element is omitted" do
|
|
52
|
+
subject do
|
|
53
|
+
described_class.new(xml.at("#{xpath}[not(./httpPublicKeyPinning)]"))
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it do
|
|
57
|
+
pending "need an example with no '<httpPublicKeyPinning/>'"
|
|
58
|
+
|
|
59
|
+
expect(subject.http_public_key_pinning).to be nil
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'xml_examples'
|
|
3
|
+
require 'sslyze/xml/invalid_target'
|
|
4
|
+
|
|
5
|
+
describe SSLyze::XML::InvalidTarget do
|
|
6
|
+
include_examples "XML specs"
|
|
7
|
+
|
|
8
|
+
let(:xpath) { '/document/invalidTargets/invalidTarget' }
|
|
9
|
+
|
|
10
|
+
subject { described_class.new(xml.at(xpath)) }
|
|
11
|
+
|
|
12
|
+
describe "#host" do
|
|
13
|
+
it "must parse the host attribute" do
|
|
14
|
+
expect(subject.host).to be == 'foo'
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe "#error" do
|
|
19
|
+
it "must parse the ip attribute" do
|
|
20
|
+
expect(subject.error).to be == 'Could not resolve foo'
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require 'rspec'
|
|
2
|
+
|
|
3
|
+
shared_examples_for "Plugin element" do
|
|
4
|
+
describe "#title" do
|
|
5
|
+
it "should parse the title attribute" do
|
|
6
|
+
expect(subject.title).to be_kind_of(String)
|
|
7
|
+
expect(subject.title).not_to be_empty
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe "#exception" do
|
|
12
|
+
pending "need an examples of plugin elements with exception messages"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
require 'xml_examples'
|
|
3
|
-
require 'sslyze/key_exchange'
|
|
3
|
+
require 'sslyze/xml/protocol/cipher_suite/key_exchange'
|
|
4
4
|
|
|
5
|
-
describe SSLyze::KeyExchange do
|
|
5
|
+
describe SSLyze::XML::Protocol::CipherSuite::KeyExchange do
|
|
6
6
|
include_examples "XML specs"
|
|
7
7
|
|
|
8
|
-
subject { described_class.new(xml.at('/document/results/target/tlsv1_2/
|
|
8
|
+
subject { described_class.new(xml.at('/document/results/target/tlsv1_2/preferredCipherSuite/cipherSuite/keyExchange')) }
|
|
9
9
|
|
|
10
10
|
describe "#a" do
|
|
11
11
|
it "should parse the A attribute" do
|
|
@@ -49,6 +49,12 @@ describe SSLyze::KeyExchange do
|
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
+
describe "#order" do
|
|
53
|
+
it "should parse the Order attribute" do
|
|
54
|
+
expect(subject.order).to be == '0x00ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
52
58
|
describe "#prime" do
|
|
53
59
|
it "should parse the Prime attribute" do
|
|
54
60
|
expect(subject.prime).to be == '0x00ffffffff00000001000000000000000000000000ffffffffffffffffffffffff'
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'xml_examples'
|
|
3
|
+
require 'sslyze/xml/protocol/cipher_suite'
|
|
4
|
+
|
|
5
|
+
describe SSLyze::XML::Protocol::CipherSuite do
|
|
6
|
+
include_examples "XML specs"
|
|
7
|
+
|
|
8
|
+
subject { described_class.new(xml.at('/document/results/target/tlsv1_2/preferredCipherSuite/cipherSuite')) }
|
|
9
|
+
|
|
10
|
+
describe "#name" do
|
|
11
|
+
it "should parse the name attribute" do
|
|
12
|
+
expect(subject.name).to be == 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256'
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe "#rfc_name" do
|
|
17
|
+
it "should return the RFC cipher suite name" do
|
|
18
|
+
expect(subject.rfc_name).to be == 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256'
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe "#openssl_name" do
|
|
23
|
+
it "should map the RFC name back to the OpenSSL name" do
|
|
24
|
+
expect(subject.openssl_name).to be == 'ECDHE-RSA-AES128-GCM-SHA256'
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe "#connection_status" do
|
|
29
|
+
it "should parse the connectionStatus attribute" do
|
|
30
|
+
expect(subject.connection_status).to be == 'HTTP 200 OK'
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe "#anonymous?" do
|
|
35
|
+
it "should query the anonymous attribute" do
|
|
36
|
+
expect(subject.anonymous?).to be false
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
describe "#key_size" do
|
|
41
|
+
it "should return the keySize attribute" do
|
|
42
|
+
expect(subject.key_size).to be 128
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe "#key_exchange" do
|
|
47
|
+
context "when the keyExchange child is present" do
|
|
48
|
+
subject do
|
|
49
|
+
described_class.new(xml.at('/document/results/target/tlsv1_2/acceptedCipherSuites/cipherSuite[keyExchange]'))
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it do
|
|
53
|
+
expect(subject.key_exchange).to be_kind_of(described_class::KeyExchange)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
context "when the keyExchange object is missing" do
|
|
58
|
+
subject do
|
|
59
|
+
described_class.new(xml.at('/document/results/target/tlsv1_2/acceptedCipherSuites/cipherSuite[not(./keyExchange)]'))
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it { expect(subject.key_exchange).to be nil }
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'xml_examples'
|
|
3
|
+
require 'sslyze/xml/protocol'
|
|
4
|
+
|
|
5
|
+
describe SSLyze::XML::Protocol do
|
|
6
|
+
include_examples "XML specs"
|
|
7
|
+
|
|
8
|
+
let(:xpath) { '/document/results/target/tlsv1_2' }
|
|
9
|
+
|
|
10
|
+
subject { described_class.new(xml.at(xpath)) }
|
|
11
|
+
|
|
12
|
+
describe "#name" do
|
|
13
|
+
it "should return the protocol name" do
|
|
14
|
+
expect(subject.name).to be == :tlsv1_2
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe "#title" do
|
|
19
|
+
it "must parse the title attribute" do
|
|
20
|
+
expect(subject.title).to be == 'TLSV1_2 Cipher Suites'
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe "#preferred_cipher_suite" do
|
|
25
|
+
context "when the 'preferredCipherSuite' XML element has children" do
|
|
26
|
+
let(:xpath) do
|
|
27
|
+
'/document/results/target/*[preferredCipherSuite/cipherSuite]'
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it do
|
|
31
|
+
expect(subject.preferred_cipher_suite).to be_kind_of(described_class::CipherSuite)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context "when the preferredCipherSuite' XML element has no children" do
|
|
36
|
+
let(:xpath) do
|
|
37
|
+
'/document/results/target/*[preferredCipherSuite][not(preferredCipherSuite/cipherSuite)]'
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it do
|
|
41
|
+
expect(subject.preferred_cipher_suite).to be nil
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe "#each_accepted_cipher_suite" do
|
|
47
|
+
it "should yield CipherSuite objects" do
|
|
48
|
+
expect { |b|
|
|
49
|
+
subject.each_accepted_cipher_suite(&b)
|
|
50
|
+
}
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context "when given no block" do
|
|
54
|
+
it { expect(subject.each_accepted_cipher_suite).to be_an(Enumerator) }
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe "#accepted_cipher_suites" do
|
|
59
|
+
it "should return an Array of CipherSuites" do
|
|
60
|
+
expect(subject.accepted_cipher_suites).to be_an(Array).and(
|
|
61
|
+
all(be_a(described_class::CipherSuite))
|
|
62
|
+
)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
describe "#each_rejected_cipher_suite" do
|
|
67
|
+
it "should yield CipherSuite objects" do
|
|
68
|
+
expect { |b|
|
|
69
|
+
subject.each_rejected_cipher_suite(&b)
|
|
70
|
+
}
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context "when given no block" do
|
|
74
|
+
it { expect(subject.each_rejected_cipher_suite).to be_an(Enumerator) }
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
describe "#rejected_cipher_suites" do
|
|
79
|
+
it "should return an Array of CipherSuites" do
|
|
80
|
+
expect(subject.rejected_cipher_suites).to be_an(Array).and(
|
|
81
|
+
all(be_a(described_class::CipherSuite))
|
|
82
|
+
)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
describe "#supported?" do
|
|
87
|
+
context "when there are preferred cipher suites" do
|
|
88
|
+
it "should return true" do
|
|
89
|
+
expect(subject.supported?).to be(true)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
describe "#each_error" do
|
|
95
|
+
it "should yield CipherSuite objects" do
|
|
96
|
+
pending "need a target with non-empty '<errors/>'"
|
|
97
|
+
|
|
98
|
+
expect { |b|
|
|
99
|
+
subject.each_error(&b)
|
|
100
|
+
}.to yield_successive_args(described_class::CipherSuite)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
context "when given no block" do
|
|
104
|
+
it { expect(subject.each_error).to be_an(Enumerator) }
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
describe "#errors" do
|
|
109
|
+
it "should return an Array of CipherSuites" do
|
|
110
|
+
expect(subject.errors).to be_an(Array).and(
|
|
111
|
+
all(be_a(described_class::CipherSuite))
|
|
112
|
+
)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|