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,131 +1,125 @@
1
- #.
2
- # xml.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
- # @private
11
- module Watobo#:nodoc: all
12
- module HTTP
13
- class Xml
14
-
15
- module Mixin
16
- def xml
17
- @xml ||= Watobo::HTTP::Xml.new(self)
18
- end
19
- end
20
-
21
- def to_s
22
- s = @root.body.to_s
23
- end
24
-
25
- def set(parm)
26
- return false unless parm.location == :xml
27
- # puts "= set "
28
- # puts parm.to_yaml
29
-
30
- doc = Nokogiri::XML(@root.body.strip)
31
- namespaces = doc.collect_namespaces
32
- parent = doc.xpath("//#{parm.parent}", namespaces).first
33
- if parent.nil?
34
- puts "* could not find parent node #{parm.parent}"
35
- return false
36
- end
37
-
38
- parm_name = parm.namespace.nil? ? "" : parm.namespace
39
- parm_name << parm.name
40
- # find node
41
- node = parent.xpath("//#{parm_name}", namespaces).first
42
- if node.nil?
43
- puts "* node does not exist #{parm_name}"
44
- end
45
-
46
- child = node.children.first
47
- if child.nil?
48
- child = Nokogiri::XML::Text.new(parm.value, node)
49
- node.add_child child
50
- else
51
- child.content = parm.value
52
- end
53
-
54
- @root.set_body doc.to_s
55
-
56
- end
57
-
58
- def has_parm?(parm_name)
59
- false
60
- end
61
-
62
- def parameters(&block)
63
- params = []
64
-
65
- return params unless @root.is_xml?
66
- leaf_nodes do |n|
67
- p = { :name => n.name }
68
- val = n.children.size == 0 ? "" : n.children.first.to_s
69
-
70
- p[:value] = val
71
- parent_name = ""
72
- unless n.parent.namespace.nil?
73
- parent_name << n.parent.namespace.prefix
74
- parent_name << ":"
75
- end
76
- parent_name << n.parent.name
77
- p[:parent] = "#{parent_name}"
78
-
79
- unless n.namespace.nil?
80
- p[:namespace] = n.namespace.prefix
81
- end
82
- param = XmlParameter.new(p)
83
- yield param if block_given?
84
- params << param
85
- end
86
-
87
- return params
88
- end
89
-
90
- def initialize(root)
91
- @root = root
92
-
93
- end
94
-
95
- private
96
-
97
- def leaf_nodes(&block)
98
-
99
- nodes = []
100
- begin
101
- doc = Nokogiri::XML(@root.body.strip)
102
- prefix = doc.children.first.namespace.prefix
103
- # check if doc has a body element
104
- start = doc
105
- doc.traverse { |node|
106
- if node.name =~ /^body$/i
107
- start = node
108
- end
109
- }
110
- start.traverse { |node|
111
- if node.children.size == 0 and node.is_a? Nokogiri::XML::Element
112
- yield node if block_given?
113
- nodes << node
114
- end
115
- if node.children.size == 1
116
- if node.children.first.is_a? Nokogiri::XML::Text
117
- yield node if block_given?
118
- nodes << node
119
- end
120
- end
121
- }
122
- rescue => bang
123
- puts bang
124
- puts bang.backtrace if $DEBUG
125
- end
126
- nodes
127
- end
128
-
129
- end
130
- end
1
+ # @private
2
+ module Watobo#:nodoc: all
3
+ module HTTP
4
+ class Xml
5
+
6
+ module Mixin
7
+ def xml
8
+ @xml ||= Watobo::HTTP::Xml.new(self)
9
+ end
10
+ end
11
+
12
+ def to_s
13
+ s = @root.body.to_s
14
+ end
15
+
16
+ def set(parm)
17
+ return false unless parm.location == :xml
18
+ # puts "= set "
19
+ # puts parm.to_yaml
20
+
21
+ doc = Nokogiri::XML(@root.body.strip)
22
+ namespaces = doc.collect_namespaces
23
+ parent = doc.xpath("//#{parm.parent}", namespaces).first
24
+ if parent.nil?
25
+ puts "* could not find parent node #{parm.parent}"
26
+ return false
27
+ end
28
+
29
+ parm_name = parm.namespace.nil? ? "" : parm.namespace
30
+ parm_name << parm.name
31
+ # find node
32
+ node = parent.xpath("//#{parm_name}", namespaces).first
33
+ if node.nil?
34
+ puts "* node does not exist #{parm_name}"
35
+ end
36
+
37
+ child = node.children.first
38
+ if child.nil?
39
+ child = Nokogiri::XML::Text.new(parm.value, node)
40
+ node.add_child child
41
+ else
42
+ child.content = parm.value
43
+ end
44
+
45
+ @root.set_body doc.to_s
46
+
47
+ end
48
+
49
+ def has_parm?(parm_name)
50
+ false
51
+ end
52
+
53
+ def parameters(&block)
54
+ params = []
55
+
56
+ return params unless @root.is_xml?
57
+ leaf_nodes do |n|
58
+ p = { :name => n.name }
59
+ val = n.children.size == 0 ? "" : n.children.first.to_s
60
+
61
+ p[:value] = val
62
+ parent_name = ""
63
+ unless n.parent.namespace.nil?
64
+ parent_name << n.parent.namespace.prefix
65
+ parent_name << ":"
66
+ end
67
+ parent_name << n.parent.name
68
+ p[:parent] = "#{parent_name}"
69
+
70
+ unless n.namespace.nil?
71
+ p[:namespace] = n.namespace.prefix
72
+ end
73
+ param = XmlParameter.new(p)
74
+ yield param if block_given?
75
+ params << param
76
+ end
77
+
78
+ return params
79
+ end
80
+
81
+ def initialize(root)
82
+ @root = root
83
+
84
+ end
85
+
86
+ private
87
+
88
+ def leaf_nodes(&block)
89
+
90
+ nodes = []
91
+ return nodes unless @root.has_body?
92
+ begin
93
+ doc = Nokogiri::XML(@root.body.strip)
94
+ #ns = doc.children.first.namespace
95
+ #prefix = ns.nil? ? '' : ns.prefix
96
+
97
+ # check if doc has a body element
98
+ start = doc
99
+ doc.traverse { |node|
100
+ if node.name =~ /^body$/i
101
+ start = node
102
+ end
103
+ }
104
+ start.traverse { |node|
105
+ if node.children.size == 0 and node.is_a? Nokogiri::XML::Element
106
+ yield node if block_given?
107
+ nodes << node
108
+ end
109
+ if node.children.size == 1
110
+ if node.children.first.is_a? Nokogiri::XML::Text
111
+ yield node if block_given?
112
+ nodes << node
113
+ end
114
+ end
115
+ }
116
+ rescue => bang
117
+ puts bang
118
+ puts bang.backtrace if $DEBUG
119
+ end
120
+ nodes
121
+ end
122
+
123
+ end
124
+ end
131
125
  end
@@ -1,13 +1,4 @@
1
- #.
2
- # interceptor.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( proxy transparent ).each do |lib|
2
+ require "watobo/interceptor/#{lib}"
3
+ end
9
4
 
