GLOBAL_LIB_TERMINATOR
};
+/** Holds state of in progress async authentication
+ *
+ */
+typedef struct {
+ char const *dn;
+ char const *password;
+ rlm_ldap_t const *inst;
+ fr_ldap_thread_t *thread;
+ fr_ldap_thread_trunk_t *ttrunk;
+ ldap_auth_mod_env_t *mod_env;
+} ldap_auth_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 1;
}
+/** Perform async lookup of user DN if required for authentication
+ *
+ */
+static unlang_action_t mod_authenticate_start(UNUSED rlm_rcode_t *p_result, UNUSED int *priority,
+ request_t *request, void *uctx)
+{
+ ldap_auth_ctx_t *auth_ctx = talloc_get_type_abort(uctx, ldap_auth_ctx_t);
+
+ return rlm_ldap_find_user_async(auth_ctx, auth_ctx->inst, request, &auth_ctx->mod_env->user_base,
+ &auth_ctx->mod_env->user_filter, auth_ctx->ttrunk, NULL, NULL);
+}
+
+/** Initiate async LDAP bind to authenticate user
+ *
+ */
+static unlang_action_t mod_authenticate_resume(rlm_rcode_t *p_result, UNUSED int *priority,
+ request_t *request, void *uctx)
+{
+ ldap_auth_ctx_t *auth_ctx = talloc_get_type_abort(uctx, ldap_auth_ctx_t);
+
+ /*
+ * Arriving here from an LDAP search will mean the dn in auth_ctx is NULL.
+ */
+ if (!auth_ctx->dn) auth_ctx->dn = rlm_find_user_dn_cached(request);
+
+ /*
+ * No DN found - can't authenticate the user.
+ */
+ if (!auth_ctx->dn) {
+ fail:
+ talloc_free(auth_ctx);
+ RETURN_MODULE_FAIL;
+ }
+
+ /*
+ * Attempt a bind using the thread specific connection for bind auths
+ */
+ if (fr_ldap_bind_auth_async(request, auth_ctx->thread, auth_ctx->dn, auth_ctx->password) < 0) goto fail;
+
+ RETURN_MODULE_RCODE(unlang_interpret_synchronous(unlang_interpret_event_list(request), request));
+}
+
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->inst->data, rlm_ldap_t);
fr_ldap_thread_t *thread = talloc_get_type_abort(module_rlm_thread_by_data(inst)->data, fr_ldap_thread_t);
- rlm_rcode_t rcode;
- char const *dn;
fr_ldap_thread_trunk_t *ttrunk = NULL;
+ ldap_auth_ctx_t *auth_ctx;
+ ldap_auth_mod_env_t *mod_env = talloc_get_type_abort(mctx->env_data, ldap_auth_mod_env_t);
char sasl_mech_buff[LDAP_MAX_DN_STR_LEN];
char sasl_proxy_buff[LDAP_MAX_DN_STR_LEN];
if (tmpl_expand(&sasl.mech, sasl_mech_buff, sizeof(sasl_mech_buff), request,
inst->user_sasl.mech, fr_ldap_escape_func, inst) < 0) {
RPEDEBUG("Failed expanding user.sasl.mech");
- rcode = RLM_MODULE_FAIL;
- goto finish;
+ fail:
+ RETURN_MODULE_RCODE(RLM_MODULE_FAIL);
}
if (inst->user_sasl.proxy) {
if (tmpl_expand(&sasl.proxy, sasl_proxy_buff, sizeof(sasl_proxy_buff), request,
inst->user_sasl.proxy, fr_ldap_escape_func, inst) < 0) {
RPEDEBUG("Failed expanding user.sasl.proxy");
- rcode = RLM_MODULE_FAIL;
- goto finish;
+ goto fail;
}
}
if (tmpl_expand(&sasl.realm, sasl_realm_buff, sizeof(sasl_realm_buff), request,
inst->user_sasl.realm, fr_ldap_escape_func, inst) < 0) {
RPEDEBUG("Failed expanding user.sasl.realm");
- rcode = RLM_MODULE_FAIL;
- goto finish;
+ goto fail;
}
}
}
RDEBUG2("Login attempt by \"%pV\"", &username->data);
- /*
- * Get the DN by doing a search.
- */
- dn = rlm_ldap_find_user(inst, request, ttrunk, NULL, false, NULL, NULL, &rcode);
- if (!dn) RETURN_MODULE_RCODE(rcode);
+ auth_ctx = talloc(unlang_interpret_frame_talloc_ctx(request), ldap_auth_ctx_t);
+ *auth_ctx = (ldap_auth_ctx_t){
+ .password = password->vp_strvalue,
+ .thread = thread,
+ .inst = inst,
+ .mod_env = mod_env,
+ .ttrunk = ttrunk
+ };
/*
- * Attempt a bind using the thread specific connection for bind auths
+ * Check for a cahed copy of the DN
*/
- if (fr_ldap_bind_auth_async(request, thread, dn, password->vp_strvalue) < 0) RETURN_MODULE_FAIL;
+ auth_ctx->dn = rlm_find_user_dn_cached(request);
- rcode = unlang_interpret_synchronous(unlang_interpret_event_list(request), request);
+ if (unlang_function_push(request, auth_ctx->dn ? NULL : mod_authenticate_start, mod_authenticate_resume,
+ NULL, 0, UNLANG_SUB_FRAME, auth_ctx) < 0) RETURN_MODULE_FAIL;
-finish:
-
- RETURN_MODULE_RCODE(rcode);
+ return UNLANG_ACTION_PUSHED_CHILD;
}
/** Search for and apply an LDAP profile