watobo 0.9.19 → 0.9.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (266) hide show
  1. data/CHANGELOG.md +104 -0
  2. data/bin/nfq_server.rb +8 -20
  3. data/bin/watobo_gui.rb +8 -20
  4. data/config/forwarding_proxy.yml +2 -2
  5. data/lib/watobo.rb +12 -22
  6. data/lib/watobo/adapters.rb +12 -24
  7. data/lib/watobo/adapters/data_store.rb +76 -66
  8. data/lib/watobo/adapters/file/file_store.rb +295 -307
  9. data/lib/watobo/adapters/session_store.rb +13 -25
  10. data/lib/watobo/ca.rb +9 -21
  11. data/lib/watobo/config.rb +205 -217
  12. data/lib/watobo/constants.rb +8 -20
  13. data/lib/watobo/core.rb +11 -23
  14. data/lib/watobo/core/active_check.rb +11 -21
  15. data/lib/watobo/core/active_checks.rb +57 -69
  16. data/lib/watobo/core/ca.rb +388 -398
  17. data/lib/watobo/core/cert_store.rb +42 -54
  18. data/lib/watobo/core/chat.rb +100 -112
  19. data/lib/watobo/core/chats.rb +271 -275
  20. data/lib/watobo/core/client_cert_store.rb +33 -45
  21. data/lib/watobo/core/conversation.rb +56 -68
  22. data/lib/watobo/core/cookie.rb +31 -43
  23. data/lib/watobo/core/finding.rb +74 -86
  24. data/lib/watobo/core/findings.rb +113 -125
  25. data/lib/watobo/core/forwarding_proxy.rb +44 -35
  26. data/lib/watobo/core/fuzz_gen.rb +8 -20
  27. data/lib/watobo/core/intercept_carver.rb +176 -188
  28. data/lib/watobo/core/intercept_filter.rb +243 -255
  29. data/lib/watobo/core/interceptor.rb +106 -118
  30. data/lib/watobo/core/min_class.rb +12 -24
  31. data/lib/watobo/core/netfilter_queue.rb +178 -190
  32. data/lib/watobo/core/ott_cache.rb +152 -148
  33. data/lib/watobo/core/parameter.rb +53 -58
  34. data/lib/watobo/core/passive_check.rb +8 -20
  35. data/lib/watobo/core/passive_checks.rb +56 -68
  36. data/lib/watobo/core/passive_scanner.rb +54 -66
  37. data/lib/watobo/core/plugin.rb +19 -31
  38. data/lib/watobo/core/project.rb +8 -20
  39. data/lib/watobo/core/proxy.rb +51 -63
  40. data/lib/watobo/core/request.rb +128 -120
  41. data/lib/watobo/core/response.rb +59 -61
  42. data/lib/watobo/core/scanner.rb +8 -20
  43. data/lib/watobo/core/scanner3.rb +413 -425
  44. data/lib/watobo/core/scope.rb +91 -103
  45. data/lib/watobo/core/session.rb +109 -87
  46. data/lib/watobo/core/sid_cache.rb +106 -118
  47. data/lib/watobo/core/subscriber.rb +33 -45
  48. data/lib/watobo/defaults.rb +29 -41
  49. data/lib/watobo/external/diff/lcs.rb +8 -20
  50. data/lib/watobo/external/diff/lcs/array.rb +8 -20
  51. data/lib/watobo/external/diff/lcs/block.rb +8 -20
  52. data/lib/watobo/external/diff/lcs/callbacks.rb +8 -20
  53. data/lib/watobo/external/diff/lcs/change.rb +8 -20
  54. data/lib/watobo/external/diff/lcs/hunk.rb +8 -20
  55. data/lib/watobo/external/diff/lcs/ldiff.rb +8 -20
  56. data/lib/watobo/external/diff/lcs/string.rb +8 -20
  57. data/lib/watobo/externals.rb +14 -26
  58. data/lib/watobo/framework.rb +12 -24
  59. data/lib/watobo/framework/create_project.rb +68 -80
  60. data/lib/watobo/framework/init.rb +8 -20
  61. data/lib/watobo/framework/init_modules.rb +8 -20
  62. data/lib/watobo/framework/license_text.rb +36 -48
  63. data/lib/watobo/framework/load_chat.rb +21 -33
  64. data/lib/watobo/gui.rb +121 -133
  65. data/lib/watobo/gui/about_watobo.rb +8 -20
  66. data/lib/watobo/gui/browser_preview.rb +8 -20
  67. data/lib/watobo/gui/certificate_dialog.rb +8 -20
  68. data/lib/watobo/gui/chat_diff.rb +11 -21
  69. data/lib/watobo/gui/chatviewer_frame.rb +10 -22
  70. data/lib/watobo/gui/checkboxtree.rb +8 -20
  71. data/lib/watobo/gui/checks_policy_frame.rb +8 -20
  72. data/lib/watobo/gui/client_cert_dialog.rb +10 -21
  73. data/lib/watobo/gui/confirm_scan_dialog.rb +8 -20
  74. data/lib/watobo/gui/conversation_table.rb +54 -44
  75. data/lib/watobo/gui/conversation_table_ctrl.rb +215 -227
  76. data/lib/watobo/gui/conversation_table_ctrl2.rb +385 -393
  77. data/lib/watobo/gui/csrf_token_dialog.rb +11 -25
  78. data/lib/watobo/gui/custom_viewer.rb +357 -369
  79. data/lib/watobo/gui/dashboard.rb +8 -20
  80. data/lib/watobo/gui/define_scope_frame.rb +8 -20
  81. data/lib/watobo/gui/differ_frame.rb +223 -235
  82. data/lib/watobo/gui/edit_comment.rb +8 -20
  83. data/lib/watobo/gui/edit_scope_dialog.rb +8 -20
  84. data/lib/watobo/gui/export_dialog.rb +114 -0
  85. data/lib/watobo/gui/finding_info.rb +9 -21
  86. data/lib/watobo/gui/findings_tree.rb +8 -20
  87. data/lib/watobo/gui/full_scan_dialog.rb +8 -20
  88. data/lib/watobo/gui/fuzzer_gui.rb +8 -20
  89. data/lib/watobo/gui/goto_url_dialog.rb +78 -90
  90. data/lib/watobo/gui/hex_viewer.rb +25 -27
  91. data/lib/watobo/gui/html_viewer.rb +295 -307
  92. data/lib/watobo/gui/intercept_filter_dialog.rb +196 -208
  93. data/lib/watobo/gui/interceptor_gui.rb +1046 -1041
  94. data/lib/watobo/gui/interceptor_settings_dialog.rb +8 -20
  95. data/lib/watobo/gui/list_box.rb +109 -121
  96. data/lib/watobo/gui/log_file_viewer.rb +40 -52
  97. data/lib/watobo/gui/log_viewer.rb +87 -99
  98. data/lib/watobo/gui/login_wizzard.rb +8 -20
  99. data/lib/watobo/gui/main_window.rb +34 -33
  100. data/lib/watobo/gui/manual_request_editor.rb +25 -35
  101. data/lib/watobo/gui/master_pw_dialog.rb +8 -20
  102. data/lib/watobo/gui/mixins/gui_settings.rb +37 -49
  103. data/lib/watobo/gui/page_tree.rb +225 -237
  104. data/lib/watobo/gui/password_policy_dialog.rb +8 -20
  105. data/lib/watobo/gui/plugin_board.rb +8 -20
  106. data/lib/watobo/gui/preferences_dialog.rb +8 -20
  107. data/lib/watobo/gui/progress_window.rb +8 -20
  108. data/lib/watobo/gui/project_wizzard.rb +8 -20
  109. data/lib/watobo/gui/proxy_dialog.rb +117 -85
  110. data/lib/watobo/gui/quick_scan_dialog.rb +8 -20
  111. data/lib/watobo/gui/request_builder_frame.rb +125 -122
  112. data/lib/watobo/gui/request_editor.rb +53 -28
  113. data/lib/watobo/gui/rewrite_filters_dialog.rb +402 -414
  114. data/lib/watobo/gui/rewrite_rules_dialog.rb +380 -392
  115. data/lib/watobo/gui/save_chat_dialog.rb +148 -160
  116. data/lib/watobo/gui/scanner_settings_dialog.rb +8 -20
  117. data/lib/watobo/gui/select_chat_dialog.rb +8 -20
  118. data/lib/watobo/gui/session_management_dialog.rb +8 -20
  119. data/lib/watobo/gui/sites_tree.rb +118 -22
  120. data/lib/watobo/gui/status_bar.rb +8 -20
  121. data/lib/watobo/gui/table_editor.rb +76 -53
  122. data/lib/watobo/gui/tagless_viewer.rb +10 -21
  123. data/lib/watobo/gui/templates/plugin.rb +8 -20
  124. data/lib/watobo/gui/templates/plugin2.rb +99 -111
  125. data/lib/watobo/gui/templates/plugin_base.rb +152 -164
  126. data/lib/watobo/gui/text_viewer.rb +8 -20
  127. data/lib/watobo/gui/transcoder_window.rb +15 -22
  128. data/lib/watobo/gui/utils/gui_utils.rb +8 -20
  129. data/lib/watobo/gui/utils/init_icons.rb +94 -106
  130. data/lib/watobo/gui/utils/load_icons.rb +41 -53
  131. data/lib/watobo/gui/utils/load_plugins.rb +118 -130
  132. data/lib/watobo/gui/utils/master_password.rb +76 -88
  133. data/lib/watobo/gui/utils/save_default_settings.rb +121 -133
  134. data/lib/watobo/gui/utils/save_project_settings.rb +8 -20
  135. data/lib/watobo/gui/utils/save_proxy_settings.rb +53 -21
  136. data/lib/watobo/gui/utils/save_scanner_settings.rb +26 -38
  137. data/lib/watobo/gui/utils/session_history.rb +120 -132
  138. data/lib/watobo/gui/workspace_dialog.rb +8 -20
  139. data/lib/watobo/gui/www_auth_dialog.rb +8 -20
  140. data/lib/watobo/gui/xml_viewer_frame.rb +8 -20
  141. data/lib/watobo/http.rb +12 -23
  142. data/lib/watobo/http/cookies/cookies.rb +63 -70
  143. data/lib/watobo/http/data/data.rb +56 -64
  144. data/lib/watobo/http/data/json.rb +51 -0
  145. data/lib/watobo/http/url/url.rb +46 -58
  146. data/lib/watobo/http/xml/xml.rb +129 -141
  147. data/lib/watobo/interceptor.rb +11 -23
  148. data/lib/watobo/interceptor/proxy.rb +624 -625
  149. data/lib/watobo/interceptor/transparent.rb +22 -34
  150. data/lib/watobo/mixins.rb +18 -30
  151. data/lib/watobo/mixins/check_info.rb +35 -47
  152. data/lib/watobo/mixins/httpparser.rb +42 -35
  153. data/lib/watobo/mixins/request_parser.rb +8 -20
  154. data/lib/watobo/mixins/shapers.rb +484 -477
  155. data/lib/watobo/mixins/transcoders.rb +8 -20
  156. data/lib/watobo/parser.rb +9 -21
  157. data/lib/watobo/parser/html.rb +91 -103
  158. data/lib/watobo/sockets.rb +11 -23
  159. data/lib/watobo/sockets/agent.rb +836 -848
  160. data/lib/watobo/sockets/client_socket.rb +283 -277
  161. data/lib/watobo/sockets/connection.rb +409 -421
  162. data/lib/watobo/sockets/http_socket.rb +16 -23
  163. data/lib/watobo/sockets/ntlm_auth.rb +137 -149
  164. data/lib/watobo/utils.rb +18 -30
  165. data/lib/watobo/utils/check_regex.rb +8 -20
  166. data/lib/watobo/utils/copy_object.rb +8 -20
  167. data/lib/watobo/utils/crypto.rb +8 -20
  168. data/lib/watobo/utils/expand_range.rb +31 -43
  169. data/lib/watobo/utils/export_xml.rb +108 -0
  170. data/lib/watobo/utils/file_management.rb +8 -20
  171. data/lib/watobo/utils/hexprint.rb +17 -29
  172. data/lib/watobo/utils/load_chat.rb +8 -20
  173. data/lib/watobo/utils/load_icon.rb +8 -20
  174. data/lib/watobo/{external/ntlm → utils}/ntlm.rb +874 -796
  175. data/lib/watobo/utils/print_debug.rb +20 -32
  176. data/lib/watobo/utils/response_builder.rb +98 -110
  177. data/lib/watobo/utils/response_hash.rb +9 -20
  178. data/lib/watobo/utils/secure_eval.rb +10 -22
  179. data/lib/watobo/utils/strings.rb +18 -30
  180. data/lib/watobo/utils/text2request.rb +12 -20
  181. data/lib/watobo/utils/url.rb +31 -43
  182. data/lib/watobo/utils/utf16.rb +22 -0
  183. data/modules/active/Apache/mod_status.rb +9 -0
  184. data/modules/active/Apache/multiview.rb +161 -0
  185. data/modules/active/Flash/crossdomain.rb +9 -0
  186. data/modules/active/directories/dirwalker.rb +8 -20
  187. data/modules/active/discovery/fileextensions.rb +10 -22
  188. data/modules/active/discovery/http_methods.rb +8 -20
  189. data/modules/active/domino/domino_db.rb +8 -20
  190. data/modules/active/dotNET/custom_errors.rb +110 -122
  191. data/modules/active/dotNET/dotnet_files.rb +98 -110
  192. data/modules/active/fileinclusion/lfi_simple.rb +8 -20
  193. data/modules/active/jboss/jboss_basic.rb +8 -20
  194. data/modules/active/sap/business_objects.rb +63 -0
  195. data/modules/active/sap/its_commands.rb +8 -20
  196. data/modules/active/sap/its_service_parameter.rb +8 -20
  197. data/modules/active/sap/its_services.rb +8 -20
  198. data/modules/active/sap/its_xss.rb +8 -20
  199. data/modules/active/shell_shock/shell_shock.rb +149 -0
  200. data/modules/active/siebel/siebel_apps.rb +168 -180
  201. data/modules/active/sqlinjection/sql_boolean.rb +9 -21
  202. data/modules/active/sqlinjection/sqli_error.rb +10 -22
  203. data/modules/active/sqlinjection/sqli_timing.rb +228 -240
  204. data/modules/active/struts2/default_handler_ognl.rb +114 -126
  205. data/modules/active/struts2/include_params_ognl.rb +113 -125
  206. data/modules/active/xml/xml_xxe.rb +122 -127
  207. data/modules/active/xss/xss_ng.rb +223 -234
  208. data/modules/active/xss/xss_simple.rb +8 -20
  209. data/modules/passive/ajax.rb +76 -84
  210. data/modules/passive/autocomplete.rb +64 -76
  211. data/modules/passive/cookie_options.rb +8 -20
  212. data/modules/passive/cookie_xss.rb +9 -21
  213. data/modules/passive/detect_code.rb +9 -21
  214. data/modules/passive/detect_fileupload.rb +11 -22
  215. data/modules/passive/detect_infrastructure.rb +23 -35
  216. data/modules/passive/detect_one_time_tokens.rb +8 -20
  217. data/modules/passive/dirindexing.rb +9 -21
  218. data/modules/passive/disclosure_domino.rb +66 -79
  219. data/modules/passive/disclosure_emails.rb +9 -21
  220. data/modules/passive/disclosure_ipaddr.rb +15 -23
  221. data/modules/passive/filename_as_parameter.rb +8 -20
  222. data/modules/passive/form_spotter.rb +15 -21
  223. data/modules/passive/hidden_fields.rb +64 -70
  224. data/modules/passive/hotspots.rb +13 -22
  225. data/modules/passive/in_script_parameter.rb +15 -24
  226. data/modules/passive/multiple_server_headers.rb +8 -20
  227. data/modules/passive/possible_login.rb +12 -23
  228. data/modules/passive/redirect_url.rb +10 -22
  229. data/modules/passive/redirectionz.rb +9 -21
  230. data/modules/passive/sap-headers.rb +64 -76
  231. data/modules/passive/xss_dom.rb +10 -21
  232. data/plugins/catalog/catalog.rb +17 -23
  233. data/plugins/crawler/crawler.rb +12 -24
  234. data/plugins/crawler/gui.rb +13 -25
  235. data/plugins/crawler/gui/auth_frame.rb +278 -290
  236. data/plugins/crawler/gui/crawler_gui.rb +302 -320
  237. data/plugins/crawler/gui/general_settings_frame.rb +104 -116
  238. data/plugins/crawler/gui/hooks_frame.rb +88 -100
  239. data/plugins/crawler/gui/scope_frame.rb +58 -70
  240. data/plugins/crawler/gui/settings_tabbook.rb +46 -58
  241. data/plugins/crawler/gui/status_frame.rb +67 -78
  242. data/plugins/crawler/lib/bags.rb +26 -38
  243. data/plugins/crawler/lib/constants.rb +19 -31
  244. data/plugins/crawler/lib/engine.rb +505 -508
  245. data/plugins/crawler/lib/grabber.rb +77 -87
  246. data/plugins/crawler/lib/status.rb +82 -0
  247. data/plugins/crawler/lib/uri_mp.rb +20 -32
  248. data/plugins/filefinder/dbs/siebel_paths.txt +1118 -0
  249. data/plugins/filefinder/dbs/subs-big.lst +31986 -0
  250. data/plugins/filefinder/filefinder.rb +13 -23
  251. data/plugins/sqlmap/bin/test.rb +86 -98
  252. data/plugins/sqlmap/gui.rb +12 -24
  253. data/plugins/sqlmap/gui/main.rb +226 -238
  254. data/plugins/sqlmap/gui/options_frame.rb +105 -117
  255. data/plugins/sqlmap/lib/sqlmap_ctrl.rb +103 -115
  256. data/plugins/sqlmap/sqlmap.rb +10 -22
  257. data/plugins/sslchecker/cli/sslchecker_cli.rb +8 -20
  258. data/plugins/sslchecker/gui/cipher_table.rb +252 -264
  259. data/plugins/sslchecker/gui/gui.rb +267 -276
  260. data/plugins/sslchecker/gui/sslchecker.rb +12 -24
  261. data/plugins/sslchecker/lib/check.rb +172 -80
  262. data/plugins/wshell/gui/main.rb +115 -127
  263. data/plugins/wshell/lib/core.rb +85 -97
  264. data/plugins/wshell/wshell.rb +19 -31
  265. metadata +14 -6
  266. data/.yardopts +0 -24
