ssl_scan 0.0.1
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/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +51 -0
- data/Rakefile +1 -0
- data/bin/ssl_scan +4 -0
- data/lib/ssl_scan/client.rb +0 -0
- data/lib/ssl_scan/compat.rb +388 -0
- data/lib/ssl_scan/exceptions.rb +274 -0
- data/lib/ssl_scan/io/bidirectional_pipe.rb +161 -0
- data/lib/ssl_scan/io/datagram_abstraction.rb +35 -0
- data/lib/ssl_scan/io/ring_buffer.rb +369 -0
- data/lib/ssl_scan/io/stream.rb +312 -0
- data/lib/ssl_scan/io/stream_abstraction.rb +209 -0
- data/lib/ssl_scan/io/stream_server.rb +221 -0
- data/lib/ssl_scan/result.rb +165 -0
- data/lib/ssl_scan/scanner.rb +241 -0
- data/lib/ssl_scan/socket/comm/local.rb +526 -0
- data/lib/ssl_scan/socket/comm.rb +120 -0
- data/lib/ssl_scan/socket/ip.rb +131 -0
- data/lib/ssl_scan/socket/parameters.rb +363 -0
- data/lib/ssl_scan/socket/range_walker.rb +470 -0
- data/lib/ssl_scan/socket/ssl_tcp.rb +345 -0
- data/lib/ssl_scan/socket/ssl_tcp_server.rb +188 -0
- data/lib/ssl_scan/socket/subnet_walker.rb +76 -0
- data/lib/ssl_scan/socket/switch_board.rb +289 -0
- data/lib/ssl_scan/socket/tcp.rb +79 -0
- data/lib/ssl_scan/socket/tcp_server.rb +67 -0
- data/lib/ssl_scan/socket/udp.rb +165 -0
- data/lib/ssl_scan/socket.rb +773 -0
- data/lib/ssl_scan/sync/thread_safe.rb +83 -0
- data/lib/ssl_scan/version.rb +9 -0
- data/lib/ssl_scan.rb +11 -0
- data/sslscan.gemspec +23 -0
- metadata +107 -0
@@ -0,0 +1,345 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
require 'ssl_scan/socket'
|
3
|
+
###
|
4
|
+
#
|
5
|
+
# This class provides methods for interacting with an SSL TCP client
|
6
|
+
# connection.
|
7
|
+
#
|
8
|
+
###
|
9
|
+
module SSLScan::Socket::SslTcp
|
10
|
+
|
11
|
+
begin
|
12
|
+
@@loaded_openssl = false
|
13
|
+
|
14
|
+
begin
|
15
|
+
require 'openssl'
|
16
|
+
@@loaded_openssl = true
|
17
|
+
require 'openssl/nonblock'
|
18
|
+
rescue ::Exception
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
include SSLScan::Socket::Tcp
|
23
|
+
|
24
|
+
##
|
25
|
+
#
|
26
|
+
# Factory
|
27
|
+
#
|
28
|
+
##
|
29
|
+
|
30
|
+
#
|
31
|
+
# Creates an SSL TCP instance.
|
32
|
+
#
|
33
|
+
def self.create(hash = {})
|
34
|
+
raise RuntimeError, "No OpenSSL support" if not @@loaded_openssl
|
35
|
+
hash['SSL'] = true
|
36
|
+
self.create_param(SSLScan::Socket::Parameters.from_hash(hash))
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# Set the SSL flag to true and call the base class's create_param routine.
|
41
|
+
#
|
42
|
+
def self.create_param(param)
|
43
|
+
param.ssl = true
|
44
|
+
SSLScan::Socket::Tcp.create_param(param)
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
#
|
49
|
+
# Class initialization
|
50
|
+
#
|
51
|
+
##
|
52
|
+
|
53
|
+
#
|
54
|
+
# Initializes the SSL socket.
|
55
|
+
#
|
56
|
+
def initsock(params = nil)
|
57
|
+
super
|
58
|
+
|
59
|
+
version = :SSLv3
|
60
|
+
if(params)
|
61
|
+
case params.ssl_version
|
62
|
+
when 'SSL2', :SSLv2
|
63
|
+
version = :SSLv2
|
64
|
+
when 'SSL23', :SSLv23
|
65
|
+
version = :SSLv23
|
66
|
+
when 'TLS1', :TLSv1
|
67
|
+
version = :TLSv1
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Build the SSL connection
|
72
|
+
self.sslctx = OpenSSL::SSL::SSLContext.new(version)
|
73
|
+
|
74
|
+
# Configure the SSL context
|
75
|
+
# TODO: Allow the user to specify the verify mode callback
|
76
|
+
# Valid modes:
|
77
|
+
# VERIFY_CLIENT_ONCE
|
78
|
+
# VERIFY_FAIL_IF_NO_PEER_CERT
|
79
|
+
# VERIFY_NONE
|
80
|
+
# VERIFY_PEER
|
81
|
+
if params.ssl_verify_mode
|
82
|
+
self.sslctx.verify_mode = OpenSSL::SSL.const_get("VERIFY_#{params.ssl_verify_mode}".intern)
|
83
|
+
else
|
84
|
+
# Could also do this as graceful faildown in case a passed verify_mode is not supported
|
85
|
+
self.sslctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
86
|
+
end
|
87
|
+
self.sslctx.options = OpenSSL::SSL::OP_ALL
|
88
|
+
if params.ssl_cipher
|
89
|
+
self.sslctx.ciphers = params.ssl_cipher
|
90
|
+
end
|
91
|
+
|
92
|
+
# Set the verification callback
|
93
|
+
self.sslctx.verify_callback = Proc.new do |valid, store|
|
94
|
+
self.peer_verified = valid
|
95
|
+
true
|
96
|
+
end
|
97
|
+
|
98
|
+
# Tie the context to a socket
|
99
|
+
self.sslsock = OpenSSL::SSL::SSLSocket.new(self, self.sslctx)
|
100
|
+
|
101
|
+
# XXX - enabling this causes infinite recursion, so disable for now
|
102
|
+
# self.sslsock.sync_close = true
|
103
|
+
|
104
|
+
|
105
|
+
# Force a negotiation timeout
|
106
|
+
begin
|
107
|
+
Timeout.timeout(params.timeout) do
|
108
|
+
if not allow_nonblock?
|
109
|
+
self.sslsock.connect
|
110
|
+
else
|
111
|
+
begin
|
112
|
+
self.sslsock.connect_nonblock
|
113
|
+
# Ruby 1.8.7 and 1.9.0/1.9.1 uses a standard Errno
|
114
|
+
rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
|
115
|
+
IO::select(nil, nil, nil, 0.10)
|
116
|
+
retry
|
117
|
+
|
118
|
+
# Ruby 1.9.2+ uses IO::WaitReadable/IO::WaitWritable
|
119
|
+
rescue ::Exception => e
|
120
|
+
if ::IO.const_defined?('WaitReadable') and e.kind_of?(::IO::WaitReadable)
|
121
|
+
IO::select( [ self.sslsock ], nil, nil, 0.10 )
|
122
|
+
retry
|
123
|
+
end
|
124
|
+
|
125
|
+
if ::IO.const_defined?('WaitWritable') and e.kind_of?(::IO::WaitWritable)
|
126
|
+
IO::select( nil, [ self.sslsock ], nil, 0.10 )
|
127
|
+
retry
|
128
|
+
end
|
129
|
+
|
130
|
+
raise e
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
rescue ::Timeout::Error
|
136
|
+
raise SSLScan::ConnectionTimeout.new(params.peerhost, params.peerport)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
##
|
141
|
+
#
|
142
|
+
# Stream mixin implementations
|
143
|
+
#
|
144
|
+
##
|
145
|
+
|
146
|
+
#
|
147
|
+
# Writes data over the SSL socket.
|
148
|
+
#
|
149
|
+
def write(buf, opts = {})
|
150
|
+
return sslsock.write(buf) if not allow_nonblock?
|
151
|
+
|
152
|
+
total_sent = 0
|
153
|
+
total_length = buf.length
|
154
|
+
block_size = 16384
|
155
|
+
retry_time = 0.5
|
156
|
+
|
157
|
+
begin
|
158
|
+
while( total_sent < total_length )
|
159
|
+
s = SSLScan::ThreadSafe.select( nil, [ self.sslsock ], nil, 0.25 )
|
160
|
+
if( s == nil || s[0] == nil )
|
161
|
+
next
|
162
|
+
end
|
163
|
+
data = buf[total_sent, block_size]
|
164
|
+
sent = sslsock.write_nonblock( data )
|
165
|
+
if sent > 0
|
166
|
+
total_sent += sent
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
rescue ::IOError, ::Errno::EPIPE
|
171
|
+
return nil
|
172
|
+
|
173
|
+
# Ruby 1.8.7 and 1.9.0/1.9.1 uses a standard Errno
|
174
|
+
rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
|
175
|
+
# Sleep for a half a second, or until we can write again
|
176
|
+
SSLScan::ThreadSafe.select( nil, [ self.sslsock ], nil, retry_time )
|
177
|
+
# Decrement the block size to handle full sendQs better
|
178
|
+
block_size = 1024
|
179
|
+
# Try to write the data again
|
180
|
+
retry
|
181
|
+
|
182
|
+
# Ruby 1.9.2+ uses IO::WaitReadable/IO::WaitWritable
|
183
|
+
rescue ::Exception => e
|
184
|
+
if ::IO.const_defined?('WaitReadable') and e.kind_of?(::IO::WaitReadable)
|
185
|
+
IO::select( [ self.sslsock ], nil, nil, retry_time )
|
186
|
+
retry
|
187
|
+
end
|
188
|
+
|
189
|
+
if ::IO.const_defined?('WaitWritable') and e.kind_of?(::IO::WaitWritable)
|
190
|
+
IO::select( nil, [ self.sslsock ], nil, retry_time )
|
191
|
+
retry
|
192
|
+
end
|
193
|
+
|
194
|
+
# Another form of SSL error, this is always fatal
|
195
|
+
if e.kind_of?(::OpenSSL::SSL::SSLError)
|
196
|
+
return nil
|
197
|
+
end
|
198
|
+
|
199
|
+
# Bubble the event up to the caller otherwise
|
200
|
+
raise e
|
201
|
+
end
|
202
|
+
|
203
|
+
total_sent
|
204
|
+
end
|
205
|
+
|
206
|
+
#
|
207
|
+
# Reads data from the SSL socket.
|
208
|
+
#
|
209
|
+
def read(length = nil, opts = {})
|
210
|
+
if not allow_nonblock?
|
211
|
+
length = 16384 unless length
|
212
|
+
begin
|
213
|
+
return sslsock.sysread(length)
|
214
|
+
rescue ::IOError, ::Errno::EPIPE, ::OpenSSL::SSL::SSLError
|
215
|
+
return nil
|
216
|
+
end
|
217
|
+
return
|
218
|
+
end
|
219
|
+
|
220
|
+
|
221
|
+
begin
|
222
|
+
while true
|
223
|
+
s = SSLScan::ThreadSafe.select( [ self.sslsock ], nil, nil, 0.10 )
|
224
|
+
if( s == nil || s[0] == nil )
|
225
|
+
next
|
226
|
+
end
|
227
|
+
return sslsock.read_nonblock( length )
|
228
|
+
end
|
229
|
+
|
230
|
+
rescue ::IOError, ::Errno::EPIPE
|
231
|
+
return nil
|
232
|
+
|
233
|
+
# Ruby 1.8.7 and 1.9.0/1.9.1 uses a standard Errno
|
234
|
+
rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
|
235
|
+
# Sleep for a tenth a second, or until we can read again
|
236
|
+
SSLScan::ThreadSafe.select( [ self.sslsock ], nil, nil, 0.10 )
|
237
|
+
# Decrement the block size to handle full sendQs better
|
238
|
+
block_size = 1024
|
239
|
+
# Try to write the data again
|
240
|
+
retry
|
241
|
+
|
242
|
+
# Ruby 1.9.2+ uses IO::WaitReadable/IO::WaitWritable
|
243
|
+
rescue ::Exception => e
|
244
|
+
if ::IO.const_defined?('WaitReadable') and e.kind_of?(::IO::WaitReadable)
|
245
|
+
IO::select( [ self.sslsock ], nil, nil, 0.5 )
|
246
|
+
retry
|
247
|
+
end
|
248
|
+
|
249
|
+
if ::IO.const_defined?('WaitWritable') and e.kind_of?(::IO::WaitWritable)
|
250
|
+
IO::select( nil, [ self.sslsock ], nil, 0.5 )
|
251
|
+
retry
|
252
|
+
end
|
253
|
+
|
254
|
+
# Another form of SSL error, this is always fatal
|
255
|
+
if e.kind_of?(::OpenSSL::SSL::SSLError)
|
256
|
+
return nil
|
257
|
+
end
|
258
|
+
|
259
|
+
raise e
|
260
|
+
end
|
261
|
+
|
262
|
+
end
|
263
|
+
|
264
|
+
|
265
|
+
#
|
266
|
+
# Closes the SSL socket.
|
267
|
+
#
|
268
|
+
def close
|
269
|
+
sslsock.close rescue nil
|
270
|
+
super
|
271
|
+
end
|
272
|
+
|
273
|
+
#
|
274
|
+
# Ignore shutdown requests
|
275
|
+
#
|
276
|
+
def shutdown(how=0)
|
277
|
+
# Calling shutdown() on an SSL socket can lead to bad things
|
278
|
+
# Cause of http://metasploit.com/dev/trac/ticket/102
|
279
|
+
end
|
280
|
+
|
281
|
+
#
|
282
|
+
# Access to peer cert
|
283
|
+
#
|
284
|
+
def peer_cert
|
285
|
+
sslsock.peer_cert if sslsock
|
286
|
+
end
|
287
|
+
|
288
|
+
#
|
289
|
+
# Access to peer cert chain
|
290
|
+
#
|
291
|
+
def peer_cert_chain
|
292
|
+
sslsock.peer_cert_chain if sslsock
|
293
|
+
end
|
294
|
+
|
295
|
+
#
|
296
|
+
# Access to the current cipher
|
297
|
+
#
|
298
|
+
def cipher
|
299
|
+
sslsock.cipher if sslsock
|
300
|
+
end
|
301
|
+
|
302
|
+
#
|
303
|
+
# Prevent a sysread from the bare socket
|
304
|
+
#
|
305
|
+
def sysread(*args)
|
306
|
+
raise RuntimeError, "Invalid sysread() call on SSL socket"
|
307
|
+
end
|
308
|
+
|
309
|
+
#
|
310
|
+
# Prevent a sysread from the bare socket
|
311
|
+
#
|
312
|
+
def syswrite(*args)
|
313
|
+
raise RuntimeError, "Invalid syswrite() call on SSL socket"
|
314
|
+
end
|
315
|
+
|
316
|
+
#
|
317
|
+
# This flag determines whether to use the non-blocking openssl
|
318
|
+
# API calls when they are available. This is still buggy on
|
319
|
+
# Linux/Mac OS X, but is required on Windows
|
320
|
+
#
|
321
|
+
def allow_nonblock?
|
322
|
+
avail = self.sslsock.respond_to?(:accept_nonblock)
|
323
|
+
if avail and SSLScan::Compat.is_windows
|
324
|
+
return true
|
325
|
+
end
|
326
|
+
false
|
327
|
+
end
|
328
|
+
|
329
|
+
attr_reader :peer_verified # :nodoc:
|
330
|
+
attr_accessor :sslsock, :sslctx # :nodoc:
|
331
|
+
|
332
|
+
protected
|
333
|
+
|
334
|
+
attr_writer :peer_verified # :nodoc:
|
335
|
+
|
336
|
+
|
337
|
+
rescue LoadError
|
338
|
+
end
|
339
|
+
|
340
|
+
def type?
|
341
|
+
return 'tcp-ssl'
|
342
|
+
end
|
343
|
+
|
344
|
+
end
|
345
|
+
|
@@ -0,0 +1,188 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
require 'ssl_scan/socket'
|
3
|
+
require 'ssl_scan/socket/tcp_server'
|
4
|
+
require 'ssl_scan/io/stream_server'
|
5
|
+
|
6
|
+
###
|
7
|
+
#
|
8
|
+
# This class provides methods for interacting with an SSL wrapped TCP server. It
|
9
|
+
# implements the StreamServer IO interface.
|
10
|
+
#
|
11
|
+
###
|
12
|
+
module SSLScan::Socket::SslTcpServer
|
13
|
+
|
14
|
+
@@loaded_openssl = false
|
15
|
+
|
16
|
+
begin
|
17
|
+
require 'openssl'
|
18
|
+
@@loaded_openssl = true
|
19
|
+
require 'openssl/nonblock'
|
20
|
+
rescue ::Exception
|
21
|
+
end
|
22
|
+
|
23
|
+
include SSLScan::Socket::TcpServer
|
24
|
+
|
25
|
+
##
|
26
|
+
#
|
27
|
+
# Factory
|
28
|
+
#
|
29
|
+
##
|
30
|
+
|
31
|
+
def self.create(hash = {})
|
32
|
+
hash['Proto'] = 'tcp'
|
33
|
+
hash['Server'] = true
|
34
|
+
hash['SSL'] = true
|
35
|
+
self.create_param(SSLScan::Socket::Parameters.from_hash(hash))
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Wrapper around the base class' creation method that automatically sets
|
40
|
+
# the parameter's protocol to TCP and sets the server flag to true.
|
41
|
+
#
|
42
|
+
def self.create_param(param)
|
43
|
+
param.proto = 'tcp'
|
44
|
+
param.server = true
|
45
|
+
param.ssl = true
|
46
|
+
SSLScan::Socket.create_param(param)
|
47
|
+
end
|
48
|
+
|
49
|
+
def initsock(params = nil)
|
50
|
+
raise RuntimeError, "No OpenSSL support" if not @@loaded_openssl
|
51
|
+
self.sslctx = makessl(params)
|
52
|
+
super
|
53
|
+
end
|
54
|
+
|
55
|
+
# (see TcpServer#accept)
|
56
|
+
def accept(opts = {})
|
57
|
+
sock = super()
|
58
|
+
return if not sock
|
59
|
+
|
60
|
+
begin
|
61
|
+
ssl = OpenSSL::SSL::SSLSocket.new(sock, self.sslctx)
|
62
|
+
|
63
|
+
if not allow_nonblock?(ssl)
|
64
|
+
ssl.accept
|
65
|
+
else
|
66
|
+
begin
|
67
|
+
ssl.accept_nonblock
|
68
|
+
|
69
|
+
# Ruby 1.8.7 and 1.9.0/1.9.1 uses a standard Errno
|
70
|
+
rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
|
71
|
+
IO::select(nil, nil, nil, 0.10)
|
72
|
+
retry
|
73
|
+
|
74
|
+
# Ruby 1.9.2+ uses IO::WaitReadable/IO::WaitWritable
|
75
|
+
rescue ::Exception => e
|
76
|
+
if ::IO.const_defined?('WaitReadable') and e.kind_of?(::IO::WaitReadable)
|
77
|
+
IO::select( [ ssl ], nil, nil, 0.10 )
|
78
|
+
retry
|
79
|
+
end
|
80
|
+
|
81
|
+
if ::IO.const_defined?('WaitWritable') and e.kind_of?(::IO::WaitWritable)
|
82
|
+
IO::select( nil, [ ssl ], nil, 0.10 )
|
83
|
+
retry
|
84
|
+
end
|
85
|
+
|
86
|
+
raise e
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
sock.extend(SSLScan::Socket::SslTcp)
|
91
|
+
sock.sslsock = ssl
|
92
|
+
sock.sslctx = self.sslctx
|
93
|
+
|
94
|
+
return sock
|
95
|
+
|
96
|
+
rescue ::OpenSSL::SSL::SSLError
|
97
|
+
sock.close
|
98
|
+
nil
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
#
|
104
|
+
# Create a new ssl context. If +ssl_cert+ is not given, generates a new
|
105
|
+
# key and a leaf certificate with random values.
|
106
|
+
#
|
107
|
+
# @param [SSLScan::Socket::Parameters] params
|
108
|
+
# @return [::OpenSSL::SSL::SSLContext]
|
109
|
+
def makessl(params)
|
110
|
+
ssl_cert = params.ssl_cert
|
111
|
+
if ssl_cert
|
112
|
+
cert = OpenSSL::X509::Certificate.new(ssl_cert)
|
113
|
+
key = OpenSSL::PKey::RSA.new(ssl_cert)
|
114
|
+
else
|
115
|
+
key = OpenSSL::PKey::RSA.new(1024){ }
|
116
|
+
cert = OpenSSL::X509::Certificate.new
|
117
|
+
cert.version = 2
|
118
|
+
cert.serial = rand(0xFFFFFFFF)
|
119
|
+
# name = OpenSSL::X509::Name.new([["C","JP"],["O","TEST"],["CN","localhost"]])
|
120
|
+
subject = OpenSSL::X509::Name.new([
|
121
|
+
["C","US"],
|
122
|
+
['ST', SSLScan::Text.rand_state()],
|
123
|
+
["L", SSLScan::Text.rand_text_alpha(rand(20) + 10)],
|
124
|
+
["O", SSLScan::Text.rand_text_alpha(rand(20) + 10)],
|
125
|
+
["CN", SSLScan::Text.rand_hostname],
|
126
|
+
])
|
127
|
+
issuer = OpenSSL::X509::Name.new([
|
128
|
+
["C","US"],
|
129
|
+
['ST', SSLScan::Text.rand_state()],
|
130
|
+
["L", SSLScan::Text.rand_text_alpha(rand(20) + 10)],
|
131
|
+
["O", SSLScan::Text.rand_text_alpha(rand(20) + 10)],
|
132
|
+
["CN", SSLScan::Text.rand_hostname],
|
133
|
+
])
|
134
|
+
|
135
|
+
cert.subject = subject
|
136
|
+
cert.issuer = issuer
|
137
|
+
cert.not_before = Time.now - (3600 * 365)
|
138
|
+
cert.not_after = Time.now + (3600 * 365)
|
139
|
+
cert.public_key = key.public_key
|
140
|
+
ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
|
141
|
+
cert.extensions = [
|
142
|
+
ef.create_extension("basicConstraints","CA:FALSE"),
|
143
|
+
ef.create_extension("subjectKeyIdentifier","hash"),
|
144
|
+
ef.create_extension("extendedKeyUsage","serverAuth"),
|
145
|
+
ef.create_extension("keyUsage","keyEncipherment,dataEncipherment,digitalSignature")
|
146
|
+
]
|
147
|
+
ef.issuer_certificate = cert
|
148
|
+
cert.add_extension ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always")
|
149
|
+
cert.sign(key, OpenSSL::Digest::SHA1.new)
|
150
|
+
end
|
151
|
+
|
152
|
+
ctx = OpenSSL::SSL::SSLContext.new()
|
153
|
+
ctx.key = key
|
154
|
+
ctx.cert = cert
|
155
|
+
ctx.options = 0
|
156
|
+
|
157
|
+
|
158
|
+
# Older versions of OpenSSL do not export the OP_NO_COMPRESSION symbol
|
159
|
+
if defined?(OpenSSL::SSL::OP_NO_COMPRESSION)
|
160
|
+
# enable/disable the SSL/TLS-level compression
|
161
|
+
if params.ssl_compression
|
162
|
+
ctx.options &= ~OpenSSL::SSL::OP_NO_COMPRESSION
|
163
|
+
else
|
164
|
+
ctx.options |= OpenSSL::SSL::OP_NO_COMPRESSION
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
ctx.session_id_context = SSLScan::Text.rand_text(16)
|
169
|
+
|
170
|
+
return ctx
|
171
|
+
end
|
172
|
+
|
173
|
+
#
|
174
|
+
# This flag determines whether to use the non-blocking openssl
|
175
|
+
# API calls when they are available. This is still buggy on
|
176
|
+
# Linux/Mac OS X, but is required on Windows
|
177
|
+
#
|
178
|
+
def allow_nonblock?(sock=self.sock)
|
179
|
+
avail = sock.respond_to?(:accept_nonblock)
|
180
|
+
if avail and SSLScan::Compat.is_windows
|
181
|
+
return true
|
182
|
+
end
|
183
|
+
false
|
184
|
+
end
|
185
|
+
|
186
|
+
attr_accessor :sslctx
|
187
|
+
end
|
188
|
+
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
require 'ssl_scan/socket'
|
3
|
+
|
4
|
+
module SSLScan
|
5
|
+
module Socket
|
6
|
+
|
7
|
+
###
|
8
|
+
#
|
9
|
+
# This class provides an interface to enumerating a subnet with a supplied
|
10
|
+
# netmask.
|
11
|
+
#
|
12
|
+
###
|
13
|
+
class SubnetWalker
|
14
|
+
|
15
|
+
#
|
16
|
+
# Initializes a subnet walker instance using the supplied subnet
|
17
|
+
# information.
|
18
|
+
#
|
19
|
+
def initialize(subnet, netmask)
|
20
|
+
self.subnet = Socket.resolv_to_dotted(subnet)
|
21
|
+
self.netmask = Socket.resolv_to_dotted(netmask)
|
22
|
+
|
23
|
+
reset
|
24
|
+
end
|
25
|
+
|
26
|
+
#
|
27
|
+
# Resets the subnet walker back to its original state.
|
28
|
+
#
|
29
|
+
def reset
|
30
|
+
self.curr_ip = self.subnet.split('.')
|
31
|
+
self.num_ips = (1 << (32 - Socket.net2bitmask(self.netmask).to_i))
|
32
|
+
self.curr_ip_idx = 0
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# Returns the next IP address.
|
37
|
+
#
|
38
|
+
def next_ip
|
39
|
+
if (curr_ip_idx >= num_ips)
|
40
|
+
return nil
|
41
|
+
end
|
42
|
+
|
43
|
+
if (curr_ip_idx > 0)
|
44
|
+
self.curr_ip[3] = (curr_ip[3].to_i + 1) % 256
|
45
|
+
self.curr_ip[2] = (curr_ip[2].to_i + 1) % 256 if (curr_ip[3] == 0)
|
46
|
+
self.curr_ip[1] = (curr_ip[1].to_i + 1) % 256 if (curr_ip[2] == 0)
|
47
|
+
self.curr_ip[0] = (curr_ip[0].to_i + 1) % 256 if (curr_ip[1] == 0)
|
48
|
+
end
|
49
|
+
|
50
|
+
self.curr_ip_idx += 1
|
51
|
+
|
52
|
+
self.curr_ip.join('.')
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# The subnet that is being enumerated.
|
57
|
+
#
|
58
|
+
attr_reader :subnet
|
59
|
+
#
|
60
|
+
# The netmask of the subnet.
|
61
|
+
#
|
62
|
+
attr_reader :netmask
|
63
|
+
#
|
64
|
+
# The total number of IPs within the subnet.
|
65
|
+
#
|
66
|
+
attr_reader :num_ips
|
67
|
+
|
68
|
+
protected
|
69
|
+
|
70
|
+
attr_writer :subnet, :netmask, :num_ips # :nodoc:
|
71
|
+
attr_accessor :curr_ip, :curr_ip_idx # :nodoc:
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|