Mercurial > prosody-hg
comparison plugins/mod_proxy65.lua @ 14150:2a66728d9e29 13.0 13.0.5
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 | 9c98cc9d9588 |
| children | e3ddbf7f2d3f |
comparison
equal
deleted
inserted
replaced
| 14149:9c98cc9d9588 | 14150:2a66728d9e29 |
|---|---|
| 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"); |