@@ -1,24 +1,12 @@
1
- # .
1
+ #.
2
2
  # transcoders.rb
3
- #
4
- # Copyright 2013 by siberas, http://www.siberas.de
5
- #
6
- # This file is part of WATOBO (Web Application Tool Box)
7
- # http://watobo.sourceforge.com
8
- #
9
- # WATOBO is free software; you can redistribute it and/or modify
10
- # it under the terms of the GNU General Public License as published by
11
- # the Free Software Foundation version 2 of the License.
12
- #
13
- # WATOBO is distributed in the hope that it will be useful,
14
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- # GNU General Public License for more details.
17
- #
18
- # You should have received a copy of the GNU General Public License
19
- # along with WATOBO; if not, write to the Free Software
20
- # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
- # .
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
+
22
10
  # @private
23
11
  module Watobo#:nodoc: all
24
12
  module Mixin
data/lib/watobo/parser.rb CHANGED
@@ -1,22 +1,10 @@
1
- # .
1
+ #.
2
2
  # parser.rb
3
- #
4
- # Copyright 2013 by siberas, http://www.siberas.de
5
- #
6
- # This file is part of WATOBO (Web Application Tool Box)
7
- # http://watobo.sourceforge.com
8
- #
9
- # WATOBO is free software; you can redistribute it and/or modify
10
- # it under the terms of the GNU General Public License as published by
11
- # the Free Software Foundation version 2 of the License.
12
- #
13
- # WATOBO is distributed in the hope that it will be useful,
14
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- # GNU General Public License for more details.
17
- #
18
- # You should have received a copy of the GNU General Public License
19
- # along with WATOBO; if not, write to the Free Software
20
- # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
- # .
22
- require 'watobo/parser/html'
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,106 +1,94 @@
1
- # .
1
+ #.
2
2
  # html.rb
