comparison plugins/mod_proxy65.lua @ 14159:4bbb17445ed9 0.12 0.12.6

mod_proxy65: Consistently apply authorization checks The module checked for authorization when a client asked for the address:port of the proxy service. It did not check for authorization when processing a request to activate a bytestream. This meant that any unauthenticated party able to guess the IP/port and XMPP domain of a proxy65 service (generally low difficulty) would be able to use the proxy to relay traffic between two connections. This factors out the permission check, and applies it to every request type.
author Matthew Wild <mwild1@gmail.com>
date Wed, 29 Apr 2026 11:40:43 +0100
parents f34ad235cf3b
children e3ddbf7f2d3f
comparison
equal deleted inserted replaced
14158:f34ad235cf3b 14159:4bbb17445ed9
101 101
102 module:depends("disco"); 102 module:depends("disco");
103 module:add_identity("proxy", "bytestreams", name); 103 module:add_identity("proxy", "bytestreams", name);
104 module:add_feature("http://jabber.org/protocol/bytestreams"); 104 module:add_feature("http://jabber.org/protocol/bytestreams");
105 105
106 module:hook("iq-get/host/http://jabber.org/protocol/bytestreams:query", function(event) 106 local function is_permitted(origin, stanza)
107 local origin, stanza = event.origin, event.stanza;
108
109 -- check ACL
110 -- using 'while' instead of 'if' so we can break out of it
111 local allow;
112 if proxy_acl and #proxy_acl > 0 then 107 if proxy_acl and #proxy_acl > 0 then
113 local jid = stanza.attr.from; 108 local jid = stanza.attr.from;
114 for _, acl in ipairs(proxy_acl) do 109 for _, acl in ipairs(proxy_acl) do
115 if jid_compare(jid, acl) then 110 if jid_compare(jid, acl) then
116 allow = true; 111 return true;
117 break;
118 end 112 end
119 end 113 end
120 elseif proxy_open_access or origin.type == "c2s" then 114 elseif proxy_open_access or origin.type == "c2s" then
121 allow = true; 115 return true;
122 end 116 end
117 return false;
118 end
123 119
124 if not allow then 120 module:hook("iq-get/host/http://jabber.org/protocol/bytestreams:query", function(event)
121 local origin, stanza = event.origin, event.stanza;
122
123 if not is_permitted(origin, stanza) then
125 module:log("warn", "Denying use of proxy for %s", stanza.attr.from); 124 module:log("warn", "Denying use of proxy for %s", stanza.attr.from);
126 origin.send(st.error_reply(stanza, "auth", "forbidden")); 125 origin.send(st.error_reply(stanza, "auth", "forbidden"));
127 return true; 126 return true;
128 end 127 end
129 128
140 return true; 139 return true;
141 end); 140 end);
142 141
143 module:hook("iq-set/host/http://jabber.org/protocol/bytestreams:query", function(event) 142 module:hook("iq-set/host/http://jabber.org/protocol/bytestreams:query", function(event)
144 local origin, stanza = event.origin, event.stanza; 143 local origin, stanza = event.origin, event.stanza;
144
145 if not is_permitted(origin, stanza) then
146 module:log("warn", "Denying use of proxy for %s", stanza.attr.from);
147 origin.send(st.error_reply(stanza, "auth", "forbidden"));
148 return true;
149 end
145 150
146 local query = stanza.tags[1]; 151 local query = stanza.tags[1];
147 local sid = query.attr.sid; 152 local sid = query.attr.sid;
148 local from = stanza.attr.from; 153 local from = stanza.attr.from;
149 local to = query:get_child_text("activate"); 154 local to = query:get_child_text("activate");