From: Marco Bettini Date: Fri, 15 Mar 2024 09:31:44 +0000 (+0000) Subject: auth: ldap - Read settings from main config X-Git-Tag: 2.4.1~781 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fc123ffcf276feedc74fbf82df2323d3f8a40d13;p=thirdparty%2Fdovecot%2Fcore.git auth: ldap - Read settings from main config --- diff --git a/src/auth/db-ldap-settings.c b/src/auth/db-ldap-settings.c index cdb7d3daeb..9b7d476984 100644 --- a/src/auth/db-ldap-settings.c +++ b/src/auth/db-ldap-settings.c @@ -4,72 +4,75 @@ #include "settings.h" #include "db-ldap-settings.h" +/* */ + +#include "ldap.h" +static bool ldap_setting_check(void *_set, pool_t pool, const char **error_r); + +/* */ + #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), +}; + +/* */ + +#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; +} + +/* */ diff --git a/src/auth/db-ldap-settings.h b/src/auth/db-ldap-settings.h index 6c4a39c7c4..1b6eddfd52 100644 --- a/src/auth/db-ldap-settings.h +++ b/src/auth/db-ldap-settings.h @@ -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 diff --git a/src/auth/db-ldap.c b/src/auth/db-ldap.c index 2fdabf9efd..0830eb783b 100644 --- a/src/auth/db-ldap.c +++ b/src/auth/db-ldap.c @@ -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); } diff --git a/src/auth/db-ldap.h b/src/auth/db-ldap.h index e0a161a41d..b20ec272b5 100644 --- a/src/auth/db-ldap.h +++ b/src/auth/db-ldap.h @@ -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); diff --git a/src/auth/passdb-ldap.c b/src/auth/passdb-ldap.c index ee7f2dbc7b..1a8a896fee 100644 --- a/src/auth/passdb-ldap.c +++ b/src/auth/passdb-ldap.c @@ -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, diff --git a/src/auth/userdb-ldap.c b/src/auth/userdb-ldap.c index f41e3d9709..9a5a791798 100644 --- a/src/auth/userdb-ldap.c +++ b/src/auth/userdb-ldap.c @@ -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,