10
- %w( proxy transparent ).each do |lib|
11
- require "watobo/interceptor/#{lib}"
12
- end
13
-
@@ -1,760 +1,763 @@
1
- #.
2
- # proxy.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 Interceptor
13
- #
14
- class Proxy
15
-
16
- include Watobo::Constants
17
-
18
- attr :port
19
-
20
- attr_accessor :proxy_mode
21
-
22
- # attr_accessor :contentLength
23
- #attr_accessor :contentTypes
24
- attr_accessor :target
25
- #attr :www_auth
26
- attr_accessor :client_certificates
27
- def self.transparent?
28
- return true if ( Watobo::Conf::Interceptor.proxy_mode & Watobo::Interceptor::MODE_TRANSPARENT ) > 0
29
- return false
2
+ module Watobo #:nodoc: all
3
+ module Interceptor
4
+ #
5
+ class Proxy
6
+
7
+ include Watobo::Constants
8
+
9
+ attr :port
10
+
11
+ attr_accessor :proxy_mode
12
+
13
+ # attr_accessor :contentLength
14
+ #attr_accessor :contentTypes
15
+ attr_accessor :target
16
+ #attr :www_auth
17
+ attr_accessor :client_certificates
18
+
19
+ def self.transparent?
20
+ return true if (Watobo::Conf::Interceptor.proxy_mode & Watobo::Interceptor::MODE_TRANSPARENT) > 0
21
+ return false
30
22
  end
31
-
32
-
33
-
23
+
24
+
34
25
  def watobo_srv_get(file)
35
- srv_file = file.empty? ? File.join(@srv_path, 'index.html') : File.join(@srv_path, file)
36
- if File.exist? srv_file
37
- ct = case srv_file
38
- when /\.ico/
39
- "image/vnd.microsoft.icon"
40
- when /\.htm/
41
- 'text/html; charset=iso-8859-1'
42
- else
43
- 'text/plain'
44
- end
45
- headers = [ "HTTP/1.0 200 OK", "Server: Watobo-Interceptor", "Connection: close", "Content-Type: #{ct}"]
46
- content = File.open(srv_file,"rb").read
47
- content.gsub!('WATOBO_VERSION', Watobo::VERSION )
48
- content.gsub!('WATOBO_HOME', Watobo.working_directory )
49
- headers << "Content-Length: #{content.length}"
50
- r = headers.join("\r\n")
51
- r << "\r\n\r\n"
52
- r << content
53
- return r
54
- end
55
-
56
- headers = [ "HTTP/1.0 404 Not Found", "Server: Watobo-Interceptor", "Connection: close", "Content-Type: text/plain; charset=iso-8859-1"]
57
- content = "The requested file (#{file}) does not exist in the interceptor web folder."
26
+ srv_file = file.empty? ? File.join(@srv_path, 'index.html') : File.join(@srv_path, file)
27
+ if File.exist? srv_file
28
+ ct = case srv_file
29
+ when /\.ico/
30
+ "image/vnd.microsoft.icon"
31
+ when /\.htm/
32
+ 'text/html; charset=iso-8859-1'
33
+ else
34
+ 'text/plain'
35
+ end
36
+ headers = ["HTTP/1.0 200 OK", "Server: Watobo-Interceptor", "Connection: close", "Content-Type: #{ct}"]
37
+ content = File.open(srv_file, "rb").read
38
+ content.gsub!('WATOBO_VERSION', Watobo::VERSION)
39
+ content.gsub!('WATOBO_HOME', Watobo.working_directory)
58
40
  headers << "Content-Length: #{content.length}"
59
41
  r = headers.join("\r\n")
60
42
  r << "\r\n\r\n"
61
43
  r << content
62
44
  return r
63
-
45
+ end
46
+
47
+ headers = ["HTTP/1.0 404 Not Found", "Server: Watobo-Interceptor", "Connection: close", "Content-Type: text/plain; charset=iso-8859-1"]
48
+ content = "The requested file (#{file}) does not exist in the interceptor web folder."
49
+ headers << "Content-Length: #{content.length}"
50
+ r = headers.join("\r\n")
51
+ r << "\r\n\r\n"
52
+ r << content
53
+ return r
54
+
64
55
  end
65
-
56
+
66
57
  def cert_response
67
- crt_file = File.join(Watobo.working_directory, "CA", "cacert.pem")
68
- headers = [ "HTTP/1.0 200 OK", "Server: Watobo-Interceptor", "Connection: close", "Content-Type: application/x-pem-file"]
69
- content = File.read(crt_file)
70
- headers << "Content-Length: #{content.length}"
71
- r = headers.join("\r\n")
72
- r << "\r\n\r\n"
73
- r << content
74
- end
75
-
76
- def server
77
- @bind_addr
78
- end
79
-
80
- def subscribe(event, &callback)
81
- (@event_dispatcher_listeners[event] ||= []) << callback
82
- end
83
-
84
- def clearEvents(event)
85
- @event_dispatcher_listener[event].clear
86
- end
87
-
88
- def getResponseFilter()
89
- YAML.load(YAML.dump(@response_filter_settings))
90
- end
91
-
92
- def getRequestFilter()
93
- YAML.load(YAML.dump(@request_filter_settings))
94
- end
95
-
96
- def setResponseFilter(new_settings)
97
- @response_filter_settings.update new_settings unless new_settings.nil?
98
- end
99
-
100
- def setRequestFilter(new_settings)
101
- @request_filter_settings.update new_settings unless new_settings.nil?
102
- # puts @request_filter_settings.to_yaml
103
- end
104
-
105
- def clear_request_carvers
106
- @request_carvers.clear unless @request_carvers.nil?
107
-
108
- end
109
-
110
- def clear_response_carvers
111
- @response_carvers.clear unless @response_carvers.nil?
112
- end
113
-
114
- def addPreview(response)
115
- preview_id = Digest::MD5.hexdigest(response.join)
116
- @preview[preview_id] = response
117
- return preview_id
118
- end
119
-
120
- def stop()
121
- begin
122
- puts "[#{self.class}] stop"
123
- if @t_server.respond_to? :status
124
- puts @t_server.status
125
- Thread.kill @t_server
126
- @intercept_srv.close
127
- end
128
- rescue IOError => bang
129
- puts bang
130
- puts bang.backtrace if $DEBUG
131
- end
132
- end
133
-
134
- #
135
- # R U N
136
- #
137
-
138
- def self.start(settings = {})
139
- proxy = Proxy.new(settings)
140
- proxy.start
141
- proxy
142
- end
58
+ crt_file = File.join(Watobo.working_directory, "CA", "cacert.pem")
59
+ headers = ["HTTP/1.0 200 OK", "Server: Watobo-Interceptor", "Connection: close", "Content-Type: application/x-pem-file"]
60
+ content = File.read(crt_file)
61
+ headers << "Content-Length: #{content.length}"
62
+ r = headers.join("\r\n")
63
+ r << "\r\n\r\n"
64
+ r << content
65
+ end
66
+
67
+ def server
68
+ @bind_addr
69
+ end
70
+
71
+ def subscribe(event, &callback)
72
+ (@event_dispatcher_listeners[event] ||= []) << callback
73
+ end
74
+
75
+ def clearEvents(event)
76
+ @event_dispatcher_listener[event].clear
77
+ end
78
+
79
+ def getResponseFilter()
80
+ YAML.load(YAML.dump(@response_filter_settings))
81
+ end
82
+
83
+ def getRequestFilter()
84
+ YAML.load(YAML.dump(@request_filter_settings))
85
+ end
86
+
87
+ def setResponseFilter(new_settings)
88
+ @response_filter_settings.update new_settings unless new_settings.nil?
89
+ end
90
+
91
+ def setRequestFilter(new_settings)
92
+ @request_filter_settings.update new_settings unless new_settings.nil?
93
+ # puts @request_filter_settings.to_yaml
94
+ end
95
+
96
+ def clear_request_carvers
97
+ @request_carvers.clear unless @request_carvers.nil?
98
+
99
+ end
100
+
101
+ def clear_response_carvers
102
+ @response_carvers.clear unless @response_carvers.nil?
103
+ end
104
+
105
+ def addPreview(response)
106
+ preview_id = Digest::MD5.hexdigest(response.join)
107
+ @preview[preview_id] = response
108
+ return preview_id
109
+ end
110
+
111
+ def stop()
112
+ begin
113
+ puts "[#{self.class}] stop"
114
+ if @t_server.respond_to? :status
115
+ puts @t_server.status
116
+ Thread.kill @t_server
117
+ @intercept_srv.close
118
+ end
119
+ rescue IOError => bang
120
+ puts bang
121
+ puts bang.backtrace if $DEBUG
122
+ end
123
+ end
124
+
125
+ #
126
+ # R U N
127
+ #
128
+
129
+ def self.start(settings = {})
130
+ proxy = Proxy.new(settings)
131
+ proxy.start
132
+ proxy
133
+ end
143
134
 
