ssl_scan 0.0.2 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rspec +3 -0
- data/README.md +23 -2
- data/lib/ssl_scan/commands/command.rb +38 -11
- data/lib/ssl_scan/commands/host.rb +18 -6
- data/lib/ssl_scan/io/stream.rb +0 -1
- data/lib/ssl_scan/io/stream_server.rb +0 -1
- data/lib/ssl_scan/main.rb +97 -43
- data/lib/ssl_scan/result.rb +6 -2
- data/lib/ssl_scan/scanner.rb +38 -11
- data/lib/ssl_scan/socket/comm/local.rb +0 -3
- data/lib/ssl_scan/socket/comm.rb +0 -1
- data/lib/ssl_scan/socket/ip.rb +0 -1
- data/lib/ssl_scan/socket/parameters.rb +1 -2
- data/lib/ssl_scan/socket/range_walker.rb +0 -1
- data/lib/ssl_scan/socket/ssl_tcp.rb +1 -1
- data/lib/ssl_scan/socket/ssl_tcp_server.rb +0 -2
- data/lib/ssl_scan/socket/subnet_walker.rb +0 -1
- data/lib/ssl_scan/socket/switch_board.rb +0 -1
- data/lib/ssl_scan/socket/tcp.rb +0 -2
- data/lib/ssl_scan/socket/tcp_server.rb +0 -3
- data/lib/ssl_scan/socket/udp.rb +0 -1
- data/lib/ssl_scan/sync/thread_safe.rb +0 -1
- data/lib/ssl_scan/version.rb +1 -1
- data/lib/ssl_scan.rb +8 -1
- data/spec/lib/ssl_scan/scanner_spec.rb +19 -0
- data/spec/spec_helper.rb +82 -0
- data/sslscan.gemspec +1 -0
- metadata +22 -5
- data/lib/ssl_scan/commands/only_certain_ssl.rb +0 -13
- data/lib/ssl_scan/commands/targets.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 859254f4c60a989e36294de93ce9efd390615238
|
4
|
+
data.tar.gz: 2137a37917a27462cd215bc351c92b9045102674
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9cc2712861a5affe88051d985d0310788c59c0d29b8a605cd92257065d9ef1757a1621b3dd863a5ba60de0e5718b2fc528f4827837dbaaa3adfae0da18811ca4
|
7
|
+
data.tar.gz: 8058ac51fb8594fd0ffca2966d2a9a719d94e5eed92cd2d5e6d8e02acaf24688fa438e50f83bcae9ea5415467bc33451af216794d1960621216f5accacdadf88
|
data/.gitignore
CHANGED
data/.rspec
ADDED
data/README.md
CHANGED
@@ -11,7 +11,7 @@ In addition to the goals stated above, this library also provides a pure ruby im
|
|
11
11
|
|
12
12
|
Add this line to your application's Gemfile:
|
13
13
|
|
14
|
-
gem '
|
14
|
+
gem 'ssl_scan'
|
15
15
|
|
16
16
|
And then execute:
|
17
17
|
|
@@ -19,7 +19,7 @@ And then execute:
|
|
19
19
|
|
20
20
|
Or install it yourself as:
|
21
21
|
|
22
|
-
$ gem install
|
22
|
+
$ gem install ssl_scan
|
23
23
|
|
24
24
|
## Usage
|
25
25
|
|
@@ -34,6 +34,9 @@ scanner.scan
|
|
34
34
|
# show the ciphers which the server prefers
|
35
35
|
scanner.get_preferred_ciphers
|
36
36
|
|
37
|
+
# only scan for a particular ssl version - it also accepts a block
|
38
|
+
scanner.scan_ssl_version(:SSLv3)
|
39
|
+
|
37
40
|
# You can also pass a block to the scan function to be able to do things
|
38
41
|
# like write to a socket stream and get some feedback to your users
|
39
42
|
# - status can be either accepted or rejected for a particular cipher
|
@@ -42,6 +45,24 @@ scanner.scan do |ssl_version, cipher, key_length, status, cert|
|
|
42
45
|
end
|
43
46
|
```
|
44
47
|
|
48
|
+
You can also easily run it from the console.
|
49
|
+
|
50
|
+
```bash
|
51
|
+
# show help information
|
52
|
+
ssl_scan --help
|
53
|
+
|
54
|
+
# scan a particular server, optionally with a custom SSL port
|
55
|
+
ssl_scan example.com
|
56
|
+
ssl_scan odd-server.net:8077
|
57
|
+
|
58
|
+
# scan a list of hosts contained in a file
|
59
|
+
ssl_scan -t /path/to/hosts_file
|
60
|
+
|
61
|
+
# only test against a particular SSL protocol version
|
62
|
+
ssl_scan --tls1 example.com
|
63
|
+
|
64
|
+
```
|
65
|
+
|
45
66
|
## Contributing
|
46
67
|
|
47
68
|
1. Fork it ( http://github.com/<my-github-username>/sslscan/fork )
|
@@ -1,10 +1,14 @@
|
|
1
|
+
require "stringio"
|
2
|
+
|
1
3
|
module SSLScan
|
2
4
|
module Commands
|
3
5
|
class Command
|
4
|
-
attr_accessor :results, :options
|
6
|
+
attr_accessor :results, :options, :stream, :errors
|
5
7
|
|
6
|
-
def initialize
|
7
|
-
@results =
|
8
|
+
def initialize(results=[], stream=nil)
|
9
|
+
@results = results
|
10
|
+
@errors = []
|
11
|
+
@stream = stream || STDOUT
|
8
12
|
end
|
9
13
|
|
10
14
|
def execute
|
@@ -12,20 +16,43 @@ module SSLScan
|
|
12
16
|
end
|
13
17
|
|
14
18
|
# Display Methods
|
15
|
-
def
|
16
|
-
printf "\nTesting SSL server #{host} on port #{port}"
|
19
|
+
def write_header(host, port=443)
|
20
|
+
stream.printf "\nTesting SSL server #{host} on port #{port}"
|
17
21
|
end
|
18
22
|
|
19
|
-
def
|
20
|
-
printf
|
21
|
-
scanner.
|
22
|
-
|
23
|
-
|
23
|
+
def write_preferred_ciphers(scanner)
|
24
|
+
stream.printf("\nServer Preferred Cipher(s)\n")
|
25
|
+
ciphers = scanner.get_preferred_ciphers
|
26
|
+
ciphers.each do |c|
|
27
|
+
if c.length > 1 && !c[1].empty?
|
28
|
+
stream.printf("%12s %10s %s\n", c[0], "#{c[1][3]} bits", c[1][0])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
stream.printf("\n")
|
32
|
+
end
|
33
|
+
|
34
|
+
def write_ciphers(scanner=nil)
|
35
|
+
stream.printf "\nSupported Server Cipher(s):\n"
|
36
|
+
|
37
|
+
sslv = options.only_ssl2 || options.only_ssl3 || options.only_tls1 || false
|
38
|
+
|
39
|
+
if sslv
|
40
|
+
scanner.scan_ssl_version(sslv) do |ssl_version, cipher_name, alg_length, status|
|
41
|
+
unless options.no_failed && status == :failed
|
42
|
+
stream.printf("%12s %10s %10s %s\n", status, ssl_version, "#{alg_length} bits", cipher_name)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
else
|
46
|
+
scanner.scan do |ssl_version, cipher_name, alg_length, status|
|
47
|
+
unless options.no_failed && status == :failed
|
48
|
+
stream.printf "%12s %10s %10s %s\n", status, ssl_version, "#{alg_length} bits", cipher_name
|
49
|
+
end
|
24
50
|
end
|
25
51
|
end
|
52
|
+
stream.printf("\n")
|
26
53
|
scanner
|
27
54
|
end
|
28
55
|
|
29
56
|
end
|
30
57
|
end
|
31
|
-
end
|
58
|
+
end
|
@@ -3,8 +3,8 @@ module SSLScan
|
|
3
3
|
class Host < Command
|
4
4
|
attr_accessor :hostname, :options
|
5
5
|
|
6
|
-
def initialize(hostname, options)
|
7
|
-
super()
|
6
|
+
def initialize(hostname, options={}, output=nil)
|
7
|
+
super([], output)
|
8
8
|
@hostname = hostname
|
9
9
|
@options = options
|
10
10
|
end
|
@@ -12,16 +12,28 @@ module SSLScan
|
|
12
12
|
def execute
|
13
13
|
parts = hostname.split(":")
|
14
14
|
if parts.length == 2
|
15
|
-
display_header(parts[0], parts[1])
|
16
15
|
scanner = SSLScan::Scanner.new(parts[0], parts[1].to_i)
|
17
16
|
else
|
18
|
-
display_header(parts[0])
|
19
17
|
scanner = SSLScan::Scanner.new(parts[0])
|
20
18
|
end
|
21
|
-
|
19
|
+
# If we can't get any SSL connection, then don't bother testing
|
20
|
+
# individual ciphers.
|
21
|
+
if [:rejected, :failed].include?(scanner.test_ssl) and [:rejected, :failed].include?(scanner.test_tls)
|
22
|
+
errors << "SSL Connection failed"
|
23
|
+
return false
|
24
|
+
end
|
25
|
+
|
26
|
+
if parts.length == 2
|
27
|
+
write_header(parts[0], parts[1])
|
28
|
+
else
|
29
|
+
write_header(parts[0])
|
30
|
+
end
|
31
|
+
|
32
|
+
write_ciphers(scanner)
|
33
|
+
write_preferred_ciphers(scanner)
|
22
34
|
@results << scanner.results
|
23
35
|
end
|
24
36
|
|
25
37
|
end # Host
|
26
38
|
end # Commands
|
27
|
-
end # SSLScan
|
39
|
+
end # SSLScan
|
data/lib/ssl_scan/io/stream.rb
CHANGED
data/lib/ssl_scan/main.rb
CHANGED
@@ -1,14 +1,25 @@
|
|
1
|
-
require "ssl_scan/compat"
|
1
|
+
# require "ssl_scan/compat"
|
2
|
+
# require "ssl_scan/version"
|
3
|
+
# require "ssl_scan/scanner"
|
4
|
+
# require "ssl_scan/result"
|
5
|
+
|
2
6
|
require "ssl_scan/version"
|
3
|
-
require "ssl_scan/
|
7
|
+
require "ssl_scan/compat"
|
4
8
|
require "ssl_scan/result"
|
9
|
+
require "timeout"
|
10
|
+
require "thread"
|
11
|
+
require "ssl_scan/sync/thread_safe"
|
12
|
+
require "ssl_scan/io/stream"
|
13
|
+
require "ssl_scan/io/stream_server"
|
14
|
+
require "ssl_scan/socket"
|
15
|
+
require "ssl_scan/socket/tcp"
|
16
|
+
require "ssl_scan/scanner"
|
17
|
+
|
5
18
|
require "openssl"
|
6
19
|
require "optparse"
|
7
20
|
require "ostruct"
|
8
21
|
|
9
22
|
require "ssl_scan/commands/command"
|
10
|
-
require "ssl_scan/commands/targets"
|
11
|
-
require "ssl_scan/commands/only_certain_ssl"
|
12
23
|
require "ssl_scan/commands/host"
|
13
24
|
|
14
25
|
module SSLScan
|
@@ -17,58 +28,94 @@ module SSLScan
|
|
17
28
|
EXIT_SUCCESS = 0
|
18
29
|
EXIT_FAILURE = 1
|
19
30
|
|
31
|
+
SYNTAX = "ssl_scan [Options] [host:port | host]"
|
20
32
|
WEBSITE = "https://www.testcloud.de"
|
21
33
|
COPYRIGHT = "Copyright (C) John Faucett #{Time.now.year}"
|
22
34
|
|
35
|
+
BANNER =<<EOH
|
36
|
+
_
|
37
|
+
_____| | ___ __ __ _ _ _
|
38
|
+
(_-<_-< | (_-</ _/ _` | ' \
|
39
|
+
/__/__/_|_/__/\__\__,_|_||_|
|
40
|
+
|___|
|
41
|
+
|
42
|
+
EOH
|
43
|
+
|
23
44
|
attr_accessor :options
|
24
45
|
|
46
|
+
|
47
|
+
def check_host(host, die_on_fail=true)
|
48
|
+
valid = true
|
49
|
+
port = 443
|
50
|
+
error_msg = "Host invalid"
|
51
|
+
begin
|
52
|
+
if !host
|
53
|
+
error_msg = "Host not given"
|
54
|
+
valid = false
|
55
|
+
else
|
56
|
+
host_parts = host.split(":")
|
57
|
+
host = host_parts.first
|
58
|
+
port = host_parts.last.to_i if host_parts.last != host
|
59
|
+
::Socket.gethostbyname(host)
|
60
|
+
end
|
61
|
+
rescue ::SocketError => ex
|
62
|
+
error_msg = ex.message
|
63
|
+
valid = false
|
64
|
+
end
|
65
|
+
|
66
|
+
unless valid
|
67
|
+
printf("Error: %s\n", error_msg)
|
68
|
+
exit(EXIT_FAILURE) unless !die_on_fail
|
69
|
+
end
|
70
|
+
return valid
|
71
|
+
end
|
72
|
+
|
25
73
|
def main(argc, argv)
|
26
74
|
@options = self.class.parse_options(argv)
|
27
75
|
|
76
|
+
host = argv.last
|
77
|
+
|
28
78
|
if options.file
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
host_parts = host.split(":")
|
42
|
-
host = host_parts.first
|
43
|
-
port = host_parts.last.to_i if host_parts.last != host
|
44
|
-
::Socket.gethostbyname(host)
|
79
|
+
file = File.read(options.file)
|
80
|
+
hosts = file.split("\n").map(&:strip).select { |h| h.length > 0 }
|
81
|
+
hosts.each do |h|
|
82
|
+
if check_host(h, false)
|
83
|
+
command = SSLScan::Commands::Host.new(h, options)
|
84
|
+
command.execute
|
85
|
+
|
86
|
+
if command.errors.empty?
|
87
|
+
show_results(command.results)
|
88
|
+
else
|
89
|
+
show_command_errors(h, command.errors)
|
90
|
+
end
|
45
91
|
end
|
46
|
-
rescue ::SocketError => ex
|
47
|
-
error_msg = ex.message
|
48
|
-
valid = false
|
49
92
|
end
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
if (options.only_ssl2 || options.only_ssl3 || options.only_tls1 )
|
57
|
-
command = SSLScan::Commands::OnlyCertainSSL.new(options)
|
58
|
-
command.execute
|
93
|
+
else
|
94
|
+
check_host(host)
|
95
|
+
command = SSLScan::Commands::Host.new(host, options)
|
96
|
+
command.execute
|
97
|
+
if command.errors.empty?
|
98
|
+
show_results(host, command.results)
|
59
99
|
else
|
60
|
-
command
|
61
|
-
command.execute
|
100
|
+
show_command_errors(host, command.errors)
|
62
101
|
end
|
63
102
|
end
|
64
103
|
|
65
|
-
show_certificate(command.results.first.cert)
|
66
104
|
end
|
67
105
|
|
68
106
|
alias_method :run, :main
|
69
107
|
|
70
|
-
def self.
|
71
|
-
|
108
|
+
def self.version_info
|
109
|
+
sprintf("ssl_scan version %s\n%s\n%s\n", VERSION::STRING, WEBSITE, COPYRIGHT)
|
110
|
+
end
|
111
|
+
|
112
|
+
def show_results(host, results)
|
113
|
+
result_set = results.compact
|
114
|
+
unless result_set.empty?
|
115
|
+
result_set.each do |result|
|
116
|
+
show_certificate(result.cert)
|
117
|
+
end
|
118
|
+
end
|
72
119
|
end
|
73
120
|
|
74
121
|
def show_certificate(cert)
|
@@ -85,6 +132,10 @@ module SSLScan
|
|
85
132
|
# TODO: Implement extensions (see: cert.extensions)
|
86
133
|
end
|
87
134
|
|
135
|
+
def show_command_errors(host, errors)
|
136
|
+
printf("Error[%s]: (%s)\n", host, errors.join(" "))
|
137
|
+
end
|
138
|
+
|
88
139
|
def self.parse_options(args)
|
89
140
|
options = OpenStruct.new
|
90
141
|
options.file = false
|
@@ -94,7 +145,10 @@ module SSLScan
|
|
94
145
|
options.only_tls1 = false
|
95
146
|
|
96
147
|
opts = OptionParser.new do |opts|
|
97
|
-
opts.banner = "
|
148
|
+
opts.banner = sprintf("%s%s", BANNER, version_info)
|
149
|
+
|
150
|
+
opts.separator ""
|
151
|
+
opts.separator "Usage: #{SYNTAX}"
|
98
152
|
|
99
153
|
opts.separator ""
|
100
154
|
opts.separator "Options:"
|
@@ -114,17 +168,17 @@ module SSLScan
|
|
114
168
|
|
115
169
|
opts.on( "--ssl2",
|
116
170
|
"Only check SSLv2 ciphers.") do
|
117
|
-
options.only_ssl2 =
|
171
|
+
options.only_ssl2 = :SSLv2
|
118
172
|
end
|
119
173
|
|
120
174
|
opts.on( "--ssl3",
|
121
175
|
"Only check SSLv3 ciphers.") do
|
122
|
-
options.only_ssl3 =
|
176
|
+
options.only_ssl3 = :SSLv3
|
123
177
|
end
|
124
178
|
|
125
179
|
opts.on( "--tls1",
|
126
180
|
"Only check TLSv1 ciphers.") do
|
127
|
-
options.only_tls1 =
|
181
|
+
options.only_tls1 = :TLSv1
|
128
182
|
end
|
129
183
|
|
130
184
|
opts.on( "-d",
|
@@ -143,7 +197,7 @@ module SSLScan
|
|
143
197
|
opts.on_tail( "-v",
|
144
198
|
"--version",
|
145
199
|
"Display the program version.") do
|
146
|
-
|
200
|
+
printf("%s", version_info)
|
147
201
|
exit(EXIT_SUCCESS)
|
148
202
|
end
|
149
203
|
|
@@ -154,4 +208,4 @@ module SSLScan
|
|
154
208
|
end
|
155
209
|
|
156
210
|
end
|
157
|
-
end
|
211
|
+
end
|
data/lib/ssl_scan/result.rb
CHANGED
@@ -59,6 +59,10 @@ module SSLScan
|
|
59
59
|
enum_ciphers(:rejected, version)
|
60
60
|
end
|
61
61
|
|
62
|
+
def failed(version = :all)
|
63
|
+
enum_ciphers(:failed, version)
|
64
|
+
end
|
65
|
+
|
62
66
|
def each_accepted(version = :all)
|
63
67
|
accepted(version).each do |cipher_result|
|
64
68
|
yield cipher_result
|
@@ -114,7 +118,7 @@ module SSLScan
|
|
114
118
|
unless key_length.kind_of? Fixnum
|
115
119
|
raise ArgumentError, "Must supply a valid key length"
|
116
120
|
end
|
117
|
-
unless [:accepted, :rejected].include? status
|
121
|
+
unless [:accepted, :rejected, :failed].include? status
|
118
122
|
raise ArgumentError, "Status must be either :accepted or :rejected"
|
119
123
|
end
|
120
124
|
|
@@ -162,4 +166,4 @@ module SSLScan
|
|
162
166
|
end
|
163
167
|
|
164
168
|
end
|
165
|
-
end
|
169
|
+
end
|
data/lib/ssl_scan/scanner.rb
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
require 'ssl_scan/socket'
|
2
|
-
require 'ssl_scan/result'
|
3
|
-
|
4
1
|
module SSLScan
|
5
2
|
|
6
3
|
class Scanner
|
@@ -57,10 +54,7 @@ class Scanner
|
|
57
54
|
scan_result.openssl_sslv2 = sslv2
|
58
55
|
# If we can't get any SSL connection, then don't bother testing
|
59
56
|
# individual ciphers.
|
60
|
-
|
61
|
-
return scan_result
|
62
|
-
end
|
63
|
-
|
57
|
+
|
64
58
|
@supported_versions.each do |ssl_version|
|
65
59
|
sslctx = OpenSSL::SSL::SSLContext.new(ssl_version)
|
66
60
|
sslctx.ciphers.each do |cipher_name, ssl_ver, key_length, alg_length|
|
@@ -85,7 +79,32 @@ class Scanner
|
|
85
79
|
scan_result
|
86
80
|
end
|
87
81
|
|
88
|
-
|
82
|
+
def scan_ssl_version(ssl_version, &block)
|
83
|
+
scan_result = SSLScan::Result.new
|
84
|
+
scan_result.openssl_sslv2 = sslv2
|
85
|
+
# If we can't get any SSL connection, then don't bother testing
|
86
|
+
# individual ciphers.
|
87
|
+
if ([:rejected, :failed].include?(test_ssl) and [:rejected, :failed].include?(test_tls)) or !@supported_versions.include?(ssl_version)
|
88
|
+
return scan_result
|
89
|
+
end
|
90
|
+
|
91
|
+
sslctx = OpenSSL::SSL::SSLContext.new(ssl_version)
|
92
|
+
sslctx.ciphers.each do |cipher_name, ssl_ver, key_length, alg_length|
|
93
|
+
status = test_cipher(ssl_version, cipher_name)
|
94
|
+
scan_result.add_cipher(ssl_version, cipher_name, key_length, status)
|
95
|
+
if status == :accepted and scan_result.cert.nil?
|
96
|
+
scan_result.cert = get_cert(ssl_version, cipher_name)
|
97
|
+
end
|
98
|
+
|
99
|
+
if block_given?
|
100
|
+
yield(ssl_version, cipher_name, alg_length, status, scan_result.cert)
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
@results = scan_result
|
105
|
+
scan_result
|
106
|
+
end
|
107
|
+
|
89
108
|
def get_preferred_ciphers
|
90
109
|
ssl_versions = {}.tap do |v|
|
91
110
|
@supported_versions.each { |sv| v[sv] = [] }
|
@@ -120,7 +139,11 @@ class Scanner
|
|
120
139
|
'Timeout' => @timeout
|
121
140
|
)
|
122
141
|
rescue ::Exception => e
|
123
|
-
|
142
|
+
if e.kind_of?(Errno::ECONNRESET)
|
143
|
+
return :failed
|
144
|
+
else
|
145
|
+
return :rejected
|
146
|
+
end
|
124
147
|
ensure
|
125
148
|
if scan_client
|
126
149
|
scan_client.close
|
@@ -140,7 +163,11 @@ class Scanner
|
|
140
163
|
'Timeout' => @timeout
|
141
164
|
)
|
142
165
|
rescue ::Exception => e
|
143
|
-
|
166
|
+
if e.kind_of?(Errno::ECONNRESET)
|
167
|
+
return :failed
|
168
|
+
else
|
169
|
+
return :rejected
|
170
|
+
end
|
144
171
|
ensure
|
145
172
|
if scan_client
|
146
173
|
scan_client.close
|
@@ -244,4 +271,4 @@ class Scanner
|
|
244
271
|
end
|
245
272
|
|
246
273
|
end
|
247
|
-
end
|
274
|
+
end
|
@@ -1,12 +1,9 @@
|
|
1
1
|
# -*- coding: binary -*-
|
2
2
|
require 'singleton'
|
3
|
-
require 'ssl_scan/socket'
|
4
|
-
require 'ssl_scan/socket/tcp'
|
5
3
|
require 'ssl_scan/socket/ssl_tcp'
|
6
4
|
require 'ssl_scan/socket/ssl_tcp_server'
|
7
5
|
require 'ssl_scan/socket/udp'
|
8
6
|
require 'ssl_scan/socket/ip'
|
9
|
-
require 'timeout'
|
10
7
|
|
11
8
|
###
|
12
9
|
#
|
data/lib/ssl_scan/socket/comm.rb
CHANGED
data/lib/ssl_scan/socket/ip.rb
CHANGED
data/lib/ssl_scan/socket/tcp.rb
CHANGED
data/lib/ssl_scan/socket/udp.rb
CHANGED
data/lib/ssl_scan/version.rb
CHANGED
data/lib/ssl_scan.rb
CHANGED
@@ -3,8 +3,15 @@ require "openssl"
|
|
3
3
|
|
4
4
|
require "ssl_scan/version"
|
5
5
|
require "ssl_scan/compat"
|
6
|
-
require "ssl_scan/scanner"
|
7
6
|
require "ssl_scan/result"
|
7
|
+
require "timeout"
|
8
|
+
require "thread"
|
9
|
+
require "ssl_scan/sync/thread_safe"
|
10
|
+
require "ssl_scan/io/stream"
|
11
|
+
require "ssl_scan/io/stream_server"
|
12
|
+
require "ssl_scan/socket"
|
13
|
+
require "ssl_scan/socket/tcp"
|
14
|
+
require "ssl_scan/scanner"
|
8
15
|
|
9
16
|
module SSLScan
|
10
17
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SSLScan::Scanner do
|
4
|
+
|
5
|
+
subject { SSLScan::Scanner.new('google.com', 443) }
|
6
|
+
|
7
|
+
# attr_accessors
|
8
|
+
it { should respond_to(:host) }
|
9
|
+
it { should respond_to(:port) }
|
10
|
+
it { should respond_to(:timeout) }
|
11
|
+
it { should respond_to(:context) }
|
12
|
+
|
13
|
+
# attr_readers
|
14
|
+
it { should respond_to(:supported_versions) }
|
15
|
+
it { should respond_to(:peer_supported_versions) }
|
16
|
+
it { should respond_to(:results) }
|
17
|
+
it { should respond_to(:sslv2) }
|
18
|
+
|
19
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# The generated `.rspec` file contains `--require spec_helper` which will cause this
|
4
|
+
# file to always be loaded, without a need to explicitly require it in any files.
|
5
|
+
#
|
6
|
+
# Given that it is always loaded, you are encouraged to keep this file as
|
7
|
+
# light-weight as possible. Requiring heavyweight dependencies from this file
|
8
|
+
# will add to the boot time of your test suite on EVERY test run, even for an
|
9
|
+
# individual file that may not need all of that loaded. Instead, make a
|
10
|
+
# separate helper file that requires this one and then use it only in the specs
|
11
|
+
# that actually need it.
|
12
|
+
#
|
13
|
+
# The `.rspec` file also contains a few flags that are not defaults but that
|
14
|
+
# users commonly want.
|
15
|
+
#
|
16
|
+
|
17
|
+
lib = File.expand_path("../../lib", __FILE__)
|
18
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
19
|
+
require "ssl_scan"
|
20
|
+
|
21
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
22
|
+
RSpec.configure do |config|
|
23
|
+
# The settings below are suggested to provide a good initial experience
|
24
|
+
# with RSpec, but feel free to customize to your heart's content.
|
25
|
+
|
26
|
+
# These two settings work together to allow you to limit a spec run
|
27
|
+
# to individual examples or groups you care about by tagging them with
|
28
|
+
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
29
|
+
# get run.
|
30
|
+
config.filter_run :focus
|
31
|
+
config.run_all_when_everything_filtered = true
|
32
|
+
|
33
|
+
# Many RSpec users commonly either run the entire suite or an individual
|
34
|
+
# file, and it's useful to allow more verbose output when running an
|
35
|
+
# individual spec file.
|
36
|
+
if config.files_to_run.one?
|
37
|
+
# Use the documentation formatter for detailed output,
|
38
|
+
# unless a formatter has already been configured
|
39
|
+
# (e.g. via a command-line flag).
|
40
|
+
config.default_formatter = 'doc'
|
41
|
+
end
|
42
|
+
|
43
|
+
# Print the 10 slowest examples and example groups at the
|
44
|
+
# end of the spec run, to help surface which specs are running
|
45
|
+
# particularly slow.
|
46
|
+
config.profile_examples = 10
|
47
|
+
|
48
|
+
# Run specs in random order to surface order dependencies. If you find an
|
49
|
+
# order dependency and want to debug it, you can fix the order by providing
|
50
|
+
# the seed, which is printed after each run.
|
51
|
+
# --seed 1234
|
52
|
+
config.order = :random
|
53
|
+
|
54
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
55
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
56
|
+
# test failures related to randomization by passing the same `--seed` value
|
57
|
+
# as the one that triggered the failure.
|
58
|
+
Kernel.srand config.seed
|
59
|
+
|
60
|
+
# rspec-expectations config goes here. You can use an alternate
|
61
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
62
|
+
# assertions if you prefer.
|
63
|
+
config.expect_with :rspec do |expectations|
|
64
|
+
# Enable only the newer, non-monkey-patching expect syntax.
|
65
|
+
# For more details, see:
|
66
|
+
# - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
67
|
+
expectations.syntax = :expect
|
68
|
+
end
|
69
|
+
|
70
|
+
# rspec-mocks config goes here. You can use an alternate test double
|
71
|
+
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
72
|
+
config.mock_with :rspec do |mocks|
|
73
|
+
# Enable only the newer, non-monkey-patching expect syntax.
|
74
|
+
# For more details, see:
|
75
|
+
# - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
76
|
+
mocks.syntax = :expect
|
77
|
+
|
78
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
79
|
+
# a real object. This is generally recommended.
|
80
|
+
mocks.verify_partial_doubles = true
|
81
|
+
end
|
82
|
+
end
|
data/sslscan.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ssl_scan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Faucett
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-06-
|
11
|
+
date: 2014-06-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - '>='
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.0.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.0.0
|
41
55
|
description: An SSL Scanner Library and Utility in pure Ruby
|
42
56
|
email:
|
43
57
|
- jwaterfaucett@gmail.com
|
@@ -47,6 +61,7 @@ extensions: []
|
|
47
61
|
extra_rdoc_files: []
|
48
62
|
files:
|
49
63
|
- .gitignore
|
64
|
+
- .rspec
|
50
65
|
- Gemfile
|
51
66
|
- LICENSE.txt
|
52
67
|
- README.md
|
@@ -55,8 +70,6 @@ files:
|
|
55
70
|
- lib/ssl_scan.rb
|
56
71
|
- lib/ssl_scan/commands/command.rb
|
57
72
|
- lib/ssl_scan/commands/host.rb
|
58
|
-
- lib/ssl_scan/commands/only_certain_ssl.rb
|
59
|
-
- lib/ssl_scan/commands/targets.rb
|
60
73
|
- lib/ssl_scan/compat.rb
|
61
74
|
- lib/ssl_scan/exceptions.rb
|
62
75
|
- lib/ssl_scan/io/bidirectional_pipe.rb
|
@@ -83,6 +96,8 @@ files:
|
|
83
96
|
- lib/ssl_scan/socket/udp.rb
|
84
97
|
- lib/ssl_scan/sync/thread_safe.rb
|
85
98
|
- lib/ssl_scan/version.rb
|
99
|
+
- spec/lib/ssl_scan/scanner_spec.rb
|
100
|
+
- spec/spec_helper.rb
|
86
101
|
- sslscan.gemspec
|
87
102
|
homepage: https://github.com/jwaterfaucett/ssl_scan
|
88
103
|
licenses:
|
@@ -108,4 +123,6 @@ rubygems_version: 2.0.3
|
|
108
123
|
signing_key:
|
109
124
|
specification_version: 4
|
110
125
|
summary: Ruby SSL Scanner
|
111
|
-
test_files:
|
126
|
+
test_files:
|
127
|
+
- spec/lib/ssl_scan/scanner_spec.rb
|
128
|
+
- spec/spec_helper.rb
|
@@ -1,31 +0,0 @@
|
|
1
|
-
module SSLScan
|
2
|
-
module Commands
|
3
|
-
class Targets < Command
|
4
|
-
|
5
|
-
attr_accessor :file, :hosts
|
6
|
-
|
7
|
-
def initialize(filename="", options)
|
8
|
-
super()
|
9
|
-
@file = File.read(filename)
|
10
|
-
@hosts = @file.split("\n").map(&:strip).select { |h| h.length > 0 }
|
11
|
-
@options = options
|
12
|
-
end
|
13
|
-
|
14
|
-
def execute
|
15
|
-
hosts.each do |host|
|
16
|
-
parts = host.split(":")
|
17
|
-
if parts.length == 2
|
18
|
-
display_header(parts[0], parts[1])
|
19
|
-
scanner = SSLScan::Scanner.new(parts[0], parts[1].to_i)
|
20
|
-
else
|
21
|
-
display_header(host)
|
22
|
-
scanner = SSLScan::Scanner.new(parts[0])
|
23
|
-
end
|
24
|
-
display_ciphers(scanner)
|
25
|
-
@results << scanner.results
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|