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 } |