ssl_scan 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+