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
@@ -1,4 +1,4 @@
1
1
  module SSLyze
2
2
  # ruby-sslyze version
3
- VERSION = "0.2.1"
3
+ VERSION = '1.0.0'
4
4
  end
@@ -1,9 +1,11 @@
1
1
  module SSLyze
2
- class Certificate
2
+ module X509
3
3
  #
4
4
  # Represents a domain name pattern.
5
5
  #
6
- class DomainName
6
+ # @since 1.0.0
7
+ #
8
+ class Domain
7
9
 
8
10
  # The subject name.
9
11
  #
@@ -43,7 +45,7 @@ module SSLyze
43
45
  # @return [Boolean]
44
46
  #
45
47
  def ==(other)
46
- @name == other.name
48
+ other.kind_of?(self.class) && @name == other.name
47
49
  end
48
50
 
49
51
  #
@@ -0,0 +1,15 @@
1
+ require 'delegate'
2
+
3
+ module SSLyze
4
+ module X509
5
+ #
6
+ # Wraps around an [OpenSSL::X509::Extension][1] object.
7
+ #
8
+ # @see http://www.rubydoc.info/stdlib/openssl/OpenSSL/X509/Extension
9
+ #
10
+ # @since 1.0.0
11
+ #
12
+ class Extension < SimpleDelegator
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,140 @@
1
+ require 'sslyze/x509/extensions'
2
+
3
+ module SSLyze
4
+ module X509
5
+ #
6
+ # Provides a Hash-like interface around an Array of
7
+ # [OpenSSL::X5095::Extension][1]s.
8
+ #
9
+ # [1]: http://www.rubydoc.info/stdlib/openssl/OpenSSL/X509/Extension
10
+ #
11
+ # @since 1.0.0
12
+ #
13
+ class ExtensionSet
14
+
15
+ include Enumerable
16
+
17
+ #
18
+ # Initializes the X509 extension set.
19
+ #
20
+ # @param [Array<OpenSSL::X509::Extension>] extensions
21
+ # The array of extensions.
22
+ #
23
+ def initialize(extensions)
24
+ @extensions = Hash[extensions.map { |ext|
25
+ [ext.oid, ext]
26
+ }]
27
+ end
28
+
29
+ #
30
+ # Enumerates over the X509 extensions in the set.
31
+ #
32
+ # @yield [extension]
33
+ #
34
+ # @yieldparam [OpenSSL::X509::Extension] extension
35
+ #
36
+ # @return [Enumerator]
37
+ #
38
+ def each(&block)
39
+ @extensions.each_value(&block)
40
+ end
41
+
42
+ #
43
+ # Determines if the X509 extension exists in the set.
44
+ #
45
+ # @param [String] oid
46
+ #
47
+ # @return [Boolean]
48
+ #
49
+ def has?(oid)
50
+ @extensions.has_key?(oid)
51
+ end
52
+
53
+ #
54
+ # Looks up the X509 extension with the given name.
55
+ # @param [String] oid
56
+ #
57
+ # @return [OpenSSL::X509::Extension]
58
+ #
59
+ def [](oid)
60
+ @extensions[oid]
61
+ end
62
+
63
+ #
64
+ # Converts the X509 extension set to an Array.
65
+ #
66
+ # @return [Array<OpenSSL::X509::Extension>]
67
+ #
68
+ def to_a
69
+ @extensions.values
70
+ end
71
+
72
+ #
73
+ # The `basicConstraints` extension.
74
+ #
75
+ # @return [Extensions::BasicConstraints, nil]
76
+ #
77
+ def basic_constraints
78
+ @basic_constraints ||= if (ext = self['basicConstraints'])
79
+ Extensions::BasicConstraints.new(ext)
80
+ end
81
+ end
82
+
83
+ #
84
+ # The `certificatePolicies` extension.
85
+ #
86
+ # @return [Extensions::CertificatePolicies, nil]
87
+ #
88
+ def certificate_policies
89
+ @certificate_policies ||= if (ext = self['certificatePolicies'])
90
+ Extensions::CertificatePolicies.new(ext)
91
+ end
92
+ end
93
+
94
+ #
95
+ # The `crlDistributionPoints` extension.
96
+ #
97
+ # @return [Extensions::CRLDistributionPoints, nil]
98
+ #
99
+ def crl_distribution_points
100
+ @crl_distribution_points ||= if (ext = self['crlDistributionPoints'])
101
+ Extensions::CRLDistributionPoints.new(ext)
102
+ end
103
+ end
104
+
105
+ #
106
+ # The `extendedKeyUsage` extension.
107
+ #
108
+ # @return [Extensions::ExtendedKeyUsage, nil]
109
+ #
110
+ def extended_key_usage
111
+ @extended_key_usage ||= if (ext = self['extendedKeyUsage'])
112
+ Extensions::ExtendedKeyUsage.new(ext)
113
+ end
114
+ end
115
+
116
+ #
117
+ # The `keyUsage` extension.
118
+ #
119
+ # @return [Extensions::KeyUsage, nil]
120
+ #
121
+ def key_usage
122
+ @key_usage ||= if (ext = self['keyUsage'])
123
+ Extensions::KeyUsage.new(ext)
124
+ end
125
+ end
126
+
127
+ #
128
+ # The `subjectAltName` extension.
129
+ #
130
+ # @return [Extensions::SubjectAltName, nil]
131
+ #
132
+ def subject_alt_name
133
+ @subject_alt_name ||= if (ext = self['subjectAltName'])
134
+ Extensions::SubjectAltName.new(ext)
135
+ end
136
+ end
137
+
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,6 @@
1
+ require 'sslyze/x509/extensions/basic_constraints'
2
+ require 'sslyze/x509/extensions/certificate_policies'
3
+ require 'sslyze/x509/extensions/crl_distribution_points'
4
+ require 'sslyze/x509/extensions/extended_key_usage'
5
+ require 'sslyze/x509/extensions/key_usage'
6
+ require 'sslyze/x509/extensions/subject_alt_name'
@@ -0,0 +1,41 @@
1
+ require 'sslyze/x509/extension'
2
+
3
+ module SSLyze
4
+ module X509
5
+ module Extensions
6
+ #
7
+ # Represents the `basicConstraints` X509v3 extension.
8
+ #
9
+ # @since 1.0.0
10
+ #
11
+ class BasicConstraints < Extension
12
+
13
+ #
14
+ # The value of the `CA` constraint.
15
+ #
16
+ # @return [Boolean, nil]
17
+ #
18
+ def ca?
19
+ if value.include?('CA:TRUE') then true
20
+ elsif value.include?('CA:FALSE') then false
21
+ end
22
+ end
23
+
24
+ #
25
+ # The value of the `pathlen` constraint.
26
+ #
27
+ # @return [Integer, nil]
28
+ #
29
+ def path_length
30
+ @path_length ||= if (match = value.match(/pathlen:(\d+)/))
31
+ match[1].to_i
32
+ end
33
+ end
34
+
35
+ alias path_len path_length
36
+ alias pathlen path_length
37
+
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,108 @@
1
+ require 'sslyze/x509/extension'
2
+
3
+ require 'uri'
4
+
5
+ module SSLyze
6
+ module X509
7
+ module Extensions
8
+ #
9
+ # Represents the `certificatePolicies` X509v3 extension.
10
+ #
11
+ # @since 1.0.0
12
+ #
13
+ class CertificatePolicies < Extension
14
+
15
+ #
16
+ # Represents an individual certificate policy.
17
+ #
18
+ class Policy
19
+
20
+ # @return [String]
21
+ attr_reader :policy
22
+
23
+ # @return [URI::Generic, nil]
24
+ attr_reader :cps
25
+
26
+ # @return [String, nil]
27
+ attr_reader :user_notice
28
+
29
+ #
30
+ # Initializes the policy.
31
+ #
32
+ # @param [String] policy
33
+ # The policy text.
34
+ #
35
+ # @param [Hash{Symbol => Object}] qualifiers
36
+ #
37
+ # @option qualifiers [URI::Generic, nil] :cps
38
+ # The CPS URI.
39
+ #
40
+ # @option qualifiers [String, nil] :user_notice
41
+ # The user notice.
42
+ #
43
+ def initialize(policy,qualifiers={})
44
+ @policy = policy
45
+
46
+ @cps = qualifiers[:cps]
47
+ @user_notice = qualifiers[:user_notice]
48
+ end
49
+
50
+ alias to_uri cps
51
+ alias to_s policy
52
+
53
+ end
54
+
55
+ include Enumerable
56
+
57
+ #
58
+ # Parses the individual policies listed in the extension's value.
59
+ #
60
+ # @return [Array<Policy>]
61
+ #
62
+ def policies
63
+ # XXX: ugly multiline regexp to parse the certificate policies and
64
+ # their qualifiers.
65
+ @policies ||= value.scan(/^Policy: [^\n]+\n(?: [^:]+: [^\n]+\n)*/m).map do |text|
66
+ policy = text.match(/^Policy: ([^\n]+)/)[1]
67
+
68
+ cps = if (match = text.match(/^ CPS: ([^\n]+)/m))
69
+ URI.parse(match[1])
70
+ end
71
+
72
+ user_notice = if (match = text.match(/^ User Notice: ([^\n]+)/m))
73
+ match[1]
74
+ end
75
+
76
+ Policy.new(policy, cps: cps, user_notice: user_notice)
77
+ end
78
+ end
79
+
80
+ #
81
+ # The number of certificate policies.
82
+ #
83
+ # @return [Integer]
84
+ #
85
+ def length
86
+ policies.length
87
+ end
88
+
89
+ #
90
+ # Enumerates over every certificate policy in the extension.
91
+ #
92
+ # @yield [policy]
93
+ # The given block will be passed each parsed policy.
94
+ #
95
+ # @yieldparam [Policy] policy
96
+ # A parsed certificate policy.
97
+ #
98
+ # @return [Enumerator]
99
+ # If no block is given, an Enumerator will be returned.
100
+ #
101
+ def each(&block)
102
+ policies.each(&block)
103
+ end
104
+
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,47 @@
1
+ require 'sslyze/x509/extension'
2
+
3
+ require 'uri'
4
+
5
+ module SSLyze
6
+ module X509
7
+ module Extensions
8
+ #
9
+ # Represents the `crlDistributionPoints` X509v3 extension.
10
+ #
11
+ # @since 1.0.0
12
+ #
13
+ class CRLDistributionPoints < Extension
14
+
15
+ include Enumerable
16
+
17
+ #
18
+ # All `URI:` values.
19
+ #
20
+ # @return [Array<URI::Generic>]
21
+ # All parsed `URI:` values from within the extension value.
22
+ #
23
+ def uris
24
+ @uris ||= value.scan(/URI:(.+)/).map { |(uri)| URI.parse(uri) }
25
+ end
26
+
27
+ #
28
+ # Enumerates over each {#uris uri} value within the
29
+ # `crlDistributionPoiints` extension.
30
+ #
31
+ # @yield [uri]
32
+ # The given block will be passed each CRL URI.
33
+ #
34
+ # @yieldparam [URI::Generic] uri
35
+ # A parsed `URI:` value from within the extension value.
36
+ #
37
+ # @return [Enumerator]
38
+ # If no block is given, an Enumerator will be returned.
39
+ #
40
+ def each(&block)
41
+ uris.each(&block)
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,58 @@
1
+ require 'sslyze/x509/extension'
2
+
3
+ module SSLyze
4
+ module X509
5
+ module Extensions
6
+ #
7
+ # Represents the `extendedKeyUsage` X509v3 extension.
8
+ #
9
+ # @since 1.0.0
10
+ #
11
+ class ExtendedKeyUsage < Extension
12
+
13
+ include Enumerable
14
+
15
+ #
16
+ # The allowed extended key uses.
17
+ #
18
+ # @return [Array<String>]
19
+ #
20
+ def uses
21
+ @uses ||= value.split(', ')
22
+ end
23
+
24
+ #
25
+ # Enumerates over the allowed extended key uses.
26
+ #
27
+ # @yield [use]
28
+ #
29
+ # @yieldparam [String] use
30
+ #
31
+ # @return [Enumerator]
32
+ #
33
+ def each(&block)
34
+ uses.each(&block)
35
+ end
36
+
37
+ #
38
+ # Determines if TLS Web Server Authentication is allowed.
39
+ #
40
+ # @return [Boolean]
41
+ #
42
+ def tls_web_server_authentication?
43
+ uses.include?('TLS Web Server Authentication')
44
+ end
45
+
46
+ #
47
+ # Determines if TLS Web Client Authentication is allowed.
48
+ #
49
+ # @return [Boolean]
50
+ #
51
+ def tls_web_client_authentication?
52
+ uses.include?('TLS Web Client Authentication')
53
+ end
54
+
55
+ end
56
+ end
57
+ end
58
+ end