ruby-sslyze 0.1.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.
- 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,106 @@
|
|
1
|
+
module SSLyze
|
2
|
+
#
|
3
|
+
# Key exchange information.
|
4
|
+
#
|
5
|
+
class KeyExchange
|
6
|
+
|
7
|
+
#
|
8
|
+
# Initializes the key exchange information.
|
9
|
+
#
|
10
|
+
# @param [Nokogiri::XML::Node] node
|
11
|
+
# The `<keyExchange>` information.
|
12
|
+
#
|
13
|
+
def initialize(node)
|
14
|
+
@node = node
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
# @return [String]
|
19
|
+
#
|
20
|
+
def a
|
21
|
+
@a ||= @node['A']
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# @return [String]
|
26
|
+
#
|
27
|
+
def b
|
28
|
+
@b ||= @node['B']
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# @return [Integer]
|
33
|
+
#
|
34
|
+
def cofactor
|
35
|
+
@cofactor ||= @node['Cofactor'].to_i
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# @return [String]
|
40
|
+
#
|
41
|
+
def field_type
|
42
|
+
@field_type ||= @node['Field_Type']
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
# @return [String]
|
47
|
+
#
|
48
|
+
def generator
|
49
|
+
@generator ||= @node['Generator']
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# @return [Symbol]
|
54
|
+
#
|
55
|
+
def generator_type
|
56
|
+
@generator ||= @node['GeneratorType'].to_sym
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# @return [Integer]
|
61
|
+
#
|
62
|
+
def group_size
|
63
|
+
@group_size ||= @node['GroupSize'].to_i
|
64
|
+
end
|
65
|
+
|
66
|
+
#
|
67
|
+
# @return [String]
|
68
|
+
#
|
69
|
+
def prime
|
70
|
+
@prime ||= @node['Prime']
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# @return [String]
|
75
|
+
#
|
76
|
+
def seed
|
77
|
+
@seed ||= @node['Seed']
|
78
|
+
end
|
79
|
+
|
80
|
+
#
|
81
|
+
# @return [:DH, :ECDHE]
|
82
|
+
#
|
83
|
+
def type
|
84
|
+
@type ||= @node['Type'].to_sym
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# Determines if DH key exchange was used.
|
89
|
+
#
|
90
|
+
# @return [Boolean]
|
91
|
+
#
|
92
|
+
def dh?
|
93
|
+
type == :DH
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
# Determines if ECDHE key exchange was used.
|
98
|
+
#
|
99
|
+
# @return [Boolean]
|
100
|
+
#
|
101
|
+
def ecdhe?
|
102
|
+
type == :ECDHE
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'sslyze/types'
|
2
|
+
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
module SSLyze
|
6
|
+
#
|
7
|
+
# Represents the `<ocspResponse>` XML element.
|
8
|
+
#
|
9
|
+
class OCSPResponse
|
10
|
+
|
11
|
+
include Types
|
12
|
+
|
13
|
+
#
|
14
|
+
# Initializes the OCSP response.
|
15
|
+
#
|
16
|
+
# @param [Nokogiri::XML::Node] node
|
17
|
+
# The `<ocspResponse>` XML element.
|
18
|
+
#
|
19
|
+
def initialize(node)
|
20
|
+
@node = node
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# Specifies whether the response was trusted.
|
25
|
+
#
|
26
|
+
# @return [Boolean]
|
27
|
+
#
|
28
|
+
def trusted?
|
29
|
+
Boolean[@node['isTrustedByMozillaCAStore']]
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# The response type.
|
34
|
+
#
|
35
|
+
# @return [String]
|
36
|
+
#
|
37
|
+
def type
|
38
|
+
@type ||= @node.at('responseType').inner_text
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# The responder ID.
|
43
|
+
#
|
44
|
+
# @return [String]
|
45
|
+
#
|
46
|
+
def responder_id
|
47
|
+
@id ||= @node.at('responderID').inner_text
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# The OCSP version.
|
52
|
+
#
|
53
|
+
# @return [Integer]
|
54
|
+
#
|
55
|
+
def version
|
56
|
+
@version ||= @node.at('version').inner_text.to_i
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# The response status.
|
61
|
+
#
|
62
|
+
# @return [Symbol]
|
63
|
+
#
|
64
|
+
def status
|
65
|
+
@status ||= @node.at('responseStatus').inner_text.to_sym
|
66
|
+
end
|
67
|
+
|
68
|
+
#
|
69
|
+
# Determines whether the OCSP response was a success.
|
70
|
+
#
|
71
|
+
# @return [Boolean]
|
72
|
+
#
|
73
|
+
def successful?
|
74
|
+
status == :successful
|
75
|
+
end
|
76
|
+
|
77
|
+
#
|
78
|
+
# When the response was produced.
|
79
|
+
#
|
80
|
+
# @return [Time]
|
81
|
+
#
|
82
|
+
def produced_at
|
83
|
+
@produced_at ||= Time.parse(@node.at('producedAt').inner_text)
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'sslyze/task'
|
2
|
+
|
3
|
+
require 'rprogram/program'
|
4
|
+
|
5
|
+
module SSLyze
|
6
|
+
#
|
7
|
+
# Represents the `sslyze.py` command line utility.
|
8
|
+
#
|
9
|
+
class Program < RProgram::Program
|
10
|
+
|
11
|
+
name_program 'sslyze.py'
|
12
|
+
|
13
|
+
#
|
14
|
+
# Finds the `sslyze.py` script and runs it.
|
15
|
+
#
|
16
|
+
# @param [Hash{Symbol => Object}] options
|
17
|
+
# Additional options for `sslyze.py`.
|
18
|
+
#
|
19
|
+
# @param [Hash{Symbol => Object}] exec_options
|
20
|
+
# Additional exec-options.
|
21
|
+
#
|
22
|
+
# @yield [task]
|
23
|
+
# If a block is given, it will be passed a task object
|
24
|
+
# used to specify options for `sslyze.py`.
|
25
|
+
#
|
26
|
+
# @yieldparam [Task] task
|
27
|
+
# The sslyze task object.
|
28
|
+
#
|
29
|
+
# @return [Boolean]
|
30
|
+
# Specifies whether the command exited normally.
|
31
|
+
#
|
32
|
+
# @see http://rubydoc.info/gems/rprogram/0.3.0/RProgram/Program#run-instance_method
|
33
|
+
# For additional exec-options.
|
34
|
+
#
|
35
|
+
def self.analyze(options={},exec_options={},&block)
|
36
|
+
find.analyze(options,exec_options,&block)
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# Runs `sslyze.py`.
|
41
|
+
#
|
42
|
+
# @param [Hash{Symbol => Object}] options
|
43
|
+
# Additional options for `sslyze.py`.
|
44
|
+
#
|
45
|
+
# @param [Hash{Symbol => Object}] exec_options
|
46
|
+
# Additional exec-options.
|
47
|
+
#
|
48
|
+
# @yield [task]
|
49
|
+
# If a block is given, it will be passed a task object
|
50
|
+
# used to specify options for `sslyze.py`.
|
51
|
+
#
|
52
|
+
# @yieldparam [Task] task
|
53
|
+
# The sslyze task object.
|
54
|
+
#
|
55
|
+
# @return [Boolean]
|
56
|
+
# Specifies whether the command exited normally.
|
57
|
+
#
|
58
|
+
# @see http://rubydoc.info/gems/rprogram/0.3.0/RProgram/Program#run-instance_method
|
59
|
+
# For additional exec-options.
|
60
|
+
#
|
61
|
+
def analyze(options={},exec_options={},&block)
|
62
|
+
run_task(Task.new(options,&block),exec_options)
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'sslyze/cipher_suite'
|
2
|
+
|
3
|
+
module SSLyze
|
4
|
+
#
|
5
|
+
# Represents the `<sslv2>`, `<sslv3>`, `<tls1>`, `<tls1_1>`, `<tlsv1_2>`
|
6
|
+
# XML elements.
|
7
|
+
#
|
8
|
+
class Protocol
|
9
|
+
|
10
|
+
# SSL protocol name.
|
11
|
+
#
|
12
|
+
# @return [Symbol]
|
13
|
+
attr_reader :name
|
14
|
+
|
15
|
+
#
|
16
|
+
# Initializes the protocol.
|
17
|
+
#
|
18
|
+
# @param [Nokogiri::XML::Node] node
|
19
|
+
# The XML element.
|
20
|
+
#
|
21
|
+
def initialize(node)
|
22
|
+
@node = node
|
23
|
+
@name = @node.name.to_sym
|
24
|
+
end
|
25
|
+
|
26
|
+
#
|
27
|
+
# Descriptive title.
|
28
|
+
#
|
29
|
+
# @return [String]
|
30
|
+
#
|
31
|
+
def title
|
32
|
+
@title ||= @node['title']
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# @raise [NotImplemnetedError]
|
37
|
+
#
|
38
|
+
# @todo figure out what `<errors />` contains.
|
39
|
+
#
|
40
|
+
def each_error
|
41
|
+
raise(NotImplementedError,"#{__method__} not implemented")
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Enumerates over every rejected cipher suite.
|
46
|
+
#
|
47
|
+
# @yield [cipher_suite]
|
48
|
+
#
|
49
|
+
# @yieldparam [CipherSuite] cipher_suite
|
50
|
+
#
|
51
|
+
# @return [Enumerator]
|
52
|
+
#
|
53
|
+
def each_rejected_cipher_suite
|
54
|
+
return enum_for(__method__) unless block_given?
|
55
|
+
|
56
|
+
@node.search('rejectedCipherSuites/cipherSuite').each do |cipher_suite|
|
57
|
+
yield CipherSuite.new(cipher_suite)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# The rejected cipher suites.
|
63
|
+
#
|
64
|
+
# @return [Array<CipherSuite>]
|
65
|
+
#
|
66
|
+
def rejected_cipher_suites
|
67
|
+
each_rejected_cipher_suite.to_a
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# Enumerates over every accepted cipher suite.
|
72
|
+
#
|
73
|
+
# @yield [cipher_suite]
|
74
|
+
#
|
75
|
+
# @yieldparam [CipherSuite] cipher_suite
|
76
|
+
#
|
77
|
+
# @return [Enumerator]
|
78
|
+
#
|
79
|
+
def each_accepted_cipher_suite
|
80
|
+
return enum_for(__method__) unless block_given?
|
81
|
+
|
82
|
+
@node.search('acceptedCipherSuites/cipherSuite').each do |cipher_suite|
|
83
|
+
yield CipherSuite.new(cipher_suite)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# The accepted cipher suites.
|
89
|
+
#
|
90
|
+
# @return [Array<CipherSuite>]
|
91
|
+
#
|
92
|
+
def accepted_cipher_suites
|
93
|
+
each_accepted_cipher_suite.to_a
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
# Enumerates over every preferred cipher suite.
|
98
|
+
#
|
99
|
+
# @yield [cipher_suite]
|
100
|
+
#
|
101
|
+
# @yieldparam [CipherSuite] cipher_suite
|
102
|
+
#
|
103
|
+
# @return [Enumerator]
|
104
|
+
#
|
105
|
+
def each_preferred_cipher_suite
|
106
|
+
return enum_for(__method__) unless block_given?
|
107
|
+
|
108
|
+
@node.search('preferredCipherSuites/cipherSuite').each do |cipher_suite|
|
109
|
+
yield CipherSuite.new(cipher_suite)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
#
|
114
|
+
# The preferred cipher suites.
|
115
|
+
#
|
116
|
+
# @return [Array<CipherSuite>]
|
117
|
+
#
|
118
|
+
def preferred_cipher_suites
|
119
|
+
each_preferred_cipher_suite.to_a
|
120
|
+
end
|
121
|
+
|
122
|
+
#
|
123
|
+
# Determines whether the protocol is supported.
|
124
|
+
#
|
125
|
+
# @return [Boolean]
|
126
|
+
# Specifies whether any cipher suite was accepted.
|
127
|
+
#
|
128
|
+
def supported?
|
129
|
+
each_accepted_cipher_suite.any?
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,295 @@
|
|
1
|
+
require 'sslyze/types'
|
2
|
+
require 'sslyze/cert_info'
|
3
|
+
require 'sslyze/protocol'
|
4
|
+
|
5
|
+
module SSLyze
|
6
|
+
#
|
7
|
+
# Represents the `<target>` XML element.
|
8
|
+
#
|
9
|
+
class Target
|
10
|
+
|
11
|
+
include Types
|
12
|
+
|
13
|
+
#
|
14
|
+
# Initializes the target.
|
15
|
+
#
|
16
|
+
# @param [Nokogiri::XML::Node] node
|
17
|
+
# The `<target>` XML element.
|
18
|
+
#
|
19
|
+
def initialize(node)
|
20
|
+
@node = node
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# The host name of the target.
|
25
|
+
#
|
26
|
+
# @return [String]
|
27
|
+
#
|
28
|
+
def host
|
29
|
+
@host ||= @node['host']
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# The IP address of the target.
|
34
|
+
#
|
35
|
+
# @return [String]
|
36
|
+
#
|
37
|
+
def ip
|
38
|
+
@ip ||= @node['ip']
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# The port number that was scanned.
|
43
|
+
#
|
44
|
+
# @return [Integer]
|
45
|
+
#
|
46
|
+
def port
|
47
|
+
@port ||= @node['port'].to_i
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# Certificate information.
|
52
|
+
#
|
53
|
+
# @return [CertInfo, nil]
|
54
|
+
#
|
55
|
+
def cert_info
|
56
|
+
@cert_info ||= if (certinfo = @node.at('certinfo'))
|
57
|
+
CertInfo.new(certinfo)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Which compression algorithms are supported.
|
63
|
+
#
|
64
|
+
# @return [Hash{Symbol => Boolean}]
|
65
|
+
# The algorithm name and support status.
|
66
|
+
#
|
67
|
+
def compression
|
68
|
+
unless @compression
|
69
|
+
@compression = {}
|
70
|
+
|
71
|
+
@node.search('compression/compressionMethod').map do |compression|
|
72
|
+
type = compression['type'].downcase.to_sym
|
73
|
+
supported = Boolean[compression['isSupported']]
|
74
|
+
|
75
|
+
@compression[type] = supported
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
return @compression
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
# Specifies whether the service was vulnerable to Heartbleed.
|
84
|
+
#
|
85
|
+
# @return [Boolean, nil]
|
86
|
+
#
|
87
|
+
def heartbleed?
|
88
|
+
if (heartbleed = @node.at('heartbleed/openSslHeartbleed'))
|
89
|
+
Boolean[heartbleed['isVulnerable']]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
#
|
94
|
+
# Represents the `<sessionRenegotiation>` XML element.
|
95
|
+
#
|
96
|
+
class SessionRenegotiation < Struct.new(:client_initiated, :secure)
|
97
|
+
|
98
|
+
def client_initiated?
|
99
|
+
client_initiated == true
|
100
|
+
end
|
101
|
+
|
102
|
+
def secure?
|
103
|
+
secure == true
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
#
|
109
|
+
# Specifies whether the service supports Session Renegotiation.
|
110
|
+
#
|
111
|
+
# @return [SessionRenegotiation, nil]
|
112
|
+
#
|
113
|
+
def session_renegotiation
|
114
|
+
@session_renegotiation ||= (
|
115
|
+
if (sessionRenegotiation = @node.at('reneg/sessionRenegotiation'))
|
116
|
+
|
117
|
+
SessionRenegotiation.new(
|
118
|
+
Boolean[sessionRenegotiation['canBeClientInitiated']],
|
119
|
+
Boolean[sessionRenegotiation['isSecure']]
|
120
|
+
)
|
121
|
+
end
|
122
|
+
)
|
123
|
+
end
|
124
|
+
|
125
|
+
#
|
126
|
+
# SSLv2 protocol information.
|
127
|
+
#
|
128
|
+
# @return [Protocol, nil]
|
129
|
+
#
|
130
|
+
def sslv2
|
131
|
+
@sslv2 ||= if (node = @node.at('sslv2'))
|
132
|
+
Protocol.new(node)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
#
|
137
|
+
# SSLv3 protocol information.
|
138
|
+
#
|
139
|
+
# @return [Protocol, nil]
|
140
|
+
#
|
141
|
+
def sslv3
|
142
|
+
@sslv3 ||= if (node = @node.at('sslv3'))
|
143
|
+
Protocol.new(node)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
#
|
148
|
+
# TLSv1 protocol information.
|
149
|
+
#
|
150
|
+
# @return [Protocol, nil]
|
151
|
+
#
|
152
|
+
def tlsv1
|
153
|
+
@tlsv1 ||= if (node = @node.at('tlsv1'))
|
154
|
+
Protocol.new(node)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
#
|
159
|
+
# TLSv1.1 protocol information.
|
160
|
+
#
|
161
|
+
# @return [Protocol, nil]
|
162
|
+
#
|
163
|
+
def tlsv1_1
|
164
|
+
@tlsv1_1 ||= if (node = @node.at('tlsv1_1'))
|
165
|
+
Protocol.new(node)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
#
|
170
|
+
# TLSv1.2 protocol information.
|
171
|
+
#
|
172
|
+
# @return [Protocol, nil]
|
173
|
+
#
|
174
|
+
def tlsv1_2
|
175
|
+
@tlsv1_2 ||= if (node = @node.at('tlsv1_2'))
|
176
|
+
Protocol.new(node)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
#
|
181
|
+
# Iterates over every SSL protocol.
|
182
|
+
#
|
183
|
+
# @yield [protocol]
|
184
|
+
# The given block will be passed each SSL protocol.
|
185
|
+
#
|
186
|
+
# @yieldparam [Protocol] protocol
|
187
|
+
# A SSL protocol.
|
188
|
+
#
|
189
|
+
# @return [Enumerator]
|
190
|
+
# If a no block was given, an Enumerator will be returned.
|
191
|
+
#
|
192
|
+
# @see {#sslv2}, {#sslv3}
|
193
|
+
#
|
194
|
+
def each_ssl_protocol
|
195
|
+
return enum_for(__method__) unless block_given?
|
196
|
+
|
197
|
+
yield sslv2 if sslv2
|
198
|
+
yield sslv3 if sslv3
|
199
|
+
end
|
200
|
+
|
201
|
+
#
|
202
|
+
# All supported SSL protocols.
|
203
|
+
#
|
204
|
+
# @return [Array<Protocol>]
|
205
|
+
#
|
206
|
+
def ssl_protocols
|
207
|
+
each_ssl_protocol.to_a
|
208
|
+
end
|
209
|
+
|
210
|
+
#
|
211
|
+
# Iterates over every TLS protocol.
|
212
|
+
#
|
213
|
+
# @yield [protocol]
|
214
|
+
# The given block will be passed each TLS protocol.
|
215
|
+
#
|
216
|
+
# @yieldparam [Protocol] protocol
|
217
|
+
# A TLS protocol.
|
218
|
+
#
|
219
|
+
# @return [Enumerator]
|
220
|
+
# If a no block was given, an Enumerator will be returned.
|
221
|
+
#
|
222
|
+
# @see {#tlsv1}, {#tlsv1_1}, {#tlsv1_2}
|
223
|
+
#
|
224
|
+
def each_tls_protocol
|
225
|
+
return enum_for(__method__) unless block_given?
|
226
|
+
|
227
|
+
yield tlsv1 if tlsv1
|
228
|
+
yield tlsv1_1 if tlsv1_1
|
229
|
+
yield tlsv1_2 if tlsv1_2
|
230
|
+
end
|
231
|
+
|
232
|
+
#
|
233
|
+
# All supported TLS protocols.
|
234
|
+
#
|
235
|
+
# @return [Array<Protocol>]
|
236
|
+
#
|
237
|
+
def tls_protocols
|
238
|
+
each_tls_protocol.to_a
|
239
|
+
end
|
240
|
+
|
241
|
+
#
|
242
|
+
# Iterates over every SSL/TLS protocol.
|
243
|
+
#
|
244
|
+
# @yield [protocol]
|
245
|
+
# The given block will be passed each SSL/TLS protocol.
|
246
|
+
#
|
247
|
+
# @yieldparam [Protocol] protocol
|
248
|
+
# A SSL/TLS protocol.
|
249
|
+
#
|
250
|
+
# @return [Enumerator]
|
251
|
+
# If a no block was given, an Enumerator will be returned.
|
252
|
+
#
|
253
|
+
# @see {#sslv2}, {#sslv3}, {#tlsv1}, {#tlsv1_1}, {#tlsv1_2}
|
254
|
+
#
|
255
|
+
def each_protocol(&block)
|
256
|
+
return enum_for(__method__) unless block
|
257
|
+
|
258
|
+
each_ssl_protocol(&block)
|
259
|
+
each_tls_protocol(&block)
|
260
|
+
end
|
261
|
+
|
262
|
+
#
|
263
|
+
# All supported SSL/TLS protocols.
|
264
|
+
#
|
265
|
+
# @return [Array<Protocol>]
|
266
|
+
#
|
267
|
+
def protocols
|
268
|
+
each_protocol.to_a
|
269
|
+
end
|
270
|
+
|
271
|
+
#
|
272
|
+
# Convert the target to a String.
|
273
|
+
#
|
274
|
+
# @return [String]
|
275
|
+
# The host and port.
|
276
|
+
#
|
277
|
+
def to_s
|
278
|
+
"#{host}:#{port}"
|
279
|
+
end
|
280
|
+
|
281
|
+
#
|
282
|
+
# Compares the other target to this target.
|
283
|
+
#
|
284
|
+
# @param [Target] other
|
285
|
+
# The other target.
|
286
|
+
#
|
287
|
+
# @return [Boolean]
|
288
|
+
# Whether the other target has the same host and port.
|
289
|
+
#
|
290
|
+
def ==(other)
|
291
|
+
other.kind_of?(self.class) && other.host == host && other.port == port
|
292
|
+
end
|
293
|
+
|
294
|
+
end
|
295
|
+
end
|