Mercurial > prosody-hg
comparison plugins/mod_xmlrpc.lua @ 1587:81992255a374
mod_xmlrpc: Added support for secure calls by non-admins
| author | Waqas Hussain <waqas20@gmail.com> |
|---|---|
| date | Sat, 25 Jul 2009 18:38:47 +0500 |
| parents | 841d61be198f |
| children | 638761692663 |
comparison
equal
deleted
inserted
replaced
| 1586:5c627d5d5e37 | 1587:81992255a374 |
|---|---|
| 14 local pcall = pcall; | 14 local pcall = pcall; |
| 15 local unpack = unpack; | 15 local unpack = unpack; |
| 16 local tostring = tostring; | 16 local tostring = tostring; |
| 17 local is_admin = require "core.usermanager".is_admin; | 17 local is_admin = require "core.usermanager".is_admin; |
| 18 local jid_split = require "util.jid".split; | 18 local jid_split = require "util.jid".split; |
| 19 local jid_bare = require "util.jid".bare; | |
| 19 local b64_decode = require "util.encodings".base64.decode; | 20 local b64_decode = require "util.encodings".base64.decode; |
| 20 local get_method = require "core.objectmanager".get_object; | 21 local get_method = require "core.objectmanager".get_object; |
| 21 local validate_credentials = require "core.usermanager".validate_credentials; | 22 local validate_credentials = require "core.usermanager".validate_credentials; |
| 22 | 23 |
| 23 local translate_request = require "util.xmlrpc".translate_request; | 24 local translate_request = require "util.xmlrpc".translate_request; |
| 63 end | 64 end |
| 64 end | 65 end |
| 65 return stanza.tags[1]; | 66 return stanza.tags[1]; |
| 66 end | 67 end |
| 67 | 68 |
| 68 local function handle_xmlrpc_request(method, args) | 69 local function handle_xmlrpc_request(jid, method, args) |
| 70 local is_secure_call = (method:sub(1,7) ~= "secure/"); | |
| 71 if not is_admin(jid) and not is_secure_call then | |
| 72 return create_error_response(401, "not authorized"); | |
| 73 end | |
| 69 method = get_method(method); | 74 method = get_method(method); |
| 70 if not method then return create_error_response(404, "method not found"); end | 75 if not method then return create_error_response(404, "method not found"); end |
| 71 args = args or {}; | 76 args = args or {}; |
| 77 if is_secure_call then t_insert(args, 1, jid); end | |
| 72 local success, result = pcall(method, unpack(args)); | 78 local success, result = pcall(method, unpack(args)); |
| 73 if success then | 79 if success then |
| 74 success, result = pcall(create_response, result or "nil"); | 80 success, result = pcall(create_response, result or "nil"); |
| 75 if success then | 81 if success then |
| 76 return result; | 82 return result; |
| 82 | 88 |
| 83 local function handle_xmpp_request(origin, stanza) | 89 local function handle_xmpp_request(origin, stanza) |
| 84 local query = stanza.tags[1]; | 90 local query = stanza.tags[1]; |
| 85 if query.name == "query" then | 91 if query.name == "query" then |
| 86 if #query.tags == 1 then | 92 if #query.tags == 1 then |
| 87 if is_admin(stanza.attr.from) then | 93 local success, method, args = pcall(translate_request, query.tags[1]); |
| 88 local success, method, args = pcall(translate_request, query.tags[1]); | 94 if success then |
| 89 if success then | 95 local result = handle_xmlrpc_request(jid_bare(stanza.attr.from), method, args); |
| 90 local result = handle_xmlrpc_request(method, args); | 96 origin.send(st.reply(stanza):tag('query', {xmlns='jabber:iq:rpc'}):add_child(result)); |
| 91 origin.send(st.reply(stanza):tag('query', {xmlns='jabber:iq:rpc'}):add_child(result)); | 97 else |
| 92 else | 98 origin.send(st.error_reply(stanza, "modify", "bad-request", method)); |
| 93 origin.send(st.error_reply(stanza, "modify", "bad-request", method)); | 99 end |
| 94 end | |
| 95 else origin.send(st.error_reply(stanza, "auth", "forbidden", "No content in XML-RPC request")); end | |
| 96 else origin.send(st.error_reply(stanza, "modify", "bad-request", "No content in XML-RPC request")); end | 100 else origin.send(st.error_reply(stanza, "modify", "bad-request", "No content in XML-RPC request")); end |
| 97 else origin.send(st.error_reply(stanza, "cancel", "service-unavailable")); end | 101 else origin.send(st.error_reply(stanza, "cancel", "service-unavailable")); end |
| 98 end | 102 end |
| 99 module:add_iq_handler({"c2s", "s2sin"}, "jabber:iq:rpc", handle_xmpp_request); | 103 module:add_iq_handler({"c2s", "s2sin"}, "jabber:iq:rpc", handle_xmpp_request); |
| 100 module:add_feature("jabber:iq:rpc"); | 104 module:add_feature("jabber:iq:rpc"); |
| 104 local unauthorized_response = { status = '401 UNAUTHORIZED', headers = {['Content-Type']='text/html', ['WWW-Authenticate']='Basic realm="WallyWorld"'}; body = "<html><body>Authentication required</body></html>"; }; | 108 local unauthorized_response = { status = '401 UNAUTHORIZED', headers = {['Content-Type']='text/html', ['WWW-Authenticate']='Basic realm="WallyWorld"'}; body = "<html><body>Authentication required</body></html>"; }; |
| 105 local function handle_http_request(method, body, request) | 109 local function handle_http_request(method, body, request) |
| 106 -- authenticate user | 110 -- authenticate user |
| 107 local username, password = b64_decode(request['authorization'] or ''):gmatch('([^:]*):(.*)')(); -- TODO digest auth | 111 local username, password = b64_decode(request['authorization'] or ''):gmatch('([^:]*):(.*)')(); -- TODO digest auth |
| 108 local node, host = jid_split(username); | 112 local node, host = jid_split(username); |
| 109 if not validate_credentials(host, node, password) and is_admin(username) then | 113 if not validate_credentials(host, node, password) then |
| 110 return unauthorized_response; | 114 return unauthorized_response; |
| 111 end | 115 end |
| 112 -- parse request | 116 -- parse request |
| 113 local stanza = body and parse_xml(body); | 117 local stanza = body and parse_xml(body); |
| 114 if (not stanza) or request.method ~= "POST" then | 118 if (not stanza) or request.method ~= "POST" then |
| 115 return "<html><body>You really don't look like an XML-RPC client to me... what do you want?</body></html>"; | 119 return "<html><body>You really don't look like an XML-RPC client to me... what do you want?</body></html>"; |
| 116 end | 120 end |
| 117 -- execute request | 121 -- execute request |
| 118 local success, method, args = pcall(translate_request, stanza); | 122 local success, method, args = pcall(translate_request, stanza); |
| 119 if success then | 123 if success then |
| 120 return { headers = default_headers; body = tostring(handle_xmlrpc_request(method, args)) }; | 124 return { headers = default_headers; body = tostring(handle_xmlrpc_request(node.."@"..host, method, args)) }; |
| 121 end | 125 end |
| 122 return "<html><body>Error parsing XML-RPC request: "..tostring(method).."</body></html>"; | 126 return "<html><body>Error parsing XML-RPC request: "..tostring(method).."</body></html>"; |
| 123 end | 127 end |
| 124 httpserver.new{ port = 9000, base = "xmlrpc", handler = handle_http_request } | 128 httpserver.new{ port = 9000, base = "xmlrpc", handler = handle_http_request } |
