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
@@ -0,0 +1,66 @@
1
+ require 'sslyze/x509/extension'
2
+
3
+ module SSLyze
4
+ module X509
5
+ module Extensions
6
+ #
7
+ # Represents the `keyUsage` X509v3 extension.
8
+ #
9
+ # @since 1.0.0
10
+ #
11
+ class KeyUsage < Extension
12
+
13
+ include Enumerable
14
+
15
+ #
16
+ # The various permitted key uses.
17
+ #
18
+ # @return [Array<String>]
19
+ #
20
+ def uses
21
+ @uses ||= value.split(', ')
22
+ end
23
+
24
+ #
25
+ # @yield [use]
26
+ #
27
+ # @yieldparam [String] use
28
+ #
29
+ # @return [Enumerator]
30
+ #
31
+ def each(&block)
32
+ uses.each(&block)
33
+ end
34
+
35
+ #
36
+ # @return [Boolean]
37
+ #
38
+ def key_encipherment?
39
+ uses.include?('Key Encipherment')
40
+ end
41
+
42
+ #
43
+ # @return [Boolean]
44
+ #
45
+ def digital_signature?
46
+ uses.include?('Digital Signature')
47
+ end
48
+
49
+ #
50
+ # @return [Boolean]
51
+ #
52
+ def crl_sign?
53
+ uses.include?('CRL Sign')
54
+ end
55
+
56
+ #
57
+ # @return [Boolean]
58
+ #
59
+ def certificate_sign?
60
+ uses.include?('Certificate Sign')
61
+ end
62
+
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,144 @@
1
+ require 'sslyze/x509/extension'
2
+ require 'sslyze/x509/domain'
3
+
4
+ require 'uri'
5
+ require 'ipaddr'
6
+
7
+ module SSLyze
8
+ module X509
9
+ module Extensions
10
+ #
11
+ # Represents the `subjectAltName` X509v3 extension.
12
+ #
13
+ # @since 1.0.0
14
+ #
15
+ class SubjectAltName < Extension
16
+
17
+ include Enumerable
18
+
19
+ # Known subject name types.
20
+ TYPES = {
21
+ 'DNS' => :dns,
22
+ 'IP' => :ip,
23
+ 'URI' => :uri,
24
+ 'RID' => :rid,
25
+
26
+ 'email' => :email,
27
+ 'dirName' => :dir_name,
28
+ 'otherName' => :other_name
29
+ }
30
+
31
+ #
32
+ # Enumerates over every alternative name within the extension's value.
33
+ #
34
+ # @yield [type, name]
35
+ # The given block will be passed each
36
+ #
37
+ # @yieldparam [:dns, :ip, :uri, :rid, :email, :dir_name, :other_name] type
38
+ # The type of the alternative name being yielded.
39
+ #
40
+ # @yieldparam [String] name
41
+ # An alternative name within the extension's value.
42
+ #
43
+ # @return [Enumerator]
44
+ # If no block is given, an Enumerator will be returned.
45
+ #
46
+ # @raise [NotImplementedError]
47
+ # An unknown name type was encountered while parsing the extension's
48
+ # value.
49
+ #
50
+ def each
51
+ return enum_for unless block_given?
52
+
53
+ value.split(', ').each do |type_value|
54
+ type, value = type_value.split(':',2)
55
+
56
+ unless TYPES.has_key?(type)
57
+ raise(NotImplementedError,"unsupported subjectAltName type: #{type}")
58
+ end
59
+
60
+ yield TYPES[type], value
61
+ end
62
+ end
63
+
64
+ #
65
+ # All `DNS:` alternative names within the extension's value.
66
+ #
67
+ # @return [Array<String>]
68
+ #
69
+ def dns
70
+ @dns ||= select { |type,value| type == :dns }.map do |(type,value)|
71
+ value
72
+ end
73
+ end
74
+
75
+ #
76
+ # All `IP:` alternative names within the extension's value.
77
+ #
78
+ # @return [Array<IPAddr>]
79
+ #
80
+ def ip
81
+ @ip ||= select { |type,value| type == :ip }.map do |(type,value)|
82
+ IPAddr.new(value)
83
+ end
84
+ end
85
+
86
+ #
87
+ # All `URI:` alternative names within the extension's value.
88
+ #
89
+ # @return [Array<URI::Generic>]
90
+ #
91
+ def uri
92
+ @uri ||= select { |type,value| type == :uri }.map do |(type,value)|
93
+ URI.parse(value)
94
+ end
95
+ end
96
+
97
+ #
98
+ # All `email:` alternative names within the extension's value.
99
+ #
100
+ # @return [Array<String>]
101
+ #
102
+ def email
103
+ @email ||= select { |type,value| type == :email }.map do |(type,value)|
104
+ value
105
+ end
106
+ end
107
+
108
+ #
109
+ # All `RID:` alternative names within the extension's value.
110
+ #
111
+ # @return [Array<String>]
112
+ #
113
+ def rid
114
+ @rid ||= select { |type,value| type == :rid }.map do |(type,value)|
115
+ value
116
+ end
117
+ end
118
+
119
+ #
120
+ # All `dirName:` alternative names within the extension's value.
121
+ #
122
+ # @return [Array<String>]
123
+ #
124
+ def dir_name
125
+ @dir_name ||= select { |type,value| type == :dir_name }.map do |(type,value)|
126
+ value
127
+ end
128
+ end
129
+
130
+ #
131
+ # All `otherName:` alternative names within the extension's value.
132
+ #
133
+ # @return [Array<String>]
134
+ #
135
+ def other_name
136
+ @other_name ||= select { |type,value| type == :other_name }.map do |(type,value)|
137
+ value
138
+ end
139
+ end
140
+
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,194 @@
1
+ require 'sslyze/x509/domain'
2
+
3
+ require 'openssl'
4
+
5
+ module SSLyze
6
+ module X509
7
+ #
8
+ # Wrapper object for [OpenSSL::X509::Name][1].
9
+ #
10
+ # [1]: http://www.rubydoc.info/stdlib/openssl/OpenSSL/X509/Name
11
+ #
12
+ # @since 1.0.0
13
+ #
14
+ class Name
15
+
16
+ include Enumerable
17
+
18
+ #
19
+ # The parsed entries of the name.
20
+ #
21
+ # @return [Array<(String, String, Integer)>]
22
+ #
23
+ attr_reader :entries
24
+
25
+ #
26
+ # @param [OpenSSL::X509::Name] name
27
+ # The OpenSSL X509 name object.
28
+ #
29
+ def initialize(name)
30
+ @name = name
31
+ @entries = name.to_a
32
+ end
33
+
34
+ #
35
+ # Enumerates over the entries.
36
+ #
37
+ # @yield [oid, value, type]
38
+ #
39
+ # @yieldparam [String] oid
40
+ # The Object IDentifier.
41
+ #
42
+ # @yieldparam [String] value
43
+ # The entry's value.
44
+ #
45
+ # @yieldparam [Integer] type
46
+ # The entry type.
47
+ #
48
+ def each(&block)
49
+ @entries.each do |(oid,value,type)|
50
+ yield oid, value, type
51
+ end
52
+ end
53
+
54
+ #
55
+ # Finds the entry with the matcing OID (Object IDentifier).
56
+ #
57
+ # @param [String] key
58
+ #
59
+ # @return [String, nil]
60
+ #
61
+ def [](key)
62
+ each do |oid,value,type|
63
+ return value if oid == key
64
+ end
65
+
66
+ return nil
67
+ end
68
+
69
+ #
70
+ # The Country (`C`) entry.
71
+ #
72
+ # @return [String]
73
+ #
74
+ def country_name
75
+ @country_name ||= self['C']
76
+ end
77
+
78
+ alias country country_name
79
+ alias c country_name
80
+
81
+ #
82
+ # The Common Name (`CN`) entry.
83
+ #
84
+ # @return [Domain]
85
+ #
86
+ def common_name
87
+ @common_name ||= Domain.new(self['CN'])
88
+ end
89
+
90
+ alias cn common_name
91
+
92
+ #
93
+ # The Domain Component (`DC`) entry.
94
+ #
95
+ # @return [String, nil]
96
+ #
97
+ def domain_component
98
+ @domain_component ||= self['DC']
99
+ end
100
+
101
+ alias dc domain_component
102
+
103
+ #
104
+ # The Organization Name (`O`) entry.
105
+ #
106
+ # @return [String]
107
+ #
108
+ def organization_name
109
+ @organization_name ||= self['O']
110
+ end
111
+
112
+ alias organization organization_name
113
+ alias o organization_name
114
+
115
+ #
116
+ # The Organization Unit Name (`OU`) entry.
117
+ #
118
+ # @return [String]
119
+ #
120
+ def organizational_unit_name
121
+ @organizational_unit_name ||= self['OU']
122
+ end
123
+
124
+ alias organizational_unit organizational_unit_name
125
+ alias ou organizational_unit_name
126
+
127
+ #
128
+ # The State/Province Name (`ST`) entry.
129
+ #
130
+ # @return [String, nil]
131
+ #
132
+ def state_name
133
+ @state_name ||= self['ST']
134
+ end
135
+
136
+ alias state state_name
137
+ alias province_name state_name
138
+ alias province province_name
139
+ alias st state_name
140
+
141
+ #
142
+ # The Location (`L`) entry.
143
+ #
144
+ # @return [String, nil]
145
+ #
146
+ def location_name
147
+ @location ||= self['L']
148
+ end
149
+
150
+ alias location location_name
151
+ alias l location_name
152
+
153
+ #
154
+ # @see http://www.rubydoc.info/stdlib/openssl/OpenSSL/X509/Name#cmp-instance_method
155
+ #
156
+ def cmp(other)
157
+ @name.cmp(other.name)
158
+ end
159
+
160
+ #
161
+ # @see http://www.rubydoc.info/stdlib/openssl/OpenSSL/X509/Name#eql%3F-instance_method
162
+ #
163
+ def eql?(other)
164
+ @name.eql?(other.name)
165
+ end
166
+
167
+ #
168
+ # @see http://www.rubydoc.info/stdlib/openssl/OpenSSL/X509/Name#to_a-instance_method
169
+ #
170
+ def to_a
171
+ @name.to_a
172
+ end
173
+
174
+ #
175
+ # @see http://www.rubydoc.info/stdlib/openssl/OpenSSL/X509/Name#to_der-instance_method
176
+ #
177
+ def to_der
178
+ @name.to_der
179
+ end
180
+
181
+ #
182
+ # @see http://www.rubydoc.info/stdlib/openssl/OpenSSL/X509/Name#to_s-instance_method
183
+ #
184
+ def to_s(*args)
185
+ @name.to_s(*args)
186
+ end
187
+
188
+ protected
189
+
190
+ attr_reader :name
191
+
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,53 @@
1
+ require 'delegate'
2
+
3
+ module SSLyze
4
+ module X509
5
+ #
6
+ # Wrapper class around [OpenSSL::PKey] classes that provide {#algorithm} and
7
+ # {#size} methods.
8
+ #
9
+ # [OpenSSL::PKey]: http://www.rubydoc.info/stdlib/openssl/OpenSSL/PKey
10
+ #
11
+ # @since 1.0.0
12
+ #
13
+ class PublicKey < SimpleDelegator
14
+
15
+ #
16
+ # The algorithm that generated the public key.
17
+ #
18
+ # @return [:rsa, :dsa, :dh, :ec]
19
+ #
20
+ def algorithm
21
+ case __getobj__
22
+ when OpenSSL::PKey::RSA then :rsa
23
+ when OpenSSL::PKey::DSA then :dsa
24
+ when OpenSSL::PKey::DH then :dh
25
+ when OpenSSL::PKey::EC then :ec
26
+ end
27
+ end
28
+
29
+ #
30
+ # The size of the public key.
31
+ #
32
+ # @return [Integer]
33
+ # The number of bits in the public key.
34
+ #
35
+ # @raise [NotImplementedError]
36
+ # Determining key size for `OpenSSL::PKey::EC` public keys is currently
37
+ # not implemented.
38
+ #
39
+ def size
40
+ pkey = __getobj__
41
+
42
+ case pkey
43
+ when OpenSSL::PKey::RSA then pkey.n.num_bits
44
+ when OpenSSL::PKey::DSA then pkey.p.num_bits
45
+ when OpenSSL::PKey::DH then pkey.p.num_bits
46
+ when OpenSSL::PKey::EC
47
+ raise(NotImplementedError,"key size for #{pkey.inspect} not implemented")
48
+ end
49
+ end
50
+
51
+ end
52
+ end
53
+ end