ldap_auth_mod_env_t *mod_env;
} ldap_auth_ctx_t;
+/** Holds state of in progress async profile lookups
+ *
+ */
+typedef struct {
+ fr_ldap_query_t *query;
+ char const *dn;
+ rlm_ldap_t const *inst;
+ fr_ldap_map_exp_t const *expanded;
+} ldap_profile_ctx_t;
+
static xlat_arg_parser_t const ldap_escape_xlat_arg[] = {
{ .required = true, .concat = true, .type = FR_TYPE_STRING },
XLAT_ARG_PARSER_TERMINATOR
return UNLANG_ACTION_PUSHED_CHILD;
}
-/** Search for and apply an LDAP profile
+/** Process the results of a profile lookup
*
- * LDAP profiles are mapped using the same attribute map as user objects, they're used to add common
- * sets of attributes to the request.
- *
- * @param[out] p_result the result of applying the profile.
- * @param[in] request Current request.
- * @param[in] autz_ctx Authorization context being processed.
- * @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, request_t *request, ldap_autz_ctx_t *autz_ctx,
- char const *dn, fr_ldap_map_exp_t const *expanded)
+static unlang_action_t ldap_map_profile_resume(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request,
+ void *uctx)
{
- rlm_ldap_t const *inst = autz_ctx->inst;
- fr_ldap_thread_trunk_t *ttrunk = autz_ctx->ttrunk;
- rlm_rcode_t rcode = RLM_MODULE_OK;
- LDAPMessage *entry = NULL;
- int ldap_errno;
- LDAP *handle;
- fr_ldap_query_t *query;
-
- if (!dn || !*dn) RETURN_MODULE_OK;
+ ldap_profile_ctx_t *profile_ctx = talloc_get_type_abort(uctx, ldap_profile_ctx_t);
+ fr_ldap_query_t *query = profile_ctx->query;
+ LDAP *handle;
+ LDAPMessage *entry = NULL;
+ int ldap_errno;
+ rlm_rcode_t rcode = RLM_MODULE_OK;
- if (fr_ldap_trunk_search(&rcode,
- unlang_interpret_frame_talloc_ctx(request), &query, request, ttrunk, dn,
- LDAP_SCOPE_BASE, autz_ctx->mod_env->profile_filter.vb_strvalue,
- expanded->attrs, NULL, NULL, false) < 0) RETURN_MODULE_FAIL;
- switch (rcode) {
- case RLM_MODULE_OK:
+ switch (query->ret) {
+ case LDAP_RESULT_SUCCESS:
break;
- case RLM_MODULE_NOTFOUND:
- RDEBUG2("Profile object \"%s\" not found", dn);
- RETURN_MODULE_NOTFOUND;
+ case LDAP_RESULT_NO_RESULT:
+ case LDAP_RESULT_BAD_DN:
+ RDEBUG2("Profile object \"%s\" not found", profile_ctx->dn);
+ rcode = RLM_MODULE_NOTFOUND;
+ goto finish;
default:
- RETURN_MODULE_FAIL;
+ rcode = RLM_MODULE_FAIL;
+ goto finish;
}
fr_assert(query->result);
if (!entry) {
ldap_get_option(handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
REDEBUG("Failed retrieving entry: %s", ldap_err2string(ldap_errno));
-
- RETURN_MODULE_RCODE(RLM_MODULE_NOTFOUND);
+ rcode = RLM_MODULE_NOTFOUND;
+ goto finish;
}
RDEBUG2("Processing profile attributes");
RINDENT();
- if (fr_ldap_map_do(request, inst->valuepair_attr, expanded, entry) > 0) rcode = RLM_MODULE_UPDATED;
+ if (fr_ldap_map_do(request, profile_ctx->inst->valuepair_attr,
+ profile_ctx->expanded, entry) > 0) rcode = RLM_MODULE_UPDATED;
REXDENT();
+finish:
+ talloc_free(profile_ctx);
RETURN_MODULE_RCODE(rcode);
}
+/** Cancel an in progress profile lookup
+ *
+ */
+static void ldap_map_profile_cancel(UNUSED request_t *request, UNUSED fr_signal_t action, void *uctx)
+{
+ ldap_profile_ctx_t *profile_ctx = talloc_get_type_abort(uctx, ldap_profile_ctx_t);
+
+ if (!profile_ctx->query || !profile_ctx->query->treq) return;
+
+ fr_trunk_request_signal_cancel(profile_ctx->query->treq);
+}
+
+/** Search for and apply an LDAP profile
+ *
+ * LDAP profiles are mapped using the same attribute map as user objects, they're used to add common
+ * sets of attributes to the request.
+ *
+ * @param[in] request Current request.
+ * @param[in] autz_ctx Authorization context being processed.
+ * @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(request_t *request, ldap_autz_ctx_t *autz_ctx,
+ char const *dn, fr_ldap_map_exp_t const *expanded)
+{
+ rlm_ldap_t const *inst = autz_ctx->inst;
+ fr_ldap_thread_trunk_t *ttrunk = autz_ctx->ttrunk;
+ ldap_profile_ctx_t *profile_ctx;
+ rlm_rcode_t ret;
+
+ if (!dn || !*dn) return UNLANG_ACTION_CALCULATE_RESULT;
+
+ MEM(profile_ctx = talloc(unlang_interpret_frame_talloc_ctx(request), ldap_profile_ctx_t));
+ *profile_ctx = (ldap_profile_ctx_t) {
+ .dn = dn,
+ .expanded = expanded,
+ .inst = inst
+ };
+
+ if (unlang_function_push(request, NULL, ldap_map_profile_resume, ldap_map_profile_cancel,
+ ~FR_SIGNAL_CANCEL, UNLANG_SUB_FRAME, profile_ctx) < 0) {
+ talloc_free(profile_ctx);
+ return UNLANG_ACTION_FAIL;
+ }
+
+ return fr_ldap_trunk_search(&ret, profile_ctx, &profile_ctx->query, request, ttrunk, dn,
+ LDAP_SCOPE_BASE, autz_ctx->mod_env->profile_filter.vb_strvalue,
+ expanded->attrs, NULL, NULL, true);
+}
+
/** Start LDAP authorization with async lookup of user DN
*
*/