ruby-sslyze 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +3 -0
- data/.gitignore +4 -0
- data/.rspec +1 -0
- data/.travis.yml +19 -0
- data/.yardopts +1 -0
- data/ChangeLog.md +8 -0
- data/Gemfile +18 -0
- data/LICENSE.txt +20 -0
- data/README.md +70 -0
- data/Rakefile +23 -0
- data/lib/sslyze.rb +3 -0
- data/lib/sslyze/cert_info.rb +55 -0
- data/lib/sslyze/certificate.rb +139 -0
- data/lib/sslyze/certificate/domain_name.rb +77 -0
- data/lib/sslyze/certificate/extensions.rb +127 -0
- data/lib/sslyze/certificate/extensions/authority_information_access.rb +38 -0
- data/lib/sslyze/certificate/extensions/extension.rb +26 -0
- data/lib/sslyze/certificate/extensions/x509v3_basic_constraints.rb +60 -0
- data/lib/sslyze/certificate/extensions/x509v3_certificate_policies.rb +50 -0
- data/lib/sslyze/certificate/extensions/x509v3_crl_distribution_points.rb +32 -0
- data/lib/sslyze/certificate/extensions/x509v3_extended_key_usage.rb +32 -0
- data/lib/sslyze/certificate/extensions/x509v3_key_usage.rb +50 -0
- data/lib/sslyze/certificate/extensions/x509v3_subject_alternative_name.rb +71 -0
- data/lib/sslyze/certificate/issuer.rb +56 -0
- data/lib/sslyze/certificate/public_key.rb +9 -0
- data/lib/sslyze/certificate/subject.rb +117 -0
- data/lib/sslyze/certificate/subject_public_key_info.rb +53 -0
- data/lib/sslyze/certificate/validity.rb +9 -0
- data/lib/sslyze/certificate_chain.rb +89 -0
- data/lib/sslyze/certificate_validation.rb +44 -0
- data/lib/sslyze/cipher_suite.rb +237 -0
- data/lib/sslyze/key_exchange.rb +106 -0
- data/lib/sslyze/ocsp_response.rb +87 -0
- data/lib/sslyze/program.rb +66 -0
- data/lib/sslyze/protocol.rb +133 -0
- data/lib/sslyze/target.rb +295 -0
- data/lib/sslyze/task.rb +65 -0
- data/lib/sslyze/types.rb +17 -0
- data/lib/sslyze/version.rb +4 -0
- data/lib/sslyze/xml.rb +139 -0
- data/ruby-sslyze.gemspec +24 -0
- data/spec/cert_info_spec.rb +29 -0
- data/spec/certificate/subject_name_spec.rb +72 -0
- data/spec/certificate_chain_spec.rb +61 -0
- data/spec/certificate_spec.rb +330 -0
- data/spec/certificate_validation_spec.rb +27 -0
- data/spec/cipher_suite_spec.rb +50 -0
- data/spec/issuer_spec.rb +33 -0
- data/spec/key_exchange_spec.rb +97 -0
- data/spec/ocsp_response_spec.rb +59 -0
- data/spec/protocol_spec.rb +99 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/sslyze.xml +2798 -0
- data/spec/sslyze_spec.rb +8 -0
- data/spec/subject_public_key_info_spec.rb +35 -0
- data/spec/subject_spec.rb +67 -0
- data/spec/target_spec.rb +176 -0
- data/spec/xml_examples.rb +9 -0
- data/spec/xml_spec.rb +72 -0
- metadata +162 -0
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'sslyze/certificate/extensions/authority_information_access'
|
2
|
+
require 'sslyze/certificate/extensions/x509v3_crl_distribution_points'
|
3
|
+
require 'sslyze/certificate/extensions/x509v3_key_usage'
|
4
|
+
require 'sslyze/certificate/extensions/x509v3_extended_key_usage'
|
5
|
+
require 'sslyze/certificate/extensions/x509v3_subject_alternative_name'
|
6
|
+
require 'sslyze/certificate/extensions/x509v3_basic_constraints'
|
7
|
+
require 'sslyze/certificate/extensions/x509v3_certificate_policies'
|
8
|
+
|
9
|
+
module SSLyze
|
10
|
+
class Certificate
|
11
|
+
#
|
12
|
+
# Represents the `<extensions>` XML element.
|
13
|
+
#
|
14
|
+
class Extensions
|
15
|
+
|
16
|
+
#
|
17
|
+
# Initializes the extensions.
|
18
|
+
#
|
19
|
+
# @param [Nokogiri::XML::Node] node
|
20
|
+
# The `<extensions>` XML element.
|
21
|
+
#
|
22
|
+
def initialize(node)
|
23
|
+
@node = node
|
24
|
+
end
|
25
|
+
|
26
|
+
#
|
27
|
+
# The x509v3 subject key identifier information.
|
28
|
+
#
|
29
|
+
# @return [String, nil]
|
30
|
+
#
|
31
|
+
def x509v3_subject_key_identifier
|
32
|
+
@x509v3_subject_key_identifier ||= if (node = @node.at('X509v3SubjectKeyIdentifier'))
|
33
|
+
node.inner_text
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
# The authority information access.
|
39
|
+
#
|
40
|
+
# @return [AuthorityInformationAccess, nil]
|
41
|
+
#
|
42
|
+
def authority_information_access
|
43
|
+
@authority_information_access ||= if (node = @node.at('AuthorityInformationAccess'))
|
44
|
+
AuthorityInformationAccess.new(node)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
# The x509v3 CRL Distribution Points.
|
50
|
+
#
|
51
|
+
# @return [X509v3CRLDistributionPoints, nil]
|
52
|
+
#
|
53
|
+
def x509v3_crl_distribution_points
|
54
|
+
@x509v3_crl_distribution_points ||= if (node = @node.at('X509v3CRLDistributionPoints'))
|
55
|
+
X509v3CRLDistributionPoints.new(node)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# The x509v3 basic constraints.
|
61
|
+
#
|
62
|
+
# @return [X509v3BasicConstraints, nil]
|
63
|
+
#
|
64
|
+
def x509v3_basic_constraints
|
65
|
+
@x509v3_basic_constraints ||= if (constraints = @node.at('X509v3BasicConstraints'))
|
66
|
+
X509v3BasicConstraints.new(constraints)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# x509v3 key usage.
|
72
|
+
#
|
73
|
+
# @return [X509v3KeyUsage, nil]
|
74
|
+
#
|
75
|
+
def x509v3_key_usage
|
76
|
+
@x509v3_key_usage ||= if (node = @node.at('X509v3KeyUsage'))
|
77
|
+
X509v3KeyUsage.new(node)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
#
|
82
|
+
# x509v3 extended key usage.
|
83
|
+
#
|
84
|
+
# @return [X509v3ExtendedKeyUsage, nil]
|
85
|
+
#
|
86
|
+
def x509v3_extended_key_usage
|
87
|
+
@x509v3_extended_key_usage ||= if (node = @node.at('X509v3ExtendedKeyUsage'))
|
88
|
+
X509v3ExtendedKeyUsage.new(node)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
#
|
93
|
+
# x509v3 subject alternative name.
|
94
|
+
#
|
95
|
+
# @return [X509v3SubjectAlternativeName, nil]
|
96
|
+
#
|
97
|
+
def x509v3_subject_alternative_name
|
98
|
+
@x509v3_subject_alternative_name ||= if (node = @node.search('X509v3SubjectAlternativeName'))
|
99
|
+
X509v3SubjectAlternativeName.new(node)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
#
|
104
|
+
# x509v3 authority key identifier.
|
105
|
+
#
|
106
|
+
# @return [String, nil]
|
107
|
+
#
|
108
|
+
def x509v3_authority_key_identifier
|
109
|
+
@x509v3_authority_key_identifier ||= if (node = @node.at('X509v3AuthorityKeyIdentifier'))
|
110
|
+
node.inner_text
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
#
|
115
|
+
# x509v3 certificate policies.
|
116
|
+
#
|
117
|
+
# @return [X509v3CertificatePolicies, nil]
|
118
|
+
#
|
119
|
+
def x509v3_certificate_policies
|
120
|
+
@x509v3_certificate_policies ||= if (node = @node.at('X509v3CertificatePolicies'))
|
121
|
+
X509v3CertificatePolicies.new(node)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'sslyze/certificate/extensions/extension'
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module SSLyze
|
6
|
+
class Certificate
|
7
|
+
class Extensions
|
8
|
+
#
|
9
|
+
# Represents the `<AuthorityInformationAccess>` XML element.
|
10
|
+
#
|
11
|
+
class AuthorityInformationAccess < Extension
|
12
|
+
|
13
|
+
#
|
14
|
+
# The CA issuers.
|
15
|
+
#
|
16
|
+
# @return [Array<URI>]
|
17
|
+
#
|
18
|
+
def ca_issuers
|
19
|
+
@ca_issuers ||= @node.search('CAIssuers/URI/listEntry').map do |uri|
|
20
|
+
URI(uri.inner_text)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# The OCSP URIs.
|
26
|
+
#
|
27
|
+
# @return [Array<URI>]
|
28
|
+
#
|
29
|
+
def ocsp
|
30
|
+
@ocsp ||= @node.search('OCSP/URI/listEntry').map do |uri|
|
31
|
+
URI(uri.inner_text)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module SSLyze
|
2
|
+
class Certificate
|
3
|
+
class Extensions
|
4
|
+
#
|
5
|
+
# Represents a SSL extension XML element.
|
6
|
+
#
|
7
|
+
class Extension
|
8
|
+
|
9
|
+
#
|
10
|
+
# Initializes the extension.
|
11
|
+
#
|
12
|
+
# @param [Nokogiri::XML::Node] node
|
13
|
+
# The extension node.
|
14
|
+
#
|
15
|
+
def initialize(node)
|
16
|
+
@node = node
|
17
|
+
end
|
18
|
+
|
19
|
+
def present?
|
20
|
+
!@node.nil?
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'sslyze/certificate/extensions/extension'
|
2
|
+
|
3
|
+
module SSLyze
|
4
|
+
class Certificate
|
5
|
+
class Extensions
|
6
|
+
#
|
7
|
+
# Represents the `<X509v3BasicConstraints>` XML element.
|
8
|
+
#
|
9
|
+
class X509v3BasicConstraints < Extension
|
10
|
+
|
11
|
+
#
|
12
|
+
# Specifies whether the `critical` constraint was specified.
|
13
|
+
#
|
14
|
+
# @return [Boolean]
|
15
|
+
#
|
16
|
+
def critical?
|
17
|
+
@node.inner_text.include?('critical')
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# The value of the `CA` constraint.
|
22
|
+
#
|
23
|
+
# @return [Boolean, nil]
|
24
|
+
#
|
25
|
+
def ca?
|
26
|
+
if @node.inner_text.include?('CA:TRUE') then true
|
27
|
+
elsif @node.inner_text.include?('CA:FALSE') then false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# The value of the `pathlen` constraint.
|
33
|
+
#
|
34
|
+
# @return [Integer, nil]
|
35
|
+
#
|
36
|
+
def path_length
|
37
|
+
@path_length ||= if (match = @node.inner_text.match(/pathlen:(\d+)/))
|
38
|
+
match[1].to_i
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
alias path_len path_length
|
43
|
+
|
44
|
+
#
|
45
|
+
# The raw basic constraint String.
|
46
|
+
#
|
47
|
+
# @return [String]
|
48
|
+
#
|
49
|
+
def to_s
|
50
|
+
if @node then @node.inner_text
|
51
|
+
else ''
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
alias to_str to_s
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'sslyze/certificate/extensions/extension'
|
2
|
+
|
3
|
+
module SSLyze
|
4
|
+
class Certificate
|
5
|
+
class Extensions
|
6
|
+
#
|
7
|
+
# Represents the `<X509v3CertificatePolicies>` XML element.
|
8
|
+
#
|
9
|
+
class X509v3CertificatePolicies < Extension
|
10
|
+
|
11
|
+
#
|
12
|
+
# The certificate policy.
|
13
|
+
#
|
14
|
+
# @return [Array<String>]
|
15
|
+
#
|
16
|
+
def policy
|
17
|
+
@policy ||= @node.search('Policy/listEntry').map(&:inner_text)
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# The explicit text.
|
22
|
+
#
|
23
|
+
# @return [Array<String>]
|
24
|
+
#
|
25
|
+
def explicit_text
|
26
|
+
@explicit_text ||= @node.search('ExplicitText/listEntry').map(&:inner_text)
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
# The CPS.
|
31
|
+
#
|
32
|
+
# @return [Array<String>]
|
33
|
+
#
|
34
|
+
def cps
|
35
|
+
@cps ||= @node.search('CPS/listEntry').map(&:inner_text)
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# User notice.
|
40
|
+
#
|
41
|
+
# @return [String, nil]
|
42
|
+
#
|
43
|
+
def user_notice
|
44
|
+
@user_notice ||= @node.search('userNotice/listEntry').map(&:inner_text)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'sslyze/certificate/extensions/extension'
|
2
|
+
|
3
|
+
module SSLyze
|
4
|
+
class Certificate
|
5
|
+
class Extensions
|
6
|
+
#
|
7
|
+
# Represents the `<X509v3CRLDistributionPoints>` XML element.
|
8
|
+
#
|
9
|
+
class X509v3CRLDistributionPoints < Extension
|
10
|
+
|
11
|
+
#
|
12
|
+
# @return [Array<String>]
|
13
|
+
#
|
14
|
+
def full_name
|
15
|
+
@full_name ||= @node.search('FullName/listEntry').map do |full_name|
|
16
|
+
full_name.inner_text
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# @return [Array<URI>]
|
22
|
+
#
|
23
|
+
def uri
|
24
|
+
@uri ||= @node.search('URI/listEntry').map do |uri|
|
25
|
+
URI(uri.inner_text)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'sslyze/certificate/extensions/extension'
|
2
|
+
|
3
|
+
module SSLyze
|
4
|
+
class Certificate
|
5
|
+
class Extensions
|
6
|
+
#
|
7
|
+
# Represetns the `<X509v3ExtendedKeyUsage>` XML element.
|
8
|
+
#
|
9
|
+
class X509v3ExtendedKeyUsage < Extension
|
10
|
+
|
11
|
+
#
|
12
|
+
# TLS web client authentication.
|
13
|
+
#
|
14
|
+
# @return [String]
|
15
|
+
#
|
16
|
+
def tls_web_client_authentication
|
17
|
+
@tls_web_client_authentication ||= @node.at('TLSWebClientAuthentication').inner_text
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# TLS web server authentication.
|
22
|
+
#
|
23
|
+
# @return [String]
|
24
|
+
#
|
25
|
+
def tls_web_server_authentication
|
26
|
+
@tls_web_server_authentication ||= @node.at('TLSWebServerAuthentication').inner_text
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'sslyze/certificate/extensions/extension'
|
2
|
+
|
3
|
+
module SSLyze
|
4
|
+
class Certificate
|
5
|
+
class Extensions
|
6
|
+
#
|
7
|
+
# Represents the `<X509v3KeyUsage>` XML element.
|
8
|
+
#
|
9
|
+
class X509v3KeyUsage < Extension
|
10
|
+
|
11
|
+
#
|
12
|
+
# Key encipherment.
|
13
|
+
#
|
14
|
+
# @return [String]
|
15
|
+
#
|
16
|
+
def key_encipherment
|
17
|
+
@key_encipherment ||= @node.at('KeyEncipherment').inner_text
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# Digital signature.
|
22
|
+
#
|
23
|
+
# @return [String]
|
24
|
+
#
|
25
|
+
def digital_signature
|
26
|
+
@digital_signature ||= @node.at('DigitalSignature').inner_text
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
# CRL Sign.
|
31
|
+
#
|
32
|
+
# @return [String]
|
33
|
+
#
|
34
|
+
def crl_sign
|
35
|
+
@crl_sign ||= @node.at('CRLSign').inner_text
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Certificate sign.
|
40
|
+
#
|
41
|
+
# @return [String]
|
42
|
+
#
|
43
|
+
def certificate_sign
|
44
|
+
@certificate_sign ||= @node.at('CertificateSign').inner_text
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'sslyze/certificate/extensions/x509v3_subject_alternative_name'
|
2
|
+
require 'sslyze/certificate/domain_name'
|
3
|
+
|
4
|
+
module SSLyze
|
5
|
+
class Certificate
|
6
|
+
class Extensions
|
7
|
+
#
|
8
|
+
# Represents the `<X509v3SubjectAlternativeName>` XML element.
|
9
|
+
#
|
10
|
+
class X509v3SubjectAlternativeName < Extension
|
11
|
+
|
12
|
+
#
|
13
|
+
# The alternative email names.
|
14
|
+
#
|
15
|
+
# @return [Array<String>]
|
16
|
+
#
|
17
|
+
def email
|
18
|
+
@email ||= @node.search('email/listEntry').map(&:inner_text)
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# The alternative URI names.
|
23
|
+
#
|
24
|
+
# @return [Array<String>]
|
25
|
+
#
|
26
|
+
def uri
|
27
|
+
@rui ||= @node.search('URI/listEntry').map(&:inner_text)
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# The alternative DNS names.
|
32
|
+
#
|
33
|
+
# @return [Array<DomainName>]
|
34
|
+
#
|
35
|
+
def dns
|
36
|
+
@dns ||= @node.search('DNS/listEntry').map do |entry|
|
37
|
+
DomainName.new(entry.inner_text)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# The alternative RID names.
|
43
|
+
#
|
44
|
+
# @return [Array<String>]
|
45
|
+
#
|
46
|
+
def rid
|
47
|
+
@rid ||= @node.search('RID/listEntry').map(&:inner_text)
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# The alternative IP names.
|
52
|
+
#
|
53
|
+
# @return [Array<String>]
|
54
|
+
#
|
55
|
+
def ip
|
56
|
+
@ip ||= @node.search('IP/listEntry').map(&:inner_text)
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# The alternative dirName names.
|
61
|
+
#
|
62
|
+
# @return [Array<String>]
|
63
|
+
#
|
64
|
+
def dir_name
|
65
|
+
@dir_name ||= @node.search('dirName/listEntry').map(&:inner_text)
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|