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.
Files changed (260) hide show
  1. data/bin/watobo_gui.rb +39 -0
  2. data/certificates/cert.pem +19 -0
  3. data/certificates/privkey.pem +15 -0
  4. data/certificates/watobo_dh.key +5 -0
  5. data/config/datastore.yml +5 -0
  6. data/config/forwarding_proxy.yml +12 -0
  7. data/config/general.yml +4 -0
  8. data/config/gui.yml +23 -0
  9. data/config/interceptor.yml +16 -0
  10. data/config/scan_policy.yml +13 -0
  11. data/config/scanner.yml +34 -0
  12. data/icons/Add.ico +0 -0
  13. data/icons/Add_24x24.ico +0 -0
  14. data/icons/Bandwidth.ico +0 -0
  15. data/icons/Bandwidth_24x24.ico +0 -0
  16. data/icons/Mr. Bomb.ico +0 -0
  17. data/icons/Mr. Bomb_16x16.ico +0 -0
  18. data/icons/Mr. Bomb_24x24.ico +0 -0
  19. data/icons/Orange Ball.ico +0 -0
  20. data/icons/Orange Ball_16x16.ico +0 -0
  21. data/icons/Orange Ball_24x24.ico +0 -0
  22. data/icons/Pause.ico +0 -0
  23. data/icons/Play.ico +0 -0
  24. data/icons/Play_24x24.ico +0 -0
  25. data/icons/Red Ball.ico +0 -0
  26. data/icons/Red Ball_16x16.ico +0 -0
  27. data/icons/Red Ball_24x24.ico +0 -0
  28. data/icons/Run.ico +0 -0
  29. data/icons/Stop.ico +0 -0
  30. data/icons/Stop_24x24.ico +0 -0
  31. data/icons/Terminal.ico +0 -0
  32. data/icons/Transfer.ico +0 -0
  33. data/icons/Transfer_16x16.ico +0 -0
  34. data/icons/User.ico +0 -0
  35. data/icons/User_16x16.ico +0 -0
  36. data/icons/User_24x24.ico +0 -0
  37. data/icons/Web Browser.ico +0 -0
  38. data/icons/Web Browser_16x16.ico +0 -0
  39. data/icons/Write Document.ico +0 -0
  40. data/icons/Yellow Ball.ico +0 -0
  41. data/icons/Yellow Ball_16x16.ico +0 -0
  42. data/icons/Yellow Ball_24x24.ico +0 -0
  43. data/icons/advanced.ico +0 -0
  44. data/icons/advanced_16x16.ico +0 -0
  45. data/icons/advanced_24x24.ico +0 -0
  46. data/icons/applications.ico +0 -0
  47. data/icons/applications_16x16.ico +0 -0
  48. data/icons/applications_24x24.ico +0 -0
  49. data/icons/browser_16x16.ico +0 -0
  50. data/icons/browser_24x24.ico +0 -0
  51. data/icons/burn.ico +0 -0
  52. data/icons/burn_16x16.ico +0 -0
  53. data/icons/burn_24x24.ico +0 -0
  54. data/icons/calculator.ico +0 -0
  55. data/icons/calculator_24x24.ico +0 -0
  56. data/icons/cb_checked.ico +0 -0
  57. data/icons/cb_checked_orange.ico +0 -0
  58. data/icons/cb_unchecked.ico +0 -0
  59. data/icons/coin_24x24.ico +0 -0
  60. data/icons/conversation.ico +0 -0
  61. data/icons/conversation_24x24.ico +0 -0
  62. data/icons/engine.ico +0 -0
  63. data/icons/filter.ico +0 -0
  64. data/icons/folder.ico +0 -0
  65. data/icons/folder_16x16.ico +0 -0
  66. data/icons/fuzzer_16x16.ico +0 -0
  67. data/icons/fuzzer_24x24.ico +0 -0
  68. data/icons/go-down_16x16.png +0 -0
  69. data/icons/go-up_16x16.png +0 -0
  70. data/icons/help.ico +0 -0
  71. data/icons/help_16x16.ico +0 -0
  72. data/icons/help_24x24.ico +0 -0
  73. data/icons/iChat.ico +0 -0
  74. data/icons/iChat_16x16.ico +0 -0
  75. data/icons/iChat_24x24.ico +0 -0
  76. data/icons/icons.txt +3 -0
  77. data/icons/info.ico +0 -0
  78. data/icons/info_16x16.ico +0 -0
  79. data/icons/info_24x24.ico +0 -0
  80. data/icons/interceptor_24x24.ico +0 -0
  81. data/icons/lock.ico +0 -0
  82. data/icons/lock_12x12.ico +0 -0
  83. data/icons/lock_16x16.ico +0 -0
  84. data/icons/monitor.ico +0 -0
  85. data/icons/plugin.ico +0 -0
  86. data/icons/plugin_24x24.ico +0 -0
  87. data/icons/scan_16x16.png +0 -0
  88. data/icons/send.ico +0 -0
  89. data/icons/server.ico +0 -0
  90. data/icons/server_16x16.ico +0 -0
  91. data/icons/siberas_logo_x24.gif +0 -0
  92. data/icons/tag_blue_32x32.ico +0 -0
  93. data/icons/watobo-48x48.png +0 -0
  94. data/icons/watobo-logo.png +0 -0
  95. data/icons/watobo.ico +0 -0
  96. data/lib/watobo/adapters/data_store.rb +38 -0
  97. data/lib/watobo/adapters/file/file_store.rb +211 -0
  98. data/lib/watobo/adapters/session_store.rb +27 -0
  99. data/lib/watobo/adapters.rb +26 -0
  100. data/lib/watobo/config.rb +143 -0
  101. data/lib/watobo/constants.rb +92 -0
  102. data/lib/watobo/core/active_check.rb +404 -0
  103. data/lib/watobo/core/cookie.rb +69 -0
  104. data/lib/watobo/core/fuzz_gen.rb +160 -0
  105. data/lib/watobo/core/http_socket.rb +142 -0
  106. data/lib/watobo/core/interceptor.rb +729 -0
  107. data/lib/watobo/core/passive_check.rb +141 -0
  108. data/lib/watobo/core/project.rb +1058 -0
  109. data/lib/watobo/core/scanner.rb +396 -0
  110. data/lib/watobo/core/session.rb +1320 -0
  111. data/lib/watobo/core/simple_ca.rb +393 -0
  112. data/lib/watobo/core.rb +34 -0
  113. data/lib/watobo/defaults.rb +40 -0
  114. data/lib/watobo/external/diff/lcs/array.rb +42 -0
  115. data/lib/watobo/external/diff/lcs/block.rb +72 -0
  116. data/lib/watobo/external/diff/lcs/callbacks.rb +343 -0
  117. data/lib/watobo/external/diff/lcs/change.rb +190 -0
  118. data/lib/watobo/external/diff/lcs/hunk.rb +279 -0
  119. data/lib/watobo/external/diff/lcs/ldiff.rb +247 -0
  120. data/lib/watobo/external/diff/lcs/string.rb +40 -0
  121. data/lib/watobo/external/diff/lcs.rb +1124 -0
  122. data/lib/watobo/external/ntlm/ntlm.rb +797 -0
  123. data/lib/watobo/externals.rb +28 -0
  124. data/lib/watobo/framework/create_project.rb +55 -0
  125. data/lib/watobo/framework/init.rb +149 -0
  126. data/lib/watobo/framework/init_modules.rb +116 -0
  127. data/lib/watobo/framework/license_text.rb +50 -0
  128. data/lib/watobo/framework.rb +26 -0
  129. data/lib/watobo/gui/about_watobo.rb +68 -0
  130. data/lib/watobo/gui/browser_preview.rb +460 -0
  131. data/lib/watobo/gui/certificate_dialog.rb +132 -0
  132. data/lib/watobo/gui/chat_diff.rb +415 -0
  133. data/lib/watobo/gui/chatviewer_frame.rb +427 -0
  134. data/lib/watobo/gui/checkboxtree.rb +221 -0
  135. data/lib/watobo/gui/checks_policy_frame.rb +123 -0
  136. data/lib/watobo/gui/client_cert_dialog.rb +227 -0
  137. data/lib/watobo/gui/confirm_scan_dialog.rb +67 -0
  138. data/lib/watobo/gui/conversation_table.rb +386 -0
  139. data/lib/watobo/gui/conversation_table_ctrl.rb +175 -0
  140. data/lib/watobo/gui/csrf_token_dialog.rb +446 -0
  141. data/lib/watobo/gui/dashboard.rb +341 -0
  142. data/lib/watobo/gui/define_scope_frame.rb +380 -0
  143. data/lib/watobo/gui/edit_comment.rb +70 -0
  144. data/lib/watobo/gui/edit_scope_dialog.rb +69 -0
  145. data/lib/watobo/gui/finding_info.rb +212 -0
  146. data/lib/watobo/gui/findings_tree.rb +459 -0
  147. data/lib/watobo/gui/full_scan_dialog.rb +269 -0
  148. data/lib/watobo/gui/fuzzer_gui.rb +1522 -0
  149. data/lib/watobo/gui/hex_viewer.rb +106 -0
  150. data/lib/watobo/gui/interceptor_gui.rb +994 -0
  151. data/lib/watobo/gui/interceptor_settings_dialog.rb +201 -0
  152. data/lib/watobo/gui/log_viewer.rb +97 -0
  153. data/lib/watobo/gui/login_wizzard.rb +301 -0
  154. data/lib/watobo/gui/main_window.rb +1815 -0
  155. data/lib/watobo/gui/manual_request_editor.rb +1105 -0
  156. data/lib/watobo/gui/master_pw_dialog.rb +142 -0
  157. data/lib/watobo/gui/password_policy_dialog.rb +98 -0
  158. data/lib/watobo/gui/plugin/base.rb +82 -0
  159. data/lib/watobo/gui/plugin_board.rb +95 -0
  160. data/lib/watobo/gui/preferences_dialog.rb +116 -0
  161. data/lib/watobo/gui/progress_window.rb +102 -0
  162. data/lib/watobo/gui/project_wizzard.rb +369 -0
  163. data/lib/watobo/gui/proxy_dialog.rb +550 -0
  164. data/lib/watobo/gui/quick_scan_dialog.rb +242 -0
  165. data/lib/watobo/gui/request_editor.rb +480 -0
  166. data/lib/watobo/gui/save_chat_dialog.rb +158 -0
  167. data/lib/watobo/gui/scanner_settings_dialog.rb +360 -0
  168. data/lib/watobo/gui/select_chat_dialog.rb +169 -0
  169. data/lib/watobo/gui/session_management_dialog.rb +688 -0
  170. data/lib/watobo/gui/sites_tree.rb +347 -0
  171. data/lib/watobo/gui/status_bar.rb +88 -0
  172. data/lib/watobo/gui/table_editor.rb +445 -0
  173. data/lib/watobo/gui/tagless_viewer.rb +62 -0
  174. data/lib/watobo/gui/templates/plugin.rb +80 -0
  175. data/lib/watobo/gui/templates/plugin2.rb +103 -0
  176. data/lib/watobo/gui/text_viewer.rb +247 -0
  177. data/lib/watobo/gui/transcoder_window.rb +215 -0
  178. data/lib/watobo/gui/utils/gui_utils.rb +129 -0
  179. data/lib/watobo/gui/utils/init_icons.rb +106 -0
  180. data/lib/watobo/gui/utils/load_icons.rb +54 -0
  181. data/lib/watobo/gui/utils/load_plugins.rb +94 -0
  182. data/lib/watobo/gui/utils/master_password.rb +90 -0
  183. data/lib/watobo/gui/utils/save_default_settings.rb +99 -0
  184. data/lib/watobo/gui/utils/save_project_settings.rb +21 -0
  185. data/lib/watobo/gui/utils/save_proxy_settings.rb +45 -0
  186. data/lib/watobo/gui/utils/save_session_settings.rb +21 -0
  187. data/lib/watobo/gui/utils/session_history.rb +134 -0
  188. data/lib/watobo/gui/workspace_dialog.rb +89 -0
  189. data/lib/watobo/gui/www_auth_dialog.rb +348 -0
  190. data/lib/watobo/gui/xml_viewer_frame.rb +114 -0
  191. data/lib/watobo/gui.rb +139 -0
  192. data/lib/watobo/mixins/httpparser.rb +664 -0
  193. data/lib/watobo/mixins/request_parser.rb +210 -0
  194. data/lib/watobo/mixins/shapers.rb +345 -0
  195. data/lib/watobo/mixins/transcoders.rb +88 -0
  196. data/lib/watobo/mixins.rb +32 -0
  197. data/lib/watobo/utils/check_regex.rb +36 -0
  198. data/lib/watobo/utils/copy_object.rb +29 -0
  199. data/lib/watobo/utils/crypto.rb +74 -0
  200. data/lib/watobo/utils/expand_range.rb +45 -0
  201. data/lib/watobo/utils/file_management.rb +73 -0
  202. data/lib/watobo/utils/load_chat.rb +219 -0
  203. data/lib/watobo/utils/load_icon.rb +47 -0
  204. data/lib/watobo/utils/print_debug.rb +34 -0
  205. data/lib/watobo/utils/response_hash.rb +143 -0
  206. data/lib/watobo/utils/secure_eval.rb +57 -0
  207. data/lib/watobo/utils/text2request.rb +96 -0
  208. data/lib/watobo/utils.rb +32 -0
  209. data/lib/watobo.rb +76 -0
  210. data/modules/active/Apache/mod_status.rb +123 -0
  211. data/modules/active/Flash/crossdomain.rb +102 -0
  212. data/modules/active/directories/dirwalker.rb +89 -0
  213. data/modules/active/discovery/fileextensions.rb +151 -0
  214. data/modules/active/discovery/http_methods.rb +135 -0
  215. data/modules/active/domino/domino_db.lst +164 -0
  216. data/modules/active/domino/domino_db.rb +128 -0
  217. data/modules/active/fileinclusion/lfi_simple.rb +134 -0
  218. data/modules/active/jboss/jboss_basic.rb +119 -0
  219. data/modules/active/sap/business_objects.rb +73 -0
  220. data/modules/active/sap/its_commands.rb +101 -0
  221. data/modules/active/sap/its_service_parameter.rb +105 -0
  222. data/modules/active/sap/its_services.rb +103 -0
  223. data/modules/active/sap/its_xss.rb +98 -0
  224. data/modules/active/sqlinjection/sql_boolean.rb +262 -0
  225. data/modules/active/sqlinjection/sqli_simple.rb +205 -0
  226. data/modules/active/xss/xss_simple.rb +179 -0
  227. data/modules/passive/cookie_options.rb +97 -0
  228. data/modules/passive/cookie_xss.rb +85 -0
  229. data/modules/passive/detect_code.rb +89 -0
  230. data/modules/passive/detect_fileupload.rb +80 -0
  231. data/modules/passive/detect_infrastructure.rb +98 -0
  232. data/modules/passive/detect_one_time_tokens.rb +86 -0
  233. data/modules/passive/dirindexing.rb +81 -0
  234. data/modules/passive/disclosure_emails.rb +82 -0
  235. data/modules/passive/disclosure_ipaddr.rb +87 -0
  236. data/modules/passive/filename_as_parameter.rb +85 -0
  237. data/modules/passive/form_spotter.rb +75 -0
  238. data/modules/passive/hotspots.rb +86 -0
  239. data/modules/passive/in_script_parameter.rb +92 -0
  240. data/modules/passive/multiple_server_headers.rb +98 -0
  241. data/modules/passive/possible_login.rb +134 -0
  242. data/modules/passive/redirect_url.rb +88 -0
  243. data/modules/passive/redirectionz.rb +96 -0
  244. data/modules/passive/xss_dom.rb +91 -0
  245. data/plugins/catalog/catalog.ico +0 -0
  246. data/plugins/catalog/catalog.rb +726 -0
  247. data/plugins/catalog/db_tests +6483 -0
  248. data/plugins/catalog/db_variables +29 -0
  249. data/plugins/filefinder/dbs/hbci.db +12 -0
  250. data/plugins/filefinder/filefinder.rb +602 -0
  251. data/plugins/sslchecker/cli/sslchecker_cli.rb +21 -0
  252. data/plugins/sslchecker/gui/cipher_table.rb +260 -0
  253. data/plugins/sslchecker/gui/gui.rb +245 -0
  254. data/plugins/sslchecker/gui/sslchecker.rb +26 -0
  255. data/plugins/sslchecker/icons/green_16x16.ico +0 -0
  256. data/plugins/sslchecker/icons/grey_16x16.ico +0 -0
  257. data/plugins/sslchecker/icons/red_16x16.ico +0 -0
  258. data/plugins/sslchecker/icons/sslchecker.ico +0 -0
  259. data/plugins/sslchecker/lib/check.rb +117 -0
  260. 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