watobo 0.9.9.pre3 → 0.9.9
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +24 -0
- data/CHANGELOG +17 -7
- data/README +4 -60
- data/bin/nfq_server.rb +191 -0
- data/config/interceptor.yml +2 -6
- data/lib/watobo/adapters/data_store.rb +1 -1
- data/lib/watobo/adapters/file/file_store.rb +50 -33
- data/lib/watobo/ca.rb +22 -0
- data/lib/watobo/config.rb +6 -0
- data/lib/watobo/core/ca.rb +411 -0
- data/lib/watobo/core/cert_store.rb +56 -0
- data/lib/watobo/core/forwarding_proxy.rb +38 -0
- data/lib/watobo/core/http_socket.rb +18 -0
- data/lib/watobo/core/intercept_carver.rb +179 -0
- data/lib/watobo/core/intercept_filter.rb +257 -0
- data/lib/watobo/core/interceptor.rb +342 -79
- data/lib/watobo/core/netfilter_queue.rb +191 -0
- data/lib/watobo/core/project.rb +84 -138
- data/lib/watobo/core/proxy.rb +61 -0
- data/lib/watobo/core/request.rb +40 -0
- data/lib/watobo/core/response.rb +30 -0
- data/lib/watobo/core/scanner.rb +64 -58
- data/lib/watobo/core/session.rb +70 -77
- data/lib/watobo/core.rb +1 -1
- data/lib/watobo/framework/create_project.rb +25 -10
- data/lib/watobo/framework/init.rb +13 -0
- data/lib/watobo/gui/browser_preview.rb +5 -4
- data/lib/watobo/gui/checks_policy_frame.rb +1 -0
- data/lib/watobo/gui/client_cert_dialog.rb +11 -6
- data/lib/watobo/gui/conversation_table.rb +7 -4
- data/lib/watobo/gui/fuzzer_gui.rb +9 -11
- data/lib/watobo/gui/intercept_filter_dialog.rb +210 -0
- data/lib/watobo/gui/interceptor_gui.rb +59 -21
- data/lib/watobo/gui/interceptor_settings_dialog.rb +39 -5
- data/lib/watobo/gui/list_box.rb +2 -1
- data/lib/watobo/gui/log_viewer.rb +79 -5
- data/lib/watobo/gui/main_window.rb +159 -113
- data/lib/watobo/gui/manual_request_editor.rb +11 -5
- data/lib/watobo/gui/mixins/subscriber.rb +47 -0
- data/lib/watobo/gui/project_wizzard.rb +3 -3
- data/lib/watobo/gui/proxy_dialog.rb +17 -18
- data/lib/watobo/gui/request_editor.rb +1 -1
- data/lib/watobo/gui/rewrite_filters_dialog.rb +416 -0
- data/lib/watobo/gui/rewrite_rules_dialog.rb +394 -0
- data/lib/watobo/gui/scanner_settings_dialog.rb +9 -6
- data/lib/watobo/gui/session_management_dialog.rb +33 -23
- data/lib/watobo/gui/sites_tree.rb +5 -6
- data/lib/watobo/gui/status_bar.rb +101 -49
- data/lib/watobo/gui/table_editor.rb +1 -1
- data/lib/watobo/gui/templates/plugin2.rb +23 -27
- data/lib/watobo/gui/utils/save_default_settings.rb +9 -9
- data/lib/watobo/gui/utils/save_proxy_settings.rb +25 -9
- data/lib/watobo/gui/utils/save_scanner_settings.rb +10 -7
- data/lib/watobo/gui/utils/session_history.rb +1 -1
- data/lib/watobo/gui/www_auth_dialog.rb +25 -21
- data/lib/watobo/gui.rb +3 -1
- data/lib/watobo/mixins/httpparser.rb +47 -40
- data/lib/watobo/mixins/request_parser.rb +126 -41
- data/lib/watobo/mixins/shapers.rb +124 -15
- data/lib/watobo/utils/hexprint.rb +31 -0
- data/lib/watobo/utils/load_chat.rb +2 -0
- data/lib/watobo/utils/response_builder.rb +111 -0
- data/lib/watobo.rb +4 -1
- data/modules/active/discovery/http_methods.rb +6 -4
- data/modules/active/fileinclusion/lfi_simple.rb +3 -3
- data/modules/active/sqlinjection/sqli_timing.rb +6 -6
- data/modules/passive/redirectionz.rb +5 -6
- data/plugins/catalog/catalog.rb +240 -56
- data/plugins/catalog/db_tests +1 -6483
- data/plugins/catalog/db_variables +2 -29
- data/plugins/crawler/gui/auth_frame.rb +15 -3
- data/plugins/crawler/gui/crawler_gui.rb +24 -0
- data/plugins/crawler/gui/hooks_frame.rb +7 -2
- data/plugins/crawler/gui/settings_tabbook.rb +4 -0
- data/plugins/crawler/gui.rb +3 -3
- data/plugins/crawler/lib/engine.rb +1 -1
- data/plugins/filefinder/filefinder.rb +21 -17
- data/plugins/sqlmap/bin/test.rb +100 -0
- data/plugins/sqlmap/gui/main.rb +227 -0
- data/plugins/sqlmap/gui/options_frame.rb +119 -0
- data/plugins/sqlmap/gui.rb +27 -0
- data/plugins/sqlmap/icons/sqlmap.ico +0 -0
- data/plugins/sqlmap/lib/sqlmap_ctrl.rb +116 -0
- data/plugins/sqlmap/sqlmap.rb +26 -0
- data/plugins/sslchecker/gui/gui.rb +45 -30
- metadata +32 -9
- data/certificates/cert.pem +0 -19
- data/certificates/privkey.pem +0 -15
- data/certificates/watobo_dh.key +0 -5
- data/lib/watobo/core/simple_ca.rb +0 -393
@@ -20,27 +20,124 @@
|
|
20
20
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
21
21
|
# .
|
22
22
|
module Watobo
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
module Interceptor
|
24
|
+
INTERCEPT_NONE = 0x00
|
25
|
+
INTERCEPT_REQUEST = 0x01
|
26
|
+
INTERCEPT_RESPONSE = 0x02
|
27
|
+
INTERCEPT_BOTH = 0x03
|
28
|
+
|
29
|
+
REWRITE_NONE = 0x00
|
30
|
+
REWRITE_REQUEST = 0x01
|
31
|
+
REWRITE_RESPONSE = 0x02
|
32
|
+
REWRITE_BOTH = 0x04
|
33
|
+
|
34
|
+
INTERCEPT_DEFAULT_PORT = 8081
|
35
|
+
|
36
|
+
MODE_REGULAR = 0x01
|
37
|
+
MODE_TRANSPARENT = 0x02
|
38
|
+
|
39
|
+
@proxy_mode ||= MODE_REGULAR
|
40
|
+
@intercept_mode ||= INTERCEPT_NONE
|
41
|
+
@rewrite_mode ||= REWRITE_NONE
|
42
|
+
|
43
|
+
@proxy = nil
|
44
|
+
#@proxy_mode = Watobo::Conf::Interceptor.proxy_mode if Watobo::Conf::Interceptor.respond_to? :proxy_mode
|
45
|
+
def self.proxy_mode
|
46
|
+
@proxy_mode
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.proxy_mode=(mode)
|
50
|
+
@proxy_mode = mode
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.rewrite_mode
|
54
|
+
@rewrite_mode
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.rewrite_mode=(mode)
|
58
|
+
@rewrite_mode = mode
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.intercept_mode
|
62
|
+
@intercept_mode
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.intercept_mode=(mode)
|
66
|
+
@intercept_mode = mode
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.transparent?
|
70
|
+
return true if ( @proxy_mode & MODE_TRANSPARENT ) > 0
|
71
|
+
return false
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.intercept_requests?
|
75
|
+
return true if ( @intercept_mode & INTERCEPT_REQUEST ) > 0
|
76
|
+
return false
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.intercept_responses?
|
80
|
+
return true if ( @intercept_mode & INTERCEPT_RESPONSE ) > 0
|
81
|
+
return false
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.rewrite_requests?
|
85
|
+
return true if ( @rewrite_mode & REWRITE_REQUEST ) > 0
|
86
|
+
return false
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.rewrite_responses?
|
90
|
+
return true if ( @rewrite_mode & REWRITE_RESPONSE ) > 0
|
91
|
+
return false
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.active?
|
95
|
+
return false if @proxy.nil?
|
96
|
+
return true
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.start
|
100
|
+
@proxy = Watobo::InterceptProxy.new()
|
101
|
+
|
102
|
+
@proxy.subscribe(:new_interception) { |chat|
|
103
|
+
Thread.new(chat) { |c|
|
104
|
+
Watobo.project.addChat(c) unless Watobo.project.nil?
|
105
|
+
}
|
106
|
+
}
|
107
|
+
|
108
|
+
@proxy.start()
|
109
|
+
puts "DEBUG: Proxy running" if $DEBUG
|
110
|
+
# puts "* set www_auth for interceptor"
|
111
|
+
# puts YAML.dump(@project.settings[:www_auth])
|
112
|
+
#@proxy.www_auth = Watobo.project.settings[:www_auth] unless Watobo.project.nil?
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.proxy
|
116
|
+
@proxy
|
117
|
+
end
|
118
|
+
|
119
|
+
def self.stop
|
120
|
+
@proxy.stop
|
121
|
+
@proxy = nil
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
27
125
|
|
28
|
-
INTERCEPT_DEFAULT_PORT = 8081
|
29
126
|
# I N T E R C E P T P R O X Y
|
30
127
|
#
|
31
128
|
class InterceptProxy
|
32
129
|
|
33
130
|
include Watobo::Constants
|
34
|
-
#
|
131
|
+
# include Watobo::Interceptor
|
35
132
|
|
36
133
|
attr :port
|
37
134
|
|
38
|
-
attr_accessor :
|
135
|
+
attr_accessor :proxy_mode
|
39
136
|
|
40
137
|
attr_accessor :contentLength
|
41
138
|
attr_accessor :contentTypes
|
42
139
|
attr_accessor :target
|
43
|
-
|
140
|
+
attr :www_auth
|
44
141
|
attr_accessor :client_certificates
|
45
142
|
def server
|
46
143
|
@bind_addr
|
@@ -68,7 +165,16 @@ module Watobo
|
|
68
165
|
|
69
166
|
def setRequestFilter(new_settings)
|
70
167
|
@request_filter_settings.update new_settings unless new_settings.nil?
|
71
|
-
|
168
|
+
# puts @request_filter_settings.to_yaml
|
169
|
+
end
|
170
|
+
|
171
|
+
def clear_request_carvers
|
172
|
+
@request_carvers.clear unless @request_carvers.nil?
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
def clear_response_carvers
|
177
|
+
@response_carvers.clear unless @response_carvers.nil?
|
72
178
|
end
|
73
179
|
|
74
180
|
# def getRequestFilter
|
@@ -88,9 +194,11 @@ module Watobo
|
|
88
194
|
def stop()
|
89
195
|
begin
|
90
196
|
puts "[#{self.class}] stop"
|
91
|
-
|
197
|
+
if @t_server.respond_to? :status
|
198
|
+
puts @t_server.status
|
92
199
|
@t_server.kill
|
93
200
|
@intercept_srv.close
|
201
|
+
end
|
94
202
|
rescue IOError => bang
|
95
203
|
puts bang
|
96
204
|
puts bang.backtrace if $DEBUG
|
@@ -101,16 +209,16 @@ module Watobo
|
|
101
209
|
# R U N
|
102
210
|
#
|
103
211
|
|
104
|
-
def
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
# @contentTypes = settings[:content_types] if settings[:content_types]
|
212
|
+
def start()
|
213
|
+
|
214
|
+
if transparent?
|
215
|
+
DRb.start_service
|
216
|
+
@connections = DRbObject.new nil, "druby://127.0.0.1:666"
|
217
|
+
end
|
111
218
|
|
219
|
+
begin
|
112
220
|
@intercept_srv = TCPServer.new(@bind_addr, @port)
|
113
|
-
@intercept_srv.setsockopt( Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
|
221
|
+
@intercept_srv.setsockopt( Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1 )
|
114
222
|
|
115
223
|
rescue => bang
|
116
224
|
puts "\n!!!Could not start InterceptProxy"
|
@@ -119,28 +227,32 @@ module Watobo
|
|
119
227
|
end
|
120
228
|
puts "\n* Intercepor started on #{@bind_addr}:#{@port}"
|
121
229
|
session_list = []
|
230
|
+
puts "!!! TRANSPARENT MODE ENABLED !!!" if transparent?
|
122
231
|
|
123
232
|
@t_server = Thread.new(@intercept_srv) { |server|
|
124
233
|
while (new_session = server.accept)
|
125
234
|
# new_session.sync = true
|
126
235
|
Thread.new(new_session) { |session|
|
236
|
+
flags = []
|
127
237
|
begin
|
238
|
+
|
128
239
|
request, c_sock = read_request(session)
|
129
240
|
|
130
241
|
if request.nil? or request.empty? then
|
131
242
|
# puts "! empty request ? :("
|
132
|
-
c_sock
|
243
|
+
closeSocket(c_sock)
|
133
244
|
Thread.current.exit
|
134
245
|
#return
|
135
246
|
end
|
136
247
|
puts "*[I] #{request.url}"
|
137
248
|
|
138
249
|
rescue => bang
|
139
|
-
|
140
|
-
|
250
|
+
puts "!!! Error reading client request "
|
251
|
+
puts bang
|
141
252
|
# puts bang.backtrace
|
142
253
|
# puts request
|
143
254
|
# puts request
|
255
|
+
closeSocket(c_sock)
|
144
256
|
Thread.current.exit
|
145
257
|
#break
|
146
258
|
end
|
@@ -160,17 +272,24 @@ module Watobo
|
|
160
272
|
closeSocket(c_sock)
|
161
273
|
end
|
162
274
|
end
|
163
|
-
next
|
275
|
+
#next
|
276
|
+
Thread.current.exit
|
164
277
|
end
|
278
|
+
|
165
279
|
request_intercepted = false
|
166
280
|
# no preview, check if interception request is turned on
|
167
|
-
if
|
168
|
-
|
281
|
+
if Watobo::Interceptor.rewrite_requests? then
|
282
|
+
Interceptor::RequestCarver.shape(request, flags)
|
283
|
+
puts "FLAGS >>"
|
284
|
+
puts flags
|
285
|
+
end
|
286
|
+
|
287
|
+
if @target and Watobo::Interceptor.intercept_requests? then
|
169
288
|
if matchRequestFilter(request)
|
170
289
|
@awaiting_requests += 1
|
171
290
|
request_intercepted = true
|
172
291
|
|
173
|
-
if @target.respond_to? :
|
292
|
+
if @target.respond_to? :addRequest
|
174
293
|
# puts "*INTERCEPT REQUEST"
|
175
294
|
# puts @target
|
176
295
|
#notify(:modify_request, request, Thread.current)
|
@@ -190,12 +309,14 @@ module Watobo
|
|
190
309
|
#p "getHTTPHeader"
|
191
310
|
#s_sock, req, resp = @sender.getHTTPHeader(request, :update_sids => true, :update_session => false, :update_contentlength => true)
|
192
311
|
begin
|
312
|
+
|
193
313
|
s_sock, req, resp = @sender.sendHTTPRequest(request, :update_sids => true, :update_session => false, :update_contentlength => true, :www_auth => @www_auth, :client_certificates => @client_certificates)
|
194
314
|
if s_sock.nil? then
|
195
315
|
c_sock.print resp.join unless resp.nil?
|
196
316
|
closeSocket(c_sock)
|
197
317
|
next
|
198
318
|
end
|
319
|
+
|
199
320
|
rescue => bang
|
200
321
|
puts bang
|
201
322
|
puts bang.backtrace if $DEBUG
|
@@ -245,7 +366,10 @@ module Watobo
|
|
245
366
|
|
246
367
|
end
|
247
368
|
else
|
369
|
+
# don't try to read body if request method is HEAD
|
370
|
+
unless req.method =~ /^head/i
|
248
371
|
@sender.readHTTPBody(s_sock, resp, req, :update_sids => true)
|
372
|
+
end
|
249
373
|
end
|
250
374
|
rescue => bang
|
251
375
|
puts "!!! could not send request !!!"
|
@@ -255,7 +379,17 @@ module Watobo
|
|
255
379
|
end
|
256
380
|
|
257
381
|
begin
|
258
|
-
|
382
|
+
Watobo::Response.create resp
|
383
|
+
# puts "* unchunk response ..."
|
384
|
+
resp.unchunk
|
385
|
+
# puts "* unzip response ..."
|
386
|
+
resp.unzip
|
387
|
+
|
388
|
+
if Watobo::Interceptor.rewrite_responses? then
|
389
|
+
Interceptor::ResponseCarver.shape(resp, flags)
|
390
|
+
end
|
391
|
+
|
392
|
+
if @target and Watobo::Interceptor.intercept_responses? then
|
259
393
|
if matchResponseFilter(resp)
|
260
394
|
# if resp.content_type =~ /text/ or resp.content_type =~ /application\/javascript/ then
|
261
395
|
if @target.respond_to? :modifyResponse
|
@@ -267,8 +401,12 @@ module Watobo
|
|
267
401
|
end
|
268
402
|
end
|
269
403
|
|
404
|
+
# puts ">> SEND TO CLIENT"
|
270
405
|
c_sock.write resp.join
|
271
|
-
|
406
|
+
# puts resp.join
|
407
|
+
# puts "-----"
|
408
|
+
# closeSocket(c_sock)
|
409
|
+
|
272
410
|
rescue Errno::ECONNRESET
|
273
411
|
print "x"
|
274
412
|
# puts "!!! ERROR (Reset): reading body"
|
@@ -285,8 +423,12 @@ module Watobo
|
|
285
423
|
#return
|
286
424
|
end
|
287
425
|
#if req then # when req == nil an error occured -> no chat necessary
|
288
|
-
|
426
|
+
|
427
|
+
rc = YAML.load(YAML.dump(request))
|
428
|
+
sc = YAML.load(YAML.dump(resp))
|
429
|
+
chat = Chat.new(rc, sc, :source => CHAT_SOURCE_INTERCEPT)
|
289
430
|
notify(:new_interception, chat)
|
431
|
+
closeSocket(c_sock)
|
290
432
|
# end
|
291
433
|
#else
|
292
434
|
# puts "* got no response"
|
@@ -295,6 +437,10 @@ module Watobo
|
|
295
437
|
end
|
296
438
|
}
|
297
439
|
end
|
440
|
+
|
441
|
+
def refresh_www_auth
|
442
|
+
@www_auth = Watobo::Conf::Scanner.www_auth
|
443
|
+
end
|
298
444
|
|
299
445
|
def initialize(settings=nil)
|
300
446
|
@event_dispatcher_listeners = Hash.new
|
@@ -307,22 +453,11 @@ module Watobo
|
|
307
453
|
# @port = @settings[:intercept_port]
|
308
454
|
# puts settings.to_yaml
|
309
455
|
|
310
|
-
@
|
311
|
-
@www_auth = {}
|
312
|
-
@client_certificates = {}
|
313
|
-
@target = nil
|
314
|
-
@sender = Watobo::Session.new(@target)
|
456
|
+
# @proxy_mode = Watobo::Interceptor.proxy_mode
|
315
457
|
|
316
|
-
|
317
|
-
puts "> Server: #{@bind_addr}"
|
318
|
-
@port = Watobo::Conf::Interceptor.port
|
319
|
-
puts "> Port: #{@port}"
|
458
|
+
#Watobo::Interceptor.proxy_mode = INTERCEPT_NONE
|
320
459
|
|
321
|
-
|
322
|
-
@contentLength = pt[:content_length]
|
323
|
-
puts "> PT-ContentLength: #{@contentLength}"
|
324
|
-
@contentTypes = pt[:content_types]
|
325
|
-
puts "> PT-ContentTypes: #{@contentTypes}"
|
460
|
+
init_instance_vars
|
326
461
|
|
327
462
|
@awaiting_requests = 0
|
328
463
|
@awaiting_responses = 0
|
@@ -358,28 +493,20 @@ module Watobo
|
|
358
493
|
# p @settings[:certificate_path]
|
359
494
|
# p @settings[:cert_file]
|
360
495
|
# p @settings[:key_file]
|
361
|
-
crt_path = Watobo::Conf::Interceptor.certificate_path
|
362
|
-
crt_file = Watobo::Conf::Interceptor.cert_file
|
363
|
-
key_file = Watobo::Conf::Interceptor.key_file
|
364
|
-
dh_key_file = Watobo::Conf::Interceptor.dh_key_file
|
365
|
-
|
366
|
-
crt_filename = File.join(Watobo.base_directory, crt_path, crt_file)
|
367
|
-
key_filename = File.join(Watobo.base_directory, crt_path, key_file)
|
368
|
-
dh_filename = File.join(Watobo.base_directory, crt_path, dh_key_file)
|
369
|
-
unless File.exist? dh_filename
|
370
|
-
#puts "* no dh key file found"
|
371
|
-
File.open(dh_filename,"w") do |fh|
|
372
|
-
puts "* creating SSL key (DH 1024) ... "
|
373
|
-
fh.write OpenSSL::PKey::DH.new(1024).to_pem
|
374
|
-
print " DONE\r\n"
|
375
|
-
end
|
376
|
-
end
|
496
|
+
# crt_path = Watobo::Conf::Interceptor.certificate_path
|
497
|
+
# crt_file = Watobo::Conf::Interceptor.cert_file
|
498
|
+
# key_file = Watobo::Conf::Interceptor.key_file
|
499
|
+
# dh_key_file = Watobo::Conf::Interceptor.dh_key_file
|
500
|
+
|
501
|
+
# crt_filename = File.join(Watobo.base_directory, crt_path, crt_file)
|
502
|
+
# key_filename = File.join(Watobo.base_directory, crt_path, key_file)
|
377
503
|
|
378
504
|
# @ctx = OpenSSL::SSL::SSLContext.new('SSLv23_server')
|
379
|
-
@cert = OpenSSL::X509::Certificate.new(File.read(crt_filename))
|
380
|
-
@key = OpenSSL::PKey::RSA.new(File.read(key_filename))
|
505
|
+
# @cert = OpenSSL::X509::Certificate.new(File.read(crt_filename))
|
506
|
+
# @key = OpenSSL::PKey::RSA.new(File.read(key_filename))
|
381
507
|
|
382
|
-
|
508
|
+
#@dh_key = OpenSSL::PKey::DH.new(File.read(dh_filename))
|
509
|
+
@dh_key = Watobo::CA.dh_key
|
383
510
|
# @ctx.ciphers = nil # ['TLSv1/SSLv3', 56, 56 ]
|
384
511
|
|
385
512
|
rescue => bang
|
@@ -391,6 +518,57 @@ module Watobo
|
|
391
518
|
end
|
392
519
|
|
393
520
|
private
|
521
|
+
|
522
|
+
def init_instance_vars
|
523
|
+
@www_auth = Watobo::Conf::Scanner.www_auth
|
524
|
+
@fake_certs = {}
|
525
|
+
@client_certificates = {}
|
526
|
+
@target = nil
|
527
|
+
@sender = Watobo::Session.new(@target)
|
528
|
+
|
529
|
+
@bind_addr = Watobo::Conf::Interceptor.bind_addr
|
530
|
+
puts "> Server: #{@bind_addr}"
|
531
|
+
@port = Watobo::Conf::Interceptor.port
|
532
|
+
puts "> Port: #{@port}"
|
533
|
+
@proxy_mode = Watobo::Conf::Interceptor.proxy_mode
|
534
|
+
|
535
|
+
pt = Watobo::Conf::Interceptor.pass_through
|
536
|
+
@contentLength = pt[:content_length]
|
537
|
+
puts "> PT-ContentLength: #{@contentLength}"
|
538
|
+
@contentTypes = pt[:content_types]
|
539
|
+
puts "> PT-ContentTypes: #{@contentTypes}"
|
540
|
+
end
|
541
|
+
|
542
|
+
def get_ssl_cert_cn(host,port)
|
543
|
+
cn = ""
|
544
|
+
begin
|
545
|
+
tcp_socket = TCPSocket.new( host, port )
|
546
|
+
tcp_socket.setsockopt( Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
|
547
|
+
tcp_socket.sync = true
|
548
|
+
ctx = OpenSSL::SSL::SSLContext.new()
|
549
|
+
|
550
|
+
ctx.tmp_dh_callback = proc { |*args|
|
551
|
+
OpenSSL::PKey::DH.new(128)
|
552
|
+
}
|
553
|
+
|
554
|
+
socket = OpenSSL::SSL::SSLSocket.new(tcp_socket, ctx)
|
555
|
+
|
556
|
+
socket.connect
|
557
|
+
cert = socket.peer_cert
|
558
|
+
|
559
|
+
if cert.subject.to_s =~ /cn=([^\/]*)/i
|
560
|
+
cn = $1
|
561
|
+
end
|
562
|
+
puts "Peer-Cert CN: #{cn}"
|
563
|
+
socket.io.shutdown(2)
|
564
|
+
rescue => bang
|
565
|
+
puts bang
|
566
|
+
cn = host
|
567
|
+
ensure
|
568
|
+
socket.close if socket.respond_to? :close
|
569
|
+
end
|
570
|
+
cn
|
571
|
+
end
|
394
572
|
|
395
573
|
#
|
396
574
|
#
|
@@ -531,14 +709,15 @@ module Watobo
|
|
531
709
|
#print "~]"
|
532
710
|
return if buf.nil?
|
533
711
|
rescue Errno::ECONNRESET
|
534
|
-
|
535
|
-
|
712
|
+
# puts "!!! ERROR (Reset): reading body"
|
713
|
+
# puts "* last data seen on socket: #{buf}"
|
714
|
+
print "R"
|
536
715
|
return if buf.nil?
|
537
716
|
rescue Timeout::Error
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
print "
|
717
|
+
#puts "!!! ERROR (Timeout): reading body"
|
718
|
+
#puts "* last data seen on socket:"
|
719
|
+
#client.write buf if buf
|
720
|
+
print "T"
|
542
721
|
return if buf.nil?
|
543
722
|
rescue => bang
|
544
723
|
puts "!!! could not read body !!!"
|
@@ -583,16 +762,76 @@ module Watobo
|
|
583
762
|
end
|
584
763
|
end
|
585
764
|
|
765
|
+
def transparent?
|
766
|
+
return true if ( @proxy_mode & Watobo::Interceptor::MODE_TRANSPARENT ) > 0
|
767
|
+
return false
|
768
|
+
end
|
769
|
+
|
586
770
|
def read_request(socket)
|
587
771
|
request = []
|
588
772
|
# read http header lines
|
589
773
|
session = socket
|
590
|
-
|
591
|
-
|
592
|
-
|
774
|
+
|
775
|
+
ra = socket.remote_address
|
776
|
+
cport = ra.ip_port
|
777
|
+
caddr = ra.ip_address
|
778
|
+
|
779
|
+
if transparent?
|
780
|
+
|
781
|
+
ci = @connections.info({ 'host' => caddr, 'port' => cport } )
|
782
|
+
unless ci['target'].empty? or ci['cn'].empty?
|
783
|
+
puts "SSL-REQUEST FROM #{caddr}:#{cport}"
|
784
|
+
|
785
|
+
ctx = Watobo::CertStore.acquire_ssl_ctx ci['target'], ci['cn']
|
786
|
+
|
787
|
+
begin
|
788
|
+
ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, ctx)
|
789
|
+
ssl_socket.setsockopt( Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
|
790
|
+
# ssl_socket.sync_close = true
|
791
|
+
ssl_socket.sync = true
|
792
|
+
# puts ssl_socket.methods.sort
|
793
|
+
session = ssl_socket.accept
|
794
|
+
rescue OpenSSL::SSL::SSLError => e
|
795
|
+
puts ">> SSLError"
|
796
|
+
puts e
|
797
|
+
return nil, session
|
798
|
+
rescue => bang
|
799
|
+
puts bang
|
800
|
+
puts bang.backtrace
|
801
|
+
return nil, session
|
802
|
+
end
|
803
|
+
else
|
804
|
+
puts ci['host']
|
805
|
+
puts ci['cn']
|
806
|
+
end
|
807
|
+
end
|
808
|
+
|
809
|
+
Watobo::HTTP.read_header(session) do |line|
|
810
|
+
# puts line
|
593
811
|
request.push line
|
594
812
|
end
|
595
813
|
|
814
|
+
if transparent?
|
815
|
+
#puts "> get hostname ..."
|
816
|
+
thn = nil
|
817
|
+
request.each do |l|
|
818
|
+
if l =~ /^Host: (.*)/
|
819
|
+
thn = $1.strip
|
820
|
+
# puts ">> #{thn}"
|
821
|
+
end
|
822
|
+
end
|
823
|
+
# puts session.class
|
824
|
+
# puts "* fix request line ..."
|
825
|
+
# puts request.first
|
826
|
+
# puts ">>"
|
827
|
+
if session.is_a? OpenSSL::SSL::SSLSocket
|
828
|
+
request.first.gsub!(/(^[^[:space:]]{1,}) (.*) (HTTP.*)/i,"\\1 https://#{thn}\\2 \\3")
|
829
|
+
else
|
830
|
+
request.first.gsub!(/(^[^[:space:]]{1,}) (.*) (HTTP.*)/i,"\\1 http://#{thn}\\2 \\3")
|
831
|
+
end
|
832
|
+
#puts request.first
|
833
|
+
end
|
834
|
+
|
596
835
|
if request.first =~ /^CONNECT (.*):(\d{1,5}) HTTP\/1\./ then
|
597
836
|
target = $1
|
598
837
|
tport = $2
|
@@ -606,13 +845,31 @@ module Watobo
|
|
606
845
|
bscount = 0 # bad handshake counter
|
607
846
|
# puts "* wait for ssl handshake ..."
|
608
847
|
begin
|
609
|
-
|
848
|
+
dst = "#{target}:#{tport}"
|
849
|
+
unless @fake_certs.has_key? dst
|
850
|
+
puts "NEW CERTIFICATE FOR >> #{dst} <<"
|
851
|
+
cn = get_ssl_cert_cn(target, tport)
|
852
|
+
puts "CN=#{cn}"
|
853
|
+
|
854
|
+
cert = {
|
855
|
+
:hostname => cn,
|
856
|
+
:type => 'server',
|
857
|
+
:user => 'watobo',
|
858
|
+
:email => 'a.schmidt@siberas.de',
|
859
|
+
}
|
860
|
+
cert_file, key_file = Watobo::CA.create_cert cert
|
861
|
+
@fake_certs[dst] = {
|
862
|
+
:cert => OpenSSL::X509::Certificate.new(File.read(cert_file)),
|
863
|
+
:key => OpenSSL::PKey::RSA.new(File.read(key_file))
|
864
|
+
}
|
865
|
+
end
|
610
866
|
ctx = OpenSSL::SSL::SSLContext.new()
|
611
867
|
|
612
|
-
ctx.cert = @cert
|
868
|
+
#ctx.cert = @cert
|
869
|
+
ctx.cert = @fake_certs[dst][:cert]
|
613
870
|
# @ctx.key = OpenSSL::PKey::DSA.new(File.read(key_file))
|
614
|
-
ctx.key = @key
|
615
|
-
|
871
|
+
#ctx.key = @key
|
872
|
+
ctx.key = @fake_certs[dst][:key]
|
616
873
|
ctx.tmp_dh_callback = proc { |*args|
|
617
874
|
@dh_key
|
618
875
|
}
|
@@ -622,7 +879,7 @@ module Watobo
|
|
622
879
|
|
623
880
|
ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, ctx)
|
624
881
|
ssl_socket.setsockopt( Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
|
625
|
-
#ssl_socket.sync_close = true
|
882
|
+
# ssl_socket.sync_close = true
|
626
883
|
ssl_socket.sync = true
|
627
884
|
# puts ssl_socket.methods.sort
|
628
885
|
|
@@ -652,9 +909,10 @@ module Watobo
|
|
652
909
|
request.first.gsub!(/(^[^[:space:]]{1,})( )(\/.*)/, "\\1 https://#{target}:#{tport}\\3")
|
653
910
|
end
|
654
911
|
#puts request
|
655
|
-
request.extend Watobo::Mixin::Parser::Url
|
656
|
-
request.extend Watobo::Mixin::Parser::Web10
|
657
|
-
request.extend Watobo::Mixin::Shaper::Web10
|
912
|
+
# request.extend Watobo::Mixin::Parser::Url
|
913
|
+
# request.extend Watobo::Mixin::Parser::Web10
|
914
|
+
# request.extend Watobo::Mixin::Shaper::Web10
|
915
|
+
Watobo::Request.create request
|
658
916
|
|
659
917
|
clen = request.content_length
|
660
918
|
if clen > 0 then
|
@@ -673,6 +931,8 @@ module Watobo
|
|
673
931
|
begin
|
674
932
|
reason = nil
|
675
933
|
clen = response.content_length
|
934
|
+
# no pass-through necessary if request method is HEAD
|
935
|
+
return false if request.method =~ /^head/i
|
676
936
|
|
677
937
|
if matchContentType?(response.content_type) then
|
678
938
|
# first forward headers
|
@@ -718,17 +978,20 @@ module Watobo
|
|
718
978
|
|
719
979
|
def closeSocket(socket)
|
720
980
|
#puts socket.class
|
981
|
+
return false if socket.nil?
|
721
982
|
begin
|
722
983
|
#if socket.class.to_s =~ /SSLSocket/
|
723
984
|
if socket.is_a? OpenSSL::SSL::SSLSocket
|
724
985
|
socket.io.shutdown(2)
|
986
|
+
#socket.sysclose
|
725
987
|
else
|
726
988
|
socket.shutdown(2)
|
727
989
|
end
|
728
|
-
socket.close
|
990
|
+
socket.close if socket.respond_to? :close
|
729
991
|
rescue => bang
|
730
992
|
puts bang
|
731
993
|
puts bang.backtrace if $DEBUG
|
994
|
+
|
732
995
|
end
|
733
996
|
end
|
734
997
|
|