#undef DEF
#define DEF(type, name) \
SETTING_DEFINE_STRUCT_##type("ldap_"#name, name, struct ldap_settings)
-#define DEFN(type, field, name) \
- SETTING_DEFINE_STRUCT_##type(#name, field, struct ldap_settings)
static const struct setting_define ldap_setting_defines[] = {
{ .type = SET_FILTER_NAME, .key = "passdb_ldap", },
DEF(STR, uris),
DEF(STR, auth_dn),
DEF(STR, auth_dn_password),
- DEFN(BOOL, passdb_ldap_bind, passdb_ldap_bind),
- DEFN(STR, passdb_ldap_bind_userdn, passdb_ldap_bind_userdn),
DEF(STR, auth_sasl_mechanism),
DEF(STR, auth_sasl_realm),
DEF(STR, auth_sasl_authz_id),
DEF(BOOL, starttls),
DEF(STR, deref),
DEF(STR, scope),
- DEF(STR, base),
DEF(UINT, version),
DEF(STR, debug_level),
- DEF(STR, filter),
- DEF(STRLIST, iterate_attrs),
- DEF(STR, iterate_filter),
SETTING_DEFINE_LIST_END
};
.uris = "",
.auth_dn = "",
.auth_dn_password = "",
- .passdb_ldap_bind = FALSE,
- .passdb_ldap_bind_userdn = "",
.auth_sasl_mechanism = "",
.auth_sasl_realm = "",
.auth_sasl_authz_id = "",
.starttls = FALSE,
.deref = "never",
.scope = "subtree",
- .base = "",
.version = 3,
.debug_level = "0",
- .filter = "",
- .iterate_attrs = ARRAY_INIT,
- .iterate_filter = "",
};
static const struct setting_keyvalue ldap_default_settings_keyvalue[] = {
.pool_offset1 = 1 + offsetof(struct ldap_settings, pool),
};
+#undef DEF
+#undef DEFN
+#define DEF(type, field) \
+ SETTING_DEFINE_STRUCT_##type("ldap_"#field, field, struct ldap_pre_settings)
+#define DEFN(type, field, name) \
+ SETTING_DEFINE_STRUCT_##type(#name, field, struct ldap_pre_settings)
+
+static const struct setting_define ldap_pre_setting_defines[] = {
+ { .type = SET_FILTER_NAME, .key = "passdb_ldap", },
+ { .type = SET_FILTER_NAME, .key = "userdb_ldap", },
+ DEF(STR, base),
+ DEFN(BOOL, passdb_ldap_bind, passdb_ldap_bind),
+ DEFN(STR, passdb_ldap_bind_userdn, passdb_ldap_bind_userdn),
+ DEF(STR, filter),
+ DEF(STR, iterate_filter),
+ SETTING_DEFINE_LIST_END
+};
+
+static const struct ldap_pre_settings ldap_pre_default_settings = {
+ .base = "",
+ .passdb_ldap_bind = FALSE,
+ .passdb_ldap_bind_userdn = "",
+ .filter = "",
+ .iterate_filter = "",
+};
+
+const struct setting_parser_info ldap_pre_setting_parser_info = {
+ .name = "auth_ldap_pre",
+
+ .defines = ldap_pre_setting_defines,
+ .defaults = &ldap_pre_default_settings,
+
+ .struct_size = sizeof(struct ldap_pre_settings),
+ .pool_offset1 = 1 + offsetof(struct ldap_pre_settings, pool),
+};
+
+#undef DEF
+#define DEF(type, field) \
+ SETTING_DEFINE_STRUCT_##type("ldap_"#field, field, struct ldap_post_settings)
+
+static const struct setting_define ldap_post_setting_defines[] = {
+ { .type = SET_FILTER_NAME, .key = "passdb_ldap", },
+ { .type = SET_FILTER_NAME, .key = "userdb_ldap", },
+ DEF(STRLIST, iterate_fields),
+ SETTING_DEFINE_LIST_END
+};
+
+static const struct ldap_post_settings ldap_post_default_settings = {
+ .iterate_fields = ARRAY_INIT,
+};
+
+const struct setting_parser_info ldap_post_setting_parser_info = {
+ .name = "auth_ldap_post",
+
+ .defines = ldap_post_setting_defines,
+ .defaults = &ldap_post_default_settings,
+
+ .struct_size = sizeof(struct ldap_post_settings),
+ .pool_offset1 = 1 + offsetof(struct ldap_post_settings, pool),
+};
+
/* <settings checks> */
static int ldap_parse_deref(const char *str, int *ref_r)
int ldap_setting_post_check(const struct ldap_settings *set, const char **error_r)
{
- if (*set->base == '\0') {
- *error_r = "No ldap_base given";
- return -1;
- }
-
if (*set->uris == '\0' && *set->hosts == '\0') {
*error_r = "Neither ldap_uris nor ldap_hosts set";
return -1;
return 0;
}
+
+int ldap_pre_settings_pre_check(const struct ldap_pre_settings *set, const char **error_r)
+{
+ if (*set->base == '\0') {
+ *error_r = "No ldap_base given";
+ return -1;
+ }
+
+ return 0;
+}
const char *uris;
const char *auth_dn;
const char *auth_dn_password;
- const char *passdb_ldap_bind_userdn;
const char *auth_sasl_mechanism;
const char *auth_sasl_realm;
const char *deref;
const char *scope;
- const char *base;
const char *debug_level;
- const char *filter;
- const char *iterate_filter;
-
- ARRAY_TYPE(const_string) iterate_attrs;
-
unsigned int version;
uid_t uid;
gid_t gid;
- bool passdb_ldap_bind;
bool starttls;
/* parsed */
int parsed_scope;
};
+struct ldap_pre_settings {
+ pool_t pool;
+
+ /* shared: */
+ const char *base;
+ const char *filter;
+
+ /* passdb: */
+ bool passdb_ldap_bind;
+ const char *passdb_ldap_bind_userdn;
+
+ /* userdb: */
+ const char *iterate_filter;
+};
+
+struct ldap_post_settings {
+ pool_t pool;
+ ARRAY_TYPE(const_string) iterate_fields;
+};
+
extern const struct setting_parser_info ldap_setting_parser_info;
+extern const struct setting_parser_info ldap_pre_setting_parser_info;
+extern const struct setting_parser_info ldap_post_setting_parser_info;
+
int ldap_setting_post_check(const struct ldap_settings *set, const char **error_r);
+int ldap_pre_settings_pre_check(const struct ldap_pre_settings *set, const char **error_r);
#endif
#endif
#define DB_LDAP_REQUEST_MAX_ATTEMPT_COUNT 3
+#define DB_LDAP_ATTR_DN "~dn"
static const char *LDAP_ESCAPE_CHARS = "*,\\#+<>;\"()= ";
pool_t pool;
struct ldap_request *ldap_request;
- const ARRAY_TYPE(ldap_field) *attr_map;
- unsigned int attr_idx;
+ char **attr_next;
/* attribute name => value */
HASH_TABLE(char *, struct db_ldap_value *) ldap_attrs;
{
if (ret == LDAP_SERVER_DOWN) {
e_error(conn->event, "Can't connect to server: %s",
- conn->set->uris != NULL ?
+ *conn->set->uris != '\0' ?
conn->set->uris : conn->set->hosts);
return -1;
}
if (ret != LDAP_SUCCESS) {
e_error(conn->event, "binding failed (dn %s): %s",
- conn->set->auth_dn == NULL ? "(none)" : conn->set->auth_dn,
+ *conn->set->auth_dn == '\0' ? "(none)" : conn->set->auth_dn,
ldap_get_error(conn));
return -1;
}
{
int ret;
- if (conn->set->uris != NULL) {
+ if (*conn->set->uris != '\0') {
#ifdef LDAP_HAVE_INITIALIZE
ret = ldap_initialize(&conn->ld, conn->set->uris);
if (ret != LDAP_SUCCESS) {
ret = ldap_start_tls_s(conn->ld, NULL, NULL);
if (ret != LDAP_SUCCESS) {
if (ret == LDAP_OPERATIONS_ERROR &&
- conn->set->uris != NULL &&
+ *conn->set->uris != '\0' &&
str_begins_with(conn->set->uris, "ldaps:")) {
i_fatal("LDAP: Don't use both ldap_starttls=yes and ldaps URI");
}
return 1;
}
-void db_ldap_set_attrs(struct ldap_connection *conn,
- const ARRAY_TYPE(const_string) *attrlist,
- char ***attr_names_r, ARRAY_TYPE(ldap_field) *attr_map,
- const char *skip_attr)
+void db_ldap_get_attribute_names(struct ldap_connection *conn,
+ const ARRAY_TYPE(const_string) *attrlist,
+ char ***attr_names_r,
+ const char *skip_attr)
{
static struct var_expand_func_table var_funcs_table[] = {
{ "ldap", db_ldap_field_find },
{ "ldap_multi", db_ldap_field_find },
- { "ldap_ptr", db_ldap_field_find },
{ NULL, NULL }
};
string_t *tmp_str = t_str_new(128);
for (unsigned int index = 0; index < count; ) {
- char *key = p_strdup(conn->pool, array_idx_elem(attrlist, index++));
- char *value = p_strdup(conn->pool, array_idx_elem(attrlist, index++));
- char *ldap_attr, *name;
-
- switch (*value) {
- case '\0':
- ldap_attr = key;
- name = key;
- break;
- default:
- ldap_attr = key;
- name = value;
- }
+ const char *name = array_idx_elem(attrlist, index++);
+ const char *value = array_idx_elem(attrlist, index++);
- char *templ = strchr(name, '=');
- if (templ == NULL) {
- if (*ldap_attr == '\0') {
- /* =foo static value */
- templ = "";
- }
- } else {
- const char *error ATTR_UNUSED;
- *templ++ = '\0';
- str_truncate(tmp_str, 0);
- if (var_expand_with_funcs(tmp_str, templ, NULL,
- var_funcs_table, &ctx, &error) <= 0) {
- /* This var_expand_with_funcs call fills the
- * ldap_field_find_context in ctx, but the
- * resulting string_t is not used, and the
- * return value or error_r is not checked since
- * it gives errors for non-ldap variable
- * expansions. */
- }
- if (strchr(templ, '%') == NULL) {
- /* backwards compatibility:
- attr=name=prefix means same as
- attr=name=prefix%$ when %vars are missing */
- templ = p_strconcat(conn->pool, templ,
- "%$", NULL);
- }
- }
+ if (skip_attr != NULL && strcmp(skip_attr, name) == 0)
+ continue;
- if (*name == '\0')
- e_error(conn->event, "Invalid empty attribute name");
- else if (skip_attr == NULL || strcmp(skip_attr, name) != 0) {
- struct ldap_field *field = array_append_space(attr_map);
- if (name[0] == '!' && name == ldap_attr) {
- /* !ldapAttr */
- name = "";
- i_assert(ldap_attr[0] == '!');
- ldap_attr++;
- field->skip = TRUE;
- }
- field->name = name;
- field->value = templ;
- field->ldap_attr_name = ldap_attr;
- if (*ldap_attr != '\0') {
- /* root request's attribute */
- array_push_back(&ctx.attr_names, &ldap_attr);
- }
- }
+ const char *error ATTR_UNUSED;
+ str_truncate(tmp_str, 0);
+
+ (void)var_expand_with_funcs(tmp_str, value, NULL, var_funcs_table, &ctx, &error);
}
array_append_zero(&ctx.attr_names);
*attr_names_r = array_front_modifiable(&ctx.attr_names);
}
-static const struct var_expand_table *
-db_ldap_value_get_var_expand_table(struct auth_request *auth_request,
- const char *ldap_value)
-{
- struct var_expand_table *table;
- unsigned int count = 1;
-
- table = auth_request_get_var_expand_table_full(auth_request,
- auth_request->fields.user, NULL, &count);
- table[0].key = '$';
- table[0].value = ldap_value;
- return table;
-}
-
#define IS_LDAP_ESCAPED_CHAR(c) \
((((unsigned char)(c)) & 0x80) != 0 || strchr(LDAP_ESCAPE_CHARS, (c)) != NULL)
ctx = p_new(pool, struct db_ldap_result_iterate_context, 1);
ctx->pool = pool;
ctx->ldap_request = &ldap_request->request;
- ctx->attr_map = ldap_request->attr_map;
+ ctx->attr_next = ldap_request->attributes;
ctx->skip_null_values = skip_null_values;
hash_table_create(&ctx->ldap_attrs, pool, 0, strcase_hash, strcasecmp);
ctx->var = str_new(ctx->pool, 256);
skip_null_values);
}
-static const char *db_ldap_field_get_default(const char *data)
-{
- const char *p;
-
- p = i_strchr_to_next(data, ':');
- if (p == NULL)
- return "";
- else {
- /* default value given */
- return p;
- }
-}
-
-static int
-db_ldap_field_expand(const char *data, void *context,
- const char **value_r, const char **error_r ATTR_UNUSED)
-{
- struct db_ldap_result_iterate_context *ctx = context;
- struct db_ldap_value *ldap_value;
- const char *field_name = t_strcut(data, ':');
-
- ldap_value = hash_table_lookup(ctx->ldap_attrs, field_name);
- if (ldap_value == NULL) {
- /* requested ldap attribute wasn't returned at all */
- str_printfa(ctx->debug, "; %s missing", field_name);
- *value_r = db_ldap_field_get_default(data);
- return 1;
- }
- ldap_value->used = TRUE;
-
- if (ldap_value->values[0] == NULL) {
- /* no value for ldap attribute */
- *value_r = db_ldap_field_get_default(data);
- return 1;
- }
- if (ldap_value->values[1] != NULL) {
- e_warning(authdb_event(ctx->ldap_request->auth_request),
- "Multiple values found for '%s', using value '%s'",
- field_name, ldap_value->values[0]);
- }
- *value_r = ldap_value->values[0];
- return 1;
-}
-
void db_ldap_field_multi_expand_parse_data(
const char *data, const char **field_name_r,
const char **separator_r, const char **default_r)
*default_r = ptr;
}
+const char *db_ldap_attribute_as_multi(const char *name)
+{
+ return t_strconcat(DB_LDAP_ATTR_MULTI_PREFIX, name, NULL);
+}
+
static int
db_ldap_field_multi_expand(const char *data, void *context,
const char **value_r, const char **error_r ATTR_UNUSED)
{
- struct db_ldap_result_iterate_context *ctx = context;
- struct db_ldap_value *ldap_value;
+ struct db_ldap_field_expand_context *ctx = context;
+ struct auth_fields *fields = ctx->fields;
const char *field_name;
const char *field_separator;
db_ldap_field_multi_expand_parse_data(data, &field_name,
&field_separator,
&field_default);
- *value_r = field_default;
- ldap_value = hash_table_lookup(ctx->ldap_attrs, field_name);
- if (ldap_value == NULL) {
- /* requested ldap attribute wasn't returned at all */
- str_printfa(ctx->debug, "; %s missing", field_name);
- return 1;
- }
- ldap_value->used = TRUE;
+ const char *value = auth_fields_find(fields,
+ db_ldap_attribute_as_multi(field_name));
+ if (value == NULL || *value == '\0')
+ value = auth_fields_find(fields, field_name);
- if (ldap_value->values[0] == NULL) {
- /* no value for ldap attribute */
- return 1;
+ if (value == NULL || *value == '\0')
+ value = field_default == NULL ? "" : field_default;
+ else {
+ const char **entries = t_strsplit(value, DB_LDAP_ATTR_SEPARATOR);
+ value = t_strarray_join(entries, field_separator);
}
-
- *value_r = t_strarray_join(ldap_value->values, field_separator);
+ *value_r = value;
return 1;
}
static int
-db_ldap_field_ptr_expand(const char *data, void *context,
- const char **value_r, const char **error_r)
+db_ldap_field_single_expand(const char *data ATTR_UNUSED, void *context,
+ const char **value_r, const char **error_r ATTR_UNUSED)
{
- struct db_ldap_result_iterate_context *ctx = context;
- const char *field_name, *suffix;
+ struct db_ldap_field_expand_context *ctx = context;
+ struct auth_fields *fields = ctx->fields;
+ const char *field_default = strchr(data, ':');
+ const char *field_name = field_default == NULL ? data : t_strdup_until(data, field_default);
- suffix = strchr(t_strcut(data, ':'), '@');
- if (db_ldap_field_expand(data, ctx, &field_name, error_r) <= 0)
- i_unreached();
- if (field_name[0] == '\0') {
- *value_r = "";
- return 1;
+ *value_r = NULL;
+ if (fields != NULL)
+ *value_r = auth_fields_find(fields, field_name);
+
+ if (*value_r == NULL || **value_r == '\0')
+ *value_r = field_default == NULL ? "" : field_default + 1;
+ else if (auth_fields_find(fields,
+ db_ldap_attribute_as_multi(field_name)) != NULL) {
+ e_warning(ctx->event, "Multiple values found for '%s': "
+ "using value '%s'", field_name, *value_r);
}
- field_name = t_strconcat(field_name, suffix, NULL);
- return db_ldap_field_expand(field_name, ctx, value_r, error_r);
+
+ return 1;
}
static int
-db_ldap_field_dn_expand(const char *data ATTR_UNUSED, void *context ATTR_UNUSED,
+db_ldap_field_dn_expand(const char *data ATTR_UNUSED, void *context,
const char **value_r, const char **error_r ATTR_UNUSED)
{
- struct db_ldap_result_iterate_context *ctx = context;
- char *dn = ldap_get_dn(ctx->ld, ctx->ldap_msg);
- *value_r = t_strdup(dn);
- ldap_memfree(dn);
+ struct db_ldap_field_expand_context *ctx = context;
+ struct auth_fields *fields = ctx->fields;
+ *value_r = auth_fields_find(fields, DB_LDAP_ATTR_DN);
return 1;
}
-static struct var_expand_func_table ldap_var_funcs_table[] = {
- { "ldap", db_ldap_field_expand },
+const struct var_expand_func_table db_ldap_field_expand_fn_table[] = {
+ { "ldap", db_ldap_field_single_expand },
{ "ldap_multi", db_ldap_field_multi_expand },
- { "ldap_ptr", db_ldap_field_ptr_expand },
- { "ldap_dn", db_ldap_field_dn_expand },
+ { "ldap_dn", db_ldap_field_dn_expand },
{ NULL, NULL }
};
-static const char *const *
-db_ldap_result_return_value(struct db_ldap_result_iterate_context *ctx,
- const struct ldap_field *field,
- struct db_ldap_value *ldap_value)
+struct auth_fields *
+ldap_query_get_fields(pool_t pool,
+ struct ldap_connection *conn,
+ struct ldap_request_search *ldap_request,
+ LDAPMessage *res, bool skip_null_values)
{
- const struct var_expand_table *var_table;
- const char *const *values, *error;
+ struct auth_fields *fields = auth_fields_init(pool);
+ struct db_ldap_result_iterate_context *ldap_iter;
+ const char *name, *const *values;
- if (ldap_value != NULL)
- values = ldap_value->values;
- else {
- /* LDAP attribute doesn't exist */
- ctx->val_1_arr[0] = NULL;
- values = ctx->val_1_arr;
- }
+ const char *dn = ldap_get_dn(conn->ld, res);
+ auth_fields_add(fields, DB_LDAP_ATTR_DN, dn, 0);
- if (field->value == NULL) {
- /* use the LDAP attribute's value */
- } else {
- /* template */
- if (values[0] == NULL && *field->ldap_attr_name != '\0') {
- /* ldapAttr=key=template%$, but ldapAttr doesn't
- exist. */
- return values;
- }
+ ldap_iter = db_ldap_result_iterate_init(conn, ldap_request, res,
+ skip_null_values);
+ while (db_ldap_result_iterate_next(ldap_iter, &name, &values)) {
+ auth_fields_add(fields, name, values[0], 0);
if (values[0] != NULL && values[1] != NULL) {
- e_warning(authdb_event(ctx->ldap_request->auth_request),
- "Multiple values found for '%s', "
- "using value '%s'",
- field->name, values[0]);
- }
-
- /* do this lookup separately for each expansion, because:
- 1) the values are allocated from data stack
- 2) if "user" field is updated, we want %u/%n/%d updated
- (and less importantly the same for other variables) */
- var_table = db_ldap_value_get_var_expand_table(
- ctx->ldap_request->auth_request, values[0]);
- if (var_expand_with_funcs(ctx->var, field->value, var_table,
- ldap_var_funcs_table, ctx, &error) <= 0) {
- e_warning(authdb_event(ctx->ldap_request->auth_request),
- "Failed to expand template %s: %s",
- field->value, error);
+ const char *mname = db_ldap_attribute_as_multi(name);
+ const char *mvalue = t_strarray_join(values, DB_LDAP_ATTR_SEPARATOR);
+ auth_fields_add(fields, mname, mvalue, 0);
}
- ctx->val_1_arr[0] = str_c(ctx->var);
- values = ctx->val_1_arr;
}
- return values;
+ db_ldap_result_iterate_deinit(&ldap_iter);
+ return fields;
+}
+
+static const char *const *
+db_ldap_result_return_value(struct db_ldap_result_iterate_context *ctx,
+ struct db_ldap_value *ldap_value)
+{
+ if (ldap_value != NULL && ldap_value->values[0] != NULL)
+ return ldap_value->values;
+
+ /* LDAP attribute doesn't exist */
+ ctx->val_1_arr[0] = "";
+ return ctx->val_1_arr;
}
bool db_ldap_result_iterate_next(struct db_ldap_result_iterate_context *ctx,
const char **name_r,
const char *const **values_r)
{
- const struct var_expand_table *tab;
- const struct ldap_field *field;
- struct db_ldap_value *ldap_value;
- unsigned int pos;
- const char *error;
+ const char *name = *ctx->attr_next;
+ if (name == NULL)
+ return FALSE;
- do {
- if (ctx->attr_idx == array_count(ctx->attr_map))
- return FALSE;
- field = array_idx(ctx->attr_map, ctx->attr_idx++);
- } while (field->skip);
+ ctx->attr_next++;
- ldap_value = *field->ldap_attr_name == '\0' ? NULL :
- hash_table_lookup(ctx->ldap_attrs, field->ldap_attr_name);
+ struct db_ldap_value *ldap_value = hash_table_lookup(ctx->ldap_attrs, name);
if (ldap_value != NULL)
ldap_value->used = TRUE;
- else if (*field->ldap_attr_name != '\0')
- str_printfa(ctx->debug, "; %s missing", field->ldap_attr_name);
+ else
+ str_printfa(ctx->debug, "; %s missing", name);
str_truncate(ctx->var, 0);
- *values_r = db_ldap_result_return_value(ctx, field, ldap_value);
-
- if (strchr(field->name, '%') == NULL)
- *name_r = field->name;
- else {
- /* expand %variables also for LDAP name fields. we'll use the
- same ctx->var, which may already contain the value. */
- str_append_c(ctx->var, '\0');
- pos = str_len(ctx->var);
-
- tab = auth_request_get_var_expand_table(
- ctx->ldap_request->auth_request, NULL);
- if (var_expand_with_funcs(ctx->var, field->name, tab,
- ldap_var_funcs_table, ctx, &error) <= 0) {
- e_warning(authdb_event(ctx->ldap_request->auth_request),
- "Failed to expand %s: %s", field->name, error);
- }
- *name_r = str_c(ctx->var) + pos;
- }
-
+ *name_r = name;
+ *values_r = db_ldap_result_return_value(ctx, ldap_value);
if (ctx->skip_null_values && (*values_r)[0] == NULL) {
/* no values. don't confuse the caller with this reply. */
return db_ldap_result_iterate_next(ctx, name_r, values_r);
#define DB_LDAP_IDLE_RECONNECT_SECS 60
#include <ldap.h>
+#include "var-expand.h"
#include "db-ldap-settings.h"
+#define DB_LDAP_ATTR_MULTI_PREFIX "+"
+#define DB_LDAP_ATTR_SEPARATOR "\001"
+
struct auth_request;
struct ldap_connection;
struct ldap_request;
const char *base;
const char *filter;
- char **attributes; /* points to pass_attr_names / user_attr_names */
- const ARRAY_TYPE(ldap_field) *attr_map;
+ char **attributes; /* points to (pass|user) module attributes */
struct db_ldap_result *result;
ARRAY(struct ldap_request_named_result) named_results;
time_t last_reply_stamp;
char **pass_attr_names, **user_attr_names, **iterate_attr_names;
- ARRAY_TYPE(ldap_field) pass_attr_map, user_attr_map, iterate_attr_map;
bool delayed_connect;
};
+struct db_ldap_field_expand_context {
+ struct event *event;
+ struct auth_fields *fields;
+};
+
+extern const struct var_expand_func_table db_ldap_field_expand_fn_table[];
+
/* Send/queue request */
void db_ldap_request(struct ldap_connection *conn,
struct ldap_request *request);
-void db_ldap_set_attrs(struct ldap_connection *conn,
- const ARRAY_TYPE(const_string) *attrlist,
- char ***attr_names_r, ARRAY_TYPE(ldap_field) *attr_map,
- const char *skip_attr) ATTR_NULL(5);
+void db_ldap_get_attribute_names(struct ldap_connection *conn,
+ const ARRAY_TYPE(const_string) *attrlist,
+ char ***attr_names_r,
+ const char *skip_attr) ATTR_NULL(4);
struct ldap_connection *db_ldap_init(struct event *event);
void db_ldap_unref(struct ldap_connection **conn);
const char *const **values_r);
void db_ldap_result_iterate_deinit(struct db_ldap_result_iterate_context **ctx);
+struct auth_fields *
+ldap_query_get_fields(pool_t pool,
+ struct ldap_connection *conn,
+ struct ldap_request_search *ldap_request,
+ LDAPMessage *res, bool skip_null_values);
+const char *db_ldap_attribute_as_multi(const char *name);
+
/* exposed only for unit tests */
const char *const *db_ldap_parse_attrs(const char *cstr);
#include <ldap.h>
+#define RAW_SETTINGS (SETTINGS_GET_FLAG_NO_CHECK | SETTINGS_GET_FLAG_NO_EXPAND)
+
struct ldap_passdb_module {
struct passdb_module module;
struct ldap_request_search *ldap_request,
LDAPMessage *res)
{
- struct passdb_module *_module = auth_request->passdb->passdb;
- struct auth_fields *fields = auth_fields_init(auth_request->pool);
- struct db_ldap_result_iterate_context *ldap_iter;
- const char *name, *const *values;
-
- ldap_iter = db_ldap_result_iterate_init(conn, ldap_request, res, FALSE);
- while (db_ldap_result_iterate_next(ldap_iter, &name, &values)) {
- auth_fields_add(fields, name, values[0], 0);
- if (!auth_request->passdb->set->fields_import_all)
- continue;
- if (values[0] == NULL) {
- auth_request_set_null_field(auth_request, name);
- continue;
- }
- if (values[1] != NULL) {
- e_warning(authdb_event(auth_request),
- "Multiple values found for '%s', "
- "using value '%s'", name, values[0]);
- }
- auth_request_set_field(auth_request, name, values[0],
- _module->default_pass_scheme);
- }
- db_ldap_result_iterate_deinit(&ldap_iter);
- return auth_request_set_passdb_fields(auth_request, fields);
+ struct db_ldap_field_expand_context ctx = {
+ .event = authdb_event(auth_request),
+ .fields = ldap_query_get_fields(auth_request->pool, conn,
+ ldap_request, res, FALSE)
+ };
+
+ const char *default_password_scheme =
+ auth_request->passdb->set->default_password_scheme;
+
+ return auth_request_set_passdb_fields_ex(auth_request, &ctx,
+ default_password_scheme,
+ db_ldap_field_expand_fn_table);
}
static void
static void ldap_lookup_pass(struct auth_request *auth_request,
struct passdb_ldap_request *request,
+ const struct ldap_pre_settings *ldap_set,
bool require_password)
{
struct passdb_module *_module = auth_request->passdb->passdb;
struct ldap_connection *conn = module->conn;
struct ldap_request_search *srequest = &request->request.search;
const char **attr_names = (const char **)conn->pass_attr_names;
- const char *error;
- string_t *str;
request->require_password = require_password;
srequest->request.type = LDAP_REQUEST_TYPE_SEARCH;
-
- str = t_str_new(512);
- if (auth_request_var_expand(str, conn->set->base, auth_request,
- ldap_escape, &error) <= 0) {
- e_error(authdb_event(auth_request),
- "Failed to expand base=%s: %s", conn->set->base, error);
- passdb_ldap_request_fail(request, PASSDB_RESULT_INTERNAL_FAILURE);
- return;
- }
- srequest->base = p_strdup(auth_request->pool, str_c(str));
-
- str_truncate(str, 0);
- if (auth_request_var_expand(str, conn->set->filter,
- auth_request, ldap_escape, &error) <= 0) {
- e_error(authdb_event(auth_request),
- "Failed to expand ldap_filter=%s: %s",
- conn->set->filter, error);
- passdb_ldap_request_fail(request, PASSDB_RESULT_INTERNAL_FAILURE);
- return;
- }
- srequest->filter = p_strdup(auth_request->pool, str_c(str));
- srequest->attr_map = &conn->pass_attr_map;
+ srequest->base = p_strdup(auth_request->pool, ldap_set->base);
+ srequest->filter = p_strdup(auth_request->pool, ldap_set->filter);
srequest->attributes = conn->pass_attr_names;
e_debug(authdb_event(auth_request), "pass search: "
}
static void ldap_bind_lookup_dn(struct auth_request *auth_request,
- struct passdb_ldap_request *request)
+ struct passdb_ldap_request *request,
+ const struct ldap_pre_settings *ldap_set)
{
struct passdb_module *_module = auth_request->passdb->passdb;
struct ldap_passdb_module *module =
(struct ldap_passdb_module *)_module;
struct ldap_connection *conn = module->conn;
struct ldap_request_search *srequest = &request->request.search;
- const char *error;
- string_t *str;
srequest->request.type = LDAP_REQUEST_TYPE_SEARCH;
-
- str = t_str_new(512);
- if (auth_request_var_expand(str, conn->set->base, auth_request,
- ldap_escape, &error) <= 0) {
- e_error(authdb_event(auth_request),
- "Failed to expand base=%s: %s", conn->set->base, error);
- passdb_ldap_request_fail(request, PASSDB_RESULT_INTERNAL_FAILURE);
- return;
- }
- srequest->base = p_strdup(auth_request->pool, str_c(str));
-
- str_truncate(str, 0);
- if (auth_request_var_expand(str, conn->set->filter,
- auth_request, ldap_escape, &error) <= 0) {
- e_error(authdb_event(auth_request),
- "Failed to expand filter=%s: %s",
- conn->set->filter, error);
- passdb_ldap_request_fail(request, PASSDB_RESULT_INTERNAL_FAILURE);
- return;
- }
- srequest->filter = p_strdup(auth_request->pool, str_c(str));
+ srequest->base = p_strdup(auth_request->pool, ldap_set->base);
+ srequest->filter = p_strdup(auth_request->pool, ldap_set->filter);
/* we don't need the attributes to perform authentication, but they
may contain some extra parameters. if a password is returned,
it's just ignored. */
- srequest->attr_map = &conn->pass_attr_map;
srequest->attributes = conn->pass_attr_names;
e_debug(authdb_event(auth_request),
static void
ldap_verify_plain_auth_bind_userdn(struct auth_request *auth_request,
- struct passdb_ldap_request *request)
+ struct passdb_ldap_request *request,
+ const struct ldap_pre_settings *ldap_set)
{
struct passdb_module *_module = auth_request->passdb->passdb;
struct ldap_passdb_module *module =
(struct ldap_passdb_module *)_module;
struct ldap_connection *conn = module->conn;
struct ldap_request_bind *brequest = &request->request.bind;
- string_t *dn;
- const char *error;
brequest->request.type = LDAP_REQUEST_TYPE_BIND;
-
- dn = t_str_new(512);
- if (auth_request_var_expand(dn, conn->set->passdb_ldap_bind_userdn,
- auth_request, ldap_escape, &error) <= 0) {
- e_error(authdb_event(auth_request),
- "Failed to expand passdb_ldap_bind_userdn=%s: %s",
- conn->set->passdb_ldap_bind_userdn, error);
- passdb_ldap_request_fail(request, PASSDB_RESULT_INTERNAL_FAILURE);
- return;
- }
-
- brequest->dn = p_strdup(auth_request->pool, str_c(dn));
+ brequest->dn = p_strdup(auth_request->pool, ldap_set->passdb_ldap_bind_userdn);
ldap_auth_bind(conn, brequest);
}
struct ldap_passdb_module *module =
(struct ldap_passdb_module *)_module;
struct ldap_connection *conn = module->conn;
+ struct event *event = authdb_event(request);
struct passdb_ldap_request *ldap_request;
+ const char *error;
/* reconnect if needed. this is also done by db_ldap_search(), but
with auth binds we'll have to do it ourself */
return;
}
+ const struct ldap_pre_settings *ldap_pre = NULL;
+ if (settings_get(event, &ldap_pre_setting_parser_info, 0,
+ &ldap_pre, &error) < 0 ||
+ ldap_pre_settings_pre_check(ldap_pre, &error) < 0) {
+ e_error(event, "%s", error);
+ callback(PASSDB_RESULT_INTERNAL_FAILURE, request);
+ settings_free(ldap_pre);
+ return;
+ }
+
ldap_request = p_new(request->pool, struct passdb_ldap_request, 1);
ldap_request->callback.verify_plain = callback;
auth_request_ref(request);
ldap_request->request.ldap.auth_request = request;
- if (!conn->set->passdb_ldap_bind)
- ldap_lookup_pass(request, ldap_request, TRUE);
- else if (conn->set->passdb_ldap_bind_userdn == NULL)
- ldap_bind_lookup_dn(request, ldap_request);
+ if (!ldap_pre->passdb_ldap_bind)
+ ldap_lookup_pass(request, ldap_request, ldap_pre, TRUE);
+ else if (*ldap_pre->passdb_ldap_bind_userdn == '\0')
+ ldap_bind_lookup_dn(request, ldap_request, ldap_pre);
else
- ldap_verify_plain_auth_bind_userdn(request, ldap_request);
+ ldap_verify_plain_auth_bind_userdn(request, ldap_request, ldap_pre);
+
+ settings_free(ldap_pre);
}
static void ldap_lookup_credentials(struct auth_request *request,
lookup_credentials_callback_t *callback)
{
- struct passdb_module *_module = request->passdb->passdb;
- struct ldap_passdb_module *module =
- (struct ldap_passdb_module *)_module;
- struct passdb_ldap_request *ldap_request;
- bool require_password;
-
- ldap_request = p_new(request->pool, struct passdb_ldap_request, 1);
+ struct event *event = authdb_event(request);
+ struct passdb_ldap_request *ldap_request =
+ p_new(request->pool, struct passdb_ldap_request, 1);
ldap_request->callback.lookup_credentials = callback;
auth_request_ref(request);
ldap_request->request.ldap.auth_request = request;
+ const char *error;
+ const struct ldap_pre_settings *ldap_pre = NULL;
+ if (settings_get(event, &ldap_pre_setting_parser_info, 0,
+ &ldap_pre, &error) < 0 ||
+ ldap_pre_settings_pre_check(ldap_pre, &error) < 0) {
+ e_error(event, "%s", error);
+ passdb_ldap_request_fail(ldap_request, PASSDB_RESULT_INTERNAL_FAILURE);
+ settings_free(ldap_pre);
+ return;
+ }
+
/* with auth_bind=yes we don't necessarily have a password.
this will fail actual password credentials lookups, but it's fine
for passdb lookups done by lmtp/doveadm */
- require_password = !module->conn->set->passdb_ldap_bind;
- ldap_lookup_pass(request, ldap_request, require_password);
+ bool require_password = !ldap_pre->passdb_ldap_bind;
+ ldap_lookup_pass(request, ldap_request, ldap_pre, require_password);
+ settings_free(ldap_pre);
}
static int passdb_ldap_preinit(pool_t pool, struct event *event,
struct passdb_module **module_r,
const char **error_r)
{
- const struct auth_passdb_post_settings *set;
+ const struct auth_passdb_post_settings *auth_post = NULL;
+ const struct ldap_pre_settings *ldap_pre = NULL;
struct ldap_passdb_module *module;
struct ldap_connection *conn;
+ int ret = -1;
+
+ if (settings_get(event, &auth_passdb_post_setting_parser_info,
+ RAW_SETTINGS, &auth_post, error_r) < 0)
+ goto failed;
+ if (settings_get(event, &ldap_pre_setting_parser_info,
+ RAW_SETTINGS, &ldap_pre, error_r) < 0)
+ goto failed;
module = p_new(pool, struct ldap_passdb_module, 1);
module->conn = conn = db_ldap_init(event);
- p_array_init(&conn->pass_attr_map, pool, 16);
- if (settings_get(event, &auth_passdb_post_setting_parser_info,
- SETTINGS_GET_FLAG_NO_CHECK | SETTINGS_GET_FLAG_NO_EXPAND,
- &set, error_r) < 0)
- return -1;
- db_ldap_set_attrs(conn, &set->fields, &conn->pass_attr_names,
- &conn->pass_attr_map,
- conn->set->passdb_ldap_bind ? "password" : NULL);
+ db_ldap_get_attribute_names(conn, &auth_post->fields,
+ &conn->pass_attr_names,
+ ldap_pre->passdb_ldap_bind ? "password" : NULL);
+
module->module.default_cache_key = auth_cache_parse_key_and_fields(
- pool, conn->set->base, &set->fields, NULL);
+ pool, t_strconcat(ldap_pre->base, ldap_pre->filter, NULL),
+ &auth_post->fields, NULL);
- settings_free(set);
*module_r = &module->module;
- return 0;
+ ret = 0;
+
+failed:
+ settings_free(auth_post);
+ settings_free(ldap_pre);
+ return ret;
}
static void passdb_ldap_init(struct passdb_module *_module)
#include <ldap.h>
+#define RAW_SETTINGS (SETTINGS_GET_FLAG_NO_CHECK | SETTINGS_GET_FLAG_NO_EXPAND)
+
struct ldap_userdb_module {
struct userdb_module module;
struct ldap_request_search *ldap_request,
LDAPMessage *res)
{
- struct auth_fields *fields = auth_fields_init(auth_request->pool);
- struct db_ldap_result_iterate_context *ldap_iter;
- const char *name, *const *values;
-
- ldap_iter = db_ldap_result_iterate_init(conn, ldap_request, res, TRUE);
- while (db_ldap_result_iterate_next(ldap_iter, &name, &values)) {
- auth_fields_add(fields, name, values[0], 0);
- if (!auth_request->userdb->set->fields_import_all)
- continue;
- auth_request_set_userdb_field_values(auth_request,
- name, values);
- }
- db_ldap_result_iterate_deinit(&ldap_iter);
- return auth_request_set_userdb_fields(auth_request, fields);
+ struct db_ldap_field_expand_context ctx = {
+ .event = authdb_event(auth_request),
+ .fields = ldap_query_get_fields(auth_request->pool, conn,
+ ldap_request, res, FALSE)
+ };
+
+ return auth_request_set_userdb_fields_ex(auth_request, &ctx,
+ db_ldap_field_expand_fn_table);
}
static void
struct ldap_userdb_module *module =
(struct ldap_userdb_module *)_module;
struct ldap_connection *conn = module->conn;
+ struct event *event = authdb_event(auth_request);
const char **attr_names = (const char **)conn->user_attr_names;
+
struct userdb_ldap_request *request;
const char *error;
- string_t *str;
- auth_request_ref(auth_request);
- request = p_new(auth_request->pool, struct userdb_ldap_request, 1);
- request->userdb_callback = callback;
-
- str = t_str_new(512);
- if (auth_request_var_expand(str, conn->set->base, auth_request,
- ldap_escape, &error) <= 0) {
- e_error(authdb_event(auth_request),
- "Failed to expand base=%s: %s", conn->set->base, error);
+ const struct ldap_pre_settings *ldap_pre = NULL;
+ if (settings_get(event, &ldap_pre_setting_parser_info, 0,
+ &ldap_pre, &error) < 0 ||
+ ldap_pre_settings_pre_check(ldap_pre, &error) < 0) {
+ e_error(event, "%s", error);
callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
+ settings_free(ldap_pre);
return;
}
- request->request.base = p_strdup(auth_request->pool, str_c(str));
- str_truncate(str, 0);
- if (auth_request_var_expand(str, conn->set->filter, auth_request,
- ldap_escape, &error) <= 0) {
- e_error(authdb_event(auth_request),
- "Failed to expand ldap_filter=%s: %s",
- conn->set->filter, error);
- callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
- return;
- }
- request->request.filter = p_strdup(auth_request->pool, str_c(str));
-
- request->request.attr_map = &conn->user_attr_map;
+ auth_request_ref(auth_request);
+ request = p_new(auth_request->pool, struct userdb_ldap_request, 1);
+ request->userdb_callback = callback;
+ request->request.base = p_strdup(auth_request->pool, ldap_pre->base);
+ request->request.filter = p_strdup(auth_request->pool, ldap_pre->filter);
request->request.attributes = conn->user_attr_names;
- e_debug(authdb_event(auth_request), "user search: "
- "base=%s scope=%s filter=%s fields=%s",
+ settings_free(ldap_pre);
+
+ e_debug(event, "user search: base=%s scope=%s filter=%s fields=%s",
request->request.base, conn->set->scope,
request->request.filter,
attr_names == NULL ? "(all)" :
struct userdb_iter_ldap_request *urequest =
(struct userdb_iter_ldap_request *)request;
struct ldap_userdb_iterate_context *ctx = urequest->ctx;
- struct db_ldap_result_iterate_context *ldap_iter;
- const char *name, *const *values;
if (res == NULL || ldap_msgtype(res) == LDAP_RES_SEARCH_RESULT) {
if (res == NULL)
request->create_time = ioloop_time;
ctx->in_callback = TRUE;
- ldap_iter = db_ldap_result_iterate_init(conn, &urequest->request,
- res, TRUE);
- while (db_ldap_result_iterate_next(ldap_iter, &name, &values)) {
- if (strcmp(name, "user") != 0) {
- e_warning(authdb_event(request->auth_request), "iterate: "
- "Ignoring field not named 'user': %s", name);
- continue;
- }
- for (; *values != NULL; values++) {
+
+ struct db_ldap_field_expand_context fctx = {
+ .event = authdb_event(request->auth_request),
+ .fields = ldap_query_get_fields(pool_datastack_create(), conn,
+ &urequest->request, res, TRUE)
+ };
+
+ struct var_expand_params params = {
+ .func_table = db_ldap_field_expand_fn_table,
+ .func_context = &fctx
+ };
+
+ struct event *event = event_create(authdb_event(urequest->request.request.auth_request));
+ event_set_ptr(event, SETTINGS_EVENT_VAR_EXPAND_PARAMS, ¶ms);
+
+ const struct ldap_post_settings *set;
+ const char *error;
+ if (settings_get(event, &ldap_post_setting_parser_info, 0,
+ &set, &error) < 0) {
+ e_error(event, "%s", error);
+ ctx->ctx.failed = TRUE;
+ }
+ else {
+ unsigned int count;
+ const char *const *items = array_get(&set->iterate_fields, &count);
+ for (unsigned int ndx = 0; ndx < count - 1;) {
+ const char *name = items[ndx++];
+ const char *value = items[ndx++];
+ if (strcmp(name, DB_LDAP_ATTR_MULTI_PREFIX"user") == 0) {
+ value = t_strsplit(value, DB_LDAP_ATTR_SEPARATOR)[0];
+ e_warning(authdb_event(request->auth_request),
+ "iterate: Taking only first value of %s: %s",
+ name + 1, value);
+ continue;
+ }
+ if (strcmp(name, "user") != 0) {
+ e_warning(authdb_event(request->auth_request),
+ "iterate: Ignoring field not named 'user': %s",
+ name);
+ continue;
+ }
ctx->continued = FALSE;
- ctx->ctx.callback(*values, ctx->ctx.context);
+ ctx->ctx.callback(value, ctx->ctx.context);
}
+ settings_free(set);
}
- db_ldap_result_iterate_deinit(&ldap_iter);
+ event_unref(&event);
+
if (!ctx->continued)
db_ldap_enable_input(conn, FALSE);
ctx->in_callback = FALSE;
struct ldap_userdb_module *module =
(struct ldap_userdb_module *)_module;
struct ldap_connection *conn = module->conn;
+ struct event *event = authdb_event(auth_request);
+
struct ldap_userdb_iterate_context *ctx;
struct userdb_iter_ldap_request *request;
const char **attr_names = (const char **)conn->iterate_attr_names;
const char *error;
- string_t *str;
ctx = p_new(auth_request->pool, struct ldap_userdb_iterate_context, 1);
ctx->ctx.auth_request = auth_request;
request = &ctx->request;
request->ctx = ctx;
- auth_request_ref(auth_request);
- request->request.request.auth_request = auth_request;
-
- str = t_str_new(512);
- if (auth_request_var_expand(str, conn->set->base, auth_request,
- ldap_escape, &error) <= 0) {
- e_error(authdb_event(auth_request),
- "Failed to expand base=%s: %s", conn->set->base, error);
+ const struct ldap_pre_settings *ldap_pre = NULL;
+ if (settings_get(event, &ldap_pre_setting_parser_info, 0,
+ &ldap_pre, &error) < 0 ||
+ ldap_pre_settings_pre_check(ldap_pre, &error) < 0) {
+ e_error(event, "%s", error);
+ settings_free(ldap_pre);
ctx->ctx.failed = TRUE;
return &ctx->ctx;
}
- request->request.base = p_strdup(auth_request->pool, str_c(str));
- str_truncate(str, 0);
- if (auth_request_var_expand(str, conn->set->iterate_filter,
- auth_request, ldap_escape, &error) <= 0) {
- e_error(authdb_event(auth_request),
- "Failed to expand iterate_filter=%s: %s",
- conn->set->iterate_filter, error);
- ctx->ctx.failed = TRUE;
- return &ctx->ctx;
- }
- request->request.filter = p_strdup(auth_request->pool, str_c(str));
- request->request.attr_map = &conn->iterate_attr_map;
+ auth_request_ref(auth_request);
+ request->request.request.auth_request = auth_request;
+ request->request.base = p_strdup(auth_request->pool, ldap_pre->base);
+ request->request.filter = p_strdup(auth_request->pool, ldap_pre->iterate_filter);
request->request.attributes = conn->iterate_attr_names;
request->request.multi_entry = TRUE;
+ settings_free(ldap_pre);
- e_debug(auth_request->event, "ldap: iterate: base=%s scope=%s filter=%s fields=%s",
+ e_debug(event, "ldap: iterate: base=%s scope=%s filter=%s fields=%s",
request->request.base, conn->set->scope,
request->request.filter, attr_names == NULL ? "(all)" :
t_strarray_join(attr_names, ","));
struct userdb_module **module_r,
const char **error_r ATTR_UNUSED)
{
- const struct auth_passdb_post_settings *set;
+ const struct auth_userdb_post_settings *auth_post = NULL;
+ const struct ldap_post_settings *ldap_post = NULL;
+ const struct ldap_pre_settings *ldap_pre = NULL;
struct ldap_userdb_module *module;
struct ldap_connection *conn;
+ int ret = -1;
+
+ if (settings_get(event, &auth_userdb_post_setting_parser_info,
+ RAW_SETTINGS, &auth_post, error_r) < 0)
+ goto failed;
+ if (settings_get(event, &ldap_post_setting_parser_info,
+ RAW_SETTINGS, &ldap_post, error_r) < 0)
+ goto failed;
+ if (settings_get(event, &ldap_pre_setting_parser_info,
+ RAW_SETTINGS, &ldap_pre, error_r) < 0)
+ goto failed;
module = p_new(pool, struct ldap_userdb_module, 1);
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);
- if (settings_get(event, &auth_passdb_post_setting_parser_info,
- SETTINGS_GET_FLAG_NO_CHECK | SETTINGS_GET_FLAG_NO_EXPAND,
- &set, error_r) < 0)
- return -1;
-
- db_ldap_set_attrs(conn, &set->fields, &conn->user_attr_names,
- &conn->user_attr_map, NULL);
- db_ldap_set_attrs(conn, &conn->set->iterate_attrs,
- &conn->iterate_attr_names,
- &conn->iterate_attr_map, NULL);
+
+ db_ldap_get_attribute_names(conn, &auth_post->fields,
+ &conn->user_attr_names, NULL);
+ db_ldap_get_attribute_names(conn, &ldap_post->iterate_fields,
+ &conn->iterate_attr_names, NULL);
+
module->module.default_cache_key = auth_cache_parse_key_and_fields(
- pool, conn->set->base, &set->fields, NULL);
+ pool, t_strconcat(ldap_pre->base, ldap_pre->filter, NULL),
+ &auth_post->fields, NULL);
- settings_free(set);
*module_r = &module->module;
- return 0;
+ ret = 0;
+
+failed:
+ settings_free(auth_post);
+ settings_free(ldap_pre);
+ settings_free(ldap_post);
+ return ret;
}
static void userdb_ldap_init(struct userdb_module *_module)
/* deep copy relevant strings */
conn->set.uri = p_strdup(pool, set->uri);
conn->set.bind_dn = p_strdup(pool, set->bind_dn);
- if (set->password != NULL) {
+ if (*set->password != '\0') {
conn->set.password = p_strdup(pool, set->password);
ber_str2bv(conn->set.password, strlen(conn->set.password), 0, &conn->cred);
}