comparison mod_auth_external/mod_auth_external.lua @ 168:cd8492748985

mod_auth_external: Renamed from mod_extauth. Update logging and options (external_auth_protocol, external_auth_command)
author Matthew Wild <mwild1@gmail.com>
date Thu, 10 Jun 2010 13:01:36 +0100
parents mod_extauth/mod_extauth.lua@75a85eac3c27
children 2686221255cf
comparison
equal deleted inserted replaced
167:0d37d18ea073 168:cd8492748985
1 --
2 -- NOTE: currently this uses lpc; when waqas fixes process, it can go back to that
3 --
4 -- Prosody IM
5 -- Copyright (C) 2010 Waqas Hussain
6 -- Copyright (C) 2010 Jeff Mitchell
7 --
8 -- This project is MIT/X11 licensed. Please see the
9 -- COPYING file in the source package for more information.
10 --
11
12
13 local nodeprep = require "util.encodings".stringprep.nodeprep;
14 --local process = require "process";
15 local lpc = require "lpc";
16
17 local config = require "core.configmanager";
18 local log = module._log;
19 local host = module.host;
20 local script_type = config.get(host, "core", "external_auth_protocol") or "generic";
21 assert(script_type == "ejabberd" or script_type == "generic");
22 local command = config.get(host, "core", "external_auth_command") or "";
23 assert(type(command) == "string");
24 assert(not host:find(":"));
25 local usermanager = require "core.usermanager";
26 local jid_bare = require "util.jid".bare;
27 local new_sasl = require "util.sasl".new;
28
29 --local proc;
30 local pid;
31 local readfile;
32 local writefile;
33 local function send_query(text)
34 -- if not proc then
35 if not pid then
36 log("debug", "Opening process");
37 -- proc = process.popen(command);
38 pid, writefile, readfile = lpc.run(command);
39 end
40 -- if not proc then
41 if not pid then
42 log("debug", "Process failed to open");
43 return nil;
44 end
45 -- proc:write(text);
46 -- proc:flush();
47 writefile:write(text);
48 writefile:flush();
49 if script_type == "ejabberd" then
50 -- return proc:read(4); -- FIXME do properly
51 return readfile:read(4); -- FIXME do properly
52 elseif script_type == "generic" then
53 -- return proc:read(1);
54 return readfile:read();
55 end
56 end
57
58 function do_query(kind, username, password)
59 if not username then return nil, "not-acceptable"; end
60 username = nodeprep(username);
61 if not username then return nil, "jid-malformed"; end
62
63 local query = (password and "%s:%s:%s:%s" or "%s:%s:%s"):format(kind, username, host, password);
64 local len = #query
65 if len > 1000 then return nil, "policy-violation"; end
66
67 if script_type == "ejabberd" then
68 local lo = len % 256;
69 local hi = (len - lo) / 256;
70 query = string.char(hi, lo)..query;
71 end
72 if script_type == "generic" then
73 query = query..'\n';
74 end
75
76 local response = send_query(query);
77 if (script_type == "ejabberd" and response == "\0\2\0\0") or
78 (script_type == "generic" and response == "0") then
79 return nil, "not-authorized";
80 elseif (script_type == "ejabberd" and response == "\0\2\0\1") or
81 (script_type == "generic" and response == "1") then
82 return true;
83 else
84 log("debug", "Nonsense back");
85 --proc:close();
86 --proc = nil;
87 return nil, "internal-server-error";
88 end
89 end
90
91 function new_external_provider(host)
92 local provider = { name = "external" };
93
94 function provider.test_password(username, password)
95 return do_query("auth", username, password);
96 end
97
98 function provider.set_password(username, password)
99 return do_query("setpass", username, password);
100 end
101
102 function provider.user_exists(username)
103 return do_query("isuser", username);
104 end
105
106 function provider.create_user(username, password) return nil, "Account creation/modification not available."; end
107
108 function provider.get_sasl_handler()
109 local realm = module:get_option("sasl_realm") or module.host;
110 local testpass_authentication_profile = {
111 plain_test = function(username, password, realm)
112 local prepped_username = nodeprep(username);
113 if not prepped_username then
114 log("debug", "NODEprep failed on username: %s", username);
115 return "", nil;
116 end
117 return usermanager.test_password(prepped_username, password, realm), true;
118 end,
119 };
120 return new_sasl(realm, testpass_authentication_profile);
121 end
122
123 function provider.is_admin(jid)
124 local admins = config.get(host, "core", "admins");
125 if admins ~= config.get("*", "core", "admins") then
126 if type(admins) == "table" then
127 jid = jid_bare(jid);
128 for _,admin in ipairs(admins) do
129 if admin == jid then return true; end
130 end
131 elseif admins then
132 log("error", "Option 'admins' for host '%s' is not a table", host);
133 end
134 end
135 return usermanager.is_admin(jid); -- Test whether it's a global admin instead
136 end
137
138 return provider;
139 end
140
141 module:add_item("auth-provider", new_external_provider(module.host));