ssl_scan 0.0.1 → 0.0.2
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 +4 -4
- data/bin/ssl_scan +14 -1
- data/lib/ssl_scan/commands/command.rb +31 -0
- data/lib/ssl_scan/commands/host.rb +27 -0
- data/lib/ssl_scan/commands/only_certain_ssl.rb +13 -0
- data/lib/ssl_scan/commands/targets.rb +31 -0
- data/lib/ssl_scan/main.rb +157 -0
- data/lib/ssl_scan/scanner.rb +8 -2
- data/lib/ssl_scan/version.rb +1 -1
- data/lib/ssl_scan.rb +0 -1
- data/sslscan.gemspec +1 -1
- metadata +7 -3
- data/lib/ssl_scan/client.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee1b01a1ed01a07e0c4f9bdadf2629fba62cec7c
|
4
|
+
data.tar.gz: 7baa900e8e512ac129a19672dc6011ee6611e522
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9bef799b8620cf82a8b3b1ac388a5ad74a752b3c0e0c434eacc13740261b9f870ab4a4d91f5d76f5860499b421e069689ff56516da4b8648ebe98f5bc4973ae
|
7
|
+
data.tar.gz: 56c3419bfbd31b857b3b1594c7f8877f74952bca6fe9374e8e86a35da98869256d02ef78673a974caffa2bf2fe4fd2f4512ce7b615bf720fe99be56f39c01611
|
data/bin/ssl_scan
CHANGED
@@ -1,4 +1,17 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
|
4
|
-
require 'ssl_scan/
|
4
|
+
require 'ssl_scan/main'
|
5
|
+
|
6
|
+
|
7
|
+
# register interrupt handlers
|
8
|
+
trap("TERM") do
|
9
|
+
exit(1)
|
10
|
+
end
|
11
|
+
|
12
|
+
trap("QUIT") do
|
13
|
+
exit(1)
|
14
|
+
end
|
15
|
+
|
16
|
+
app = SSLScan::Main.new
|
17
|
+
app.run(ARGV.length, ARGV)
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module SSLScan
|
2
|
+
module Commands
|
3
|
+
class Command
|
4
|
+
attr_accessor :results, :options
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@results = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def execute
|
11
|
+
raise "Implement"
|
12
|
+
end
|
13
|
+
|
14
|
+
# Display Methods
|
15
|
+
def display_header(host, port=443)
|
16
|
+
printf "\nTesting SSL server #{host} on port #{port}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def display_ciphers(scanner=nil)
|
20
|
+
printf "\nSupported Server Cipher(s):\n"
|
21
|
+
scanner.scan do |ssl_version, cipher_name, alg_length, status|
|
22
|
+
unless options.no_failed && status == :failed
|
23
|
+
printf "%12s %10s %10s %s\n", status, ssl_version, "#{alg_length} bits", cipher_name
|
24
|
+
end
|
25
|
+
end
|
26
|
+
scanner
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module SSLScan
|
2
|
+
module Commands
|
3
|
+
class Host < Command
|
4
|
+
attr_accessor :hostname, :options
|
5
|
+
|
6
|
+
def initialize(hostname, options)
|
7
|
+
super()
|
8
|
+
@hostname = hostname
|
9
|
+
@options = options
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute
|
13
|
+
parts = hostname.split(":")
|
14
|
+
if parts.length == 2
|
15
|
+
display_header(parts[0], parts[1])
|
16
|
+
scanner = SSLScan::Scanner.new(parts[0], parts[1].to_i)
|
17
|
+
else
|
18
|
+
display_header(parts[0])
|
19
|
+
scanner = SSLScan::Scanner.new(parts[0])
|
20
|
+
end
|
21
|
+
display_ciphers(scanner)
|
22
|
+
@results << scanner.results
|
23
|
+
end
|
24
|
+
|
25
|
+
end # Host
|
26
|
+
end # Commands
|
27
|
+
end # SSLScan
|
@@ -0,0 +1,31 @@
|
|
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
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require "ssl_scan/compat"
|
2
|
+
require "ssl_scan/version"
|
3
|
+
require "ssl_scan/scanner"
|
4
|
+
require "ssl_scan/result"
|
5
|
+
require "openssl"
|
6
|
+
require "optparse"
|
7
|
+
require "ostruct"
|
8
|
+
|
9
|
+
require "ssl_scan/commands/command"
|
10
|
+
require "ssl_scan/commands/targets"
|
11
|
+
require "ssl_scan/commands/only_certain_ssl"
|
12
|
+
require "ssl_scan/commands/host"
|
13
|
+
|
14
|
+
module SSLScan
|
15
|
+
class Main
|
16
|
+
|
17
|
+
EXIT_SUCCESS = 0
|
18
|
+
EXIT_FAILURE = 1
|
19
|
+
|
20
|
+
WEBSITE = "https://www.testcloud.de"
|
21
|
+
COPYRIGHT = "Copyright (C) John Faucett #{Time.now.year}"
|
22
|
+
|
23
|
+
attr_accessor :options
|
24
|
+
|
25
|
+
def main(argc, argv)
|
26
|
+
@options = self.class.parse_options(argv)
|
27
|
+
|
28
|
+
if options.file
|
29
|
+
command = SSLScan::Commands::Targets.new(options.file)
|
30
|
+
command.execute
|
31
|
+
else
|
32
|
+
valid = true
|
33
|
+
port = 443
|
34
|
+
error_msg = "Host invalid"
|
35
|
+
begin
|
36
|
+
host = argv.last
|
37
|
+
if !host
|
38
|
+
error_msg = "Host not given"
|
39
|
+
valid = false
|
40
|
+
else
|
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)
|
45
|
+
end
|
46
|
+
rescue ::SocketError => ex
|
47
|
+
error_msg = ex.message
|
48
|
+
valid = false
|
49
|
+
end
|
50
|
+
|
51
|
+
unless valid
|
52
|
+
printf("Error: %s\n", error_msg)
|
53
|
+
exit(EXIT_FAILURE)
|
54
|
+
end
|
55
|
+
|
56
|
+
if (options.only_ssl2 || options.only_ssl3 || options.only_tls1 )
|
57
|
+
command = SSLScan::Commands::OnlyCertainSSL.new(options)
|
58
|
+
command.execute
|
59
|
+
else
|
60
|
+
command = SSLScan::Commands::Host.new(argv.last)
|
61
|
+
command.execute
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
show_certificate(command.results.first.cert)
|
66
|
+
end
|
67
|
+
|
68
|
+
alias_method :run, :main
|
69
|
+
|
70
|
+
def self.show_version_info
|
71
|
+
printf("ssl_scan version %s\n%s\n%s\n", VERSION::STRING, WEBSITE, COPYRIGHT)
|
72
|
+
end
|
73
|
+
|
74
|
+
def show_certificate(cert)
|
75
|
+
printf("SSL Certificate:\n")
|
76
|
+
printf(" Version: %d\n", cert.version)
|
77
|
+
printf(" Serial Number: %s\n", cert.serial.to_s(16))
|
78
|
+
printf(" Signature Algorithm: %s\n", cert.signature_algorithm)
|
79
|
+
printf(" Issuer: %s\n", cert.issuer.to_s)
|
80
|
+
printf(" Not valid before: %s\n", cert.not_before.to_s)
|
81
|
+
printf(" Not valid after: %s\n", cert.not_after.to_s)
|
82
|
+
printf(" Subject: %s\n", cert.subject.to_s)
|
83
|
+
printf(" %s", cert.public_key.to_text)
|
84
|
+
|
85
|
+
# TODO: Implement extensions (see: cert.extensions)
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.parse_options(args)
|
89
|
+
options = OpenStruct.new
|
90
|
+
options.file = false
|
91
|
+
options.no_failed = false
|
92
|
+
options.only_ssl2 = false
|
93
|
+
options.only_ssl3 = false
|
94
|
+
options.only_tls1 = false
|
95
|
+
|
96
|
+
opts = OptionParser.new do |opts|
|
97
|
+
opts.banner = "Command: ssl_scan [options] [host:port | host]"
|
98
|
+
|
99
|
+
opts.separator ""
|
100
|
+
opts.separator "Options:"
|
101
|
+
|
102
|
+
# File containing list of hosts to check
|
103
|
+
opts.on( "-t",
|
104
|
+
"--targets FILE",
|
105
|
+
"A file containing a list of hosts to check with syntax ( host | host:port).") do |filename|
|
106
|
+
options.file = filename
|
107
|
+
end
|
108
|
+
|
109
|
+
# List only accepted ciphers
|
110
|
+
opts.on( "--no-failed",
|
111
|
+
"List only accepted ciphers.") do
|
112
|
+
options.no_failed = true
|
113
|
+
end
|
114
|
+
|
115
|
+
opts.on( "--ssl2",
|
116
|
+
"Only check SSLv2 ciphers.") do
|
117
|
+
options.only_ssl2 = true
|
118
|
+
end
|
119
|
+
|
120
|
+
opts.on( "--ssl3",
|
121
|
+
"Only check SSLv3 ciphers.") do
|
122
|
+
options.only_ssl3 = true
|
123
|
+
end
|
124
|
+
|
125
|
+
opts.on( "--tls1",
|
126
|
+
"Only check TLSv1 ciphers.") do
|
127
|
+
options.only_tls1 = true
|
128
|
+
end
|
129
|
+
|
130
|
+
opts.on( "-d",
|
131
|
+
"--debug",
|
132
|
+
"Print any SSL errors to stderr.") do
|
133
|
+
OpenSSL.debug = true
|
134
|
+
end
|
135
|
+
|
136
|
+
opts.on_tail( "-h",
|
137
|
+
"--help",
|
138
|
+
"Display the help text you are now reading.") do
|
139
|
+
puts opts
|
140
|
+
exit(EXIT_SUCCESS)
|
141
|
+
end
|
142
|
+
|
143
|
+
opts.on_tail( "-v",
|
144
|
+
"--version",
|
145
|
+
"Display the program version.") do
|
146
|
+
show_version_info
|
147
|
+
exit(EXIT_SUCCESS)
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
opts.parse!(args)
|
153
|
+
options.freeze
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
end
|
data/lib/ssl_scan/scanner.rb
CHANGED
@@ -12,6 +12,7 @@ class Scanner
|
|
12
12
|
|
13
13
|
attr_reader :supported_versions
|
14
14
|
attr_reader :peer_supported_versions
|
15
|
+
attr_reader :results
|
15
16
|
attr_reader :sslv2
|
16
17
|
|
17
18
|
# Initializes the scanner object
|
@@ -70,7 +71,7 @@ class Scanner
|
|
70
71
|
end
|
71
72
|
|
72
73
|
if block_given?
|
73
|
-
yield(ssl_version, cipher_name,
|
74
|
+
yield(ssl_version, cipher_name, alg_length, status, scan_result.cert)
|
74
75
|
end
|
75
76
|
|
76
77
|
end
|
@@ -80,6 +81,7 @@ class Scanner
|
|
80
81
|
psv << :SSLv3 if scan_result.supports_sslv3?
|
81
82
|
psv << :TLSv1 if scan_result.supports_tlsv1?
|
82
83
|
end
|
84
|
+
@results = scan_result
|
83
85
|
scan_result
|
84
86
|
end
|
85
87
|
|
@@ -164,7 +166,11 @@ class Scanner
|
|
164
166
|
'Timeout' => @timeout
|
165
167
|
)
|
166
168
|
rescue ::Exception => e
|
167
|
-
|
169
|
+
if e.kind_of?(Errno::ECONNRESET)
|
170
|
+
return :failed
|
171
|
+
else
|
172
|
+
return :rejected
|
173
|
+
end
|
168
174
|
ensure
|
169
175
|
if scan_client
|
170
176
|
scan_client.close
|
data/lib/ssl_scan/version.rb
CHANGED
data/lib/ssl_scan.rb
CHANGED
data/sslscan.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["jwaterfaucett@gmail.com"]
|
11
11
|
spec.summary = %q{Ruby SSL Scanner}
|
12
12
|
spec.description = %q{An SSL Scanner Library and Utility in pure Ruby}
|
13
|
-
spec.homepage = ""
|
13
|
+
spec.homepage = "https://github.com/jwaterfaucett/ssl_scan"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0")
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
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.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Faucett
|
@@ -53,7 +53,10 @@ files:
|
|
53
53
|
- Rakefile
|
54
54
|
- bin/ssl_scan
|
55
55
|
- lib/ssl_scan.rb
|
56
|
-
- lib/ssl_scan/
|
56
|
+
- lib/ssl_scan/commands/command.rb
|
57
|
+
- lib/ssl_scan/commands/host.rb
|
58
|
+
- lib/ssl_scan/commands/only_certain_ssl.rb
|
59
|
+
- lib/ssl_scan/commands/targets.rb
|
57
60
|
- lib/ssl_scan/compat.rb
|
58
61
|
- lib/ssl_scan/exceptions.rb
|
59
62
|
- lib/ssl_scan/io/bidirectional_pipe.rb
|
@@ -62,6 +65,7 @@ files:
|
|
62
65
|
- lib/ssl_scan/io/stream.rb
|
63
66
|
- lib/ssl_scan/io/stream_abstraction.rb
|
64
67
|
- lib/ssl_scan/io/stream_server.rb
|
68
|
+
- lib/ssl_scan/main.rb
|
65
69
|
- lib/ssl_scan/result.rb
|
66
70
|
- lib/ssl_scan/scanner.rb
|
67
71
|
- lib/ssl_scan/socket.rb
|
@@ -80,7 +84,7 @@ files:
|
|
80
84
|
- lib/ssl_scan/sync/thread_safe.rb
|
81
85
|
- lib/ssl_scan/version.rb
|
82
86
|
- sslscan.gemspec
|
83
|
-
homepage:
|
87
|
+
homepage: https://github.com/jwaterfaucett/ssl_scan
|
84
88
|
licenses:
|
85
89
|
- MIT
|
86
90
|
metadata: {}
|
data/lib/ssl_scan/client.rb
DELETED
File without changes
|