watobo 0.9.21 → 0.9.23

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