3
- #
4
- # Copyright 2013 by siberas, http://www.siberas.de
5
- #
6
- # This file is part of WATOBO (Web Application Tool Box)
7
- # http://watobo.sourceforge.com
8
- #
9
- # WATOBO is free software; you can redistribute it and/or modify
10
- # it under the terms of the GNU General Public License as published by
11
- # the Free Software Foundation version 2 of the License.
12
- #
13
- # WATOBO is distributed in the hope that it will be useful,
14
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- # GNU General Public License for more details.
17
- #
18
- # You should have received a copy of the GNU General Public License
19
- # along with WATOBO; if not, write to the Free Software
20
- # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
- # .
22
- # @private
23
- module Watobo#:nodoc: all
24
- module Parser
25
- module HTML
26
- class Form
27
- def input_fields(&block)
28
- if block_given?
29
- @input_fields.each do |field|
30
- yield field
31
- end
32
- end
33
- @input_fields
34
- end
35
-
36
- def initialize(form_css)
37
- @form = form_css
38
- @input_fields = []
39
- @form.css('input').each do |i|
40
- @input_fields << InputField.new(i)
41
- end
42
-
43
- end
44
- end
45
-
46
- class InputField
47
- attr :id
48
- attr :value
49
- attr :name
50
- # attr :autocomplete
51
-
52
- def to_www_form_parm()
53
- Watobo::WWWFormParameter.new(:name => @name, :value => @value)
54
- end
55
-
56
- def to_url_parm()
57
- Watobo::UrlParameter.new(:name => @name, :value => @value)
58
- end
59
-
60
- def initialize(input_css)
61
- @css = input_css
62
- @id = input_css["id"].nil? ? "" : input_css["id"]
63
- @value = input_css["value"].nil? ? "" : input_css["value"]
64
- @name = input_css["name"].nil? ? "" : input_css["name"]
65
- #@autocomplete = input_css["autocomplete"]
66
- end
67
-
68
- def method_missing(name, *args, &block)
69
- @css[name.to_s].nil? ? "" : input_css[name.to_s]
70
- end
71
-
72
- end
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
73
9
 
