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
@@ -0,0 +1,33 @@
1
+ require 'sslyze/xml/attributes/error'
2
+
3
+ module SSLyze
4
+ class XML
5
+ #
6
+ # Represents the `<invalidTarget>` XML element.
7
+ #
8
+ class InvalidTarget
9
+
10
+ include Attributes::Error
11
+
12
+ #
13
+ # Initializes the invalid target.
14
+ #
15
+ # @param [Nokogiri::XML::Node] node
16
+ # The `<invalid>` XML element.
17
+ #
18
+ def initialize(node)
19
+ @node = node
20
+ end
21
+
22
+ #
23
+ # The host name of the target.
24
+ #
25
+ # @return [String]
26
+ #
27
+ def host
28
+ @host ||= @node.inner_text
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,34 @@
1
+ require 'sslyze/xml/plugin'
2
+
3
+ module SSLyze
4
+ class XML
5
+ #
6
+ # Represents the `<openssl_ccs>` XML element.
7
+ #
8
+ # @since 1.0.0
9
+ #
10
+ class OpenSSLCCS < Plugin
11
+
12
+ #
13
+ # @return [OpenSSLCCSInjection]
14
+ #
15
+ def openssl_ccs_injection
16
+ @openssl_ccs_injection ||= OpenSSLCCSInjection.new(
17
+ @node.at_xpath('openSslCcsInjection')
18
+ )
19
+ end
20
+
21
+ alias injection openssl_ccs_injection
22
+
23
+ #
24
+ # @return [Boolean]
25
+ #
26
+ def is_vulnerable?
27
+ openssl_ccs_injection.is_vulnerable?
28
+ end
29
+
30
+ alias vulnerable? is_vulnerable?
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,26 @@
1
+ require 'sslyze/xml/plugin'
2
+ require 'sslyze/xml/attributes/is_vulnerable'
3
+
4
+ module SSLyze
5
+ class XML
6
+ class OpenSSLCCS < Plugin
7
+ #
8
+ # Represents the `<openSslCcsInjection />` XML element.
9
+ #
10
+ # @since 1.0.0
11
+ #
12
+ class OpenSSLCCSInjection
13
+
14
+ include Attributes::IsVulnerable
15
+
16
+ #
17
+ # Initializes the {OpenSSLCCSInjection} object.
18
+ #
19
+ def initialize(node)
20
+ @node = node
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,27 @@
1
+ require 'sslyze/xml/attributes/title'
2
+ require 'sslyze/xml/attributes/exception'
3
+
4
+ module SSLyze
5
+ class XML
6
+ #
7
+ # Common base class for all plugin XML elements.
8
+ #
9
+ # @since 1.0.0
10
+ #
11
+ class Plugin
12
+
13
+ include Attributes::Title
14
+ include Attributes::Exception
15
+
16
+ #
17
+ # Initializes the plugin.
18
+ #
19
+ # @param [Nokogiri::XML::Element] node
20
+ #
21
+ def initialize(node)
22
+ @node = node
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,143 @@
1
+ require 'sslyze/xml/plugin'
2
+ require 'sslyze/xml/types'
3
+ require 'sslyze/xml/protocol/cipher_suite'
4
+
5
+ module SSLyze
6
+ class XML
7
+ #
8
+ # Represents the `<sslv2>`, `<sslv3>`, `<tls1>`, `<tls1_1>`, `<tlsv1_2>`
9
+ # XML elements.
10
+ #
11
+ class Protocol < Plugin
12
+
13
+ include Types
14
+
15
+ # SSL protocol name.
16
+ #
17
+ # @return [Symbol]
18
+ attr_reader :name
19
+
20
+ #
21
+ # Initializes the protocol.
22
+ #
23
+ # @param [Nokogiri::XML::Node] node
24
+ # The XML element.
25
+ #
26
+ def initialize(node)
27
+ @node = node
28
+ @name = @node.name.to_sym
29
+ end
30
+
31
+ #
32
+ # Determines whether the protocol is supported.
33
+ #
34
+ # @return [Boolean]
35
+ # Specifies whether any cipher suite was accepted.
36
+ #
37
+ # @since 1.0.0
38
+ #
39
+ def is_protocol_supported?
40
+ Boolean[@node['isProtocolSupported']]
41
+ end
42
+
43
+ alias is_supported? is_protocol_supported?
44
+ alias supported? is_protocol_supported?
45
+
46
+ #
47
+ # Enumerates over every rejected cipher suite.
48
+ #
49
+ # @yield [cipher_suite]
50
+ #
51
+ # @yieldparam [CipherSuite] cipher_suite
52
+ #
53
+ # @return [Enumerator]
54
+ #
55
+ def each_rejected_cipher_suite
56
+ return enum_for(__method__) unless block_given?
57
+
58
+ @node.xpath('rejectedCipherSuites/cipherSuite').each do |cipher_suite|
59
+ yield CipherSuite.new(cipher_suite)
60
+ end
61
+ end
62
+
63
+ #
64
+ # The rejected cipher suites.
65
+ #
66
+ # @return [Array<CipherSuite>]
67
+ #
68
+ def rejected_cipher_suites
69
+ each_rejected_cipher_suite.to_a
70
+ end
71
+
72
+ #
73
+ # Enumerates over every accepted cipher suite.
74
+ #
75
+ # @yield [cipher_suite]
76
+ #
77
+ # @yieldparam [CipherSuite] cipher_suite
78
+ #
79
+ # @return [Enumerator]
80
+ #
81
+ def each_accepted_cipher_suite
82
+ return enum_for(__method__) unless block_given?
83
+
84
+ @node.xpath('acceptedCipherSuites/cipherSuite').each do |cipher_suite|
85
+ yield CipherSuite.new(cipher_suite)
86
+ end
87
+ end
88
+
89
+ #
90
+ # The accepted cipher suites.
91
+ #
92
+ # @return [Array<CipherSuite>]
93
+ #
94
+ def accepted_cipher_suites
95
+ each_accepted_cipher_suite.to_a
96
+ end
97
+
98
+ #
99
+ # The preferred cipher suite.
100
+ #
101
+ # @return [CipherSuite, nil]
102
+ #
103
+ # @since 1.0.0
104
+ #
105
+ def preferred_cipher_suite
106
+ @preferred_cipher_suite ||= if (element = @node.at_xpath('preferredCipherSuite/cipherSuite'))
107
+ CipherSuite.new(element)
108
+ end
109
+ end
110
+
111
+ #
112
+ # Enumerates over every errored cipher suite.
113
+ #
114
+ # @yield [cipher_suite]
115
+ #
116
+ # @yieldparam [CipherSuite] cipher_suite
117
+ #
118
+ # @return [Enumerator]
119
+ #
120
+ # @since 1.0.0
121
+ #
122
+ def each_error
123
+ return enum_for(__method__) unless block_given?
124
+
125
+ @node.xpath('errors/cipherSuite').each do |cipher_suite|
126
+ yield CipherSuite.new(cipher_suite)
127
+ end
128
+ end
129
+
130
+ #
131
+ # The errored cipher suites.
132
+ #
133
+ # @return [Array<CipherSuite>]
134
+ #
135
+ # @since 1.0.0
136
+ #
137
+ def errors
138
+ each_error.to_a
139
+ end
140
+
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,93 @@
1
+ require 'sslyze/xml/plugin'
2
+ require 'sslyze/xml/types'
3
+ require 'sslyze/xml/protocol/cipher_suite/key_exchange'
4
+ require 'sslyze/cipher_suites'
5
+
6
+ module SSLyze
7
+ class XML
8
+ class Protocol < Plugin
9
+ #
10
+ # Represents the `<cipherSuite>` XML element.
11
+ #
12
+ class CipherSuite
13
+
14
+ include Types
15
+
16
+ #
17
+ # Initializes the cipher suite.
18
+ #
19
+ # @param [Nokogiri::XML::Node] node
20
+ # The `<cipherSuite>` XML element.
21
+ #
22
+ def initialize(node)
23
+ @node = node
24
+ end
25
+
26
+ #
27
+ # The cipher suite name.
28
+ #
29
+ # @return [String]
30
+ #
31
+ def name
32
+ @name ||= @node['name']
33
+ end
34
+
35
+ alias rfc_name name
36
+
37
+ #
38
+ # Maps the RFC cipher name to it's OpenSSL name.
39
+ #
40
+ # @return [String, nil]
41
+ #
42
+ # @since 1.0.0
43
+ #
44
+ def openssl_name
45
+ CipherSuites::OPENSSL_NAMES[rfc_name]
46
+ end
47
+
48
+ #
49
+ # The connection status when the cipher suite was used.
50
+ #
51
+ # @return [String]
52
+ #
53
+ def connection_status
54
+ @connection_status ||= @node['connectionStatus']
55
+ end
56
+
57
+ #
58
+ # @return [Boolean]
59
+ #
60
+ def anonymous?
61
+ Boolean[@node['anonymous']]
62
+ end
63
+
64
+ #
65
+ # The key size required by the cipher suite.
66
+ #
67
+ # @return [Integer, nil]
68
+ #
69
+ # @since 1.0.0
70
+ #
71
+ def key_size
72
+ @key_size ||= if (value = @node['keySize'])
73
+ value.to_i
74
+ end
75
+ end
76
+
77
+ #
78
+ # Key exchange information.
79
+ #
80
+ # @return [KeyExchange, nil]
81
+ #
82
+ def key_exchange
83
+ @key_exchange ||= if (element = @node.at_xpath('keyExchange'))
84
+ KeyExchange.new(element)
85
+ end
86
+ end
87
+
88
+ alias to_s name
89
+
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,127 @@
1
+ require 'sslyze/xml/plugin'
2
+
3
+ module SSLyze
4
+ class XML
5
+ class Protocol < Plugin
6
+ class CipherSuite
7
+ #
8
+ # Key exchange information.
9
+ #
10
+ class KeyExchange
11
+
12
+ #
13
+ # Initializes the key exchange information.
14
+ #
15
+ # @param [Nokogiri::XML::Node] node
16
+ # The `<keyExchange>` information.
17
+ #
18
+ def initialize(node)
19
+ @node = node
20
+ end
21
+
22
+ #
23
+ # @return [String, nil]
24
+ #
25
+ def a
26
+ @a ||= @node['A']
27
+ end
28
+
29
+ #
30
+ # @return [String, nil]
31
+ #
32
+ def b
33
+ @b ||= @node['B']
34
+ end
35
+
36
+ #
37
+ # @return [Integer, nil]
38
+ #
39
+ def cofactor
40
+ @cofactor ||= if (value = @node['Cofactor'])
41
+ value.to_i
42
+ end
43
+ end
44
+
45
+ #
46
+ # @return [String, nil]
47
+ #
48
+ def field_type
49
+ @field_type ||= @node['Field_Type']
50
+ end
51
+
52
+ #
53
+ # @return [String]
54
+ #
55
+ def generator
56
+ @generator ||= @node['Generator']
57
+ end
58
+
59
+ #
60
+ # @return [Symbol, nil]
61
+ #
62
+ def generator_type
63
+ @generator_type ||= if (value = @node['GeneratorType'])
64
+ value.to_sym
65
+ end
66
+ end
67
+
68
+ #
69
+ # @return [Integer]
70
+ #
71
+ def group_size
72
+ @group_size ||= @node['GroupSize'].to_i
73
+ end
74
+
75
+ #
76
+ # @return [String, nil]
77
+ #
78
+ # @since 1.0.0
79
+ #
80
+ def order
81
+ @order ||= @node['Order']
82
+ end
83
+
84
+ #
85
+ # @return [String, nil]
86
+ #
87
+ def prime
88
+ @prime ||= @node['Prime']
89
+ end
90
+
91
+ #
92
+ # @return [String, nil]
93
+ #
94
+ def seed
95
+ @seed ||= @node['Seed']
96
+ end
97
+
98
+ #
99
+ # @return [Symbol]
100
+ #
101
+ def type
102
+ @type ||= @node['Type'].to_sym
103
+ end
104
+
105
+ #
106
+ # Determines if DH key exchange was used.
107
+ #
108
+ # @return [Boolean]
109
+ #
110
+ def dh?
111
+ type == :DH
112
+ end
113
+
114
+ #
115
+ # Determines if ECDHE key exchange was used.
116
+ #
117
+ # @return [Boolean]
118
+ #
119
+ def ecdhe?
120
+ type == :ECDHE
121
+ end
122
+
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end