firescan 0.07
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.
- data/LICENSE.txt +202 -0
- data/README.txt +37 -0
- data/USAGE.txt +43 -0
- data/VERSION.txt +4 -0
- data/bin/firescan +4 -0
- data/build +7 -0
- data/doc/Example.html +224 -0
- data/doc/Firebind.html +213 -0
- data/doc/Firebind/Client.html +750 -0
- data/doc/Firebind/Portspec.html +390 -0
- data/doc/Firebind/Scan.html +413 -0
- data/doc/Firebind/ScanError.html +277 -0
- data/doc/Firebind/ScanState.html +1015 -0
- data/doc/Firebind/SimpleProtocol.html +292 -0
- data/doc/Firebind/TcpTransport.html +481 -0
- data/doc/Firebind/Transport.html +275 -0
- data/doc/Firebind/UdpTransport.html +472 -0
- data/doc/LICENSE_txt.html +323 -0
- data/doc/README_txt.html +171 -0
- data/doc/Runner.html +166 -0
- data/doc/TestPortspec.html +289 -0
- data/doc/Tools.html +321 -0
- data/doc/USAGE_txt.html +184 -0
- data/doc/VERSION_txt.html +126 -0
- data/doc/build.html +125 -0
- data/doc/created.rid +22 -0
- data/doc/doc/created_rid.html +121 -0
- data/doc/firescan_gemspec.html +140 -0
- data/doc/images/add.png +0 -0
- data/doc/images/arrow_up.png +0 -0
- data/doc/images/brick.png +0 -0
- data/doc/images/brick_link.png +0 -0
- data/doc/images/bug.png +0 -0
- data/doc/images/bullet_black.png +0 -0
- data/doc/images/bullet_toggle_minus.png +0 -0
- data/doc/images/bullet_toggle_plus.png +0 -0
- data/doc/images/date.png +0 -0
- data/doc/images/delete.png +0 -0
- data/doc/images/find.png +0 -0
- data/doc/images/loadingAnimation.gif +0 -0
- data/doc/images/macFFBgHack.png +0 -0
- data/doc/images/package.png +0 -0
- data/doc/images/page_green.png +0 -0
- data/doc/images/page_white_text.png +0 -0
- data/doc/images/page_white_width.png +0 -0
- data/doc/images/plugin.png +0 -0
- data/doc/images/ruby.png +0 -0
- data/doc/images/tag_blue.png +0 -0
- data/doc/images/tag_green.png +0 -0
- data/doc/images/transparent.png +0 -0
- data/doc/images/wrench.png +0 -0
- data/doc/images/wrench_orange.png +0 -0
- data/doc/images/zoom.png +0 -0
- data/doc/index.html +118 -0
- data/doc/js/darkfish.js +155 -0
- data/doc/js/jquery.js +18 -0
- data/doc/js/navigation.js +142 -0
- data/doc/js/search.js +94 -0
- data/doc/js/search_index.js +1 -0
- data/doc/js/searcher.js +228 -0
- data/doc/rdoc.css +595 -0
- data/doc/table_of_contents.html +230 -0
- data/firescan.gemspec +18 -0
- data/lib/example.rb +20 -0
- data/lib/firebind/client.rb +308 -0
- data/lib/firebind/portspec.rb +107 -0
- data/lib/firebind/scan.rb +288 -0
- data/lib/firebind/scan_error.rb +32 -0
- data/lib/firebind/scan_state.rb +140 -0
- data/lib/firebind/simple_protocol.rb +59 -0
- data/lib/firebind/tcp_transport.rb +184 -0
- data/lib/firebind/tools.rb +107 -0
- data/lib/firebind/transport.rb +44 -0
- data/lib/firebind/udp_transport.rb +174 -0
- data/test/portspec_test.rb +53 -0
- data/test/runner.rb +7 -0
- metadata +136 -0
@@ -0,0 +1,107 @@
|
|
1
|
+
# Firebind -- Path Scan Client Software
|
2
|
+
# Copyright (C) 2013 Firebind Inc. All rights reserved.
|
3
|
+
# Authors - Jay Houghton
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
6
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
7
|
+
# the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
13
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
14
|
+
# License for the specific language governing permissions and limitations under
|
15
|
+
# the License.
|
16
|
+
|
17
|
+
module Firebind
|
18
|
+
|
19
|
+
# This data structure encapsulates the properties and operations of a port list. Arbitrary lists of comma separated
|
20
|
+
# and dashed-ranges can be converted into a full array of ports for a list.
|
21
|
+
# This class will eventually require the full complement of set arithmetic
|
22
|
+
class Portspec
|
23
|
+
|
24
|
+
attr_reader :ports, :compiled_list
|
25
|
+
|
26
|
+
# Supply either a string or int array
|
27
|
+
# examples: 1,2,3,55,10-20 or [56,34,443,25,6000]
|
28
|
+
def initialize(port_list)
|
29
|
+
|
30
|
+
port_map = Hash.new
|
31
|
+
if port_list.kind_of?(Array) # numeric array, possible dups and out of range values
|
32
|
+
port_list.each do |port|
|
33
|
+
port_map[port] = port
|
34
|
+
end
|
35
|
+
|
36
|
+
elsif port_list.kind_of?(String) # comma and dash port list, possible dups and out of range values
|
37
|
+
#validate
|
38
|
+
if port_list !~ /^[0-9,\-]+$/
|
39
|
+
raise ArgumentError, 'Bad port specification '+port_list, caller
|
40
|
+
end
|
41
|
+
port_list.split(/\s*,\s*/).each do |part|
|
42
|
+
if part =~ /[\-]+/ # is this a range?
|
43
|
+
first,last = part.split(/\-/)
|
44
|
+
#noinspection RubyForLoopInspection
|
45
|
+
for port in first.gsub(/[^0-9]/,'').to_i..last.gsub(/[^0-9]/,'').to_i
|
46
|
+
port_map[port] = port
|
47
|
+
end
|
48
|
+
else
|
49
|
+
port = part.gsub(/[^0-9]/,'').to_i
|
50
|
+
port_map[port] = port
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# sort the map and insert the expanded port list into our @ports array
|
56
|
+
@ports = Array.new
|
57
|
+
i = 0
|
58
|
+
port_map.sort_by {|number,flag|number}.each do |port,flag|
|
59
|
+
if port < 1 or port > 65535
|
60
|
+
raise ArgumentError, 'Bad port number '+port.to_s, caller
|
61
|
+
end
|
62
|
+
@ports[i] = port
|
63
|
+
i += 1
|
64
|
+
end
|
65
|
+
|
66
|
+
# generate a compiled port specification based on the ordered list in array
|
67
|
+
last_port = -1
|
68
|
+
building_a_range = false
|
69
|
+
@compiled_list = ''
|
70
|
+
@ports.each_with_index do |port,index|
|
71
|
+
if port == (last_port+1)
|
72
|
+
# continue building range
|
73
|
+
building_a_range = true
|
74
|
+
# are we at the end of the array? if so we're not coming back here...
|
75
|
+
if index == @ports.length-1
|
76
|
+
@compiled_list += '-' + port.to_s
|
77
|
+
end
|
78
|
+
else
|
79
|
+
if building_a_range
|
80
|
+
# end of the range
|
81
|
+
@compiled_list += '-' + last_port.to_s + ',' + port.to_s
|
82
|
+
building_a_range = false
|
83
|
+
else
|
84
|
+
@compiled_list += ',' unless @compiled_list.length == 0
|
85
|
+
@compiled_list += port.to_s
|
86
|
+
end
|
87
|
+
end
|
88
|
+
last_port = port
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def to_s
|
93
|
+
@compiled_list
|
94
|
+
end
|
95
|
+
|
96
|
+
def size
|
97
|
+
@ports.length
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
#ports = '6,5,4445,4,3,2,50-60,666,69,55,65534,65533'
|
103
|
+
#ps = Firebind::Portspec.new(ports)
|
104
|
+
#puts ports + " ==> " + ps.to_s
|
105
|
+
|
106
|
+
end
|
107
|
+
|
@@ -0,0 +1,288 @@
|
|
1
|
+
# Firebind -- Path Scan Client Software
|
2
|
+
# Copyright (C) 2013 Firebind Inc. All rights reserved.
|
3
|
+
# Authors - Jay Houghton
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
6
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
7
|
+
# the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
13
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
14
|
+
# License for the specific language governing permissions and limitations under
|
15
|
+
# the License.
|
16
|
+
|
17
|
+
require 'net/http'
|
18
|
+
require 'uri'
|
19
|
+
require 'json'
|
20
|
+
require 'observer'
|
21
|
+
require_relative 'simple_protocol'
|
22
|
+
require_relative 'portspec'
|
23
|
+
require_relative 'tools'
|
24
|
+
require_relative 'scan_state'
|
25
|
+
|
26
|
+
# This module encapsulates client-side path scanning functionality for use with an associated Firebind server.
|
27
|
+
module Firebind
|
28
|
+
|
29
|
+
|
30
|
+
# This is the primary API object for performing scans. Simply supply the necessary arguments to create a Scan
|
31
|
+
# and call the scan() method
|
32
|
+
#--
|
33
|
+
#noinspection RubyTooManyInstanceVariablesInspection
|
34
|
+
class Scan
|
35
|
+
include Observable
|
36
|
+
include Tools
|
37
|
+
|
38
|
+
# Create a new Scan
|
39
|
+
#
|
40
|
+
#--
|
41
|
+
# @param [Object] command_server
|
42
|
+
# @param [Object] ports
|
43
|
+
def initialize (command_server, ports, transport, timeout=5000, protocol=:SimpleProtocol, username=NIL, password=NIL)
|
44
|
+
@command_server = command_server
|
45
|
+
@portspec = Firebind::Portspec.new(ports)
|
46
|
+
@timeout = timeout
|
47
|
+
@protocol = protocol
|
48
|
+
@username = username
|
49
|
+
@password = password
|
50
|
+
@transport = transport
|
51
|
+
@done = false
|
52
|
+
@state = ScanState.new(command_server,protocol,transport,@portspec,timeout)
|
53
|
+
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
# Perform the path scan
|
58
|
+
#
|
59
|
+
# :call-seq:
|
60
|
+
# scan -> ScanState
|
61
|
+
#
|
62
|
+
def scan
|
63
|
+
|
64
|
+
api_start
|
65
|
+
changed
|
66
|
+
notify_observers(@state)
|
67
|
+
|
68
|
+
if @done
|
69
|
+
return @state
|
70
|
+
end
|
71
|
+
|
72
|
+
case @protocol
|
73
|
+
when :SimpleProtocol
|
74
|
+
scan_protocol = SimpleProtocol.new(@state.guid,@state.echo_server,@state.transport,@timeout)
|
75
|
+
|
76
|
+
else
|
77
|
+
scan_protocol = SimpleProtocol.new(@state.guid,@state.echo_server,@state.transport,@timeout)
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
@portspec.ports.each do |port|
|
82
|
+
break if @done
|
83
|
+
begin
|
84
|
+
|
85
|
+
if @state.ports_scanned > 0
|
86
|
+
# make sure we don't fry the routers
|
87
|
+
debug("waiting #{@state.port_delay_seconds}s for next port echo")
|
88
|
+
IO.select(nil,nil,nil,@state.port_delay_seconds)
|
89
|
+
end
|
90
|
+
|
91
|
+
# callback for port start
|
92
|
+
@state.on_port_start(port)
|
93
|
+
changed
|
94
|
+
notify_observers(@state)
|
95
|
+
|
96
|
+
# perform the path echo send/receive
|
97
|
+
scan_protocol.echo(port)
|
98
|
+
port_result_code = $result_codes[:SUCCESS]
|
99
|
+
|
100
|
+
rescue Firebind::ScanError => error
|
101
|
+
debug "error on port #{port} #{error.to_s}"
|
102
|
+
case error.status_code
|
103
|
+
when :HANDSHAKE_CONNECTION_TIME_OUT,
|
104
|
+
:HANDSHAKE_CONNECTION_INITIATION_FAILURE,
|
105
|
+
:HANDSHAKE_CONNECTION_REFUSED,
|
106
|
+
:HANDSHAKE_CONNECTION_COMPLETION_FAILURE,
|
107
|
+
:PAYLOAD_REFUSED_ON_RECV,
|
108
|
+
:PAYLOAD_TIMED_OUT_ON_RECV,
|
109
|
+
:PAYLOAD_ERROR_ON_RECV,
|
110
|
+
:PAYLOAD_MISMATCH_ON_RECV,
|
111
|
+
:FAILURE_ON_PAYLOAD_SEND
|
112
|
+
|
113
|
+
# try skipping
|
114
|
+
port_result_code = $result_codes[error.status_code]
|
115
|
+
if api_skip port
|
116
|
+
|
117
|
+
else
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
else # status_code is not skippable
|
122
|
+
@state.on_error(error.status_code)
|
123
|
+
changed
|
124
|
+
notify_observers(@state)
|
125
|
+
raise error
|
126
|
+
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
ensure
|
131
|
+
# callback for port complete - success/open
|
132
|
+
@state.on_port_complete(port,port_result_code)
|
133
|
+
changed
|
134
|
+
notify_observers(@state)
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
api_update
|
140
|
+
|
141
|
+
if @portspec.size == @state.ports_scanned
|
142
|
+
@state.on_scan_complete($client_scan_completed)
|
143
|
+
changed
|
144
|
+
notify_observers(@state)
|
145
|
+
end
|
146
|
+
|
147
|
+
#update
|
148
|
+
@state
|
149
|
+
end
|
150
|
+
|
151
|
+
def stop
|
152
|
+
puts 'setting flags'
|
153
|
+
@stop_requested = true
|
154
|
+
@done = true
|
155
|
+
api_stop
|
156
|
+
api_update
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
160
|
+
|
161
|
+
# perform an Identify API call to the server, for authentication testing
|
162
|
+
def api_identify
|
163
|
+
uri = URI.parse("http://#{@command_server}/api/user")
|
164
|
+
http = Net::HTTP.new(uri.host, uri.port) # create http client
|
165
|
+
request = Net::HTTP::Head.new(uri.request_uri) # create request object
|
166
|
+
request.basic_auth(@username, @password)
|
167
|
+
|
168
|
+
begin
|
169
|
+
response = http.request(request)
|
170
|
+
rescue
|
171
|
+
debug "Identify API call failed #{$!}"
|
172
|
+
return false
|
173
|
+
end
|
174
|
+
|
175
|
+
'1001' == response['status']
|
176
|
+
end
|
177
|
+
|
178
|
+
# perform a Scan API call to the server to initiate a path scan sequence
|
179
|
+
def api_start
|
180
|
+
uri = URI.parse("http://#{@command_server}/api/scan")
|
181
|
+
http = Net::HTTP.new(uri.host, uri.port) # create http client
|
182
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
183
|
+
request.basic_auth(@username, @password)
|
184
|
+
|
185
|
+
transport_proto = if @transport == :UDP then 'udp' else 'tcp' end
|
186
|
+
|
187
|
+
data = {portSpec:@portspec.to_s,protocol:transport_proto}
|
188
|
+
request.body = data.to_json
|
189
|
+
|
190
|
+
#noinspection RubyStringKeysInHashInspection
|
191
|
+
#request.set_form_data({'portSpec' => @portspec.to_s, 'protocol' => 'TCP'})
|
192
|
+
|
193
|
+
begin
|
194
|
+
response = http.request(request)
|
195
|
+
rescue # can't connect
|
196
|
+
@state.on_start_failure($command_server_unavailable)
|
197
|
+
@state.message = @command_server
|
198
|
+
@done = true
|
199
|
+
return
|
200
|
+
end
|
201
|
+
|
202
|
+
result = JSON.parse response.body
|
203
|
+
if 2000 == result['status']
|
204
|
+
# we're ok to go
|
205
|
+
@state.on_scan_start(result['guid'],result['echoHost'],result['portDelay'])
|
206
|
+
else
|
207
|
+
@state.on_start_failure(result['status'])
|
208
|
+
@done = true
|
209
|
+
#raise ('scan request failed with status '+result['status'].to_s)
|
210
|
+
end
|
211
|
+
|
212
|
+
true
|
213
|
+
end
|
214
|
+
|
215
|
+
# perform a Skip API call to the server
|
216
|
+
def api_skip(port)
|
217
|
+
begin
|
218
|
+
uri = URI.parse("http://#{@command_server}/api/scan/#{@state.echo_server}/#{@state.guid.to_s}/#{port.to_s}")
|
219
|
+
http = Net::HTTP.new(uri.host, uri.port) # create http client
|
220
|
+
request = Net::HTTP::Patch.new(uri.request_uri)
|
221
|
+
request.basic_auth(@username, @password)
|
222
|
+
verbose "skipping port #{port}"
|
223
|
+
response = http.request(request)
|
224
|
+
if '5000' == response['status']
|
225
|
+
debug "successful skip for port #{port}"
|
226
|
+
true
|
227
|
+
else
|
228
|
+
debug "unsuccessful skip for port #{port} response was #{response['status']}"
|
229
|
+
false
|
230
|
+
end
|
231
|
+
rescue
|
232
|
+
debug "Skip API call failed with #{$!}"
|
233
|
+
false
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
# perform a Stop API call to the server
|
238
|
+
def api_stop
|
239
|
+
uri = URI.parse("http://#{@command_server}/api/scan/#{@state.echo_server}/#{@state.guid.to_s}")
|
240
|
+
debug "stopping scan with #{uri}"
|
241
|
+
http = Net::HTTP.new(uri.host, uri.port) # create http client
|
242
|
+
request = Net::HTTP::Delete.new(uri.request_uri)
|
243
|
+
request.basic_auth(@username, @password)
|
244
|
+
begin
|
245
|
+
response = http.request(request)
|
246
|
+
rescue
|
247
|
+
debug "Stop API call failed #{$!}"
|
248
|
+
return false
|
249
|
+
end
|
250
|
+
@state.on_scan_stop
|
251
|
+
'9000' == response['status']
|
252
|
+
end
|
253
|
+
|
254
|
+
# perform an Update API call to the server
|
255
|
+
def api_update
|
256
|
+
uri = URI.parse("http://#{@command_server}/api/scan/#{@state.echo_server}/#{@state.guid.to_s}")
|
257
|
+
http = Net::HTTP.new(uri.host, uri.port) # create http client
|
258
|
+
request = Net::HTTP::Put.new(uri.request_uri)
|
259
|
+
request.basic_auth(@username, @password)
|
260
|
+
|
261
|
+
data = Array.new
|
262
|
+
@state.result_map.each do |code,ports|
|
263
|
+
ps = Portspec.new(ports)
|
264
|
+
status = if code == $success then 'Passed' else 'Failed' end
|
265
|
+
data << { guid:@state.guid, serverId:@state.echo_server, portSpec:ps.to_s, statusCode:code, status:status}
|
266
|
+
end
|
267
|
+
|
268
|
+
test_status = if @state.current_state == :SCAN_COMPLETE then 'Success' else 'Failed' end
|
269
|
+
|
270
|
+
#build json payload with results
|
271
|
+
report = { clientReport: { guid:@state.guid, serverId:@state.echo_server, testStatus:test_status, uid:@username},
|
272
|
+
clientReportData: data }
|
273
|
+
#jj report
|
274
|
+
json = report.to_json
|
275
|
+
request.body = json
|
276
|
+
|
277
|
+
begin
|
278
|
+
response = http.request(request)
|
279
|
+
rescue
|
280
|
+
debug "Update API call failed #{$!}"
|
281
|
+
return false
|
282
|
+
end
|
283
|
+
|
284
|
+
'9000' == response['status']
|
285
|
+
end
|
286
|
+
|
287
|
+
end
|
288
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Firebind -- Path Scan Client Software
|
2
|
+
# Copyright (C) 2013 Firebind Inc. All rights reserved.
|
3
|
+
# Authors - Jay Houghton
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
6
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
7
|
+
# the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
13
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
14
|
+
# License for the specific language governing permissions and limitations under
|
15
|
+
# the License.
|
16
|
+
|
17
|
+
module Firebind
|
18
|
+
class ScanError < IOError
|
19
|
+
|
20
|
+
attr_reader :status_code
|
21
|
+
|
22
|
+
def initialize(status_code, error=nil)
|
23
|
+
@status_code = status_code
|
24
|
+
@error = error
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_s
|
28
|
+
"ScanError status_code:#{@status_code} cause:#{@error.to_s}"
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# Firebind -- Path Scan Client Software
|
2
|
+
# Copyright (C) 2013 Firebind Inc. All rights reserved.
|
3
|
+
# Authors - Jay Houghton
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
6
|
+
# use this file except in compliance with the License. You may obtain a copy of
|
7
|
+
# the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
13
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
14
|
+
# License for the specific language governing permissions and limitations under
|
15
|
+
# the License.
|
16
|
+
|
17
|
+
require_relative 'tools'
|
18
|
+
module Firebind
|
19
|
+
|
20
|
+
#
|
21
|
+
# Scan lifecycle states
|
22
|
+
# SCAN_SETUP
|
23
|
+
# SCAN_START
|
24
|
+
# PORT_START
|
25
|
+
# PORT_TICK
|
26
|
+
# PORT_COMPLETE
|
27
|
+
# ...
|
28
|
+
# SCAN_STOP or SCAN_COMPLETE or START_FAILURE or ERROR
|
29
|
+
#
|
30
|
+
#noinspection RubyTooManyInstanceVariablesInspection
|
31
|
+
class ScanState
|
32
|
+
include Tools
|
33
|
+
|
34
|
+
attr_reader :current_state, :guid, :echo_server, :protocol, :transport, :portspec, :port, :port_delay, :status_code,
|
35
|
+
:port_result_code, :ports_scanned, :last_duration, :result_map, :command_server, :timeout
|
36
|
+
attr_accessor :message
|
37
|
+
|
38
|
+
# @param [Firebind::Portspec] portspec
|
39
|
+
def initialize(command_server,protocol,transport,portspec,timeout)
|
40
|
+
@command_server = command_server
|
41
|
+
@current_state = :SCAN_SETUP
|
42
|
+
@protocol = protocol
|
43
|
+
@transport = transport
|
44
|
+
@portspec = portspec
|
45
|
+
@timeout = timeout
|
46
|
+
@guid = NIL
|
47
|
+
@echo_server = NIL
|
48
|
+
@port = 0
|
49
|
+
@last_duration = 0
|
50
|
+
@ports_scanned = 0
|
51
|
+
@result_map = Hash.new {|hash,key| hash[key]=[]} # block form
|
52
|
+
@message = NIL
|
53
|
+
end
|
54
|
+
|
55
|
+
def to_s
|
56
|
+
"#{@current_state.to_s} port #{@port} results #{@result_map}"
|
57
|
+
end
|
58
|
+
|
59
|
+
# lifecycle methods
|
60
|
+
def on_scan_start(guid,echo_server,port_delay)
|
61
|
+
@current_state = :SCAN_START
|
62
|
+
@guid = guid
|
63
|
+
@echo_server = echo_server
|
64
|
+
@port_delay = port_delay
|
65
|
+
end
|
66
|
+
|
67
|
+
def on_start_failure(status_code)
|
68
|
+
@current_state = :START_FAILURE
|
69
|
+
@status_code = status_code
|
70
|
+
end
|
71
|
+
|
72
|
+
def on_port_start(port)
|
73
|
+
@current_state = :PORT_START
|
74
|
+
@port = port
|
75
|
+
@port_start_time = Time.now
|
76
|
+
end
|
77
|
+
|
78
|
+
def on_port_tick
|
79
|
+
@current_state = :PORT_TICK
|
80
|
+
end
|
81
|
+
|
82
|
+
# @param [Object] port
|
83
|
+
def on_port_complete(port,port_result_code)
|
84
|
+
@port_end_time = Time.now
|
85
|
+
@current_state = :PORT_COMPLETE
|
86
|
+
@port = port
|
87
|
+
@port_result_code = port_result_code
|
88
|
+
@ports_scanned += 1
|
89
|
+
@result_map[port_result_code] << port
|
90
|
+
end
|
91
|
+
|
92
|
+
def on_scan_complete(status_code)
|
93
|
+
@current_state = :SCAN_COMPLETE
|
94
|
+
@status_code = status_code
|
95
|
+
end
|
96
|
+
|
97
|
+
def on_scan_stop
|
98
|
+
@current_state = :SCAN_STOPPED
|
99
|
+
end
|
100
|
+
|
101
|
+
def on_error(status_code)
|
102
|
+
@current_state = :ERROR
|
103
|
+
@status_code = status_code
|
104
|
+
end
|
105
|
+
|
106
|
+
# data methods
|
107
|
+
def port_duration
|
108
|
+
(((@port_end_time - @port_start_time) * 1000)+0.5).to_i
|
109
|
+
end
|
110
|
+
|
111
|
+
def percent_complete
|
112
|
+
((@ports_scanned.to_f / @portspec.size.to_f) * 100).to_i
|
113
|
+
end
|
114
|
+
|
115
|
+
# return a Portspec of the open ports for this scan
|
116
|
+
def open_ports
|
117
|
+
Portspec.new(@result_map[$success])
|
118
|
+
end
|
119
|
+
|
120
|
+
# return a Portspec of the closed ports for this scan
|
121
|
+
def closed_ports
|
122
|
+
closed = Array.new
|
123
|
+
@result_map.each do |code,ports|
|
124
|
+
closed += ports unless code == $success
|
125
|
+
end
|
126
|
+
Portspec.new(closed)
|
127
|
+
end
|
128
|
+
|
129
|
+
def port_delay_seconds
|
130
|
+
@port_delay.to_f / 1000
|
131
|
+
end
|
132
|
+
|
133
|
+
def description(port_result_code)
|
134
|
+
$result_code_messages[port_result_code]
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|