74
- class Links
75
-
76
- end
77
-
78
- def links(&block)
79
-
80
- end
81
-
82
- def input_fields(&block)
83
- fields = []
84
- forms do |form|
85
- form.input_fields do |field|
86
- yield field if block_given?
87
- fields << field
88
- end
89
- end
90
- fields
91
- end
92
-
93
-
94
- def forms(&block)
95
- fs = []
96
- doc = Nokogiri::HTML(self.body)
97
- doc.css('form').each do |f|
98
- fo = Form.new(f)
99
- yield fo if block_given?
100
- end
101
- fs
102
- end
103
-
104
- end
105
- end
10
+ # @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
106
94
  end
@@ -1,25 +1,13 @@
1
- # .
1
+ #.
2
2
  # sockets.rb
3
- #
4
- # Copyright 2013 by siberas, http://www.siberas.de
5
- #
6
- # This file is part of WATOBO (Web Application Tool Box)
7
- # http://watobo.sourceforge.com
8
- #
9
- # WATOBO is free software; you can redistribute it and/or modify
10
- # it under the terms of the GNU General Public License as published by
11
- # the Free Software Foundation version 2 of the License.
12
- #
13
- # WATOBO is distributed in the hope that it will be useful,
14
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- # GNU General Public License for more details.
17
- #
18
- # You should have received a copy of the GNU General Public License
19
- # along with WATOBO; if not, write to the Free Software
20
- # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
- # .
22
- %w( client_socket http_socket ).each do |lib|
23
- require "watobo/sockets/#{lib}"
24
- end
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
25
9
 
10
+ %w( client_socket http_socket ).each do |lib|
11
+ require "watobo/sockets/#{lib}"
12
+ end
13
+
@@ -1,851 +1,839 @@
1
- # .
1
+ #.
2
2
  # agent.rb