144
135
  def start()
145
- @wait_queue = Queue.new
146
-
147
- if transparent?
148
- Watobo::Interceptor::Transparent.start
149
- end
150
-
151
- begin
152
- @intercept_srv = TCPServer.new(@bind_addr, @port)
153
- @intercept_srv.setsockopt( Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1 )
154
-
155
- rescue => bang
156
- puts "\n!!!Could not start InterceptProxy"
157
- puts bang
158
- return nil
159
- end
160
- puts "\n* Intercepor started on #{@bind_addr}:#{@port}"
161
- session_list = []
162
- puts "!!! TRANSPARENT MODE ENABLED !!!" if transparent?
163
-
164
- @t_server = Thread.new(@intercept_srv) { |server|
165
- while (new_session = server.accept)
166
- # new_session.sync = true
167
- new_sender = Watobo::Session.new(@target)
168
- Thread.new(new_sender, new_session) { |sender, session|
169
-
170
- c_sock = Watobo::HTTPSocket::ClientSocket.connect(session)
171
-
172
- #puts "ClientSocket: #{c_sock}"
173
- Thread.exit if c_sock.nil?
174
-
175
- #
176
- # loop for reusing client connections
177
-
178
- max_loop = 0
179
- loop do
180
- flags = []
181
- begin
182
-
183
- # puts "#{c_sock} - read request"
184
- request = c_sock.request
185
-
186
- #if request.is_multipart?
187
- # puts request
188
- # puts request.body.to_s.length
189
- # puts request.body.to_s.unpack("H*")[0]
190
- #end
191
-
192
- if request.nil? or request.empty? then
193
- print "c/"
194
- c_sock.close
195
- Thread.exit
196
- end
197
-
198
- url = ( request.url.to_s.length > 65 ) ? request.url.to_s.slice(0,65) + "..." : request.url.to_s
199
- puts "\n[I] #{url}"
200
-
201
- rescue => bang
202
- puts "!!! Error reading client request "
203
- puts bang
204
- puts bang.backtrace
205
- # puts request.class
206
- # puts request
207
- c_sock.close
208
- Thread.exit
209
- #break
210
- end
211
-
212
- if request.host =~ /safebrowsing.*google\.com/
213
- c_sock.close
214
- Thread.exit
215
- end
216
-
217
- # check if preview is requested
218
- if request.host =='watobo.localhost' or request.first =~ /WATOBOPreview/ then
219
- if request.first =~ /WATOBOPreview=([0-9a-zA-Z]*)/ then
220
- hashid = $1
221
- response = @preview[hashid]
222
-
223
- if response then
224
- c_sock.write response.join
225
- c_sock.close
226
- end
227
- end
228
- #next
229
- Thread.exit
230
- end
231
-
232
- # check for watobo info page
233
- if request.host =~ /^watobo$/
234
- if request.path =~ /watobo\.pem/
235
- response = cert_response
236
- else
237
- response = watobo_srv_get(request.path)
238
- end
239
-
240
- c_sock.write response
241
- c_sock.close
242
- Thread.exit
243
- end
244
-
245
- request_intercepted = false
246
- # no preview, check if interception request is turned on
247
- if Watobo::Interceptor.rewrite_requests? then
248
- Interceptor::RequestCarver.shape(request, flags)
249
- puts "FLAGS >>"
250
- puts flags
251
- end
252
-
253
- if @target and Watobo::Interceptor.intercept_requests? then
254
- if matchRequestFilter(request)
255
- @awaiting_requests += 1
256
- request_intercepted = true
257
-
258
- if @target.respond_to? :addRequest
259
- Watobo.print_debug "send request to target"
260
- @target.addRequest(request, Thread.current)
261
- Thread.stop
262
- else
263
- p "! no target for editing request"
264
- end
265
- @awaiting_requests -= 1
266
- end
267
- end
268
-
269
- begin
270
- s_sock, req, resp = sender.sendHTTPRequest(request, :update_sids => true,
271
- :update_session => false,
272
- :update_contentlength => true,
273
- :www_auth => @www_auth
274
- # :client_certificates => @client_certificates
275
- )
276
- if s_sock.nil? then
277
- puts "s_sock is nil! bye, bye, ..."
278
- puts request if $DEBUG
279
- c_sock.write resp.join unless resp.nil?
280
- c_sock.close
281
- Thread.exit
282
- end
283
-
284
- rescue => bang
285
- puts bang
286
- puts bang.backtrace if $DEBUG
287
- c_sock.close
288
- Thread.exit
289
- end
290
-
291
- # check if response should be passed through
292
- #Thread.current.exit if isPassThrough?(req, resp, s_sock, c_sock)
293
- if isPassThrough?(req, resp, s_sock, c_sock)
294
- #puts "[Interceptor] PassThrough >> #{req.url}"
295
- Watobo::HTTPSocket.close s_sock
296
- c_sock.close
297
- Thread.exit
298
- end
299
-
300
- begin
301
- missing_credentials = false
302
- rs = resp.status
303
- auth_type = AUTH_TYPE_NONE
304
- if rs =~ /^(401|407)/ then
305
-
306
- missing_credentials = true
307
-
308
- resp.each do |rl|
309
- if rl =~ /^(Proxy|WWW)-Authenticate: Basic/i
310
- auth_type = AUTH_TYPE_BASIC
311
- break
312
- elsif rl =~ /^(Proxy|WWW)-Authenticate: NTLM/i
313
- auth_type = AUTH_TYPE_NTLM
314
- break
315
- end
316
- end
317
- # when auth type not basic assume it's ntlm -> ntlm credentials must be set in watobo
318
- unless auth_type == AUTH_TYPE_NONE
319
- if auth_type == AUTH_TYPE_NTLM
320
- if rs =~ /^401/ then
321
- resp.push "WATOBO: Server requires (NTLM) authorization, please set WWW_Auth Credentials!"
322
- resp.shift
323
- resp.unshift "HTTP/1.1 200 OK\r\n"
324
- else
325
- resp.push "WATOBO: Proxy requires (NTLM) authorization, please set Proxy Credentials!"
326
- resp.shift
327
- resp.unshift "HTTP/1.1 200 OK\r\n"
328
- end
329
- end
330
- end
331
- end
332
-
333
- # don't try to read body if request method is HEAD
334
- unless auth_type == AUTH_TYPE_UNKNOWN or req.method =~ /^head/i
335
- sender.readHTTPBody(s_sock, resp, req, :update_sids => true)
336
- Watobo::HTTPSocket.close s_sock
136
+ @wait_queue = Queue.new
137
+
138
+ if transparent?
139
+ Watobo::Interceptor::Transparent.start
140
+ end
141
+
142
+ begin
143
+ @intercept_srv = TCPServer.new(@bind_addr, @port)
144
+ @intercept_srv.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
145
+
146
+ rescue => bang
147
+ puts "\n!!!Could not start InterceptProxy"
148
+ puts bang
149
+ return nil
150
+ end
151
+ puts "\n* Intercepor started on #{@bind_addr}:#{@port}"
152
+ session_list = []
153
+ puts "!!! TRANSPARENT MODE ENABLED !!!" if transparent?
154
+
155
+ @t_server = Thread.new(@intercept_srv) { |server|
156
+ while (new_session = server.accept)
157
+ # new_session.sync = true
158
+ new_sender = Watobo::Session.new(@target)
159
+ Thread.new(new_sender, new_session) { |sender, session|
160
+ #puts "* got new request from client"
161
+ c_sock = Watobo::HTTPSocket::ClientSocket.connect(session)
162
+
163
+ #puts "ClientSocket: #{c_sock}"
164
+ Thread.exit if c_sock.nil?
165
+
166
+ #
167
+ # loop for reusing client connections
168
+
169
+ max_loop = 0
170
+ loop do
171
+ flags = []
172
+ begin
173
+
174
+ # puts "#{c_sock} - read request"
175
+ request = c_sock.request
176
+
177
+ #if request.is_multipart?
178
+ # puts request
179
+ # puts request.body.to_s.length
180
+ # puts request.body.to_s.unpack("H*")[0]
181
+ #end
182
+
183
+ if request.nil? or request.empty? then
184
+ print "c/"
185
+ c_sock.close
186
+ Thread.exit
187
+ end
188
+
189
+ url = (request.url.to_s.length > 65) ? request.url.to_s.slice(0, 65) + "..." : request.url.to_s
190
+ puts "\n[I] #{url}"
191
+
192
+ rescue => bang
193
+ puts "!!! Error reading client request "
194
+ puts bang
195
+ puts bang.backtrace
196
+ # puts request.class
197
+ # puts request
198
+ c_sock.close
199
+ Thread.exit
200
+ #break
201
+ end
202
+
203
+ #if request.host =~ /safebrowsing.*google\.com/
204
+ # c_sock.close
205
+ # Thread.exit
206
+ #end
207
+
208
+ # check if preview is requested
209
+ if request.host =='watobo.localhost' or request.first =~ /WATOBOPreview/ then
210
+ if request.first =~ /WATOBOPreview=([0-9a-zA-Z]*)/ then
211
+ hashid = $1
212
+ response = @preview[hashid]
213
+
214
+ if response then
215
+ c_sock.write response.join
216
+ c_sock.close
217
+ end
218
+ end
219
+ #next
220
+ Thread.exit
221
+ end
222
+
223
+ # check for watobo info page
224
+ if request.host =~ /^watobo$/
225
+ if request.path =~ /watobo\.pem/
226
+ response = cert_response
227
+ else
228
+ response = watobo_srv_get(request.path)
229
+ end
230
+
231
+ c_sock.write response
232
+ c_sock.close
233
+ Thread.exit
234
+ end
235
+
236
+ request_intercepted = false
237
+ # no preview, check if interception request is turned on
238
+ if Watobo::Interceptor.rewrite_requests? then
239
+ Interceptor::RequestCarver.shape(request, flags)
240
+ puts "FLAGS >>"
241
+ puts flags
242
+ end
243
+
244
+ if @target and Watobo::Interceptor.intercept_requests? then
245
+ if matchRequestFilter(request)
246
+ @awaiting_requests += 1
247
+ request_intercepted = true
248
+
249
+ if @target.respond_to? :addRequest
250
+ Watobo.print_debug "send request to target"
251
+ @target.addRequest(request, Thread.current)
252
+ Thread.stop
253
+ else
254
+ p "! no target for editing request"
255
+ end
256
+ @awaiting_requests -= 1
257
+ end
258
+ end
259
+
260
+ begin
261
+ s_sock, req, resp = sender.sendHTTPRequest(request, :update_sids => true,
262
+ :update_session => false,
263
+ :update_contentlength => true,
264
+ :www_auth => @www_auth
265
+ # :client_certificates => @client_certificates
266
+ )
267
+ if s_sock.nil? then
268
+ puts "s_sock is nil! bye, bye, ..."
269
+ puts request if $DEBUG
270
+ c_sock.write resp.join unless resp.nil?
271
+ c_sock.close
272
+ Thread.exit
273
+ end
274
+
275
+ rescue => bang
276
+ puts bang
277
+ puts bang.backtrace if $DEBUG
278
+ c_sock.close
279
+ Thread.exit
280
+ end
281
+
282
+ # check if response should be passed through
283
+ #Thread.current.exit if isPassThrough?(req, resp, s_sock, c_sock)
284
+ if isPassThrough?(req, resp, s_sock, c_sock)
285
+ #puts "[Interceptor] PassThrough >> #{req.url}"
286
+ Watobo::HTTPSocket.close s_sock
287
+ c_sock.close
288
+ Thread.exit
289
+ end
290
+
291
+ begin
292
+ missing_credentials = false
293
+ rs = resp.status
294
+ auth_type = AUTH_TYPE_NONE
295
+ if rs =~ /^(401|407)/ then
296
+
297
+ missing_credentials = true
298
+
299
+ resp.each do |rl|
300
+ if rl =~ /^(Proxy|WWW)-Authenticate: Basic/i
301
+ auth_type = AUTH_TYPE_BASIC
302
+ break
303
+ elsif rl =~ /^(Proxy|WWW)-Authenticate: NTLM/i
304
+ auth_type = AUTH_TYPE_NTLM
305
+ break
306
+ end
307
+ end
308
+ # when auth type not basic assume it's ntlm -> ntlm credentials must be set in watobo
309
+ unless auth_type == AUTH_TYPE_NONE
310
+ if auth_type == AUTH_TYPE_NTLM
311
+ if rs =~ /^401/ then
312
+ resp.push "WATOBO: Server requires (NTLM) authorization, please set WWW_Auth Credentials!"
313
+ resp.shift
314
+ resp.unshift "HTTP/1.1 200 OK\r\n"
315
+ else
316
+ resp.push "WATOBO: Proxy requires (NTLM) authorization, please set Proxy Credentials!"
317
+ resp.shift
318
+ resp.unshift "HTTP/1.1 200 OK\r\n"
319
+ end
320
+ end
321
+ end
322
+ end
323
+
324
+ # don't try to read body if request method is HEAD
325
+ unless auth_type == AUTH_TYPE_UNKNOWN or req.method =~ /^head/i
326
+ sender.readHTTPBody(s_sock, resp, req, :update_sids => true)
327
+ Watobo::HTTPSocket.close s_sock
328
+ end
329
+
330
+ rescue => bang
331
+ puts "!!! could not send request !!!"
332
+ puts bang
333
+ puts bang.backtrace if $DEBUG
334
+ # puts "* Error sending request"
335
+ end
336
+
337
+ begin
338
+ # Watobo::Response.create resp
339
+ #resp = Watobo::Response.new resp
340
+ # puts "* unchunk response ..."
341
+ resp.unchunk!
342
+ # puts "* unzip response ..."
343
+ resp.unzip!
344
+
345
+ if Watobo::Interceptor.rewrite_responses? then
346
+ Interceptor::ResponseCarver.shape(resp, flags)
347
+ end
348
+
349
+ if @target and Watobo::Interceptor.intercept_responses? then
350
+ if matchResponseFilter(resp)
351
+ # if resp.content_type =~ /text/ or resp.content_type =~ /application\/javascript/ then
352
+ if @target.respond_to? :modifyResponse
353
+ @target.modifyResponse(resp, Thread.current)
354
+ Thread.stop
355
+ else
356
+ p "! no target for editing response"
357
+ end
358
+ end
359
+ end
360
+
361
+ # puts ">> SEND TO CLIENT"
362
+ # puts ">>C<< - Close: #{request.connection_close?}"
363
+ # request.headers("Connection"){ |h| puts h }
364
+
365
+ if missing_credentials
366
+ resp.set_header("Connection", "close")
367
+ elsif request.connection_close? or resp.content_length < 0 or max_loop > 4
368
+ # resp.set_header("Proxy-Connection","close")
369
+ resp.set_header("Connection", "close")
370
+ else
371
+ resp.set_header("Connection", "keep-alive")
372
+ resp.set_header("Keep-Alive", "max=4, timeout=120")
373
+ end
374
+
375
+ resp_data = resp.join
376
+ c_sock.write resp_data
377
+
378
+ chat = Chat.new(request.copy, resp.copy, :source => CHAT_SOURCE_INTERCEPT)
379
+ Watobo::Chats.add chat
380
+
381
+ rescue Errno::ECONNRESET
382
+ print "x"
383
+ # puts "!!! ERROR (Reset): reading body"
384
+ # puts "* last data seen on socket: #{buf}"
385
+ #return
386
+ c_sock.close
387
+ Thread.exit
388
+ rescue Errno::ECONNABORTED
389
+ print "x"
390
+ #return
391
+ c_sock.close
392
+ Thread.exit
393
+ rescue => bang
394
+ puts "!!! Error (???) in Client Communication:"
395
+ puts bang
396
+ puts bang.class
397
+ puts bang.backtrace #if $DEBUG
398
+ #return
399
+ c_sock.close
400
+ Thread.exit
401
+ end
402
+
403
+
404
+ # TODO: place check into ClientSocket, because headers must be checked and changed too
405
+ # e.g. if c_sock.open?
406
+ if missing_credentials or request.connection_close? or resp.content_length < 0 or max_loop > 4
407
+ c_sock.close
408
+ Thread.exit
409
+ end
410
+
411
+ max_loop += 1
412
+
337
413
  end
338
-
339
- rescue => bang
340
- puts "!!! could not send request !!!"
341
- puts bang
342
- puts bang.backtrace if $DEBUG
343
- # puts "* Error sending request"
344
- end
345
-
346
- begin
347
- # Watobo::Response.create resp
348
- #resp = Watobo::Response.new resp
349
- # puts "* unchunk response ..."
350
- resp.unchunk!
351
- # puts "* unzip response ..."
352
- resp.unzip!
353
-
354
- if Watobo::Interceptor.rewrite_responses? then
355
- Interceptor::ResponseCarver.shape(resp, flags)
356
- end
357
-
358
- if @target and Watobo::Interceptor.intercept_responses? then
359
- if matchResponseFilter(resp)
360
- # if resp.content_type =~ /text/ or resp.content_type =~ /application\/javascript/ then
361
- if @target.respond_to? :modifyResponse
362
- @target.modifyResponse(resp, Thread.current)
363
- Thread.stop
364
- else
365
- p "! no target for editing response"
366
- end
367
- end
368
- end
369
-
370
- # puts ">> SEND TO CLIENT"
371
- # puts ">>C<< - Close: #{request.connection_close?}"
372
- # request.headers("Connection"){ |h| puts h }
373
-
374
- if missing_credentials
375
- resp.set_header("Connection", "close")
376
- elsif request.connection_close? or resp.content_length < 0 or max_loop > 4
377
- # resp.set_header("Proxy-Connection","close")
378
- resp.set_header("Connection","close")
379
- else
380
- resp.set_header("Connection","keep-alive")
381
- resp.set_header("Keep-Alive", "max=4, timeout=120")
382
- end
383
-
384
- resp_data = resp.join
385
- c_sock.write resp_data
386
-
387
- # puts "---"
388
- # puts resp_data.unpack("H*")[0]
389
- # puts "==="
390
-
391
- rescue Errno::ECONNRESET
392
- print "x"
393
- # puts "!!! ERROR (Reset): reading body"
394
- # puts "* last data seen on socket: #{buf}"
395
- #return
396
- rescue Errno::ECONNABORTED
397
- print "x"
398
- #return
399
- rescue => bang
400
- puts "!!! Error (???) in Client Communication:"
401
- puts bang
402
- puts bang.class
403
- puts bang.backtrace #if $DEBUG
404
- #return
405
- end
406
-
407
- chat = Chat.new(request.copy, resp.copy, :source => CHAT_SOURCE_INTERCEPT)
408
-
409
- Watobo::Chats.add chat
410
-
411
- # TODO: place check into ClientSocket, because headers must be checked and changed too
412
- # e.g. if c_sock.open?
413
- if missing_credentials or request.connection_close? or resp.content_length < 0 or max_loop > 4
414
- c_sock.close
415
- Thread.exit
416
- end
417
- print "o"
418
- max_loop += 1
419
-
420
- end
421
- }
422
-
423
- end
424
- }
425
- end
426
-
427
- def refresh_www_auth
428
- @www_auth = Watobo::Conf::Scanner.www_auth
429
- end
430
-
431
- def initialize(settings=nil)
432
- @event_dispatcher_listeners = Hash.new
433
- begin
434
-
435
- puts
436
- puts "=== Initialize Interceptor/Proxy ==="
437
-
438
- #Watobo::Interceptor.proxy_mode = INTERCEPT_NONE
439
-
414
+ }
415
+
416
+ end
417
+ }
418
+ end
419
+
420
+ def refresh_www_auth
421
+ @www_auth = Watobo::Conf::Scanner.www_auth
422
+ end
423
+
424
+ def initialize(settings=nil)
425
+ @event_dispatcher_listeners = Hash.new
426
+ @pass_through_hosts = ['safebrowsing.*google\.com', 'download.cdn.mozilla.net', 'shavar.services.mozilla.com']
427
+ begin
428
+
429
+ puts
430
+ puts "=== Initialize Interceptor/Proxy ==="
431
+
432
+ #Watobo::Interceptor.proxy_mode = INTERCEPT_NONE
433
+
440
434
  init_instance_vars
