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.
@@ -0,0 +1,289 @@
1
+ # -*- coding: binary -*-
2
+ require 'singleton'
3
+ require 'thread'
4
+ require 'ssl_scan/socket'
5
+
6
+ module SSLScan
7
+ module Socket
8
+
9
+ ###
10
+ #
11
+ # This class provides a global routing table that associates subnets with Comm
12
+ # classes. Comm classes are used to instantiate objects that are tied to
13
+ # remote network entities. For example, the Local Comm class is used to
14
+ # building network connections directly from the local machine whereas, for
15
+ # instance, a Meterpreter Comm would build a local socket pair that is
16
+ # associated with a connection established by a remote entity. This can be
17
+ # seen as a uniform way of communicating with hosts through arbitrary
18
+ # channels.
19
+ #
20
+ ###
21
+ class SwitchBoard
22
+
23
+ include Singleton
24
+ include Enumerable
25
+
26
+ def initialize
27
+ @_initialized = false
28
+ end
29
+
30
+ ###
31
+ #
32
+ # This class represents a logical switch board route.
33
+ # TODO: Enable this to work with IPv6 addresses
34
+ #
35
+ ###
36
+ class Route
37
+ def initialize(subnet, netmask, comm)
38
+ self.subnet = subnet
39
+ self.netmask = netmask
40
+ self.comm = comm
41
+ self.subnet_nbo = Socket.resolv_nbo_i(subnet)
42
+ self.netmask_nbo = Socket.resolv_nbo_i(netmask)
43
+ end
44
+
45
+ #
46
+ # Sort according to bitmask
47
+ #
48
+ def <=>(other)
49
+ self.bitmask <=> other.bitmask
50
+ end
51
+
52
+ #
53
+ # Convert the netmask to a bitmask and cache it.
54
+ #
55
+ def bitmask
56
+ @_bitmask = Socket.net2bitmask(self.netmask) if (@_bitmask == nil)
57
+ @_bitmask
58
+ end
59
+
60
+ attr_reader :subnet, :netmask, :comm
61
+ attr_reader :subnet_nbo, :netmask_nbo
62
+ protected
63
+ attr_writer :subnet, :netmask, :comm
64
+ attr_writer :subnet_nbo, :netmask_nbo
65
+ end
66
+
67
+ ##
68
+ #
69
+ # Class method wrappers
70
+ #
71
+ ##
72
+
73
+ #
74
+ # Adds a route to the switch board routing table using the supplied Comm
75
+ # instance.
76
+ #
77
+ def self.add_route(subnet, mask, comm)
78
+ ret = self.instance.add_route(subnet, mask, comm)
79
+ if ret && comm.respond_to?(:routes) && comm.routes.kind_of?(Array)
80
+ comm.routes << "#{subnet}/#{mask}"
81
+ end
82
+ ret
83
+ end
84
+
85
+ #
86
+ # Removes a route from the switch board routing table for the supplied
87
+ # subnet routing through the supplied Comm instance.
88
+ #
89
+ def self.remove_route(subnet, mask, comm)
90
+ ret = self.instance.remove_route(subnet, mask, comm)
91
+ if ret && comm.respond_to?(:routes) && comm.routes.kind_of?(Array)
92
+ comm.routes.delete "#{subnet}/#{mask}"
93
+ end
94
+ ret
95
+ end
96
+
97
+ #
98
+ # Flush all the routes from the switch board routing table.
99
+ #
100
+ def self.flush_routes
101
+ ret = self.instance.flush_routes
102
+ end
103
+
104
+ #
105
+ # Enumerate each route in the routing table.
106
+ #
107
+ def self.each(&block)
108
+ self.instance.each(&block)
109
+ end
110
+
111
+ #
112
+ # Returns the array of routes.
113
+ #
114
+ def self.routes
115
+ self.instance.routes
116
+ end
117
+
118
+ def self.route_exists?(subnet, mask)
119
+ self.instance.route_exists?(subnet, mask)
120
+ end
121
+
122
+ #
123
+ # Returns the Comm instance that should be used for the supplied address.
124
+ # If no comm can be found, the default Local Comm is returned.
125
+ #
126
+ def self.best_comm(addr)
127
+ self.instance.best_comm(addr)
128
+ end
129
+
130
+ #
131
+ # Removes all routes that go through the supplied Comm.
132
+ #
133
+ def self.remove_by_comm(comm)
134
+ self.instance.remove_by_comm(comm)
135
+ end
136
+
137
+ ##
138
+ #
139
+ # Instance methods
140
+ #
141
+ ##
142
+
143
+ #
144
+ # Adds a route for a given subnet and netmask destined through a given comm
145
+ # instance.
146
+ #
147
+ def add_route(subnet, mask, comm)
148
+ # If a bitmask was supplied, convert it.
149
+ netmask = (mask.to_s =~ /^\d+$/) ? Rex::Socket.bit2netmask(mask.to_i) : mask
150
+ rv = true
151
+
152
+ _init
153
+
154
+ mutex.synchronize {
155
+ # If the route already exists, return false to the caller.
156
+ if (route_exists?(subnet, netmask) == false)
157
+ self.routes << Route.new(subnet, netmask, comm)
158
+ else
159
+ rv = false
160
+ end
161
+ }
162
+
163
+ rv
164
+ end
165
+
166
+ #
167
+ # Removes a route for a given subnet and netmask destined through a given
168
+ # comm instance.
169
+ #
170
+ def remove_route(subnet, mask, comm)
171
+ # If a bitmask was supplied, convert it.
172
+ netmask = (mask.to_s =~ /^\d+$/) ? Rex::Socket.bit2netmask(mask.to_i) : mask
173
+ rv = false
174
+
175
+ _init
176
+
177
+ mutex.synchronize {
178
+ self.routes.delete_if { |route|
179
+ if (route.subnet == subnet and route.netmask == netmask and route.comm == comm)
180
+ rv = true
181
+ else
182
+ false
183
+ end
184
+ }
185
+ }
186
+
187
+ rv
188
+ end
189
+
190
+ #
191
+ # Flushes all established routes.
192
+ #
193
+ def flush_routes
194
+ _init
195
+
196
+ # Remove each of the individual routes so the comms don't think they're
197
+ # still routing after a flush.
198
+ self.routes.each { |r|
199
+ if r.comm.respond_to? :routes
200
+ r.comm.routes.delete("#{r.subnet}/#{r.netmask}")
201
+ end
202
+ }
203
+ # Re-initialize to an empty array
204
+ self.routes = Array.new
205
+ end
206
+
207
+ #
208
+ # Checks to see if a route already exists for the supplied subnet and
209
+ # netmask.
210
+ #
211
+ def route_exists?(subnet, netmask)
212
+ each { |route|
213
+ return true if (route.subnet == subnet and route.netmask == netmask)
214
+ }
215
+
216
+ false
217
+ end
218
+
219
+ #
220
+ # Enumerates each entry in the routing table.
221
+ #
222
+ def each(&block)
223
+ _init
224
+
225
+ routes.each(&block)
226
+ end
227
+
228
+ #
229
+ # Finds the best possible comm for the supplied target address.
230
+ #
231
+ def best_comm(addr)
232
+
233
+ addr_nbo = Socket.resolv_nbo_i(addr)
234
+ comm = nil
235
+ msb = 0
236
+
237
+ each { |route|
238
+ if ((route.subnet_nbo & route.netmask_nbo) ==
239
+ (addr_nbo & route.netmask_nbo))
240
+ if (route.bitmask >= msb)
241
+ comm = route.comm
242
+ msb = route.bitmask
243
+ end
244
+ end
245
+ }
246
+
247
+ comm
248
+ end
249
+
250
+ #
251
+ # Remove all routes that go through the supplied comm.
252
+ #
253
+ def remove_by_comm(comm)
254
+ _init
255
+ mutex.synchronize {
256
+ routes.delete_if { |route|
257
+ route.comm == comm
258
+ }
259
+ }
260
+ end
261
+
262
+ #
263
+ # The routes array.
264
+ #
265
+ attr_reader :routes
266
+ #
267
+ # The mutex protecting the routes array.
268
+ #
269
+ attr_reader :mutex
270
+
271
+ protected
272
+
273
+ attr_writer :routes, :mutex # :nodoc:
274
+
275
+ #
276
+ # Initializes the underlying stuff.
277
+ #
278
+ def _init
279
+ if (@_initialized != true)
280
+ @_initialized = true
281
+ self.routes = Array.new
282
+ self.mutex = Mutex.new
283
+ end
284
+ end
285
+
286
+ end
287
+
288
+ end
289
+ end
@@ -0,0 +1,79 @@
1
+ # -*- coding: binary -*-
2
+ require 'ssl_scan/socket'
3
+ require 'ssl_scan/io/stream'
4
+
5
+ ###
6
+ #
7
+ # This class provides methods for interacting with a TCP client connection.
8
+ #
9
+ ###
10
+ module SSLScan::Socket::Tcp
11
+
12
+ include SSLScan::Socket
13
+ include SSLScan::IO::Stream
14
+
15
+ ##
16
+ #
17
+ # Factory
18
+ #
19
+ ##
20
+
21
+ #
22
+ # Creates the client using the supplied hash.
23
+ #
24
+ # @see create_param
25
+ # @see SSLScan::Socket::Parameters.from_hash
26
+ def self.create(hash = {})
27
+ hash['Proto'] = 'tcp'
28
+ self.create_param(SSLScan::Socket::Parameters.from_hash(hash))
29
+ end
30
+
31
+ #
32
+ # Wrapper around the base socket class' creation method that automatically
33
+ # sets the parameter's protocol to TCP.
34
+ #
35
+ def self.create_param(param)
36
+ param.proto = 'tcp'
37
+ SSLScan::Socket.create_param(param)
38
+ end
39
+
40
+ ##
41
+ #
42
+ # Stream mixin implementations
43
+ #
44
+ ##
45
+
46
+ #
47
+ # Calls shutdown on the TCP connection.
48
+ #
49
+ def shutdown(how = ::Socket::SHUT_RDWR)
50
+ begin
51
+ return (super(how) == 0)
52
+ rescue ::Exception
53
+ end
54
+ end
55
+
56
+ #
57
+ # Returns peer information (host + port) in host:port format.
58
+ #
59
+ def peerinfo
60
+ if (pi = getpeername)
61
+ return pi[1] + ':' + pi[2].to_s
62
+ end
63
+ end
64
+
65
+ #
66
+ # Returns local information (host + port) in host:port format.
67
+ #
68
+ def localinfo
69
+ if (pi = getlocalname)
70
+ return pi[1] + ':' + pi[2].to_s
71
+ end
72
+ end
73
+
74
+ # returns socket type
75
+ def type?
76
+ return 'tcp'
77
+ end
78
+
79
+ end
@@ -0,0 +1,67 @@
1
+ # -*- coding: binary -*-
2
+ require 'ssl_scan/socket'
3
+ require 'ssl_scan/socket/tcp'
4
+ require 'ssl_scan/io/stream_server'
5
+
6
+ ###
7
+ #
8
+ # This class provides methods for interacting with a TCP server. It
9
+ # implements the SSLScan::IO::StreamServer interface.
10
+ #
11
+ ###
12
+ module SSLScan::Socket::TcpServer
13
+
14
+ include SSLScan::Socket
15
+ include SSLScan::IO::StreamServer
16
+
17
+ ##
18
+ #
19
+ # Factory
20
+ #
21
+ ##
22
+
23
+ #
24
+ # Creates the server using the supplied hash.
25
+ #
26
+ def self.create(hash = {})
27
+ hash['Proto'] = 'tcp'
28
+ hash['Server'] = true
29
+ self.create_param(SSLScan::Socket::Parameters.from_hash(hash))
30
+ end
31
+
32
+ #
33
+ # Wrapper around the base class' creation method that automatically sets
34
+ # the parameter's protocol to TCP and sets the server flag to true.
35
+ #
36
+ def self.create_param(param)
37
+ param.proto = 'tcp'
38
+ param.server = true
39
+ SSLScan::Socket.create_param(param)
40
+ end
41
+
42
+ #
43
+ # Accepts a child connection.
44
+ #
45
+ def accept(opts = {})
46
+ t = super()
47
+
48
+ # jRuby compatibility
49
+ if t.respond_to?('[]')
50
+ t = t[0]
51
+ end
52
+
53
+ if (t)
54
+ t.extend(SSLScan::Socket::Tcp)
55
+ t.context = self.context
56
+
57
+ pn = t.getpeername
58
+
59
+ t.peerhost = pn[1]
60
+ t.peerport = pn[2]
61
+ end
62
+
63
+ t
64
+ end
65
+
66
+ end
67
+
@@ -0,0 +1,165 @@
1
+ # -*- coding: binary -*-
2
+ require 'ssl_scan/socket'
3
+
4
+ ###
5
+ #
6
+ # This class provides methods for interacting with a UDP socket.
7
+ #
8
+ ###
9
+ module SSLScan::Socket::Udp
10
+
11
+ include SSLScan::Socket
12
+
13
+ ##
14
+ #
15
+ # Factory
16
+ #
17
+ ##
18
+
19
+ #
20
+ # Creates the client using the supplied hash.
21
+ #
22
+ def self.create(hash = {})
23
+ hash['Proto'] = 'udp'
24
+ # If we have are to bind to a LocalHost we must be a Server to avail of pivoting.
25
+ # SSLScan::Socket::Parameters will subsequently turn off the sever flag after the correct
26
+ # comm has been chosen.
27
+ if( hash['LocalHost'] )
28
+ hash['Server'] = true
29
+ end
30
+ self.create_param(SSLScan::Socket::Parameters.from_hash(hash))
31
+ end
32
+
33
+ #
34
+ # Wrapper around the base socket class' creation method that automatically
35
+ # sets the parameter's protocol to UDP.
36
+ #
37
+ def self.create_param(param)
38
+ param.proto = 'udp'
39
+ SSLScan::Socket.create_param(param)
40
+ end
41
+
42
+ ##
43
+ #
44
+ # UDP connected state methods
45
+ #
46
+ ##
47
+
48
+ #
49
+ # Write the supplied datagram to the connected UDP socket.
50
+ #
51
+ def write(gram)
52
+ begin
53
+ return syswrite(gram)
54
+ rescue ::Errno::EHOSTUNREACH,::Errno::ENETDOWN,::Errno::ENETUNREACH,::Errno::ENETRESET,::Errno::EHOSTDOWN,::Errno::EACCES,::Errno::EINVAL,::Errno::EADDRNOTAVAIL
55
+ return nil
56
+ end
57
+ end
58
+
59
+ alias put write
60
+
61
+ #
62
+ # Read a datagram from the UDP socket.
63
+ #
64
+ def read(length = 65535)
65
+ if length < 0
66
+ length = 65535
67
+ end
68
+ return sysread(length)
69
+ end
70
+
71
+ #
72
+ # Read a datagram from the UDP socket with a timeout
73
+ #
74
+ def timed_read(length = 65535, timeout=def_read_timeout)
75
+ begin
76
+ if ((rv = ::IO.select([ fd ], nil, nil, timeout)) and
77
+ (rv[0]) and (rv[0][0] == fd)
78
+ )
79
+ return read(length)
80
+ else
81
+ return ''
82
+ end
83
+ rescue Exception
84
+ return ''
85
+ end
86
+ end
87
+
88
+ #alias send write
89
+ #alias recv read
90
+
91
+ ##
92
+ #
93
+ # UDP non-connected state methods
94
+ #
95
+ ##
96
+
97
+ #
98
+ # Sends a datagram to the supplied host:port with optional flags.
99
+ #
100
+ def sendto(gram, peerhost, peerport, flags = 0)
101
+
102
+ # Catch unconnected IPv6 sockets talking to IPv4 addresses
103
+ peer = SSLScan::Socket.resolv_nbo(peerhost)
104
+ if (peer.length == 4 and self.ipv == 6)
105
+ peerhost = SSLScan::Socket.getaddress(peerhost, true)
106
+ if peerhost[0,7].downcase != '::ffff:'
107
+ peerhost = '::ffff:' + peerhost
108
+ end
109
+ end
110
+
111
+ begin
112
+ send(gram, flags, SSLScan::Socket.to_sockaddr(peerhost, peerport))
113
+ rescue ::Errno::EHOSTUNREACH,::Errno::ENETDOWN,::Errno::ENETUNREACH,::Errno::ENETRESET,::Errno::EHOSTDOWN,::Errno::EACCES,::Errno::EINVAL,::Errno::EADDRNOTAVAIL
114
+ return nil
115
+ end
116
+
117
+ end
118
+
119
+ #
120
+ # Receives a datagram and returns the data and host:port of the requestor
121
+ # as [ data, host, port ].
122
+ #
123
+ def recvfrom(length = 65535, timeout=def_read_timeout)
124
+
125
+ begin
126
+ if ((rv = ::IO.select([ fd ], nil, nil, timeout)) and
127
+ (rv[0]) and (rv[0][0] == fd)
128
+ )
129
+ data, saddr = recvfrom_nonblock(length)
130
+ af, host, port = SSLScan::Socket.from_sockaddr(saddr)
131
+
132
+ return [ data, host, port ]
133
+ else
134
+ return [ '', nil, nil ]
135
+ end
136
+ rescue ::Timeout::Error
137
+ return [ '', nil, nil ]
138
+ rescue ::Interrupt
139
+ raise $!
140
+ rescue ::Exception
141
+ return [ '', nil, nil ]
142
+ end
143
+ end
144
+
145
+ #
146
+ # Calls recvfrom and only returns the data
147
+ #
148
+ def get(timeout=nil)
149
+ data, saddr, sport = recvfrom(65535, timeout)
150
+ return data
151
+ end
152
+
153
+ #
154
+ # The default number of seconds to wait for a read operation to timeout.
155
+ #
156
+ def def_read_timeout
157
+ 10
158
+ end
159
+
160
+ def type?
161
+ return 'udp'
162
+ end
163
+
164
+ end
165
+