Software /
code /
prosody
Changeset
7765:4757c3644168
Merge 0.10->trunk
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Mon, 05 Dec 2016 12:29:21 +0100 |
parents | 7758:2b305ec8c146 (current diff) 7764:d6b96e42e8e6 (diff) |
children | 7768:57d0f2d3d5c5 |
files | |
diffstat | 2 files changed, 38 insertions(+), 16 deletions(-) [+] |
line wrap: on
line diff
--- a/net/websocket.lua Fri Dec 02 11:13:05 2016 +0100 +++ b/net/websocket.lua Mon Dec 05 12:29:21 2016 +0100 @@ -44,7 +44,7 @@ return false end -function websocket_listeners.onincoming(handler, buffer, err) +function websocket_listeners.onincoming(handler, buffer, err) -- luacheck: ignore 212/err local s = websockets[handler]; s.readbuffer = s.readbuffer..buffer; while true do @@ -123,7 +123,7 @@ end local websocket_methods = {}; -local function close_timeout_cb(now, timerid, s) +local function close_timeout_cb(now, timerid, s) -- luacheck: ignore 212/now 212/timerid s.close_timer = nil; log("warn", "Close timeout waiting for server to close, closing manually."); s.handler:close(); @@ -232,7 +232,7 @@ }, websocket_metatable); local http_url = url:gsub("^(ws)", "http"); - local http_req = http.request(http_url, { + local http_req = http.request(http_url, { -- luacheck: ignore 211/http_req method = "GET"; headers = headers; sslctx = ex.sslctx;
--- a/plugins/mod_websocket.lua Fri Dec 02 11:13:05 2016 +0100 +++ b/plugins/mod_websocket.lua Mon Dec 05 12:29:21 2016 +0100 @@ -14,6 +14,7 @@ local base64 = require "util.encodings".base64.encode; local st = require "util.stanza"; local parse_xml = require "util.xml".parse; +local contains_token = require "util.http".contains_token; local portmanager = require "core.portmanager"; local sm_destroy_session = require"core.sessionmanager".destroy_session; local log = module._log; @@ -28,16 +29,16 @@ local stream_close_timeout = module:get_option_number("c2s_close_timeout", 5); local consider_websocket_secure = module:get_option_boolean("consider_websocket_secure"); -local cross_domain = module:get_option("cross_domain_websocket"); -if cross_domain then +local cross_domain = module:get_option_set("cross_domain_websocket", {}); +if cross_domain:contains("*") or cross_domain:contains(true) then + cross_domain = true; +end + +local function check_origin(origin) if cross_domain == true then - cross_domain = "*"; - elseif type(cross_domain) == "table" then - cross_domain = t_concat(cross_domain, ", "); + return true; end - if type(cross_domain) ~= "string" then - cross_domain = nil; - end + return cross_domain:contains(origin); end local xmlns_framing = "urn:ietf:params:xml:ns:xmpp-framing"; @@ -142,15 +143,18 @@ </body></html>]]; end - local wants_xmpp = false; - (request.headers.sec_websocket_protocol or ""):gsub("([^,]*),?", function (proto) - if proto == "xmpp" then wants_xmpp = true; end - end); + local wants_xmpp = contains_token(request.headers.sec_websocket_protocol or "", "xmpp"); if not wants_xmpp then + module:log("debug", "Client didn't want to talk XMPP, list of protocols was %s", request.headers.sec_websocket_protocol or "(empty)"); return 501; end + if not check_origin(request.headers.origin or "") then + module:log("debug", "Origin %s is not allowed by 'cross_domain_websocket'", request.headers.origin or "(missing header)"); + return 403; + end + local function websocket_close(code, message) conn:write(build_close(code, message)); conn:close(); @@ -285,7 +289,8 @@ response.headers.connection = "Upgrade"; response.headers.sec_webSocket_accept = base64(sha1(request.headers.sec_websocket_key .. "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")); response.headers.sec_webSocket_protocol = "xmpp"; - response.headers.access_control_allow_origin = cross_domain; + + session.log("debug", "Sending WebSocket handshake"); return ""; end @@ -310,4 +315,21 @@ }; }); module:hook("c2s-read-timeout", keepalive, -0.9); + + if cross_domain ~= true then + local url = require "socket.url"; + local ws_url = module:http_url("websocket", "xmpp-websocket"); + local url_components = url.parse(ws_url); + -- The 'Origin' consists of the base URL without path + url_components.path = nil; + local this_origin = url.build(url_components); + local local_cross_domain = module:get_option_set("cross_domain_websocket", { this_origin }); + -- Don't add / remove something added by another host + -- This might be weird with random load order + local_cross_domain:exclude(cross_domain); + cross_domain:include(local_cross_domain); + function module.unload() + cross_domain:exclude(local_cross_domain); + end + end end