int fr_ldap_map_expand(fr_ldap_map_exp_t *expanded, request_t *request, fr_map_list_t const *maps);
-int fr_ldap_map_do(request_t *request, fr_ldap_connection_t *conn,
+int fr_ldap_map_do(request_t *request, LDAP *handle,
char const *valuepair_attr, fr_ldap_map_exp_t const *expanded, LDAPMessage *entry);
/*
* This is *NOT* atomic, but there's no condition for which we should error out...
*
* @param[in] request Current request.
- * @param[in] conn associated with entry.
+ * @param[in] handle associated with entry.
* @param[in] valuepair_attr Treat attribute with this name as holding complete AVP definitions.
* @param[in] expanded attributes (rhs of map).
* @param[in] entry to retrieve attributes from.
* - Number of maps successfully applied.
* - -1 on failure.
*/
-int fr_ldap_map_do(request_t *request, fr_ldap_connection_t *conn,
+int fr_ldap_map_do(request_t *request, LDAP *handle,
char const *valuepair_attr, fr_ldap_map_exp_t const *expanded, LDAPMessage *entry)
{
map_t const *map = NULL;
/*
* Binary safe
*/
- result.values = ldap_get_values_len(conn->handle, entry, name);
+ result.values = ldap_get_values_len(handle, entry, name);
if (!result.values) {
RDEBUG3("Attribute \"%s\" not found in LDAP object", name);
struct berval **values;
int count, i;
- values = ldap_get_values_len(conn->handle, entry, valuepair_attr);
+ values = ldap_get_values_len(handle, entry, valuepair_attr);
count = ldap_count_values_len(values);
for (i = 0; i < count; i++) {
talloc_free(request);
return -1;
}
- if (fr_ldap_map_do(request, conn, NULL, &expanded, msg) < 0) goto error;
+ if (fr_ldap_map_do(request, conn->handle, NULL, &expanded, msg) < 0) goto error;
// request_enqueue(request);
* @param[out] p_result The result of trying to resolve a group name to a dn.
* @param[in] inst rlm_ldap configuration.
* @param[in] request Current request.
- * @param[in,out] pconn to use. May change as this function calls functions which auto re-connect.
+ * @param[in] ttrunk to use.
* @param[in] names to convert to DNs (NULL terminated).
* @param[out] out Where to write the DNs. DNs must be freed with
* ldap_memfree(). Will be NULL terminated.
* @return One of the RLM_MODULE_* values.
*/
static unlang_action_t rlm_ldap_group_name2dn(rlm_rcode_t *p_result, rlm_ldap_t const *inst, request_t *request,
- fr_ldap_connection_t **pconn,
+ fr_ldap_thread_trunk_t *ttrunk,
char **names, char **out, size_t outlen)
{
rlm_rcode_t rcode = RLM_MODULE_OK;
- fr_ldap_rcode_t status;
int ldap_errno;
unsigned int name_cnt = 0;
unsigned int entry_cnt;
char const *attrs[] = { NULL };
- LDAPMessage *result = NULL, *entry;
+ LDAPMessage *entry;
+ fr_ldap_query_t *query = NULL;
char **name = names;
char **dn = out;
RETURN_MODULE_INVALID;
}
- status = fr_ldap_search(&result, request, pconn, base_dn, inst->groupobj_scope,
- filter, attrs, NULL, NULL);
- switch (status) {
- case LDAP_PROC_SUCCESS:
+ if (fr_ldap_trunk_search(unlang_interpret_frame_talloc_ctx(request), &query, request, ttrunk, base_dn,
+ inst->groupobj_scope, filter, attrs, NULL, NULL) < 0 ) {
+ rcode = RLM_MODULE_FAIL;
+ goto finish;
+ }
+ rcode = unlang_interpret_synchronous(unlang_interpret_event_list(request), request);
+
+ switch (rcode) {
+ case RLM_MODULE_OK:
break;
- case LDAP_PROC_NO_RESULT:
+ case RLM_MODULE_NOTFOUND:
RDEBUG2("Tried to resolve group name(s) to DNs but got no results");
goto finish;
goto finish;
}
- entry_cnt = ldap_count_entries((*pconn)->handle, result);
+ entry_cnt = ldap_count_entries(query->ldap_conn->handle, query->result);
if (entry_cnt > name_cnt) {
REDEBUG("Number of DNs exceeds number of names, group and/or dn should be more restrictive");
rcode = RLM_MODULE_INVALID;
name_cnt, entry_cnt);
}
- entry = ldap_first_entry((*pconn)->handle, result);
+ entry = ldap_first_entry(query->ldap_conn->handle, query->result);
if (!entry) {
- ldap_get_option((*pconn)->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
+ ldap_get_option(query->ldap_conn->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
REDEBUG("Failed retrieving entry: %s", ldap_err2string(ldap_errno));
rcode = RLM_MODULE_FAIL;
}
do {
- *dn = ldap_get_dn((*pconn)->handle, entry);
+ *dn = ldap_get_dn(query->ldap_conn->handle, entry);
if (!*dn) {
- ldap_get_option((*pconn)->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
+ ldap_get_option(query->ldap_conn->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
REDEBUG("Retrieving object DN from entry failed: %s", ldap_err2string(ldap_errno));
rcode = RLM_MODULE_FAIL;
RDEBUG2("Got group DN \"%s\"", *dn);
dn++;
- } while((entry = ldap_next_entry((*pconn)->handle, entry)));
+ } while((entry = ldap_next_entry(query->ldap_conn->handle, entry)));
*dn = NULL;
finish:
talloc_free(filter);
- if (result) ldap_msgfree(result);
/*
* Be nice and cleanup the output array if we error out.
* @param[out] p_result The result of trying to resolve a dn to a group name.
* @param[in] inst rlm_ldap configuration.
* @param[in] request Current request.
- * @param[in,out] pconn to use. May change as this function calls functions which auto re-connect.
+ * @param[in] ttrunk to use.
* @param[in] dn to resolve.
* @param[out] out Where to write group name (must be freed with talloc_free).
* @return One of the RLM_MODULE_* values.
*/
static unlang_action_t rlm_ldap_group_dn2name(rlm_rcode_t *p_result, rlm_ldap_t const *inst, request_t *request,
- fr_ldap_connection_t **pconn, char const *dn, char **out)
+ fr_ldap_thread_trunk_t *ttrunk, char const *dn, char **out)
{
rlm_rcode_t rcode = RLM_MODULE_OK;
- fr_ldap_rcode_t status;
int ldap_errno;
struct berval **values = NULL;
char const *attrs[] = { inst->groupobj_name_attr, NULL };
- LDAPMessage *result = NULL, *entry;
+ LDAPMessage *entry;
+ fr_ldap_query_t *query = NULL;
*out = NULL;
RDEBUG2("Resolving group DN \"%s\" to group name", dn);
- status = fr_ldap_search(&result, request, pconn, dn, LDAP_SCOPE_BASE, NULL, attrs, NULL, NULL);
- switch (status) {
- case LDAP_PROC_SUCCESS:
+ if (fr_ldap_trunk_search(unlang_interpret_frame_talloc_ctx(request), &query, request, ttrunk, dn,
+ LDAP_SCOPE_BASE, NULL, attrs, NULL, NULL) < 0) {
+ RETURN_MODULE_FAIL;
+ }
+ rcode = unlang_interpret_synchronous(unlang_interpret_event_list(request), request);
+
+ switch (rcode) {
+ case RLM_MODULE_OK:
break;
- case LDAP_PROC_NO_RESULT:
+ case RLM_MODULE_NOTFOUND:
REDEBUG("Group DN \"%s\" did not resolve to an object", dn);
RETURN_MODULE_RCODE(inst->allow_dangling_group_refs ? RLM_MODULE_NOOP : RLM_MODULE_INVALID);
RETURN_MODULE_FAIL;
}
- entry = ldap_first_entry((*pconn)->handle, result);
+ entry = ldap_first_entry(query->ldap_conn->handle, query->result);
if (!entry) {
- ldap_get_option((*pconn)->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
+ ldap_get_option(query->ldap_conn->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
REDEBUG("Failed retrieving entry: %s", ldap_err2string(ldap_errno));
rcode = RLM_MODULE_INVALID;
goto finish;
}
- values = ldap_get_values_len((*pconn)->handle, entry, inst->groupobj_name_attr);
+ values = ldap_get_values_len(query->ldap_conn->handle, entry, inst->groupobj_name_attr);
if (!values) {
REDEBUG("No %s attributes found in object", inst->groupobj_name_attr);
RDEBUG2("Group DN \"%s\" resolves to name \"%s\"", dn, *out);
finish:
- if (result) ldap_msgfree(result);
if (values) ldap_value_free_len(values);
RETURN_MODULE_RCODE(rcode);
* @param[out] p_result The result of trying to resolve a dn to a group name.
* @param[in] inst rlm_ldap configuration.
* @param[in] request Current request.
- * @param[in,out] pconn to use. May change as this function calls functions which auto re-connect.
+ * @param[in] ttrunk to use.
* @param[in] entry retrieved by rlm_ldap_find_user or fr_ldap_search.
+ * @param[in] handle on which original object was found.
* @param[in] attr membership attribute to look for in the entry.
* @return One of the RLM_MODULE_* values.
*/
unlang_action_t rlm_ldap_cacheable_userobj(rlm_rcode_t *p_result, rlm_ldap_t const *inst,
- request_t *request, fr_ldap_connection_t **pconn,
- LDAPMessage *entry, char const *attr)
+ request_t *request, fr_ldap_thread_trunk_t *ttrunk,
+ LDAPMessage *entry, LDAP *handle, char const *attr)
{
rlm_rcode_t rcode = RLM_MODULE_OK;
/*
* Parse the membership information we got in the initial user query.
*/
- values = ldap_get_values_len((*pconn)->handle, entry, attr);
+ values = ldap_get_values_len(handle, entry, attr);
if (!values) {
RDEBUG2("No cacheable group memberships found in user object");
char *dn;
dn = fr_ldap_berval_to_string(value_ctx, values[i]);
- rlm_ldap_group_dn2name(&rcode, inst, request, pconn, dn, &name);
+ rlm_ldap_group_dn2name(&rcode, inst, request, ttrunk, dn, &name);
talloc_free(dn);
if (rcode == RLM_MODULE_NOOP) continue;
}
*name_p = NULL;
- rlm_ldap_group_name2dn(&rcode, inst, request, pconn, group_name, group_dn, sizeof(group_dn));
+ rlm_ldap_group_name2dn(&rcode, inst, request, ttrunk, group_name, group_dn, sizeof(group_dn));
ldap_value_free_len(values);
talloc_free(value_ctx);
* @param[out] p_result The result of trying to resolve a dn to a group name.
* @param[in] inst rlm_ldap configuration.
* @param[in] request Current request.
- * @param[in,out] pconn to use. May change as this function calls functions which auto re-connect.
+ * @param[in] ttrunk to use.
* @return One of the RLM_MODULE_* values.
*/
unlang_action_t rlm_ldap_cacheable_groupobj(rlm_rcode_t *p_result, rlm_ldap_t const *inst,
- request_t *request, fr_ldap_connection_t **pconn)
+ request_t *request, fr_ldap_thread_trunk_t *ttrunk)
{
rlm_rcode_t rcode = RLM_MODULE_OK;
- fr_ldap_rcode_t status;
int ldap_errno;
- LDAPMessage *result = NULL;
LDAPMessage *entry;
+ fr_ldap_query_t *query;
char const *base_dn;
char base_dn_buff[LDAP_MAX_DN_STR_LEN];
RETURN_MODULE_INVALID;
}
- status = fr_ldap_search(&result, request, pconn, base_dn,
- inst->groupobj_scope, filter, attrs, NULL, NULL);
- switch (status) {
- case LDAP_PROC_SUCCESS:
+ if (fr_ldap_trunk_search(unlang_interpret_frame_talloc_ctx(request), &query, request, ttrunk, base_dn,
+ inst->groupobj_scope, filter, attrs, NULL, NULL) < 0) {
+ rcode = RLM_MODULE_FAIL;
+ goto finish;
+ }
+ rcode = unlang_interpret_synchronous(unlang_interpret_event_list(request), request);
+
+ switch (rcode) {
+ case RLM_MODULE_OK:
break;
- case LDAP_PROC_NO_RESULT:
+ case RLM_MODULE_NOTFOUND:
RDEBUG2("No cacheable group memberships found in group objects");
goto finish;
goto finish;
}
- entry = ldap_first_entry((*pconn)->handle, result);
+ entry = ldap_first_entry(query->ldap_conn->handle, query->result);
if (!entry) {
- ldap_get_option((*pconn)->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
+ ldap_get_option(query->ldap_conn->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
REDEBUG("Failed retrieving entry: %s", ldap_err2string(ldap_errno));
goto finish;
RDEBUG2("Adding cacheable group object memberships");
do {
if (inst->cacheable_group_dn) {
- dn = ldap_get_dn((*pconn)->handle, entry);
+ dn = ldap_get_dn(query->ldap_conn->handle, entry);
if (!dn) {
- ldap_get_option((*pconn)->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
+ ldap_get_option(query->ldap_conn->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
REDEBUG("Retrieving object DN from entry failed: %s", ldap_err2string(ldap_errno));
goto finish;
if (inst->cacheable_group_name) {
struct berval **values;
- values = ldap_get_values_len((*pconn)->handle, entry, inst->groupobj_name_attr);
+ values = ldap_get_values_len(query->ldap_conn->handle, entry, inst->groupobj_name_attr);
if (!values) continue;
MEM(pair_append_control(&vp, inst->cache_da) == 0);
ldap_value_free_len(values);
}
- } while ((entry = ldap_next_entry((*pconn)->handle, entry)));
+ } while ((entry = ldap_next_entry(query->ldap_conn->handle, entry)));
finish:
- if (result) ldap_msgfree(result);
RETURN_MODULE_RCODE(rcode);
}
* @param[out] p_result Result of calling the module.
* @param[in] inst rlm_ldap configuration.
* @param[in] request Current request.
- * @param[in,out] pconn to use. May change as this function calls functions which auto re-connect.
+ * @param[in] ttrunk to use.
* @param[in] check vp containing the group value (name or dn).
*/
unlang_action_t rlm_ldap_check_groupobj_dynamic(rlm_rcode_t *p_result, rlm_ldap_t const *inst, request_t *request,
- fr_ldap_connection_t **pconn, fr_pair_t const *check)
+ fr_ldap_thread_trunk_t *ttrunk, fr_pair_t const *check)
{
- fr_ldap_rcode_t status;
+ rlm_rcode_t rcode;
+ fr_ldap_query_t *query = NULL;
char const *base_dn;
char base_dn_buff[LDAP_MAX_DN_STR_LEN + 1];
}
RINDENT();
- status = fr_ldap_search(NULL, request, pconn, base_dn, inst->groupobj_scope, filter, NULL, NULL, NULL);
+ if (fr_ldap_trunk_search(unlang_interpret_frame_talloc_ctx(request), &query, request, ttrunk, base_dn,
+ inst->groupobj_scope, filter, NULL, NULL, NULL) < 0) {
+ REXDENT();
+ RETURN_MODULE_FAIL;
+ }
+ rcode = unlang_interpret_synchronous(unlang_interpret_event_list(request), request);
REXDENT();
- switch (status) {
- case LDAP_PROC_SUCCESS:
+ switch (rcode) {
+ case RLM_MODULE_OK:
RDEBUG2("User found in group object \"%s\"", base_dn);
break;
- case LDAP_PROC_NO_RESULT:
+ case RLM_MODULE_NOTFOUND:
RETURN_MODULE_NOTFOUND;
default:
* @param[out] p_result Result of calling the module.
* @param[in] inst rlm_ldap configuration.
* @param[in] request Current request.
- * @param[in,out] pconn to use. May change as this function calls functions which auto re-connect.
+ * @param[in] ttrunk to use.
* @param[in] dn of user object.
* @param[in] check vp containing the group value (name or dn).
*/
unlang_action_t rlm_ldap_check_userobj_dynamic(rlm_rcode_t *p_result, rlm_ldap_t const *inst, request_t *request,
- fr_ldap_connection_t **pconn,
+ fr_ldap_thread_trunk_t *ttrunk,
char const *dn, fr_pair_t const *check)
{
rlm_rcode_t rcode = RLM_MODULE_NOTFOUND, ret;
- fr_ldap_rcode_t status;
bool name_is_dn = false, value_is_dn = false;
+ fr_ldap_query_t *query;
- LDAPMessage *result = NULL;
LDAPMessage *entry = NULL;
struct berval **values = NULL;
RDEBUG2("Checking user object's %s attributes", inst->userobj_membership_attr);
RINDENT();
- status = fr_ldap_search(&result, request, pconn, dn, LDAP_SCOPE_BASE, NULL, attrs, NULL, NULL);
+ if (fr_ldap_trunk_search(unlang_interpret_frame_talloc_ctx(request), &query, request, ttrunk, dn,
+ LDAP_SCOPE_BASE, NULL, attrs, NULL, NULL) < 0) {
+ REXDENT();
+ goto finish;
+ }
+ rcode = unlang_interpret_synchronous(unlang_interpret_event_list(request), request);
REXDENT();
- switch (status) {
- case LDAP_PROC_SUCCESS:
+ switch (rcode) {
+ case RLM_MODULE_OK:
break;
- case LDAP_PROC_NO_RESULT:
+ case RLM_MODULE_NOTFOUND:
RDEBUG2("Can't check membership attributes, user object not found");
- rcode = RLM_MODULE_NOTFOUND;
-
FALL_THROUGH;
default:
goto finish;
}
- entry = ldap_first_entry((*pconn)->handle, result);
+ entry = ldap_first_entry(query->ldap_conn->handle, query->result);
if (!entry) {
- ldap_get_option((*pconn)->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
+ ldap_get_option(query->ldap_conn->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
REDEBUG("Failed retrieving entry: %s", ldap_err2string(ldap_errno));
rcode = RLM_MODULE_FAIL;
goto finish;
}
- values = ldap_get_values_len((*pconn)->handle, entry, inst->userobj_membership_attr);
+ values = ldap_get_values_len(query->ldap_conn->handle, entry, inst->userobj_membership_attr);
if (!values) {
RDEBUG2("No group membership attribute(s) found in user object");
bool eq = false;
RINDENT();
- rlm_ldap_group_dn2name(&ret, inst, request, pconn, check->vp_strvalue, &resolved);
+ rlm_ldap_group_dn2name(&ret, inst, request, ttrunk, check->vp_strvalue, &resolved);
REXDENT();
if (ret == RLM_MODULE_NOOP) continue;
value = fr_ldap_berval_to_string(request, values[i]);
RINDENT();
- rlm_ldap_group_dn2name(&ret, inst, request, pconn, value, &resolved);
+ rlm_ldap_group_dn2name(&ret, inst, request, ttrunk, value, &resolved);
REXDENT();
talloc_free(value);
finish:
if (values) ldap_value_free_len(values);
- if (result) ldap_msgfree(result);
RETURN_MODULE_RCODE(rcode);
}
{ FR_CONF_POINTER("global", FR_TYPE_SUBSECTION, NULL), .subcs = (void const *) global_config },
{ FR_CONF_OFFSET("tls", FR_TYPE_SUBSECTION, rlm_ldap_t, handle_config), .subcs = (void const *) tls_config },
+
+ { FR_CONF_OFFSET("pool", FR_TYPE_SUBSECTION, rlm_ldap_t, trunk_conf), .subcs = (void const *) fr_trunk_config },
+
CONF_PARSER_TERMINATOR
};
{
rlm_rcode_t rcode = RLM_MODULE_UPDATED;
rlm_ldap_t *inst = talloc_get_type_abort(mod_inst, rlm_ldap_t);
- fr_ldap_rcode_t status;
+ fr_ldap_thread_t *thread = talloc_get_type_abort(module_thread_by_data(inst)->data, fr_ldap_thread_t);
LDAPURLDesc *ldap_url;
- LDAPMessage *result = NULL;
LDAPMessage *entry = NULL;
map_t const *map;
char const *url_str;
- fr_ldap_connection_t *conn;
-
- LDAPControl *server_ctrls[] = { NULL, NULL };
+ char *host_url;
+ fr_ldap_query_t *query;
+ fr_ldap_thread_trunk_t *ttrunk;
fr_ldap_map_exp_t expanded; /* faster than allocing every time */
fr_value_box_t *url_head = fr_dlist_head(url);
goto free_urldesc;
}
- conn = mod_conn_get(inst, request);
- if (!conn) goto free_expanded;
+ /*
+ * If the URL is <scheme>:/// the parsed host will be NULL - use config default
+ */
+ if (!ldap_url->lud_host) {
+ host_url = inst->handle_config.server;
+ } else {
+ host_url = talloc_asprintf(unlang_interpret_frame_talloc_ctx(request), "%s://%s:%d",
+ ldap_url->lud_scheme, ldap_url->lud_host, ldap_url->lud_port);
+ }
- if (fr_ldap_parse_url_extensions(&server_ctrls[0], request, conn, ldap_url->lud_exts) < 0) goto free_socket;
+ ttrunk = fr_thread_ldap_trunk_get(thread, host_url, inst->handle_config.admin_identity,
+ inst->handle_config.admin_password, request, &inst->handle_config);
+ if (!ttrunk) goto free_expanded;
- status = fr_ldap_search(&result, request, &conn, ldap_url->lud_dn, ldap_url->lud_scope,
- ldap_url->lud_filter, expanded.attrs, server_ctrls, NULL);
+ fr_ldap_trunk_search(unlang_interpret_frame_talloc_ctx(request), &query, request, ttrunk, ldap_url->lud_dn,
+ ldap_url->lud_scope, ldap_url->lud_filter, expanded.attrs, NULL, NULL);
-#ifdef HAVE_LDAP_CREATE_SORT_CONTROL
- if (server_ctrls[0]) ldap_control_free(server_ctrls[0]);
-#endif
+ rcode = unlang_interpret_synchronous(unlang_interpret_event_list(request), request);
- switch (status) {
- case LDAP_PROC_SUCCESS:
+ switch (rcode) {
+ case RLM_MODULE_OK:
+ rcode = RLM_MODULE_UPDATED;
break;
- case LDAP_PROC_NO_RESULT:
- rcode = RLM_MODULE_NOOP;
- goto free_socket;
+ case RLM_MODULE_NOTFOUND:
+ goto free_expanded;
default:
rcode = RLM_MODULE_FAIL;
- goto free_socket;
+ goto free_expanded;
}
- fr_assert(conn);
- fr_assert(result);
-
- for (entry = ldap_first_entry(conn->handle, result);
+ for (entry = ldap_first_entry(query->ldap_conn->handle, query->result);
entry;
- entry = ldap_next_entry(conn->handle, entry)) {
+ entry = ldap_next_entry(query->ldap_conn->handle, entry)) {
char *dn = NULL;
int i;
if (RDEBUG_ENABLED2) {
- dn = ldap_get_dn(conn->handle, entry);
+ dn = ldap_get_dn(query->ldap_conn->handle, entry);
RDEBUG2("Processing \"%s\"", dn);
}
int ret;
fr_ldap_result_t attr;
- attr.values = ldap_get_values_len(conn->handle, entry, expanded.attrs[i]);
+ attr.values = ldap_get_values_len(query->ldap_conn->handle, entry, expanded.attrs[i]);
if (!attr.values) {
/*
* Many LDAP directories don't expose the DN of
struct berval value;
struct berval *values[2] = { &value, NULL };
- if (!dn) dn = ldap_get_dn(conn->handle, entry);
+ if (!dn) dn = ldap_get_dn(query->ldap_conn->handle, entry);
value.bv_val = dn;
value.bv_len = strlen(dn);
if (ret == -1) {
rcode = RLM_MODULE_FAIL;
ldap_memfree(dn);
- goto free_result;
+ goto free_expanded;
}
continue;
}
if (ret == -1) {
rcode = RLM_MODULE_FAIL;
ldap_memfree(dn);
- goto free_result;
+ goto free_expanded;
}
}
ldap_memfree(dn);
REXDENT();
}
-free_result:
- ldap_msgfree(result);
-free_socket:
- ldap_mod_conn_release(inst, request, conn);
free_expanded:
talloc_free(expanded.ctx);
free_urldesc:
static int rlm_ldap_groupcmp(void *instance, request_t *request, UNUSED fr_pair_list_t *request_list, fr_pair_t const *check)
{
rlm_ldap_t const *inst = talloc_get_type_abort_const(instance, rlm_ldap_t);
+ fr_ldap_thread_t *thread = talloc_get_type_abort(module_thread_by_data(inst)->data, fr_ldap_thread_t);
rlm_rcode_t rcode;
bool found = false;
bool check_is_dn;
- fr_ldap_connection_t *conn = NULL;
+ fr_ldap_thread_trunk_t *ttrunk = NULL;
char const *user_dn;
fr_pair_t *check_p = NULL;
}
}
- conn = mod_conn_get(inst, request);
- if (!conn) goto cleanup;
+ ttrunk = fr_thread_ldap_trunk_get(thread, inst->handle_config.server, inst->handle_config.admin_identity,
+ inst->handle_config.admin_password, request, &inst->handle_config);
+ if (!ttrunk) goto cleanup;
/*
* This is used in the default membership filter.
*/
- user_dn = rlm_ldap_find_user(inst, request, &conn, NULL, false, NULL, &rcode);
- if (!user_dn) {
- ldap_mod_conn_release(inst, request, conn);
- goto cleanup;
- }
-
- fr_assert(conn);
+ user_dn = rlm_ldap_find_user(inst, request, ttrunk, NULL, false, NULL, NULL, &rcode);
+ if (!user_dn) goto cleanup;
/*
* Check groupobj user membership
if (inst->groupobj_membership_filter) {
rlm_rcode_t our_rcode;
- rlm_ldap_check_groupobj_dynamic(&our_rcode, inst, request, &conn, check);
+ rlm_ldap_check_groupobj_dynamic(&our_rcode, inst, request, ttrunk, check);
switch (our_rcode) {
case RLM_MODULE_NOTFOUND:
break;
}
}
- fr_assert(conn);
-
/*
* Check userobj group membership
*/
if (inst->userobj_membership_attr) {
rlm_rcode_t our_rcode;
- rlm_ldap_check_userobj_dynamic(&our_rcode, inst, request, &conn, user_dn, check);
+ rlm_ldap_check_userobj_dynamic(&our_rcode, inst, request, ttrunk, user_dn, check);
switch (our_rcode) {
case RLM_MODULE_NOTFOUND:
break;
}
}
- fr_assert(conn);
-
finish:
- if (conn) ldap_mod_conn_release(inst, request, conn);
-
if (found) {
talloc_free(check_p);
return 0;
static unlang_action_t CC_HINT(nonnull) mod_authenticate(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
{
rlm_ldap_t const *inst = talloc_get_type_abort_const(mctx->instance, rlm_ldap_t);
+ fr_ldap_thread_t *thread = talloc_get_type_abort(module_thread_by_data(inst)->data, fr_ldap_thread_t);
rlm_rcode_t rcode;
- fr_ldap_rcode_t status;
char const *dn;
- fr_ldap_connection_t *conn;
+ fr_ldap_thread_trunk_t *ttrunk = NULL;
char sasl_mech_buff[LDAP_MAX_DN_STR_LEN];
char sasl_proxy_buff[LDAP_MAX_DN_STR_LEN];
RDEBUG2("Login attempt with password");
}
- conn = mod_conn_get(inst, request);
- if (!conn) RETURN_MODULE_FAIL;
+ ttrunk = fr_thread_ldap_trunk_get(thread, inst->handle_config.server, inst->handle_config.admin_identity,
+ inst->handle_config.admin_password, request, &inst->handle_config);
+ if (!ttrunk) RETURN_MODULE_FAIL;
/*
* Expand dynamic SASL fields
/*
* Get the DN by doing a search.
*/
- dn = rlm_ldap_find_user(inst, request, &conn, NULL, false, NULL, &rcode);
- if (!dn) {
- ldap_mod_conn_release(inst, request, conn);
-
- RETURN_MODULE_RCODE(rcode);
- }
- conn->rebound = true;
- status = fr_ldap_bind(request,
- &conn,
- dn, password->vp_strvalue,
- inst->user_sasl.mech ? &sasl : NULL,
- fr_time_delta_wrap(0),
- NULL, NULL);
- switch (status) {
- case LDAP_PROC_SUCCESS:
- rcode = RLM_MODULE_OK;
- RDEBUG2("Bind as user \"%s\" was successful", dn);
- break;
-
- case LDAP_PROC_NOT_PERMITTED:
- rcode = RLM_MODULE_DISALLOW;
- break;
-
- case LDAP_PROC_REJECT:
- rcode = RLM_MODULE_REJECT;
- break;
+ dn = rlm_ldap_find_user(inst, request, ttrunk, NULL, false, NULL, NULL, &rcode);
+ if (!dn) RETURN_MODULE_RCODE(rcode);
- case LDAP_PROC_BAD_DN:
- rcode = RLM_MODULE_INVALID;
- break;
+ /*
+ * Attempt a bind using the thread specific connection for bind auths
+ */
+ if (fr_ldap_bind_auth_async(request, thread, dn, password->vp_strvalue) < 0) RETURN_MODULE_FAIL;
- case LDAP_PROC_NO_RESULT:
- rcode = RLM_MODULE_NOTFOUND;
- break;
-
- default:
- rcode = RLM_MODULE_FAIL;
- break;
- };
+ rcode = unlang_interpret_synchronous(unlang_interpret_event_list(request), request);
finish:
- ldap_mod_conn_release(inst, request, conn);
RETURN_MODULE_RCODE(rcode);
}
* @param[out] p_result the result of applying the profile.
* @param[in] inst rlm_ldap configuration.
* @param[in] request Current request.
- * @param[in,out] pconn to use. May change as this function calls functions which auto re-connect.
+ * @param[in] ttrunk to use.
* @param[in] dn of profile object to apply.
* @param[in] expanded Structure containing a list of xlat
* expanded attribute names and mapping information.
* @return One of the RLM_MODULE_* values.
*/
static unlang_action_t rlm_ldap_map_profile(rlm_rcode_t *p_result, rlm_ldap_t const *inst,
- request_t *request, fr_ldap_connection_t **pconn,
+ request_t *request, fr_ldap_thread_trunk_t *ttrunk,
char const *dn, fr_ldap_map_exp_t const *expanded)
{
rlm_rcode_t rcode = RLM_MODULE_OK;
- fr_ldap_rcode_t status;
- LDAPMessage *result = NULL, *entry = NULL;
+ LDAPMessage *entry = NULL;
int ldap_errno;
- LDAP *handle = (*pconn)->handle;
+ LDAP *handle;
char const *filter;
char filter_buff[LDAP_MAX_FILTER_STR_LEN];
+ fr_ldap_query_t *query;
fr_assert(inst->profile_filter); /* We always have a default filter set */
RETURN_MODULE_INVALID;
}
- status = fr_ldap_search(&result, request, pconn, dn,
- LDAP_SCOPE_BASE, filter, expanded->attrs, NULL, NULL);
- switch (status) {
- case LDAP_PROC_SUCCESS:
+ if (fr_ldap_trunk_search(unlang_interpret_frame_talloc_ctx(request), &query, request, ttrunk, dn,
+ LDAP_SCOPE_BASE, filter, expanded->attrs, NULL, NULL) < 0) RETURN_MODULE_FAIL;
+
+ rcode = unlang_interpret_synchronous(unlang_interpret_event_list(request), request);
+
+ switch (rcode) {
+ case RLM_MODULE_OK:
break;
- case LDAP_PROC_BAD_DN:
- case LDAP_PROC_NO_RESULT:
+ case RLM_MODULE_NOTFOUND:
RDEBUG2("Profile object \"%s\" not found", dn);
RETURN_MODULE_NOTFOUND;
RETURN_MODULE_FAIL;
}
- fr_assert(*pconn);
- fr_assert(result);
+ fr_assert(query->result);
+ handle = query->ldap_conn->handle;
- entry = ldap_first_entry(handle, result);
+ entry = ldap_first_entry(handle, query->result);
if (!entry) {
ldap_get_option(handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
REDEBUG("Failed retrieving entry: %s", ldap_err2string(ldap_errno));
- rcode = RLM_MODULE_NOTFOUND;
-
- goto free_result;
+ RETURN_MODULE_RCODE(RLM_MODULE_NOTFOUND);
}
RDEBUG2("Processing profile attributes");
RINDENT();
- if (fr_ldap_map_do(request, *pconn, inst->valuepair_attr, expanded, entry) > 0) rcode = RLM_MODULE_UPDATED;
+ if (fr_ldap_map_do(request, query->ldap_conn->handle, inst->valuepair_attr, expanded, entry) > 0) rcode = RLM_MODULE_UPDATED;
REXDENT();
-free_result:
- ldap_msgfree(result);
-
RETURN_MODULE_RCODE(rcode);
}
static unlang_action_t CC_HINT(nonnull) mod_authorize(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
{
rlm_ldap_t const *inst = talloc_get_type_abort_const(mctx->instance, rlm_ldap_t);
+ fr_ldap_thread_t *thread = talloc_get_type_abort(module_thread_by_data(inst)->data, fr_ldap_thread_t);
rlm_rcode_t rcode = RLM_MODULE_OK;
int ldap_errno;
int i;
struct berval **values;
- fr_ldap_connection_t *conn;
+ fr_ldap_thread_trunk_t *ttrunk;
+ LDAP *handle;
LDAPMessage *result, *entry;
char const *dn = NULL;
fr_ldap_map_exp_t expanded; /* faster than allocing every time */
-#ifdef WITH_EDIR
- fr_ldap_rcode_t status;
-#endif
/*
* Don't be tempted to add a check for User-Name or
if (fr_ldap_map_expand(&expanded, request, &inst->user_map) < 0) RETURN_MODULE_FAIL;
- conn = mod_conn_get(inst, request);
- if (!conn) RETURN_MODULE_FAIL;
+ ttrunk = fr_thread_ldap_trunk_get(thread, inst->handle_config.server, inst->handle_config.admin_identity,
+ inst->handle_config.admin_password, request, &inst->handle_config);
+ if (!ttrunk) RETURN_MODULE_FAIL;
/*
* Add any additional attributes we need for checking access, memberships, and profiles
expanded.attrs[expanded.count] = NULL;
- dn = rlm_ldap_find_user(inst, request, &conn, expanded.attrs, true, &result, &rcode);
+ dn = rlm_ldap_find_user(inst, request, ttrunk, expanded.attrs, true, &result, &handle, &rcode);
if (!dn) {
goto finish;
}
- entry = ldap_first_entry(conn->handle, result);
+ entry = ldap_first_entry(handle, result);
if (!entry) {
- ldap_get_option(conn->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
+ ldap_get_option(handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
REDEBUG("Failed retrieving entry: %s", ldap_err2string(ldap_errno));
goto finish;
* Check for access.
*/
if (inst->userobj_access_attr) {
- rcode = rlm_ldap_check_access(inst, request, conn, entry);
+ rcode = rlm_ldap_check_access(inst, request, handle, entry);
if (rcode != RLM_MODULE_OK) {
goto finish;
}
*/
if (inst->cacheable_group_dn || inst->cacheable_group_name) {
if (inst->userobj_membership_attr) {
- rlm_ldap_cacheable_userobj(&rcode, inst, request, &conn, entry, inst->userobj_membership_attr);
+ rlm_ldap_cacheable_userobj(&rcode, inst, request, ttrunk, entry, handle, inst->userobj_membership_attr);
if (rcode != RLM_MODULE_OK) {
goto finish;
}
}
- rlm_ldap_cacheable_groupobj(&rcode, inst, request, &conn);
+ rlm_ldap_cacheable_groupobj(&rcode, inst, request, ttrunk);
if (rcode != RLM_MODULE_OK) {
goto finish;
}
/*
* Retrive universal password
*/
- res = fr_ldap_edir_get_password(conn->handle, dn, password, &pass_size);
+ res = fr_ldap_edir_get_password(handle, dn, password, &pass_size);
if (res != 0) {
REDEBUG("Failed to retrieve eDirectory password: (%i) %s", res, fr_ldap_edir_errstr(res));
rcode = RLM_MODULE_FAIL;
/*
* Bind as the user
*/
- conn->rebound = true;
- status = fr_ldap_bind(request, &conn, dn, vp->vp_strvalue, NULL,
- fr_time_delta_wrap(0), NULL, NULL);
- switch (status) {
- case LDAP_PROC_SUCCESS:
- rcode = RLM_MODULE_OK;
- RDEBUG2("Bind as user '%s' was successful", dn);
- break;
-
- case LDAP_PROC_NOT_PERMITTED:
- rcode = RLM_MODULE_DISALLOW;
- goto finish;
-
- case LDAP_PROC_REJECT:
- rcode = RLM_MODULE_REJECT;
- goto finish;
-
- case LDAP_PROC_BAD_DN:
- rcode = RLM_MODULE_INVALID;
+ if (fr_ldap_bind_auth_async(request, thread, dn, vp->vp_strvalue) < 0) {
+ rcode = RLM_MODULE_FAIL;
goto finish;
+ }
- case LDAP_PROC_NO_RESULT:
- rcode = RLM_MODULE_NOTFOUND;
- goto finish;
+ rcode = unlang_interpret_synchronous(unlang_interpret_event_list(request), request);
- default:
- rcode = RLM_MODULE_FAIL;
- goto finish;
- };
+ if (rcode != RLM_MODULE_OK) goto finish;
}
}
goto finish;
}
- rlm_ldap_map_profile(&ret, inst, request, &conn, profile, &expanded);
+ rlm_ldap_map_profile(&ret, inst, request, ttrunk, profile, &expanded);
switch (ret) {
case RLM_MODULE_INVALID:
rcode = RLM_MODULE_INVALID;
* Apply a SET of user profiles.
*/
if (inst->profile_attr) {
- values = ldap_get_values_len(conn->handle, entry, inst->profile_attr);
+ values = ldap_get_values_len(handle, entry, inst->profile_attr);
if (values != NULL) {
for (i = 0; values[i] != NULL; i++) {
rlm_rcode_t ret;
char *value;
value = fr_ldap_berval_to_string(request, values[i]);
- rlm_ldap_map_profile(&ret, inst, request, &conn, value, &expanded);
+ rlm_ldap_map_profile(&ret, inst, request, ttrunk, value, &expanded);
talloc_free(value);
if (ret == RLM_MODULE_FAIL) {
ldap_value_free_len(values);
if (!fr_dlist_empty(&inst->user_map) || inst->valuepair_attr) {
RDEBUG2("Processing user attributes");
RINDENT();
- if (fr_ldap_map_do(request, conn, inst->valuepair_attr,
+ if (fr_ldap_map_do(request, handle, inst->valuepair_attr,
&expanded, entry) > 0) rcode = RLM_MODULE_UPDATED;
REXDENT();
- rlm_ldap_check_reply(inst, request, conn);
+ rlm_ldap_check_reply(inst, request, ttrunk);
}
finish:
talloc_free(expanded.ctx);
- if (result) ldap_msgfree(result);
- ldap_mod_conn_release(inst, request, conn);
RETURN_MODULE_RCODE(rcode);
}
request_t *request, ldap_acct_section_t *section)
{
rlm_rcode_t rcode = RLM_MODULE_OK;
- fr_ldap_rcode_t status;
+ fr_ldap_thread_t *thread = talloc_get_type_abort(module_thread_by_data(inst)->data, fr_ldap_thread_t);
- fr_ldap_connection_t *conn = NULL;
+ fr_ldap_thread_trunk_t *ttrunk = NULL;
+ fr_ldap_query_t *query = NULL;
LDAPMod *mod_p[LDAP_MAX_ATTRMAP + 1], mod_s[LDAP_MAX_ATTRMAP];
LDAPMod **modify = mod_p;
mod_p[total] = NULL;
- conn = mod_conn_get(inst, request);
- if (!conn) RETURN_MODULE_FAIL;
+ ttrunk = fr_thread_ldap_trunk_get(thread, inst->handle_config.server, inst->handle_config.admin_identity,
+ inst->handle_config.admin_password, request, &inst->handle_config);
- dn = rlm_ldap_find_user(inst, request, &conn, NULL, false, NULL, &rcode);
+ dn = rlm_ldap_find_user(inst, request, ttrunk, NULL, false, NULL, NULL, &rcode);
if (!dn || (rcode != RLM_MODULE_OK)) {
goto error;
}
- status = fr_ldap_modify(request, &conn, dn, modify, NULL, NULL);
- switch (status) {
- case LDAP_PROC_SUCCESS:
+ if (fr_ldap_trunk_modify(unlang_interpret_frame_talloc_ctx(request), &query, request, ttrunk, dn,
+ modify, NULL, NULL) < 0 ){
+ rcode = RLM_MODULE_FAIL;
+ goto error;
+ }
+
+ rcode = unlang_interpret_synchronous(unlang_interpret_event_list(request), request);
+
+ switch (rcode) {
+ case RLM_MODULE_OK:
break;
- case LDAP_PROC_REJECT:
- case LDAP_PROC_BAD_DN:
+ case RLM_MODULE_NOTFOUND:
rcode = RLM_MODULE_INVALID;
break;
*/
for (i = 0; i < last_exp; i++) talloc_free(expanded[i]);
- ldap_mod_conn_release(inst, request, conn);
-
RETURN_MODULE_RCODE(rcode);
}
*/
if (fr_ldap_init() < 0) goto error;
- /*
- * Initialize the socket pool.
- */
- inst->pool = module_connection_pool_init(inst->cs, &inst->handle_config,
- ldap_mod_conn_create, NULL, NULL, NULL, NULL);
- if (!inst->pool) goto error;
-
fr_ldap_global_config(inst->ldap_debug, inst->tls_random_file);
return 0;
/*
* user.c - User lookup functions
*/
-char const *rlm_ldap_find_user(rlm_ldap_t const *inst, request_t *request, fr_ldap_connection_t **pconn,
- char const *attrs[], bool force, LDAPMessage **result, rlm_rcode_t *rcode);
+char const *rlm_ldap_find_user(rlm_ldap_t const *inst, request_t *request, fr_ldap_thread_trunk_t *tconn,
+ char const *attrs[], bool force, LDAPMessage **result, LDAP **handle, rlm_rcode_t *rcode);
-rlm_rcode_t rlm_ldap_check_access(rlm_ldap_t const *inst, request_t *request,
- fr_ldap_connection_t const *conn, LDAPMessage *entry);
+rlm_rcode_t rlm_ldap_check_access(rlm_ldap_t const *inst, request_t *request, LDAP *handle, LDAPMessage *entry);
-void rlm_ldap_check_reply(rlm_ldap_t const *inst, request_t *request, fr_ldap_connection_t const *conn);
+void rlm_ldap_check_reply(rlm_ldap_t const *inst, request_t *request, fr_ldap_thread_trunk_t const *ttrunk);
/*
* groups.c - Group membership functions.
*/
unlang_action_t rlm_ldap_cacheable_userobj(rlm_rcode_t *p_result, rlm_ldap_t const *inst,
- request_t *request, fr_ldap_connection_t **pconn,
- LDAPMessage *entry, char const *attr);
+ request_t *request, fr_ldap_thread_trunk_t *ttrunk,
+ LDAPMessage *entry, LDAP *handle, char const *attr);
unlang_action_t rlm_ldap_cacheable_groupobj(rlm_rcode_t *p_result,
- rlm_ldap_t const *inst, request_t *request, fr_ldap_connection_t **pconn);
+ rlm_ldap_t const *inst, request_t *request, fr_ldap_thread_trunk_t *ttrunk);
unlang_action_t rlm_ldap_check_groupobj_dynamic(rlm_rcode_t *p_result,
- rlm_ldap_t const *inst, request_t *request, fr_ldap_connection_t **pconn,
+ rlm_ldap_t const *inst, request_t *request, fr_ldap_thread_trunk_t *ttrunk,
fr_pair_t const *check);
unlang_action_t rlm_ldap_check_userobj_dynamic(rlm_rcode_t *p_result,
- rlm_ldap_t const *inst, request_t *request, fr_ldap_connection_t **pconn,
+ rlm_ldap_t const *inst, request_t *request, fr_ldap_thread_trunk_t *ttrunk,
char const *dn, fr_pair_t const *check);
unlang_action_t rlm_ldap_check_cached(rlm_rcode_t *p_result,
*
* @param[in] inst rlm_ldap configuration.
* @param[in] request Current request.
- * @param[in,out] pconn to use. May change as this function calls functions which auto re-connect.
+ * @param[in] ttrunk LDAP thread trunk to use.
* @param[in] attrs Additional attributes to retrieve, may be NULL.
* @param[in] force Query even if the User-DN already exists.
* @param[out] result Where to write the result, may be NULL in which case result is discarded.
* @param[out] rcode The status of the operation, one of the RLM_MODULE_* codes.
* @return The user's DN or NULL on error.
*/
-char const *rlm_ldap_find_user(rlm_ldap_t const *inst, request_t *request, fr_ldap_connection_t **pconn,
- char const *attrs[], bool force, LDAPMessage **result, rlm_rcode_t *rcode)
+char const *rlm_ldap_find_user(rlm_ldap_t const *inst, request_t *request, fr_ldap_thread_trunk_t *ttrunk,
+ char const *attrs[], bool force, LDAPMessage **result, LDAP **handle, rlm_rcode_t *rcode)
{
static char const *tmp_attrs[] = { NULL };
- fr_ldap_rcode_t status;
fr_pair_t *vp = NULL;
LDAPMessage *tmp_msg = NULL, *entry = NULL;
int ldap_errno;
char const *base_dn;
char base_dn_buff[LDAP_MAX_DN_STR_LEN];
LDAPControl *serverctrls[] = { inst->userobj_sort_ctrl, NULL };
+ fr_ldap_query_t *query = NULL;
bool freeit = false; //!< Whether the message should
//!< be freed after being processed.
}
}
- /*
- * Perform all searches as the admin user.
- */
- if ((*pconn)->rebound) {
- status = fr_ldap_bind(request, pconn, (*pconn)->config->admin_identity,
- (*pconn)->config->admin_password, &(*pconn)->config->admin_sasl,
- fr_time_delta_wrap(0), NULL, NULL);
- if (status != LDAP_PROC_SUCCESS) {
- *rcode = RLM_MODULE_FAIL;
- return NULL;
- }
-
- fr_assert(*pconn);
-
- (*pconn)->rebound = false;
- }
-
if (inst->userobj_filter) {
if (tmpl_expand(&filter, filter_buff, sizeof(filter_buff), request, inst->userobj_filter,
fr_ldap_escape_func, NULL) < 0) {
return NULL;
}
- status = fr_ldap_search(result, request, pconn, base_dn,
- inst->userobj_scope, filter, attrs, serverctrls, NULL);
- switch (status) {
- case LDAP_PROC_SUCCESS:
- break;
-
- case LDAP_PROC_BAD_DN:
- case LDAP_PROC_NO_RESULT:
- *rcode = RLM_MODULE_NOTFOUND;
- return NULL;
-
- default:
+ if (fr_ldap_trunk_search(unlang_interpret_frame_talloc_ctx(request), &query ,request, ttrunk, base_dn,
+ inst->userobj_scope, filter, attrs, serverctrls, NULL) < 0) {
*rcode = RLM_MODULE_FAIL;
return NULL;
}
+ *rcode = unlang_interpret_synchronous(unlang_interpret_event_list(request), request);
+
+ if (*rcode != RLM_MODULE_OK) return NULL;
- fr_assert(*pconn);
+ *result = query->result;
/*
* Forbid the use of unsorted search results that
* security issue, and likely non deterministic.
*/
if (!inst->userobj_sort_ctrl) {
- cnt = ldap_count_entries((*pconn)->handle, *result);
+ cnt = ldap_count_entries(query->ldap_conn->handle, *result);
if (cnt > 1) {
REDEBUG("Ambiguous search result, returned %i unsorted entries (should return 1 or 0). "
"Enable sorting, or specify a more restrictive base_dn, filter or scope", cnt);
REDEBUG("The following entries were returned:");
RINDENT();
- for (entry = ldap_first_entry((*pconn)->handle, *result);
+ for (entry = ldap_first_entry(query->ldap_conn->handle, *result);
entry;
- entry = ldap_next_entry((*pconn)->handle, entry)) {
- dn = ldap_get_dn((*pconn)->handle, entry);
+ entry = ldap_next_entry(query->ldap_conn->handle, entry)) {
+ dn = ldap_get_dn(query->ldap_conn->handle, entry);
REDEBUG("%s", dn);
ldap_memfree(dn);
}
}
}
- entry = ldap_first_entry((*pconn)->handle, *result);
+ entry = ldap_first_entry(query->ldap_conn->handle, *result);
if (!entry) {
- ldap_get_option((*pconn)->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
+ ldap_get_option(query->ldap_conn->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
REDEBUG("Failed retrieving entry: %s",
ldap_err2string(ldap_errno));
goto finish;
}
- dn = ldap_get_dn((*pconn)->handle, entry);
+ dn = ldap_get_dn(query->ldap_conn->handle, entry);
if (!dn) {
- ldap_get_option((*pconn)->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
+ ldap_get_option(query->ldap_conn->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
REDEBUG("Retrieving object DN from entry failed: %s", ldap_err2string(ldap_errno));
goto finish;
MEM(pair_update_control(&vp, attr_ldap_userdn) >= 0);
fr_pair_value_strdup(vp, dn, false);
- *rcode = RLM_MODULE_OK;
+ if (handle) *handle = query->ldap_conn->handle;
ldap_memfree(dn);
finish:
- if ((freeit || (*rcode != RLM_MODULE_OK)) && *result) {
- ldap_msgfree(*result);
- *result = NULL;
- }
+ /*
+ * Actual freeing of the result is handled by the query destructor
+ */
+ if ((freeit || (*rcode != RLM_MODULE_OK)) && *result) *result = NULL;
return vp ? vp->vp_strvalue : NULL;
}
*
* @param[in] inst rlm_ldap configuration.
* @param[in] request Current request.
- * @param[in] conn used to retrieve access attributes.
+ * @param[in] handle used to retrieve access attributes.
* @param[in] entry retrieved by rlm_ldap_find_user or fr_ldap_search.
* @return
* - #RLM_MODULE_DISALLOW if the user was denied access.
* - #RLM_MODULE_OK otherwise.
*/
-rlm_rcode_t rlm_ldap_check_access(rlm_ldap_t const *inst, request_t *request,
- fr_ldap_connection_t const *conn, LDAPMessage *entry)
+rlm_rcode_t rlm_ldap_check_access(rlm_ldap_t const *inst, request_t *request, LDAP *handle, LDAPMessage *entry)
{
rlm_rcode_t rcode = RLM_MODULE_OK;
struct berval **values = NULL;
- values = ldap_get_values_len(conn->handle, entry, inst->userobj_access_attr);
+ values = ldap_get_values_len(handle, entry, inst->userobj_access_attr);
if (values) {
if (inst->access_positive) {
if ((values[0]->bv_len >= 5) && (strncasecmp(values[0]->bv_val, "false", 5) == 0)) {
*
* @param inst rlm_ldap configuration.
* @param request Current request.
- * @param conn the connection handle
+ * @param ttrunk the connection thread trunk.
*/
-void rlm_ldap_check_reply(rlm_ldap_t const *inst, request_t *request, fr_ldap_connection_t const *conn)
+void rlm_ldap_check_reply(rlm_ldap_t const *inst, request_t *request, fr_ldap_thread_trunk_t const *ttrunk)
{
/*
* More warning messages for people who can't be bothered to read the documentation.
!fr_pair_find_by_da(&request->control_pairs, attr_user_password, 0) &&
!fr_pair_find_by_da(&request->control_pairs, attr_password_with_header, 0) &&
!fr_pair_find_by_da(&request->control_pairs, attr_crypt_password, 0)) {
- switch (conn->directory->type) {
+ switch (ttrunk->directory->type) {
case FR_LDAP_DIRECTORY_ACTIVE_DIRECTORY:
RWDEBUG2("!!! Found map between LDAP attribute and a FreeRADIUS password attribute");
RWDEBUG2("!!! Active Directory does not allow passwords to be read via LDAP");
break;
default:
- if (!conn->config->admin_identity) {
+ if (!ttrunk->config.admin_identity) {
RWDEBUG2("!!! Found map between LDAP attribute and a FreeRADIUS password attribute");
RWDEBUG2("!!! but no password attribute found in search result");
RWDEBUG2("!!! Either:");
RWDEBUG2("!!! - Ensure the user object contains a password attribute, and that");
RWDEBUG2("!!! \"%s\" has permission to read that password attribute (recommended)",
- conn->config->admin_identity);
+ ttrunk->config.admin_identity);
RWDEBUG2("!!! - Bind as the user by listing %s in the authenticate section, and",
inst->name);
RWDEBUG2("!!! setting attribute &control.Auth-Type := '%s' in the authorize section",