diff options
Diffstat (limited to 'src/auth/passdb-bsdauth.c')
-rw-r--r-- | src/auth/passdb-bsdauth.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/src/auth/passdb-bsdauth.c b/src/auth/passdb-bsdauth.c new file mode 100644 index 0000000..36469c6 --- /dev/null +++ b/src/auth/passdb-bsdauth.c @@ -0,0 +1,97 @@ +/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */ + +#include "auth-common.h" +#include "passdb.h" + +#ifdef PASSDB_BSDAUTH + +#include "safe-memset.h" +#include "auth-cache.h" +#include "ipwd.h" +#include "mycrypt.h" + +#include <login_cap.h> +#include <bsd_auth.h> + +static void +bsdauth_verify_plain(struct auth_request *request, const char *password, + verify_plain_callback_t *callback) +{ + struct passwd pw; + const char *type; + int result; + + e_debug(authdb_event(request), "lookup"); + + switch (i_getpwnam(request->fields.user, &pw)) { + case -1: + e_error(authdb_event(request), + "getpwnam() failed: %m"); + callback(PASSDB_RESULT_INTERNAL_FAILURE, request); + return; + case 0: + auth_request_log_unknown_user(request, AUTH_SUBSYS_DB); + callback(PASSDB_RESULT_USER_UNKNOWN, request); + return; + } + + /* check if the password is valid */ + type = t_strdup_printf("auth-%s", request->fields.service); + result = auth_userokay(request->fields.user, NULL, + t_strdup_noconst(type), + t_strdup_noconst(password)); + + /* clear the passwords from memory */ + safe_memset(pw.pw_passwd, 0, strlen(pw.pw_passwd)); + + if (result == 0) { + auth_request_log_password_mismatch(request, AUTH_SUBSYS_DB); + callback(PASSDB_RESULT_PASSWORD_MISMATCH, request); + return; + } + + /* make sure we're using the username exactly as it's in the database */ + auth_request_set_field(request, "user", pw.pw_name, NULL); + + callback(PASSDB_RESULT_OK, request); +} + +static struct passdb_module * +bsdauth_preinit(pool_t pool, const char *args) +{ + struct passdb_module *module; + + module = p_new(pool, struct passdb_module, 1); + module->default_pass_scheme = "PLAIN"; /* same reason as PAM */ + module->blocking = TRUE; + + if (strcmp(args, "blocking=no") == 0) + module->blocking = FALSE; + else if (str_begins(args, "cache_key=")) + module->default_cache_key = auth_cache_parse_key(pool, args + 10); + else if (*args != '\0') + i_fatal("passdb bsdauth: Unknown setting: %s", args); + return module; +} + +static void bsdauth_deinit(struct passdb_module *module ATTR_UNUSED) +{ + endpwent(); +} + +struct passdb_module_interface passdb_bsdauth = { + "bsdauth", + + bsdauth_preinit, + NULL, + bsdauth_deinit, + + bsdauth_verify_plain, + NULL, + NULL +}; +#else +struct passdb_module_interface passdb_bsdauth = { + .name = "bsdauth" +}; +#endif |