From: Nick Porter Date: Thu, 20 Apr 2023 13:24:09 +0000 (+0100) Subject: Add support for LDAP extended operations to async framework X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=df75fefeb2716e6bfa81f2a5695c759790fce0ba;p=thirdparty%2Ffreeradius-server.git Add support for LDAP extended operations to async framework --- diff --git a/src/lib/ldap/base.c b/src/lib/ldap/base.c index fba2da02071..5b0c420bf79 100644 --- a/src/lib/ldap/base.c +++ b/src/lib/ldap/base.c @@ -836,6 +836,81 @@ fr_ldap_rcode_t fr_ldap_modify_async(int *msgid, request_t *request, fr_ldap_con return LDAP_PROC_SUCCESS; } +/** Run an async LDAP "extended operation" query on a trunk connection + * + * @param[out] p_result from synchronous evaluation. + * @param[in] ctx to allocate the query in. + * @param[out] out that has been allocated. + * @param[in] request this query relates to. + * @param[in] ttrunk to submit the query to. + * @param[in] reqoid OID of extended operation. + * @param[in] reqdata Request data to send. + * @param[in] serverctrls specific to this query. + * @param[in] clientctrls specific to this query. + * @return + * - UNLANG_ACTION_FAIL on error. + * - UNLANG_ACTION_YIELD on success. + * - UNLANG_ACTION_CALCULATE_RESULT if the query was run synchronously. + */ +unlang_action_t fr_ldap_trunk_extended(rlm_rcode_t *p_result, + TALLOC_CTX *ctx, + fr_ldap_query_t **out, request_t *request, fr_ldap_thread_trunk_t *ttrunk, + char const *reqoid, struct berval *reqdata, + LDAPControl **serverctrls, LDAPControl **clientctrls) +{ + unlang_action_t action; + fr_ldap_query_t *query; + + query = fr_ldap_extended_alloc(ctx, reqoid, reqdata, serverctrls, clientctrls); + + switch (fr_trunk_request_enqueue(&query->treq, ttrunk->trunk, request, query, NULL)) { + case FR_TRUNK_ENQUEUE_OK: + case FR_TRUNK_ENQUEUE_IN_BACKLOG: + break; + + default: + error: + *out = NULL; + *p_result = RLM_MODULE_FAIL; + talloc_free(query); + return UNLANG_ACTION_FAIL; + } + + action = unlang_function_push(request, NULL, ldap_trunk_query_results, ldap_trunk_query_cancel, + ~FR_SIGNAL_CANCEL, UNLANG_SUB_FRAME, query); + + if (action == UNLANG_ACTION_FAIL) goto error; + + *out = query; + + return UNLANG_ACTION_PUSHED_CHILD; +} + +/** Initiate an LDAP extended operation + * + * Called by the trunk mux function + * + * @param[out] msgid LDAP message ID. + * @param[in] request Current request. + * @param[in] pconn to use. + * @param[in] reqoid OID of extended operation to perform. + * @param[in] reqdata Data required for the request. + * @return One of the LDAP_PROC_* (#fr_ldap_rcode_t) values. + */ +fr_ldap_rcode_t fr_ldap_extended_async(int *msgid, request_t *request, fr_ldap_connection_t **pconn, + char const *reqoid, struct berval *reqdata) +{ + int err; + + fr_assert(*pconn && (*pconn)->handle); + + RDEBUG2("Requesting extended operation with OID %s", reqoid); + err = ldap_extended_operation((*pconn)->handle, reqoid, reqdata, NULL, NULL, msgid); + + if (err) return LDAP_PROC_ERROR; + return LDAP_PROC_SUCCESS; +} + /** Free any libldap structures when an fr_ldap_query_t is freed * * It is also possible that the connection used for this query is now closed, @@ -889,6 +964,11 @@ static int _ldap_query_free(fr_ldap_query_t *query) talloc_free(query->ldap_conn); } + /* + * Ensure the request data for extended operations are freed. + */ + if (query->type == LDAP_REQUEST_EXTENDED && query->extended.reqdata) ber_bvfree(query->extended.reqdata); + return 0; } @@ -959,6 +1039,29 @@ fr_ldap_query_t *fr_ldap_modify_alloc(TALLOC_CTX *ctx, char const *dn, return query; } +/** Allocate a new LDAP extended operations object + * + * @param[in] ctx to allocate the query in. + * @param[in] reqoid OID of extended operation to perform. + * @param[in] reqdata Request data to send. + * @param[in] serverctrls Controls to pass to the server. May be NULL. + * @param[in] clientctrls Client controls. May be NULL. + * @return LDAP query object + */ +fr_ldap_query_t *fr_ldap_extended_alloc(TALLOC_CTX *ctx, char const *reqoid, struct berval *reqdata, + LDAPControl **serverctrls, LDAPControl **clientctrls) +{ + fr_ldap_query_t *query; + + query = ldap_query_alloc(ctx, LDAP_REQUEST_EXTENDED); + query->extended.reqoid = reqoid; + query->extended.reqdata = reqdata; + SET_LDAP_CTRLS(query->serverctrls, serverctrls); + SET_LDAP_CTRLS(query->clientctrls, clientctrls); + + return (query); +} + static int _ldap_handle_thread_local_free(void *handle) { if (ldap_unbind_ext_s(handle, NULL, NULL) < 0) return -1; diff --git a/src/lib/ldap/base.h b/src/lib/ldap/base.h index 3669a62b8f5..e3b78f0857e 100644 --- a/src/lib/ldap/base.h +++ b/src/lib/ldap/base.h @@ -175,7 +175,8 @@ typedef enum { */ typedef enum { LDAP_REQUEST_SEARCH = 1, //!< A lookup in an LDAP directory - LDAP_REQUEST_MODIFY //!< A modification to an LDAP entity + LDAP_REQUEST_MODIFY, //!< A modification to an LDAP entity + LDAP_REQUEST_EXTENDED //!< An extended LDAP operation } fr_ldap_request_type_t; /** LDAP query result codes @@ -427,6 +428,10 @@ struct fr_ldap_query_s { int scope; //!< Search scope. char const *filter; //!< Filter for search. } search; + struct { + char const *reqoid; //!< OID of extended operation to perform. + struct berval *reqdata; //!< Data required for the request. + } extended; LDAPMod **mods; //!< Changes to be applied if this query is a modification. }; @@ -700,6 +705,9 @@ fr_ldap_query_t *fr_ldap_search_alloc(TALLOC_CTX *ctx, fr_ldap_query_t *fr_ldap_modify_alloc(TALLOC_CTX *ctx, char const *dn, LDAPMod *mods[], LDAPControl **serverctrls, LDAPControl **clientctrls); +fr_ldap_query_t *fr_ldap_extended_alloc(TALLOC_CTX *ctx, char const *reqiod, struct berval *reqdata, + LDAPControl **serverctrls, LDAPControl **clientctrls); + unlang_action_t fr_ldap_trunk_search(rlm_rcode_t *p_result, TALLOC_CTX *ctx, fr_ldap_query_t **out, request_t *request, fr_ldap_thread_trunk_t *ttrunk, @@ -713,6 +721,12 @@ unlang_action_t fr_ldap_trunk_modify(rlm_rcode_t *p_result, char const *dn, LDAPMod *mods[], LDAPControl **serverctrls, LDAPControl **clientctrls); +unlang_action_t fr_ldap_trunk_extended(rlm_rcode_t *p_result, + TALLOC_CTX *ctx, + fr_ldap_query_t **out, request_t *request, fr_ldap_thread_trunk_t *ttrunk, + char const *reqoid, struct berval *reqdata, + LDAPControl **serverctrls, LDAPControl **clientctrls); + /* * base.c - Wrappers arounds OpenLDAP functions. */ @@ -736,6 +750,9 @@ fr_ldap_rcode_t fr_ldap_modify_async(int *msgid, request_t *request, fr_ldap_con char const *dn, LDAPMod *mods[], LDAPControl **serverctrls, LDAPControl **clientctrls); +fr_ldap_rcode_t fr_ldap_extended_async(int *msgid, request_t *request, fr_ldap_connection_t **pconn, + char const *reqiod, struct berval *reqdata); + fr_ldap_rcode_t fr_ldap_error_check(LDAPControl ***ctrls, fr_ldap_connection_t const *conn, LDAPMessage *msg, char const *dn);