passdb-passwd-file.c revision dd93aba1901a457346990f49c54a738947dc7128
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "common.h"
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen#include "passdb.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifdef PASSDB_PASSWD_FILE
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "str.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "auth-cache.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "var-expand.h"
463e82bdf0e990f4f2252d2b53ea23a5abe5883cTimo Sirainen#include "password-scheme.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "db-passwd-file.h"
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen
d41573018e85896ec836d897fd554e87126147f5Timo Sirainenstruct passwd_file_passdb_module {
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen struct passdb_module module;
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen struct auth *auth;
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen struct db_passwd_file *pwf;
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen};
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainenstatic void passwd_file_save_results(struct auth_request *request,
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen const struct passwd_user *pu,
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen const char **crypted_pass_r,
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen const char **scheme_r)
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen{
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen const struct var_expand_table *table;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen const char *key, *value;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen string_t *str;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen char **p;
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen *crypted_pass_r = pu->password;
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen *scheme_r = password_get_scheme(crypted_pass_r);
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen if (*scheme_r == NULL)
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen *scheme_r = request->passdb->passdb->default_pass_scheme;
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen /* save the password so cache can use it */
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen if (*crypted_pass_r != NULL) {
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen auth_request_set_field(request, "password",
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen *crypted_pass_r, *scheme_r);
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen }
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen if (pu->extra_fields != NULL) {
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen str = t_str_new(512);
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen table = auth_request_get_var_expand_table(request, NULL);
c21c33a8c98972c45349066fc76ac9e2c05013c1Timo Sirainen
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen for (p = pu->extra_fields; *p != NULL; p++) {
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen value = strchr(*p, '=');
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen if (value != NULL) {
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen key = t_strdup_until(*p, value);
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen str_truncate(str, 0);
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen var_expand(str, value + 1, table);
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen value = str_c(str);
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen } else {
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen key = *p;
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen value = "";
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen auth_request_set_field(request, key, value, NULL);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
e6d7d19c328e7043ad35d5a52c1617bde915a16fTimo Sirainen }
d7095f3a4466fbb78b2d5eb3d322bc15a5b0ab1fTimo Sirainen}
153de7823e64c67678b3fc95719c41a8ec5b864dTimo Sirainen
153de7823e64c67678b3fc95719c41a8ec5b864dTimo Sirainenstatic void
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainenpasswd_file_verify_plain(struct auth_request *request, const char *password,
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen verify_plain_callback_t *callback)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
e6d7d19c328e7043ad35d5a52c1617bde915a16fTimo Sirainen struct passdb_module *_module = request->passdb->passdb;
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen struct passwd_file_passdb_module *module =
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainen (struct passwd_file_passdb_module *)_module;
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen struct passwd_user *pu;
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen const char *scheme, *crypted_pass;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen int ret;
538c58fc95200fcc5e91abdda8b912b574a2f968Timo Sirainen
b99f3f908d51f4d1f7628bdf2cc6100cd8587656Timo Sirainen pu = db_passwd_file_lookup(module->pwf, request);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen if (pu == NULL) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen callback(PASSDB_RESULT_USER_UNKNOWN, request);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return;
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen }
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen passwd_file_save_results(request, pu, &crypted_pass, &scheme);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ret = auth_request_password_verify(request, password, crypted_pass,
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen scheme, "passwd-file");
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen callback(ret > 0 ? PASSDB_RESULT_OK : PASSDB_RESULT_PASSWORD_MISMATCH,
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen request);
b99f3f908d51f4d1f7628bdf2cc6100cd8587656Timo Sirainen}
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainenstatic void
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenpasswd_file_lookup_credentials(struct auth_request *request,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen lookup_credentials_callback_t *callback)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen struct passdb_module *_module = request->passdb->passdb;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen struct passwd_file_passdb_module *module =
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen (struct passwd_file_passdb_module *)_module;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct passwd_user *pu;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen const char *crypted_pass, *scheme;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen pu = db_passwd_file_lookup(module->pwf, request);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (pu == NULL) {
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen callback(PASSDB_RESULT_USER_UNKNOWN, NULL, 0, request);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen passwd_file_save_results(request, pu, &crypted_pass, &scheme);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen passdb_handle_credentials(PASSDB_RESULT_OK, crypted_pass, scheme,
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen callback, request);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen}
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic struct passdb_module *
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainenpasswd_file_preinit(struct auth_passdb *auth_passdb, const char *args)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen{
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen struct passwd_file_passdb_module *module;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen const char *scheme = PASSWD_FILE_DEFAULT_SCHEME;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen const char *format = PASSWD_FILE_DEFAULT_USERNAME_FORMAT;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen const char *key, *value;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen while (*args != '\0') {
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (*args == '/')
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen key = args;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen value = strchr(key, '=');
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (value == NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen value = "";
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen args = strchr(key, ' ');
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen } else {
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen key = t_strdup_until(key, value);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen args = strchr(++value, ' ');
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (args != NULL)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen value = t_strdup_until(value, args);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen }
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (args == NULL)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen args = "";
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen else
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen args++;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (strcmp(key, "scheme") == 0)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen scheme = p_strdup(auth_passdb->auth->pool, value);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else if (strcmp(key, "username_format") == 0)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen format = p_strdup(auth_passdb->auth->pool, value);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_fatal("passdb passwd-file: Unknown setting: %s", key);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen module = p_new(auth_passdb->auth->pool,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen struct passwd_file_passdb_module, 1);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen module->auth = auth_passdb->auth;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen module->pwf = db_passwd_file_init(args, format, FALSE,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen module->auth->verbose_debug);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (!module->pwf->vars)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen module->module.cache_key = format;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen else {
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen module->module.cache_key =
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen auth_cache_parse_key(auth_passdb->auth->pool,
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen t_strconcat(format, module->pwf->path, NULL));
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen module->module.default_pass_scheme = scheme;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen return &module->module;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen}
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainenstatic void passwd_file_init(struct passdb_module *_module,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const char *args ATTR_UNUSED)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen struct passwd_file_passdb_module *module =
b9ec0443d7d8afebfe61c17a9d692d6fad30c276Timo Sirainen (struct passwd_file_passdb_module *)_module;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen db_passwd_file_parse(module->pwf);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
b9ec0443d7d8afebfe61c17a9d692d6fad30c276Timo Sirainen
23079bf0a6e7489c5f542b0b897a71bdfd884a51Timo Sirainenstatic void passwd_file_deinit(struct passdb_module *_module)
23079bf0a6e7489c5f542b0b897a71bdfd884a51Timo Sirainen{
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen struct passwd_file_passdb_module *module =
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen (struct passwd_file_passdb_module *)_module;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen db_passwd_file_unref(&module->pwf);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen}
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainenstruct passdb_module_interface passdb_passwd_file = {
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen "passwd-file",
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen passwd_file_preinit,
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen passwd_file_init,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen passwd_file_deinit,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen passwd_file_verify_plain,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen passwd_file_lookup_credentials,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen NULL
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen};
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen#else
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainenstruct passdb_module_interface passdb_passwd_file = {
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen MEMBER(name) "passwd-file"
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen};
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen#endif
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen