mod_auth_ha1/mod_auth_ha1.lua
changeset 1472 d44926f39f00
child 1473 31c4d92a81e5
equal deleted inserted replaced
1471:153df603f73d 1472:d44926f39f00
       
     1 -- Prosody IM
       
     2 -- Copyright (C) 2014 Matthew Wild
       
     3 --
       
     4 -- This project is MIT/X11 licensed. Please see the
       
     5 -- COPYING file in the source package for more information.
       
     6 --
       
     7 
       
     8 local usermanager = require "core.usermanager";
       
     9 local new_sasl = require "util.sasl".new;
       
    10 
       
    11 local nodeprep = require "util.encodings".stringprep.nodeprep;
       
    12 local nameprep = require "util.encodings".stringprep.nameprep;
       
    13 local md5 = require "util.hashes".md5;
       
    14 
       
    15 local host = module.host;
       
    16 
       
    17 local auth_filename = module:get_option_string("auth_ha1_file", "auth.txt");
       
    18 local auth_data = {};
       
    19 
       
    20 function reload_auth_data()
       
    21 	local f, err = io.open(auth_filename);
       
    22 	if not f then
       
    23 		module:log("error", "Failed to read from auth file: %s", err);
       
    24 		return;
       
    25 	end
       
    26 	auth_data = {};
       
    27 	local line_number, imported_count, not_authorized_count = 0, 0, 0;
       
    28 	for line in f:lines() do
       
    29 		line_number = line_number + 1;
       
    30 		local username, hash, realm, state = line:match("^([^:]+):(%x+):([^:]+):(.+)$");
       
    31 		if not username then
       
    32 			module:log("error", "Unable to parse line %d of auth file, skipping", line_number);
       
    33 		else
       
    34 			username, realm = nodeprep(username), nameprep(realm);
       
    35 			if not username then
       
    36 				module:log("error", "Invalid username on line %d of auth file, skipping", line_number);
       
    37 			elseif not realm then
       
    38 				module:log("error", "Invalid hostname/realm on line %d of auth file, skipping", line_number);
       
    39 			elseif state ~= "authorized" then
       
    40 				not_authorized_count = not_authorized_count + 1;
       
    41 			elseif realm == host then
       
    42 				auth_data[username] = hash;
       
    43 				imported_count = imported_count + 1;
       
    44 			end
       
    45 		end
       
    46 	end
       
    47 	f:close();
       
    48 	module:log("debug", "Loaded %d accounts from auth file (%d authorized)", imported_count, imported_count-not_authorized_count);
       
    49 end
       
    50 
       
    51 function module.load()
       
    52 	reload_auth_data();
       
    53 end
       
    54 
       
    55 module:hook_global("config-reloaded", reload_auth_data);
       
    56 
       
    57 -- define auth provider
       
    58 local provider = {};
       
    59 
       
    60 function provider.test_password(username, password)
       
    61 	module:log("debug", "test password for user %s at host %s, %s", username, host, password);
       
    62 
       
    63 	local test_hash = md5(username..":"..host..":"..password, true);
       
    64 
       
    65 	if test_hash == auth_data[username] then
       
    66 		return true;
       
    67 	else
       
    68 		return nil, "Auth failed. Invalid username or password.";
       
    69 	end
       
    70 end
       
    71 
       
    72 function provider.set_password(username, password)
       
    73 	return nil, "Changing passwords not supported";
       
    74 end
       
    75 
       
    76 function provider.user_exists(username)
       
    77 	if not auth_data[username] then
       
    78 		module:log("debug", "account not found for username '%s' at host '%s'", username, host);
       
    79 		return nil, "Auth failed. Invalid username";
       
    80 	end
       
    81 	return true;
       
    82 end
       
    83 
       
    84 function provider.create_user(username, password)
       
    85 	return nil, "User creation not supported";
       
    86 end
       
    87 
       
    88 function provider.delete_user(username)
       
    89 	return nil , "User deletion not supported";
       
    90 end
       
    91 
       
    92 function provider.get_sasl_handler()
       
    93 	return new_sasl(host, {
       
    94 		plain_test = function(sasl, username, password, realm)
       
    95 			return usermanager.test_password(username, realm, password), true;
       
    96 		end
       
    97 	});
       
    98 end
       
    99 
       
   100 module:provides("auth", provider);
       
   101