dovecot-2.2: auth: passdb/userdb dict rewrite to support more co...
dovecot at dovecot.org
dovecot at dovecot.org
Sun Dec 8 19:01:09 EET 2013
details: http://hg.dovecot.org/dovecot-2.2/rev/d2ad697ba810
changeset: 17040:d2ad697ba810
user: Timo Sirainen <tss at iki.fi>
date: Sun Dec 08 19:00:31 2013 +0200
description:
auth: passdb/userdb dict rewrite to support more complex configuration.
See the new doc/example-config/dovecot-dict-auth.conf.ext for explanation
how it works. The old configuration format will also stay functional.
diffstat:
doc/example-config/dovecot-dict-auth.conf.ext | 56 ++-
src/auth/Makefile.am | 8 +-
src/auth/db-dict-cache-key.c | 65 +++
src/auth/db-dict.c | 526 +++++++++++++++++++++++--
src/auth/db-dict.h | 57 ++-
src/auth/passdb-dict.c | 49 +-
src/auth/test-db-dict.c | 51 ++
src/auth/userdb-dict.c | 42 +-
8 files changed, 731 insertions(+), 123 deletions(-)
diffs (truncated from 1134 to 300 lines):
diff -r 342f6962390e -r d2ad697ba810 doc/example-config/dovecot-dict-auth.conf.ext
--- a/doc/example-config/dovecot-dict-auth.conf.ext Tue Dec 03 21:31:59 2013 +0200
+++ b/doc/example-config/dovecot-dict-auth.conf.ext Sun Dec 08 19:00:31 2013 +0200
@@ -1,24 +1,54 @@
-# This file is commonly accessed via dict {} section in dovecot.conf
+# This file is commonly accessed via passdb {} or userdb {} section in
+# conf.d/auth-dict.conf.ext
# Dictionary URI
#uri =
-# Key for passdb lookups
-password_key = dovecot/passdb/%u
-
-# Key for userdb lookups
-user_key = dovecot/userdb/%u
-
-# How to parse the value for key=value pairs. Currently we support only JSON
-# format with { "key": "value", ... } object.
-#value_format = json
+# Default password scheme
+default_pass_scheme = MD5
# Username iteration prefix. Keys under this are assumed to contain usernames.
-iterate_prefix = dovecot/userdb/
+iterate_prefix = userdb/
# Should iteration be disabled for this userdb? If this userdb acts only as a
# cache there's no reason to try to iterate the (partial & duplicate) users.
#iterate_disable = no
-# Default password scheme
-default_pass_scheme = MD5
+# The example here shows how to do multiple dict lookups and merge the replies.
+# The "passdb" and "userdb" keys are JSON objects containing key/value pairs,
+# for example: { "uid": 1000, "gid": 1000, "home": "/home/user" }
+
+key passdb {
+ key = passdb/%u
+ format = json
+}
+key userdb {
+ key = userdb/%u
+ format = json
+}
+key quota {
+ key = userdb/%u/quota
+ #format = value
+ # The default_value is used if the key isn't found. If default_value setting
+ # isn't specified at all (even as empty), the passdb/userdb lookup fails with
+ # "user doesn't exist".
+ default_value = 100M
+}
+
+# Space separated list of keys whose values contain key/value paired objects.
+# All the key/value pairs inside the object are added as passdb fields.
+passdb_objects = passdb
+
+#passdb_fields {
+#}
+
+# Userdb key/value object list.
+userdb_objects = userdb
+
+userdb_fields {
+ # dict:<key> refers to key names
+ quota_rule = *:storage=%{dict:quota}
+
+ # dict:<key>.<objkey> refers to the objkey inside (JSON) object
+ mail = maildir:%{dict:userdb.home}/Maildir
+}
diff -r 342f6962390e -r d2ad697ba810 src/auth/Makefile.am
--- a/src/auth/Makefile.am Tue Dec 03 21:31:59 2013 +0200
+++ b/src/auth/Makefile.am Sun Dec 08 19:00:31 2013 +0200
@@ -77,6 +77,7 @@
auth-worker-server.c \
db-checkpassword.c \
db-dict.c \
+ db-dict-cache-key.c \
db-sql.c \
db-passwd-file.c \
main.c \
@@ -193,7 +194,8 @@
checkpassword-reply.c
test_programs = \
- test-auth-cache
+ test-auth-cache \
+ test-db-dict
noinst_PROGRAMS = $(test_programs)
@@ -205,6 +207,10 @@
test_auth_cache_LDADD = auth-cache.o $(test_libs)
test_auth_cache_DEPENDENCIES = $(pkglibexec_PROGRAMS) $(test_libs)
+test_db_dict_SOURCES = test-db-dict.c
+test_db_dict_LDADD = db-dict-cache-key.o $(test_libs)
+test_db_dict_DEPENDENCIES = $(pkglibexec_PROGRAMS) $(test_libs)
+
check: check-am check-test
check-test: all-am
for bin in $(test_programs); do \
diff -r 342f6962390e -r d2ad697ba810 src/auth/db-dict-cache-key.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/auth/db-dict-cache-key.c Sun Dec 08 19:00:31 2013 +0200
@@ -0,0 +1,65 @@
+/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
+
+#include "auth-common.h"
+#include "array.h"
+#include "str.h"
+#include "var-expand.h"
+#include "db-dict.h"
+
+const struct db_dict_key *
+db_dict_set_key_find(const ARRAY_TYPE(db_dict_key) *keys, const char *name)
+{
+ const struct db_dict_key *key;
+
+ array_foreach(keys, key) {
+ if (strcmp(key->name, name) == 0)
+ return key;
+ }
+ return NULL;
+}
+
+
+const char *
+db_dict_parse_cache_key(const ARRAY_TYPE(db_dict_key) *keys,
+ const ARRAY_TYPE(db_dict_field) *fields,
+ const ARRAY_TYPE(db_dict_key_p) *objects)
+{
+ const struct db_dict_field *field;
+ const struct db_dict_key *key;
+ const struct db_dict_key *const *keyp;
+ const char *p, *name;
+ unsigned int idx, size;
+ string_t *str = t_str_new(128);
+
+ array_foreach(fields, field) {
+ for (p = field->value; *p != '\0'; ) {
+ if (*p != '%') {
+ p++;
+ continue;
+ }
+
+ var_get_key_range(++p, &idx, &size);
+ if (size == 0) {
+ /* broken %variable ending too early */
+ break;
+ }
+ p += idx;
+ if (size > 5 && memcmp(p, "dict:", 5) == 0) {
+ name = t_strcut(t_strndup(p+5, size-5), ':');
+ key = db_dict_set_key_find(keys, name);
+ if (key != NULL)
+ str_printfa(str, "\t%s", key->key);
+ } else if (size == 1) {
+ str_printfa(str, "\t%%%c", p[0]);
+ } else {
+ str_append(str, "\t%{");
+ str_append_n(str, p, size);
+ str_append_c(str, '}');
+ }
+ p += size;
+ }
+ }
+ array_foreach(objects, keyp)
+ str_printfa(str, "\t%s", (*keyp)->key);
+ return str_c(str);
+}
diff -r 342f6962390e -r d2ad697ba810 src/auth/db-dict.c
--- a/src/auth/db-dict.c Tue Dec 03 21:31:59 2013 +0200
+++ b/src/auth/db-dict.c Sun Dec 08 19:00:31 2013 +0200
@@ -2,11 +2,12 @@
#include "auth-common.h"
+#include "array.h"
+#include "istream.h"
+#include "str.h"
+#include "json-parser.h"
#include "settings.h"
#include "dict.h"
-#include "json-parser.h"
-#include "istream.h"
-#include "str.h"
#include "auth-request.h"
#include "auth-worker-client.h"
#include "db-dict.h"
@@ -14,29 +15,80 @@
#include <stddef.h>
#include <stdlib.h>
+enum dict_settings_section {
+ DICT_SETTINGS_SECTION_ROOT = 0,
+ DICT_SETTINGS_SECTION_KEY,
+ DICT_SETTINGS_SECTION_PASSDB,
+ DICT_SETTINGS_SECTION_USERDB
+};
+
+struct dict_settings_parser_ctx {
+ struct dict_connection *conn;
+ enum dict_settings_section section;
+ struct db_dict_key *cur_key;
+};
+
+struct db_dict_iter_key {
+ const struct db_dict_key *key;
+ bool used;
+ const char *value;
+};
+
+struct db_dict_value_iter {
+ pool_t pool;
+ struct auth_request *auth_request;
+ struct dict_connection *conn;
+ const struct var_expand_table *var_expand_table;
+ ARRAY(struct db_dict_iter_key) keys;
+
+ const ARRAY_TYPE(db_dict_field) *fields;
+ const ARRAY_TYPE(db_dict_key_p) *objects;
+ unsigned int field_idx;
+ unsigned int object_idx;
+
+ struct json_parser *json_parser;
+ string_t *tmpstr;
+ const char *error;
+};
+
#define DEF_STR(name) DEF_STRUCT_STR(name, db_dict_settings)
#define DEF_BOOL(name) DEF_STRUCT_BOOL(name, db_dict_settings)
-
static struct setting_def setting_defs[] = {
DEF_STR(uri),
- DEF_STR(password_key),
- DEF_STR(user_key),
+ DEF_STR(default_pass_scheme),
DEF_STR(iterate_prefix),
- DEF_STR(value_format),
DEF_BOOL(iterate_disable),
- DEF_STR(default_pass_scheme),
+ DEF_STR(passdb_objects),
+ DEF_STR(userdb_objects),
{ 0, NULL, 0 }
};
static struct db_dict_settings default_dict_settings = {
.uri = NULL,
- .password_key = "",
- .user_key = "",
+ .default_pass_scheme = "MD5",
.iterate_prefix = "",
.iterate_disable = FALSE,
- .value_format = "json",
- .default_pass_scheme = "MD5"
+ .passdb_objects = "",
+ .userdb_objects = ""
+};
+
+#undef DEF_STR
+#define DEF_STR(name) DEF_STRUCT_STR(name, db_dict_key)
+static struct setting_def key_setting_defs[] = {
+ DEF_STR(name),
+ DEF_STR(key),
+ DEF_STR(format),
+ DEF_STR(default_value),
+
+ { 0, NULL, 0 }
+};
+
+static struct db_dict_key default_key_settings = {
+ .name = NULL,
+ .key = "",
+ .format = "value",
+ .default_value = NULL
};
static struct dict_connection *connections = NULL;
@@ -53,15 +105,167 @@
return NULL;
}
+static bool
+parse_obsolete_setting(const char *key, const char *value,
+ struct dict_settings_parser_ctx *ctx,
+ const char **error_r)
+{
+ const struct db_dict_key *dbkey;
+
+ if (strcmp(key, "password_key") == 0) {
+ /* key passdb { key=<value> format=json }
+ passdb_objects = passdb */
+ ctx->cur_key = array_append_space(&ctx->conn->set.keys);
+ *ctx->cur_key = default_key_settings;
+ ctx->cur_key->name = "passdb";
+ ctx->cur_key->format = "json";
+ ctx->cur_key->parsed_format = DB_DICT_VALUE_FORMAT_JSON;
More information about the dovecot-cvs
mailing list