|
|
|
|
@ -39,113 +39,111 @@ end |
|
|
|
|
-- Default; can be set per-user |
|
|
|
|
local iteration_count = 4096; |
|
|
|
|
|
|
|
|
|
function new_hashpass_provider(host) |
|
|
|
|
local provider = { name = "internal_hashed" }; |
|
|
|
|
log("debug", "initializing internal_hashed authentication provider for host '%s'", host); |
|
|
|
|
local host = module.host; |
|
|
|
|
-- define auth provider |
|
|
|
|
local provider = { name = "internal_hashed" }; |
|
|
|
|
log("debug", "initializing internal_hashed authentication provider for host '%s'", host); |
|
|
|
|
|
|
|
|
|
function provider.test_password(username, password) |
|
|
|
|
local credentials = datamanager.load(username, host, "accounts") or {}; |
|
|
|
|
|
|
|
|
|
if credentials.password ~= nil and string.len(credentials.password) ~= 0 then |
|
|
|
|
if credentials.password ~= password then |
|
|
|
|
return nil, "Auth failed. Provided password is incorrect."; |
|
|
|
|
end |
|
|
|
|
function provider.test_password(username, password) |
|
|
|
|
local credentials = datamanager.load(username, host, "accounts") or {}; |
|
|
|
|
|
|
|
|
|
if provider.set_password(username, credentials.password) == nil then |
|
|
|
|
return nil, "Auth failed. Could not set hashed password from plaintext."; |
|
|
|
|
else |
|
|
|
|
return true; |
|
|
|
|
end |
|
|
|
|
if credentials.password ~= nil and string.len(credentials.password) ~= 0 then |
|
|
|
|
if credentials.password ~= password then |
|
|
|
|
return nil, "Auth failed. Provided password is incorrect."; |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
if credentials.iteration_count == nil or credentials.salt == nil or string.len(credentials.salt) == 0 then |
|
|
|
|
return nil, "Auth failed. Stored salt and iteration count information is not complete."; |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
local valid, stored_key, server_key = getAuthenticationDatabaseSHA1(password, credentials.salt, credentials.iteration_count); |
|
|
|
|
|
|
|
|
|
local stored_key_hex = to_hex(stored_key); |
|
|
|
|
local server_key_hex = to_hex(server_key); |
|
|
|
|
|
|
|
|
|
if valid and stored_key_hex == credentials.stored_key and server_key_hex == credentials.server_key then |
|
|
|
|
return true; |
|
|
|
|
if provider.set_password(username, credentials.password) == nil then |
|
|
|
|
return nil, "Auth failed. Could not set hashed password from plaintext."; |
|
|
|
|
else |
|
|
|
|
return nil, "Auth failed. Invalid username, password, or password hash information."; |
|
|
|
|
return true; |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
function provider.set_password(username, password) |
|
|
|
|
local account = datamanager.load(username, host, "accounts"); |
|
|
|
|
if account then |
|
|
|
|
account.salt = account.salt or generate_uuid(); |
|
|
|
|
account.iteration_count = account.iteration_count or iteration_count; |
|
|
|
|
local valid, stored_key, server_key = getAuthenticationDatabaseSHA1(password, account.salt, account.iteration_count); |
|
|
|
|
local stored_key_hex = to_hex(stored_key); |
|
|
|
|
local server_key_hex = to_hex(server_key); |
|
|
|
|
|
|
|
|
|
account.stored_key = stored_key_hex |
|
|
|
|
account.server_key = server_key_hex |
|
|
|
|
|
|
|
|
|
account.password = nil; |
|
|
|
|
return datamanager.store(username, host, "accounts", account); |
|
|
|
|
end |
|
|
|
|
return nil, "Account not available."; |
|
|
|
|
if credentials.iteration_count == nil or credentials.salt == nil or string.len(credentials.salt) == 0 then |
|
|
|
|
return nil, "Auth failed. Stored salt and iteration count information is not complete."; |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
function provider.user_exists(username) |
|
|
|
|
local account = datamanager.load(username, host, "accounts"); |
|
|
|
|
if not account then |
|
|
|
|
log("debug", "account not found for username '%s' at host '%s'", username, module.host); |
|
|
|
|
return nil, "Auth failed. Invalid username"; |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
local valid, stored_key, server_key = getAuthenticationDatabaseSHA1(password, credentials.salt, credentials.iteration_count); |
|
|
|
|
|
|
|
|
|
local stored_key_hex = to_hex(stored_key); |
|
|
|
|
local server_key_hex = to_hex(server_key); |
|
|
|
|
|
|
|
|
|
if valid and stored_key_hex == credentials.stored_key and server_key_hex == credentials.server_key then |
|
|
|
|
return true; |
|
|
|
|
else |
|
|
|
|
return nil, "Auth failed. Invalid username, password, or password hash information."; |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
function provider.create_user(username, password) |
|
|
|
|
if password == nil then |
|
|
|
|
return datamanager.store(username, host, "accounts", {}); |
|
|
|
|
end |
|
|
|
|
local salt = generate_uuid(); |
|
|
|
|
local valid, stored_key, server_key = getAuthenticationDatabaseSHA1(password, salt, iteration_count); |
|
|
|
|
function provider.set_password(username, password) |
|
|
|
|
local account = datamanager.load(username, host, "accounts"); |
|
|
|
|
if account then |
|
|
|
|
account.salt = account.salt or generate_uuid(); |
|
|
|
|
account.iteration_count = account.iteration_count or iteration_count; |
|
|
|
|
local valid, stored_key, server_key = getAuthenticationDatabaseSHA1(password, account.salt, account.iteration_count); |
|
|
|
|
local stored_key_hex = to_hex(stored_key); |
|
|
|
|
local server_key_hex = to_hex(server_key); |
|
|
|
|
return datamanager.store(username, host, "accounts", {stored_key = stored_key_hex, server_key = server_key_hex, salt = salt, iteration_count = iteration_count}); |
|
|
|
|
|
|
|
|
|
account.stored_key = stored_key_hex |
|
|
|
|
account.server_key = server_key_hex |
|
|
|
|
|
|
|
|
|
account.password = nil; |
|
|
|
|
return datamanager.store(username, host, "accounts", account); |
|
|
|
|
end |
|
|
|
|
return nil, "Account not available."; |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
function provider.delete_user(username) |
|
|
|
|
return datamanager.store(username, host, "accounts", nil); |
|
|
|
|
function provider.user_exists(username) |
|
|
|
|
local account = datamanager.load(username, host, "accounts"); |
|
|
|
|
if not account then |
|
|
|
|
log("debug", "account not found for username '%s' at host '%s'", username, host); |
|
|
|
|
return nil, "Auth failed. Invalid username"; |
|
|
|
|
end |
|
|
|
|
return true; |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
function provider.get_sasl_handler() |
|
|
|
|
local testpass_authentication_profile = { |
|
|
|
|
plain_test = function(sasl, username, password, realm) |
|
|
|
|
local prepped_username = nodeprep(username); |
|
|
|
|
if not prepped_username then |
|
|
|
|
log("debug", "NODEprep failed on username: %s", username); |
|
|
|
|
return "", nil; |
|
|
|
|
end |
|
|
|
|
return usermanager.test_password(prepped_username, realm, password), true; |
|
|
|
|
end, |
|
|
|
|
scram_sha_1 = function(sasl, username, realm) |
|
|
|
|
local credentials = datamanager.load(username, host, "accounts"); |
|
|
|
|
if not credentials then return; end |
|
|
|
|
if credentials.password then |
|
|
|
|
usermanager.set_password(username, credentials.password, host); |
|
|
|
|
credentials = datamanager.load(username, host, "accounts"); |
|
|
|
|
if not credentials then return; end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
local stored_key, server_key, iteration_count, salt = credentials.stored_key, credentials.server_key, credentials.iteration_count, credentials.salt; |
|
|
|
|
stored_key = stored_key and from_hex(stored_key); |
|
|
|
|
server_key = server_key and from_hex(server_key); |
|
|
|
|
return stored_key, server_key, iteration_count, salt, true; |
|
|
|
|
end |
|
|
|
|
}; |
|
|
|
|
return new_sasl(module.host, testpass_authentication_profile); |
|
|
|
|
function provider.create_user(username, password) |
|
|
|
|
if password == nil then |
|
|
|
|
return datamanager.store(username, host, "accounts", {}); |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
return provider; |
|
|
|
|
local salt = generate_uuid(); |
|
|
|
|
local valid, stored_key, server_key = getAuthenticationDatabaseSHA1(password, salt, iteration_count); |
|
|
|
|
local stored_key_hex = to_hex(stored_key); |
|
|
|
|
local server_key_hex = to_hex(server_key); |
|
|
|
|
return datamanager.store(username, host, "accounts", {stored_key = stored_key_hex, server_key = server_key_hex, salt = salt, iteration_count = iteration_count}); |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
module:add_item("auth-provider", new_hashpass_provider(module.host)); |
|
|
|
|
function provider.delete_user(username) |
|
|
|
|
return datamanager.store(username, host, "accounts", nil); |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
function provider.get_sasl_handler() |
|
|
|
|
local testpass_authentication_profile = { |
|
|
|
|
plain_test = function(sasl, username, password, realm) |
|
|
|
|
local prepped_username = nodeprep(username); |
|
|
|
|
if not prepped_username then |
|
|
|
|
log("debug", "NODEprep failed on username: %s", username); |
|
|
|
|
return "", nil; |
|
|
|
|
end |
|
|
|
|
return usermanager.test_password(prepped_username, realm, password), true; |
|
|
|
|
end, |
|
|
|
|
scram_sha_1 = function(sasl, username, realm) |
|
|
|
|
local credentials = datamanager.load(username, host, "accounts"); |
|
|
|
|
if not credentials then return; end |
|
|
|
|
if credentials.password then |
|
|
|
|
usermanager.set_password(username, credentials.password, host); |
|
|
|
|
credentials = datamanager.load(username, host, "accounts"); |
|
|
|
|
if not credentials then return; end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
local stored_key, server_key, iteration_count, salt = credentials.stored_key, credentials.server_key, credentials.iteration_count, credentials.salt; |
|
|
|
|
stored_key = stored_key and from_hex(stored_key); |
|
|
|
|
server_key = server_key and from_hex(server_key); |
|
|
|
|
return stored_key, server_key, iteration_count, salt, true; |
|
|
|
|
end |
|
|
|
|
}; |
|
|
|
|
return new_sasl(host, testpass_authentication_profile); |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
module:add_item("auth-provider", provider); |
|
|
|
|
|
|
|
|
|
|