24 RCSID(
"$Id: 59e57d7825882054d1fc8ec22fd83e04b8ce9bf3 $")
28 #include <freeradius-devel/ldap/base.h>
29 #include <freeradius-devel/util/debug.h>
30 #include <sasl/sasl.h>
63 sasl_interact_t *cb = sasl_callbacks;
64 sasl_interact_t *cb_p;
66 for (cb_p = cb; cb_p->id != SASL_CB_LIST_END; cb_p++) {
67 DEBUG3(
"SASL challenge : %s", cb_p->challenge);
68 DEBUG3(
"SASL prompt : %s", cb_p->prompt);
71 case SASL_CB_AUTHNAME:
83 cb_p->len = strlen(sasl_ctx->
identity);
87 if (!sasl_ctx->
password)
goto null_result;
90 cb_p->len = strlen(sasl_ctx->
password);
94 if (!sasl_ctx->
proxy && !sasl_ctx->
identity)
goto null_result;
100 case SASL_CB_GETREALM:
101 if (!sasl_ctx->
realm)
goto null_result;
103 cb_p->result = sasl_ctx->
realm;
104 cb_p->len = strlen(sasl_ctx->
realm);
110 DEBUG3(
"SASL result : %s", cb_p->result ? (
char const *)cb_p->result :
"");
132 ldap_msgfree(sasl_ctx->
result);
146 struct berval *srv_cred;
149 ret = ldap_parse_sasl_bind_result(c->
handle, sasl_ctx->
result, &srv_cred, 0);
150 if (ret != LDAP_SUCCESS) {
151 ERROR(
"SASL decode failed (bind failed): %s", ldap_err2string(ret));
163 DEBUG3(
"SASL response : %pV",
165 ber_bvfree(srv_cred);
188 PERROR(
"SASL bind failed");
215 DEBUG2(
"%s SASL mech(s): %s", (sasl_ctx->
result == NULL ?
"Starting" :
"Continuing"), sasl_ctx->
mechs);
217 ret = ldap_sasl_interactive_bind(c->
handle, NULL, sasl_ctx->
mechs,
218 our_serverctrls, our_clientctrls,
231 case LDAP_X_CONNECTING:
232 ret = ldap_get_option(c->
handle, LDAP_OPT_DESC, &fd);
252 case LDAP_SASL_BIND_IN_PROGRESS:
254 ret = ldap_get_option(c->
handle, LDAP_OPT_DESC, &fd);
255 if ((ret != LDAP_OPT_SUCCESS) || (fd < 0))
goto error;
270 DEBUG2(
"SASL bind as \"%s\" to \"%s\" successful",
277 ERROR(
"ldap sasl bind failed: %s", ldap_err2string(ret));
310 char const *identity,
311 char const *password,
314 LDAPControl **serverctrls, LDAPControl **clientctrls)
320 DEBUG2(
"Starting SASL bind operation");
326 sasl_ctx->
mechs = mechs;
329 sasl_ctx->
proxy = proxy;
330 sasl_ctx->
realm = realm;
340 if ((ldap_get_option(c->
handle, LDAP_OPT_DESC, &fd) == LDAP_SUCCESS) && (fd >= 0)){
370 return ldap_sasl_interactive_bind(ldap_conn->
handle, NULL, sasl_ctx->
mechs,
371 NULL, NULL, LDAP_SASL_AUTOMATIC,
373 &sasl_ctx->
rmech, msgid);
395 RWARN(
"Cancelling SASL bind auth");
415 switch (bind_auth_ctx->
ret) {
452 if (bind_auth_ctx->
treq) {
453 if (bind_auth_ctx->
treq->tconn) ldap_conn = talloc_get_type_abort(bind_auth_ctx->
treq->tconn->conn->h,
484 RPERROR(
"LDAP connection returned an error - restarting the connection");
505 char const *identity,
char const *password,
char const *proxy,
char const *realm)
513 ERROR(
"Failed to get trunk connection for LDAP bind");
519 ERROR(
"Failed to allocate trunk request for LDAP bind");
529 .type = LDAP_BIND_SASL
536 .identity = identity,
537 .password = password,
550 ERROR(
"Failed to enqueue bind request");
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
@ UNLANG_ACTION_YIELD
Temporarily pause execution until an event occurs.
#define USES_APPLE_DEPRECATED_API
fr_dcursor_eval_t void const * uctx
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define fr_event_fd_insert(...)
#define unlang_function_repeat_set(_request, _repeat)
Set a new repeat function for an existing function frame.
#define unlang_function_push(_request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack.
char const * proxy
Proxy identity, may be NULL in which case identity is used.
fr_ldap_rcode_t ret
Return code of bind operation.
int msgid
libldap msgid for this bind.
char * server
Initial server to bind to.
LDAP * handle
libldap handle.
void fr_ldap_control_merge(LDAPControl *serverctrls_out[], LDAPControl *clientctrls_out[], size_t serverctrls_len, size_t clientctrls_len, fr_ldap_connection_t *conn, LDAPControl *serverctrls_in[], LDAPControl *clientctrls_in[])
Merge connection and call specific client and server controls.
char const * identity
of the user.
int fd
File descriptor for this connection.
void fr_ldap_state_error(fr_ldap_connection_t *c)
Signal that there's been an error on the connection.
LDAPMessage * result
Previous result.
fr_ldap_config_t const * config
rlm_ldap connection configuration.
fr_ldap_connection_t * c
to bind. Only used when binding as admin user.
LDAPControl ** clientctrls
Controls to pass to the client (library).
trunk_request_t * treq
Trunk request this bind is associated with.
char const * realm
SASL realm (may be NULL).
char const * mechs
SASL mechanisms to run.
char const * password
of the user, may be NULL if no password is specified.
fr_ldap_state_t fr_ldap_state_next(fr_ldap_connection_t *c)
Move between LDAP connection states.
fr_ldap_thread_trunk_t * fr_thread_ldap_bind_trunk_get(fr_ldap_thread_t *thread)
Find the thread specific trunk to use for LDAP bind auths.
int msgid
Last msgid. Only used when binding as admin user.
#define LDAP_MAX_CONTROLS
Maximum number of client/server controls.
char const * rmech
Mech we're continuing with.
LDAPControl ** serverctrls
Controls to pass to the server.
int fr_ldap_connection_timeout_reset(fr_ldap_connection_t const *conn)
trunk_t * trunk
Connection trunk.
fr_ldap_thread_t * thread
This bind is being run by.
connection_t * conn
Connection state handle.
fr_rb_tree_t * binds
Tree of outstanding bind auths.
fr_ldap_rcode_t
Codes returned by fr_ldap internal functions.
@ LDAP_PROC_CONTINUE
Operation is in progress.
@ LDAP_PROC_SUCCESS
Operation was successful.
@ LDAP_PROC_ERROR
Unrecoverable library/server error.
@ LDAP_PROC_NOT_PERMITTED
Operation was not permitted, either current user was locked out in the case of binds,...
@ LDAP_PROC_REJECT
Bind failed, user was rejected.
@ LDAP_PROC_BAD_DN
Specified an invalid object in a bind or search DN.
@ LDAP_PROC_NO_RESULT
Got no results.
Holds arguments for async bind auth requests.
Tracks the state of a libldap connection handle.
Holds arguments for the async SASL bind operation.
Thread specific structure to manage LDAP trunk connections.
Thread LDAP trunk structure.
fr_ldap_rcode_t fr_ldap_result(LDAPMessage **result, LDAPControl ***ctrls, fr_ldap_connection_t const *conn, int msgid, int all, char const *dn, fr_time_delta_t timeout)
Parse response from LDAP server dealing with any errors.
Stores all information relating to an event list.
void * fr_rb_remove(fr_rb_tree_t *tree, void const *data)
#define RETURN_MODULE_REJECT
#define RETURN_MODULE_INVALID
#define RETURN_MODULE_DISALLOW
rlm_rcode_t
Return codes indicating the result of the module call.
#define RETURN_MODULE_NOTFOUND
static USES_APPLE_DEPRECATED_API void _ldap_sasl_bind_io_write(fr_event_list_t *el, int fd, UNUSED int flags, void *uctx)
Progress an interactive SASL bind.
static void ldap_async_sasl_bind_auth_cancel(request_t *request, UNUSED fr_signal_t action, void *uctx)
Signal an outstanding SASL LDAP bind to cancel.
static void _ldap_sasl_bind_io_error(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, UNUSED int fd_errno, void *uctx)
Error reading from or writing to the file descriptor.
static void _ldap_sasl_bind_io_read(fr_event_list_t *el, int fd, UNUSED int flags, void *uctx)
Parse a sasl bind response from a server.
static int _sasl_interact(UNUSED LDAP *handle, UNUSED unsigned flags, void *uctx, void *sasl_callbacks)
Callback for fr_ldap_sasl_interactive_bind.
unlang_action_t fr_ldap_sasl_bind_auth_async(request_t *request, fr_ldap_thread_t *thread, char const *mechs, char const *identity, char const *password, char const *proxy, char const *realm)
Initiate an async SASL LDAP bind for authentication.
static unlang_action_t ldap_async_sasl_bind_auth_results(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
Handle the return code from parsed LDAP results to set the module rcode.
int fr_ldap_sasl_bind_async(fr_ldap_connection_t *c, char const *mechs, char const *identity, char const *password, char const *proxy, char const *realm, LDAPControl **serverctrls, LDAPControl **clientctrls)
Install I/O handlers for the bind operation.
static int _sasl_ctx_free(fr_ldap_sasl_ctx_t *sasl_ctx)
Ensure any outstanding messages are freed.
int fr_ldap_sasl_bind_auth_send(fr_ldap_sasl_ctx_t *sasl_ctx, int *msgid, fr_ldap_connection_t *ldap_conn)
Send a SASL LDAP auth bind.
static unlang_action_t ldap_async_sasl_bind_auth_start(UNUSED rlm_rcode_t *p_result, UNUSED int *priority, UNUSED request_t *request, UNUSED void *uctx)
Yield interpreter after enqueueing sasl auth bind.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
#define fr_time_delta_wrap(_time)
trunk_enqueue_t trunk_request_enqueue(trunk_request_t **treq_out, trunk_t *trunk, request_t *request, void *preq, void *rctx)
Enqueue a request that needs data written to the trunk.
trunk_enqueue_t trunk_request_requeue(trunk_request_t *treq)
Re-enqueue a request on the same connection.
void trunk_request_signal_cancel(trunk_request_t *treq)
Cancel a trunk request.
void trunk_request_free(trunk_request_t **treq_to_free)
If the trunk request is freed then update the target requests.
trunk_request_t * trunk_request_alloc(trunk_t *trunk, request_t *request)
(Pre-)Allocate a new trunk request
void trunk_request_signal_complete(trunk_request_t *treq)
Signal that a trunk request is complete.
@ TRUNK_ENQUEUE_OK
Operation was successful.
@ TRUNK_ENQUEUE_IN_BACKLOG
Request should be enqueued in backlog.
static fr_event_list_t * el
#define fr_box_strvalue_len(_val, _len)