ruby-sslyze 0.2.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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