123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- local cyrussasl = require "cyrussasl";
- local log = require "util.logger".init("sasl_cyrus");
- local setmetatable = setmetatable
- local pcall = pcall
- local s_match, s_gmatch = string.match, string.gmatch
- local sasl_errstring = {
-
- [1] = "another step is needed in authentication";
- [0] = "successful result";
- [-1] = "generic failure";
- [-2] = "memory shortage failure";
- [-3] = "overflowed buffer";
- [-4] = "mechanism not supported";
- [-5] = "bad protocol / cancel";
- [-6] = "can't request info until later in exchange";
- [-7] = "invalid parameter supplied";
- [-8] = "transient failure (e.g., weak key)";
- [-9] = "integrity check failed";
- [-12] = "SASL library not initialized";
-
- [2] = "needs user interaction";
- [-10] = "server failed mutual authentication step";
- [-11] = "mechanism doesn't support requested feature";
-
- [-13] = "authentication failure";
- [-14] = "authorization failure";
- [-15] = "mechanism too weak for this user";
- [-16] = "encryption needed to use mechanism";
- [-17] = "One time use of a plaintext password will enable requested mechanism for user";
- [-18] = "passphrase expired, has to be reset";
- [-19] = "account disabled";
- [-20] = "user not found";
- [-23] = "version mismatch with plug-in";
- [-24] = "remote authentication server unavailable";
- [-26] = "user exists, but no verifier for user";
-
- [-21] = "passphrase locked";
- [-22] = "requested change was not needed";
- [-27] = "passphrase is too weak for security policy";
- [-28] = "user supplied passwords not permitted";
- };
- setmetatable(sasl_errstring, { __index = function() return "undefined error!" end });
- local _ENV = nil;
- local method = {};
- method.__index = method;
- local initialized = false;
- local function init(service_name)
- if not initialized then
- local st, errmsg = pcall(cyrussasl.server_init, service_name);
- if st then
- initialized = true;
- else
- log("error", "Failed to initialize Cyrus SASL: %s", errmsg);
- end
- end
- end
- local function new(realm, service_name, app_name, host_fqdn)
- init(app_name or service_name);
- local st, ret = pcall(cyrussasl.server_new, service_name, host_fqdn, realm, nil, nil)
- if not st then
- log("error", "Creating SASL server connection failed: %s", ret);
- return nil;
- end
- local sasl_i = { realm = realm, service_name = service_name, cyrus = ret };
- if cyrussasl.set_canon_cb then
- local c14n_cb = function (user)
- local node = s_match(user, "^([^@]+)");
- log("debug", "Canonicalizing username %s to %s", user, node)
- return node
- end
- cyrussasl.set_canon_cb(sasl_i.cyrus, c14n_cb);
- end
- cyrussasl.setssf(sasl_i.cyrus, 0, 0xffffffff)
- local mechanisms = {};
- local cyrus_mechs = cyrussasl.listmech(sasl_i.cyrus, nil, "", " ", "");
- for w in s_gmatch(cyrus_mechs, "[^ ]+") do
- mechanisms[w] = true;
- end
- sasl_i.mechs = mechanisms;
- return setmetatable(sasl_i, method);
- end
- function method:clean_clone()
- return new(self.realm, self.service_name)
- end
- function method:mechanisms()
- return self.mechs;
- end
- function method:select(mechanism)
- if not self.selected and self.mechs[mechanism] then
- self.selected = mechanism;
- return true;
- end
- end
- function method:process(message)
- local err;
- local data;
- if not self.first_step_done then
- err, data = cyrussasl.server_start(self.cyrus, self.selected, message or "")
- self.first_step_done = true;
- else
- err, data = cyrussasl.server_step(self.cyrus, message or "")
- end
- self.username = cyrussasl.get_username(self.cyrus)
- if (err == 0) then
- if self.require_provisioning and not self.require_provisioning(self.username) then
- return "failure", "not-authorized", "User authenticated successfully, but not provisioned for XMPP";
- end
- return "success", data
- elseif (err == 1) then
- return "challenge", data
- elseif (err == -4) then
- log("debug", "SASL mechanism not available from remote end")
- return "failure", "invalid-mechanism", "SASL mechanism not available"
- elseif (err == -13) then
- return "failure", "not-authorized", sasl_errstring[err];
- else
- log("debug", "Got SASL error condition %d: %s", err, sasl_errstring[err]);
- return "failure", "undefined-condition", sasl_errstring[err];
- end
- end
- return {
- new = new;
- };
|