Comparison

plugins/mod_websocket.lua @ 10563:e8db377a2983

Merge 0.11->trunk
author Kim Alvefur <zash@zash.se>
date Tue, 24 Dec 2019 00:39:45 +0100
parent 10325:f2bbad04cf64
child 10582:6d4562acef81
comparison
equal deleted inserted replaced
10562:670afc079f68 10563:e8db377a2983
27 27
28 local t_concat = table.concat; 28 local t_concat = table.concat;
29 29
30 local stream_close_timeout = module:get_option_number("c2s_close_timeout", 5); 30 local stream_close_timeout = module:get_option_number("c2s_close_timeout", 5);
31 local consider_websocket_secure = module:get_option_boolean("consider_websocket_secure"); 31 local consider_websocket_secure = module:get_option_boolean("consider_websocket_secure");
32 local cross_domain = module:get_option_set("cross_domain_websocket", {}); 32 local cross_domain = module:get_option("cross_domain_websocket");
33 if cross_domain:contains("*") or cross_domain:contains(true) then 33 if cross_domain ~= nil then
34 cross_domain = true; 34 module:log("info", "The 'cross_domain_websocket' option has been deprecated");
35 end 35 end
36
37 local function check_origin(origin)
38 if cross_domain == true then
39 return true;
40 end
41 return cross_domain:contains(origin);
42 end
43
44 local xmlns_framing = "urn:ietf:params:xml:ns:xmpp-framing"; 36 local xmlns_framing = "urn:ietf:params:xml:ns:xmpp-framing";
45 local xmlns_streams = "http://etherx.jabber.org/streams"; 37 local xmlns_streams = "http://etherx.jabber.org/streams";
46 local xmlns_client = "jabber:client"; 38 local xmlns_client = "jabber:client";
47 local stream_xmlns_attr = {xmlns='urn:ietf:params:xml:ns:xmpp-streams'}; 39 local stream_xmlns_attr = {xmlns='urn:ietf:params:xml:ns:xmpp-streams'};
48 40
86 end 78 end
87 elseif reason.name then -- a stanza 79 elseif reason.name then -- a stanza
88 stream_error = reason; 80 stream_error = reason;
89 end 81 end
90 end 82 end
91 log("debug", "Disconnecting client, <stream:error> is: %s", tostring(stream_error)); 83 log("debug", "Disconnecting client, <stream:error> is: %s", stream_error);
92 session.send(stream_error); 84 session.send(stream_error);
93 end 85 end
94 86
95 session.send(st.stanza("close", { xmlns = xmlns_framing })); 87 session.send(st.stanza("close", { xmlns = xmlns_framing }));
96 function session.send() return false; end 88 function session.send() return false; end
142 local request, response = event.request, event.response; 134 local request, response = event.request, event.response;
143 local conn = response.conn; 135 local conn = response.conn;
144 136
145 conn.starttls = false; -- Prevent mod_tls from believing starttls can be done 137 conn.starttls = false; -- Prevent mod_tls from believing starttls can be done
146 138
147 if not request.headers.sec_websocket_key then 139 if not request.headers.sec_websocket_key or request.method ~= "GET" then
148 response.headers.content_type = "text/html"; 140 response.headers.content_type = "text/html";
149 return [[<!DOCTYPE html><html><head><title>Websocket</title></head><body> 141 return [[<!DOCTYPE html><html><head><title>Websocket</title></head><body>
150 <p>It works! Now point your WebSocket client to this URL to connect to Prosody.</p> 142 <p>It works! Now point your WebSocket client to this URL to connect to Prosody.</p>
151 </body></html>]]; 143 </body></html>]];
152 end 144 end
154 local wants_xmpp = contains_token(request.headers.sec_websocket_protocol or "", "xmpp"); 146 local wants_xmpp = contains_token(request.headers.sec_websocket_protocol or "", "xmpp");
155 147
156 if not wants_xmpp then 148 if not wants_xmpp then
157 module:log("debug", "Client didn't want to talk XMPP, list of protocols was %s", request.headers.sec_websocket_protocol or "(empty)"); 149 module:log("debug", "Client didn't want to talk XMPP, list of protocols was %s", request.headers.sec_websocket_protocol or "(empty)");
158 return 501; 150 return 501;
159 end
160
161 if not check_origin(request.headers.origin or "") then
162 module:log("debug", "Origin %s is not allowed by 'cross_domain_websocket' [ %s ]", request.headers.origin or "(missing header)", cross_domain);
163 return 403;
164 end 151 end
165 152
166 local function websocket_close(code, message) 153 local function websocket_close(code, message)
167 conn:write(build_close(code, message)); 154 conn:write(build_close(code, message));
168 conn:close(); 155 conn:close();
328 }; 315 };
329 }); 316 });
330 317
331 function module.add_host(module) 318 function module.add_host(module)
332 module:hook("c2s-read-timeout", keepalive, -0.9); 319 module:hook("c2s-read-timeout", keepalive, -0.9);
333 320 end
334 if cross_domain ~= true then
335 local url = require "socket.url";
336 local ws_url = module:http_url("websocket", "xmpp-websocket");
337 local url_components = url.parse(ws_url);
338 -- The 'Origin' consists of the base URL without path
339 url_components.path = nil;
340 local this_origin = url.build(url_components);
341 local local_cross_domain = module:get_option_set("cross_domain_websocket", { this_origin });
342 if local_cross_domain:contains(true) then
343 module:log("error", "cross_domain_websocket = true only works in the global section");
344 return;
345 end
346
347 -- Don't add / remove something added by another host
348 -- This might be weird with random load order
349 local_cross_domain:exclude(cross_domain);
350 cross_domain:include(local_cross_domain);
351 module:log("debug", "cross_domain = %s", tostring(cross_domain));
352 function module.unload()
353 cross_domain:exclude(local_cross_domain);
354 end
355 end
356 end