util/sasl_cyrus.lua
changeset 2389 8f6526da4757
child 2392 8777831706d9
equal deleted inserted replaced
2388:4768879d3591 2389:8f6526da4757
       
     1 -- sasl.lua v0.4
       
     2 -- Copyright (C) 2008-2009 Tobias Markmann
       
     3 --
       
     4 --    All rights reserved.
       
     5 --
       
     6 --    Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
       
     7 --
       
     8 --        * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
       
     9 --        * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
       
    10 --        * Neither the name of Tobias Markmann nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
       
    11 --
       
    12 --    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    13 
       
    14 local cyrussasl = require "cyrussasl";
       
    15 local log = require "util.logger".init("sasl_cyrus");
       
    16 local array = require "util.array";
       
    17 
       
    18 local tostring = tostring;
       
    19 local pairs, ipairs = pairs, ipairs;
       
    20 local t_insert, t_concat = table.insert, table.concat;
       
    21 local s_match = string.match;
       
    22 
       
    23 local keys = keys;
       
    24 
       
    25 local print = print
       
    26 
       
    27 module "sasl_cyrus"
       
    28 
       
    29 local method = {};
       
    30 method.__index = method;
       
    31 local mechanisms = {};
       
    32 local backend_mechanism = {};
       
    33 
       
    34 -- register a new SASL mechanims
       
    35 local function registerMechanism(name, backends, f)
       
    36 	assert(type(name) == "string", "Parameter name MUST be a string.");
       
    37 	assert(type(backends) == "string" or type(backends) == "table", "Parameter backends MUST be either a string or a table.");
       
    38 	assert(type(f) == "function", "Parameter f MUST be a function.");
       
    39 	mechanisms[name] = f
       
    40 	for _, backend_name in ipairs(backends) do
       
    41 		if backend_mechanism[backend_name] == nil then backend_mechanism[backend_name] = {}; end
       
    42 		t_insert(backend_mechanism[backend_name], name);
       
    43 	end
       
    44 end
       
    45 
       
    46 -- create a new SASL object which can be used to authenticate clients
       
    47 function new(realm, service_name)
       
    48 	local sasl_i = {};
       
    49 	sasl_i.realm = realm;
       
    50 	sasl_i.service_name = service_name;
       
    51 	sasl_i.cyrus = cyrussasl.server_new(service_name, realm, realm, nil, nil)
       
    52 	if sasl_i.cyrus ~= 0, 
       
    53 		   "got NULL return value from server_new")
       
    54 	cyrussasl.setssf(sasl_i.cyrus, 0, 0xffffffff)
       
    55 	local s = setmetatable(sasl_i, method);
       
    56 	return s;
       
    57 end
       
    58 
       
    59 -- get a fresh clone with the same realm, profiles and forbidden mechanisms
       
    60 function method:clean_clone()
       
    61 	return new(self.realm, self.service_name)
       
    62 end
       
    63 
       
    64 -- set the forbidden mechanisms
       
    65 function method:forbidden( restrict )
       
    66 	log("debug", "Called method:forbidden. NOT IMPLEMENTED.")
       
    67 	return {}
       
    68 end
       
    69 
       
    70 -- get a list of possible SASL mechanims to use
       
    71 function method:mechanisms()
       
    72 	local mechanisms = {}
       
    73 	local cyrus_mechs = cyrussasl.listmech(self.cyrus)
       
    74 	for w in s_gmatch(cyrus_mechs, "%a+") do
       
    75 		mechanisms[w] = true;
       
    76 	end
       
    77 	self.mechanisms = mechanisms
       
    78 	return array.collect(keys(mechanisms));
       
    79 end
       
    80 
       
    81 -- select a mechanism to use
       
    82 function method:select(mechanism)
       
    83 	self.mechanism = mechanism;
       
    84 	return not self.mechanisms[mechanisms];
       
    85 end
       
    86 
       
    87 -- feed new messages to process into the library
       
    88 function method:process(message)
       
    89 	local err;
       
    90 	local data;
       
    91 	if self.mechanism then
       
    92 		err, data = cyrussasl.server_start(self.cyrus, self.mechanism, message)
       
    93 	else
       
    94 		err, data = cyrussasl.server_step(self.cyrus, message)
       
    95 	end
       
    96 
       
    97 	self.username = cyrussasl.get_username(self.cyrus)
       
    98 
       
    99 	if (err == 0) then -- SASL_OK
       
   100 	   return "success", data
       
   101 	elseif (err == 1) then -- SASL_CONTINUE
       
   102 	   return "challenge", data
       
   103 	elseif (err == -4) then -- SASL_NOMECH
       
   104 	   log("debug", "SASL mechanism not available from remote end")
       
   105 	   return "failure", 
       
   106 	     "undefined-condition",
       
   107 	     "SASL mechanism not available"
       
   108 	elseif (err == -13) then -- SASL_BADAUTH
       
   109 	   return "failure", "not-authorized"
       
   110 	else
       
   111 	   log("debug", "Got SASL error condition %d", err)
       
   112 	   return "failure", 
       
   113 	     "undefined-condition",
       
   114 	     cyrussasl.get_message( self.cyrus )
       
   115 	end
       
   116 end
       
   117 
       
   118 return _M;