passdb.c revision 1f1e81aab38d833d1c9cdc244c91fd762e0080d4
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen/* Copyright (C) 2002-2003 Timo Sirainen */
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen#include "common.h"
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen#include "mech.h"
70cb37c37e4dce8f57cd3f882f7444e76b918befTimo Sirainen#include "auth-module.h"
ff487c974815bdaa2d05a3b834f4c2c841f4cc34Timo Sirainen#include "password-scheme.h"
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen#include "passdb.h"
dc9bfb7dc057964238e181d3d8b08751527bb08aTimo Sirainen#include "passdb-cache.h"
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen#include <stdlib.h>
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
98a711be68ba64e1cabf8cacc150af44421e2ac9Timo Sirainen#ifdef HAVE_MODULES
70cb37c37e4dce8f57cd3f882f7444e76b918befTimo Sirainenstatic struct auth_module *passdb_module = NULL;
70cb37c37e4dce8f57cd3f882f7444e76b918befTimo Sirainen#endif
70cb37c37e4dce8f57cd3f882f7444e76b918befTimo Sirainen
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainenstruct passdb_module *passdbs[] = {
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen#ifdef PASSDB_PASSWD
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen &passdb_passwd,
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen#endif
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen#ifdef PASSDB_BSDAUTH
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen &passdb_bsdauth,
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen#endif
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen#ifdef PASSDB_PASSWD_FILE
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen &passdb_passwd_file,
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen#endif
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen#ifdef PASSDB_PAM
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen &passdb_pam,
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen#endif
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen#ifdef PASSDB_CHECKPASSWORD
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen &passdb_checkpassword,
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen#endif
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen#ifdef PASSDB_SHADOW
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen &passdb_shadow,
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen#endif
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen#ifdef PASSDB_VPOPMAIL
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen &passdb_vpopmail,
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen#endif
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen#ifdef PASSDB_LDAP
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen &passdb_ldap,
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen#endif
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen#ifdef PASSDB_SQL
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen &passdb_sql,
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen#endif
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen NULL
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen};
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainenstruct passdb_module *passdb;
08aea01ef9a9d20703e0fcf8618e6195c0037a44Timo Sirainenstatic char *passdb_args;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainenstatic const char *
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainenpassdb_credentials_to_str(enum passdb_credentials credentials)
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen{
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen switch (credentials) {
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen case _PASSDB_CREDENTIALS_INTERNAL:
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen break;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen case PASSDB_CREDENTIALS_PLAINTEXT:
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen return "PLAIN";
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen case PASSDB_CREDENTIALS_CRYPT:
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen return "CRYPT";
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainen case PASSDB_CREDENTIALS_CRAM_MD5:
6c07b8ddc5e894feead4d422075b079451721241Timo Sirainen return "HMAC-MD5";
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen case PASSDB_CREDENTIALS_DIGEST_MD5:
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen return "DIGEST-MD5";
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen case PASSDB_CREDENTIALS_LANMAN:
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen return "LANMAN";
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen case PASSDB_CREDENTIALS_NTLM:
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen return "NTLM";
a4ac325c2802693c6b761e5a8fda961e5d7490eaTimo Sirainen case PASSDB_CREDENTIALS_RPA:
a4ac325c2802693c6b761e5a8fda961e5d7490eaTimo Sirainen return "RPA";
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen }
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen return "??";
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen}
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainenvoid passdb_handle_credentials(enum passdb_credentials credentials,
dc9bfb7dc057964238e181d3d8b08751527bb08aTimo Sirainen const char *password, const char *scheme,
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen lookup_credentials_callback_t *callback,
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen struct auth_request *auth_request)
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen{
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen const char *wanted_scheme;
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen if (credentials == PASSDB_CREDENTIALS_CRYPT) {
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen /* anything goes */
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen if (password != NULL)
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen password = t_strdup_printf("{%s}%s", scheme, password);
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen callback(password, auth_request);
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen return;
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen }
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen if (password != NULL) {
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen wanted_scheme = passdb_credentials_to_str(credentials);
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen if (strcasecmp(scheme, wanted_scheme) != 0) {
794ac3e4a22caba0297a1333b43e6bd47fc50b91Timo Sirainen if (strcasecmp(scheme, "PLAIN") == 0 ||
794ac3e4a22caba0297a1333b43e6bd47fc50b91Timo Sirainen strcasecmp(scheme, "CLEARTEXT") == 0) {
ff487c974815bdaa2d05a3b834f4c2c841f4cc34Timo Sirainen /* we can generate anything out of plaintext
ff487c974815bdaa2d05a3b834f4c2c841f4cc34Timo Sirainen passwords */
dc9bfb7dc057964238e181d3d8b08751527bb08aTimo Sirainen password = password_generate(password,
dc9bfb7dc057964238e181d3d8b08751527bb08aTimo Sirainen auth_request->user,
ff487c974815bdaa2d05a3b834f4c2c841f4cc34Timo Sirainen wanted_scheme);
ff487c974815bdaa2d05a3b834f4c2c841f4cc34Timo Sirainen } else {
ff487c974815bdaa2d05a3b834f4c2c841f4cc34Timo Sirainen if (verbose) {
ff487c974815bdaa2d05a3b834f4c2c841f4cc34Timo Sirainen i_info("password(%s): Requested %s "
ff487c974815bdaa2d05a3b834f4c2c841f4cc34Timo Sirainen "scheme, but we have only %s",
dc9bfb7dc057964238e181d3d8b08751527bb08aTimo Sirainen auth_request->user,
dc9bfb7dc057964238e181d3d8b08751527bb08aTimo Sirainen wanted_scheme, scheme);
ff487c974815bdaa2d05a3b834f4c2c841f4cc34Timo Sirainen }
ff487c974815bdaa2d05a3b834f4c2c841f4cc34Timo Sirainen password = NULL;
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen }
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen }
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen }
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen callback(password, auth_request);
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen}
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainenstatic void mech_list_verify_passdb(struct passdb_module *passdb)
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen{
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen struct mech_module_list *list;
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen for (list = mech_modules; list != NULL; list = list->next) {
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen if (list->module.passdb_need_plain &&
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen passdb->verify_plain == NULL)
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen break;
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen if (list->module.passdb_need_credentials &&
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen passdb->lookup_credentials == NULL)
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen break;
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen }
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen if (list != NULL) {
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen i_fatal("Passdb %s doesn't support %s method",
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen passdb->name, list->module.mech_name);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen }
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen}
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen
08aea01ef9a9d20703e0fcf8618e6195c0037a44Timo Sirainenvoid passdb_preinit(void)
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen{
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen struct passdb_module **p;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen const char *name, *args;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen name = getenv("PASSDB");
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen if (name == NULL)
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen i_fatal("PASSDB environment is unset");
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen args = strchr(name, ' ');
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen name = t_strcut(name, ' ');
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
91e4199476cb2add8143c18583fa57e1decfea88Timo Sirainen if (args == NULL) args = "";
91e4199476cb2add8143c18583fa57e1decfea88Timo Sirainen while (*args == ' ' || *args == '\t')
0727e38ac12efb8963a339daf56255e2be1f29fcTimo Sirainen args++;
0727e38ac12efb8963a339daf56255e2be1f29fcTimo Sirainen
08aea01ef9a9d20703e0fcf8618e6195c0037a44Timo Sirainen passdb_args = i_strdup(args);
08aea01ef9a9d20703e0fcf8618e6195c0037a44Timo Sirainen
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen passdb = NULL;
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen for (p = passdbs; *p != NULL; p++) {
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen if (strcmp((*p)->name, name) == 0) {
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen passdb = *p;
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen break;
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen }
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen }
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen
98a711be68ba64e1cabf8cacc150af44421e2ac9Timo Sirainen#ifdef HAVE_MODULES
6d239203867965ad42f38747f0b84e7314d215d3Timo Sirainen passdb_module = passdb != NULL ? NULL : auth_module_open(name);
70cb37c37e4dce8f57cd3f882f7444e76b918befTimo Sirainen if (passdb_module != NULL) {
70cb37c37e4dce8f57cd3f882f7444e76b918befTimo Sirainen passdb = auth_module_sym(passdb_module,
70cb37c37e4dce8f57cd3f882f7444e76b918befTimo Sirainen t_strconcat("passdb_", name, NULL));
70cb37c37e4dce8f57cd3f882f7444e76b918befTimo Sirainen }
70cb37c37e4dce8f57cd3f882f7444e76b918befTimo Sirainen#endif
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen if (passdb == NULL)
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen i_fatal("Unknown passdb type '%s'", name);
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
08aea01ef9a9d20703e0fcf8618e6195c0037a44Timo Sirainen if (passdb->preinit != NULL)
08aea01ef9a9d20703e0fcf8618e6195c0037a44Timo Sirainen passdb->preinit(passdb_args);
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen mech_list_verify_passdb(passdb);
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen}
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
08aea01ef9a9d20703e0fcf8618e6195c0037a44Timo Sirainenvoid passdb_init(void)
08aea01ef9a9d20703e0fcf8618e6195c0037a44Timo Sirainen{
dc9bfb7dc057964238e181d3d8b08751527bb08aTimo Sirainen passdb_cache_init();
08aea01ef9a9d20703e0fcf8618e6195c0037a44Timo Sirainen if (passdb->init != NULL)
08aea01ef9a9d20703e0fcf8618e6195c0037a44Timo Sirainen passdb->init(passdb_args);
08aea01ef9a9d20703e0fcf8618e6195c0037a44Timo Sirainen}
08aea01ef9a9d20703e0fcf8618e6195c0037a44Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainenvoid passdb_deinit(void)
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen{
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen if (passdb != NULL && passdb->deinit != NULL)
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen passdb->deinit();
98a711be68ba64e1cabf8cacc150af44421e2ac9Timo Sirainen#ifdef HAVE_MODULES
70cb37c37e4dce8f57cd3f882f7444e76b918befTimo Sirainen if (passdb_module != NULL)
70cb37c37e4dce8f57cd3f882f7444e76b918befTimo Sirainen auth_module_close(passdb_module);
70cb37c37e4dce8f57cd3f882f7444e76b918befTimo Sirainen#endif
dc9bfb7dc057964238e181d3d8b08751527bb08aTimo Sirainen passdb_cache_deinit();
08aea01ef9a9d20703e0fcf8618e6195c0037a44Timo Sirainen i_free(passdb_args);
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen}