]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
auth: ldap - Read settings from main config
authorMarco Bettini <marco.bettini@open-xchange.com>
Fri, 15 Mar 2024 09:31:44 +0000 (09:31 +0000)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Wed, 12 Feb 2025 10:34:13 +0000 (12:34 +0200)
src/auth/db-ldap-settings.c
src/auth/db-ldap-settings.h
src/auth/db-ldap.c
src/auth/db-ldap.h
src/auth/passdb-ldap.c
src/auth/userdb-ldap.c

index cdb7d3daeb3f7f00f5cd1e57dd65a9ac0e9a3f52..9b7d476984725461f3c5815d68f39dbf1dc7b4f7 100644 (file)
@@ -4,72 +4,75 @@
 #include "settings.h"
 #include "db-ldap-settings.h"
 
+/* <settings checks> */
+
+#include "ldap.h"
+static bool ldap_setting_check(void *_set, pool_t pool, const char **error_r);
+
+/* </settings checks> */
+
 #undef DEF
-/*
 #define DEF(type, name) \
-       SETTING_DEFINE_STRUCT_##type("passdb_"#name, name, struct auth_passdb_settings)
-*/
-#define DEF_STR(name) DEF_STRUCT_STR(name, ldap_settings)
-#define DEF_INT(name) DEF_STRUCT_INT(name, ldap_settings)
-#define DEF_BOOL(name) DEF_STRUCT_BOOL(name, ldap_settings)
-
-static struct setting_def ldap_setting_defs[] = {
-       DEF_STR(hosts),
-       DEF_STR(uris),
-       DEF_STR(dn),
-       DEF_STR(dnpass),
-       DEF_BOOL(auth_bind),
-       DEF_STR(auth_bind_userdn),
-       DEF_BOOL(tls),
-       DEF_BOOL(sasl_bind),
-       DEF_STR(sasl_mech),
-       DEF_STR(sasl_realm),
-       DEF_STR(sasl_authz_id),
-       DEF_STR(tls_ca_cert_file),
-       DEF_STR(tls_ca_cert_dir),
-       DEF_STR(tls_cert_file),
-       DEF_STR(tls_key_file),
-       DEF_STR(tls_cipher_suite),
-       DEF_STR(tls_require_cert),
-       DEF_STR(deref),
-       DEF_STR(scope),
-       DEF_STR(base),
-       DEF_INT(ldap_version),
-       DEF_STR(debug_level),
-       DEF_STR(ldaprc_path),
-       DEF_STR(user_attrs),
-       DEF_STR(user_filter),
-       DEF_STR(pass_attrs),
-       DEF_STR(pass_filter),
-       DEF_STR(iterate_attrs),
-       DEF_STR(iterate_filter),
-       DEF_STR(default_pass_scheme),
-       DEF_BOOL(blocking),
-
-       { 0, NULL, 0 }
+       SETTING_DEFINE_STRUCT_##type("ldap_"#name, name, struct ldap_settings)
+
+static const struct setting_define ldap_setting_defines[] = {
+       { .type = SET_FILTER_NAME, .key = "passdb_ldap", },
+       { .type = SET_FILTER_NAME, .key = "userdb_ldap", },
+       DEF(STR, hosts),
+       DEF(STR, uris),
+       DEF(STR, dn),
+       DEF(STR, dnpass),
+       DEF(BOOL, auth_bind),
+       DEF(STR, auth_bind_userdn),
+       DEF(BOOL, tls),
+       DEF(BOOL, sasl_bind),
+       DEF(STR, sasl_mech),
+       DEF(STR, sasl_realm),
+       DEF(STR, sasl_authz_id),
+       DEF(STR, tls_ca_cert_file),
+       DEF(STR, tls_ca_cert_dir),
+       DEF(STR, tls_cert_file),
+       DEF(STR, tls_key_file),
+       DEF(STR, tls_cipher_suite),
+       DEF(STR, tls_require_cert),
+       DEF(STR, deref),
+       DEF(STR, scope),
+       DEF(STR, base),
+       DEF(UINT, ldap_version),
+       DEF(STR, debug_level),
+       DEF(STR, ldaprc_path),
+       DEF(STR, user_attrs),
+       DEF(STR, user_filter),
+       DEF(STR, pass_attrs),
+       DEF(STR, pass_filter),
+       DEF(STR, iterate_attrs),
+       DEF(STR, iterate_filter),
+       DEF(STR, default_pass_scheme),
+       DEF(BOOL, blocking),
+       SETTING_DEFINE_LIST_END
 };
 
-static struct ldap_settings ldap_default_settings = {
-       .hosts = NULL,
-       .uris = NULL,
-       .dn = NULL,
-       .dnpass = NULL,
+static const struct ldap_settings ldap_default_settings = {
+       .hosts = "",
+       .uris = "",
+       .dn = "",
+       .dnpass = "",
        .auth_bind = FALSE,
-       .auth_bind_userdn = NULL,
+       .auth_bind_userdn = "",
        .tls = FALSE,
        .sasl_bind = FALSE,
-       .sasl_mech = NULL,
-       .sasl_realm = NULL,
-       .sasl_authz_id = NULL,
-       .tls_ca_cert_file = NULL,
-       .tls_ca_cert_dir = NULL,
-       .tls_cert_file = NULL,
-       .tls_key_file = NULL,
-       .tls_cipher_suite = NULL,
-       .tls_require_cert = NULL,
+       .sasl_mech = "",
+       .sasl_realm = "",
+       .sasl_authz_id = "",
+       .tls_ca_cert_file = "",
+       .tls_ca_cert_dir = "",
+       .tls_cert_file = "",
+       .tls_key_file = "",
+       .tls_cipher_suite = "",
+       .tls_require_cert = "",
        .deref = "never",
        .scope = "subtree",
-       .base = NULL,
+       .base = "",
        .ldap_version = 3,
        .debug_level = "0",
        .ldaprc_path = "",
@@ -82,3 +85,94 @@ static struct ldap_settings ldap_default_settings = {
        .default_pass_scheme = "crypt",
        .blocking = FALSE
 };
+
+const struct setting_parser_info ldap_setting_parser_info = {
+       .name = "auth_ldap",
+
+       .check_func = ldap_setting_check,
+       .defines = ldap_setting_defines,
+       .defaults = &ldap_default_settings,
+
+       .struct_size = sizeof(struct ldap_settings),
+       .pool_offset1 = 1 + offsetof(struct ldap_settings, pool),
+};
+
+/* <settings checks> */
+
+#ifdef OPENLDAP_TLS_OPTIONS
+static int ldap_parse_tls_require_cert(const char *str, int *value_r)
+{
+       if (strcasecmp(str, "never") == 0)
+               *value_r = LDAP_OPT_X_TLS_NEVER;
+       else if (strcasecmp(str, "hard") == 0)
+               *value_r = LDAP_OPT_X_TLS_HARD;
+       else if (strcasecmp(str, "demand") == 0)
+               *value_r = LDAP_OPT_X_TLS_DEMAND;
+       else if (strcasecmp(str, "allow") == 0)
+               *value_r = LDAP_OPT_X_TLS_ALLOW;
+       else if (strcasecmp(str, "try") == 0)
+               *value_r = LDAP_OPT_X_TLS_TRY;
+       else
+               return -1;
+       return 1;
+}
+#endif
+
+static int ldap_parse_deref(const char *str, int *ref_r)
+{
+       if (strcasecmp(str, "never") == 0)
+               *ref_r = LDAP_DEREF_NEVER;
+       else if (strcasecmp(str, "searching") == 0)
+               *ref_r = LDAP_DEREF_SEARCHING;
+       else if (strcasecmp(str, "finding") == 0)
+               *ref_r = LDAP_DEREF_FINDING;
+       else if (strcasecmp(str, "always") == 0)
+               *ref_r = LDAP_DEREF_ALWAYS;
+       else
+               return -1;
+       return 0;
+}
+
+static int ldap_parse_scope(const char *str, int *scope_r)
+{
+       if (strcasecmp(str, "base") == 0)
+               *scope_r = LDAP_SCOPE_BASE;
+       else if (strcasecmp(str, "onelevel") == 0)
+               *scope_r = LDAP_SCOPE_ONELEVEL;
+       else if (strcasecmp(str, "subtree") == 0)
+               *scope_r = LDAP_SCOPE_SUBTREE;
+       else
+               return -1;
+       return 0;
+}
+
+static bool ldap_setting_check(void *_set, pool_t pool ATTR_UNUSED,
+                              const char **error_r)
+{
+       struct ldap_settings *set = _set;
+
+        if (ldap_parse_deref(set->deref, &set->ldap_deref) < 0) {
+               *error_r = t_strdup_printf("Unknown ldap_deref option '%s'",
+                                          set->deref);
+               return FALSE;
+       }
+
+       if (ldap_parse_scope(set->scope, &set->ldap_scope) < 0) {
+               *error_r = t_strdup_printf("Unknown ldap_scope option '%s'",
+                                          set->scope);
+               return FALSE;
+       }
+
+#ifdef OPENLDAP_TLS_OPTIONS
+       if (ldap_parse_tls_require_cert(set->tls_require_cert,
+                                            &set->ldap_tls_require_cert_parsed) < 0) {
+               *error_r = t_strdup_printf("Unknown tls_require_cert value '%s'",
+                                          set->tls_require_cert);
+               return FALSE;
+       }
+#endif
+
+       return TRUE;
+}
+
+/* </settings checks> */
index 6c4a39c7c44c79b56fcefc109263ae2c3dd995ef..1b6eddfd52367db9c843bba1b63091bb8e6366fd 100644 (file)
@@ -2,6 +2,8 @@
 #define DB_LDAP_SETTINGS_H
 
 struct ldap_settings {
+       pool_t pool;
+
        const char *hosts;
        const char *uris;
        const char *dn;
@@ -50,4 +52,6 @@ struct ldap_settings {
        bool blocking;
 };
 
+extern const struct setting_parser_info ldap_setting_parser_info;
+
 #endif
index 2fdabf9efd7a3c64a201f093983e661819eb594f..0830eb783b8b19e099b8c188fa6697ba6dad0085 100644 (file)
@@ -13,7 +13,7 @@
 #include "time-util.h"
 #include "env-util.h"
 #include "var-expand.h"
-#include "settings-legacy.h"
+#include "settings.h"
 #include "userdb.h"
 #include "db-ldap.h"
 
@@ -101,53 +101,6 @@ static bool db_ldap_abort_requests(struct ldap_connection *conn,
                                   bool error, const char *reason);
 static void db_ldap_request_free(struct ldap_request *request);
 
-static int deref2str(const char *str, int *ref_r)
-{
-       if (strcasecmp(str, "never") == 0)
-               *ref_r = LDAP_DEREF_NEVER;
-       else if (strcasecmp(str, "searching") == 0)
-               *ref_r = LDAP_DEREF_SEARCHING;
-       else if (strcasecmp(str, "finding") == 0)
-               *ref_r = LDAP_DEREF_FINDING;
-       else if (strcasecmp(str, "always") == 0)
-               *ref_r = LDAP_DEREF_ALWAYS;
-       else
-               return -1;
-       return 0;
-}
-
-static int scope2str(const char *str, int *scope_r)
-{
-       if (strcasecmp(str, "base") == 0)
-               *scope_r = LDAP_SCOPE_BASE;
-       else if (strcasecmp(str, "onelevel") == 0)
-               *scope_r = LDAP_SCOPE_ONELEVEL;
-       else if (strcasecmp(str, "subtree") == 0)
-               *scope_r = LDAP_SCOPE_SUBTREE;
-       else
-               return -1;
-       return 0;
-}
-
-#ifdef OPENLDAP_TLS_OPTIONS
-static int tls_require_cert2str(const char *str, int *value_r)
-{
-       if (strcasecmp(str, "never") == 0)
-               *value_r = LDAP_OPT_X_TLS_NEVER;
-       else if (strcasecmp(str, "hard") == 0)
-               *value_r = LDAP_OPT_X_TLS_HARD;
-       else if (strcasecmp(str, "demand") == 0)
-               *value_r = LDAP_OPT_X_TLS_DEMAND;
-       else if (strcasecmp(str, "allow") == 0)
-               *value_r = LDAP_OPT_X_TLS_ALLOW;
-       else if (strcasecmp(str, "try") == 0)
-               *value_r = LDAP_OPT_X_TLS_TRY;
-       else
-               return -1;
-       return 0;
-}
-#endif
-
 static int ldap_get_errno(struct ldap_connection *conn)
 {
        int ret, err;
@@ -886,7 +839,7 @@ db_ldap_set_opt(LDAP *ld, int opt, const void *value, const char *optname,
 static void ATTR_NULL(0)
 db_ldap_set_opt_str(LDAP *ld, int opt, const char *value, const char *optname)
 {
-       if (value != NULL)
+       if (*value != '\0')
                db_ldap_set_opt(ld, opt, value, optname, value);
 }
 
@@ -931,12 +884,12 @@ static void db_ldap_set_options(struct ldap_connection *conn)
 #endif
 
        db_ldap_set_opt(conn->ld, LDAP_OPT_DEREF, &conn->set->ldap_deref,
-                       "deref", conn->set->deref);
+                       "ldap_deref", conn->set->deref);
 #ifdef LDAP_OPT_DEBUG_LEVEL
        int debug_level;
        if (str_to_int(conn->set->debug_level, &debug_level) >= 0 && debug_level != 0) {
                db_ldap_set_opt(NULL, LDAP_OPT_DEBUG_LEVEL, &debug_level,
-                               "debug_level", conn->set->debug_level);
+                               "ldap_debug_level", conn->set->debug_level);
                event_set_forced_debug(conn->event, TRUE);
        }
 #endif
@@ -1713,105 +1666,76 @@ void db_ldap_result_iterate_deinit(struct db_ldap_result_iterate_context **_ctx)
        pool_unref(&ctx->pool);
 }
 
-static const char *parse_setting(const char *key, const char *value,
-                                struct ldap_connection *conn)
-{
-       return parse_setting_from_defs(conn->pool, setting_defs,
-                                      &conn->set, key, value);
-}
-
-static struct ldap_connection *ldap_conn_find(const char *config_path)
+static struct ldap_connection *
+db_ldap_conn_find(const struct ldap_settings *set)
 {
        struct ldap_connection *conn;
-
        for (conn = ldap_connections; conn != NULL; conn = conn->next) {
-               if (strcmp(conn->config_path, config_path) == 0)
+               if (settings_equal(&ldap_setting_parser_info, set, conn->set, NULL))
                        return conn;
        }
-
        return NULL;
 }
 
-struct ldap_connection *db_ldap_init(const char *config_path)
+struct ldap_connection *db_ldap_init(struct event *event)
 {
-       struct ldap_connection *conn;
-       const char *str, *error;
-       pool_t pool;
+        const struct ldap_settings *set;
+       set = settings_get_or_fatal(event, &ldap_setting_parser_info);
 
        /* see if it already exists */
-       conn = ldap_conn_find(config_path);
+       struct ldap_connection *conn = db_ldap_conn_find(set);
        if (conn != NULL) {
+               settings_free(set);
                conn->refcount++;
                return conn;
        }
 
-       if (*config_path == '\0')
-               i_fatal("LDAP: Configuration file path not given");
-
-       pool = pool_alloconly_create("ldap_connection", 1024);
+       pool_t pool = pool_alloconly_create("ldap_connection", 1024);
        conn = p_new(pool, struct ldap_connection, 1);
        conn->pool = pool;
        conn->refcount = 1;
 
+       conn->set = set;
        conn->conn_state = LDAP_CONN_STATE_DISCONNECTED;
        conn->default_bind_msgid = -1;
        conn->fd = -1;
-       conn->config_path = p_strdup(pool, config_path);
-
-       conn->set = p_new(pool, struct ldap_settings, 1);
-       *conn->set = default_ldap_settings;
-       if (!settings_read_nosection(config_path, parse_setting, conn, &error))
-               i_fatal("LDAP: %s", error);
 
        if (conn->set->base == NULL)
-               i_fatal("LDAP: No base given");
+               i_fatal("LDAP: No ldap_base given");
 
        if (conn->set->uris == NULL && conn->set->hosts == NULL)
-               i_fatal("LDAP: No uris or hosts set");
+               i_fatal("LDAP: Neither ldap_uris nor ldap_hosts set");
 #ifndef LDAP_HAVE_INITIALIZE
        if (conn->set->uris != NULL) {
-               i_fatal("LDAP: uris set, but Dovecot compiled without support for LDAP uris "
+               i_fatal("LDAP: ldap_uris set, but Dovecot compiled without support for LDAP uris "
                        "(ldap_initialize() not supported by LDAP library)");
        }
 #endif
 #ifndef LDAP_HAVE_START_TLS_S
        if (conn->set->tls)
-               i_fatal("LDAP: tls=yes, but your LDAP library doesn't support TLS");
+               i_fatal("LDAP: ldap_tls=yes, but your LDAP library doesn't support TLS");
 #endif
 #ifndef HAVE_LDAP_SASL
        if (conn->set->sasl_bind)
-               i_fatal("LDAP: sasl_bind=yes but no SASL support compiled in");
+               i_fatal("LDAP: ldap_sasl_bind=yes but no SASL support compiled in");
 #endif
        if (conn->set->ldap_version < 3) {
                if (conn->set->sasl_bind)
-                       i_fatal("LDAP: sasl_bind=yes requires ldap_version=3");
+                       i_fatal("LDAP: ldap_sasl_bind=yes requires ldap_version=3");
                if (conn->set->tls)
-                       i_fatal("LDAP: tls=yes requires ldap_version=3");
-       }
-#ifdef OPENLDAP_TLS_OPTIONS
-       if (conn->set->tls_require_cert != NULL) {
-               if (tls_require_cert2str(conn->set->tls_require_cert,
-                                        &conn->set->ldap_tls_require_cert_parsed) < 0)
-                       i_fatal("LDAP: Unknown tls_require_cert value '%s'",
-                               conn->set->tls_require_cert);
+                       i_fatal("LDAP: ldap_tls=yes requires ldap_version=3");
        }
-#endif
 
        if (*conn->set->ldaprc_path != '\0') {
-               str = getenv("LDAPRC");
+               const char *str = getenv("LDAPRC");
                if (str != NULL && strcmp(str, conn->set->ldaprc_path) != 0) {
-                       i_fatal("LDAP: Multiple different ldaprc_path "
+                       i_fatal("LDAP: Multiple different ldap_ldaprc_path "
                                "settings not allowed (%s and %s)",
                                str, conn->set->ldaprc_path);
                }
                env_put("LDAPRC", conn->set->ldaprc_path);
        }
 
-        if (deref2str(conn->set->deref, &conn->set->ldap_deref) < 0)
-               i_fatal("LDAP: Unknown deref option '%s'", conn->set->deref);
-       if (scope2str(conn->set->scope, &conn->set->ldap_scope) < 0)
-               i_fatal("LDAP: Unknown scope option '%s'", conn->set->scope);
-
        conn->event = event_create(auth_event);
        event_set_append_log_prefix(conn->event, "ldap: ");
 
@@ -1850,6 +1774,8 @@ void db_ldap_unref(struct ldap_connection **_conn)
        array_free(&conn->request_array);
        aqueue_deinit(&conn->request_queue);
 
+       settings_free(conn->set);
+
        event_unref(&conn->event);
        pool_unref(&conn->pool);
 }
index e0a161a41d53bab21b2d523eae405dc3387e7771..b20ec272b5fc753aa0c1bc017367a356ee5b0acc 100644 (file)
@@ -115,8 +115,7 @@ struct ldap_connection {
        int refcount;
        struct event *event;
 
-       char *config_path;
-       struct ldap_settings *set;
+        const struct ldap_settings *set;
 
        LDAP *ld;
        enum ldap_connection_state conn_state;
@@ -149,7 +148,7 @@ void db_ldap_set_attrs(struct ldap_connection *conn, const char *attrlist,
                       char ***attr_names_r, ARRAY_TYPE(ldap_field) *attr_map,
                       const char *skip_attr) ATTR_NULL(5);
 
-struct ldap_connection *db_ldap_init(const char *config_path);
+struct ldap_connection *db_ldap_init(struct event *event);
 void db_ldap_unref(struct ldap_connection **conn);
 
 int db_ldap_connect(struct ldap_connection *conn);
index ee7f2dbc7bb34c147db1aed134aeb2610b710400..1a8a896feeca5b90578670cc04c44012c3838978 100644 (file)
@@ -452,14 +452,15 @@ static void ldap_lookup_credentials(struct auth_request *request,
         ldap_lookup_pass(request, ldap_request, require_password);
 }
 
-static struct passdb_module *
-passdb_ldap_preinit(pool_t pool, const char *args)
+static int passdb_ldap_preinit(pool_t pool, struct event *event,
+                              struct passdb_module **module_r,
+                              const char **error_r ATTR_UNUSED)
 {
        struct ldap_passdb_module *module;
        struct ldap_connection *conn;
 
        module = p_new(pool, struct ldap_passdb_module, 1);
-       module->conn = conn = db_ldap_init(args);
+       module->conn = conn = db_ldap_init(event);
        p_array_init(&conn->pass_attr_map, pool, 16);
        db_ldap_set_attrs(conn, conn->set->pass_attrs, &conn->pass_attr_names,
                          &conn->pass_attr_map,
@@ -471,7 +472,8 @@ passdb_ldap_preinit(pool_t pool, const char *args)
                                                 conn->set->pass_attrs,
                                                 conn->set->pass_filter, NULL));
        module->module.default_pass_scheme = conn->set->default_pass_scheme;
-       return &module->module;
+       *module_r = &module->module;
+       return 0;
 }
 
 static void passdb_ldap_init(struct passdb_module *_module)
@@ -499,7 +501,7 @@ struct passdb_module_interface passdb_ldap_plugin =
 {
        .name = "ldap",
 
-       .preinit_legacy = passdb_ldap_preinit,
+       .preinit = passdb_ldap_preinit,
        .init = passdb_ldap_init,
        .deinit = passdb_ldap_deinit,
 
index f41e3d9709691d8910ad88cb8d8416ad8336249b..9a5a7917980ffe77766b10a950c66513c9cf3136 100644 (file)
@@ -282,14 +282,15 @@ static int userdb_ldap_iterate_deinit(struct userdb_iterate_context *_ctx)
        return ret;
 }
 
-static struct userdb_module *
-userdb_ldap_preinit(pool_t pool, const char *args)
+static int userdb_ldap_preinit(pool_t pool, struct event *event,
+                              struct userdb_module **module_r,
+                              const char **error_r ATTR_UNUSED)
 {
        struct ldap_userdb_module *module;
        struct ldap_connection *conn;
 
        module = p_new(pool, struct ldap_userdb_module, 1);
-       module->conn = conn = db_ldap_init(args);
+       module->conn = conn = db_ldap_init(event);
        p_array_init(&conn->user_attr_map, pool, 16);
        p_array_init(&conn->iterate_attr_map, pool, 16);
 
@@ -304,7 +305,8 @@ userdb_ldap_preinit(pool_t pool, const char *args)
                                     t_strconcat(conn->set->base,
                                                 conn->set->user_attrs,
                                                 conn->set->user_filter, NULL));
-       return &module->module;
+       *module_r = &module->module;
+       return 0;
 }
 
 static void userdb_ldap_init(struct userdb_module *_module)
@@ -332,7 +334,7 @@ struct userdb_module_interface userdb_ldap_plugin =
 {
        .name = "ldap",
 
-       .preinit_legacy = userdb_ldap_preinit,
+       .preinit = userdb_ldap_preinit,
        .init = userdb_ldap_init,
        .deinit = userdb_ldap_deinit,