userdb {
driver = ldap
args = /etc/dovecot/dovecot-ldap.conf.ext
+
+ # Default fields can be used to specify defaults that LDAP may override
+ #default_fields = home=/home/virtual/%u
}
# If you don't have any user-specific settings, you can avoid the userdb LDAP
userdb {
driver = passwd-file
args = username_format=%u /etc/dovecot/users
+
+ # Default fields that can be overridden by passwd-file
+ #default_fields = quota_rule=*:storage=1G
+
+ # Override fields from passwd-file
+ #override_fields = home=/home/virtual/%u
}
driver = passwd
# [blocking=no]
#args =
+
+ # Override fields from passwd
+ #override_fields = home=/home/virtual/%u
}
# Static settings generated from template <doc/wiki/UserDatabase.Static.txt>
passdb-vpopmail.c \
passdb-sql.c \
passdb-static.c \
+ passdb-template.c \
userdb.c \
userdb-blocking.c \
userdb-checkpassword.c \
userdb-static.c \
userdb-vpopmail.c \
userdb-sql.c \
+ userdb-template.c \
$(ldap_sources)
headers = \
passdb.h \
passdb-blocking.h \
passdb-cache.h \
+ passdb-template.h \
password-scheme.h \
userdb.h \
userdb-blocking.h \
- userdb-static.h \
+ userdb-template.h \
userdb-vpopmail.h
if GSSAPI_PLUGIN
#include "auth-master-connection.h"
#include "passdb.h"
#include "passdb-blocking.h"
-#include "userdb-blocking.h"
#include "passdb-cache.h"
+#include "passdb-template.h"
+#include "userdb-blocking.h"
+#include "userdb-template.h"
#include "password-scheme.h"
#include <stdlib.h>
void auth_request_verify_plain_callback(enum passdb_result result,
struct auth_request *request)
{
+ struct passdb_module *passdb = request->passdb->passdb;
+
i_assert(request->state == AUTH_REQUEST_STATE_PASSDB);
auth_request_set_state(request, AUTH_REQUEST_STATE_MECH_CONTINUE);
- if (result != PASSDB_RESULT_INTERNAL_FAILURE)
+ if (result != PASSDB_RESULT_INTERNAL_FAILURE) {
+ passdb_template_export(passdb->override_fields_tmpl, request);
auth_request_save_cache(request, result);
- else {
+ } else {
/* lookup failed. if we're looking here only because the
request was expired in cache, fallback to using cached
expired record. */
- const char *cache_key = request->passdb->passdb->cache_key;
+ const char *cache_key = passdb->cache_key;
if (passdb_cache_verify_plain(request, cache_key,
request->mech_password,
} else if (passdb->blocking) {
passdb_blocking_verify_plain(request);
} else if (passdb->iface.verify_plain != NULL) {
+ passdb_template_export(passdb->default_fields_tmpl, request);
passdb->iface.verify_plain(request, password,
auth_request_verify_plain_callback);
}
size_t size,
struct auth_request *request)
{
+ struct passdb_module *passdb = request->passdb->passdb;
const char *cache_cred, *cache_scheme;
i_assert(request->state == AUTH_REQUEST_STATE_PASSDB);
auth_request_set_state(request, AUTH_REQUEST_STATE_MECH_CONTINUE);
- if (result != PASSDB_RESULT_INTERNAL_FAILURE)
+ if (result != PASSDB_RESULT_INTERNAL_FAILURE) {
+ passdb_template_export(passdb->override_fields_tmpl, request);
auth_request_save_cache(request, result);
- else {
+ } else {
/* lookup failed. if we're looking here only because the
request was expired in cache, fallback to using cached
expired record. */
- const char *cache_key = request->passdb->passdb->cache_key;
+ const char *cache_key = passdb->cache_key;
if (passdb_cache_lookup_credentials(request, cache_key,
&cache_cred, &cache_scheme,
} else if (passdb->blocking) {
passdb_blocking_lookup_credentials(request);
} else {
+ passdb_template_export(passdb->default_fields_tmpl, request);
passdb->iface.lookup_credentials(request,
auth_request_lookup_credentials_callback);
}
return;
}
- if (request->userdb_internal_failure && result != USERDB_RESULT_OK) {
+ if (result == USERDB_RESULT_OK)
+ userdb_template_export(userdb->override_fields_tmpl, request);
+ else if (request->userdb_internal_failure) {
/* one of the userdb lookups failed. the user might have been
in there, so this is an internal failure */
result = USERDB_RESULT_INTERNAL_FAILURE;
void auth_request_init_userdb_reply(struct auth_request *request)
{
+ struct userdb_module *module = request->userdb->userdb;
+
request->userdb_reply = auth_stream_reply_init(request->pool);
auth_stream_reply_add(request->userdb_reply, NULL, request->user);
+
+ userdb_template_export(module->default_fields_tmpl, request);
}
static void auth_request_set_uidgid_file(struct auth_request *request,
return;
} else if (strcmp(name, "system_user") == 0) {
/* FIXME: the system_user is for backwards compatibility */
+ static bool warned = FALSE;
+ if (!warned) {
+ i_warning("userdb: Replace system_user with system_groups_user");
+ warned = TRUE;
+ }
name = "system_groups_user";
}
static const struct setting_define auth_passdb_setting_defines[] = {
DEF(SET_STR, driver),
DEF(SET_STR, args),
+ DEF(SET_STR, default_fields),
+ DEF(SET_STR, override_fields),
DEF(SET_BOOL, deny),
DEF(SET_BOOL, pass),
DEF(SET_BOOL, master),
static const struct auth_passdb_settings auth_passdb_default_settings = {
.driver = "",
.args = "",
+ .default_fields = "",
+ .override_fields = "",
.deny = FALSE,
.pass = FALSE,
.master = FALSE
static const struct setting_define auth_userdb_setting_defines[] = {
DEF(SET_STR, driver),
DEF(SET_STR, args),
+ DEF(SET_STR, default_fields),
+ DEF(SET_STR, override_fields),
SETTING_DEFINE_LIST_END
};
static const struct auth_userdb_settings auth_userdb_default_settings = {
.driver = "",
- .args = ""
+ .args = "",
+ .default_fields = "",
+ .override_fields = ""
};
const struct setting_parser_info auth_userdb_setting_parser_info = {
struct auth_passdb_settings {
const char *driver;
const char *args;
+ const char *default_fields;
+ const char *override_fields;
bool deny;
bool pass;
bool master;
struct auth_userdb_settings {
const char *driver;
const char *args;
+ const char *default_fields;
+ const char *override_fields;
};
struct auth_settings {
for (dest = passdbs; *dest != NULL; dest = &(*dest)->next) ;
*dest = auth_passdb;
- auth_passdb->passdb =
- passdb_preinit(auth->pool, set->driver, set->args);
+ auth_passdb->passdb = passdb_preinit(auth->pool, set);
}
static void
for (dest = &auth->userdbs; *dest != NULL; dest = &(*dest)->next) ;
*dest = auth_userdb;
- auth_userdb->userdb =
- userdb_preinit(auth->pool, set->driver, set->args);
+ auth_userdb->userdb = userdb_preinit(auth->pool, set);
}
static struct auth *
#include "str.h"
#include "var-expand.h"
#include "passdb.h"
-
-#define STATIC_PASS_SCHEME "PLAIN"
+#include "passdb-template.h"
struct static_passdb_module {
struct passdb_module module;
- ARRAY_TYPE(const_string) tmpl;
+ struct passdb_template *tmpl;
+ const char *static_password_tmpl;
};
static void
struct static_passdb_module *module =
(struct static_passdb_module *)request->passdb->passdb;
const struct var_expand_table *table;
- const char *const *args;
- unsigned int i, count;
string_t *str = t_str_new(128);
auth_request_log_debug(request, "static", "lookup");
+ passdb_template_export(module->tmpl, request);
table = auth_request_get_var_expand_table(request, NULL);
-
- *password_r = "";
- args = array_get(&module->tmpl, &count);
- i_assert((count % 2) == 0);
- for (i = 0; i < count; i += 2) {
- const char *key = args[i];
- const char *value = args[i+1];
-
- if (value != NULL) {
- str_truncate(str, 0);
- var_expand(str, args[i+1], table);
- value = str_c(str);
- }
-
- if (strcmp(key, "password") == 0)
- *password_r = value;
- else {
- auth_request_set_field(request, key, value,
- STATIC_PASS_SCHEME);
- }
- }
+ var_expand(str, module->static_password_tmpl, table);
+ *password_r = str_c(str);
}
static void
static_preinit(pool_t pool, const char *args)
{
struct static_passdb_module *module;
+ const char *value;
module = p_new(pool, struct static_passdb_module, 1);
- p_array_init(&module->tmpl, pool, 16);
- T_BEGIN {
- const char *const *tmp;
-
- tmp = t_strsplit_spaces(args, " ");
- for (; *tmp != NULL; tmp++) {
- const char *key = *tmp;
- const char *value = strchr(key, '=');
-
- if (value == NULL)
- value = "";
- else
- key = t_strdup_until(key, value++);
-
- key = p_strdup(pool, key);
- value = p_strdup(pool, value);
- array_append(&module->tmpl, &key, 1);
- array_append(&module->tmpl, &value, 1);
- }
- } T_END;
+ module->tmpl = passdb_template_build(pool, args);
+
+ if (passdb_template_remove(module->tmpl, "password", &value))
+ module->static_password_tmpl = value;
return &module->module;
}
#include "array.h"
#include "password-scheme.h"
#include "auth-worker-server.h"
+#include "passdb-template.h"
#include "passdb.h"
#include <stdlib.h>
}
struct passdb_module *
-passdb_preinit(pool_t pool, const char *driver, const char *args)
+passdb_preinit(pool_t pool, const struct auth_passdb_settings *set)
{
static unsigned int auth_passdb_id = 0;
struct passdb_module_interface *iface;
struct passdb_module *passdb;
unsigned int idx;
- iface = passdb_interface_find(driver);
+ iface = passdb_interface_find(set->driver);
if (iface == NULL)
- i_fatal("Unknown passdb driver '%s'", driver);
+ i_fatal("Unknown passdb driver '%s'", set->driver);
if (iface->verify_plain == NULL) {
i_fatal("Support not compiled in for passdb driver '%s'",
- driver);
+ set->driver);
+ }
+ if (iface->preinit == NULL && iface->init == NULL &&
+ *set->args != '\0') {
+ i_fatal("passdb %s: No args are supported: %s",
+ set->driver, set->args);
}
- if (iface->preinit == NULL && iface->init == NULL && *args != '\0')
- i_fatal("passdb %s: No args are supported: %s", driver, args);
- passdb = passdb_find(driver, args, &idx);
+ passdb = passdb_find(set->driver, set->args, &idx);
if (passdb != NULL)
return passdb;
if (iface->preinit == NULL)
passdb = p_new(pool, struct passdb_module, 1);
else
- passdb = iface->preinit(pool, args);
+ passdb = iface->preinit(pool, set->args);
passdb->id = ++auth_passdb_id;
passdb->iface = *iface;
- passdb->args = p_strdup(pool, args);
+ passdb->args = p_strdup(pool, set->args);
+
+ passdb->default_fields_tmpl =
+ passdb_template_build(pool, set->default_fields);
+ passdb->override_fields_tmpl =
+ passdb_template_build(pool, set->override_fields);
+
array_append(&passdb_modules, &passdb, 1);
return passdb;
}
((pass)[0] != '\0' && (pass)[0] != '*' && (pass)[0] != '!')
struct auth_request;
+struct auth_passdb_settings;
enum passdb_result {
PASSDB_RESULT_INTERNAL_FAILURE = -1,
/* number of time init() has been called */
int init_refcount;
+ struct passdb_template *default_fields_tmpl;
+ struct passdb_template *override_fields_tmpl;
+
struct passdb_module_interface iface;
};
struct auth_request *auth_request);
struct passdb_module *
-passdb_preinit(pool_t pool, const char *driver, const char *args);
+passdb_preinit(pool_t pool, const struct auth_passdb_settings *set);
void passdb_init(struct passdb_module *passdb);
void passdb_deinit(struct passdb_module *passdb);
#include "ioloop.h"
#include "ipwd.h"
-#include "userdb-static.h"
+#include "userdb-template.h"
#define USER_CACHE_KEY "%u"
struct passwd_userdb_module {
struct userdb_module module;
- struct userdb_static_template *tmpl;
+ struct userdb_template *tmpl;
};
struct passwd_userdb_iterate_context {
auth_request_set_field(auth_request, "user", pw.pw_name, NULL);
auth_request_init_userdb_reply(auth_request);
- userdb_static_template_export(module->tmpl, auth_request);
-
- /* FIXME: the system_user is for backwards compatibility */
- if (!userdb_static_template_isset(module->tmpl, "system_groups_user") &&
- !userdb_static_template_isset(module->tmpl, "system_user")) {
- auth_request_set_userdb_field(auth_request,
- "system_groups_user",
- pw.pw_name);
- }
- if (!userdb_static_template_isset(module->tmpl, "uid")) {
- auth_request_set_userdb_field(auth_request,
- "uid", dec2str(pw.pw_uid));
- }
- if (!userdb_static_template_isset(module->tmpl, "gid")) {
- auth_request_set_userdb_field(auth_request,
- "gid", dec2str(pw.pw_gid));
- }
- if (!userdb_static_template_isset(module->tmpl, "home"))
- auth_request_set_userdb_field(auth_request, "home", pw.pw_dir);
+ auth_request_set_userdb_field(auth_request, "system_groups_user",
+ pw.pw_name);
+ auth_request_set_userdb_field(auth_request, "uid", dec2str(pw.pw_uid));
+ auth_request_set_userdb_field(auth_request, "gid", dec2str(pw.pw_gid));
+ auth_request_set_userdb_field(auth_request, "home", pw.pw_dir);
+
+ userdb_template_export(module->tmpl, auth_request);
callback(USERDB_RESULT_OK, auth_request);
}
module = p_new(pool, struct passwd_userdb_module, 1);
module->module.cache_key = USER_CACHE_KEY;
- module->tmpl = userdb_static_template_build(pool, "passwd", args);
+ module->tmpl = userdb_template_build(pool, "passwd", args);
- if (userdb_static_template_remove(module->tmpl, "blocking",
- &value)) {
+ if (userdb_template_remove(module->tmpl, "blocking", &value)) {
module->module.blocking = value == NULL ||
strcasecmp(value, "yes") == 0;
}
+ /* FIXME: backwards compatibility */
+ if (!userdb_template_is_empty(module->tmpl))
+ i_warning("userdb passwd: Move templates args to override_fields setting");
return &module->module;
}
#include "str.h"
#include "var-expand.h"
#include "userdb.h"
-#include "userdb-static.h"
+#include "userdb-template.h"
#include <stdlib.h>
-struct userdb_static_template {
- ARRAY_DEFINE(args, const char *);
-};
-
-struct userdb_static_template *
-userdb_static_template_build(pool_t pool, const char *userdb_name,
- const char *args)
-{
- struct userdb_static_template *tmpl;
- const char *const *tmp, *key, *value;
- uid_t uid;
- gid_t gid;
-
- tmpl = p_new(pool, struct userdb_static_template, 1);
-
- tmp = t_strsplit_spaces(args, " ");
- p_array_init(&tmpl->args, pool, str_array_length(tmp));
-
- for (; *tmp != NULL; tmp++) {
- value = strchr(*tmp, '=');
- if (value == NULL)
- key = *tmp;
- else {
- key = t_strdup_until(*tmp, value);
- value++;
- }
-
- if (strcasecmp(key, "uid") == 0) {
- uid = userdb_parse_uid(NULL, value);
- if (uid == (uid_t)-1) {
- i_fatal("%s userdb: Invalid uid: %s",
- userdb_name, value);
- }
- value = dec2str(uid);
- } else if (strcasecmp(key, "gid") == 0) {
- gid = userdb_parse_gid(NULL, value);
- if (gid == (gid_t)-1) {
- i_fatal("%s userdb: Invalid gid: %s",
- userdb_name, value);
- }
- value = dec2str(gid);
- } else if (*key == '\0') {
- i_fatal("%s userdb: Empty key (=%s)",
- userdb_name, value);
- }
- key = p_strdup(pool, key);
- value = p_strdup(pool, value);
-
- array_append(&tmpl->args, &key, 1);
- array_append(&tmpl->args, &value, 1);
- }
- return tmpl;
-}
-
-bool userdb_static_template_isset(struct userdb_static_template *tmpl,
- const char *key)
-{
- const char *const *args;
- unsigned int i, count;
-
- args = array_get(&tmpl->args, &count);
- i_assert((count % 2) == 0);
- for (i = 0; i < count; i += 2) {
- if (strcmp(args[i], key) == 0)
- return TRUE;
- }
- return FALSE;
-}
-
-bool userdb_static_template_remove(struct userdb_static_template *tmpl,
- const char *key, const char **value_r)
-{
- const char *const *args;
- unsigned int i, count;
-
- args = array_get(&tmpl->args, &count);
- i_assert((count % 2) == 0);
- for (i = 0; i < count; i += 2) {
- if (strcmp(args[i], key) == 0) {
- *value_r = args[i+1];
- array_delete(&tmpl->args, i, 2);
- return TRUE;
- }
- }
- return FALSE;
-}
-
-void userdb_static_template_export(struct userdb_static_template *tmpl,
- struct auth_request *auth_request)
-{
- const struct var_expand_table *table;
- string_t *str;
- const char *const *args, *value;
- unsigned int i, count;
-
- str = t_str_new(256);
- table = auth_request_get_var_expand_table(auth_request, NULL);
-
- args = array_get(&tmpl->args, &count);
- i_assert((count % 2) == 0);
- for (i = 0; i < count; i += 2) {
- if (args[i+1] == NULL)
- value = NULL;
- else {
- str_truncate(str, 0);
- var_expand(str, args[i+1], table);
- value = str_c(str);
- }
- auth_request_set_userdb_field(auth_request, args[i], value);
- }
-}
-
struct static_context {
userdb_callback_t *callback, *old_callback;
void *old_context;
struct static_userdb_module {
struct userdb_module module;
- struct userdb_static_template *tmpl;
+ struct userdb_template *tmpl;
unsigned int allow_all_users:1;
};
(struct static_userdb_module *)_module;
auth_request_init_userdb_reply(auth_request);
- userdb_static_template_export(module->tmpl, auth_request);
+ userdb_template_export(module->tmpl, auth_request);
callback(USERDB_RESULT_OK, auth_request);
}
const char *value;
module = p_new(pool, struct static_userdb_module, 1);
- module->tmpl = userdb_static_template_build(pool, "static", args);
+ module->tmpl = userdb_template_build(pool, "static", args);
- if (userdb_static_template_remove(module->tmpl, "allow_all_users",
- &value)) {
+ if (userdb_template_remove(module->tmpl, "allow_all_users", &value)) {
module->allow_all_users = value == NULL ||
strcasecmp(value, "yes") == 0;
}
+++ /dev/null
-#ifndef USERDB_STATIC_H
-#define USERDB_STATIC_H
-
-struct userdb_static_template *
-userdb_static_template_build(pool_t pool, const char *userdb_name,
- const char *args);
-bool userdb_static_template_isset(struct userdb_static_template *tmpl,
- const char *key);
-bool userdb_static_template_remove(struct userdb_static_template *tmpl,
- const char *key, const char **value_r);
-void userdb_static_template_export(struct userdb_static_template *tmpl,
- struct auth_request *auth_request);
-
-#endif
#include "array.h"
#include "ipwd.h"
#include "auth-worker-server.h"
+#include "userdb-template.h"
#include "userdb.h"
#include <stdlib.h>
}
struct userdb_module *
-userdb_preinit(pool_t pool, const char *driver, const char *args)
+userdb_preinit(pool_t pool, const struct auth_userdb_settings *set)
{
static unsigned int auth_userdb_id = 0;
struct userdb_module_interface *iface;
struct userdb_module *userdb;
unsigned int idx;
- iface = userdb_interface_find(driver);
+ iface = userdb_interface_find(set->driver);
if (iface == NULL)
- i_fatal("Unknown userdb driver '%s'", driver);
+ i_fatal("Unknown userdb driver '%s'", set->driver);
if (iface->lookup == NULL) {
i_fatal("Support not compiled in for userdb driver '%s'",
- driver);
+ set->driver);
+ }
+ if (iface->preinit == NULL && iface->init == NULL &&
+ *set->args != '\0') {
+ i_fatal("userdb %s: No args are supported: %s",
+ set->driver, set->args);
}
- if (iface->preinit == NULL && iface->init == NULL && *args != '\0')
- i_fatal("userdb %s: No args are supported: %s", driver, args);
- userdb = userdb_find(driver, args, &idx);
+ userdb = userdb_find(set->driver, set->args, &idx);
if (userdb != NULL)
return userdb;
if (iface->preinit == NULL)
userdb = p_new(pool, struct userdb_module, 1);
else
- userdb = iface->preinit(pool, args);
+ userdb = iface->preinit(pool, set->args);
userdb->id = ++auth_userdb_id;
userdb->iface = iface;
- userdb->args = p_strdup(pool, args);
+ userdb->args = p_strdup(pool, set->args);
+
+ userdb->default_fields_tmpl =
+ userdb_template_build(pool, set->driver,
+ set->default_fields);
+ userdb->override_fields_tmpl =
+ userdb_template_build(pool, set->driver,
+ set->override_fields);
+
array_append(&userdb_modules, &userdb, 1);
return userdb;
}
struct auth;
struct auth_request;
+struct auth_userdb_settings;
enum userdb_result {
USERDB_RESULT_INTERNAL_FAILURE = -1,
/* number of time init() has been called */
int init_refcount;
+ struct userdb_template *default_fields_tmpl;
+ struct userdb_template *override_fields_tmpl;
+
const struct userdb_module_interface *iface;
};
gid_t userdb_parse_gid(struct auth_request *request, const char *str);
struct userdb_module *
-userdb_preinit(pool_t pool, const char *driver, const char *args);
+userdb_preinit(pool_t pool, const struct auth_userdb_settings *set);
void userdb_init(struct userdb_module *userdb);
void userdb_deinit(struct userdb_module *userdb);