Mercurial > prosody-modules
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)); |