441
-
442
- @srv_path = File.join(File.dirname(__FILE__),'html')
443
-
444
- @awaiting_requests = 0
445
- @awaiting_responses = 0
446
-
447
- @request_filter_settings = {
448
- :site_in_scope => false,
449
- :method_filter => '(get|post|put)',
450
- :negate_method_filter => false,
451
- :negate_url_filter => false,
452
- :url_filter => '',
453
- :file_type_filter => '(jpg|gif|png|jpeg|bmp)',
454
- :negate_file_type_filter => true,
455
-
456
- :parms_filter => '',
457
- :negate_parms_filter => false
458
- #:regex_location => 0, # TODO: HEADER_LOCATION, BODY_LOCATION, ALL
459
-
460
- }
461
-
462
- @response_filter_settings = {
463
- :content_type_filter => '(text|script)',
464
- :negate_content_type_filter => false,
465
- :response_code_filter => '2\d{2}',
466
- :negate_response_code_filter => false,
467
- :request_intercepted => false,
468
- :content_printable => true,
469
- :enable_printable_check => false
470
- }
471
-
472
- @preview = Hash.new
473
- @preview['ProxyTest'] = ["HTTP/1.0 200 OK\r\nServer: Watobo-Interceptor\r\nConnection: close\r\nContent-Type: text/html; charset=iso-8859-1\r\n\r\n<html><body>PROXY_OK</body></html>"]
474
-
475
- @dh_key = Watobo::CA.dh_key
476
-
477
- rescue => bang
478
- puts "!!!could not read certificate files:"
479
- puts bang
480
- puts bang.backtrace if $DEBUG
481
- end
482
-
483
- end
484
-
485
- private
486
-
487
- def init_instance_vars
488
- @www_auth = Watobo::Conf::Scanner.www_auth
489
- @fake_certs = {}
490
- @client_certificates = {}
491
- @target = nil
492
- # @sender = Watobo::Session.new(@target)
493
-
494
- @bind_addr = Watobo::Conf::Interceptor.bind_addr
495
- # puts "> Server: #{@bind_addr}"
496
- @port = Watobo::Conf::Interceptor.port
497
- # puts "> Port: #{@port}"
498
- @proxy_mode = Watobo::Conf::Interceptor.proxy_mode
499
-
500
- pt = Watobo::Conf::Interceptor.pass_through
501
- @contentLength = pt[:content_length]
502
- # puts "> PT-ContentLength: #{@contentLength}"
503
- @contentTypes = pt[:content_types]
504
- # puts "> PT-ContentTypes: #{@contentTypes}"
505
- end
506
-
507
- #
508
- #
509
- # matchContentType(content_type)
510
- #
511
- #
512
- def matchContentType?(content_type)
513
- @contentTypes.each do |p|
514
- return true if content_type =~ /#{p}/
515
- end
516
- return false
517
- end
518
-
519
- #
520
- #
521
- # matchRequestFilter(request)
522
- #
523
- #
524
- def matchRequestFilter(request)
525
- match_url = true
526
- # puts @request_filter_settings.to_yaml
527
- url_filter = @request_filter_settings[:url_filter]
528
- if url_filter != ''
529
- match_url = false
530
- if request.url.to_s =~ /#{url_filter}/i
531
- match_url = true
532
- end
533
- if @request_filter_settings[:negate_url_filter] == true
534
- match_url = ( match_url == true ) ? false : true
535
- end
536
- end
537
-
538
- return false if match_url == false
539
-
540
- match_method = true
541
- method_filter = @request_filter_settings[:method_filter]
542
- if method_filter != ''
543
- match_method = false
544
- if request.method =~ /#{method_filter}/i
545
- match_method = true
546
- end
547
-
548
- if @request_filter_settings[:negate_method_filter] == true
549
- match_method = ( match_method == true ) ? false : true
550
- end
551
- end
552
-
553
- return false if match_method == false
554
-
555
- match_ftype = true
556
- ftype_filter = @request_filter_settings[:file_type_filter]
557
- if ftype_filter != ''
558
- match_ftype = false
559
- if request.doctype != '' and request.doctype =~ /#{ftype_filter}/i
560
- match_ftype = true
561
- end
562
- if @request_filter_settings[:negate_file_type_filter] == true
563
- match_ftype = ( match_ftype == true ) ? false : true
564
- end
565
- end
566
- return false if match_ftype == false
567
-
568
- match_parms = true
569
- parms_filter = @request_filter_settings[:parms_filter]
570
- if parms_filter != ''
571
- # puts "!PARMS FILTER: #{parms_filter}"
572
- match_parms = false
573
- puts request.parms
574
- match_parms = request.parms.find {|x| x =~ /#{parms_filter}/ }
575
- match_parms = ( match_parms.nil? ) ? false : true
576
- if @request_filter_settings[:negate_parms_filter] == true
577
- match_parms = ( match_parms == true ) ? false : true
578
- end
579
- end
580
- return false if match_parms == false
581
-
582
- true
583
- end
584
-
585
- #
586
- #
587
- # matchResponseFilter(response)
588
- #
589
- #
590
-
591
- def matchResponseFilter(response)
592
- match_ctype = true
593
- ct_filter = @response_filter_settings[:content_type_filter]
594
- unless ct_filter.empty?
595
- match_ctype = false
596
- negate = @response_filter_settings[:negate_content_type_filter]
597
- if response.content_type =~ /#{ct_filter}/
598
- match_ctype = true
599
-
600
- end
601
- if negate == true
602
- match_ctype = ( match_ctype == true ) ? false : true
603
- end
604
- end
605
- return false if match_ctype == false
606
- #puts "* pass ctype filter"
607
- match_rcode = true
608
- rcode_filter = @response_filter_settings[:response_code_filter]
609
- negate = @response_filter_settings[:negate_response_code_filter]
610
- unless rcode_filter.empty?
611
- match_rcode = false
612
- puts rcode_filter
613
- puts response.responseCode
614
- if response.responseCode =~ /#{rcode_filter}/
615
- match_rcode = true
616
- end
617
- if negate == true
618
- match_rcode = ( match_rcode == true ) ? false : true
619
- end
620
- end
621
- return false if match_rcode == false
622
- #puts "* pass rcode filter"
623
- true
624
- end
625
-
626
- #
627
- #
628
- # pass_through(server, client, maxbytes)
629
- #
630
- #
631
- def pass_through(server, client, maxbytes = 0)
632
-
633
- bytes_read = 0
634
- while 1
635
- begin
636
- #timeout(2) do
637
- buf = nil
638
- buf = server.readpartial(2048)
639
- #end
640
- rescue EOFError
641
- #client.write buf if buf
642
- #print "~]"
643
- # msg = "\n[pass_through] EOF - "
644
- # msg += buf.nil? ? "nil" : buf.size
645
- # puts msg
646
- return if buf.nil?
647
- rescue Errno::ECONNRESET
648
- # puts "!!! ERROR (Reset): reading body"
649
- # puts "* last data seen on socket: #{buf}"
650
- # msg = "!R - "
651
- # msg += buf.nil? ? "nil" : buf.size
652
- # msg << " !\n"
653
- # puts msg
654
-
655
- return if buf.nil?
656
- rescue Timeout::Error
657
- #puts "!!! ERROR (Timeout): reading body"
658
- #puts "* last data seen on socket:"
659
- #client.write buf if buf
660
- print "T"
661
- return
662
- rescue => bang
663
- puts "!!! could not read body !!!"
664
- puts bang
665
- puts bang.class
666
- puts bang.backtrace if $DEBUG
667
- # puts "* last data seen on socket:"
668
- # print "~]"
669
- #client.write buf if buf
670
- return
671
- end
672
-
673
- begin
674
- return if buf.nil?
675
- # print "~"
676
- client.write buf
677
- bytes_read += buf.length
678
- # puts "#{server} #{bytes_read} of #{maxbytes}"
679
- if maxbytes > 0 and bytes_read >= maxbytes
680
- #print "~]"
681
- return
682
- end
683
- rescue Errno::ECONNRESET
684
- #print "~x]"
685
- # puts "!!! ERROR (Reset): reading body"
686
- # puts "* last data seen on socket: #{buf}"
687
- return
688
- rescue Errno::ECONNABORTED
689
- # print "~x]"
690
- return
691
- rescue Errno::EPIPE
692
- # print "~x]"
693
- return
694
- rescue => bang
695
- puts "!!! client communication broken !!!"
696
- puts bang
697
- puts bang.class
698
- puts bang.backtrace if $DEBUG
699
- return
700
- end
701
- end
702
- end
703
-
704
- def transparent?
705
- ( @proxy_mode & Watobo::Interceptor::MODE_TRANSPARENT ) > 0
706
- end
707
-
708
- def isPassThrough?(request, response, s_sock, c_sock)
435
+
436
+ @srv_path = File.join(File.dirname(__FILE__), 'html')
437
+
438
+ @awaiting_requests = 0
439
+ @awaiting_responses = 0
440
+
441
+ @request_filter_settings = {
442
+ :site_in_scope => false,
443
+ :method_filter => '(get|post|put)',
444
+ :negate_method_filter => false,
445
+ :negate_url_filter => false,
446
+ :url_filter => '',
447
+ :file_type_filter => '(jpg|gif|png|jpeg|bmp)',
448
+ :negate_file_type_filter => true,
449
+
450
+ :parms_filter => '',
451
+ :negate_parms_filter => false
452
+ #:regex_location => 0, # TODO: HEADER_LOCATION, BODY_LOCATION, ALL
453
+
454
+ }
455
+
456
+ @response_filter_settings = {
457
+ :content_type_filter => '(text|script)',
458
+ :negate_content_type_filter => false,
459
+ :response_code_filter => '2\d{2}',
460
+ :negate_response_code_filter => false,
461
+ :request_intercepted => false,
462
+ :content_printable => true,
463
+ :enable_printable_check => false
464
+ }
465
+
466
+ @preview = Hash.new
467
+ @preview['ProxyTest'] = ["HTTP/1.0 200 OK\r\nServer: Watobo-Interceptor\r\nConnection: close\r\nContent-Type: text/html; charset=iso-8859-1\r\n\r\n<html><body>PROXY_OK</body></html>"]
468
+
469
+ @dh_key = Watobo::CA.dh_key
470
+
471
+ rescue => bang
472
+ puts "!!!could not read certificate files:"
473
+ puts bang
474
+ puts bang.backtrace if $DEBUG
475
+ end
476
+
477
+ end
478
+
479
+ private
480
+
481
+ def init_instance_vars
482
+ @www_auth = Watobo::Conf::Scanner.www_auth
483
+ @fake_certs = {}
484
+ @client_certificates = {}
485
+ @target = nil
486
+ # @sender = Watobo::Session.new(@target)
487
+
488
+ @bind_addr = Watobo::Conf::Interceptor.bind_addr
489
+ # puts "> Server: #{@bind_addr}"
490
+ @port = Watobo::Conf::Interceptor.port
491
+ # puts "> Port: #{@port}"
492
+ @proxy_mode = Watobo::Conf::Interceptor.proxy_mode
493
+
494
+ pt = Watobo::Conf::Interceptor.pass_through
495
+ @contentLength = pt[:content_length]
496
+ # puts "> PT-ContentLength: #{@contentLength}"
497
+ @contentTypes = pt[:content_types]
498
+ # puts "> PT-ContentTypes: #{@contentTypes}"
499
+ end
500
+
501
+ #
502
+ #
503
+ # matchContentType(content_type)
504
+ #
505
+ #
506
+ def matchContentType?(content_type)
507
+ @contentTypes.each do |p|
508
+ return true if content_type =~ /#{p}/
509
+ end
510
+ return false
511
+ end
512
+
513
+ #
514
+ #
515
+ # matchRequestFilter(request)
516
+ #
517
+ #
518
+ def matchRequestFilter(request)
519
+ match_url = true
520
+ # puts @request_filter_settings.to_yaml
521
+ url_filter = @request_filter_settings[:url_filter]
522
+ if url_filter != ''
523
+ match_url = false
524
+ if request.url.to_s =~ /#{url_filter}/i
525
+ match_url = true
526
+ end
527
+ if @request_filter_settings[:negate_url_filter] == true
528
+ match_url = (match_url == true) ? false : true
529
+ end
530
+ end
531
+
532
+ return false if match_url == false
533
+
534
+ match_method = true
535
+ method_filter = @request_filter_settings[:method_filter]
536
+ if method_filter != ''
537
+ match_method = false
538
+ if request.method =~ /#{method_filter}/i
539
+ match_method = true
540
+ end
541
+
542
+ if @request_filter_settings[:negate_method_filter] == true
543
+ match_method = (match_method == true) ? false : true
544
+ end
545
+ end
546
+
547
+ return false if match_method == false
548
+
549
+ match_ftype = true
550
+ ftype_filter = @request_filter_settings[:file_type_filter]
551
+ if ftype_filter != ''
552
+ match_ftype = false
553
+ if request.doctype != '' and request.doctype =~ /#{ftype_filter}/i
554
+ match_ftype = true
555
+ end
556
+ if @request_filter_settings[:negate_file_type_filter] == true
557
+ match_ftype = (match_ftype == true) ? false : true
558
+ end
559
+ end
560
+ return false if match_ftype == false
561
+
562
+ match_parms = true
563
+ parms_filter = @request_filter_settings[:parms_filter]
564
+ if parms_filter != ''
565
+ # puts "!PARMS FILTER: #{parms_filter}"
566
+ match_parms = false
567
+ puts request.parms
568
+ match_parms = request.parms.find { |x| x =~ /#{parms_filter}/ }
569
+ match_parms = (match_parms.nil?) ? false : true
570
+ if @request_filter_settings[:negate_parms_filter] == true
571
+ match_parms = (match_parms == true) ? false : true
572
+ end
573
+ end
574
+ return false if match_parms == false
575
+
576
+ true
577
+ end
578
+
579
+ #
580
+ #
581
+ # matchResponseFilter(response)
582
+ #
583
+ #
584
+
585
+ def matchResponseFilter(response)
586
+ match_ctype = true
587
+ ct_filter = @response_filter_settings[:content_type_filter]
588
+ unless ct_filter.empty?
589
+ match_ctype = false
590
+ negate = @response_filter_settings[:negate_content_type_filter]
591
+ if response.content_type =~ /#{ct_filter}/
592
+ match_ctype = true
593
+
594
+ end
595
+ if negate == true
596
+ match_ctype = (match_ctype == true) ? false : true
597
+ end
598
+ end
599
+ return false if match_ctype == false
600
+ #puts "* pass ctype filter"
601
+ match_rcode = true
602
+ rcode_filter = @response_filter_settings[:response_code_filter]
603
+ negate = @response_filter_settings[:negate_response_code_filter]
604
+ unless rcode_filter.empty?
605
+ match_rcode = false
606
+ puts rcode_filter
607
+ puts response.responseCode
608
+ if response.responseCode =~ /#{rcode_filter}/
609
+ match_rcode = true
610
+ end
611
+ if negate == true
612
+ match_rcode = (match_rcode == true) ? false : true
613
+ end
614
+ end
615
+ return false if match_rcode == false
616
+ #puts "* pass rcode filter"
617
+ true
618
+ end
619
+
620
+ #
621
+ #
622
+ # pass_through(server, client, maxbytes)
623
+ #
624
+ #
625
+ def pass_through(server, client, maxbytes = 0)
626
+
627
+ bytes_read = 0
628
+ while 1
629
+ begin
630
+ #timeout(2) do
631
+ buf = nil
632
+ buf = server.readpartial(2048)
633
+ #end
634
+ rescue EOFError
635
+ #client.write buf if buf
636
+ #print "~]"
637
+ # msg = "\n[pass_through] EOF - "
638
+ # msg += buf.nil? ? "nil" : buf.size
639
+ # puts msg
640
+ return if buf.nil?
641
+ rescue Errno::ECONNRESET
642
+ # puts "!!! ERROR (Reset): reading body"
643
+ # puts "* last data seen on socket: #{buf}"
644
+ # msg = "!R - "
645
+ # msg += buf.nil? ? "nil" : buf.size
646
+ # msg << " !\n"
647
+ # puts msg
648
+
649
+ return if buf.nil?
650
+ rescue Timeout::Error
651
+ #puts "!!! ERROR (Timeout): reading body"
652
+ #puts "* last data seen on socket:"
653
+ #client.write buf if buf
654
+ print "T"
655
+ return
656
+ rescue => bang
657
+ puts "!!! could not read body !!!"
658
+ puts bang
659
+ puts bang.class
660
+ puts bang.backtrace if $DEBUG
661
+ # puts "* last data seen on socket:"
662
+ # print "~]"
663
+ #client.write buf if buf
664
+ return
665
+ end
666
+
667
+ begin
668
+ return if buf.nil?
669
+ # print "~"
670
+ client.write buf
671
+ bytes_read += buf.length
672
+ # puts "#{server} #{bytes_read} of #{maxbytes}"
673
+ if maxbytes > 0 and bytes_read >= maxbytes
674
+ #print "~]"
675
+ return
676
+ end
677
+ rescue Errno::ECONNRESET
678
+ #print "~x]"
679
+ # puts "!!! ERROR (Reset): reading body"
680
+ # puts "* last data seen on socket: #{buf}"
681
+ return
682
+ rescue Errno::ECONNABORTED
683
+ # print "~x]"
684
+ return
685
+ rescue Errno::EPIPE
686
+ # print "~x]"
687
+ return
688
+ rescue => bang
689
+ puts "!!! client communication broken !!!"
690
+ puts bang
691
+ puts bang.class
692
+ puts bang.backtrace if $DEBUG
693
+ return
694
+ end
695
+ end
696
+ end
697
+
698
+ def transparent?
699
+ (@proxy_mode & Watobo::Interceptor::MODE_TRANSPARENT) > 0
700
+ end
701
+
702
+ def isPassThrough?(request, response, s_sock, c_sock)
709
703
  begin
710
- # return false if true
711
- reason = nil
704
+ # return false if true
705
+ reason = nil
712
706
  clen = response.content_length
713
-
714
- # no pass-through necessary if request method is HEAD
715
- return false if request.method =~ /^head/i
716
-
717
- if matchContentType?(response.content_type) then
718
- # first forward headers
719
- #c_sock.write response.join
720
- reason = []
721
- reason.push "---> WATOBO: PASS_THROUGH <---"
722
- reason.push "Reason: Content-Type = #{response.content_type}"
723
- elsif clen > @contentLength
724
- # puts "PASS-THROUGH: #{response.content_length}"
725
- #c_sock.write response.join
726
- reason = []
727
- reason.push "---> WATOBO: PASS_THROUGH <---"
728
- reason.push "Reason: Content-Length > #{@contentLength} (#{response.content_length})"
729
- end
730
-
707
+
708
+
709
+ # no pass-through necessary if request method is HEAD
710
+ return false if request.method =~ /^head/i
711
+
712
+ if matchContentType?(response.content_type) then
713
+ # first forward headers
714
+ #c_sock.write response.join
715
+ reason = []
716
+ reason.push "---> WATOBO: PASS_THROUGH <---"
717
+ reason.push "Reason: Content-Type = #{response.content_type}"
718
+ elsif clen > @contentLength
719
+ # puts "PASS-THROUGH: #{response.content_length}"
720
+ #c_sock.write response.join
721
+ reason = []
722
+ reason.push "---> WATOBO: PASS_THROUGH <---"
723
+ reason.push "Reason: Content-Length > #{@contentLength} (#{response.content_length})"
724
+ end
725
+
726
+ @pass_through_hosts.each do |p|
727
+ if request.host =~ /#{p}/
728
+ c_sock.write response.join
729
+ pass_through(s_sock, c_sock, clen)
730
+ return true
731
+ end
732
+ end
733
+
731
734
  return false if reason.nil?
732
-
735
+
733
736
  response.remove_header("Keep-Alive")
734
737
  response.set_header("Connection", "close")
735
-
738
+
736
739
  c_sock.write response.join
737
-
738
- reason.push "* DO MANUAL REQUEST TO GET FULL RESPONSE *"
739
- response.push reason.join("\n")
740
- chat = Watobo::Chat.new(request, response, :source => CHAT_SOURCE_INTERCEPT)
741
- #notify(:new_interception, chat)
742
- Watobo::Chats.add chat
743
-
744
- pass_through(s_sock, c_sock, clen)
745
- # puts "* Close Server Socket..."
746
- #closeSocket(c_sock)
747
- # puts "* Close Client Socket..."
748
- #closeSocket(s_sock)
749
- # puts "... done."
750
- return true
751
- rescue => bang
752
- puts bang
753
- puts bang.backtrace if $DEBUG
740
+
741
+ reason.push "* DO MANUAL REQUEST TO GET FULL RESPONSE *"
742
+ response.push reason.join("\n")
743
+ chat = Watobo::Chat.new(request, response, :source => CHAT_SOURCE_INTERCEPT)
744
+ #notify(:new_interception, chat)
745
+ Watobo::Chats.add chat
746
+
747
+ pass_through(s_sock, c_sock, clen)
748
+ # puts "* Close Server Socket..."
749
+ #closeSocket(c_sock)
750
+ # puts "* Close Client Socket..."
751
+ #closeSocket(s_sock)
752
+ # puts "... done."
753
+ return true
754
+ rescue => bang
755
+ puts bang
756
+ puts bang.backtrace if $DEBUG
754
757
  end
755
- return false
756
- end
757
-
758
- end
759
- end
760
- end
758
+ return false
759
+ end
760
+
761
+ end
762
+ end
763
+ end