passdb.c revision b4f2560c29dacd066ba89e782d95ceed7ac473a3
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (C) 2002-2003 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "common.h"
e05a4c4136fec723f019bee8383103080203f127Timo Sirainen#include "auth-module.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "password-scheme.h"
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen#include "auth-worker-server.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "passdb.h"
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <stdlib.h>
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainenextern struct passdb_module_interface passdb_passwd;
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainenextern struct passdb_module_interface passdb_bsdauth;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenextern struct passdb_module_interface passdb_shadow;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenextern struct passdb_module_interface passdb_passwd_file;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenextern struct passdb_module_interface passdb_pam;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainenextern struct passdb_module_interface passdb_checkpassword;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainenextern struct passdb_module_interface passdb_vpopmail;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainenextern struct passdb_module_interface passdb_ldap;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenextern struct passdb_module_interface passdb_sql;
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainenextern struct passdb_module_interface passdb_sia;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainenstruct passdb_module_interface *passdb_interfaces[] = {
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen#ifdef PASSDB_PASSWD
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen &passdb_passwd,
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen#endif
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen#ifdef PASSDB_BSDAUTH
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen &passdb_bsdauth,
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen#endif
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen#ifdef PASSDB_PASSWD_FILE
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen &passdb_passwd_file,
01937f71b3ae0d5b30b813372f44a3e7e86c89dcTimo Sirainen#endif
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen#ifdef PASSDB_PAM
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &passdb_pam,
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen#endif
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen#ifdef PASSDB_CHECKPASSWORD
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen &passdb_checkpassword,
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen#endif
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen#ifdef PASSDB_SHADOW
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen &passdb_shadow,
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifdef PASSDB_VPOPMAIL
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen &passdb_vpopmail,
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen#endif
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen#ifdef PASSDB_LDAP
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen &passdb_ldap,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifdef PASSDB_SQL
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &passdb_sql,
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen#endif
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen#ifdef PASSDB_SIA
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen &passdb_sia,
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen#endif
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen NULL
d22301419109ed4a38351715e6760011421dadecTimo Sirainen};
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainenbool passdb_get_credentials(struct auth_request *auth_request,
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen const char *input, const char *input_scheme,
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen const unsigned char **credentials_r, size_t *size_r)
01937f71b3ae0d5b30b813372f44a3e7e86c89dcTimo Sirainen{
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen const char *wanted_scheme = auth_request->credentials_scheme;
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen const char *plaintext;
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen int ret;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen ret = password_decode(input, input_scheme, credentials_r, size_r);
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen if (ret <= 0) {
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen if (ret < 0) {
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen auth_request_log_error(auth_request, "password",
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen "Invalid password format for scheme %s",
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen input_scheme);
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen } else {
a341c4cdbd4b93ba479f465ad3f569dc82f57312Timo Sirainen auth_request_log_error(auth_request, "password",
013e3b3942e9550fde619a0b3ce6bdd04edc4268Timo Sirainen "Unknown scheme %s", input_scheme);
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen }
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen return FALSE;
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen }
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen if (*wanted_scheme == '\0') {
9293bf90039454f47e94e4ba3722a775cfa7d25cTimo Sirainen /* anything goes. change the credentials_scheme to what we
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen actually got, so blocking passdbs work. */
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen auth_request->credentials_scheme =
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen p_strdup(auth_request->pool, input_scheme);
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen return TRUE;
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen }
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen if (!password_scheme_is_alias(input_scheme, wanted_scheme)) {
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen if (!password_scheme_is_alias(input_scheme, "PLAIN")) {
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen auth_request_log_info(auth_request, "password",
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen "Requested %s scheme, but we have only %s",
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen wanted_scheme, input_scheme);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen return FALSE;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen }
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen /* we can generate anything out of plaintext passwords */
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen plaintext = t_strndup(*credentials_r, *size_r);
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen if (!password_generate(plaintext, auth_request->user,
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen wanted_scheme, credentials_r, size_r)) {
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen auth_request_log_error(auth_request, "password",
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen "Requested unknown scheme %s", wanted_scheme);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen return FALSE;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen }
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen }
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen return TRUE;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen}
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainenvoid passdb_handle_credentials(enum passdb_result result,
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen const char *password, const char *scheme,
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen lookup_credentials_callback_t *callback,
4d2211dac61c615c5bdfd501ea54d46c89d41b0fTimo Sirainen struct auth_request *auth_request)
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen{
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen const unsigned char *credentials;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen size_t size = 0;
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen if (result != PASSDB_RESULT_OK) {
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen callback(result, NULL, 0, auth_request);
741d705983e10046f07ef372b760bcdd169b068aTimo Sirainen return;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen }
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen if (password == NULL ||
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen !passdb_get_credentials(auth_request, password, scheme,
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen &credentials, &size))
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen result = PASSDB_RESULT_SCHEME_NOT_AVAILABLE;
4d2211dac61c615c5bdfd501ea54d46c89d41b0fTimo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen callback(result, credentials, size, auth_request);
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen}
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainenstruct auth_passdb *passdb_preinit(struct auth *auth, const char *driver,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen const char *args, unsigned int id)
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen{
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen struct passdb_module_interface **p, *iface;
741d705983e10046f07ef372b760bcdd169b068aTimo Sirainen struct auth_passdb *auth_passdb;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen if (args == NULL) args = "";
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_passdb = p_new(auth->pool, struct auth_passdb, 1);
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen auth_passdb->auth = auth;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_passdb->args = p_strdup(auth->pool, args);
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen auth_passdb->id = id;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen iface = NULL;
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen for (p = passdb_interfaces; *p != NULL; p++) {
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen if (strcmp((*p)->name, driver) == 0) {
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen iface = *p;
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen break;
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen }
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen }
#ifdef HAVE_MODULES
if (iface == NULL)
auth_passdb->module = auth_module_open(driver);
if (auth_passdb->module != NULL) {
iface = auth_module_sym(auth_passdb->module,
t_strconcat("passdb_", driver, NULL));
}
#endif
if (iface == NULL) {
i_fatal("Unknown passdb driver '%s' "
"(typo, or Dovecot was built without support for it? "
"Check with dovecot --build-options)",
driver);
}
if (iface->preinit == NULL) {
auth_passdb->passdb =
p_new(auth->pool, struct passdb_module, 1);
} else {
auth_passdb->passdb =
iface->preinit(auth_passdb, auth_passdb->args);
}
auth_passdb->passdb->iface = *iface;
return auth_passdb;
}
void passdb_init(struct auth_passdb *passdb)
{
if (passdb->passdb->iface.init != NULL)
passdb->passdb->iface.init(passdb->passdb, passdb->args);
i_assert(passdb->passdb->default_pass_scheme != NULL ||
passdb->passdb->cache_key == NULL);
if (passdb->passdb->blocking && !worker) {
/* blocking passdb - we need an auth server */
auth_worker_server_init();
}
}
void passdb_deinit(struct auth_passdb *passdb)
{
if (passdb->passdb->iface.deinit != NULL)
passdb->passdb->iface.deinit(passdb->passdb);
#ifdef HAVE_MODULES
if (passdb->module != NULL)
auth_module_close(&passdb->module);
#endif
}