watobo 0.9.21 → 0.9.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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