Software /
code /
prosody
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 |
parent | 1523:841d61be198f |
child | 1590: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 } |