diff options
Diffstat (limited to 'plugins/mod_proxy65.lua')
-rw-r--r-- | plugins/mod_proxy65.lua | 187 |
1 files changed, 89 insertions, 98 deletions
diff --git a/plugins/mod_proxy65.lua b/plugins/mod_proxy65.lua index d02f3b58..b2f6f703 100644 --- a/plugins/mod_proxy65.lua +++ b/plugins/mod_proxy65.lua @@ -6,35 +6,21 @@ -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. -- ---[[ -* to restart the proxy in the console: e.g. -module:unload("proxy65"); -> server.removeserver(<proxy65_port>); -module:load("proxy65", <proxy65_jid>); -]]-- +module:set_global(); -local module = module; -local tostring = tostring; local jid_compare, jid_prep = require "util.jid".compare, require "util.jid".prep; local st = require "util.stanza"; -local connlisteners = require "net.connlisteners"; local sha1 = require "util.hashes".sha1; -local server = require "net.server"; local b64 = require "util.encodings".base64.encode; +local server = require "net.server"; -local host, name = module:get_host(), "SOCKS5 Bytestreams Service"; -local sessions, transfers = {}, {}; - -local proxy_port = module:get_option("proxy65_port") or 5000; -local proxy_interface = module:get_option("proxy65_interface") or "*"; -local proxy_address = module:get_option("proxy65_address") or (proxy_interface ~= "*" and proxy_interface) or host; -local proxy_acl = module:get_option("proxy65_acl"); +local sessions, transfers = module:shared("sessions", "transfers"); local max_buffer_size = 4096; -local connlistener = { default_port = proxy_port, default_interface = proxy_interface, default_mode = "*a" }; +local listener = {}; -function connlistener.onincoming(conn, data) +function listener.onincoming(conn, data) local session = sessions[conn] or {}; local transfer = transfers[session.sha]; @@ -84,7 +70,7 @@ function connlistener.onincoming(conn, data) end end -function connlistener.ondisconnect(conn, err) +function listener.ondisconnect(conn, err) local session = sessions[conn]; if session then if transfers[session.sha] then @@ -101,88 +87,93 @@ function connlistener.ondisconnect(conn, err) end end -module:add_identity("proxy", "bytestreams", name); -module:add_feature("http://jabber.org/protocol/bytestreams"); - -module:hook("iq-get/host/http://jabber.org/protocol/disco#info:query", function(event) - local origin, stanza = event.origin, event.stanza; - origin.send(st.reply(stanza):query("http://jabber.org/protocol/disco#info") - :tag("identity", {category='proxy', type='bytestreams', name=name}):up() - :tag("feature", {var="http://jabber.org/protocol/bytestreams"}) ); - return true; -end, -1); - -module:hook("iq-get/host/http://jabber.org/protocol/disco#items:query", function(event) - local origin, stanza = event.origin, event.stanza; - origin.send(st.reply(stanza):query("http://jabber.org/protocol/disco#items")); - return true; -end, -1); +function module.add_host(module) + local host, name = module:get_host(), module:get_option_string("name", "SOCKS5 Bytestreams Service"); + + local proxy_address = module:get_option("proxy65_address", host); + local proxy_port = module:get_option_number("proxy65_port", next(portmanager.get_active_services():search("proxy65", nil)[1] or {})); + local proxy_acl = module:get_option("proxy65_acl"); -module:hook("iq-get/host/http://jabber.org/protocol/bytestreams:query", function(event) - local origin, stanza = event.origin, event.stanza; + module:add_identity("proxy", "bytestreams", name); + module:add_feature("http://jabber.org/protocol/bytestreams"); + + module:hook("iq-get/host/http://jabber.org/protocol/disco#info:query", function(event) + local origin, stanza = event.origin, event.stanza; + origin.send(st.reply(stanza):query("http://jabber.org/protocol/disco#info") + :tag("identity", {category='proxy', type='bytestreams', name=name}):up() + :tag("feature", {var="http://jabber.org/protocol/bytestreams"}) ); + return true; + end, -1); + + module:hook("iq-get/host/http://jabber.org/protocol/disco#items:query", function(event) + local origin, stanza = event.origin, event.stanza; + origin.send(st.reply(stanza):query("http://jabber.org/protocol/disco#items")); + return true; + end, -1); - -- check ACL - while proxy_acl and #proxy_acl > 0 do -- using 'while' instead of 'if' so we can break out of it - local jid = stanza.attr.from; - for _, acl in ipairs(proxy_acl) do - if jid_compare(jid, acl) then break; end + module:hook("iq-get/host/http://jabber.org/protocol/bytestreams:query", function(event) + local origin, stanza = event.origin, event.stanza; + + -- check ACL + while proxy_acl and #proxy_acl > 0 do -- using 'while' instead of 'if' so we can break out of it + local jid = stanza.attr.from; + for _, acl in ipairs(proxy_acl) do + if jid_compare(jid, acl) then break; end + end + module:log("warn", "Denying use of proxy for %s", tostring(stanza.attr.from)); + origin.send(st.error_reply(stanza, "auth", "forbidden")); + return true; end - module:log("warn", "Denying use of proxy for %s", tostring(stanza.attr.from)); - origin.send(st.error_reply(stanza, "auth", "forbidden")); + + local sid = stanza.tags[1].attr.sid; + origin.send(st.reply(stanza):tag("query", {xmlns="http://jabber.org/protocol/bytestreams", sid=sid}) + :tag("streamhost", {jid=host, host=proxy_address, port=proxy_port})); return true; - end - - local sid = stanza.tags[1].attr.sid; - origin.send(st.reply(stanza):tag("query", {xmlns="http://jabber.org/protocol/bytestreams", sid=sid}) - :tag("streamhost", {jid=host, host=proxy_address, port=proxy_port})); - return true; -end); - -module.unload = function() - connlisteners.deregister(module.host .. ':proxy65'); -end - -module:hook("iq-set/host/http://jabber.org/protocol/bytestreams:query", function(event) - local origin, stanza = event.origin, event.stanza; - - local query = stanza.tags[1]; - local sid = query.attr.sid; - local from = stanza.attr.from; - local to = query:get_child_text("activate"); - local prepped_to = jid_prep(to); - - local info = "sid: "..tostring(sid)..", initiator: "..tostring(from)..", target: "..tostring(prepped_to or to); - if prepped_to and sid then - local sha = sha1(sid .. from .. prepped_to, true); - if not transfers[sha] then - module:log("debug", "Activation request has unknown session id; activation failed (%s)", info); - origin.send(st.error_reply(stanza, "modify", "item-not-found")); - elseif not transfers[sha].initiator then - module:log("debug", "The sender was not connected to the proxy; activation failed (%s)", info); - origin.send(st.error_reply(stanza, "cancel", "not-allowed", "The sender (you) is not connected to the proxy")); - --elseif not transfers[sha].target then -- can't happen, as target is set when a transfer object is created - -- module:log("debug", "The recipient was not connected to the proxy; activation failed (%s)", info); - -- origin.send(st.error_reply(stanza, "cancel", "not-allowed", "The recipient is not connected to the proxy")); - else -- if transfers[sha].initiator ~= nil and transfers[sha].target ~= nil then - module:log("debug", "Transfer activated (%s)", info); - transfers[sha].activated = true; - transfers[sha].target:resume(); - transfers[sha].initiator:resume(); - origin.send(st.reply(stanza)); + end); + + module:hook("iq-set/host/http://jabber.org/protocol/bytestreams:query", function(event) + local origin, stanza = event.origin, event.stanza; + + local query = stanza.tags[1]; + local sid = query.attr.sid; + local from = stanza.attr.from; + local to = query:get_child_text("activate"); + local prepped_to = jid_prep(to); + + local info = "sid: "..tostring(sid)..", initiator: "..tostring(from)..", target: "..tostring(prepped_to or to); + if prepped_to and sid then + local sha = sha1(sid .. from .. prepped_to, true); + if not transfers[sha] then + module:log("debug", "Activation request has unknown session id; activation failed (%s)", info); + origin.send(st.error_reply(stanza, "modify", "item-not-found")); + elseif not transfers[sha].initiator then + module:log("debug", "The sender was not connected to the proxy; activation failed (%s)", info); + origin.send(st.error_reply(stanza, "cancel", "not-allowed", "The sender (you) is not connected to the proxy")); + --elseif not transfers[sha].target then -- can't happen, as target is set when a transfer object is created + -- module:log("debug", "The recipient was not connected to the proxy; activation failed (%s)", info); + -- origin.send(st.error_reply(stanza, "cancel", "not-allowed", "The recipient is not connected to the proxy")); + else -- if transfers[sha].initiator ~= nil and transfers[sha].target ~= nil then + module:log("debug", "Transfer activated (%s)", info); + transfers[sha].activated = true; + transfers[sha].target:resume(); + transfers[sha].initiator:resume(); + origin.send(st.reply(stanza)); + end + elseif to and sid then + module:log("debug", "Malformed activation jid; activation failed (%s)", info); + origin.send(st.error_reply(stanza, "modify", "jid-malformed")); + else + module:log("debug", "Bad request; activation failed (%s)", info); + origin.send(st.error_reply(stanza, "modify", "bad-request")); end - elseif to and sid then - module:log("debug", "Malformed activation jid; activation failed (%s)", info); - origin.send(st.error_reply(stanza, "modify", "jid-malformed")); - else - module:log("debug", "Bad request; activation failed (%s)", info); - origin.send(st.error_reply(stanza, "modify", "bad-request")); - end - return true; -end); - -if not connlisteners.register(module.host .. ':proxy65', connlistener) then - module:log("error", "mod_proxy65: Could not establish a connection listener. Check your configuration please."); - module:log("error", "Possibly two proxy65 components are configured to share the same port."); + return true; + end); end -connlisteners.start(module.host .. ':proxy65'); +module:provides("net", { + default_port = 5000; + listener = listener; + multiplex = { + pattern = "^\5"; + }; +}); |