#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 = "",
.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> */
#define DB_LDAP_SETTINGS_H
struct ldap_settings {
+ pool_t pool;
+
const char *hosts;
const char *uris;
const char *dn;
bool blocking;
};
+extern const struct setting_parser_info ldap_setting_parser_info;
+
#endif
#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"
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;
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);
}
#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
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: ");
array_free(&conn->request_array);
aqueue_deinit(&conn->request_queue);
+ settings_free(conn->set);
+
event_unref(&conn->event);
pool_unref(&conn->pool);
}
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;
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);
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,
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)
{
.name = "ldap",
- .preinit_legacy = passdb_ldap_preinit,
+ .preinit = passdb_ldap_preinit,
.init = passdb_ldap_init,
.deinit = passdb_ldap_deinit,
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);
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)
{
.name = "ldap",
- .preinit_legacy = userdb_ldap_preinit,
+ .preinit = userdb_ldap_preinit,
.init = userdb_ldap_init,
.deinit = userdb_ldap_deinit,