3
- #
4
- # Copyright 2013 by siberas, http://www.siberas.de
5
- #
6
- # This file is part of WATOBO (Web Application Tool Box)
7
- # http://watobo.sourceforge.com
8
- #
9
- # WATOBO is free software; you can redistribute it and/or modify
10
- # it under the terms of the GNU General Public License as published by
11
- # the Free Software Foundation version 2 of the License.
12
- #
13
- # WATOBO is distributed in the hope that it will be useful,
14
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- # GNU General Public License for more details.
17
- #
18
- # You should have received a copy of the GNU General Public License
19
- # along with WATOBO; if not, write to the Free Software
20
- # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
- # .
22
- # @private
23
- module Watobo#:nodoc: all
24
- module HTTPSocket
25
- class Agent_UNUSED
26
-
27
- include Watobo::Constants
28
- extend Watobo::Subscriber
29
-
30
-
31
- def runLogin(chat_list, prefs={})
32
- @@login_mutex.synchronize do
33
- begin
34
- @@login_in_progress = true
35
- login_prefs = Hash.new
36
- login_prefs.update prefs
37
- dummy = {:ignore_logout => true, :update_sids => true, :update_session => true, :update_contentlength => true}
38
- login_prefs.update dummy
39
- puts "! Start Login ..." if $DEBUG
40
- unless chat_list.empty?
41
- # puts login_prefs.to_yaml
42
- chat_list.each do |chat|
43
- print "! LoginRequest: #{chat.id}" if $DEBUG
44
- test_req = chat.copyRequest
45
- request, response = doRequest(test_req, login_prefs)
46
- end
47
- else
48
- puts "! no login script configured !"
49
- end
50
- rescue => bang
51
- puts "!ERROR in runLogin"
52
- puts bang.backtrace if $DEBUG
53
- ensure
54
- @@login_in_progress = false
55
- @@login_cv.signal
56
- # exit
57
- # print "L]"
58
- end
59
- end
60
- end
61
-
62
- def connected?
63
- !@connection.nil?
64
- end
65
-
66
-
67
-
68
-
69
-
70
- # sendHTTPRequest
71
- def send(request, prefs={})
72
- #Watobo.print_debug("huhule", "#{prefs.to_yaml}", "gagagag")
73
- begin
74
- @lasterror = nil
75
- response_header = nil
76
-
77
-
78
- # update current preferences, prefs given here are stronger then global settings!
79
- current_prefs = Hash.new
80
- [:update_session, :update_sids, :update_contentlength, :ssl_cipher, :www_auth, :client_certificates].each do |k|
81
- current_prefs[k] = prefs[k].nil? ? @session[k] : prefs[k]
82
- end
83
-
84
- updateSession(request) if current_prefs[:update_session] == true
85
-
86
- #---------------------------------------
87
- request.removeHeader("^Proxy-Connection") #if not use_proxy
88
- #request.removeHeader("^Connection") #if not use_proxy
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 then
99
- request.fix_content_length()
100
- end
101
-
102
- #request.add_header("Via", "Watobo") if use_proxy
103
- #puts request
104
- # puts "=============="
105
- rescue SocketError
106
- puts "!!! unknown hostname #{host}"
107
- puts request.first
108
- return nil, "WATOBO: Could not resolve hostname #{host}", nil
109
- rescue => bang
110
- puts bang
111
- puts bang.backtrace if $DEBUG
112
- end
113
-
114
- begin
115
- unless proxy.nil?
116
- # connection requires proxy
117
- # puts "* use proxy #{proxy.name}"
118
-
119
- # check for regular proxy authentication
120
- if request.is_ssl?
121
- socket, response_header = sslProxyConnect(request, proxy, current_prefs)
122
- return socket, response_header, error_response("Could Not Connect To Proxy: #{proxy.name} (#{proxy.host}:#{proxy.port})\n", "#{response_header}") if socket.nil?
123
-
124
- if current_prefs[:www_auth].has_key?(site)
125
- case current_prefs[:www_auth][site][:type]
126
- when AUTH_TYPE_NTLM
127
- # puts "* found NTLM credentials for site #{site}"
128
- socket, response_header = wwwAuthNTLM(socket, request, current_prefs[:www_auth][site])
129
-
130
- else
131
- puts "* Unknown Authentication Type: #{current_prefs[:www_auth][site][:type]}"
132
- end
133
- else
134
-
135
- data = request.join + "\r\n"
136
- unless socket.nil?
137
- socket.print data
138
- response_header = readHTTPHeader(socket, current_prefs)
139
- end
140
- end
141
- return socket, request, response_header
142
- end
143
- # puts "* doProxyRequest"
144
- socket, response_header = doProxyRequest(request, proxy, current_prefs)
145
- # puts socket.class
146
- return socket, response_header, error_response("Could Not Connect To Proxy: #{proxy.name} (#{proxy.host}:#{proxy.port})\n", "#{response_header}") if socket.nil?
147
-
148
- return socket, request, response_header
149
- else
150
- # direct connection to host
151
- tcp_socket = nil
152
- # timeout(6) do
153
- #puts "* no proxy - direct connection"
154
- tcp_socket = TCPSocket.new( host, port )
155
- tcp_socket.setsockopt( Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
156
- tcp_socket.sync = true
157
-
158
- socket = tcp_socket
159
- if request.is_ssl?
160
- ssl_prefs = {}
161
- ssl_prefs[:ssl_cipher] = current_prefs[:ssl_cipher] if current_prefs.has_key? :ssl_cipher
162
- if current_prefs.has_key? :client_certificates
163
- if current_prefs[:client_certificates].has_key? request.site
164
- puts "* use ssl client certificate for site #{request.site}" if $DEBUG
165
- ssl_prefs[:ssl_client_cert] = current_prefs[:client_certificates][request.site][:ssl_client_cert]
166
- ssl_prefs[:ssl_client_key] = current_prefs[:client_certificates][request.site][:ssl_client_key]
167
- end
168
- end
169
- socket = sslConnect(tcp_socket, ssl_prefs)
170
- end
171
- #puts socket.class
172
- # remove URI before sending request but cache it for restoring request
173
- uri_cache = nil
174
- uri_cache = request.removeURI #if proxy.nil?
175
-
176
-
177
- # request.addHeader("Proxy-Connection", "Close") unless proxy.nil?
178
- # request.addHeader("Accept-Encoding", "gzip;q=0;identity; q=0.5, *;q=0") #don't want encoding
179
-
180
-
181
- if current_prefs[:www_auth].has_key?(site)
182
- case current_prefs[:www_auth][site][:type]
183
- when AUTH_TYPE_NTLM
184
- # puts "* found NTLM credentials for site #{site}"
185
- socket, response_header = wwwAuthNTLM(socket, request, current_prefs[:www_auth][site])
186
- request.restoreURI(uri_cache)
187
-
188
- else
189
- puts "* Unknown Authentication Type: #{current_prefs[:www_auth][site][:type]}"
190
- end
191
- else
192
- # puts "========== Add Headers"
193
- # request.addHeader("Connection", "Close") #if not use_proxy
194
-
195
- data = request.join
196
- unless request.has_body?
197
- data << "\r\n" unless data =~ /\r\n\r\n$/
198
- end
199
- # puts "= SESSION ="
200
- # puts data
201
- # puts data.unpack("H*")[0].gsub(/0d0a/,"0d0a\n")
202
-
203
- unless socket.nil?
204
- socket.print data
205
- # if socket.is_a? OpenSSL::SSL::SSLSocket
206
- # socket.io.shutdown(Socket::SHUT_WR)
207
- # else
208
- # socket.shutdown(Socket::SHUT_WR)
209
- # end
210
- response_header = readHTTPHeader(socket, current_prefs)
211
- end
212
- # RESTORE URI FOR HISTORY/LOG
213
- request.restoreURI(uri_cache)
214
-
215
- end
216
- return socket, Watobo::Request.new(request), Watobo::Response.new(response_header)
217
- end
218
-
219
- rescue Errno::ECONNREFUSED
220
- response = error_response "connection refused (#{host}:#{port})"
221
- puts response
222
- socket = nil
223
- rescue Errno::ECONNRESET
224
- response = error_response "connection reset (#{host}:#{port})"
225
- socket = nil
226
- rescue Errno::ECONNABORTED
227
- response = error_response "connection aborted (#{host}:#{port})"
228
- socket = nil
229
- rescue Errno::EHOSTUNREACH
230
- response = error_response "host unreachable (#{host}:#{port})"
231
- socket = nil
232
- rescue Timeout::Error
233
- #request = "WATOBO: TimeOut (#{host}:#{port})\n"
234
- response = error_response "TimeOut (#{host}:#{port})"
235
- socket = nil
236
- rescue Errno::ETIMEDOUT
237
- response = error_response "TimeOut (#{host}:#{port})"
238
- socket = nil
239
- rescue Errno::ENOTCONN
240
- puts "!!!ENOTCONN"
241
- rescue OpenSSL::SSL::SSLError
242
- response = error_response "SSL-Error", $!.backtrace.join
243
- socket = nil
244
- rescue => bang
245
- response = error_response "ERROR:", "#{bang}\n#{bang.backtrace}"
246
- socket = nil
247
-
248
- puts bang
249
- puts bang.backtrace if $DEBUG
250
- end
251
- puts response
252
- return socket, request, response
253
- end
254
-
255
- def sidCache()
256
- #puts @project
257
- @session[:valid_sids]
258
- end
259
-
260
- def setSIDCache(new_cache = {} )
261
- @session[:valid_sids] = new_cache if new_cache.is_a? Hash
262
- end
263
-
264
- # +++ doRequest(request) +++
265
- # + function:
266
- #
267
- def doRequest(request, opts={} )
268
- begin
269
- @session.update opts
270
- # puts "[doRequest] #{@session.to_yaml}"
271
- # puts "#[#{self.class}]" + @session[:csrf_requests].first.object_id.to_s
272
- unless @session[:csrf_requests].empty? or @session[:csrf_patterns].empty?
273
- csrf_cache = Hash.new
274
- @session[:csrf_requests].each do |req|
275
- copy = Watobo::Request.new YAML.load(YAML.dump(req))
276
-
277
- updateCSRFToken(csrf_cache, copy)
278
- socket, csrf_request, csrf_response = sendHTTPRequest(copy, opts)
279
- next if socket.nil?
280
- # puts "= Response Headers:"
281
- # puts csrf_response
282
- # puts "==="
283
- update_sids(csrf_request.host, csrf_response.headers)
284
- next if socket.nil?
285
- # p "*"
286
- # csrf_response = readHTTPHeader(socket)
287
- readHTTPBody(socket, csrf_response, csrf_request, opts)
288
-
289
- next if csrf_response.body.nil?
290
- update_sids(csrf_request.host, [csrf_response.body])
291
-
292
- updateCSRFCache(csrf_cache, csrf_request, [csrf_response.body]) if csrf_response.content_type =~ /text\//
293
-
294
- # socket.close
295
- closeSocket(socket)
296
- end
297
- #p @session[:csrf_requests].length
298
- updateCSRFToken(csrf_cache, request)
299
- end
300
-
301
- socket, request, response = sendHTTPRequest(request, opts)
302
-
303
- if socket.nil?
304
- return request, response
305
- end
306
-
307
- update_sids(request.host, response.headers) if @session[:update_sids] == true
308
-
309
- if @session[:follow_redirect]
310
- # puts response.status
311
- if response.status =~ /^302/
312
- response.extend Watobo::Mixin::Parser::Web10
313
- request.extend Watobo::Mixin::Shaper::Web10
314
-
315
- loc_header = response.headers("Location:").first
316
- new_location = loc_header.gsub(/^[^:]*:/,'').strip
317
- unless new_location =~ /^http/
318
- new_location = request.proto + "://" + request.site + "/" + request.dir + "/" + new_location.sub(/^[\.\/]*/,'')
319
- end
320
-
321
- notify(:follow_redirect, new_location)
322
- nr = Watobo::Request.new YAML.load(YAML.dump(request))
323
-
324
- # create GET request for new location
325
- nr.replaceMethod("GET")
326
- nr.removeHeader("Content-Length")
327
- nr.removeBody()
328
- nr.replaceURL(new_location)
329
-
330
-
331
- socket, request, response = sendHTTPRequest(nr, opts)
332
-
333
- if socket.nil?
334
- #return nil, request
335
- return request, response
336
- end
337
- end
338
- end
339
-
340
- readHTTPBody(socket, response, request, opts)
341
-
342
- unless response.body.nil?
343
- update_sids(request.host, [response.body]) if @session[:update_sids] == true and response.content_type =~ /text\//
344
- end
345
-
346
- #socket.close
347
- closeSocket(socket)
348
-
349
- rescue => bang
350
- # puts "! Error in doRequest"
351
- puts "! Module #{Module.nesting[0].name}"
352
- puts bang
353
- # puts bang.backtrace if $DEBUG
354
- @lasterror = bang
355
- # raise
356
- # ensure
357
- end
358
-
359
- response.extend Watobo::Mixin::Parser::Web10
360
- return request, response
361
- end
362
-
363
- def addProxy(prefs=nil)
364
-
365
- proxy = nil
366
- unless prefs.nil?
367
- proxy = Proxy.new(prefs)
368
- # proxy.setCredentials(prefs[:credentials]) unless prefs[:credentials].nil?
369
- unless prefs[:site].nil?
370
- @@proxy[prefs[:site]] = proxy
371
- return
372
- end
373
- end
374
-
375
- @@proxy[:default] = proxy
376
- end
377
-
378
- def get_settings
379
- @@settings
380
- end
381
-
382
- def getProxy(site=nil)
383
- unless site.nil?
384
- return @@proxy[site] unless @@proxy[site].nil?
385
- end
386
- return @@proxy[:default]
387
- end
388
-
389
- #
390
- # INITIALIZE
391
- #
392
- # Possible preferences:
393
- # :proxy => '127.0.0.1:port'
394
- # :valid_sids => Hash.new,
395
- # :sid_patterns => [],
396
- # :logout_signatures => [],
397
- # :update_valid_sids => false,
398
- # :update_sids => false,
399
- # :update_contentlength => true
400
- def initialize( session_id, prefs={} )
401
-
402
- @connection = nil
403
-
404
- session = nil
405
-
406
- session = ( session_id.is_a? Fixnum ) ? session_id : session_id.object_id
407
- session = Digest::MD5.hexdigest(Time.now.to_f.to_s) if session_id.nil?
408
-
409
- unless @@settings.has_key? session
410
- @@settings[session] = {
411
- :valid_sids => Hash.new,
412
- :sid_patterns => [],
413
- # :valid_csrf_tokens => Hash.new,
414
- :csrf_patterns => [],
415
- :csrf_requests => [],
416
- :logout_signatures => [],
417
- :logout_content_types => Hash.new,
418
- :update_valid_sids => false,
419
- :update_sids => false,
420
- :update_session => true,
421
- :update_contentlength => true,
422
- :login_chats => [],
423
- :www_auth => Hash.new,
424
- :client_certificates => {},
425
- :proxy_auth => Hash.new
426
- }
427
- end
428
- @session = @@settings[session] # shortcut to settings
429
- @session.update prefs
430
-
431
- # @valid_csrf_tokens = Hash.new
432
-
433
- addProxy( prefs[:proxy] ) if prefs.is_a? Hash and prefs[:proxy]
434
-
435
- @ctx = OpenSSL::SSL::SSLContext.new()
436
- @ctx.key = nil
437
- @ctx.cert = nil
438
-
439
- # TODO: Implement switches for URL-Encoding (http://www.blooberry.com/indexdot/html/topics/urlencoding.htm)
440
- # TODO: Implement switches for Following Redirects
441
- # TODO: Implement switches for Logging, Debugging, ...
442
- end
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
443
9
 
444
-
445
-
446
- private
447
-
448
- #def doNtlmAuth(socket, request, ntlm_credentials)
449
- def wwwAuthNTLM(socket, request, ntlm_credentials)
450
- response_header = nil
451
- begin
452
- auth_request = request.copy
453
-
454
- ntlm_challenge = nil
455
- t1 = Net::NTLM::Message::Type1.new()
456
- msg = "NTLM " + t1.encode64
457
-
458
- auth_request.removeHeader("Connection")
459
- auth_request.removeHeader("Authorization")
460
-
461
- auth_request.addHeader("Authorization", msg)
462
- auth_request.addHeader("Connection", "Keep-Alive")
463
-
464
- if $DEBUG
465
- puts "============= T1 ======================="
466
- puts auth_request
467
- end
468
-
469
- data = auth_request.join + "\r\n"
470
- socket.print data
471
-
472
- puts "-----------------" if $DEBUG
473
-
474
- response_header = []
475
- rcode = nil
476
- clen = nil
477
- ntlm_challenge = nil
478
- response_header = readHTTPHeader(socket)
479
- response_header.each do |line|
480
- if line =~ /^HTTP\/\d\.\d (\d+) (.*)/ then
481
- rcode = $1.to_i
482
- rmsg = $2
483
- end
484
- if line =~ /^WWW-Authenticate: (NTLM) (.+)\r\n/
485
- ntlm_challenge = $2
486
- end
487
- if line =~ /^Content-Length: (\d{1,})\r\n/
488
- clen = $1.to_i
489
- end
490
- break if line.strip.empty?
491
- end
492
- # puts "==================="
493
-
494
- if $DEBUG
495
- puts "--- T1 RESPONSE HEADERS ---"
496
- puts response_header
497
- puts "---"
498
- end
499
- if rcode == 401 #Authentication Required
500
- puts "[NTLM] got ntlm challenge: #{ntlm_challenge}" if $DEBUG
501
- return socket, response_header if ntlm_challenge.nil?
502
- elsif rcode == 200 # Ok
503
- puts "[NTLM] seems request doesn't need authentication" if $DEBUG
504
- return socket, Watobo::Response.new(response_header)
505
- else
506
- if $DEBUG
507
- puts "[NTLM] ... !#*+.!*peep* ...."
508
- puts response_header
509
- end
510
- return socket, Watobo::Response.new(response_header)
511
- end
512
-
513
- # reading rest of response
514
- rest = ''
515
- Watobo::HTTPSocket.read_body(socket, :max_bytes => clen){ |d|
516
- rest += d
517
- }
518
-
519
- if $DEBUG
520
- puts "--- T1 RESPONSE BODY ---"
521
- puts rest
522
- puts "---"
523
- end
524
- t2 = Net::NTLM::Message.decode64(ntlm_challenge)
525
- t3 = t2.response({:user => ntlm_credentials[:username],
526
- :password => ntlm_credentials[:password],
527
- :domain => ntlm_credentials[:domain]},
528
- {:workstation => ntlm_credentials[:workstation], :ntlmv2 => true})
529
-
530
- # puts "* NTLM-Credentials: #{ntlm_credentials[:username]},#{ntlm_credentials[:password]}, #{ntlm_credentials[:domain]}, #{ntlm_credentials[:workstation]}"
531
- auth_request.removeHeader("Authorization")
532
- auth_request.removeHeader("Connection")
533
-
534
- auth_request.addHeader("Connection", "Close")
535
-
536
- msg = "NTLM " + t3.encode64
537
- auth_request.addHeader("Authorization", msg)
538
- # puts "============= T3 ======================="
539
-
540
- data = auth_request.join + "\r\n"
541
-
542
- if $DEBUG
543
- puts "= NTLM Type 3 ="
544
- puts data
545
- end
546
- socket.print data
547
-
548
- response_header = []
549
- response_header = readHTTPHeader(socket)
550
- response_header.each do |line|
551
-
552
- if line =~ /^HTTP\/\d\.\d (\d+) (.*)/ then
553
- rcode = $1.to_i
554
- rmsg = $2
555
- end
556
- break if line.strip.empty?
557
- end
558
-
559
- if rcode == 200 # Ok
560
- puts "[NTLM] Authentication Successfull" if $DEBUG
561
- elsif rcode == 401 # Authentication Required
562
- # TODO: authorization didn't work -> do some notification
563
- # ...
564
- puts "[NTLM] could not authenticate. Bad credentials?"
565
- puts ntlm_credentials.to_yaml
566
- end
567
-
568
- return socket, Watobo::Response.new(response_header)
569
- rescue => bang
570
- puts "!!! ERROR: in ntlm_auth"
571
- puts bang
572
-
573
- puts bang.backtrace if $DEBUG
574
- return nil, nil
575
- end
576
- end
577
-
578
-
579
- ##################################################
580
- # doProxyRequest
581
- ################################################
582
- def doProxyRequest(request, proxy, prefs={})
583
- #puts "DO PROXY REQUEST"
584
- # puts prefs.to_yaml
585
- begin
586
- tcp_socket = nil
587
- site = request.site
588
-
589
- auth_request = Watobo::Utils::copyObject(request)
590
- auth_request.extend Watobo::Mixin::Parser::Url
591
- auth_request.extend Watobo::Mixin::Parser::Web10
592
- auth_request.extend Watobo::Mixin::Shaper::Web10
593
- # timeout(6) do
594
-
595
- tcp_socket = TCPSocket.new( proxy.host, proxy.port)
596
- tcp_socket.setsockopt( Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
597
- tcp_socket.sync = true
598
- # end
599
-
600
- auth_request.removeHeader("Proxy-Connection")
601
- auth_request.removeHeader("Connection")
602
-
603
- auth_request.addHeader("Pragma", "no-cache")
604
-
605
- if proxy.has_login?
606
- response_header = doProxyAuth(tcp_socket, auth_request, proxy)
607
- # puts "* got request_header from doProxy Auth"
608
- # puts request_header.class
609
- puts "[Proxy Auth] Status: #{response_header.status}" if $DEBUG
610
- return tcp_socket, response_header unless response_header.status =~ /401/
611
- return tcp_socket, response_header unless prefs[:www_auth].has_key?(site)
612
- end
613
-
614
- # puts "CHECK WWW_AUTH"
615
- # puts prefs.to_yaml
616
- if prefs[:www_auth].has_key?(site)
617
- case prefs[:www_auth][site][:type]
618
- when AUTH_TYPE_NTLM
619
- # puts "* found NTLM credentials for site #{site}"
620
- socket, response_header = wwwAuthNTLM(tcp_socket, request, prefs[:www_auth][site])
621
-
622
- #response_header.extend Watobo::Mixin::Parser::Url
623
- #response_header.extend Watobo::Mixin::Parser::Web10
624
- return socket, response_header
625
- else
626
- puts "* Unknown Authentication Type: #{prefs[:www_auth][site][:type]}"
627
- end
628
- else
629
- data = auth_request.join + "\r\n"
630
-
631
- tcp_socket.print data
632
-
633
- response_header = readHTTPHeader(tcp_socket)
634
- return tcp_socket, response_header
635
- end
636
- rescue => bang
637
- puts bang
638
- puts bang.backtrace if $DEBUG
639
-
640
- end
641
- return nil
642
- end
643
-
644
- def loggedOut?(response, prefs={})
645
- begin
646
- return false if @session[:logout_signatures].empty?
647
- response.each do |line|
648
- @session[:logout_signatures].each do |p|
649
- # puts "!!!*LOGOUT*!!!" if line =~ /#{p}/
650
- return true if line =~ /#{p}/
651
- end
652
- end
653
- rescue => bang
654
- puts bang
655
- puts bang.backtrace if $DEBUG
656
- end
657
- return false
658
- end
659
-
660
- def error_response(msg, comment=nil)
661
- er = []
662
- er << "HTTP/1.1 555 Watobo Error\r\n"
663
- er << "WATOBO: #{msg.gsub(/\r?\n/," ").strip}\r\n"
664
- er << "Content-Length: 0\r\n"
665
- er << "Connection: close\r\n"
666
- er << "\r\n"
667
- unless comment.nil?
668
- body = "<H1>#{msg}</H1></br><H2>#{comment.gsub(/\r?\n/,"</br>")}</H2>"
669
- er << body
670
- end
671
- er.extend Watobo::Mixin::Parser::Url
672
- er.extend Watobo::Mixin::Parser::Web10
673
- er.extend Watobo::Mixin::Shaper::Web10
674
- er.fix_content_length
675
- er
676
- end
677
-
678
-
679
-
680
- # def read_response(socket)
681
-
682
- # return response
683
- # end
684
-
685
-
686
- def updateCSRFCache(csrf_cache, request, response)
687
- puts "=UPDATE CSRF CACHE" if $DEBUG
688
- # Thread.new{
689
- begin
690
- # site = request.site
691
- @@csrf_lock.synchronize do
692
- response.each do |line|
693
- # puts line
694
- @session[:csrf_patterns].each do |pat|
695
- puts pat if $DEBUG
696
- if line =~ /#{pat}/i then
697
- token_key = Regexp.quote($1.upcase)
698
- token_value = $2
699
- #print "U"
700
- puts "GOT NEW TOKEN (#{token_key}): #{token_value}" if $DEBUG
701
- # @session[:valid_csrf_tokens][site] = Hash.new if @session[:valid_csrf_tokens][site].nil?
702
- # @session[:valid_csrf_tokens][site][token_key] = token_value
703
- csrf_cache[token_key] = token_value
704
- end
705
- end
706
-
707
- end
708
- end
709
- rescue => bang
710
- puts bang
711
- if $DEBUG
712
- puts bang.backtrace
713
- puts "= Request"
714
- puts request
715
- puts "= Response"
716
- puts response
717
- puts "==="
718
- end
719
-
720
- end
721
- # }
722
- end
723
-
724
- def closeSocket(socket)
725
- return false if socket.nil?
726
- begin
727
- if socket.respond_to? :sysclose
728
- #socket.io.shutdown(2)
729
- # puts "sysclose"
730
- socket.sysclose
731
- elsif socket.respond_to? :shutdown
732
- socket.shutdown(2)
733
- elsif socket.respond_to? :close
734
- socket.close
735
- end
736
- return true
737
- rescue => bang
738
- puts bang
739
- puts bang.backtrace if $DEBUG
740
- end
741
- false
742
- end
743
-
744
- def updateSessionSettings(settings={})
745
- [
746
- :ssl_client_cert,
747
- :ssl_client_key,
748
- :ssl_client_pass,
749
- :csrf_requests,
750
- :valid_sids,
751
- :sid_patterns,
752
- :logout_signatures,
753
- :logout_content_types,
754
- :update_valid_sids,
755
- :update_sids,
756
- :update_session,
757
- :update_contentlength,
758
- :login_chats,
759
- :follow_redirect
760
- ].each do |k|
761
- @session[k] = settings[k] if settings.has_key? k
762
- end
763
- end
764
-
765
-
766
-
767
- def updateCSRFToken(csrf_cache, request)
768
- # puts "=UPDATE CSRF TOKEN"
769
- # @session[:valid_csrf_tokens].to_yaml
770
- # puts request if request.site.nil?
771
- # puts "= = = = = = "
772
- @@csrf_lock.synchronize do
773
- # if @session[:valid_csrf_tokens].has_key?(request.site)
774
- # puts "* found token for site: #{request.site}"
775
-
776
- request.map!{ |line|
777
- res = line
778
- @session[:csrf_patterns].each do |pat|
779
- begin
780
- if line =~ /#{pat}/i then
781
- key = Regexp.quote($1.upcase)
782
- old_value = $2
783
- if csrf_cache.has_key?(key) then
784
- res = line.gsub!(/#{Regexp.quote(old_value)}/, csrf_cache[key])
785
- if res.nil? then
786
- res = line
787
- puts "!!!could not update token (#{key})"
788
- end
789
- end
790
- end
791
- rescue => bang
792
- puts bang
793
- puts bang.backtrace if $DEBUG
794
- # puts @session.to_yaml
795
- end
796
- end
797
- res
798
- }
799
- end
800
- # end
801
- end
802
-
803
- # this function updates specific patterns of a request, e.g. CSRF Tokens
804
- # Parameters:
805
- # request - the request which has to be updated
806
- # cache - the value store of already collected key-value-pairs
807
- # patterns - pattern expressions, similar to session-id-patterns, e.g. /name="(sessid)" value="([0-9a-zA-Z!-]*)"/
808
- def updateRequestPattern(request, cache, patterns)
809
-
810
- request.map!{ |line|
811
- res = line
812
- patterns.each do |pat|
813
- begin
814
- if line =~ /#{pat}/i then
815
- pattern_key = Regexp.quote($1.upcase)
816
- old_value = Regexp.quote($2)
817
- if cache.has_key?(sid_key) then
818
- if not old_value =~ /#{cache[sid_key]}/ then # sid value has changed and needs update
819
- # print "S"
820
- # puts "+ update sid #{sid_key}"
821
- # puts "-OLD: #{old_value}"
822
- # puts "-NEW: #{@session[:valid_sids][request.site][sid_key]}"
823
-
824
- # puts "---"
825
- # dummy = Regexp.quote(old_value)
826
- res = line.gsub!(/#{old_value}/, cache[sid_key])
827
- if not res then puts "!!!could not update sid (#{sid_key})"; end
828
- # puts "->#{line}"
829
- end
830
- end
831
- end
832
- rescue => bang
833
- puts bang
834
- puts bang.backtrace if $DEBUG
835
- # puts @session.to_yaml
836
- end
837
- end
838
- res
839
- }
840
- end
841
-
842
- def applySessionSettings(prefs)
843
- [ :update_valid_sids, :update_session, :update_contentlength, :valid_sids, :sid_patterns, :logout_signatures ].each do |v|
844
- @@settings[v] = prefs[v] if prefs[v]
845
- end
846
- end
847
-
848
-
849
- end
850
- end
10
+ # @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
851
839
  end