* Perform all searches as the admin user.
*/
if (conn->rebound) {
- status = rlm_ldap_bind(inst, NULL, &conn, conn->inst->admin_identity, conn->inst->admin_password,
- &(conn->inst->admin_sasl), true, NULL, NULL, NULL);
+ status = rlm_ldap_bind(inst, NULL, &conn,
+ conn->pool_inst->admin_identity, conn->pool_inst->admin_password,
+ &(conn->pool_inst->admin_sasl), true, NULL, NULL, NULL);
if (status != LDAP_PROC_SUCCESS) {
ret = -1;
goto finish;
* - 1 if we failed identifying the directory server.
* - -1 on error.
*/
-int rlm_ldap_directory_alloc(TALLOC_CTX *ctx, ldap_directory_t **out, rlm_ldap_t *inst, ldap_handle_t **pconn)
+int rlm_ldap_directory_alloc(TALLOC_CTX *ctx, ldap_directory_t **out, rlm_ldap_t const *inst, ldap_handle_t **pconn)
{
static char const *attrs[] = { "vendorname",
"vendorversion",
values = ldap_get_values_len((*pconn)->handle, entry, "vendorname");
if (values) {
- directory->vendor_str = rlm_ldap_berval_to_string(inst, values[0]);
+ directory->vendor_str = rlm_ldap_berval_to_string(directory, values[0]);
INFO("Directory vendor: %s", directory->vendor_str);
ldap_value_free_len(values);
values = ldap_get_values_len((*pconn)->handle, entry, "vendorversion");
if (values) {
- directory->version_str = rlm_ldap_berval_to_string(inst, values[0]);
+ directory->version_str = rlm_ldap_berval_to_string(directory, values[0]);
INFO("Directory version: %s", directory->version_str);
ldap_value_free_len(values);
*pconn = fr_connection_reconnect(inst->pool, request, *pconn);
if (*pconn) {
ROPTIONAL(RWDEBUG, WARN, "Bind with %s to %s failed: %s. Got new socket, "
- "retrying...", *dn ? dn : "(anonymous)", inst->server, error);
+ "retrying...", *dn ? dn : "(anonymous)",
+ (*pconn)->pool_inst->server, error);
talloc_free(extra); /* don't leak debug info */
/* FALL-THROUGH */
default:
ROPTIONAL(REDEBUG, ERROR, "Bind with %s to %s failed: %s", *dn ? dn : "(anonymous)",
- inst->server, error);
+ (*pconn)->pool_inst->server, error);
LDAP_EXTRA_DEBUG();
break;
* Do all searches as the admin user.
*/
if ((*pconn)->rebound) {
- status = rlm_ldap_bind(inst, request, pconn, (*pconn)->inst->admin_identity,
- (*pconn)->inst->admin_password, &(*pconn)->inst->admin_sasl, true,
+ status = rlm_ldap_bind(inst, request, pconn, (*pconn)->pool_inst->admin_identity,
+ (*pconn)->pool_inst->admin_password, &(*pconn)->pool_inst->admin_sasl, true,
NULL, NULL, NULL);
if (status != LDAP_PROC_SUCCESS) {
return LDAP_PROC_ERROR;
* Perform all modifications as the admin user.
*/
if ((*pconn)->rebound) {
- status = rlm_ldap_bind(inst, request, pconn, (*pconn)->inst->admin_identity,
- (*pconn)->inst->admin_password, &(*pconn)->inst->admin_sasl, true,
+ status = rlm_ldap_bind(inst, request, pconn, (*pconn)->pool_inst->admin_identity,
+ (*pconn)->pool_inst->admin_password, &(*pconn)->pool_inst->admin_sasl, true,
NULL, NULL, NULL);
if (status != LDAP_PROC_SUCCESS) {
return LDAP_PROC_ERROR;
* Perform all searches as the admin user.
*/
if ((*pconn)->rebound) {
- status = rlm_ldap_bind(inst, request, pconn, (*pconn)->inst->admin_identity,
- (*pconn)->inst->admin_password, &(*pconn)->inst->admin_sasl, true,
+ status = rlm_ldap_bind(inst, request, pconn, (*pconn)->pool_inst->admin_identity,
+ (*pconn)->pool_inst->admin_password, &(*pconn)->pool_inst->admin_sasl, true,
NULL, NULL, NULL);
if (status != LDAP_PROC_SUCCESS) {
*rcode = RLM_MODULE_FAIL;
* @param inst rlm_ldap configuration.
* @param request Current request.
*/
-void rlm_ldap_check_reply(rlm_ldap_t const *inst, REQUEST *request)
+void rlm_ldap_check_reply(rlm_ldap_t const *inst, REQUEST *request, ldap_handle_t const *conn)
{
/*
* More warning messages for people who can't be bothered to read the documentation.
!fr_pair_find_by_num(request->control, 0, PW_USER_PASSWORD, TAG_ANY) &&
!fr_pair_find_by_num(request->control, 0, PW_PASSWORD_WITH_HEADER, TAG_ANY) &&
!fr_pair_find_by_num(request->control, 0, PW_CRYPT_PASSWORD, TAG_ANY)) {
- switch (inst->directory->type) {
+ switch (conn->directory->type) {
case LDAP_DIRECTORY_ACTIVE_DIRECTORY:
RWDEBUG("!!! Found map between LDAP attribute and a FreeRADIUS password attribute");
RWDEBUG("!!! Active Directory does not allow passwords to be read via LDAP");
break;
default:
- if (!inst->admin_identity) {
+ if (!conn->pool_inst->admin_identity) {
RWDEBUG("!!! Found map between LDAP attribute and a FreeRADIUS password attribute");
RWDEBUG("!!! but no password attribute found in search result");
RWDEBUG("!!! Either:");
RWDEBUG("!!! - Ensure the user object contains a password attribute, and that ");
RWDEBUG("!!! \"%s\" has permission to read that password attribute (recommended)",
- inst->admin_identity);
+ conn->pool_inst->admin_identity);
RWDEBUG("!!! - Bind as the user by listing %s in the authenticate section, and",
inst->name);
RWDEBUG("!!! setting attribute &control:Auth-Type := '%s' in the authorize section",
static int rlm_ldap_rebind(LDAP *handle, LDAP_CONST char *url, UNUSED ber_tag_t request, UNUSED ber_int_t msgid,
void *ctx)
{
- ldap_rcode_t status;
- ldap_handle_t *conn = talloc_get_type_abort(ctx, ldap_handle_t);
- rlm_ldap_t const *inst = conn->inst;
+ ldap_rcode_t status;
+ ldap_handle_t *conn = talloc_get_type_abort(ctx, ldap_handle_t);
+ ldap_pool_inst_t const *pool_inst = conn->pool_inst;
+ rlm_ldap_t const *inst = conn->inst;
- char const *admin_identity = NULL;
- char const *admin_password = NULL;
+ char const *admin_identity = NULL;
+ char const *admin_password = NULL;
- int ldap_errno;
+ int ldap_errno;
conn->referred = true;
conn->rebound = true; /* not really, but oh well... */
* SASL mech is inherited from the module that defined the connection
* pool.
*/
- if (inst->use_referral_credentials) {
+ if (pool_inst->use_referral_credentials) {
LDAPURLDesc *ldap_url;
int ret;
char **ext;
} else
# endif
{
- admin_identity = conn->inst->admin_identity;
- admin_password = conn->inst->admin_password;
+ admin_identity = pool_inst->admin_identity;
+ admin_password = pool_inst->admin_password;
}
status = rlm_ldap_bind(inst, NULL, &conn, admin_identity, admin_password,
- &conn->inst->admin_sasl, false, NULL, NULL, NULL);
+ &conn->pool_inst->admin_sasl, false, NULL, NULL, NULL);
if (status != LDAP_PROC_SUCCESS) {
ldap_get_option(handle, LDAP_OPT_ERROR_NUMBER, &ldap_errno);
int ldap_errno, ldap_version;
- rlm_ldap_t *inst = instance;
- ldap_handle_t *conn;
- LDAP *handle = NULL;
+ rlm_ldap_t const *inst = talloc_get_type_abort(instance, rlm_ldap_t);
+ ldap_pool_inst_t const *pool_inst = &inst->pool_inst;
+ ldap_handle_t *conn;
+ LDAP *handle = NULL;
- DEBUG("Connecting to %s", inst->server);
+ DEBUG("Connecting to %s", pool_inst->server);
#ifdef HAVE_LDAP_INITIALIZE
- ldap_errno = ldap_initialize(&handle, inst->server);
+ ldap_errno = ldap_initialize(&handle, pool_inst->server);
if (ldap_errno != LDAP_SUCCESS) {
ERROR("ldap_initialize failed: %s", ldap_err2string(ldap_errno));
return NULL;
}
#else
- handle = ldap_init(inst->server, inst->port);
+ handle = ldap_init(pool_inst->server, pool_inst->port);
if (!handle) {
ERROR("ldap_init failed");
return NULL;
conn = talloc_zero(ctx, ldap_handle_t);
if (!conn) return NULL;
- conn->inst = inst;
+ conn->pool_inst = pool_inst;
conn->handle = handle;
conn->rebound = false;
conn->referred = false;
/*
* Leave "dereference" unset to use the OpenLDAP default.
*/
- if (inst->dereference_str) {
- do_ldap_option(LDAP_OPT_DEREF, "dereference", &(inst->dereference));
+ if (pool_inst->dereference_str) {
+ do_ldap_option(LDAP_OPT_DEREF, "dereference", &(pool_inst->dereference));
}
/*
* Leave "chase_referrals" unset to use the OpenLDAP default.
*/
- if (!inst->chase_referrals_unset) {
- if (inst->chase_referrals) {
+ if (!pool_inst->chase_referrals_unset) {
+ if (pool_inst->chase_referrals) {
do_ldap_option(LDAP_OPT_REFERRALS, "chase_referrals", LDAP_OPT_ON);
- if (inst->rebind == true) {
+ if (pool_inst->rebind == true) {
#if LDAP_SET_REBIND_PROC_ARGS == 3
ldap_set_rebind_proc(conn->handle, rlm_ldap_rebind, conn);
#endif
#ifdef LDAP_OPT_NETWORK_TIMEOUT
/*
- * A value of zero results in an instant failure.
+ * A value of zero results in an pool_instant failure.
*
* When most people specify zero they mean infinite.
*
}
#endif
- do_ldap_option(LDAP_OPT_TIMELIMIT, "srv_timelimit", &(inst->srv_timelimit));
+ do_ldap_option(LDAP_OPT_TIMELIMIT, "srv_timelimit", &(pool_inst->srv_timelimit));
ldap_version = LDAP_VERSION3;
do_ldap_option(LDAP_OPT_PROTOCOL_VERSION, "ldap_version", &ldap_version);
#ifdef LDAP_OPT_X_KEEPALIVE_IDLE
- do_ldap_option(LDAP_OPT_X_KEEPALIVE_IDLE, "keepalive_idle", &(inst->keepalive_idle));
+ do_ldap_option(LDAP_OPT_X_KEEPALIVE_IDLE, "keepalive_idle", &(pool_inst->keepalive_idle));
#endif
#ifdef LDAP_OPT_X_KEEPALIVE_PROBES
- do_ldap_option(LDAP_OPT_X_KEEPALIVE_PROBES, "keepalive_probes", &(inst->keepalive_probes));
+ do_ldap_option(LDAP_OPT_X_KEEPALIVE_PROBES, "keepalive_probes", &(pool_inst->keepalive_probes));
#endif
#ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL
- do_ldap_option(LDAP_OPT_X_KEEPALIVE_INTERVAL, "keepalive_interval", &(inst->keepalive_interval));
+ do_ldap_option(LDAP_OPT_X_KEEPALIVE_INTERVAL, "keepalive_interval", &(pool_inst->keepalive_interval));
#endif
#ifdef HAVE_LDAP_START_TLS_S
/*
* Set all of the TLS options
*/
- if (inst->tls_mode) do_ldap_option(LDAP_OPT_X_TLS, "tls_mode", &(inst->tls_mode));
+ if (pool_inst->tls_mode) do_ldap_option(LDAP_OPT_X_TLS, "tls_mode", &(pool_inst->tls_mode));
- maybe_ldap_option(LDAP_OPT_X_TLS_CACERTFILE, "ca_file", inst->tls_ca_file);
- maybe_ldap_option(LDAP_OPT_X_TLS_CACERTDIR, "ca_path", inst->tls_ca_path);
+ maybe_ldap_option(LDAP_OPT_X_TLS_CACERTFILE, "ca_file", pool_inst->tls_ca_file);
+ maybe_ldap_option(LDAP_OPT_X_TLS_CACERTDIR, "ca_path", pool_inst->tls_ca_path);
/*
* Set certificate options
*/
- maybe_ldap_option(LDAP_OPT_X_TLS_CERTFILE, "certificate_file", inst->tls_certificate_file);
- maybe_ldap_option(LDAP_OPT_X_TLS_KEYFILE, "private_key_file", inst->tls_private_key_file);
+ maybe_ldap_option(LDAP_OPT_X_TLS_CERTFILE, "certificate_file", pool_inst->tls_certificate_file);
+ maybe_ldap_option(LDAP_OPT_X_TLS_KEYFILE, "private_key_file", pool_inst->tls_private_key_file);
# ifdef LDAP_OPT_X_TLS_NEVER
- if (inst->tls_require_cert_str) {
- do_ldap_option(LDAP_OPT_X_TLS_REQUIRE_CERT, "require_cert", &inst->tls_require_cert);
+ if (pool_inst->tls_require_cert_str) {
+ do_ldap_option(LDAP_OPT_X_TLS_REQUIRE_CERT, "require_cert", &pool_inst->tls_require_cert);
}
# endif
/*
* And finally start the TLS code.
*/
- if (inst->start_tls) {
- if (inst->port == 636) {
+ if (pool_inst->start_tls) {
+ if (pool_inst->port == 636) {
WARN("Told to Start TLS on LDAPS port this will probably fail, please correct the "
"configuration");
}
}
#endif /* HAVE_LDAP_START_TLS_S */
- status = rlm_ldap_bind(inst, NULL, &conn, conn->inst->admin_identity, conn->inst->admin_password,
- &(conn->inst->admin_sasl), false, timeout, NULL, NULL);
+ status = rlm_ldap_bind(inst, NULL, &conn, conn->pool_inst->admin_identity, conn->pool_inst->admin_password,
+ &(conn->pool_inst->admin_sasl), false, timeout, NULL, NULL);
if (status != LDAP_PROC_SUCCESS) goto error;
/*
- * This allows multiple connections to spawn simultaneously,
- * but prevents them being used until we've directory
- * directory capabilities.
+ * Only error out on memory allocation errors
*/
- if (!inst->directory) {
- pthread_mutex_lock(&inst->directory_mutex);
- if (!inst->directory) {
- /*
- * Only error out on memory allocation errors
- */
- if (rlm_ldap_directory_alloc(NULL, &inst->directory, inst, &conn) < 0) goto error;
- pthread_mutex_unlock(&inst->directory_mutex);
- }
- }
+ if (rlm_ldap_directory_alloc(conn, &conn->directory, inst, &conn) < 0) goto error;
return conn;
/*
* Deprecated attributes
*/
- { FR_CONF_OFFSET("ca_file", PW_TYPE_FILE_INPUT, rlm_ldap_t, tls_ca_file) },
+ { FR_CONF_OFFSET("ca_file", PW_TYPE_FILE_INPUT, ldap_pool_inst_t, tls_ca_file) },
- { FR_CONF_OFFSET("ca_path", PW_TYPE_FILE_INPUT, rlm_ldap_t, tls_ca_path) },
+ { FR_CONF_OFFSET("ca_path", PW_TYPE_FILE_INPUT, ldap_pool_inst_t, tls_ca_path) },
- { FR_CONF_OFFSET("certificate_file", PW_TYPE_FILE_INPUT, rlm_ldap_t, tls_certificate_file) },
+ { FR_CONF_OFFSET("certificate_file", PW_TYPE_FILE_INPUT, ldap_pool_inst_t, tls_certificate_file) },
- { FR_CONF_OFFSET("private_key_file", PW_TYPE_FILE_INPUT, rlm_ldap_t, tls_private_key_file) },
-
- { FR_CONF_OFFSET("random_file", PW_TYPE_FILE_EXISTS, rlm_ldap_t, tls_random_file) },
+ { FR_CONF_OFFSET("private_key_file", PW_TYPE_FILE_INPUT, ldap_pool_inst_t, tls_private_key_file) },
/*
* LDAP Specific TLS attributes
*/
- { FR_CONF_OFFSET("start_tls", PW_TYPE_BOOLEAN, rlm_ldap_t, start_tls), .dflt = "no" },
- { FR_CONF_OFFSET("require_cert", PW_TYPE_STRING, rlm_ldap_t, tls_require_cert_str) },
+ { FR_CONF_OFFSET("start_tls", PW_TYPE_BOOLEAN, ldap_pool_inst_t, start_tls), .dflt = "no" },
+
+ { FR_CONF_OFFSET("require_cert", PW_TYPE_STRING, ldap_pool_inst_t, tls_require_cert_str) },
+
CONF_PARSER_TERMINATOR
};
*/
static CONF_PARSER option_config[] = {
/*
- * Debugging flags to the server
+ * Pool config items
*/
- { FR_CONF_OFFSET("ldap_debug", PW_TYPE_INTEGER, rlm_ldap_t, ldap_debug), .dflt = "0x0000" },
-
- { FR_CONF_OFFSET("dereference", PW_TYPE_STRING, rlm_ldap_t, dereference_str) },
+ { FR_CONF_OFFSET("chase_referrals", PW_TYPE_BOOLEAN, rlm_ldap_t, pool_inst.chase_referrals) },
- { FR_CONF_OFFSET("chase_referrals", PW_TYPE_BOOLEAN, rlm_ldap_t, chase_referrals) },
+ { FR_CONF_OFFSET("use_referral_credentials", PW_TYPE_BOOLEAN, rlm_ldap_t, pool_inst.use_referral_credentials), .dflt = "no" },
- { FR_CONF_OFFSET("use_referral_credentials", PW_TYPE_BOOLEAN, rlm_ldap_t, use_referral_credentials), .dflt = "no" },
-
- { FR_CONF_OFFSET("rebind", PW_TYPE_BOOLEAN, rlm_ldap_t, rebind) },
+ { FR_CONF_OFFSET("rebind", PW_TYPE_BOOLEAN, rlm_ldap_t, pool_inst.rebind) },
#ifdef LDAP_CONTROL_X_SESSION_TRACKING
- { FR_CONF_OFFSET("session_tracking", PW_TYPE_BOOLEAN, rlm_ldap_t, session_tracking), .dflt = "no" },
+ { FR_CONF_OFFSET("session_tracking", PW_TYPE_BOOLEAN, rlm_ldap_t, pool_inst.session_tracking), .dflt = "no" },
#endif
#ifdef LDAP_OPT_NETWORK_TIMEOUT
/* timeout on network activity */
- { FR_CONF_DEPRECATED("net_timeout", PW_TYPE_INTEGER, rlm_ldap_t, net_timeout), .dflt = "10" },
+ { FR_CONF_DEPRECATED("net_timeout", PW_TYPE_INTEGER, rlm_ldap_t, pool_inst.net_timeout), .dflt = "10" },
#endif
- /* timeout for search results */
- { FR_CONF_OFFSET("res_timeout", PW_TYPE_INTEGER, rlm_ldap_t, res_timeout), .dflt = "20" },
-
- /* allow server unlimited time for search (server-side limit) */
- { FR_CONF_OFFSET("srv_timelimit", PW_TYPE_INTEGER, rlm_ldap_t, srv_timelimit), .dflt = "20" },
-
#ifdef LDAP_OPT_X_KEEPALIVE_IDLE
- { FR_CONF_OFFSET("idle", PW_TYPE_INTEGER, rlm_ldap_t, keepalive_idle), .dflt = "60" },
+ { FR_CONF_OFFSET("idle", PW_TYPE_INTEGER, rlm_ldap_t, pool_inst.keepalive_idle), .dflt = "60" },
#endif
#ifdef LDAP_OPT_X_KEEPALIVE_PROBES
- { FR_CONF_OFFSET("probes", PW_TYPE_INTEGER, rlm_ldap_t, keepalive_probes), .dflt = "3" },
+ { FR_CONF_OFFSET("probes", PW_TYPE_INTEGER, rlm_ldap_t, pool_inst.keepalive_probes), .dflt = "3" },
#endif
#ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL
- { FR_CONF_OFFSET("interval", PW_TYPE_INTEGER, rlm_ldap_t, keepalive_interval), .dflt = "30" },
+ { FR_CONF_OFFSET("interval", PW_TYPE_INTEGER, rlm_ldap_t, pool_inst.keepalive_interval), .dflt = "30" },
#endif
+
+ { FR_CONF_OFFSET("dereference", PW_TYPE_STRING, rlm_ldap_t, pool_inst.dereference_str) },
+
+ /* allow server unlimited time for search (server-side limit) */
+ { FR_CONF_OFFSET("srv_timelimit", PW_TYPE_INTEGER, rlm_ldap_t, pool_inst.srv_timelimit), .dflt = "20" },
+
+ /*
+ * Instance config items
+ */
+ /* timeout for search results */
+ { FR_CONF_OFFSET("res_timeout", PW_TYPE_INTEGER, rlm_ldap_t, res_timeout), .dflt = "20" },
+
CONF_PARSER_TERMINATOR
};
+static const CONF_PARSER global_config[] = {
+ { FR_CONF_OFFSET("random_file", PW_TYPE_FILE_EXISTS, rlm_ldap_t, tls_random_file) },
+
+ { FR_CONF_OFFSET("ldap_debug", PW_TYPE_INTEGER, rlm_ldap_t, ldap_debug), .dflt = "0x0000" }, /* Debugging flags to the server */
+
+ CONF_PARSER_TERMINATOR
+};
static const CONF_PARSER module_config[] = {
- { FR_CONF_OFFSET("server", PW_TYPE_STRING | PW_TYPE_MULTI, rlm_ldap_t, config_server) }, /* Do not set to required */
- { FR_CONF_OFFSET("port", PW_TYPE_SHORT, rlm_ldap_t, port) },
+ /*
+ * Pool config items
+ */
+ { FR_CONF_OFFSET("server", PW_TYPE_STRING | PW_TYPE_MULTI, rlm_ldap_t, pool_inst.config_server) }, /* Do not set to required */
+
+ { FR_CONF_OFFSET("port", PW_TYPE_SHORT, rlm_ldap_t, pool_inst.port) },
- { FR_CONF_OFFSET("identity", PW_TYPE_STRING, rlm_ldap_t, admin_identity) },
- { FR_CONF_OFFSET("password", PW_TYPE_STRING | PW_TYPE_SECRET, rlm_ldap_t, admin_password) },
+ { FR_CONF_OFFSET("identity", PW_TYPE_STRING, rlm_ldap_t, pool_inst.admin_identity) },
+ { FR_CONF_OFFSET("password", PW_TYPE_STRING | PW_TYPE_SECRET, rlm_ldap_t, pool_inst.admin_password) },
- { FR_CONF_OFFSET("sasl", PW_TYPE_SUBSECTION, rlm_ldap_t, admin_sasl), .subcs = (void const *) sasl_mech_static },
+ { FR_CONF_OFFSET("sasl", PW_TYPE_SUBSECTION, rlm_ldap_t, pool_inst.admin_sasl), .subcs = (void const *) sasl_mech_static },
{ FR_CONF_OFFSET("valuepair_attribute", PW_TYPE_STRING, rlm_ldap_t, valuepair_attr) },
{ FR_CONF_POINTER("options", PW_TYPE_SUBSECTION, NULL), .subcs = (void const *) option_config },
- { FR_CONF_POINTER("tls", PW_TYPE_SUBSECTION, NULL), .subcs = (void const *) tls_config },
+ { FR_CONF_POINTER("global", PW_TYPE_SUBSECTION, NULL), .subcs = (void const *) global_config },
+
+ { FR_CONF_OFFSET("tls", PW_TYPE_SUBSECTION, rlm_ldap_t, pool_inst), .subcs = (void const *) tls_config },
CONF_PARSER_TERMINATOR
};
/*
* Expand dynamic SASL fields
*/
- if (conn->inst->user_sasl.mech) {
+ if (inst->user_sasl.mech) {
memset(&sasl, 0, sizeof(sasl));
if (tmpl_expand(&sasl.mech, sasl_mech_buff, sizeof(sasl_mech_buff), request,
- conn->inst->user_sasl.mech, rlm_ldap_escape_func, inst) < 0) {
+ inst->user_sasl.mech, rlm_ldap_escape_func, inst) < 0) {
REDEBUG("Failed expanding user.sasl.mech: %s", fr_strerror());
rcode = RLM_MODULE_FAIL;
goto finish;
}
- if (conn->inst->user_sasl.proxy) {
+ if (inst->user_sasl.proxy) {
if (tmpl_expand(&sasl.proxy, sasl_proxy_buff, sizeof(sasl_proxy_buff), request,
- conn->inst->user_sasl.proxy, rlm_ldap_escape_func, inst) < 0) {
+ inst->user_sasl.proxy, rlm_ldap_escape_func, inst) < 0) {
REDEBUG("Failed expanding user.sasl.proxy: %s", fr_strerror());
rcode = RLM_MODULE_FAIL;
goto finish;
}
}
- if (conn->inst->user_sasl.realm) {
+ if (inst->user_sasl.realm) {
if (tmpl_expand(&sasl.realm, sasl_realm_buff, sizeof(sasl_realm_buff), request,
- conn->inst->user_sasl.realm, rlm_ldap_escape_func, inst) < 0) {
+ inst->user_sasl.realm, rlm_ldap_escape_func, inst) < 0) {
REDEBUG("Failed expanding user.sasl.realm: %s", fr_strerror());
rcode = RLM_MODULE_FAIL;
goto finish;
}
conn->rebound = true;
status = rlm_ldap_bind(inst, request, &conn, dn, request->password->vp_strvalue,
- conn->inst->user_sasl.mech ? &sasl : NULL, true, NULL, NULL, NULL);
+ inst->user_sasl.mech ? &sasl : NULL, true, NULL, NULL, NULL);
switch (status) {
case LDAP_PROC_SUCCESS:
rcode = RLM_MODULE_OK;
RINDENT();
if (rlm_ldap_map_do(inst, request, conn->handle, &expanded, entry) > 0) rcode = RLM_MODULE_UPDATED;
REXDENT();
- rlm_ldap_check_reply(inst, request);
+ rlm_ldap_check_reply(inst, request, conn);
}
finish:
if (inst->userobj_sort_ctrl) ldap_control_free(inst->userobj_sort_ctrl);
#endif
- pthread_mutex_destroy(&inst->directory_mutex);
-
fr_connection_pool_free(inst->pool);
talloc_free(inst->user_map);
- talloc_free(inst->directory);
return 0;
}
options = cf_section_sub_find(conf, "options");
if (!options || !cf_pair_find(options, "chase_referrals")) {
- inst->chase_referrals_unset = true; /* use OpenLDAP defaults */
+ inst->pool_inst.chase_referrals_unset = true; /* use OpenLDAP defaults */
}
/*
* connection pool.
*/
if (!cf_pair_find(conf, "pool")) {
- if (!inst->config_server) {
+ if (!inst->pool_inst.config_server) {
cf_log_err_cs(conf, "Configuration item 'server' must have a value");
goto error;
}
goto error;
}
- if (inst->admin_sasl.mech) {
+ if (inst->pool_inst.admin_sasl.mech) {
cf_log_err_cs(conf, "Configuration item 'sasl.mech' not supported. "
"Linked libldap does not provide ldap_sasl_interactive_bind function");
goto error;
/*
* Now iterate over all the 'server' config items
*/
- for (i = 0; i < talloc_array_length(inst->config_server); i++) {
- char const *value = inst->config_server[i];
+ for (i = 0; i < talloc_array_length(inst->pool_inst.config_server); i++) {
+ char const *value = inst->pool_inst.config_server[i];
size_t j;
/*
*/
if (ldap_url->lud_scheme) {
if (strcmp(ldap_url->lud_scheme, "ldaps") == 0) {
- if (inst->start_tls == true) {
+ if (inst->pool_inst.start_tls == true) {
cf_log_err_cs(conf, "ldaps:// scheme is not compatible "
"with 'start_tls'");
goto ldap_url_error;
/*
* URL port overrides configured port.
*/
- ldap_url->lud_port = inst->port;
+ ldap_url->lud_port = inst->pool_inst.port;
/*
* If there's no URL port, then set it to the default
cf_log_err_cs(conf, "Failed recombining URL components");
goto ldap_url_error;
}
- inst->server = talloc_asprintf_append(inst->server, "%s ", url);
+ inst->pool_inst.server = talloc_asprintf_append(inst->pool_inst.server, "%s ", url);
free(url);
}
# else
* port, we use the hard-coded default.
*/
if (set_port_maybe) {
- ldap_url->lud_port = inst->port;
+ ldap_url->lud_port = inst->pool_inst.port;
if (!ldap_url->lud_port) ldap_url->lud_port = default_port;
}
- inst->server = talloc_asprintf_append(inst->server, "%s:%i ",
+ inst->pool_inst.server = talloc_asprintf_append(inst->pool_inst.server, "%s:%i ",
ldap_url->lud_host ? ldap_url->lud_host : "localhost",
ldap_url->lud_port);
# endif
int port = 0;
size_t len;
- port = inst->port;
+ port = inst->pool_inst.port;
/*
* We don't support URLs if the library didn't provide
}
if (port == 0) port = LDAP_PORT;
- inst->server = talloc_asprintf_append(inst->server, "ldap://%.*s:%i ", (int) len, value, port);
+ inst->pool_inst.server = talloc_asprintf_append(inst->pool_inst.server, "ldap://%.*s:%i ", (int) len, value, port);
#else
/*
* ldap_init takes port, which can be overridden by :port so
* we don't need to do any parsing here.
*/
- inst->server = talloc_asprintf_append(inst->server, "%s ", value);
+ inst->pool_inst.server = talloc_asprintf_append(inst->pool_inst.server, "%s ", value);
#endif
}
}
- if (inst->server) inst->server[talloc_array_length(inst->server) - 2] = '\0';
- DEBUG4("rlm_ldap (%s) - LDAP server string: %s", inst->name, inst->server);
+ /*
+ * inst->pool_inst.server be unset if connection pool sharing is used.
+ */
+ if (inst->pool_inst.server) {
+ inst->pool_inst.server[talloc_array_length(inst->pool_inst.server) - 2] = '\0';
+ DEBUG4("rlm_ldap (%s) - LDAP server string: %s", inst->name, inst->pool_inst.server);
+ }
#ifdef LDAP_OPT_X_TLS_NEVER
/*
* Workaround for servers which support LDAPS but not START TLS
*/
- if (inst->port == LDAPS_PORT || inst->tls_mode) {
- inst->tls_mode = LDAP_OPT_X_TLS_HARD;
+ if (inst->pool_inst.port == LDAPS_PORT || inst->pool_inst.tls_mode) {
+ inst->pool_inst.tls_mode = LDAP_OPT_X_TLS_HARD;
} else {
- inst->tls_mode = 0;
+ inst->pool_inst.tls_mode = 0;
}
#endif
/*
* Convert dereference strings to enumerated constants
*/
- if (inst->dereference_str) {
- inst->dereference = fr_str2int(ldap_dereference, inst->dereference_str, -1);
- if (inst->dereference < 0) {
+ if (inst->pool_inst.dereference_str) {
+ inst->pool_inst.dereference = fr_str2int(ldap_dereference, inst->pool_inst.dereference_str, -1);
+ if (inst->pool_inst.dereference < 0) {
cf_log_err_cs(conf, "Invalid 'dereference' value \"%s\", expected 'never', 'searching', "
- "'finding' or 'always'", inst->dereference_str);
+ "'finding' or 'always'", inst->pool_inst.dereference_str);
goto error;
}
}
}
#endif
- if (inst->tls_require_cert_str) {
+ if (inst->pool_inst.tls_require_cert_str) {
#ifdef LDAP_OPT_X_TLS_NEVER
/*
* Convert cert strictness to enumerated constants
*/
- inst->tls_require_cert = fr_str2int(ldap_tls_require_cert, inst->tls_require_cert_str, -1);
- if (inst->tls_require_cert < 0) {
+ inst->pool_inst.tls_require_cert = fr_str2int(ldap_tls_require_cert,
+ inst->pool_inst.tls_require_cert_str, -1);
+ if (inst->pool_inst.tls_require_cert < 0) {
cf_log_err_cs(conf, "Invalid 'tls.require_cert' value \"%s\", expected 'never', "
- "'demand', 'allow', 'try' or 'hard'", inst->tls_require_cert_str);
+ "'demand', 'allow', 'try' or 'hard'", inst->pool_inst.tls_require_cert_str);
goto error;
}
#else
return -1;
}
- /*
- * Initialise the directory mutex
- */
- pthread_mutex_init(&inst->directory_mutex, NULL);
-
/*
* Set global options
*/
extern FR_NAME_NUMBER const ldap_supported_extensions[];
-typedef struct ldap_instance rlm_ldap_t;
+typedef struct rlm_ldap_s rlm_ldap_t;
typedef struct ldap_acct_section {
CONF_SECTION *cs; //!< Section configuration.
//!< we've finished using it.
} rlm_ldap_control_t;
-/** Tracks the state of a libldap connection handle
- *
- */
-typedef struct ldap_handle {
- LDAP *handle; //!< libldap handle.
- bool rebound; //!< Whether the connection has been rebound to something
- //!< other than the admin user.
- bool referred; //!< Whether the connection is now established a server
- //!< other than the configured one.
-
- rlm_ldap_control_t serverctrls[LDAP_MAX_CONTROLS + 1]; //!< Server controls to use for all operations with
- //!< this handle.
- rlm_ldap_control_t clientctrls[LDAP_MAX_CONTROLS + 1]; //!< Client controls to use for all operations with
- //!< this handle.
- int serverctrls_cnt; //!< Number of server controls associated with the handle.
- int clientctrls_cnt; //!< Number of client controls associated with the handle.
-
- rlm_ldap_t const *inst; //!< rlm_ldap configuration.
-} ldap_handle_t;
typedef enum {
LDAP_DIRECTORY_UNKNOWN = 0, //!< We can't determine the directory server.
//!< password.
} ldap_directory_t;
-struct ldap_instance {
- char const *name; //!< Instance name.
-
- CONF_SECTION *cs; //!< Main configuration section for this instance.
- fr_connection_pool_t *pool; //!< Connection pool instance.
-
- char const **config_server; //!< Server set in the config.
+/** Pool configuration
+ *
+ * Must not be passed into functions except via the connection handle
+ * this avoids problems with not using the connection pool configuration.
+ */
+typedef struct {
char *server; //!< Initial server to bind to.
+ char const **config_server; //!< Server set in the config.
+
uint16_t port; //!< Port to use when binding to the server.
char const *admin_identity; //!< Identity we bind as when we need to query the LDAP
ldap_sasl admin_sasl; //!< SASL parameters used when binding as the admin.
- char const *dereference_str; //!< When to dereference (never, searching, finding, always)
int dereference; //!< libldap value specifying dereferencing behaviour.
+ char const *dereference_str; //!< When to dereference (never, searching, finding, always)
bool chase_referrals; //!< If the LDAP server returns a referral to another server
//!< or point in the tree, follow it, establishing new
//!< referrals on the same server, but won't bind to other
//!< servers.
- uint32_t ldap_debug; //!< Debug flag for the SDK.
+ /*
+ * TLS items.
+ */
+ int tls_mode;
+ bool start_tls; //!< Send the Start TLS message to the LDAP directory
+ //!< to start encrypted communications using the standard
+ //!< LDAP port.
+
+ char const *tls_ca_file; //!< Sets the full path to a CA certificate (used to validate
+ //!< the certificate the server presents).
- ldap_directory_t *directory; //!< Server capabilities.
- pthread_mutex_t directory_mutex; //!< Sync modifications to directory structure.
+ char const *tls_ca_path; //!< Sets the path to a directory containing CA certificates.
+
+ char const *tls_certificate_file; //!< Sets the path to the public certificate file we present
+ //!< to the servers.
+
+ char const *tls_private_key_file; //!< Sets the path to the private key for our public
+ //!< certificate.
+
+ char const *tls_require_cert_str; //!< Sets requirements for validating the certificate the
+ //!< server presents.
+
+ int tls_require_cert; //!< OpenLDAP constant representing the require cert string.
+
+ /*
+ * Options
+ */
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+ bool session_tracking; //!< Whether we add session tracking controls, which help
+ //!< identify the autz or acct session the commands were
+ //!< issued for.
+#endif
+
+ /*
+ * For keep-alives.
+ */
+#ifdef LDAP_OPT_X_KEEPALIVE_IDLE
+ uint32_t keepalive_idle; //!< Number of seconds a connections needs to remain idle
+ //!< before TCP starts sending keepalive probes.
+#endif
+#ifdef LDAP_OPT_X_KEEPALIVE_PROBES
+ uint32_t keepalive_probes; //!< Number of missed timeouts before the connection is
+ //!< dropped.
+#endif
+#ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL
+ uint32_t keepalive_interval; //!< Interval between keepalive probes.
+#endif
+
+ /*
+ * Search timelimits
+ */
+ uint32_t srv_timelimit; //!< How long the server should spent on a single request
+ //!< (also bounded by value on the server).
+} ldap_pool_inst_t;
+
+struct rlm_ldap_s {
+ char const *name; //!< Instance name.
+
+ CONF_SECTION *cs; //!< Main configuration section for this instance.
bool expect_password; //!< True if the user_map included a mapping between an LDAP
//!< attribute and one of our password reference attributes.
*/
vp_map_t *user_map; //!< Attribute map applied to users and profiles.
+ /*
+ * Search time limits
+ */
+ uint32_t res_timeout; //!< How long we wait for a result from the server.
+
/*
* User object attributes and filters
*/
bool access_positive; //!< If true the presence of the attribute will allow access,
//!< else it will deny access.
+ ldap_sasl_dynamic user_sasl; //!< SASL parameters used when binding as the user.
+
char const *valuepair_attr; //!< Generic dynamic mapping attribute, contains a RADIUS
//!< attribute and value.
- ldap_sasl_dynamic user_sasl; //!< SASL parameters used when binding as the user.
/*
* Group object attributes and filters
ldap_acct_section_t *postauth; //!< Modify mappings for post-auth.
ldap_acct_section_t *accounting; //!< Modify mappings for accounting.
- /*
- * TLS items. We should really normalize these with the
- * TLS code in 3.0.
- */
- int tls_mode;
- bool start_tls; //!< Send the Start TLS message to the LDAP directory
- //!< to start encrypted communications using the standard
- //!< LDAP port.
-
- char const *tls_ca_file; //!< Sets the full path to a CA certificate (used to validate
- //!< the certificate the server presents).
-
- char const *tls_ca_path; //!< Sets the path to a directory containing CA certificates.
-
- char const *tls_certificate_file; //!< Sets the path to the public certificate file we present
- //!< to the servers.
-
- char const *tls_private_key_file; //!< Sets the path to the private key for our public
- //!< certificate.
-
- char const *tls_random_file; //!< Path to the random file if /dev/random and /dev/urandom
- //!< are unavailable.
-
- char const *tls_require_cert_str; //!< Sets requirements for validating the certificate the
- //!< server presents.
-
- int tls_require_cert; //!< OpenLDAP constant representing the require cert string.
-
- /*
- * Options
- */
-#ifdef LDAP_CONTROL_X_SESSION_TRACKING
- bool session_tracking; //!< Whether we add session tracking controls, which help
- //!< identify the autz or acct session the commands were
- //!< issued for.
-#endif
- uint32_t res_timeout; //!< How long we wait for a result from the server.
- uint32_t srv_timelimit; //!< How long the server should spent on a single request
- //!< (also bounded by value on the server).
-
#ifdef WITH_EDIR
/*
* eDir support
bool edir_autz; //!< If true, and we have the Universal Password, bind with it
//!< to perform additional authorisation checks.
#endif
+
+ fr_connection_pool_t *pool; //!< Connection pool instance.
+ ldap_pool_inst_t pool_inst; //!< Connection configuration instance.
+
/*
- * For keep-alives.
+ * Global config
*/
-#ifdef LDAP_OPT_X_KEEPALIVE_IDLE
- uint32_t keepalive_idle; //!< Number of seconds a connections needs to remain idle
- //!< before TCP starts sending keepalive probes.
-#endif
-#ifdef LDAP_OPT_X_KEEPALIVE_PROBES
- uint32_t keepalive_probes; //!< Number of missed timeouts before the connection is
- //!< dropped.
-#endif
-#ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL
- uint32_t keepalive_interval; //!< Interval between keepalive probes.
-#endif
+ char const *tls_random_file; //!< Path to the random file if /dev/random and /dev/urandom
+ //!< are unavailable.
+
+ uint32_t ldap_debug; //!< Debug flag for the SDK.
};
+/** Tracks the state of a libldap connection handle
+ *
+ */
+typedef struct ldap_handle {
+ LDAP *handle; //!< libldap handle.
+ bool rebound; //!< Whether the connection has been rebound to something
+ //!< other than the admin user.
+ bool referred; //!< Whether the connection is now established a server
+ //!< other than the configured one.
+
+ rlm_ldap_control_t serverctrls[LDAP_MAX_CONTROLS + 1]; //!< Server controls to use for all operations with
+ //!< this handle.
+ rlm_ldap_control_t clientctrls[LDAP_MAX_CONTROLS + 1]; //!< Client controls to use for all operations with
+ //!< this handle.
+ int serverctrls_cnt; //!< Number of server controls associated with the handle.
+ int clientctrls_cnt; //!< Number of client controls associated with the handle.
+
+ ldap_directory_t *directory; //!< The type of directory we're connected to.
+
+ ldap_pool_inst_t const *pool_inst; //!< rlm_ldap connection configuration.
+ rlm_ldap_t const *inst; //!< rlm_ldap pool inst.
+} ldap_handle_t;
+
/** Result of expanding the RHS of a set of maps
*
* Used to store the array of attributes we'll be querying for.
rlm_rcode_t rlm_ldap_check_access(rlm_ldap_t const *inst, REQUEST *request, ldap_handle_t const *conn,
LDAPMessage *entry);
-void rlm_ldap_check_reply(rlm_ldap_t const *inst, REQUEST *request);
+void rlm_ldap_check_reply(rlm_ldap_t const *inst, REQUEST *request, ldap_handle_t const *conn);
/*
* ldap.c - Callbacks for the connection pool API.
/*
* directory.c - Get directory capabilities from the remote server
*/
-int rlm_ldap_directory_alloc(TALLOC_CTX *ctx, ldap_directory_t **out, rlm_ldap_t *inst, ldap_handle_t **pconn);
+int rlm_ldap_directory_alloc(TALLOC_CTX *ctx, ldap_directory_t **out, rlm_ldap_t const *inst, ldap_handle_t **pconn);
/*
* edir.c - Magic extensions for Novell