watobo 0.9.8.677
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/bin/watobo_gui.rb +39 -0
- data/certificates/cert.pem +19 -0
- data/certificates/privkey.pem +15 -0
- data/certificates/watobo_dh.key +5 -0
- data/config/datastore.yml +5 -0
- data/config/forwarding_proxy.yml +12 -0
- data/config/general.yml +4 -0
- data/config/gui.yml +23 -0
- data/config/interceptor.yml +16 -0
- data/config/scan_policy.yml +13 -0
- data/config/scanner.yml +34 -0
- data/icons/Add.ico +0 -0
- data/icons/Add_24x24.ico +0 -0
- data/icons/Bandwidth.ico +0 -0
- data/icons/Bandwidth_24x24.ico +0 -0
- data/icons/Mr. Bomb.ico +0 -0
- data/icons/Mr. Bomb_16x16.ico +0 -0
- data/icons/Mr. Bomb_24x24.ico +0 -0
- data/icons/Orange Ball.ico +0 -0
- data/icons/Orange Ball_16x16.ico +0 -0
- data/icons/Orange Ball_24x24.ico +0 -0
- data/icons/Pause.ico +0 -0
- data/icons/Play.ico +0 -0
- data/icons/Play_24x24.ico +0 -0
- data/icons/Red Ball.ico +0 -0
- data/icons/Red Ball_16x16.ico +0 -0
- data/icons/Red Ball_24x24.ico +0 -0
- data/icons/Run.ico +0 -0
- data/icons/Stop.ico +0 -0
- data/icons/Stop_24x24.ico +0 -0
- data/icons/Terminal.ico +0 -0
- data/icons/Transfer.ico +0 -0
- data/icons/Transfer_16x16.ico +0 -0
- data/icons/User.ico +0 -0
- data/icons/User_16x16.ico +0 -0
- data/icons/User_24x24.ico +0 -0
- data/icons/Web Browser.ico +0 -0
- data/icons/Web Browser_16x16.ico +0 -0
- data/icons/Write Document.ico +0 -0
- data/icons/Yellow Ball.ico +0 -0
- data/icons/Yellow Ball_16x16.ico +0 -0
- data/icons/Yellow Ball_24x24.ico +0 -0
- data/icons/advanced.ico +0 -0
- data/icons/advanced_16x16.ico +0 -0
- data/icons/advanced_24x24.ico +0 -0
- data/icons/applications.ico +0 -0
- data/icons/applications_16x16.ico +0 -0
- data/icons/applications_24x24.ico +0 -0
- data/icons/browser_16x16.ico +0 -0
- data/icons/browser_24x24.ico +0 -0
- data/icons/burn.ico +0 -0
- data/icons/burn_16x16.ico +0 -0
- data/icons/burn_24x24.ico +0 -0
- data/icons/calculator.ico +0 -0
- data/icons/calculator_24x24.ico +0 -0
- data/icons/cb_checked.ico +0 -0
- data/icons/cb_checked_orange.ico +0 -0
- data/icons/cb_unchecked.ico +0 -0
- data/icons/coin_24x24.ico +0 -0
- data/icons/conversation.ico +0 -0
- data/icons/conversation_24x24.ico +0 -0
- data/icons/engine.ico +0 -0
- data/icons/filter.ico +0 -0
- data/icons/folder.ico +0 -0
- data/icons/folder_16x16.ico +0 -0
- data/icons/fuzzer_16x16.ico +0 -0
- data/icons/fuzzer_24x24.ico +0 -0
- data/icons/go-down_16x16.png +0 -0
- data/icons/go-up_16x16.png +0 -0
- data/icons/help.ico +0 -0
- data/icons/help_16x16.ico +0 -0
- data/icons/help_24x24.ico +0 -0
- data/icons/iChat.ico +0 -0
- data/icons/iChat_16x16.ico +0 -0
- data/icons/iChat_24x24.ico +0 -0
- data/icons/icons.txt +3 -0
- data/icons/info.ico +0 -0
- data/icons/info_16x16.ico +0 -0
- data/icons/info_24x24.ico +0 -0
- data/icons/interceptor_24x24.ico +0 -0
- data/icons/lock.ico +0 -0
- data/icons/lock_12x12.ico +0 -0
- data/icons/lock_16x16.ico +0 -0
- data/icons/monitor.ico +0 -0
- data/icons/plugin.ico +0 -0
- data/icons/plugin_24x24.ico +0 -0
- data/icons/scan_16x16.png +0 -0
- data/icons/send.ico +0 -0
- data/icons/server.ico +0 -0
- data/icons/server_16x16.ico +0 -0
- data/icons/siberas_logo_x24.gif +0 -0
- data/icons/tag_blue_32x32.ico +0 -0
- data/icons/watobo-48x48.png +0 -0
- data/icons/watobo-logo.png +0 -0
- data/icons/watobo.ico +0 -0
- data/lib/watobo/adapters/data_store.rb +38 -0
- data/lib/watobo/adapters/file/file_store.rb +211 -0
- data/lib/watobo/adapters/session_store.rb +27 -0
- data/lib/watobo/adapters.rb +26 -0
- data/lib/watobo/config.rb +143 -0
- data/lib/watobo/constants.rb +92 -0
- data/lib/watobo/core/active_check.rb +404 -0
- data/lib/watobo/core/cookie.rb +69 -0
- data/lib/watobo/core/fuzz_gen.rb +160 -0
- data/lib/watobo/core/http_socket.rb +142 -0
- data/lib/watobo/core/interceptor.rb +729 -0
- data/lib/watobo/core/passive_check.rb +141 -0
- data/lib/watobo/core/project.rb +1058 -0
- data/lib/watobo/core/scanner.rb +396 -0
- data/lib/watobo/core/session.rb +1320 -0
- data/lib/watobo/core/simple_ca.rb +393 -0
- data/lib/watobo/core.rb +34 -0
- data/lib/watobo/defaults.rb +40 -0
- data/lib/watobo/external/diff/lcs/array.rb +42 -0
- data/lib/watobo/external/diff/lcs/block.rb +72 -0
- data/lib/watobo/external/diff/lcs/callbacks.rb +343 -0
- data/lib/watobo/external/diff/lcs/change.rb +190 -0
- data/lib/watobo/external/diff/lcs/hunk.rb +279 -0
- data/lib/watobo/external/diff/lcs/ldiff.rb +247 -0
- data/lib/watobo/external/diff/lcs/string.rb +40 -0
- data/lib/watobo/external/diff/lcs.rb +1124 -0
- data/lib/watobo/external/ntlm/ntlm.rb +797 -0
- data/lib/watobo/externals.rb +28 -0
- data/lib/watobo/framework/create_project.rb +55 -0
- data/lib/watobo/framework/init.rb +149 -0
- data/lib/watobo/framework/init_modules.rb +116 -0
- data/lib/watobo/framework/license_text.rb +50 -0
- data/lib/watobo/framework.rb +26 -0
- data/lib/watobo/gui/about_watobo.rb +68 -0
- data/lib/watobo/gui/browser_preview.rb +460 -0
- data/lib/watobo/gui/certificate_dialog.rb +132 -0
- data/lib/watobo/gui/chat_diff.rb +415 -0
- data/lib/watobo/gui/chatviewer_frame.rb +427 -0
- data/lib/watobo/gui/checkboxtree.rb +221 -0
- data/lib/watobo/gui/checks_policy_frame.rb +123 -0
- data/lib/watobo/gui/client_cert_dialog.rb +227 -0
- data/lib/watobo/gui/confirm_scan_dialog.rb +67 -0
- data/lib/watobo/gui/conversation_table.rb +386 -0
- data/lib/watobo/gui/conversation_table_ctrl.rb +175 -0
- data/lib/watobo/gui/csrf_token_dialog.rb +446 -0
- data/lib/watobo/gui/dashboard.rb +341 -0
- data/lib/watobo/gui/define_scope_frame.rb +380 -0
- data/lib/watobo/gui/edit_comment.rb +70 -0
- data/lib/watobo/gui/edit_scope_dialog.rb +69 -0
- data/lib/watobo/gui/finding_info.rb +212 -0
- data/lib/watobo/gui/findings_tree.rb +459 -0
- data/lib/watobo/gui/full_scan_dialog.rb +269 -0
- data/lib/watobo/gui/fuzzer_gui.rb +1522 -0
- data/lib/watobo/gui/hex_viewer.rb +106 -0
- data/lib/watobo/gui/interceptor_gui.rb +994 -0
- data/lib/watobo/gui/interceptor_settings_dialog.rb +201 -0
- data/lib/watobo/gui/log_viewer.rb +97 -0
- data/lib/watobo/gui/login_wizzard.rb +301 -0
- data/lib/watobo/gui/main_window.rb +1815 -0
- data/lib/watobo/gui/manual_request_editor.rb +1105 -0
- data/lib/watobo/gui/master_pw_dialog.rb +142 -0
- data/lib/watobo/gui/password_policy_dialog.rb +98 -0
- data/lib/watobo/gui/plugin/base.rb +82 -0
- data/lib/watobo/gui/plugin_board.rb +95 -0
- data/lib/watobo/gui/preferences_dialog.rb +116 -0
- data/lib/watobo/gui/progress_window.rb +102 -0
- data/lib/watobo/gui/project_wizzard.rb +369 -0
- data/lib/watobo/gui/proxy_dialog.rb +550 -0
- data/lib/watobo/gui/quick_scan_dialog.rb +242 -0
- data/lib/watobo/gui/request_editor.rb +480 -0
- data/lib/watobo/gui/save_chat_dialog.rb +158 -0
- data/lib/watobo/gui/scanner_settings_dialog.rb +360 -0
- data/lib/watobo/gui/select_chat_dialog.rb +169 -0
- data/lib/watobo/gui/session_management_dialog.rb +688 -0
- data/lib/watobo/gui/sites_tree.rb +347 -0
- data/lib/watobo/gui/status_bar.rb +88 -0
- data/lib/watobo/gui/table_editor.rb +445 -0
- data/lib/watobo/gui/tagless_viewer.rb +62 -0
- data/lib/watobo/gui/templates/plugin.rb +80 -0
- data/lib/watobo/gui/templates/plugin2.rb +103 -0
- data/lib/watobo/gui/text_viewer.rb +247 -0
- data/lib/watobo/gui/transcoder_window.rb +215 -0
- data/lib/watobo/gui/utils/gui_utils.rb +129 -0
- data/lib/watobo/gui/utils/init_icons.rb +106 -0
- data/lib/watobo/gui/utils/load_icons.rb +54 -0
- data/lib/watobo/gui/utils/load_plugins.rb +94 -0
- data/lib/watobo/gui/utils/master_password.rb +90 -0
- data/lib/watobo/gui/utils/save_default_settings.rb +99 -0
- data/lib/watobo/gui/utils/save_project_settings.rb +21 -0
- data/lib/watobo/gui/utils/save_proxy_settings.rb +45 -0
- data/lib/watobo/gui/utils/save_session_settings.rb +21 -0
- data/lib/watobo/gui/utils/session_history.rb +134 -0
- data/lib/watobo/gui/workspace_dialog.rb +89 -0
- data/lib/watobo/gui/www_auth_dialog.rb +348 -0
- data/lib/watobo/gui/xml_viewer_frame.rb +114 -0
- data/lib/watobo/gui.rb +139 -0
- data/lib/watobo/mixins/httpparser.rb +664 -0
- data/lib/watobo/mixins/request_parser.rb +210 -0
- data/lib/watobo/mixins/shapers.rb +345 -0
- data/lib/watobo/mixins/transcoders.rb +88 -0
- data/lib/watobo/mixins.rb +32 -0
- data/lib/watobo/utils/check_regex.rb +36 -0
- data/lib/watobo/utils/copy_object.rb +29 -0
- data/lib/watobo/utils/crypto.rb +74 -0
- data/lib/watobo/utils/expand_range.rb +45 -0
- data/lib/watobo/utils/file_management.rb +73 -0
- data/lib/watobo/utils/load_chat.rb +219 -0
- data/lib/watobo/utils/load_icon.rb +47 -0
- data/lib/watobo/utils/print_debug.rb +34 -0
- data/lib/watobo/utils/response_hash.rb +143 -0
- data/lib/watobo/utils/secure_eval.rb +57 -0
- data/lib/watobo/utils/text2request.rb +96 -0
- data/lib/watobo/utils.rb +32 -0
- data/lib/watobo.rb +76 -0
- data/modules/active/Apache/mod_status.rb +123 -0
- data/modules/active/Flash/crossdomain.rb +102 -0
- data/modules/active/directories/dirwalker.rb +89 -0
- data/modules/active/discovery/fileextensions.rb +151 -0
- data/modules/active/discovery/http_methods.rb +135 -0
- data/modules/active/domino/domino_db.lst +164 -0
- data/modules/active/domino/domino_db.rb +128 -0
- data/modules/active/fileinclusion/lfi_simple.rb +134 -0
- data/modules/active/jboss/jboss_basic.rb +119 -0
- data/modules/active/sap/business_objects.rb +73 -0
- data/modules/active/sap/its_commands.rb +101 -0
- data/modules/active/sap/its_service_parameter.rb +105 -0
- data/modules/active/sap/its_services.rb +103 -0
- data/modules/active/sap/its_xss.rb +98 -0
- data/modules/active/sqlinjection/sql_boolean.rb +262 -0
- data/modules/active/sqlinjection/sqli_simple.rb +205 -0
- data/modules/active/xss/xss_simple.rb +179 -0
- data/modules/passive/cookie_options.rb +97 -0
- data/modules/passive/cookie_xss.rb +85 -0
- data/modules/passive/detect_code.rb +89 -0
- data/modules/passive/detect_fileupload.rb +80 -0
- data/modules/passive/detect_infrastructure.rb +98 -0
- data/modules/passive/detect_one_time_tokens.rb +86 -0
- data/modules/passive/dirindexing.rb +81 -0
- data/modules/passive/disclosure_emails.rb +82 -0
- data/modules/passive/disclosure_ipaddr.rb +87 -0
- data/modules/passive/filename_as_parameter.rb +85 -0
- data/modules/passive/form_spotter.rb +75 -0
- data/modules/passive/hotspots.rb +86 -0
- data/modules/passive/in_script_parameter.rb +92 -0
- data/modules/passive/multiple_server_headers.rb +98 -0
- data/modules/passive/possible_login.rb +134 -0
- data/modules/passive/redirect_url.rb +88 -0
- data/modules/passive/redirectionz.rb +96 -0
- data/modules/passive/xss_dom.rb +91 -0
- data/plugins/catalog/catalog.ico +0 -0
- data/plugins/catalog/catalog.rb +726 -0
- data/plugins/catalog/db_tests +6483 -0
- data/plugins/catalog/db_variables +29 -0
- data/plugins/filefinder/dbs/hbci.db +12 -0
- data/plugins/filefinder/filefinder.rb +602 -0
- data/plugins/sslchecker/cli/sslchecker_cli.rb +21 -0
- data/plugins/sslchecker/gui/cipher_table.rb +260 -0
- data/plugins/sslchecker/gui/gui.rb +245 -0
- data/plugins/sslchecker/gui/sslchecker.rb +26 -0
- data/plugins/sslchecker/icons/green_16x16.ico +0 -0
- data/plugins/sslchecker/icons/grey_16x16.ico +0 -0
- data/plugins/sslchecker/icons/red_16x16.ico +0 -0
- data/plugins/sslchecker/icons/sslchecker.ico +0 -0
- data/plugins/sslchecker/lib/check.rb +117 -0
- metadata +317 -0
|
@@ -0,0 +1,1320 @@
|
|
|
1
|
+
# .
|
|
2
|
+
# session.rb
|
|
3
|
+
#
|
|
4
|
+
# Copyright 2012 by siberas, http://www.siberas.de
|
|
5
|
+
#
|
|
6
|
+
# This file is part of WATOBO (Web Application Tool Box)
|
|
7
|
+
# http://watobo.sourceforge.com
|
|
8
|
+
#
|
|
9
|
+
# WATOBO is free software; you can redistribute it and/or modify
|
|
10
|
+
# it under the terms of the GNU General Public License as published by
|
|
11
|
+
# the Free Software Foundation version 2 of the License.
|
|
12
|
+
#
|
|
13
|
+
# WATOBO is distributed in the hope that it will be useful,
|
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16
|
+
# GNU General Public License for more details.
|
|
17
|
+
#
|
|
18
|
+
# You should have received a copy of the GNU General Public License
|
|
19
|
+
# along with WATOBO; if not, write to the Free Software
|
|
20
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
21
|
+
# .
|
|
22
|
+
module Watobo
|
|
23
|
+
class Proxy
|
|
24
|
+
attr :login
|
|
25
|
+
attr :name
|
|
26
|
+
attr :host
|
|
27
|
+
attr :port
|
|
28
|
+
attr :login
|
|
29
|
+
|
|
30
|
+
def unsetCredentials()
|
|
31
|
+
@login = nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def setCredentials(creds)
|
|
35
|
+
@login = Hash.new
|
|
36
|
+
@login.update creds
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def has_login?
|
|
40
|
+
return false if @login.nil?
|
|
41
|
+
return true
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def initialize(prefs)
|
|
45
|
+
@login = nil
|
|
46
|
+
@name = prefs[:name]
|
|
47
|
+
@host = prefs[:host]
|
|
48
|
+
@port = prefs[:port]
|
|
49
|
+
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
class Session
|
|
54
|
+
|
|
55
|
+
include Watobo::Constants
|
|
56
|
+
|
|
57
|
+
@@settings = Hash.new
|
|
58
|
+
@@proxy = Hash.new
|
|
59
|
+
|
|
60
|
+
@@session_lock = Mutex.new
|
|
61
|
+
@@csrf_lock = Mutex.new
|
|
62
|
+
|
|
63
|
+
@@login_mutex = Mutex.new
|
|
64
|
+
@@login_cv = ConditionVariable.new
|
|
65
|
+
@@login_in_progress = false
|
|
66
|
+
def subscribe(event, &callback)
|
|
67
|
+
(@event_dispatcher_listeners[event] ||= []) << callback
|
|
68
|
+
#puts callback.class_
|
|
69
|
+
puts callback.object_id
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def clearEvents(event)
|
|
73
|
+
@event_dispatcher_listeners[event] ||= []
|
|
74
|
+
@event_dispatcher_listeners[event].clear
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def notify(event, *args)
|
|
78
|
+
if @event_dispatcher_listeners[event]
|
|
79
|
+
puts "NOTIFY: #{self}(:#{event}) [#{@event_dispatcher_listeners[event].length}]" if $DEBUG
|
|
80
|
+
@event_dispatcher_listeners[event].each do |m|
|
|
81
|
+
m.call(*args) if m.respond_to? :call
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def runLogin(chat_list, prefs={})
|
|
87
|
+
@@login_mutex.synchronize do
|
|
88
|
+
begin
|
|
89
|
+
@@login_in_progress = true
|
|
90
|
+
login_prefs = Hash.new
|
|
91
|
+
login_prefs.update prefs
|
|
92
|
+
dummy = {:ignore_logout => true, :update_sids => true, :update_session => true, :update_contentlength => true}
|
|
93
|
+
login_prefs.update dummy
|
|
94
|
+
puts "! Start Login ..." if $DEBUG
|
|
95
|
+
unless chat_list.empty?
|
|
96
|
+
# puts login_prefs.to_yaml
|
|
97
|
+
chat_list.each do |chat|
|
|
98
|
+
print "! LoginRequest: #{chat.id}" if $DEBUG
|
|
99
|
+
test_req = chat.copyRequest
|
|
100
|
+
request, response = doRequest(test_req, login_prefs)
|
|
101
|
+
end
|
|
102
|
+
else
|
|
103
|
+
puts "! no login script configured !"
|
|
104
|
+
end
|
|
105
|
+
rescue => bang
|
|
106
|
+
puts "!ERROR in runLogin"
|
|
107
|
+
puts bang.backtrace if $DEBUG
|
|
108
|
+
ensure
|
|
109
|
+
@@login_in_progress = false
|
|
110
|
+
@@login_cv.signal
|
|
111
|
+
# exit
|
|
112
|
+
# print "L]"
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# def sessionSettings=(prefs)
|
|
118
|
+
# applySessionSettings(prefs)
|
|
119
|
+
# end
|
|
120
|
+
|
|
121
|
+
def sessionSettings()
|
|
122
|
+
@@settings
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# sendHTTPRequest
|
|
126
|
+
# returns Socket, ResponseHeader
|
|
127
|
+
def sendHTTPRequest(request, prefs={})
|
|
128
|
+
#Watobo.print_debug("huhule", "#{prefs.to_yaml}", "gagagag")
|
|
129
|
+
begin
|
|
130
|
+
@lasterror = nil
|
|
131
|
+
response_header = nil
|
|
132
|
+
site = request.site
|
|
133
|
+
proxy = getProxy(site)
|
|
134
|
+
|
|
135
|
+
unless proxy.nil?
|
|
136
|
+
host = proxy.host
|
|
137
|
+
port = proxy.port
|
|
138
|
+
else
|
|
139
|
+
host = request.host
|
|
140
|
+
port = request.port
|
|
141
|
+
end
|
|
142
|
+
# check if hostname is valid and can be resolved
|
|
143
|
+
hostip = IPSocket.getaddress(host)
|
|
144
|
+
# update current preferences, prefs given here are stronger then global settings!
|
|
145
|
+
current_prefs = Hash.new
|
|
146
|
+
[:update_session, :update_sids, :update_contentlength, :ssl_cipher, :www_auth, :client_certificates].each do |k|
|
|
147
|
+
current_prefs[k] = prefs[k].nil? ? @session[k] : prefs[k]
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
updateSession(request) if current_prefs[:update_session] == true
|
|
151
|
+
|
|
152
|
+
#---------------------------------------
|
|
153
|
+
request.removeHeader("^Proxy-Connection") #if not use_proxy
|
|
154
|
+
request.removeHeader("^Connection") #if not use_proxy
|
|
155
|
+
request.removeHeader("^Accept-Encoding")
|
|
156
|
+
# If-Modified-Since: Tue, 28 Oct 2008 11:06:43 GMT
|
|
157
|
+
# If-None-Match: W/"3975-1225192003000"
|
|
158
|
+
request.removeHeader("^If-")
|
|
159
|
+
# puts
|
|
160
|
+
# request.each do |line|
|
|
161
|
+
# puts line.unpack("H*")
|
|
162
|
+
#end
|
|
163
|
+
#puts
|
|
164
|
+
if current_prefs[:update_contentlength] == true then
|
|
165
|
+
request.fix_content_length()
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
#request.add_header("Via", "Watobo") if use_proxy
|
|
169
|
+
#puts request
|
|
170
|
+
# puts "=============="
|
|
171
|
+
rescue SocketError
|
|
172
|
+
puts "!!! unknown hostname #{host}"
|
|
173
|
+
puts request.first
|
|
174
|
+
return nil, "WATOBO: Could not resolve hostname #{host}", nil
|
|
175
|
+
rescue => bang
|
|
176
|
+
puts bang
|
|
177
|
+
puts bang.backtrace if $DEBUG
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
begin
|
|
181
|
+
unless proxy.nil?
|
|
182
|
+
# connection requires proxy
|
|
183
|
+
# puts "* use proxy #{proxy.name}"
|
|
184
|
+
|
|
185
|
+
# check for regular proxy authentication
|
|
186
|
+
if request.is_ssl?
|
|
187
|
+
socket, response_header = sslProxyConnect(request, proxy, current_prefs)
|
|
188
|
+
return socket, response_header, "WATOBO: could not connect to proxy #{proxy.name}:#{proxy.host}" if socket.nil?
|
|
189
|
+
if current_prefs[:www_auth].has_key?(site)
|
|
190
|
+
case current_prefs[:www_auth][site][:type]
|
|
191
|
+
when AUTH_TYPE_NTLM
|
|
192
|
+
# puts "* found NTLM credentials for site #{site}"
|
|
193
|
+
socket, response_header = wwwAuthNTLM(socket, request, current_prefs[:www_auth][site])
|
|
194
|
+
|
|
195
|
+
response_header.extend Watobo::Mixin::Parser::Url
|
|
196
|
+
response_header.extend Watobo::Mixin::Parser::Web10
|
|
197
|
+
|
|
198
|
+
else
|
|
199
|
+
puts "* Unknown Authentication Type: #{current_prefs[:www_auth][site][:type]}"
|
|
200
|
+
end
|
|
201
|
+
else
|
|
202
|
+
data = request.join + "\r\n"
|
|
203
|
+
unless socket.nil?
|
|
204
|
+
socket.print data
|
|
205
|
+
response_header = readHTTPHeader(socket, current_prefs)
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
return socket, request, response_header
|
|
209
|
+
end
|
|
210
|
+
# puts "* doProxyRequest"
|
|
211
|
+
socket, response_header = doProxyRequest(request, proxy, current_prefs)
|
|
212
|
+
# puts socket.class
|
|
213
|
+
# puts response_header.class
|
|
214
|
+
|
|
215
|
+
return socket, request, response_header
|
|
216
|
+
else
|
|
217
|
+
# direct connection to host
|
|
218
|
+
tcp_socket = nil
|
|
219
|
+
# timeout(6) do
|
|
220
|
+
#puts "* no proxy - direct connection"
|
|
221
|
+
tcp_socket = TCPSocket.new( host, port )
|
|
222
|
+
tcp_socket.setsockopt( Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
|
|
223
|
+
tcp_socket.sync = true
|
|
224
|
+
|
|
225
|
+
socket = tcp_socket
|
|
226
|
+
if request.is_ssl?
|
|
227
|
+
ssl_prefs = {}
|
|
228
|
+
ssl_prefs[:ssl_cipher] = current_prefs[:ssl_cipher] if current_prefs.has_key? :ssl_cipher
|
|
229
|
+
if current_prefs.has_key? :client_certificates
|
|
230
|
+
if current_prefs[:client_certificates].has_key? request.site
|
|
231
|
+
puts "* use ssl client certificate for site #{request.site}" if $DEBUG
|
|
232
|
+
ssl_prefs[:ssl_client_cert] = current_prefs[:client_certificates][request.site][:ssl_client_cert]
|
|
233
|
+
ssl_prefs[:ssl_client_key] = current_prefs[:client_certificates][request.site][:ssl_client_key]
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
socket = sslConnect(tcp_socket, ssl_prefs)
|
|
237
|
+
end
|
|
238
|
+
#puts socket.class
|
|
239
|
+
# remove URI before sending request but cache it for restoring request
|
|
240
|
+
uri_cache = nil
|
|
241
|
+
uri_cache = request.removeURI #if proxy.nil?
|
|
242
|
+
|
|
243
|
+
# puts "========== Add Headers"
|
|
244
|
+
request.addHeader("Connection", "Close") #if not use_proxy
|
|
245
|
+
request.addHeader("Proxy-Connection", "Close") #if not use_proxy
|
|
246
|
+
request.addHeader("Accept-Encoding", "None") #don't want encoding
|
|
247
|
+
|
|
248
|
+
if current_prefs[:www_auth].has_key?(site)
|
|
249
|
+
case current_prefs[:www_auth][site][:type]
|
|
250
|
+
when AUTH_TYPE_NTLM
|
|
251
|
+
# puts "* found NTLM credentials for site #{site}"
|
|
252
|
+
socket, response_header = wwwAuthNTLM(socket, request, current_prefs[:www_auth][site])
|
|
253
|
+
request.restoreURI(uri_cache)
|
|
254
|
+
response_header.extend Watobo::Mixin::Parser::Url
|
|
255
|
+
response_header.extend Watobo::Mixin::Parser::Web10
|
|
256
|
+
|
|
257
|
+
else
|
|
258
|
+
puts "* Unknown Authentication Type: #{current_prefs[:www_auth][site][:type]}"
|
|
259
|
+
end
|
|
260
|
+
else
|
|
261
|
+
|
|
262
|
+
data = request.join + "\r\n"
|
|
263
|
+
|
|
264
|
+
unless socket.nil?
|
|
265
|
+
socket.print data
|
|
266
|
+
response_header = readHTTPHeader(socket, current_prefs)
|
|
267
|
+
end
|
|
268
|
+
# RESTORE URI FOR HISTORY/LOG
|
|
269
|
+
request.restoreURI(uri_cache)
|
|
270
|
+
|
|
271
|
+
end
|
|
272
|
+
return socket, request, response_header
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
rescue Errno::ECONNREFUSED
|
|
276
|
+
response = error_response "connection refused (#{host}:#{port})"
|
|
277
|
+
socket = nil
|
|
278
|
+
rescue Errno::ECONNRESET
|
|
279
|
+
response = error_response "connection reset (#{host}:#{port})"
|
|
280
|
+
socket = nil
|
|
281
|
+
rescue Errno::ECONNABORTED
|
|
282
|
+
response = error_response "connection aborted (#{host}:#{port})"
|
|
283
|
+
socket = nil
|
|
284
|
+
rescue Errno::EHOSTUNREACH
|
|
285
|
+
response = error_response "host unreachable (#{host}:#{port})"
|
|
286
|
+
socket = nil
|
|
287
|
+
rescue Timeout::Error
|
|
288
|
+
#request = "WATOBO: TimeOut (#{host}:#{port})\n"
|
|
289
|
+
response = error_response "TimeOut (#{host}:#{port})"
|
|
290
|
+
socket = nil
|
|
291
|
+
rescue Errno::ETIMEDOUT
|
|
292
|
+
response = error_response "TimeOut (#{host}:#{port})"
|
|
293
|
+
socket = nil
|
|
294
|
+
rescue Errno::ENOTCONN
|
|
295
|
+
puts "!!!ENOTCONN"
|
|
296
|
+
rescue OpenSSL::SSL::SSLError
|
|
297
|
+
response = error_response "SSL-Error", $!.backtrace.join
|
|
298
|
+
socket = nil
|
|
299
|
+
rescue => bang
|
|
300
|
+
response = error_response "ERROR:", "#{bang}\n#{bang.backtrace}"
|
|
301
|
+
socket = nil
|
|
302
|
+
|
|
303
|
+
puts bang
|
|
304
|
+
puts bang.backtrace if $DEBUG
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
return socket, request, response
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def sidCache()
|
|
311
|
+
#puts @project
|
|
312
|
+
@session[:valid_sids]
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
def setSIDCache(new_cache = {} )
|
|
316
|
+
@session[:valid_sids] = new_cache if new_cache.is_a? Hash
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
# +++ doRequest(request) +++
|
|
320
|
+
# + function:
|
|
321
|
+
#
|
|
322
|
+
def doRequest(request, opts={} )
|
|
323
|
+
begin
|
|
324
|
+
@session.update opts
|
|
325
|
+
# puts "#[#{self.class}]" + @session[:csrf_requests].first.object_id.to_s
|
|
326
|
+
unless @session[:csrf_requests].empty? or @session[:csrf_patterns].empty?
|
|
327
|
+
csrf_cache = Hash.new
|
|
328
|
+
@session[:csrf_requests].each do |req|
|
|
329
|
+
copy = YAML.load(YAML.dump(req))
|
|
330
|
+
copy.map!{|l|
|
|
331
|
+
x = l.strip + "\r\n"
|
|
332
|
+
x = l if l == copy.last
|
|
333
|
+
x
|
|
334
|
+
}
|
|
335
|
+
# now extend the new request with the Watobo mixins
|
|
336
|
+
copy.extend Watobo::Mixin::Parser::Url
|
|
337
|
+
copy.extend Watobo::Mixin::Parser::Web10
|
|
338
|
+
copy.extend Watobo::Mixin::Shaper::Web10
|
|
339
|
+
|
|
340
|
+
# p copy.first
|
|
341
|
+
|
|
342
|
+
updateCSRFToken(csrf_cache, copy)
|
|
343
|
+
socket, csrf_request, csrf_response = sendHTTPRequest(copy, opts)
|
|
344
|
+
puts "= Response Headers:"
|
|
345
|
+
puts csrf_response
|
|
346
|
+
puts "==="
|
|
347
|
+
update_sids(csrf_request.host, csrf_response.headers)
|
|
348
|
+
next if socket.nil?
|
|
349
|
+
# p "*"
|
|
350
|
+
# csrf_response = readHTTPHeader(socket)
|
|
351
|
+
readHTTPBody(socket, csrf_response, csrf_request, opts)
|
|
352
|
+
|
|
353
|
+
next if csrf_response.body.nil?
|
|
354
|
+
update_sids(csrf_request.host, [csrf_response.body])
|
|
355
|
+
|
|
356
|
+
updateCSRFCache(csrf_cache, csrf_request, [csrf_response.body]) if csrf_response.content_type =~ /text\//
|
|
357
|
+
|
|
358
|
+
socket.close
|
|
359
|
+
end
|
|
360
|
+
#p @session[:csrf_requests].length
|
|
361
|
+
updateCSRFToken(csrf_cache, request)
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
socket, request, response = sendHTTPRequest(request, opts)
|
|
365
|
+
|
|
366
|
+
if socket.nil?
|
|
367
|
+
return request, response
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
update_sids(request.host, response.headers) if @session[:update_sids] == true
|
|
371
|
+
|
|
372
|
+
if @session[:follow_redirect]
|
|
373
|
+
# puts response.status
|
|
374
|
+
if response.status =~ /^302/
|
|
375
|
+
response.extend Watobo::Mixin::Parser::Web10
|
|
376
|
+
request.extend Watobo::Mixin::Shaper::Web10
|
|
377
|
+
|
|
378
|
+
loc_header = response.headers("Location:").first
|
|
379
|
+
new_location = loc_header.gsub(/^[^:]*:/,'').strip
|
|
380
|
+
unless new_location =~ /^http/
|
|
381
|
+
new_location = request.proto + "://" + request.site + "/" + request.dir + "/" + new_location.sub(/^[\.\/]*/,'')
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
notify(:follow_redirect, new_location)
|
|
385
|
+
nr = YAML.load(YAML.dump(request))
|
|
386
|
+
nr.extend Watobo::Mixin::Parser::Url
|
|
387
|
+
nr.extend Watobo::Mixin::Parser::Web10
|
|
388
|
+
nr.extend Watobo::Mixin::Shaper::Web10
|
|
389
|
+
# create GET request for new location
|
|
390
|
+
nr.replaceMethod("GET")
|
|
391
|
+
nr.removeHeader("Content-Length")
|
|
392
|
+
nr.removeBody()
|
|
393
|
+
nr.replaceURL(new_location)
|
|
394
|
+
|
|
395
|
+
# puts response
|
|
396
|
+
# puts nr
|
|
397
|
+
puts "send redirect request"
|
|
398
|
+
socket, request, response = sendHTTPRequest(nr, opts)
|
|
399
|
+
puts "= request"
|
|
400
|
+
puts request
|
|
401
|
+
puts "= response"
|
|
402
|
+
puts response
|
|
403
|
+
if socket.nil?
|
|
404
|
+
#return nil, request
|
|
405
|
+
return request, response
|
|
406
|
+
end
|
|
407
|
+
end
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
readHTTPBody(socket, response, request, opts)
|
|
411
|
+
|
|
412
|
+
unless response.body.nil?
|
|
413
|
+
update_sids(request.host, [response.body]) if @session[:update_sids] == true and response.content_type =~ /text\//
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
socket.close
|
|
417
|
+
|
|
418
|
+
rescue => bang
|
|
419
|
+
# puts "! Error in doRequest"
|
|
420
|
+
puts "! Module #{Module.nesting[0].name}"
|
|
421
|
+
puts bang
|
|
422
|
+
# puts bang.backtrace if $DEBUG
|
|
423
|
+
@lasterror = bang
|
|
424
|
+
# raise
|
|
425
|
+
# ensure
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
response.extend Watobo::Mixin::Parser::Web10
|
|
429
|
+
return request, response
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
def addProxy(prefs=nil)
|
|
433
|
+
|
|
434
|
+
# puts "* add proxy"
|
|
435
|
+
# puts prefs.to_yaml
|
|
436
|
+
proxy = nil
|
|
437
|
+
unless prefs.nil?
|
|
438
|
+
proxy = Proxy.new(:name => prefs[:name], :host => prefs[:host], :port => prefs[:port])
|
|
439
|
+
proxy.setCredentials(prefs[:credentials]) unless prefs[:credentials].nil?
|
|
440
|
+
unless prefs[:site].nil?
|
|
441
|
+
@@proxy[prefs[:site]] = proxy
|
|
442
|
+
return
|
|
443
|
+
end
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
@@proxy[:default] = proxy
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
def get_settings
|
|
450
|
+
@@settings
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
def getProxy(site=nil)
|
|
454
|
+
unless site.nil?
|
|
455
|
+
return @@proxy[site] unless @@proxy[site].nil?
|
|
456
|
+
end
|
|
457
|
+
return @@proxy[:default]
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
#
|
|
461
|
+
# INITIALIZE
|
|
462
|
+
#
|
|
463
|
+
# Possible preferences:
|
|
464
|
+
# :proxy => '127.0.0.1:port'
|
|
465
|
+
# :valid_sids => Hash.new,
|
|
466
|
+
# :sid_patterns => [],
|
|
467
|
+
# :logout_signatures => [],
|
|
468
|
+
# :update_valid_sids => false,
|
|
469
|
+
# :update_sids => false,
|
|
470
|
+
# :update_contentlength => true
|
|
471
|
+
def initialize(session_id, prefs={})
|
|
472
|
+
@event_dispatcher_listeners = Hash.new
|
|
473
|
+
# @session = {}
|
|
474
|
+
|
|
475
|
+
session = nil
|
|
476
|
+
|
|
477
|
+
session = ( session_id.is_a? Fixnum ) ? session_id : session_id.object_id
|
|
478
|
+
session = Digest::MD5.hexdigest(Time.now.to_f.to_s) if session_id.nil?
|
|
479
|
+
|
|
480
|
+
unless @@settings.has_key? session
|
|
481
|
+
@@settings[session] = {
|
|
482
|
+
:valid_sids => Hash.new,
|
|
483
|
+
:sid_patterns => [],
|
|
484
|
+
# :valid_csrf_tokens => Hash.new,
|
|
485
|
+
:csrf_patterns => [],
|
|
486
|
+
:csrf_requests => [],
|
|
487
|
+
:logout_signatures => [],
|
|
488
|
+
:logout_content_types => Hash.new,
|
|
489
|
+
:update_valid_sids => false,
|
|
490
|
+
:update_sids => false,
|
|
491
|
+
:update_session => true,
|
|
492
|
+
:update_contentlength => true,
|
|
493
|
+
:login_chats => [],
|
|
494
|
+
:www_auth => Hash.new,
|
|
495
|
+
:client_certificates => {},
|
|
496
|
+
:proxy_auth => Hash.new
|
|
497
|
+
}
|
|
498
|
+
end
|
|
499
|
+
@session = @@settings[session] # shortcut to settings
|
|
500
|
+
@session.update prefs
|
|
501
|
+
|
|
502
|
+
# @valid_csrf_tokens = Hash.new
|
|
503
|
+
|
|
504
|
+
addProxy( prefs[:proxy] ) if prefs.is_a? Hash and prefs[:proxy]
|
|
505
|
+
|
|
506
|
+
@socket = nil
|
|
507
|
+
|
|
508
|
+
@ctx = OpenSSL::SSL::SSLContext.new()
|
|
509
|
+
@ctx.key = nil
|
|
510
|
+
@ctx.cert = nil
|
|
511
|
+
|
|
512
|
+
# TODO: Implement switches for URL-Encoding (http://www.blooberry.com/indexdot/html/topics/urlencoding.htm)
|
|
513
|
+
# TODO: Implement switches for Following Redirects
|
|
514
|
+
# TODO: Implement switches for Logging, Debugging, ...
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
def readHTTPBody(socket, response, request, prefs={})
|
|
518
|
+
clen = response.content_length
|
|
519
|
+
data = ""
|
|
520
|
+
# timeout(5) do
|
|
521
|
+
begin
|
|
522
|
+
if response.is_chunked?
|
|
523
|
+
Watobo::HTTP.readChunkedBody(socket) { |c|
|
|
524
|
+
data += c
|
|
525
|
+
}
|
|
526
|
+
elsif clen > 0
|
|
527
|
+
# puts "* read #{clen} bytes for body"
|
|
528
|
+
Watobo::HTTP.read_body(socket, :max_bytes => clen) { |c|
|
|
529
|
+
data += c
|
|
530
|
+
break if data.length == clen
|
|
531
|
+
}
|
|
532
|
+
else
|
|
533
|
+
# puts "* no content-length information ... mmmmmpf"
|
|
534
|
+
eofcount = 0
|
|
535
|
+
Watobo::HTTP.read_body(socket) do |c|
|
|
536
|
+
data += c
|
|
537
|
+
end
|
|
538
|
+
|
|
539
|
+
end
|
|
540
|
+
rescue => e
|
|
541
|
+
puts "! Could not read response"
|
|
542
|
+
puts e
|
|
543
|
+
# puts e.backtrace
|
|
544
|
+
end
|
|
545
|
+
# end
|
|
546
|
+
|
|
547
|
+
response.push data
|
|
548
|
+
unless prefs[:ignore_logout]==true or @session[:logout_signatures].empty?
|
|
549
|
+
notify(:logout, self) if loggedOut?(response)
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
update_sids(request.host, response) if prefs[:update_sids] == true
|
|
553
|
+
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
private
|
|
557
|
+
|
|
558
|
+
#def doNtlmAuth(socket, request, ntlm_credentials)
|
|
559
|
+
def wwwAuthNTLM(socket, request, ntlm_credentials)
|
|
560
|
+
response_header = nil
|
|
561
|
+
begin
|
|
562
|
+
auth_request = Watobo::Utils::copyObject(request)
|
|
563
|
+
auth_request.extend Watobo::Mixin::Parser::Url
|
|
564
|
+
auth_request.extend Watobo::Mixin::Parser::Web10
|
|
565
|
+
auth_request.extend Watobo::Mixin::Shaper::Web10
|
|
566
|
+
|
|
567
|
+
ntlm_challenge = nil
|
|
568
|
+
t1 = Net::NTLM::Message::Type1.new()
|
|
569
|
+
msg = "NTLM " + t1.encode64
|
|
570
|
+
|
|
571
|
+
auth_request.removeHeader("Connection")
|
|
572
|
+
auth_request.removeHeader("Authorization")
|
|
573
|
+
|
|
574
|
+
auth_request.addHeader("Authorization", msg)
|
|
575
|
+
auth_request.addHeader("Connection", "Keep-Alive")
|
|
576
|
+
|
|
577
|
+
# puts "============= T1 ======================="
|
|
578
|
+
# puts auth_request
|
|
579
|
+
data = auth_request.join + "\r\n"
|
|
580
|
+
#puts "= REQUEST ="
|
|
581
|
+
|
|
582
|
+
socket.print data
|
|
583
|
+
# puts "-----------------"
|
|
584
|
+
response_header = []
|
|
585
|
+
rcode = nil
|
|
586
|
+
clen = nil
|
|
587
|
+
ntlm_challenge = nil
|
|
588
|
+
response_header = readHTTPHeader(socket)
|
|
589
|
+
response_header.each do |line|
|
|
590
|
+
if line =~ /^HTTP\/\d\.\d (\d+) (.*)/ then
|
|
591
|
+
rcode = $1.to_i
|
|
592
|
+
rmsg = $2
|
|
593
|
+
end
|
|
594
|
+
if line =~ /^WWW-Authenticate: (NTLM) (.+)\r\n/
|
|
595
|
+
ntlm_challenge = $2
|
|
596
|
+
end
|
|
597
|
+
if line =~ /^Content-Length: (\d{1,})\r\n/
|
|
598
|
+
clen = $1.to_i
|
|
599
|
+
end
|
|
600
|
+
break if line.strip.empty?
|
|
601
|
+
end
|
|
602
|
+
# puts "==================="
|
|
603
|
+
|
|
604
|
+
#if rcode == 200 # Ok
|
|
605
|
+
# puts "* seems request doesn't need authentication"
|
|
606
|
+
# return socket, response_header
|
|
607
|
+
if rcode == 401 #Authentication Required
|
|
608
|
+
puts "* got ntlm challenge: #{ntlm_challenge}" if $DEBUG
|
|
609
|
+
return socket, response_header if ntlm_challenge.nil?
|
|
610
|
+
else
|
|
611
|
+
# puts "! arrgh .... :("
|
|
612
|
+
# puts response_header
|
|
613
|
+
return socket, response_header
|
|
614
|
+
end
|
|
615
|
+
|
|
616
|
+
# reading rest of response
|
|
617
|
+
Watobo::HTTP.read_body(socket, :max_bytes => clen){ |d| }
|
|
618
|
+
|
|
619
|
+
t2 = Net::NTLM::Message.decode64(ntlm_challenge)
|
|
620
|
+
t3 = t2.response({:user => ntlm_credentials[:username],
|
|
621
|
+
:password => ntlm_credentials[:password],
|
|
622
|
+
:domain => ntlm_credentials[:domain]},
|
|
623
|
+
{:workstation => ntlm_credentials[:workstation], :ntlmv2 => true})
|
|
624
|
+
|
|
625
|
+
# puts "* NTLM-Credentials: #{ntlm_credentials[:username]},#{ntlm_credentials[:password]}, #{ntlm_credentials[:domain]}, #{ntlm_credentials[:workstation]}"
|
|
626
|
+
auth_request.removeHeader("Authorization")
|
|
627
|
+
auth_request.removeHeader("Connection")
|
|
628
|
+
|
|
629
|
+
auth_request.addHeader("Connection", "Close")
|
|
630
|
+
|
|
631
|
+
msg = "NTLM " + t3.encode64
|
|
632
|
+
auth_request.addHeader("Authorization", msg)
|
|
633
|
+
# puts "============= T3 ======================="
|
|
634
|
+
|
|
635
|
+
data = auth_request.join + "\r\n"
|
|
636
|
+
|
|
637
|
+
if $DEBUG
|
|
638
|
+
puts "= NTLM Type 3 ="
|
|
639
|
+
puts data
|
|
640
|
+
end
|
|
641
|
+
socket.print data
|
|
642
|
+
|
|
643
|
+
response_header = []
|
|
644
|
+
response_header = readHTTPHeader(socket)
|
|
645
|
+
response_header.each do |line|
|
|
646
|
+
|
|
647
|
+
if line =~ /^HTTP\/\d\.\d (\d+) (.*)/ then
|
|
648
|
+
rcode = $1.to_i
|
|
649
|
+
rmsg = $2
|
|
650
|
+
end
|
|
651
|
+
break if line.strip.empty?
|
|
652
|
+
end
|
|
653
|
+
|
|
654
|
+
if rcode == 200 # Ok
|
|
655
|
+
# puts "* authentication successfull [OK]"
|
|
656
|
+
elsif rcode == 401 # Authentication Required
|
|
657
|
+
# TODO: authorization didn't work -> do some notification
|
|
658
|
+
# ...
|
|
659
|
+
puts "* could not authenticate with the following credentials:"
|
|
660
|
+
puts ntlm_credentials.to_yaml
|
|
661
|
+
end
|
|
662
|
+
|
|
663
|
+
return socket, response_header
|
|
664
|
+
rescue => bang
|
|
665
|
+
puts "!!! ERROR: in ntlm_auth"
|
|
666
|
+
puts bang
|
|
667
|
+
|
|
668
|
+
puts bang.backtrace if $DEBUG
|
|
669
|
+
return nil, nil
|
|
670
|
+
end
|
|
671
|
+
end
|
|
672
|
+
|
|
673
|
+
def sslConnect(tcp_socket, current_prefs = {} )
|
|
674
|
+
begin
|
|
675
|
+
# @ctx = OpenSSL::SSL::SSLContext.new()
|
|
676
|
+
# @ctx.key = nil
|
|
677
|
+
# @ctx.cert = nil
|
|
678
|
+
ctx = OpenSSL::SSL::SSLContext.new()
|
|
679
|
+
ctx.ciphers = current_prefs[:ssl_cipher] if current_prefs.has_key? :ssl_cipher
|
|
680
|
+
|
|
681
|
+
if current_prefs.has_key? :ssl_client_cert and current_prefs.has_key? :ssl_client_key
|
|
682
|
+
|
|
683
|
+
ctx.cert = current_prefs[:ssl_client_cert]
|
|
684
|
+
ctx.key = current_prefs[:ssl_client_key]
|
|
685
|
+
if $DEBUG
|
|
686
|
+
puts "* using client certificates"
|
|
687
|
+
puts "= CERT ="
|
|
688
|
+
# puts @ctx.cert.methods.sort
|
|
689
|
+
puts ctx.cert.display
|
|
690
|
+
puts "---"
|
|
691
|
+
p
|
|
692
|
+
puts "= KEY ="
|
|
693
|
+
puts ctx.key.display
|
|
694
|
+
puts "---"
|
|
695
|
+
end
|
|
696
|
+
|
|
697
|
+
|
|
698
|
+
end
|
|
699
|
+
# @ctx.tmp_dh_callback = proc { |*args|
|
|
700
|
+
# OpenSSL::PKey::DH.new(128)
|
|
701
|
+
#}
|
|
702
|
+
|
|
703
|
+
socket = OpenSSL::SSL::SSLSocket.new(tcp_socket, ctx)
|
|
704
|
+
|
|
705
|
+
socket.connect
|
|
706
|
+
socket.setsockopt( Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
|
|
707
|
+
puts "* socket status: #{socket.state}" if $DEBUG
|
|
708
|
+
return socket
|
|
709
|
+
rescue => bang
|
|
710
|
+
if current_prefs[:ssl_cipher].nil?
|
|
711
|
+
puts "!sslConnect"
|
|
712
|
+
puts bang
|
|
713
|
+
puts bang.backtrace if $DEBUG
|
|
714
|
+
end
|
|
715
|
+
end
|
|
716
|
+
end
|
|
717
|
+
|
|
718
|
+
# SSLProxyConnect
|
|
719
|
+
# return SSLSocket, ResponseHeader of ConnectionSetup
|
|
720
|
+
def sslProxyConnect(orig_request, proxy, prefs)
|
|
721
|
+
begin
|
|
722
|
+
tcp_socket = nil
|
|
723
|
+
response_header = []
|
|
724
|
+
|
|
725
|
+
request = Watobo::Utils::copyObject(orig_request)
|
|
726
|
+
request.extend Watobo::Mixin::Parser::Url
|
|
727
|
+
request.extend Watobo::Mixin::Parser::Web10
|
|
728
|
+
request.extend Watobo::Mixin::Shaper::Web10
|
|
729
|
+
# timeout(6) do
|
|
730
|
+
|
|
731
|
+
tcp_socket = TCPSocket.new( proxy.host, proxy.port)
|
|
732
|
+
tcp_socket.setsockopt( Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
|
|
733
|
+
tcp_socket.sync = true
|
|
734
|
+
# end
|
|
735
|
+
# puts "* sslProxyConnect"
|
|
736
|
+
# puts "Host: #{request.host}"
|
|
737
|
+
# puts "Port: #{request.port}"
|
|
738
|
+
# setup request
|
|
739
|
+
dummy = "CONNECT #{request.host}:#{request.port} HTTP/1.0\r\n"
|
|
740
|
+
request.shift
|
|
741
|
+
request.unshift dummy
|
|
742
|
+
|
|
743
|
+
request.removeHeader("Proxy-Connection")
|
|
744
|
+
request.removeHeader("Connection")
|
|
745
|
+
request.removeHeader("Content-Length")
|
|
746
|
+
request.removeBody()
|
|
747
|
+
request.addHeader("Proxy-Connection", "Keep-Alive")
|
|
748
|
+
request.addHeader("Pragma", "no-cache")
|
|
749
|
+
|
|
750
|
+
# puts "=== sslProxyConnect ==="
|
|
751
|
+
# puts request
|
|
752
|
+
|
|
753
|
+
if proxy.has_login?
|
|
754
|
+
case proxy.login[:type]
|
|
755
|
+
when AUTH_TYPE_NTLM
|
|
756
|
+
|
|
757
|
+
ntlm_challenge = nil
|
|
758
|
+
t1 = Net::NTLM::Message::Type1.new()
|
|
759
|
+
msg = "NTLM " + t1.encode64
|
|
760
|
+
request.addHeader("Proxy-Authorization", msg)
|
|
761
|
+
|
|
762
|
+
# puts "============= T1 ======================="
|
|
763
|
+
# puts request
|
|
764
|
+
data = request.join + "\r\n"
|
|
765
|
+
|
|
766
|
+
tcp_socket.print data
|
|
767
|
+
# puts "-----------------"
|
|
768
|
+
while (line = tcp_socket.gets)
|
|
769
|
+
response_header.push line
|
|
770
|
+
# puts line
|
|
771
|
+
if line =~ /^HTTP\/\d\.\d (\d+) (.*)/ then
|
|
772
|
+
rcode = $1.to_i
|
|
773
|
+
rmsg = $2
|
|
774
|
+
end
|
|
775
|
+
if line =~ /^Proxy-Authenticate: (NTLM) (.+)\r\n/
|
|
776
|
+
ntlm_challenge = $2
|
|
777
|
+
end
|
|
778
|
+
break if line.strip.empty?
|
|
779
|
+
end
|
|
780
|
+
|
|
781
|
+
Watobo::HTTP.read_body(tcp_socket) { |d|
|
|
782
|
+
# puts d
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
if rcode == 200 # Ok
|
|
786
|
+
puts "* seems proxy doesn't require authentication"
|
|
787
|
+
socket = sslConnect(tcp_socket, prefs)
|
|
788
|
+
return socket, response_header
|
|
789
|
+
end
|
|
790
|
+
|
|
791
|
+
return socket, response_header if ntlm_challenge.nil? or ntlm_challenge == ""
|
|
792
|
+
|
|
793
|
+
t2 = Net::NTLM::Message.decode64(ntlm_challenge)
|
|
794
|
+
t3 = t2.response( { :user => proxy.login[:username],
|
|
795
|
+
:password => proxy.login[:password],
|
|
796
|
+
:domain => proxy.login[:domain] },
|
|
797
|
+
{ :workstation => proxy.login[:workstation], :ntlmv2 => true } )
|
|
798
|
+
request.removeHeader("Proxy-Authorization")
|
|
799
|
+
|
|
800
|
+
msg = "NTLM " + t3.encode64
|
|
801
|
+
request.addHeader("Proxy-Authorization", msg)
|
|
802
|
+
# puts "============= T3 ======================="
|
|
803
|
+
# puts request
|
|
804
|
+
data = request.join + "\r\n"
|
|
805
|
+
|
|
806
|
+
tcp_socket.print data
|
|
807
|
+
# puts "-----------------"
|
|
808
|
+
|
|
809
|
+
response_header = []
|
|
810
|
+
rcode = 0
|
|
811
|
+
response_header = readHTTPHeader(tcp_socket)
|
|
812
|
+
rcode = response_header.status
|
|
813
|
+
if rcode =~/^200/ # Ok
|
|
814
|
+
puts "* proxy authentication successfull"
|
|
815
|
+
elsif rcode =~ /^407/ # ProxyAuthentication Required
|
|
816
|
+
# if rcode is still 407 authentication didn't work -> break
|
|
817
|
+
return nil
|
|
818
|
+
else
|
|
819
|
+
puts "! check proxy connection [FALSE]"
|
|
820
|
+
puts "> #{rcode} #{rmsg} <"
|
|
821
|
+
end
|
|
822
|
+
|
|
823
|
+
socket = sslConnect(tcp_socket, prefs)
|
|
824
|
+
return socket, response_header
|
|
825
|
+
end
|
|
826
|
+
end # END OF PROXY AUTH
|
|
827
|
+
|
|
828
|
+
# Start ProxyConnect Without Authentication
|
|
829
|
+
data = request.join + "\r\n"
|
|
830
|
+
tcp_socket.print data
|
|
831
|
+
# puts "-----------------"
|
|
832
|
+
|
|
833
|
+
response_header = []
|
|
834
|
+
response_header = readHTTPHeader(tcp_socket)
|
|
835
|
+
rcode = response_header.status
|
|
836
|
+
if rcode =~ /^200/ # Ok
|
|
837
|
+
# puts "* proxy connection successfull"
|
|
838
|
+
elsif rcode =~ /^407/ # ProxyAuthentication Required
|
|
839
|
+
# if rcode is still 407 authentication didn't work -> break
|
|
840
|
+
|
|
841
|
+
else
|
|
842
|
+
puts "! check proxy connection [FALSE]"
|
|
843
|
+
puts "> #{rcode} #{rmsg} <"
|
|
844
|
+
end
|
|
845
|
+
|
|
846
|
+
socket = sslConnect(tcp_socket, prefs)
|
|
847
|
+
return socket, response_header
|
|
848
|
+
rescue => bang
|
|
849
|
+
puts bang
|
|
850
|
+
return nil, bang
|
|
851
|
+
end
|
|
852
|
+
# return nil, nil
|
|
853
|
+
end
|
|
854
|
+
|
|
855
|
+
# proxyAuthNTLM
|
|
856
|
+
# returns: ResponseHeaders
|
|
857
|
+
def proxyAuthNTLM(tcp_socket, orig_request, credentials)
|
|
858
|
+
|
|
859
|
+
request = Watobo::Utils::copyObject(orig_request)
|
|
860
|
+
request.extend Watobo::Mixin::Parser::Url
|
|
861
|
+
request.extend Watobo::Mixin::Parser::Web10
|
|
862
|
+
request.extend Watobo::Mixin::Shaper::Web10
|
|
863
|
+
|
|
864
|
+
request.removeHeader("Proxy-Authorization")
|
|
865
|
+
request.removeHeader("Proxy-Connection")
|
|
866
|
+
|
|
867
|
+
response_header = []
|
|
868
|
+
|
|
869
|
+
ntlm_challenge = nil
|
|
870
|
+
t1 = Net::NTLM::Message::Type1.new()
|
|
871
|
+
msg = "NTLM " + t1.encode64
|
|
872
|
+
|
|
873
|
+
request.addHeader("Proxy-Authorization", msg)
|
|
874
|
+
request.addHeader("Proxy-Connection", "Keep-Alive")
|
|
875
|
+
|
|
876
|
+
# puts "============= T1 ======================="
|
|
877
|
+
# puts auth_request
|
|
878
|
+
data = request.join + "\r\n"
|
|
879
|
+
|
|
880
|
+
tcp_socket.print data
|
|
881
|
+
# puts "-----------------"
|
|
882
|
+
response_header = readHTTPHeader(tcp_socket)
|
|
883
|
+
rcode = nil
|
|
884
|
+
rmsg = nil
|
|
885
|
+
ntlm_challenge = nil
|
|
886
|
+
clen = 0
|
|
887
|
+
response_header.each do |line|
|
|
888
|
+
# puts line
|
|
889
|
+
if line =~ /^HTTP\/\d\.\d (\d+) (.*)/ then
|
|
890
|
+
rcode = $1.to_i
|
|
891
|
+
rmsg = $2
|
|
892
|
+
end
|
|
893
|
+
if line =~ /^Proxy-Authenticate: (NTLM) (.+)\r\n/
|
|
894
|
+
ntlm_challenge = $2
|
|
895
|
+
end
|
|
896
|
+
if line =~ /^Content-Length: (\d{1,})\r\n/
|
|
897
|
+
clen = $1.to_i
|
|
898
|
+
end
|
|
899
|
+
break if line.strip.empty?
|
|
900
|
+
end
|
|
901
|
+
|
|
902
|
+
#puts "* reading #{clen} bytes"
|
|
903
|
+
|
|
904
|
+
if rcode == 407 # ProxyAuthentication Required
|
|
905
|
+
return response_header if ntlm_challenge.nil? or ntlm_challenge == ""
|
|
906
|
+
else
|
|
907
|
+
puts "* no proxy authentication required!"
|
|
908
|
+
return response_header
|
|
909
|
+
end
|
|
910
|
+
|
|
911
|
+
Watobo::HTTP.read_body(tcp_socket, :max_bytes => clen){ |d|
|
|
912
|
+
#puts d
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
t2 = Net::NTLM::Message.decode64(ntlm_challenge)
|
|
916
|
+
t3 = t2.response({:user => credentials[:username], :password => credentials[:password], :workstation => credentials[:workstation], :domain => credentials[:domain]}, {:ntlmv2 => true})
|
|
917
|
+
request.removeHeader("Proxy-Authorization")
|
|
918
|
+
# request.removeHeader("Proxy-Connection")
|
|
919
|
+
|
|
920
|
+
# request.addHeader("Proxy-Connection", "Close")
|
|
921
|
+
# request.addHeader("Pragma", "no-cache")
|
|
922
|
+
msg = "NTLM " + t3.encode64
|
|
923
|
+
request.addHeader("Proxy-Authorization", msg)
|
|
924
|
+
# puts "============= T3 ======================="
|
|
925
|
+
# puts request
|
|
926
|
+
# puts "------------------------"
|
|
927
|
+
data = request.join + "\r\n"
|
|
928
|
+
tcp_socket.print data
|
|
929
|
+
|
|
930
|
+
response_header = readHTTPHeader(tcp_socket)
|
|
931
|
+
response_header.each do |line|
|
|
932
|
+
# puts line
|
|
933
|
+
if line =~ /^HTTP\/\d\.\d (\d+) (.*)/ then
|
|
934
|
+
rcode = $1.to_i
|
|
935
|
+
rmsg = $2
|
|
936
|
+
end
|
|
937
|
+
if line =~ /^Proxy-Authenticate: (NTLM) (.+)\r\n/
|
|
938
|
+
ntlm_challenge = $2
|
|
939
|
+
end
|
|
940
|
+
if line =~ /^Content-Length: (\d{1,})\r\n/
|
|
941
|
+
clen = $1.to_i
|
|
942
|
+
end
|
|
943
|
+
break if line.strip.empty?
|
|
944
|
+
end
|
|
945
|
+
# Watobo::HTTP.read_body(tcp_socket, :max_bytes => clen){ |d|
|
|
946
|
+
#puts d
|
|
947
|
+
# }
|
|
948
|
+
return response_header
|
|
949
|
+
end
|
|
950
|
+
|
|
951
|
+
#
|
|
952
|
+
# doProxyAuth
|
|
953
|
+
#
|
|
954
|
+
def doProxyAuth(tcp_socket, orig_request, credentials)
|
|
955
|
+
response_headers = nil
|
|
956
|
+
case credentials[:type]
|
|
957
|
+
when AUTH_TYPE_NTLM
|
|
958
|
+
return proxyAuthNTLM(tcp_socket, orig_request, credentials)
|
|
959
|
+
|
|
960
|
+
end # END OF NTLM
|
|
961
|
+
|
|
962
|
+
end
|
|
963
|
+
|
|
964
|
+
##################################################
|
|
965
|
+
# doProxyRequest
|
|
966
|
+
################################################
|
|
967
|
+
def doProxyRequest(request, proxy, prefs={})
|
|
968
|
+
|
|
969
|
+
begin
|
|
970
|
+
tcp_socket = nil
|
|
971
|
+
site = request.site
|
|
972
|
+
|
|
973
|
+
auth_request = Watobo::Utils::copyObject(request)
|
|
974
|
+
auth_request.extend Watobo::Mixin::Parser::Url
|
|
975
|
+
auth_request.extend Watobo::Mixin::Parser::Web10
|
|
976
|
+
auth_request.extend Watobo::Mixin::Shaper::Web10
|
|
977
|
+
# timeout(6) do
|
|
978
|
+
|
|
979
|
+
tcp_socket = TCPSocket.new( proxy.host, proxy.port)
|
|
980
|
+
tcp_socket.setsockopt( Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
|
|
981
|
+
tcp_socket.sync = true
|
|
982
|
+
# end
|
|
983
|
+
|
|
984
|
+
auth_request.removeHeader("Proxy-Connection")
|
|
985
|
+
auth_request.removeHeader("Connection")
|
|
986
|
+
|
|
987
|
+
auth_request.addHeader("Pragma", "no-cache")
|
|
988
|
+
|
|
989
|
+
if proxy.has_login?
|
|
990
|
+
request_header = doProxyAuth(tcp_socket, auth_request, proxy.login)
|
|
991
|
+
# puts "* got request_header from doProxy Auth"
|
|
992
|
+
# puts request_header.class
|
|
993
|
+
return tcp_socket, request_header
|
|
994
|
+
end
|
|
995
|
+
|
|
996
|
+
if prefs[:www_auth].has_key?(site)
|
|
997
|
+
case prefs[:www_auth][site][:type]
|
|
998
|
+
when AUTH_TYPE_NTLM
|
|
999
|
+
# puts "* found NTLM credentials for site #{site}"
|
|
1000
|
+
socket, response_header = wwwAuthNTLM(tcp_socket, request, prefs[:www_auth][site])
|
|
1001
|
+
|
|
1002
|
+
response_header.extend Watobo::Mixin::Parser::Url
|
|
1003
|
+
response_header.extend Watobo::Mixin::Parser::Web10
|
|
1004
|
+
return socket, response_header
|
|
1005
|
+
else
|
|
1006
|
+
puts "* Unknown Authentication Type: #{prefs[:www_auth][site][:type]}"
|
|
1007
|
+
end
|
|
1008
|
+
else
|
|
1009
|
+
data = auth_request.join + "\r\n"
|
|
1010
|
+
|
|
1011
|
+
tcp_socket.print data
|
|
1012
|
+
|
|
1013
|
+
request_header = readHTTPHeader(tcp_socket)
|
|
1014
|
+
return tcp_socket, request_header
|
|
1015
|
+
end
|
|
1016
|
+
rescue => bang
|
|
1017
|
+
puts bang
|
|
1018
|
+
puts bang.backtrace if $DEBUG
|
|
1019
|
+
|
|
1020
|
+
end
|
|
1021
|
+
return nil
|
|
1022
|
+
end
|
|
1023
|
+
|
|
1024
|
+
def loggedOut?(response, prefs={})
|
|
1025
|
+
begin
|
|
1026
|
+
return false if @session[:logout_signatures].empty?
|
|
1027
|
+
response.each do |line|
|
|
1028
|
+
@session[:logout_signatures].each do |p|
|
|
1029
|
+
# puts "!!!*LOGOUT*!!!" if line =~ /#{p}/
|
|
1030
|
+
return true if line =~ /#{p}/
|
|
1031
|
+
end
|
|
1032
|
+
end
|
|
1033
|
+
rescue => bang
|
|
1034
|
+
puts bang
|
|
1035
|
+
puts bang.backtrace if $DEBUG
|
|
1036
|
+
end
|
|
1037
|
+
return false
|
|
1038
|
+
end
|
|
1039
|
+
|
|
1040
|
+
def error_response(msg, comment=nil)
|
|
1041
|
+
er = []
|
|
1042
|
+
er << "HTTP/1.1 504 Gateway Timeout\r\n"
|
|
1043
|
+
er << "WATOBO: #{msg}\r\n"
|
|
1044
|
+
er << "Content-Length: 0\r\n"
|
|
1045
|
+
er << "Connection: close\r\n"
|
|
1046
|
+
er << "\r\n"
|
|
1047
|
+
er << "<H1>#{msg}</H1>"
|
|
1048
|
+
er << "<H2>#{comment}</H2>" unless comment.nil?
|
|
1049
|
+
er.extend Watobo::Mixin::Parser::Url
|
|
1050
|
+
er.extend Watobo::Mixin::Parser::Web10
|
|
1051
|
+
er.extend Watobo::Mixin::Shaper::Web10
|
|
1052
|
+
er.fix_content_length
|
|
1053
|
+
er
|
|
1054
|
+
end
|
|
1055
|
+
|
|
1056
|
+
def readHTTPHeader(socket, prefs={})
|
|
1057
|
+
header = []
|
|
1058
|
+
msg = nil
|
|
1059
|
+
begin
|
|
1060
|
+
Watobo::HTTP.read_header(socket) do |line|
|
|
1061
|
+
# puts line.unpack("H*")
|
|
1062
|
+
header.push line
|
|
1063
|
+
end
|
|
1064
|
+
rescue Errno::ECONNRESET
|
|
1065
|
+
msg = "<html><head><title>WATOBO</title></head><body>WATOBO: Connection Reset By Peer</body></html>"
|
|
1066
|
+
rescue Timeout::Error
|
|
1067
|
+
msg = "<html><head><title>WATOBO</title></head><body>WATOBO: Timeout</body></html>"
|
|
1068
|
+
rescue => bang
|
|
1069
|
+
puts "!ERROR: read_header"
|
|
1070
|
+
return nil
|
|
1071
|
+
end
|
|
1072
|
+
|
|
1073
|
+
header = [ "HTTP/1.1 200 OK\r\n", "Server: WATOBO\r\n", "Content-Length: #{msg.length.to_i}\r\n", "Content-Type: text/html\r\n", "\r\n", "#{msg}" ] unless msg.nil?
|
|
1074
|
+
|
|
1075
|
+
header.extend Watobo::Mixin::Parser::Url
|
|
1076
|
+
header.extend Watobo::Mixin::Parser::Web10
|
|
1077
|
+
# update_sids(header)
|
|
1078
|
+
|
|
1079
|
+
# update_sids(request.site, response) if prefs[:update_sids] == true
|
|
1080
|
+
|
|
1081
|
+
unless prefs[:ignore_logout]==true or @session[:logout_signatures].empty?
|
|
1082
|
+
notify(:logout, self) if loggedOut?(header)
|
|
1083
|
+
end
|
|
1084
|
+
|
|
1085
|
+
return header
|
|
1086
|
+
end
|
|
1087
|
+
|
|
1088
|
+
# def read_response(socket)
|
|
1089
|
+
|
|
1090
|
+
# return response
|
|
1091
|
+
# end
|
|
1092
|
+
|
|
1093
|
+
def update_sids(host, response)
|
|
1094
|
+
# p "* update sids"
|
|
1095
|
+
Thread.new{
|
|
1096
|
+
begin
|
|
1097
|
+
#site = request.site
|
|
1098
|
+
@@session_lock.synchronize do
|
|
1099
|
+
response.each do |line|
|
|
1100
|
+
# puts line
|
|
1101
|
+
@session[:sid_patterns].each do |pat|
|
|
1102
|
+
if line =~ /#{pat}/i then
|
|
1103
|
+
sid_key = Regexp.quote($1.upcase)
|
|
1104
|
+
sid_value = $2
|
|
1105
|
+
#print "U"
|
|
1106
|
+
# puts "GOT NEW SID (#{sid_key}): #{sid_value}"
|
|
1107
|
+
@session[:valid_sids][host] = Hash.new if @session[:valid_sids][host].nil?
|
|
1108
|
+
@session[:valid_sids][host][sid_key] = sid_value
|
|
1109
|
+
end
|
|
1110
|
+
end
|
|
1111
|
+
|
|
1112
|
+
end
|
|
1113
|
+
end
|
|
1114
|
+
rescue => bang
|
|
1115
|
+
puts bang
|
|
1116
|
+
puts bang.backtrace if $DEBUG
|
|
1117
|
+
|
|
1118
|
+
end
|
|
1119
|
+
}
|
|
1120
|
+
end
|
|
1121
|
+
|
|
1122
|
+
def updateCSRFCache(csrf_cache, request, response)
|
|
1123
|
+
puts "=UPDATE CSRF CACHE" if $DEBUG
|
|
1124
|
+
# Thread.new{
|
|
1125
|
+
begin
|
|
1126
|
+
# site = request.site
|
|
1127
|
+
@@csrf_lock.synchronize do
|
|
1128
|
+
response.each do |line|
|
|
1129
|
+
# puts line
|
|
1130
|
+
@session[:csrf_patterns].each do |pat|
|
|
1131
|
+
puts pat if $DEBUG
|
|
1132
|
+
if line =~ /#{pat}/i then
|
|
1133
|
+
token_key = Regexp.quote($1.upcase)
|
|
1134
|
+
token_value = $2
|
|
1135
|
+
#print "U"
|
|
1136
|
+
puts "GOT NEW TOKEN (#{token_key}): #{token_value}" if $DEBUG
|
|
1137
|
+
# @session[:valid_csrf_tokens][site] = Hash.new if @session[:valid_csrf_tokens][site].nil?
|
|
1138
|
+
# @session[:valid_csrf_tokens][site][token_key] = token_value
|
|
1139
|
+
csrf_cache[token_key] = token_value
|
|
1140
|
+
end
|
|
1141
|
+
end
|
|
1142
|
+
|
|
1143
|
+
end
|
|
1144
|
+
end
|
|
1145
|
+
rescue => bang
|
|
1146
|
+
puts bang
|
|
1147
|
+
if $DEBUG
|
|
1148
|
+
puts bang.backtrace
|
|
1149
|
+
puts "= Request"
|
|
1150
|
+
puts request
|
|
1151
|
+
puts "= Response"
|
|
1152
|
+
puts response
|
|
1153
|
+
puts "==="
|
|
1154
|
+
end
|
|
1155
|
+
|
|
1156
|
+
end
|
|
1157
|
+
# }
|
|
1158
|
+
end
|
|
1159
|
+
|
|
1160
|
+
def closeSocket(socket)
|
|
1161
|
+
#puts socket.class
|
|
1162
|
+
begin
|
|
1163
|
+
#puts socket.class
|
|
1164
|
+
#if socket.class.to_s =~ /SSLSocket/
|
|
1165
|
+
if socket.is_a? OpenSSL::SSL::SSLSocket
|
|
1166
|
+
socket.io.shutdown(2)
|
|
1167
|
+
else
|
|
1168
|
+
socket.shutdown(2)
|
|
1169
|
+
end
|
|
1170
|
+
socket.close
|
|
1171
|
+
rescue => bang
|
|
1172
|
+
puts bang
|
|
1173
|
+
puts bang.backtrace if $DEBUG
|
|
1174
|
+
end
|
|
1175
|
+
end
|
|
1176
|
+
|
|
1177
|
+
def updateSessionSettings(settings={})
|
|
1178
|
+
[
|
|
1179
|
+
:ssl_client_cert,
|
|
1180
|
+
:ssl_client_key,
|
|
1181
|
+
:ssl_client_pass,
|
|
1182
|
+
:csrf_requests,
|
|
1183
|
+
:valid_sids,
|
|
1184
|
+
:sid_patterns,
|
|
1185
|
+
:logout_signatures,
|
|
1186
|
+
:logout_content_types,
|
|
1187
|
+
:update_valid_sids,
|
|
1188
|
+
:update_sids,
|
|
1189
|
+
:update_session,
|
|
1190
|
+
:update_contentlength,
|
|
1191
|
+
:login_chats,
|
|
1192
|
+
:follow_redirect
|
|
1193
|
+
].each do |k|
|
|
1194
|
+
@session[k] = settings[k] if settings.has_key? k
|
|
1195
|
+
end
|
|
1196
|
+
end
|
|
1197
|
+
|
|
1198
|
+
def updateSession(request)
|
|
1199
|
+
@@session_lock.synchronize do
|
|
1200
|
+
if @session[:valid_sids].has_key?(request.host)
|
|
1201
|
+
# puts "* found sid for site: #{request.site}"
|
|
1202
|
+
request.map!{ |line|
|
|
1203
|
+
res = line
|
|
1204
|
+
@session[:sid_patterns].each do |pat|
|
|
1205
|
+
begin
|
|
1206
|
+
if line =~ /#{pat}/i then
|
|
1207
|
+
next if $~.length < 3
|
|
1208
|
+
sid_key = Regexp.quote($1.upcase)
|
|
1209
|
+
old_value = $2
|
|
1210
|
+
|
|
1211
|
+
if @session[:valid_sids][request.host].has_key?(sid_key) then
|
|
1212
|
+
if not old_value =~ /#{@session[:valid_sids][request.host][sid_key]}/ then # sid value has changed and needs update
|
|
1213
|
+
Watobo.print_debug("update session", "#{old_value} - #{@session[:valid_sids][request.host][sid_key]}") if $DEBUG
|
|
1214
|
+
|
|
1215
|
+
res = line.gsub!(/#{Regexp.quote(old_value)}/, @session[:valid_sids][request.host][sid_key])
|
|
1216
|
+
|
|
1217
|
+
if not res then puts "!!!could not update sid (#{sid_key})"; end
|
|
1218
|
+
|
|
1219
|
+
end
|
|
1220
|
+
end
|
|
1221
|
+
end
|
|
1222
|
+
rescue => bang
|
|
1223
|
+
puts bang
|
|
1224
|
+
puts bang.backtrace if $DEBUG
|
|
1225
|
+
# puts @session.to_yaml
|
|
1226
|
+
end
|
|
1227
|
+
end
|
|
1228
|
+
res
|
|
1229
|
+
}
|
|
1230
|
+
end
|
|
1231
|
+
end
|
|
1232
|
+
end
|
|
1233
|
+
|
|
1234
|
+
def updateCSRFToken(csrf_cache, request)
|
|
1235
|
+
# puts "=UPDATE CSRF TOKEN"
|
|
1236
|
+
# @session[:valid_csrf_tokens].to_yaml
|
|
1237
|
+
# puts request if request.site.nil?
|
|
1238
|
+
# puts "= = = = = = "
|
|
1239
|
+
@@csrf_lock.synchronize do
|
|
1240
|
+
# if @session[:valid_csrf_tokens].has_key?(request.site)
|
|
1241
|
+
# puts "* found token for site: #{request.site}"
|
|
1242
|
+
|
|
1243
|
+
request.map!{ |line|
|
|
1244
|
+
res = line
|
|
1245
|
+
@session[:csrf_patterns].each do |pat|
|
|
1246
|
+
begin
|
|
1247
|
+
if line =~ /#{pat}/i then
|
|
1248
|
+
key = Regexp.quote($1.upcase)
|
|
1249
|
+
old_value = $2
|
|
1250
|
+
# if @session[:valid_csrf_tokens][request.site].has_key?(key) then
|
|
1251
|
+
if csrf_cache.has_key?(key) then
|
|
1252
|
+
res = line.gsub!(/#{Regexp.quote(old_value)}/, csrf_cache[key])
|
|
1253
|
+
if res.nil? then
|
|
1254
|
+
res = line
|
|
1255
|
+
puts "!!!could not update token (#{key})"
|
|
1256
|
+
end
|
|
1257
|
+
# puts "->#{line}"
|
|
1258
|
+
|
|
1259
|
+
#end
|
|
1260
|
+
end
|
|
1261
|
+
end
|
|
1262
|
+
rescue => bang
|
|
1263
|
+
puts bang
|
|
1264
|
+
puts bang.backtrace if $DEBUG
|
|
1265
|
+
# puts @session.to_yaml
|
|
1266
|
+
end
|
|
1267
|
+
end
|
|
1268
|
+
res
|
|
1269
|
+
}
|
|
1270
|
+
end
|
|
1271
|
+
# end
|
|
1272
|
+
end
|
|
1273
|
+
|
|
1274
|
+
# this function updates specific patterns of a request, e.g. CSRF Tokens
|
|
1275
|
+
# Parameters:
|
|
1276
|
+
# request - the request which has to be updated
|
|
1277
|
+
# cache - the value store of already collected key-value-pairs
|
|
1278
|
+
# patterns - pattern expressions, similar to session-id-patterns, e.g. /name="(sessid)" value="([0-9a-zA-Z!-]*)"/
|
|
1279
|
+
def updateRequestPattern(request, cache, patterns)
|
|
1280
|
+
|
|
1281
|
+
request.map!{ |line|
|
|
1282
|
+
res = line
|
|
1283
|
+
patterns.each do |pat|
|
|
1284
|
+
begin
|
|
1285
|
+
if line =~ /#{pat}/i then
|
|
1286
|
+
pattern_key = Regexp.quote($1.upcase)
|
|
1287
|
+
old_value = Regexp.quote($2)
|
|
1288
|
+
if cache.has_key?(sid_key) then
|
|
1289
|
+
if not old_value =~ /#{cache[sid_key]}/ then # sid value has changed and needs update
|
|
1290
|
+
# print "S"
|
|
1291
|
+
# puts "+ update sid #{sid_key}"
|
|
1292
|
+
# puts "-OLD: #{old_value}"
|
|
1293
|
+
# puts "-NEW: #{@session[:valid_sids][request.site][sid_key]}"
|
|
1294
|
+
|
|
1295
|
+
# puts "---"
|
|
1296
|
+
# dummy = Regexp.quote(old_value)
|
|
1297
|
+
res = line.gsub!(/#{old_value}/, cache[sid_key])
|
|
1298
|
+
if not res then puts "!!!could not update sid (#{sid_key})"; end
|
|
1299
|
+
# puts "->#{line}"
|
|
1300
|
+
end
|
|
1301
|
+
end
|
|
1302
|
+
end
|
|
1303
|
+
rescue => bang
|
|
1304
|
+
puts bang
|
|
1305
|
+
puts bang.backtrace if $DEBUG
|
|
1306
|
+
# puts @session.to_yaml
|
|
1307
|
+
end
|
|
1308
|
+
end
|
|
1309
|
+
res
|
|
1310
|
+
}
|
|
1311
|
+
end
|
|
1312
|
+
|
|
1313
|
+
def applySessionSettings(prefs)
|
|
1314
|
+
[ :update_valid_sids, :update_session, :update_contentlength, :valid_sids, :sid_patterns, :logout_signatures ].each do |v|
|
|
1315
|
+
@@settings[v] = prefs[v] if prefs[v]
|
|
1316
|
+
end
|
|
1317
|
+
end
|
|
1318
|
+
|
|
1319
|
+
end
|
|
1320
|
+
end
|