view src/auth/passdb-passwd-file.c @ 4034:b533c52196e3 HEAD

Updated passwd-file format to allow specifying any key=value fields. Since the value fields may contain ':' characters, this changes the file format a bit. Previously the last two fields were "flags" and "mail". Flags has been empty for last 3 years however, so the new format is used if the flags field contains something. In that case there is no separate mail field, it can instead be specified by adding userdb_mail=<mail> parameter.
author Timo Sirainen <timo.sirainen@movial.fi>
date Mon, 20 Feb 2006 16:16:00 +0200
parents 40a461d554e6
children 335ac59efffd
line wrap: on
line source

/* Copyright (C) 2002-2003 Timo Sirainen */

#include "common.h"

#ifdef PASSDB_PASSWD_FILE

#include "str.h"
#include "var-expand.h"
#include "passdb.h"
#include "password-scheme.h"
#include "db-passwd-file.h"

#define PASSWD_FILE_CACHE_KEY "%u"
#define PASSWD_FILE_DEFAULT_SCHEME "CRYPT"

struct passwd_file_passdb_module {
	struct passdb_module module;

	struct auth *auth;
	struct db_passwd_file *pwf;
};

static void
passwd_file_verify_plain(struct auth_request *request, const char *password,
			 verify_plain_callback_t *callback)
{
	struct passdb_module *_module = request->passdb->passdb;
	struct passwd_file_passdb_module *module =
		(struct passwd_file_passdb_module *)_module;
	struct passwd_user *pu;
        const struct var_expand_table *table;
	const char *scheme, *crypted_pass, *key, *value;
	string_t *str;
	char **p;
        int ret;

	pu = db_passwd_file_lookup(module->pwf, request);
	if (pu == NULL) {
		callback(PASSDB_RESULT_USER_UNKNOWN, request);
		return;
	}

	crypted_pass = pu->password;
	scheme = password_get_scheme(&crypted_pass);
	if (scheme == NULL) scheme = _module->default_pass_scheme;

	/* save the password so cache can use it */
	if (crypted_pass != NULL) {
		auth_request_set_field(request, "password",
				       crypted_pass, scheme);
        }

	t_push();
	str = t_str_new(512);
	table = auth_request_get_var_expand_table(request, NULL);

	for (p = pu->extra_fields; *p != NULL; p++) {
		value = strchr(*p, '=');
		if (value != NULL) {
			key = t_strdup_until(*p, value);
			str_truncate(str, 0);
			var_expand(str, value + 1, table);
			value = str_c(str);
		} else {
			key = *p;
			value = "";
		}
		auth_request_set_field(request, key, value, NULL);
	}
	t_pop();

	ret = auth_request_password_verify(request, password, crypted_pass,
					   scheme, "passwd-file");

	callback(ret > 0 ? PASSDB_RESULT_OK : PASSDB_RESULT_PASSWORD_MISMATCH,
		 request);
}

static void
passwd_file_lookup_credentials(struct auth_request *request,
			       lookup_credentials_callback_t *callback)
{
	struct passdb_module *_module = request->passdb->passdb;
	struct passwd_file_passdb_module *module =
		(struct passwd_file_passdb_module *)_module;
	struct passwd_user *pu;
	const char *crypted_pass, *scheme;

	pu = db_passwd_file_lookup(module->pwf, request);
	if (pu == NULL) {
		callback(PASSDB_RESULT_USER_UNKNOWN, NULL, request);
		return;
	}

	crypted_pass = pu->password;
	scheme = password_get_scheme(&crypted_pass);

	passdb_handle_credentials(PASSDB_RESULT_OK, crypted_pass, scheme,
				  callback, request);
}

static struct passdb_module *
passwd_file_preinit(struct auth_passdb *auth_passdb,
		    const char *args __attr_unused__)
{
	struct passwd_file_passdb_module *module;

	module = p_new(auth_passdb->auth->pool,
		       struct passwd_file_passdb_module, 1);
	module->auth = auth_passdb->auth;
	module->module.cache_key = PASSWD_FILE_CACHE_KEY;
	module->module.default_pass_scheme = PASSWD_FILE_DEFAULT_SCHEME;
	return &module->module;
}

static void passwd_file_init(struct passdb_module *_module, const char *args)
{
	struct passwd_file_passdb_module *module =
		(struct passwd_file_passdb_module *)_module;

	module->pwf =
		db_passwd_file_parse(args, FALSE, module->auth->verbose_debug);
}

static void passwd_file_deinit(struct passdb_module *_module)
{
	struct passwd_file_passdb_module *module =
		(struct passwd_file_passdb_module *)_module;

	db_passwd_file_unref(&module->pwf);
}

struct passdb_module_interface passdb_passwd_file = {
	"passwd-file",

	passwd_file_preinit,
	passwd_file_init,
	passwd_file_deinit,

	passwd_file_verify_plain,
	passwd_file_lookup_credentials
};

#endif