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,12 +1,3 @@
1
- #.
2
- # transcoders.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
3
  module Mixin
@@ -23,8 +14,9 @@ module Watobo#:nodoc: all
23
14
  err_count = 0
24
15
  begin
25
16
  b64string = self.force_encoding('ASCII-8BIT')
26
- rs = Base64.strict_decode64(b64string)
27
- #rs = Base64.decode64(b64string)
17
+ #rs = Base64.strict_decode64(b64string)
18
+ # using regular decode64 because of JWT (JSON Web Tokens) decoding
19
+ rs = Base64.decode64(b64string)
28
20
  return rs
29
21
  rescue
30
22
  #b64string.gsub!(/.$/,'')
@@ -1,10 +1 @@
1
- #.
2
- # parser.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
- require 'watobo/parser/html'
1
+ require 'watobo/parser/html'
@@ -1,94 +1,85 @@
1
- #.
2
- # html.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
- module Parser
13
- module HTML
14
- class Form
15
- def input_fields(&block)
16
- if block_given?
17
- @input_fields.each do |field|
18
- yield field
19
- end
20
- end
21
- @input_fields
22
- end
23
-
24
- def initialize(form_css)
25
- @form = form_css
26
- @input_fields = []
27
- @form.css('input').each do |i|
28
- @input_fields << InputField.new(i)
29
- end
30
-
31
- end
32
- end
33
-
34
- class InputField
35
- attr :id
36
- attr :value
37
- attr :name
38
- # attr :autocomplete
39
-
40
- def to_www_form_parm()
41
- Watobo::WWWFormParameter.new(:name => @name, :value => @value)
42
- end
43
-
44
- def to_url_parm()
45
- Watobo::UrlParameter.new(:name => @name, :value => @value)
46
- end
47
-
48
- def initialize(input_css)
49
- @css = input_css
50
- @id = input_css["id"].nil? ? "" : input_css["id"]
51
- @value = input_css["value"].nil? ? "" : input_css["value"]
52
- @name = input_css["name"].nil? ? "" : input_css["name"]
53
- #@autocomplete = input_css["autocomplete"]
54
- end
55
-
56
- def method_missing(name, *args, &block)
57
- @css[name.to_s].nil? ? "" : input_css[name.to_s]
58
- end
59
-
60
- end
61
-
62
- class Links
63
-
64
- end
65
-
66
- def links(&block)
67
-
68
- end
69
-
70
- def input_fields(&block)
71
- fields = []
72
- forms do |form|
73
- form.input_fields do |field|
74
- yield field if block_given?
75
- fields << field
76
- end
77
- end
78
- fields
79
- end
80
-
81
-
82
- def forms(&block)
83
- fs = []
84
- doc = Nokogiri::HTML(self.body)
85
- doc.css('form').each do |f|
86
- fo = Form.new(f)
87
- yield fo if block_given?
88
- end
89
- fs
90
- end
91
-
92
- end
93
- end
2
+ module Watobo#:nodoc: all
3
+ module Parser
4
+ module HTML
5
+ class Form
6
+ def input_fields(&block)
7
+ if block_given?
8
+ @input_fields.each do |field|
9
+ yield field
10
+ end
11
+ end
12
+ @input_fields
13
+ end
14
+
15
+ def initialize(form_css)
16
+ @form = form_css
17
+ @input_fields = []
18
+ @form.css('input').each do |i|
19
+ @input_fields << InputField.new(i)
20
+ end
21
+
22
+ end
23
+ end
24
+
25
+ class InputField
26
+ attr :id
27
+ attr :value
28
+ attr :name
29
+ # attr :autocomplete
30
+
31
+ def to_www_form_parm()
32
+ Watobo::WWWFormParameter.new(:name => @name, :value => @value)
33
+ end
34
+
35
+ def to_url_parm()
36
+ Watobo::UrlParameter.new(:name => @name, :value => @value)
37
+ end
38
+
39
+ def initialize(input_css)
40
+ @css = input_css
41
+ @id = input_css["id"].nil? ? "" : input_css["id"]
42
+ @value = input_css["value"].nil? ? "" : input_css["value"]
43
+ @name = input_css["name"].nil? ? "" : input_css["name"]
44
+ #@autocomplete = input_css["autocomplete"]
45
+ end
46
+
47
+ def method_missing(name, *args, &block)
48
+ @css[name.to_s].nil? ? "" : input_css[name.to_s]
49
+ end
50
+
51
+ end
52
+
53
+ class Links
54
+
55
+ end
56
+
57
+ def links(&block)
58
+
59
+ end
60
+
61
+ def input_fields(&block)
62
+ fields = []
63
+ forms do |form|
64
+ form.input_fields do |field|
65
+ yield field if block_given?
66
+ fields << field
67
+ end
68
+ end
69
+ fields
70
+ end
71
+
72
+
73
+ def forms(&block)
74
+ fs = []
75
+ doc = Nokogiri::HTML(self.body)
76
+ doc.css('form').each do |f|
77
+ fo = Form.new(f)
78
+ yield fo if block_given?
79
+ end
80
+ fs
81
+ end
82
+
83
+ end
84
+ end
94
85
  end
@@ -0,0 +1,26 @@
1
+ # Work around error 'FXComposeContext: illegal window parameter'
2
+ # in FXWindow#setFocus of some libfox versions.
3
+
4
+ class Fox::FXWindow
5
+ def setFocus
6
+ app.addChore do
7
+ super
8
+ end
9
+ end
10
+ end
11
+
12
+ class Fox::FXDialogBox
13
+ def setFocus
14
+ app.addChore do
15
+ super
16
+ end
17
+ end
18
+ end
19
+
20
+ class Fox::FXTextField
21
+ def setFocus
22
+ app.addChore do
23
+ super
24
+ end
25
+ end
26
+ end
@@ -1,13 +1,4 @@
1
- #.
2
- # sockets.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
1
+ %w( client_socket http_socket ).each do |lib|
2
+ require "watobo/sockets/#{lib}"
3
+ end
9
4
 
10
- %w( client_socket http_socket ).each do |lib|
11
- require "watobo/sockets/#{lib}"
12
- end
13
-
@@ -1,839 +1,830 @@
1
- #.
2
- # agent.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
- module HTTPSocket
13
- class Agent_UNUSED
14
-
15
- include Watobo::Constants
16
- extend Watobo::Subscriber
17
-
18
-
19
- def runLogin(chat_list, prefs={})
20
- @@login_mutex.synchronize do
21
- begin
22
- @@login_in_progress = true
23
- login_prefs = Hash.new
24
- login_prefs.update prefs
25
- dummy = {:ignore_logout => true, :update_sids => true, :update_session => true, :update_contentlength => true}
26
- login_prefs.update dummy
27
- puts "! Start Login ..." if $DEBUG
28
- unless chat_list.empty?
29
- # puts login_prefs.to_yaml
30
- chat_list.each do |chat|
31
- print "! LoginRequest: #{chat.id}" if $DEBUG
32
- test_req = chat.copyRequest
33
- request, response = doRequest(test_req, login_prefs)
34
- end
35
- else
36
- puts "! no login script configured !"
37
- end
38
- rescue => bang
39
- puts "!ERROR in runLogin"
40
- puts bang.backtrace if $DEBUG
41
- ensure
42
- @@login_in_progress = false
43
- @@login_cv.signal
44
- # exit
45
- # print "L]"
46
- end
47
- end
48
- end
49
-
50
- def connected?
51
- !@connection.nil?
52
- end
53
-
54
-
55
-
56
-
57
-
58
- # sendHTTPRequest
59
- def send(request, prefs={})
60
- #Watobo.print_debug("huhule", "#{prefs.to_yaml}", "gagagag")
61
- begin
62
- @lasterror = nil
63
- response_header = nil
64
-
65
-
66
- # update current preferences, prefs given here are stronger then global settings!
67
- current_prefs = Hash.new
68
- [:update_session, :update_sids, :update_contentlength, :ssl_cipher, :www_auth, :client_certificates].each do |k|
69
- current_prefs[k] = prefs[k].nil? ? @session[k] : prefs[k]
70
- end
71
-
72
- updateSession(request) if current_prefs[:update_session] == true
73
-
74
- #---------------------------------------
75
- request.removeHeader("^Proxy-Connection") #if not use_proxy
76
- #request.removeHeader("^Connection") #if not use_proxy
77
- request.removeHeader("^Accept-Encoding")
78
- # If-Modified-Since: Tue, 28 Oct 2008 11:06:43 GMT
79
- # If-None-Match: W/"3975-1225192003000"
80
- request.removeHeader("^If-")
81
- # puts
82
- # request.each do |line|
83
- # puts line.unpack("H*")
84
- #end
85
- #puts
86
- if current_prefs[:update_contentlength] == true then
87
- request.fix_content_length()
88
- end
89
-
90
- #request.add_header("Via", "Watobo") if use_proxy
91
- #puts request
92
- # puts "=============="
93
- rescue SocketError
94
- puts "!!! unknown hostname #{host}"
95
- puts request.first
96
- return nil, "WATOBO: Could not resolve hostname #{host}", nil
97
- rescue => bang
98
- puts bang
99
- puts bang.backtrace if $DEBUG
100
- end
101
-
102
- begin
103
- unless proxy.nil?
104
- # connection requires proxy
105
- # puts "* use proxy #{proxy.name}"
106
-
107
- # check for regular proxy authentication
108
- if request.is_ssl?
109
- socket, response_header = sslProxyConnect(request, proxy, current_prefs)
110
- return socket, response_header, error_response("Could Not Connect To Proxy: #{proxy.name} (#{proxy.host}:#{proxy.port})\n", "#{response_header}") if socket.nil?
111
-
112
- if current_prefs[:www_auth].has_key?(site)
113
- case current_prefs[:www_auth][site][:type]
114
- when AUTH_TYPE_NTLM
115
- # puts "* found NTLM credentials for site #{site}"
116
- socket, response_header = wwwAuthNTLM(socket, request, current_prefs[:www_auth][site])
117
-
118
- else
119
- puts "* Unknown Authentication Type: #{current_prefs[:www_auth][site][:type]}"
120
- end
121
- else
122
-
123
- data = request.join + "\r\n"
124
- unless socket.nil?
125
- socket.print data
126
- response_header = readHTTPHeader(socket, current_prefs)
127
- end
128
- end
129
- return socket, request, response_header
130
- end
131
- # puts "* doProxyRequest"
132
- socket, response_header = doProxyRequest(request, proxy, current_prefs)
133
- # puts socket.class
134
- return socket, response_header, error_response("Could Not Connect To Proxy: #{proxy.name} (#{proxy.host}:#{proxy.port})\n", "#{response_header}") if socket.nil?
135
-
136
- return socket, request, response_header
137
- else
138
- # direct connection to host
139
- tcp_socket = nil
140
- # timeout(6) do
141
- #puts "* no proxy - direct connection"
142
- tcp_socket = TCPSocket.new( host, port )
143
- tcp_socket.setsockopt( Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
144
- tcp_socket.sync = true
145
-
146
- socket = tcp_socket
147
- if request.is_ssl?
148
- ssl_prefs = {}
149
- ssl_prefs[:ssl_cipher] = current_prefs[:ssl_cipher] if current_prefs.has_key? :ssl_cipher
150
- if current_prefs.has_key? :client_certificates
151
- if current_prefs[:client_certificates].has_key? request.site
152
- puts "* use ssl client certificate for site #{request.site}" if $DEBUG
153
- ssl_prefs[:ssl_client_cert] = current_prefs[:client_certificates][request.site][:ssl_client_cert]
154
- ssl_prefs[:ssl_client_key] = current_prefs[:client_certificates][request.site][:ssl_client_key]
155
- end
156
- end
157
- socket = sslConnect(tcp_socket, ssl_prefs)
158
- end
159
- #puts socket.class
160
- # remove URI before sending request but cache it for restoring request
161
- uri_cache = nil
162
- uri_cache = request.removeURI #if proxy.nil?
163
-
164
-
165
- # request.addHeader("Proxy-Connection", "Close") unless proxy.nil?
166
- # request.addHeader("Accept-Encoding", "gzip;q=0;identity; q=0.5, *;q=0") #don't want encoding
167
-
168
-
169
- if current_prefs[:www_auth].has_key?(site)
170
- case current_prefs[:www_auth][site][:type]
171
- when AUTH_TYPE_NTLM
172
- # puts "* found NTLM credentials for site #{site}"
173
- socket, response_header = wwwAuthNTLM(socket, request, current_prefs[:www_auth][site])
174
- request.restoreURI(uri_cache)
175
-
176
- else
177
- puts "* Unknown Authentication Type: #{current_prefs[:www_auth][site][:type]}"
178
- end
179
- else
180
- # puts "========== Add Headers"
181
- # request.addHeader("Connection", "Close") #if not use_proxy
182
-
183
- data = request.join
184
- unless request.has_body?
185
- data << "\r\n" unless data =~ /\r\n\r\n$/
186
- end
187
- # puts "= SESSION ="
188
- # puts data
189
- # puts data.unpack("H*")[0].gsub(/0d0a/,"0d0a\n")
190
-
191
- unless socket.nil?
192
- socket.print data
193
- # if socket.is_a? OpenSSL::SSL::SSLSocket
194
- # socket.io.shutdown(Socket::SHUT_WR)
195
- # else
196
- # socket.shutdown(Socket::SHUT_WR)
197
- # end
198
- response_header = readHTTPHeader(socket, current_prefs)
199
- end
200
- # RESTORE URI FOR HISTORY/LOG
201
- request.restoreURI(uri_cache)
202
-
203
- end
204
- return socket, Watobo::Request.new(request), Watobo::Response.new(response_header)
205
- end
206
-
207
- rescue Errno::ECONNREFUSED
208
- response = error_response "connection refused (#{host}:#{port})"
209
- puts response
210
- socket = nil
211
- rescue Errno::ECONNRESET
212
- response = error_response "connection reset (#{host}:#{port})"
213
- socket = nil
214
- rescue Errno::ECONNABORTED
215
- response = error_response "connection aborted (#{host}:#{port})"
216
- socket = nil
217
- rescue Errno::EHOSTUNREACH
218
- response = error_response "host unreachable (#{host}:#{port})"
219
- socket = nil
220
- rescue Timeout::Error
221
- #request = "WATOBO: TimeOut (#{host}:#{port})\n"
222
- response = error_response "TimeOut (#{host}:#{port})"
223
- socket = nil
224
- rescue Errno::ETIMEDOUT
225
- response = error_response "TimeOut (#{host}:#{port})"
226
- socket = nil
227
- rescue Errno::ENOTCONN
228
- puts "!!!ENOTCONN"
229
- rescue OpenSSL::SSL::SSLError
230
- response = error_response "SSL-Error", $!.backtrace.join
231
- socket = nil
232
- rescue => bang
233
- response = error_response "ERROR:", "#{bang}\n#{bang.backtrace}"
234
- socket = nil
235
-
236
- puts bang
237
- puts bang.backtrace if $DEBUG
238
- end
239
- puts response
240
- return socket, request, response
241
- end
242
-
243
- def sidCache()
244
- #puts @project
245
- @session[:valid_sids]
246
- end
247
-
248
- def setSIDCache(new_cache = {} )
249
- @session[:valid_sids] = new_cache if new_cache.is_a? Hash
250
- end
251
-
252
- # +++ doRequest(request) +++
253
- # + function:
254
- #
255
- def doRequest(request, opts={} )
256
- begin
257
- @session.update opts
258
- # puts "[doRequest] #{@session.to_yaml}"
259
- # puts "#[#{self.class}]" + @session[:csrf_requests].first.object_id.to_s
260
- unless @session[:csrf_requests].empty? or @session[:csrf_patterns].empty?
261
- csrf_cache = Hash.new
262
- @session[:csrf_requests].each do |req|
263
- copy = Watobo::Request.new YAML.load(YAML.dump(req))
264
-
265
- updateCSRFToken(csrf_cache, copy)
266
- socket, csrf_request, csrf_response = sendHTTPRequest(copy, opts)
267
- next if socket.nil?
268
- # puts "= Response Headers:"
269
- # puts csrf_response
270
- # puts "==="
271
- update_sids(csrf_request.host, csrf_response.headers)
272
- next if socket.nil?
273
- # p "*"
274
- # csrf_response = readHTTPHeader(socket)
275
- readHTTPBody(socket, csrf_response, csrf_request, opts)
276
-
277
- next if csrf_response.body.nil?
278
- update_sids(csrf_request.host, [csrf_response.body])
279
-
280
- updateCSRFCache(csrf_cache, csrf_request, [csrf_response.body]) if csrf_response.content_type =~ /text\//
281
-
282
- # socket.close
283
- closeSocket(socket)
284
- end
285
- #p @session[:csrf_requests].length
286
- updateCSRFToken(csrf_cache, request)
287
- end
288
-
289
- socket, request, response = sendHTTPRequest(request, opts)
290
-
291
- if socket.nil?
292
- return request, response
293
- end
294
-
295
- update_sids(request.host, response.headers) if @session[:update_sids] == true
296
-
297
- if @session[:follow_redirect]
298
- # puts response.status
299
- if response.status =~ /^302/
300
- response.extend Watobo::Mixin::Parser::Web10
301
- request.extend Watobo::Mixin::Shaper::Web10
302
-
303
- loc_header = response.headers("Location:").first
304
- new_location = loc_header.gsub(/^[^:]*:/,'').strip
305
- unless new_location =~ /^http/
306
- new_location = request.proto + "://" + request.site + "/" + request.dir + "/" + new_location.sub(/^[\.\/]*/,'')
307
- end
308
-
309
- notify(:follow_redirect, new_location)
310
- nr = Watobo::Request.new YAML.load(YAML.dump(request))
311
-
312
- # create GET request for new location
313
- nr.replaceMethod("GET")
314
- nr.removeHeader("Content-Length")
315
- nr.removeBody()
316
- nr.replaceURL(new_location)
317
-
318
-
319
- socket, request, response = sendHTTPRequest(nr, opts)
320
-
321
- if socket.nil?
322
- #return nil, request
323
- return request, response
324
- end
325
- end
326
- end
327
-
328
- readHTTPBody(socket, response, request, opts)
329
-
330
- unless response.body.nil?
331
- update_sids(request.host, [response.body]) if @session[:update_sids] == true and response.content_type =~ /text\//
332
- end
333
-
334
- #socket.close
335
- closeSocket(socket)
336
-
337
- rescue => bang
338
- # puts "! Error in doRequest"
339
- puts "! Module #{Module.nesting[0].name}"
340
- puts bang
341
- # puts bang.backtrace if $DEBUG
342
- @lasterror = bang
343
- # raise
344
- # ensure
345
- end
346
-
347
- response.extend Watobo::Mixin::Parser::Web10
348
- return request, response
349
- end
350
-
351
- def addProxy(prefs=nil)
352
-
353
- proxy = nil
354
- unless prefs.nil?
355
- proxy = Proxy.new(prefs)
356
- # proxy.setCredentials(prefs[:credentials]) unless prefs[:credentials].nil?
357
- unless prefs[:site].nil?
358
- @@proxy[prefs[:site]] = proxy
359
- return
360
- end
361
- end
362
-
363
- @@proxy[:default] = proxy
364
- end
365
-
366
- def get_settings
367
- @@settings
368
- end
369
-
370
- def getProxy(site=nil)
371
- unless site.nil?
372
- return @@proxy[site] unless @@proxy[site].nil?
373
- end
374
- return @@proxy[:default]
375
- end
376
-
377
- #
378
- # INITIALIZE
379
- #
380
- # Possible preferences:
381
- # :proxy => '127.0.0.1:port'
382
- # :valid_sids => Hash.new,
383
- # :sid_patterns => [],
384
- # :logout_signatures => [],
385
- # :update_valid_sids => false,
386
- # :update_sids => false,
387
- # :update_contentlength => true
388
- def initialize( session_id, prefs={} )
389
-
390
- @connection = nil
391
-
392
- session = nil
393
-
394
- session = ( session_id.is_a? Fixnum ) ? session_id : session_id.object_id
395
- session = Digest::MD5.hexdigest(Time.now.to_f.to_s) if session_id.nil?
396
-
397
- unless @@settings.has_key? session
398
- @@settings[session] = {
399
- :valid_sids => Hash.new,
400
- :sid_patterns => [],
401
- # :valid_csrf_tokens => Hash.new,
402
- :csrf_patterns => [],
403
- :csrf_requests => [],
404
- :logout_signatures => [],
405
- :logout_content_types => Hash.new,
406
- :update_valid_sids => false,
407
- :update_sids => false,
408
- :update_session => true,
409
- :update_contentlength => true,
410
- :login_chats => [],
411
- :www_auth => Hash.new,
412
- :client_certificates => {},
413
- :proxy_auth => Hash.new
414
- }
415
- end
416
- @session = @@settings[session] # shortcut to settings
417
- @session.update prefs
418
-
419
- # @valid_csrf_tokens = Hash.new
420
-
421
- addProxy( prefs[:proxy] ) if prefs.is_a? Hash and prefs[:proxy]
422
-
423
- @ctx = OpenSSL::SSL::SSLContext.new()
424
- @ctx.key = nil
425
- @ctx.cert = nil
426
-
427
- # TODO: Implement switches for URL-Encoding (http://www.blooberry.com/indexdot/html/topics/urlencoding.htm)
428
- # TODO: Implement switches for Following Redirects
429
- # TODO: Implement switches for Logging, Debugging, ...
430
- end
431
-
432
-
433
-
434
- private
435
-
436
- #def doNtlmAuth(socket, request, ntlm_credentials)
437
- def wwwAuthNTLM(socket, request, ntlm_credentials)
438
- response_header = nil
439
- begin
440
- auth_request = request.copy
441
-
442
- ntlm_challenge = nil
443
- t1 = Watobo::NTLM::Message::Type1.new()
444
- msg = "NTLM " + t1.encode64
445
-
446
- auth_request.removeHeader("Connection")
447
- auth_request.removeHeader("Authorization")
448
-
449
- auth_request.addHeader("Authorization", msg)
450
- auth_request.addHeader("Connection", "Keep-Alive")
451
-
452
- if $DEBUG
453
- puts "============= T1 ======================="
454
- puts auth_request
455
- end
456
-
457
- data = auth_request.join + "\r\n"
458
- socket.print data
459
-
460
- puts "-----------------" if $DEBUG
461
-
462
- response_header = []
463
- rcode = nil
464
- clen = nil
465
- ntlm_challenge = nil
466
- response_header = readHTTPHeader(socket)
467
- response_header.each do |line|
468
- if line =~ /^HTTP\/\d\.\d (\d+) (.*)/ then
469
- rcode = $1.to_i
470
- rmsg = $2
471
- end
472
- if line =~ /^WWW-Authenticate: (NTLM) (.+)\r\n/
473
- ntlm_challenge = $2
474
- end
475
- if line =~ /^Content-Length: (\d{1,})\r\n/
476
- clen = $1.to_i
477
- end
478
- break if line.strip.empty?
479
- end
480
- # puts "==================="
481
-
482
- if $DEBUG
483
- puts "--- T1 RESPONSE HEADERS ---"
484
- puts response_header
485
- puts "---"
486
- end
487
- if rcode == 401 #Authentication Required
488
- puts "[NTLM] got ntlm challenge: #{ntlm_challenge}" if $DEBUG
489
- return socket, response_header if ntlm_challenge.nil?
490
- elsif rcode == 200 # Ok
491
- puts "[NTLM] seems request doesn't need authentication" if $DEBUG
492
- return socket, Watobo::Response.new(response_header)
493
- else
494
- if $DEBUG
495
- puts "[NTLM] ... !#*+.!*peep* ...."
496
- puts response_header
497
- end
498
- return socket, Watobo::Response.new(response_header)
499
- end
500
-
501
- # reading rest of response
502
- rest = ''
503
- Watobo::HTTPSocket.read_body(socket, :max_bytes => clen){ |d|
504
- rest += d
505
- }
506
-
507
- if $DEBUG
508
- puts "--- T1 RESPONSE BODY ---"
509
- puts rest
510
- puts "---"
511
- end
512
- t2 = Watobo::NTLM::Message.decode64(ntlm_challenge)
513
- t3 = t2.response({:user => ntlm_credentials[:username],
514
- :password => ntlm_credentials[:password],
515
- :domain => ntlm_credentials[:domain]},
516
- {:workstation => ntlm_credentials[:workstation], :ntlmv2 => true})
517
-
518
- # puts "* NTLM-Credentials: #{ntlm_credentials[:username]},#{ntlm_credentials[:password]}, #{ntlm_credentials[:domain]}, #{ntlm_credentials[:workstation]}"
519
- auth_request.removeHeader("Authorization")
520
- auth_request.removeHeader("Connection")
521
-
522
- auth_request.addHeader("Connection", "Close")
523
-
524
- msg = "NTLM " + t3.encode64
525
- auth_request.addHeader("Authorization", msg)
526
- # puts "============= T3 ======================="
527
-
528
- data = auth_request.join + "\r\n"
529
-
530
- if $DEBUG
531
- puts "= NTLM Type 3 ="
532
- puts data
533
- end
534
- socket.print data
535
-
536
- response_header = []
537
- response_header = readHTTPHeader(socket)
538
- response_header.each do |line|
539
-
540
- if line =~ /^HTTP\/\d\.\d (\d+) (.*)/ then
541
- rcode = $1.to_i
542
- rmsg = $2
543
- end
544
- break if line.strip.empty?
545
- end
546
-
547
- if rcode == 200 # Ok
548
- puts "[NTLM] Authentication Successfull" if $DEBUG
549
- elsif rcode == 401 # Authentication Required
550
- # TODO: authorization didn't work -> do some notification
551
- # ...
552
- puts "[NTLM] could not authenticate. Bad credentials?"
553
- puts ntlm_credentials.to_yaml
554
- end
555
-
556
- return socket, Watobo::Response.new(response_header)
557
- rescue => bang
558
- puts "!!! ERROR: in ntlm_auth"
559
- puts bang
560
-
561
- puts bang.backtrace if $DEBUG
562
- return nil, nil
563
- end
564
- end
565
-
566
-
567
- ##################################################
568
- # doProxyRequest
569
- ################################################
570
- def doProxyRequest(request, proxy, prefs={})
571
- #puts "DO PROXY REQUEST"
572
- # puts prefs.to_yaml
573
- begin
574
- tcp_socket = nil
575
- site = request.site
576
-
577
- auth_request = Watobo::Utils::copyObject(request)
578
- auth_request.extend Watobo::Mixin::Parser::Url
579
- auth_request.extend Watobo::Mixin::Parser::Web10
580
- auth_request.extend Watobo::Mixin::Shaper::Web10
581
- # timeout(6) do
582
-
583
- tcp_socket = TCPSocket.new( proxy.host, proxy.port)
584
- tcp_socket.setsockopt( Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
585
- tcp_socket.sync = true
586
- # end
587
-
588
- auth_request.removeHeader("Proxy-Connection")
589
- auth_request.removeHeader("Connection")
590
-
591
- auth_request.addHeader("Pragma", "no-cache")
592
-
593
- if proxy.has_login?
594
- response_header = doProxyAuth(tcp_socket, auth_request, proxy)
595
- # puts "* got request_header from doProxy Auth"
596
- # puts request_header.class
597
- puts "[Proxy Auth] Status: #{response_header.status}" if $DEBUG
598
- return tcp_socket, response_header unless response_header.status =~ /401/
599
- return tcp_socket, response_header unless prefs[:www_auth].has_key?(site)
600
- end
601
-
602
- # puts "CHECK WWW_AUTH"
603
- # puts prefs.to_yaml
604
- if prefs[:www_auth].has_key?(site)
605
- case prefs[:www_auth][site][:type]
606
- when AUTH_TYPE_NTLM
607
- # puts "* found NTLM credentials for site #{site}"
608
- socket, response_header = wwwAuthNTLM(tcp_socket, request, prefs[:www_auth][site])
609
-
610
- #response_header.extend Watobo::Mixin::Parser::Url
611
- #response_header.extend Watobo::Mixin::Parser::Web10
612
- return socket, response_header
613
- else
614
- puts "* Unknown Authentication Type: #{prefs[:www_auth][site][:type]}"
615
- end
616
- else
617
- data = auth_request.join + "\r\n"
618
-
619
- tcp_socket.print data
620
-
621
- response_header = readHTTPHeader(tcp_socket)
622
- return tcp_socket, response_header
623
- end
624
- rescue => bang
625
- puts bang
626
- puts bang.backtrace if $DEBUG
627
-
628
- end
629
- return nil
630
- end
631
-
632
- def loggedOut?(response, prefs={})
633
- begin
634
- return false if @session[:logout_signatures].empty?
635
- response.each do |line|
636
- @session[:logout_signatures].each do |p|
637
- # puts "!!!*LOGOUT*!!!" if line =~ /#{p}/
638
- return true if line =~ /#{p}/
639
- end
640
- end
641
- rescue => bang
642
- puts bang
643
- puts bang.backtrace if $DEBUG
644
- end
645
- return false
646
- end
647
-
648
- def error_response(msg, comment=nil)
649
- er = []
650
- er << "HTTP/1.1 555 Watobo Error\r\n"
651
- er << "WATOBO: #{msg.gsub(/\r?\n/," ").strip}\r\n"
652
- er << "Content-Length: 0\r\n"
653
- er << "Connection: close\r\n"
654
- er << "\r\n"
655
- unless comment.nil?
656
- body = "<H1>#{msg}</H1></br><H2>#{comment.gsub(/\r?\n/,"</br>")}</H2>"
657
- er << body
658
- end
659
- er.extend Watobo::Mixin::Parser::Url
660
- er.extend Watobo::Mixin::Parser::Web10
661
- er.extend Watobo::Mixin::Shaper::Web10
662
- er.fix_content_length
663
- er
664
- end
665
-
666
-
667
-
668
- # def read_response(socket)
669
-
670
- # return response
671
- # end
672
-
673
-
674
- def updateCSRFCache(csrf_cache, request, response)
675
- puts "=UPDATE CSRF CACHE" if $DEBUG
676
- # Thread.new{
677
- begin
678
- # site = request.site
679
- @@csrf_lock.synchronize do
680
- response.each do |line|
681
- # puts line
682
- @session[:csrf_patterns].each do |pat|
683
- puts pat if $DEBUG
684
- if line =~ /#{pat}/i then
685
- token_key = Regexp.quote($1.upcase)
686
- token_value = $2
687
- #print "U"
688
- puts "GOT NEW TOKEN (#{token_key}): #{token_value}" if $DEBUG
689
- # @session[:valid_csrf_tokens][site] = Hash.new if @session[:valid_csrf_tokens][site].nil?
690
- # @session[:valid_csrf_tokens][site][token_key] = token_value
691
- csrf_cache[token_key] = token_value
692
- end
693
- end
694
-
695
- end
696
- end
697
- rescue => bang
698
- puts bang
699
- if $DEBUG
700
- puts bang.backtrace
701
- puts "= Request"
702
- puts request
703
- puts "= Response"
704
- puts response
705
- puts "==="
706
- end
707
-
708
- end
709
- # }
710
- end
711
-
712
- def closeSocket(socket)
713
- return false if socket.nil?
714
- begin
715
- if socket.respond_to? :sysclose
716
- #socket.io.shutdown(2)
717
- # puts "sysclose"
718
- socket.sysclose
719
- elsif socket.respond_to? :shutdown
720
- socket.shutdown(2)
721
- elsif socket.respond_to? :close
722
- socket.close
723
- end
724
- return true
725
- rescue => bang
726
- puts bang
727
- puts bang.backtrace if $DEBUG
728
- end
729
- false
730
- end
731
-
732
- def updateSessionSettings(settings={})
733
- [
734
- :ssl_client_cert,
735
- :ssl_client_key,
736
- :ssl_client_pass,
737
- :csrf_requests,
738
- :valid_sids,
739
- :sid_patterns,
740
- :logout_signatures,
741
- :logout_content_types,
742
- :update_valid_sids,
743
- :update_sids,
744
- :update_session,
745
- :update_contentlength,
746
- :login_chats,
747
- :follow_redirect
748
- ].each do |k|
749
- @session[k] = settings[k] if settings.has_key? k
750
- end
751
- end
752
-
753
-
754
-
755
- def updateCSRFToken(csrf_cache, request)
756
- # puts "=UPDATE CSRF TOKEN"
757
- # @session[:valid_csrf_tokens].to_yaml
758
- # puts request if request.site.nil?
759
- # puts "= = = = = = "
760
- @@csrf_lock.synchronize do
761
- # if @session[:valid_csrf_tokens].has_key?(request.site)
762
- # puts "* found token for site: #{request.site}"
763
-
764
- request.map!{ |line|
765
- res = line
766
- @session[:csrf_patterns].each do |pat|
767
- begin
768
- if line =~ /#{pat}/i then
769
- key = Regexp.quote($1.upcase)
770
- old_value = $2
771
- if csrf_cache.has_key?(key) then
772
- res = line.gsub!(/#{Regexp.quote(old_value)}/, csrf_cache[key])
773
- if res.nil? then
774
- res = line
775
- puts "!!!could not update token (#{key})"
776
- end
777
- end
778
- end
779
- rescue => bang
780
- puts bang
781
- puts bang.backtrace if $DEBUG
782
- # puts @session.to_yaml
783
- end
784
- end
785
- res
786
- }
787
- end
788
- # end
789
- end
790
-
791
- # this function updates specific patterns of a request, e.g. CSRF Tokens
792
- # Parameters:
793
- # request - the request which has to be updated
794
- # cache - the value store of already collected key-value-pairs
795
- # patterns - pattern expressions, similar to session-id-patterns, e.g. /name="(sessid)" value="([0-9a-zA-Z!-]*)"/
796
- def updateRequestPattern(request, cache, patterns)
797
-
798
- request.map!{ |line|
799
- res = line
800
- patterns.each do |pat|
801
- begin
802
- if line =~ /#{pat}/i then
803
- pattern_key = Regexp.quote($1.upcase)
804
- old_value = Regexp.quote($2)
805
- if cache.has_key?(sid_key) then
806
- if not old_value =~ /#{cache[sid_key]}/ then # sid value has changed and needs update
807
- # print "S"
808
- # puts "+ update sid #{sid_key}"
809
- # puts "-OLD: #{old_value}"
810
- # puts "-NEW: #{@session[:valid_sids][request.site][sid_key]}"
811
-
812
- # puts "---"
813
- # dummy = Regexp.quote(old_value)
814
- res = line.gsub!(/#{old_value}/, cache[sid_key])
815
- if not res then puts "!!!could not update sid (#{sid_key})"; end
816
- # puts "->#{line}"
817
- end
818
- end
819
- end
820
- rescue => bang
821
- puts bang
822
- puts bang.backtrace if $DEBUG
823
- # puts @session.to_yaml
824
- end
825
- end
826
- res
827
- }
828
- end
829
-
830
- def applySessionSettings(prefs)
831
- [ :update_valid_sids, :update_session, :update_contentlength, :valid_sids, :sid_patterns, :logout_signatures ].each do |v|
832
- @@settings[v] = prefs[v] if prefs[v]
833
- end
834
- end
835
-
836
-
837
- end
838
- end
2
+ module Watobo#:nodoc: all
3
+ module HTTPSocket
4
+ class Agent_UNUSED
5
+
6
+ include Watobo::Constants
7
+ extend Watobo::Subscriber
8
+
9
+
10
+ def runLogin(chat_list, prefs={})
11
+ @@login_mutex.synchronize do
12
+ begin
13
+ @@login_in_progress = true
14
+ login_prefs = Hash.new
15
+ login_prefs.update prefs
16
+ dummy = {:ignore_logout => true, :update_sids => true, :update_session => true, :update_contentlength => true}
17
+ login_prefs.update dummy
18
+ puts "! Start Login ..." if $DEBUG
19
+ unless chat_list.empty?
20
+ # puts login_prefs.to_yaml
21
+ chat_list.each do |chat|
22
+ print "! LoginRequest: #{chat.id}" if $DEBUG
23
+ test_req = chat.copyRequest
24
+ request, response = doRequest(test_req, login_prefs)
25
+ end
26
+ else
27
+ puts "! no login script configured !"
28
+ end
29
+ rescue => bang
30
+ puts "!ERROR in runLogin"
31
+ puts bang.backtrace if $DEBUG
32
+ ensure
33
+ @@login_in_progress = false
34
+ @@login_cv.signal
35
+ # exit
36
+ # print "L]"
37
+ end
38
+ end
39
+ end
40
+
41
+ def connected?
42
+ !@connection.nil?
43
+ end
44
+
45
+
46
+
47
+
48
+
49
+ # sendHTTPRequest
50
+ def send(request, prefs={})
51
+ #Watobo.print_debug("huhule", "#{prefs.to_yaml}", "gagagag")
52
+ begin
53
+ @lasterror = nil
54
+ response_header = nil
55
+
56
+
57
+ # update current preferences, prefs given here are stronger then global settings!
58
+ current_prefs = Hash.new
59
+ [:update_session, :update_sids, :update_contentlength, :ssl_cipher, :www_auth, :client_certificates].each do |k|
60
+ current_prefs[k] = prefs[k].nil? ? @session[k] : prefs[k]
61
+ end
62
+
63
+ updateSession(request) if current_prefs[:update_session] == true
64
+
65
+ #---------------------------------------
66
+ request.removeHeader("^Proxy-Connection") #if not use_proxy
67
+ #request.removeHeader("^Connection") #if not use_proxy
68
+ request.removeHeader("^Accept-Encoding")
69
+ # If-Modified-Since: Tue, 28 Oct 2008 11:06:43 GMT
70
+ # If-None-Match: W/"3975-1225192003000"
71
+ request.removeHeader("^If-")
72
+ # puts
73
+ # request.each do |line|
74
+ # puts line.unpack("H*")
75
+ #end
76
+ #puts
77
+ if current_prefs[:update_contentlength] == true then
78
+ request.fix_content_length()
79
+ end
80
+
81
+ #request.add_header("Via", "Watobo") if use_proxy
82
+ #puts request
83
+ # puts "=============="
84
+ rescue SocketError
85
+ puts "!!! unknown hostname #{host}"
86
+ puts request.first
87
+ return nil, "WATOBO: Could not resolve hostname #{host}", nil
88
+ rescue => bang
89
+ puts bang
90
+ puts bang.backtrace if $DEBUG
91
+ end
92
+
93
+ begin
94
+ unless proxy.nil?
95
+ # connection requires proxy
96
+ # puts "* use proxy #{proxy.name}"
97
+
98
+ # check for regular proxy authentication
99
+ if request.is_ssl?
100
+ socket, response_header = sslProxyConnect(request, proxy, current_prefs)
101
+ return socket, response_header, error_response("Could Not Connect To Proxy: #{proxy.name} (#{proxy.host}:#{proxy.port})\n", "#{response_header}") if socket.nil?
102
+
103
+ if current_prefs[:www_auth].has_key?(site)
104
+ case current_prefs[:www_auth][site][:type]
105
+ when AUTH_TYPE_NTLM
106
+ # puts "* found NTLM credentials for site #{site}"
107
+ socket, response_header = wwwAuthNTLM(socket, request, current_prefs[:www_auth][site])
108
+
109
+ else
110
+ puts "* Unknown Authentication Type: #{current_prefs[:www_auth][site][:type]}"
111
+ end
112
+ else
113
+
114
+ data = request.join + "\r\n"
115
+ unless socket.nil?
116
+ socket.print data
117
+ response_header = readHTTPHeader(socket, current_prefs)
118
+ end
119
+ end
120
+ return socket, request, response_header
121
+ end
122
+ # puts "* doProxyRequest"
123
+ socket, response_header = doProxyRequest(request, proxy, current_prefs)
124
+ # puts socket.class
125
+ return socket, response_header, error_response("Could Not Connect To Proxy: #{proxy.name} (#{proxy.host}:#{proxy.port})\n", "#{response_header}") if socket.nil?
126
+
127
+ return socket, request, response_header
128
+ else
129
+ # direct connection to host
130
+ tcp_socket = nil
131
+ # timeout(6) do
132
+ #puts "* no proxy - direct connection"
133
+ tcp_socket = TCPSocket.new( host, port )
134
+ tcp_socket.setsockopt( Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
135
+ tcp_socket.sync = true
136
+
137
+ socket = tcp_socket
138
+ if request.is_ssl?
139
+ ssl_prefs = {}
140
+ ssl_prefs[:ssl_cipher] = current_prefs[:ssl_cipher] if current_prefs.has_key? :ssl_cipher
141
+ if current_prefs.has_key? :client_certificates
142
+ if current_prefs[:client_certificates].has_key? request.site
143
+ puts "* use ssl client certificate for site #{request.site}" if $DEBUG
144
+ ssl_prefs[:ssl_client_cert] = current_prefs[:client_certificates][request.site][:ssl_client_cert]
145
+ ssl_prefs[:ssl_client_key] = current_prefs[:client_certificates][request.site][:ssl_client_key]
146
+ end
147
+ end
148
+ socket = sslConnect(tcp_socket, ssl_prefs)
149
+ end
150
+ #puts socket.class
151
+ # remove URI before sending request but cache it for restoring request
152
+ uri_cache = nil
153
+ uri_cache = request.removeURI #if proxy.nil?
154
+
155
+
156
+ # request.addHeader("Proxy-Connection", "Close") unless proxy.nil?
157
+ # request.addHeader("Accept-Encoding", "gzip;q=0;identity; q=0.5, *;q=0") #don't want encoding
158
+
159
+
160
+ if current_prefs[:www_auth].has_key?(site)
161
+ case current_prefs[:www_auth][site][:type]
162
+ when AUTH_TYPE_NTLM
163
+ # puts "* found NTLM credentials for site #{site}"
164
+ socket, response_header = wwwAuthNTLM(socket, request, current_prefs[:www_auth][site])
165
+ request.restoreURI(uri_cache)
166
+
167
+ else
168
+ puts "* Unknown Authentication Type: #{current_prefs[:www_auth][site][:type]}"
169
+ end
170
+ else
171
+ # puts "========== Add Headers"
172
+ # request.addHeader("Connection", "Close") #if not use_proxy
173
+
174
+ data = request.join
175
+ unless request.has_body?
176
+ data << "\r\n" unless data =~ /\r\n\r\n$/
177
+ end
178
+ # puts "= SESSION ="
179
+ # puts data
180
+ # puts data.unpack("H*")[0].gsub(/0d0a/,"0d0a\n")
181
+
182
+ unless socket.nil?
183
+ socket.print data
184
+ # if socket.is_a? OpenSSL::SSL::SSLSocket
185
+ # socket.io.shutdown(Socket::SHUT_WR)
186
+ # else
187
+ # socket.shutdown(Socket::SHUT_WR)
188
+ # end
189
+ response_header = readHTTPHeader(socket, current_prefs)
190
+ end
191
+ # RESTORE URI FOR HISTORY/LOG
192
+ request.restoreURI(uri_cache)
193
+
194
+ end
195
+ return socket, Watobo::Request.new(request), Watobo::Response.new(response_header)
196
+ end
197
+
198
+ rescue Errno::ECONNREFUSED
199
+ response = error_response "connection refused (#{host}:#{port})"
200
+ puts response
201
+ socket = nil
202
+ rescue Errno::ECONNRESET
203
+ response = error_response "connection reset (#{host}:#{port})"
204
+ socket = nil
205
+ rescue Errno::ECONNABORTED
206
+ response = error_response "connection aborted (#{host}:#{port})"
207
+ socket = nil
208
+ rescue Errno::EHOSTUNREACH
209
+ response = error_response "host unreachable (#{host}:#{port})"
210
+ socket = nil
211
+ rescue Timeout::Error
212
+ #request = "WATOBO: TimeOut (#{host}:#{port})\n"
213
+ response = error_response "TimeOut (#{host}:#{port})"
214
+ socket = nil
215
+ rescue Errno::ETIMEDOUT
216
+ response = error_response "TimeOut (#{host}:#{port})"
217
+ socket = nil
218
+ rescue Errno::ENOTCONN
219
+ puts "!!!ENOTCONN"
220
+ rescue OpenSSL::SSL::SSLError
221
+ response = error_response "SSL-Error", $!.backtrace.join
222
+ socket = nil
223
+ rescue => bang
224
+ response = error_response "ERROR:", "#{bang}\n#{bang.backtrace}"
225
+ socket = nil
226
+
227
+ puts bang
228
+ puts bang.backtrace if $DEBUG
229
+ end
230
+ puts response
231
+ return socket, request, response
232
+ end
233
+
234
+ def sidCache()
235
+ #puts @project
236
+ @session[:valid_sids]
237
+ end
238
+
239
+ def setSIDCache(new_cache = {} )
240
+ @session[:valid_sids] = new_cache if new_cache.is_a? Hash
241
+ end
242
+
243
+ # +++ doRequest(request) +++
244
+ # + function:
245
+ #
246
+ def doRequest(request, opts={} )
247
+ begin
248
+ @session.update opts
249
+ # puts "[doRequest] #{@session.to_yaml}"
250
+ # puts "#[#{self.class}]" + @session[:csrf_requests].first.object_id.to_s
251
+ unless @session[:csrf_requests].empty? or @session[:csrf_patterns].empty?
252
+ csrf_cache = Hash.new
253
+ @session[:csrf_requests].each do |req|
254
+ copy = Watobo::Request.new YAML.load(YAML.dump(req))
255
+
256
+ updateCSRFToken(csrf_cache, copy)
257
+ socket, csrf_request, csrf_response = sendHTTPRequest(copy, opts)
258
+ next if socket.nil?
259
+ # puts "= Response Headers:"
260
+ # puts csrf_response
261
+ # puts "==="
262
+ update_sids(csrf_request.host, csrf_response.headers)
263
+ next if socket.nil?
264
+ # p "*"
265
+ # csrf_response = readHTTPHeader(socket)
266
+ readHTTPBody(socket, csrf_response, csrf_request, opts)
267
+
268
+ next if csrf_response.body.nil?
269
+ update_sids(csrf_request.host, [csrf_response.body])
270
+
271
+ updateCSRFCache(csrf_cache, csrf_request, [csrf_response.body]) if csrf_response.content_type =~ /text\//
272
+
273
+ # socket.close
274
+ closeSocket(socket)
275
+ end
276
+ #p @session[:csrf_requests].length
277
+ updateCSRFToken(csrf_cache, request)
278
+ end
279
+
280
+ socket, request, response = sendHTTPRequest(request, opts)
281
+
282
+ if socket.nil?
283
+ return request, response
284
+ end
285
+
286
+ update_sids(request.host, response.headers) if @session[:update_sids] == true
287
+
288
+ if @session[:follow_redirect]
289
+ # puts response.status
290
+ if response.status =~ /^302/
291
+ response.extend Watobo::Mixin::Parser::Web10
292
+ request.extend Watobo::Mixin::Shaper::Web10
293
+
294
+ loc_header = response.headers("Location:").first
295
+ new_location = loc_header.gsub(/^[^:]*:/,'').strip
296
+ unless new_location =~ /^http/
297
+ new_location = request.proto + "://" + request.site + "/" + request.dir + "/" + new_location.sub(/^[\.\/]*/,'')
298
+ end
299
+
300
+ notify(:follow_redirect, new_location)
301
+ nr = Watobo::Request.new YAML.load(YAML.dump(request))
302
+
303
+ # create GET request for new location
304
+ nr.replaceMethod("GET")
305
+ nr.removeHeader("Content-Length")
306
+ nr.removeBody()
307
+ nr.replaceURL(new_location)
308
+
309
+
310
+ socket, request, response = sendHTTPRequest(nr, opts)
311
+
312
+ if socket.nil?
313
+ #return nil, request
314
+ return request, response
315
+ end
316
+ end
317
+ end
318
+
319
+ readHTTPBody(socket, response, request, opts)
320
+
321
+ unless response.body.nil?
322
+ update_sids(request.host, [response.body]) if @session[:update_sids] == true and response.content_type =~ /text\//
323
+ end
324
+
325
+ #socket.close
326
+ closeSocket(socket)
327
+
328
+ rescue => bang
329
+ # puts "! Error in doRequest"
330
+ puts "! Module #{Module.nesting[0].name}"
331
+ puts bang
332
+ # puts bang.backtrace if $DEBUG
333
+ @lasterror = bang
334
+ # raise
335
+ # ensure
336
+ end
337
+
338
+ response.extend Watobo::Mixin::Parser::Web10
339
+ return request, response
340
+ end
341
+
342
+ def addProxy(prefs=nil)
343
+
344
+ proxy = nil
345
+ unless prefs.nil?
346
+ proxy = Proxy.new(prefs)
347
+ # proxy.setCredentials(prefs[:credentials]) unless prefs[:credentials].nil?
348
+ unless prefs[:site].nil?
349
+ @@proxy[prefs[:site]] = proxy
350
+ return
351
+ end
352
+ end
353
+
354
+ @@proxy[:default] = proxy
355
+ end
356
+
357
+ def get_settings
358
+ @@settings
359
+ end
360
+
361
+ def getProxy(site=nil)
362
+ unless site.nil?
363
+ return @@proxy[site] unless @@proxy[site].nil?
364
+ end
365
+ return @@proxy[:default]
366
+ end
367
+
368
+ #
369
+ # INITIALIZE
370
+ #
371
+ # Possible preferences:
372
+ # :proxy => '127.0.0.1:port'
373
+ # :valid_sids => Hash.new,
374
+ # :sid_patterns => [],
375
+ # :logout_signatures => [],
376
+ # :update_valid_sids => false,
377
+ # :update_sids => false,
378
+ # :update_contentlength => true
379
+ def initialize( session_id, prefs={} )
380
+
381
+ @connection = nil
382
+
383
+ session = nil
384
+
385
+ session = ( session_id.is_a? Fixnum ) ? session_id : session_id.object_id
386
+ session = Digest::MD5.hexdigest(Time.now.to_f.to_s) if session_id.nil?
387
+
388
+ unless @@settings.has_key? session
389
+ @@settings[session] = {
390
+ :valid_sids => Hash.new,
391
+ :sid_patterns => [],
392
+ # :valid_csrf_tokens => Hash.new,
393
+ :csrf_patterns => [],
394
+ :csrf_requests => [],
395
+ :logout_signatures => [],
396
+ :logout_content_types => Hash.new,
397
+ :update_valid_sids => false,
398
+ :update_sids => false,
399
+ :update_session => true,
400
+ :update_contentlength => true,
401
+ :login_chats => [],
402
+ :www_auth => Hash.new,
403
+ :client_certificates => {},
404
+ :proxy_auth => Hash.new
405
+ }
406
+ end
407
+ @session = @@settings[session] # shortcut to settings
408
+ @session.update prefs
409
+
410
+ # @valid_csrf_tokens = Hash.new
411
+
412
+ addProxy( prefs[:proxy] ) if prefs.is_a? Hash and prefs[:proxy]
413
+
414
+ @ctx = OpenSSL::SSL::SSLContext.new()
415
+ @ctx.key = nil
416
+ @ctx.cert = nil
417
+
418
+ # TODO: Implement switches for URL-Encoding (http://www.blooberry.com/indexdot/html/topics/urlencoding.htm)
419
+ # TODO: Implement switches for Following Redirects
420
+ # TODO: Implement switches for Logging, Debugging, ...
421
+ end
422
+
423
+
424
+
425
+ private
426
+
427
+ #def doNtlmAuth(socket, request, ntlm_credentials)
428
+ def wwwAuthNTLM(socket, request, ntlm_credentials)
429
+ response_header = nil
430
+ begin
431
+ auth_request = request.copy
432
+
433
+ ntlm_challenge = nil
434
+ t1 = Watobo::NTLM::Message::Type1.new()
435
+ msg = "NTLM " + t1.encode64
436
+
437
+ auth_request.removeHeader("Connection")
438
+ auth_request.removeHeader("Authorization")
439
+
440
+ auth_request.addHeader("Authorization", msg)
441
+ auth_request.addHeader("Connection", "Keep-Alive")
442
+
443
+ if $DEBUG
444
+ puts "============= T1 ======================="
445
+ puts auth_request
446
+ end
447
+
448
+ data = auth_request.join + "\r\n"
449
+ socket.print data
450
+
451
+ puts "-----------------" if $DEBUG
452
+
453
+ response_header = []
454
+ rcode = nil
455
+ clen = nil
456
+ ntlm_challenge = nil
457
+ response_header = readHTTPHeader(socket)
458
+ response_header.each do |line|
459
+ if line =~ /^HTTP\/\d\.\d (\d+) (.*)/ then
460
+ rcode = $1.to_i
461
+ rmsg = $2
462
+ end
463
+ if line =~ /^WWW-Authenticate: (NTLM) (.+)\r\n/
464
+ ntlm_challenge = $2
465
+ end
466
+ if line =~ /^Content-Length: (\d{1,})\r\n/
467
+ clen = $1.to_i
468
+ end
469
+ break if line.strip.empty?
470
+ end
471
+ # puts "==================="
472
+
473
+ if $DEBUG
474
+ puts "--- T1 RESPONSE HEADERS ---"
475
+ puts response_header
476
+ puts "---"
477
+ end
478
+ if rcode == 401 #Authentication Required
479
+ puts "[NTLM] got ntlm challenge: #{ntlm_challenge}" if $DEBUG
480
+ return socket, response_header if ntlm_challenge.nil?
481
+ elsif rcode == 200 # Ok
482
+ puts "[NTLM] seems request doesn't need authentication" if $DEBUG
483
+ return socket, Watobo::Response.new(response_header)
484
+ else
485
+ if $DEBUG
486
+ puts "[NTLM] ... !#*+.!*peep* ...."
487
+ puts response_header
488
+ end
489
+ return socket, Watobo::Response.new(response_header)
490
+ end
491
+
492
+ # reading rest of response
493
+ rest = ''
494
+ Watobo::HTTPSocket.read_body(socket, :max_bytes => clen){ |d|
495
+ rest += d
496
+ }
497
+
498
+ if $DEBUG
499
+ puts "--- T1 RESPONSE BODY ---"
500
+ puts rest
501
+ puts "---"
502
+ end
503
+ t2 = Watobo::NTLM::Message.decode64(ntlm_challenge)
504
+ t3 = t2.response({:user => ntlm_credentials[:username],
505
+ :password => ntlm_credentials[:password],
506
+ :domain => ntlm_credentials[:domain]},
507
+ {:workstation => ntlm_credentials[:workstation], :ntlmv2 => true})
508
+
509
+ # puts "* NTLM-Credentials: #{ntlm_credentials[:username]},#{ntlm_credentials[:password]}, #{ntlm_credentials[:domain]}, #{ntlm_credentials[:workstation]}"
510
+ auth_request.removeHeader("Authorization")
511
+ auth_request.removeHeader("Connection")
512
+
513
+ auth_request.addHeader("Connection", "Close")
514
+
515
+ msg = "NTLM " + t3.encode64
516
+ auth_request.addHeader("Authorization", msg)
517
+ # puts "============= T3 ======================="
518
+
519
+ data = auth_request.join + "\r\n"
520
+
521
+ if $DEBUG
522
+ puts "= NTLM Type 3 ="
523
+ puts data
524
+ end
525
+ socket.print data
526
+
527
+ response_header = []
528
+ response_header = readHTTPHeader(socket)
529
+ response_header.each do |line|
530
+
531
+ if line =~ /^HTTP\/\d\.\d (\d+) (.*)/ then
532
+ rcode = $1.to_i
533
+ rmsg = $2
534
+ end
535
+ break if line.strip.empty?
536
+ end
537
+
538
+ if rcode == 200 # Ok
539
+ puts "[NTLM] Authentication Successfull" if $DEBUG
540
+ elsif rcode == 401 # Authentication Required
541
+ # TODO: authorization didn't work -> do some notification
542
+ # ...
543
+ puts "[NTLM] could not authenticate. Bad credentials?"
544
+ puts ntlm_credentials.to_yaml
545
+ end
546
+
547
+ return socket, Watobo::Response.new(response_header)
548
+ rescue => bang
549
+ puts "!!! ERROR: in ntlm_auth"
550
+ puts bang
551
+
552
+ puts bang.backtrace if $DEBUG
553
+ return nil, nil
554
+ end
555
+ end
556
+
557
+
558
+ ##################################################
559
+ # doProxyRequest
560
+ ################################################
561
+ def doProxyRequest(request, proxy, prefs={})
562
+ #puts "DO PROXY REQUEST"
563
+ # puts prefs.to_yaml
564
+ begin
565
+ tcp_socket = nil
566
+ site = request.site
567
+
568
+ auth_request = Watobo::Utils::copyObject(request)
569
+ auth_request.extend Watobo::Mixin::Parser::Url
570
+ auth_request.extend Watobo::Mixin::Parser::Web10
571
+ auth_request.extend Watobo::Mixin::Shaper::Web10
572
+ # timeout(6) do
573
+
574
+ tcp_socket = TCPSocket.new( proxy.host, proxy.port)
575
+ tcp_socket.setsockopt( Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
576
+ tcp_socket.sync = true
577
+ # end
578
+
579
+ auth_request.removeHeader("Proxy-Connection")
580
+ auth_request.removeHeader("Connection")
581
+
582
+ auth_request.addHeader("Pragma", "no-cache")
583
+
584
+ if proxy.has_login?
585
+ response_header = doProxyAuth(tcp_socket, auth_request, proxy)
586
+ # puts "* got request_header from doProxy Auth"
587
+ # puts request_header.class
588
+ puts "[Proxy Auth] Status: #{response_header.status}" if $DEBUG
589
+ return tcp_socket, response_header unless response_header.status =~ /401/
590
+ return tcp_socket, response_header unless prefs[:www_auth].has_key?(site)
591
+ end
592
+
593
+ # puts "CHECK WWW_AUTH"
594
+ # puts prefs.to_yaml
595
+ if prefs[:www_auth].has_key?(site)
596
+ case prefs[:www_auth][site][:type]
597
+ when AUTH_TYPE_NTLM
598
+ # puts "* found NTLM credentials for site #{site}"
599
+ socket, response_header = wwwAuthNTLM(tcp_socket, request, prefs[:www_auth][site])
600
+
601
+ #response_header.extend Watobo::Mixin::Parser::Url
602
+ #response_header.extend Watobo::Mixin::Parser::Web10
603
+ return socket, response_header
604
+ else
605
+ puts "* Unknown Authentication Type: #{prefs[:www_auth][site][:type]}"
606
+ end
607
+ else
608
+ data = auth_request.join + "\r\n"
609
+
610
+ tcp_socket.print data
611
+
612
+ response_header = readHTTPHeader(tcp_socket)
613
+ return tcp_socket, response_header
614
+ end
615
+ rescue => bang
616
+ puts bang
617
+ puts bang.backtrace if $DEBUG
618
+
619
+ end
620
+ return nil
621
+ end
622
+
623
+ def loggedOut?(response, prefs={})
624
+ begin
625
+ return false if @session[:logout_signatures].empty?
626
+ response.each do |line|
627
+ @session[:logout_signatures].each do |p|
628
+ # puts "!!!*LOGOUT*!!!" if line =~ /#{p}/
629
+ return true if line =~ /#{p}/
630
+ end
631
+ end
632
+ rescue => bang
633
+ puts bang
634
+ puts bang.backtrace if $DEBUG
635
+ end
636
+ return false
637
+ end
638
+
639
+ def error_response(msg, comment=nil)
640
+ er = []
641
+ er << "HTTP/1.1 555 Watobo Error\r\n"
642
+ er << "WATOBO: #{msg.gsub(/\r?\n/," ").strip}\r\n"
643
+ er << "Content-Length: 0\r\n"
644
+ er << "Connection: close\r\n"
645
+ er << "\r\n"
646
+ unless comment.nil?
647
+ body = "<H1>#{msg}</H1></br><H2>#{comment.gsub(/\r?\n/,"</br>")}</H2>"
648
+ er << body
649
+ end
650
+ er.extend Watobo::Mixin::Parser::Url
651
+ er.extend Watobo::Mixin::Parser::Web10
652
+ er.extend Watobo::Mixin::Shaper::Web10
653
+ er.fix_content_length
654
+ er
655
+ end
656
+
657
+
658
+
659
+ # def read_response(socket)
660
+
661
+ # return response
662
+ # end
663
+
664
+
665
+ def updateCSRFCache(csrf_cache, request, response)
666
+ puts "=UPDATE CSRF CACHE" if $DEBUG
667
+ # Thread.new{
668
+ begin
669
+ # site = request.site
670
+ @@csrf_lock.synchronize do
671
+ response.each do |line|
672
+ # puts line
673
+ @session[:csrf_patterns].each do |pat|
674
+ puts pat if $DEBUG
675
+ if line =~ /#{pat}/i then
676
+ token_key = Regexp.quote($1.upcase)
677
+ token_value = $2
678
+ #print "U"
679
+ puts "GOT NEW TOKEN (#{token_key}): #{token_value}" if $DEBUG
680
+ # @session[:valid_csrf_tokens][site] = Hash.new if @session[:valid_csrf_tokens][site].nil?
681
+ # @session[:valid_csrf_tokens][site][token_key] = token_value
682
+ csrf_cache[token_key] = token_value
683
+ end
684
+ end
685
+
686
+ end
687
+ end
688
+ rescue => bang
689
+ puts bang
690
+ if $DEBUG
691
+ puts bang.backtrace
692
+ puts "= Request"
693
+ puts request
694
+ puts "= Response"
695
+ puts response
696
+ puts "==="
697
+ end
698
+
699
+ end
700
+ # }
701
+ end
702
+
703
+ def closeSocket(socket)
704
+ return false if socket.nil?
705
+ begin
706
+ if socket.respond_to? :sysclose
707
+ #socket.io.shutdown(2)
708
+ # puts "sysclose"
709
+ socket.sysclose
710
+ elsif socket.respond_to? :shutdown
711
+ socket.shutdown(2)
712
+ elsif socket.respond_to? :close
713
+ socket.close
714
+ end
715
+ return true
716
+ rescue => bang
717
+ puts bang
718
+ puts bang.backtrace if $DEBUG
719
+ end
720
+ false
721
+ end
722
+
723
+ def updateSessionSettings(settings={})
724
+ [
725
+ :ssl_client_cert,
726
+ :ssl_client_key,
727
+ :ssl_client_pass,
728
+ :csrf_requests,
729
+ :valid_sids,
730
+ :sid_patterns,
731
+ :logout_signatures,
732
+ :logout_content_types,
733
+ :update_valid_sids,
734
+ :update_sids,
735
+ :update_session,
736
+ :update_contentlength,
737
+ :login_chats,
738
+ :follow_redirect
739
+ ].each do |k|
740
+ @session[k] = settings[k] if settings.has_key? k
741
+ end
742
+ end
743
+
744
+
745
+
746
+ def updateCSRFToken(csrf_cache, request)
747
+ # puts "=UPDATE CSRF TOKEN"
748
+ # @session[:valid_csrf_tokens].to_yaml
749
+ # puts request if request.site.nil?
750
+ # puts "= = = = = = "
751
+ @@csrf_lock.synchronize do
752
+ # if @session[:valid_csrf_tokens].has_key?(request.site)
753
+ # puts "* found token for site: #{request.site}"
754
+
755
+ request.map!{ |line|
756
+ res = line
757
+ @session[:csrf_patterns].each do |pat|
758
+ begin
759
+ if line =~ /#{pat}/i then
760
+ key = Regexp.quote($1.upcase)
761
+ old_value = $2
762
+ if csrf_cache.has_key?(key) then
763
+ res = line.gsub!(/#{Regexp.quote(old_value)}/, csrf_cache[key])
764
+ if res.nil? then
765
+ res = line
766
+ puts "!!!could not update token (#{key})"
767
+ end
768
+ end
769
+ end
770
+ rescue => bang
771
+ puts bang
772
+ puts bang.backtrace if $DEBUG
773
+ # puts @session.to_yaml
774
+ end
775
+ end
776
+ res
777
+ }
778
+ end
779
+ # end
780
+ end
781
+
782
+ # this function updates specific patterns of a request, e.g. CSRF Tokens
783
+ # Parameters:
784
+ # request - the request which has to be updated
785
+ # cache - the value store of already collected key-value-pairs
786
+ # patterns - pattern expressions, similar to session-id-patterns, e.g. /name="(sessid)" value="([0-9a-zA-Z!-]*)"/
787
+ def updateRequestPattern(request, cache, patterns)
788
+
789
+ request.map!{ |line|
790
+ res = line
791
+ patterns.each do |pat|
792
+ begin
793
+ if line =~ /#{pat}/i then
794
+ pattern_key = Regexp.quote($1.upcase)
795
+ old_value = Regexp.quote($2)
796
+ if cache.has_key?(sid_key) then
797
+ if not old_value =~ /#{cache[sid_key]}/ then # sid value has changed and needs update
798
+ # print "S"
799
+ # puts "+ update sid #{sid_key}"
800
+ # puts "-OLD: #{old_value}"
801
+ # puts "-NEW: #{@session[:valid_sids][request.site][sid_key]}"
802
+
803
+ # puts "---"
804
+ # dummy = Regexp.quote(old_value)
805
+ res = line.gsub!(/#{old_value}/, cache[sid_key])
806
+ if not res then puts "!!!could not update sid (#{sid_key})"; end
807
+ # puts "->#{line}"
808
+ end
809
+ end
810
+ end
811
+ rescue => bang
812
+ puts bang
813
+ puts bang.backtrace if $DEBUG
814
+ # puts @session.to_yaml
815
+ end
816
+ end
817
+ res
818
+ }
819
+ end
820
+
821
+ def applySessionSettings(prefs)
822
+ [ :update_valid_sids, :update_session, :update_contentlength, :valid_sids, :sid_patterns, :logout_signatures ].each do |v|
823
+ @@settings[v] = prefs[v] if prefs[v]
824
+ end
825
+ end
826
+
827
+
828
+ end
829
+ end
839
830
  end