-- sasl.lua v0.4
--- Copyright (C) 2008-2009 Tobias Markmann
+-- Copyright (C) 2008-2010 Tobias Markmann
--
-- All rights reserved.
--
local s_match = string.match;
local saslprep = require "util.encodings".stringprep.saslprep;
+local nodeprep = require "util.encodings".stringprep.nodeprep;
local log = require "util.logger".init("sasl");
-module "plain"
+module "sasl.plain"
+
+-- ================================
+-- SASL PLAIN according to RFC 4616
+
+--[[
+Supported Authentication Backends
+
+plain:
+ function(username, realm)
+ return password, state;
+ end
+
+plain_test:
+ function(username, password, realm)
+ return true or false, state;
+ end
+]]
---=========================
---SASL PLAIN according to RFC 4616
local function plain(self, message)
- local response = message
-
- local authorization, authentication, password;
- if response then
- authorization = s_match(response, "([^%z]+)")
- authentication = s_match(response, "%z([^%z]+)%z")
- password = s_match(response, "%z[^%z]+%z([^%z]+)")
+ if not message then
+ return "failure", "malformed-request";
end
-
- if authentication == nil or password == nil then
+
+ local authorization, authentication, password = s_match(message, "^([^%z]*)%z([^%z]+)%z([^%z]+)");
+
+ if not authorization then
return "failure", "malformed-request";
end
-
+
-- SASLprep password and authentication
authentication = saslprep(authentication);
password = saslprep(password);
-
+
if (not password) or (password == "") or (not authentication) or (authentication == "") then
log("debug", "Username or password violates SASLprep.");
return "failure", "malformed-request", "Invalid username or password.";
end
+ local _nodeprep = self.profile.nodeprep;
+ if _nodeprep ~= false then
+ authentication = (_nodeprep or nodeprep)(authentication);
+ if not authentication or authentication == "" then
+ return "failure", "malformed-request", "Invalid username or password."
+ end
+ end
+
local correct, state = false, false;
if self.profile.plain then
local correct_password;
- correct_password, state = self.profile.plain(authentication, self.realm);
- if correct_password == password then correct = true; else correct = false; end
+ correct_password, state = self.profile.plain(self, authentication, self.realm);
+ correct = (correct_password == password);
elseif self.profile.plain_test then
- correct, state = self.profile.plain_test(authentication, self.realm, password);
+ correct, state = self.profile.plain_test(self, authentication, password, self.realm);
end
self.username = authentication
- if not state then
+ if state == false then
return "failure", "account-disabled";
- end
-
- if correct then
- return "success";
- else
+ elseif state == nil or not correct then
return "failure", "not-authorized", "Unable to authorize you with the authentication credentials you've sent.";
end
+
+ return "success";
end
function init(registerMechanism)