Comparison

plugins/mod_websocket.lua @ 7762:2208e6cd0d9f

mod_websocket: Verify that the client-sent Origin header matches cross_domain_websocket (fixes #652)
author Kim Alvefur <zash@zash.se>
date Mon, 05 Dec 2016 12:22:41 +0100
parent 7761:e0e1f6d6fb4f
child 7763:c5ce14539fc4
comparison
equal deleted inserted replaced
7761:e0e1f6d6fb4f 7762:2208e6cd0d9f
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("cross_domain_websocket"); 32 local cross_domain = module:get_option_set("cross_domain_websocket", {});
33 if cross_domain then 33 if cross_domain:contains("*") or cross_domain:contains(true) then
34 cross_domain = true;
35 end
36
37 local function check_origin(origin)
34 if cross_domain == true then 38 if cross_domain == true then
35 cross_domain = "*"; 39 return true;
36 elseif type(cross_domain) == "table" then 40 end
37 cross_domain = t_concat(cross_domain, ", "); 41 return cross_domain:contains(origin);
38 end
39 if type(cross_domain) ~= "string" then
40 cross_domain = nil;
41 end
42 end 42 end
43 43
44 local xmlns_framing = "urn:ietf:params:xml:ns:xmpp-framing"; 44 local xmlns_framing = "urn:ietf:params:xml:ns:xmpp-framing";
45 local xmlns_streams = "http://etherx.jabber.org/streams"; 45 local xmlns_streams = "http://etherx.jabber.org/streams";
46 local xmlns_client = "jabber:client"; 46 local xmlns_client = "jabber:client";
146 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");
147 147
148 if not wants_xmpp then 148 if not wants_xmpp then
149 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)");
150 return 501; 150 return 501;
151 end
152
153 if not check_origin(request.headers.origin or "") then
154 module:log("debug", "Origin %s is not allowed by 'cross_domain_websocket'", request.headers.origin or "(missing header)");
155 return 403;
151 end 156 end
152 157
153 local function websocket_close(code, message) 158 local function websocket_close(code, message)
154 conn:write(build_close(code, message)); 159 conn:write(build_close(code, message));
155 conn:close(); 160 conn:close();
282 response.status_code = 101; 287 response.status_code = 101;
283 response.headers.upgrade = "websocket"; 288 response.headers.upgrade = "websocket";
284 response.headers.connection = "Upgrade"; 289 response.headers.connection = "Upgrade";
285 response.headers.sec_webSocket_accept = base64(sha1(request.headers.sec_websocket_key .. "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")); 290 response.headers.sec_webSocket_accept = base64(sha1(request.headers.sec_websocket_key .. "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"));
286 response.headers.sec_webSocket_protocol = "xmpp"; 291 response.headers.sec_webSocket_protocol = "xmpp";
287 response.headers.access_control_allow_origin = cross_domain;
288 292
289 session.log("debug", "Sending WebSocket handshake"); 293 session.log("debug", "Sending WebSocket handshake");
290 294
291 return ""; 295 return "";
292 end 296 end