The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
sasl.c
Go to the documentation of this file.
1 /*
2  * This program is is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or (at
5  * your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /**
18  * $Id: 9e47a36b4831a43cc746ca7ddb730866cdede49a $
19  * @file lib/ldap/bind.c
20  * @brief Asynchronous SASL bind functions for LDAP.
21  *
22  * @copyright 2017 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23  */
24 RCSID("$Id: 9e47a36b4831a43cc746ca7ddb730866cdede49a $")
25 
27 
28 #include <freeradius-devel/ldap/base.h>
29 #include <freeradius-devel/util/debug.h>
30 #include <sasl/sasl.h>
31 
32 static void _ldap_sasl_bind_io_write(fr_event_list_t *el, int fd, UNUSED int flags, void *uctx);
33 
34 /** Error reading from or writing to the file descriptor
35  *
36  * @param[in] el the event occurred in.
37  * @param[in] fd the event occurred on.
38  * @param[in] flags from kevent.
39  * @param[in] fd_errno The error that occurred.
40  * @param[in] uctx Connection config and handle.
41  */
43  UNUSED int flags, UNUSED int fd_errno, void *uctx)
44 {
45  fr_ldap_sasl_ctx_t *sasl_ctx = talloc_get_type_abort(uctx, fr_ldap_sasl_ctx_t);
46  fr_ldap_connection_t *c = sasl_ctx->c;
47 
48  talloc_free(sasl_ctx);
49  fr_ldap_state_error(c); /* Restart the connection state machine */
50 }
51 
52 /** Callback for fr_ldap_sasl_interactive_bind
53  *
54  * @param[in] handle used for the SASL bind.
55  * @param[in] flags data as provided to fr_ldap_sasl_interactive_bind.
56  * @param[in] uctx Our context data, containing the identity, password, realm and various other things.
57  * @param[in] sasl_callbacks Array of challenges to provide responses for.
58  * @return SASL_OK.
59  */
60 static int _sasl_interact(UNUSED LDAP *handle, UNUSED unsigned flags, void *uctx, void *sasl_callbacks)
61 {
62  fr_ldap_sasl_ctx_t *sasl_ctx = talloc_get_type_abort(uctx, fr_ldap_sasl_ctx_t);
63  sasl_interact_t *cb = sasl_callbacks;
64  sasl_interact_t *cb_p;
65 
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);
69 
70  switch (cb_p->id) {
71  case SASL_CB_AUTHNAME:
72  /*
73  * For mechs like -Y EXTERNAL we don't have
74  * any information to provide to SASL.
75  */
76  if (!sasl_ctx->identity) {
77  null_result:
78  cb_p->result = NULL;
79  cb_p->len = 0;
80  break;
81  }
82  cb_p->result = sasl_ctx->identity;
83  cb_p->len = strlen(sasl_ctx->identity);
84  break;
85 
86  case SASL_CB_PASS:
87  if (!sasl_ctx->password) goto null_result;
88 
89  cb_p->result = sasl_ctx->password;
90  cb_p->len = strlen(sasl_ctx->password);
91  break;
92 
93  case SASL_CB_USER:
94  if (!sasl_ctx->proxy && !sasl_ctx->identity) goto null_result;
95 
96  cb_p->result = sasl_ctx->proxy ? sasl_ctx->proxy : sasl_ctx->identity;
97  cb_p->len = sasl_ctx->proxy ? strlen(sasl_ctx->proxy) : strlen(sasl_ctx->identity);
98  break;
99 
100  case SASL_CB_GETREALM:
101  if (!sasl_ctx->realm) goto null_result;
102 
103  cb_p->result = sasl_ctx->realm;
104  cb_p->len = strlen(sasl_ctx->realm);
105  break;
106 
107  default:
108  break;
109  }
110  DEBUG3("SASL result : %s", cb_p->result ? (char const *)cb_p->result : "");
111  }
112  return SASL_OK;
113 }
114 
115 /** Parse a sasl bind response from a server
116  *
117  * @param[in] el the event occurred in.
118  * @param[in] fd the event occurred on.
119  * @param[in] flags from kevent.
120  * @param[in] uctx bind_ctx containing credentials, and connection config/handle.
121  */
122 static void _ldap_sasl_bind_io_read(fr_event_list_t *el, int fd, UNUSED int flags, void *uctx)
123 {
124  fr_ldap_sasl_ctx_t *sasl_ctx = talloc_get_type_abort(uctx, fr_ldap_sasl_ctx_t);
125  fr_ldap_connection_t *c = sasl_ctx->c;
126  fr_ldap_rcode_t status;
127 
128  /*
129  * Free the old result (if there is one)
130  */
131  if (sasl_ctx->result) {
132  ldap_msgfree(sasl_ctx->result);
133  sasl_ctx->result = NULL;
134  }
135 
136  /*
137  * If LDAP parse result indicates there was an error
138  * then we're done.
139  */
140  status = fr_ldap_result(&sasl_ctx->result, NULL, c, sasl_ctx->msgid, LDAP_MSG_ALL,
141  sasl_ctx->identity, fr_time_delta_wrap(0));
142  switch (status) {
143  case LDAP_PROC_SUCCESS:
144  case LDAP_PROC_CONTINUE:
145  {
146  struct berval *srv_cred;
147  int ret;
148 
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));
152  error:
153  talloc_free(sasl_ctx);
154  fr_ldap_state_error(c); /* Restart the connection state machine */
155  return;
156  }
157 
158  /*
159  * Observed as NULL when doing EXTERNAL
160  * authentication.
161  */
162  if (srv_cred) {
163  DEBUG3("SASL response : %pV",
164  fr_box_strvalue_len(srv_cred->bv_val, srv_cred->bv_len));
165  ber_bvfree(srv_cred);
166  }
167 
168  /*
169  * If we need to continue, wait until the
170  * socket is writable, and then call
171  * ldap_sasl_interactive_bind again.
172  *
173  * sasl_ctx->rmech may be NULL if there's
174  * nothing else to do.
175  */
176  if (sasl_ctx->rmech) DEBUG3("Continuing SASL mech %s...", sasl_ctx->rmech);
177 
178  ret = fr_event_fd_insert(sasl_ctx, NULL, el, fd,
179  NULL,
180  _ldap_sasl_bind_io_write, /* Need to write more SASL stuff */
182  sasl_ctx);
183  if (!fr_cond_assert(ret == 0)) goto error;
184  }
185  return;
186 
187  default:
188  PERROR("SASL bind failed");
189  goto error;
190  }
191 }
192 
193 /** Progress an interactive SASL bind
194  *
195  * @param[in] el the event occurred in.
196  * @param[in] fd the event occurred on.
197  * @param[in] flags from kevent.
198  * @param[in] uctx Connection config and handle.
199  */
200 static void _ldap_sasl_bind_io_write(fr_event_list_t *el, int fd, UNUSED int flags, void *uctx)
201 {
202  fr_ldap_sasl_ctx_t *sasl_ctx = talloc_get_type_abort(uctx, fr_ldap_sasl_ctx_t);
203  fr_ldap_connection_t *c = sasl_ctx->c;
204 
205  int ret = 0;
206 
207  LDAPControl *our_serverctrls[LDAP_MAX_CONTROLS];
208  LDAPControl *our_clientctrls[LDAP_MAX_CONTROLS];
209 
210  fr_ldap_control_merge(our_serverctrls, our_clientctrls,
211  NUM_ELEMENTS(our_serverctrls),
212  NUM_ELEMENTS(our_clientctrls),
213  c, sasl_ctx->serverctrls, sasl_ctx->clientctrls);
214 
215  DEBUG2("%s SASL mech(s): %s", (sasl_ctx->result == NULL ? "Starting" : "Continuing"), sasl_ctx->mechs);
216 
217  ret = ldap_sasl_interactive_bind(c->handle, NULL, sasl_ctx->mechs,
218  our_serverctrls, our_clientctrls,
219  LDAP_SASL_AUTOMATIC,
220  _sasl_interact, sasl_ctx, sasl_ctx->result,
221  &sasl_ctx->rmech, &sasl_ctx->msgid);
223  switch (ret) {
224  /*
225  * If the handle was not connected, this operation
226  * can return either LDAP_X_CONNECTING or
227  * LDAP_SASL_BIND_IN_PROGRESS
228  * depending on how fast the connection came up
229  * and whether it was connectionless.
230  */
231  case LDAP_X_CONNECTING:
232  ret = ldap_get_option(c->handle, LDAP_OPT_DESC, &fd);
233  if (!fr_cond_assert(ret == LDAP_OPT_SUCCESS)) {
234  error:
235  talloc_free(sasl_ctx);
237  fr_ldap_state_error(c); /* Restart the connection state machine */
238  return;
239  }
240 
241  ret = fr_event_fd_insert(sasl_ctx, NULL, el, fd,
242  NULL,
243  _ldap_sasl_bind_io_write, /* We'll be called again when the conn is open */
245  sasl_ctx);
246  if (!fr_cond_assert(ret == 0)) goto error;
247  break;
248 
249  /*
250  * Want to read more SASL stuff...
251  */
252  case LDAP_SASL_BIND_IN_PROGRESS:
253  if (fd < 0) {
254  ret = ldap_get_option(c->handle, LDAP_OPT_DESC, &fd);
255  if ((ret != LDAP_OPT_SUCCESS) || (fd < 0)) goto error;
256  }
257  c->fd = fd;
258  ret = fr_event_fd_insert(sasl_ctx, NULL, el, fd,
260  NULL,
262  sasl_ctx);
263  if (!fr_cond_assert(ret == 0)) goto error;
264  break;
265 
266  /*
267  * We're done, woohoo!
268  */
269  case LDAP_SUCCESS:
270  DEBUG2("SASL bind as \"%s\" to \"%s\" successful",
271  sasl_ctx->identity ? sasl_ctx->identity : "(anonymous)", c->config->server);
272  talloc_free(sasl_ctx);
274  break;
275 
276  default:
277  ERROR("ldap sasl bind failed: %s", ldap_err2string(ret));
278  goto error;
279  }
280 }
281 
282 /** Ensure any outstanding messages are freed
283  *
284  * @param[in] sasl_ctx to free.
285  * @return 0;
286  */
287 static int _sasl_ctx_free(fr_ldap_sasl_ctx_t *sasl_ctx)
288 {
289  if (sasl_ctx->result) ldap_msgfree(sasl_ctx->result);
290 
291  return 0;
292 }
293 
294 /** Install I/O handlers for the bind operation
295  *
296  * @param[in] c connection to StartTLS on.
297  * @param[in] mechs Space delimited list of sasl mechs to try.
298  * @param[in] identity SASL identity to bind with.
299  * @param[in] password Password credential to pass to SASL.
300  * @param[in] proxy identity. May be NULL.
301  * @param[in] realm SASL realm.
302  * @param[in] serverctrls Extra controls to pass to the server.
303  * @param[in] clientctrls Extra controls to pass to libldap.
304  * @return
305  * - 0 on success.
306  * - -1 on failure.
307  */
309  char const *mechs,
310  char const *identity,
311  char const *password,
312  char const *proxy,
313  char const *realm,
314  LDAPControl **serverctrls, LDAPControl **clientctrls)
315 {
316  int fd = -1;
317  fr_ldap_sasl_ctx_t *sasl_ctx;
319 
320  DEBUG2("Starting SASL bind operation");
321 
322  MEM(sasl_ctx = talloc_zero(c, fr_ldap_sasl_ctx_t));
323  talloc_set_destructor(sasl_ctx, _sasl_ctx_free);
324 
325  sasl_ctx->c = c;
326  sasl_ctx->mechs = mechs;
327  sasl_ctx->identity = identity;
328  sasl_ctx->password = password;
329  sasl_ctx->proxy = proxy;
330  sasl_ctx->realm = realm;
331  sasl_ctx->serverctrls = serverctrls;
332  sasl_ctx->clientctrls = clientctrls;
333 
334  el = c->conn->el;
335 
336  /*
337  * ldap_get_option can return LDAP_SUCCESS even if the fd is not yet available
338  * - hence the test for fd >= 0
339  */
340  if ((ldap_get_option(c->handle, LDAP_OPT_DESC, &fd) == LDAP_SUCCESS) && (fd >= 0)){
341  int ret;
342 
343  ret = fr_event_fd_insert(sasl_ctx, NULL, el, fd,
344  NULL,
347  sasl_ctx);
348  if (!fr_cond_assert(ret == 0)) {
349  talloc_free(sasl_ctx);
350  return -1;
351  }
352  } else {
353  _ldap_sasl_bind_io_write(el, -1, 0, sasl_ctx);
354  }
355 
356  return 0;
357 }
358 
359 /** Send a SASL LDAP auth bind
360  *
361  * Shares the same callback as SASL admin binds
362  *
363  * @param[in] sasl_ctx containing SASL parameters / state for the bind.
364  * @param[out] msgid where to write the LDAP message ID.
365  * @param[in] ldap_conn on which the message should be sent.
366  */
368  fr_ldap_connection_t *ldap_conn)
369 {
370  return ldap_sasl_interactive_bind(ldap_conn->handle, NULL, sasl_ctx->mechs,
371  NULL, NULL, LDAP_SASL_AUTOMATIC,
372  _sasl_interact, sasl_ctx, sasl_ctx->result,
373  &sasl_ctx->rmech, msgid);
374 }
375 
376 /** Yield interpreter after enqueueing sasl auth bind
377  *
378  */
380  UNUSED request_t *request, UNUSED void *uctx)
381 {
382  return UNLANG_ACTION_YIELD;
383 }
384 
385 /** Signal an outstanding SASL LDAP bind to cancel
386  *
387  * @param[in] request being processed. Unused.
388  * @param[in] action Signal to handle.
389  * @param[in] uctx bind auth ctx.
390  */
391 static void ldap_async_sasl_bind_auth_cancel(request_t *request, UNUSED fr_signal_t action, void *uctx)
392 {
393  fr_ldap_bind_auth_ctx_t *bind_auth_ctx = talloc_get_type_abort(uctx, fr_ldap_bind_auth_ctx_t);
394 
395  RWARN("Cancelling SASL bind auth");
396  if (bind_auth_ctx->msgid > 0) fr_rb_remove(bind_auth_ctx->thread->binds, bind_auth_ctx);
397  fr_trunk_request_signal_cancel(bind_auth_ctx->treq);
398 }
399 
400 /** Handle the return code from parsed LDAP results to set the module rcode
401  *
402  * @param[out] p_result Where to write return code.
403  * @param[in] priority Unused.
404  * @param[in] request being processed.
405  * @param[in] uctx bind auth ctx.
406  * @return unlang action.
407  */
408 static unlang_action_t ldap_async_sasl_bind_auth_results(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
409 {
410  fr_ldap_bind_auth_ctx_t *bind_auth_ctx = talloc_get_type_abort(uctx, fr_ldap_bind_auth_ctx_t);
411  fr_ldap_sasl_ctx_t *sasl_ctx = bind_auth_ctx->sasl_ctx;
412  fr_ldap_rcode_t ret = bind_auth_ctx->ret;
413  fr_ldap_connection_t *ldap_conn = NULL;
414 
415  switch (bind_auth_ctx->ret) {
416  case LDAP_PROC_SUCCESS:
417  RDEBUG2("Bind as user \"%s\" was successful", sasl_ctx->identity);
418  break;
419 
421  RDEBUG2("Bind as user \"%s\" not permitted", sasl_ctx->identity);
422  break;
423 
424  case LDAP_PROC_REJECT:
425  RDEBUG2("Bind as user \"%s\" rejected", sasl_ctx->identity);
426  break;
427 
428  case LDAP_PROC_CONTINUE:
429  if (fr_trunk_request_requeue(bind_auth_ctx->treq) != FR_TRUNK_ENQUEUE_OK) {
430  ret = LDAP_PROC_ERROR;
431  break;
432  }
433 
434  /*
435  * Once the next SASL exchange has completed repeat this function to
436  * process the results
437  */
439  /*
440  * Not strictly an LDAP error but if this happens we will want to reset
441  * the connection to get a known state.
442  */
443  ret = LDAP_PROC_ERROR;
444  break;
445  }
446  return UNLANG_ACTION_YIELD;
447 
448  default:
449  break;
450  }
451 
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,
455  /*
456  * Will free bind_auth_ctx
457  */
458  fr_trunk_request_signal_complete(bind_auth_ctx->treq);
459  } else {
460  /*
461  * If there is no trunk request, the request failed, and we need to free the ctx
462  */
463  talloc_free(bind_auth_ctx);
464  }
465 
466  switch (ret) {
467  case LDAP_PROC_SUCCESS:
469 
472 
473  case LDAP_PROC_REJECT:
475 
476  case LDAP_PROC_BAD_DN:
478 
479  case LDAP_PROC_NO_RESULT:
481 
482  default:
483  if (ldap_conn) {
484  RPERROR("LDAP connection returned an error - restarting the connection");
485  fr_ldap_state_error(ldap_conn);
486  }
488  }
489 }
490 
491 /** Initiate an async SASL LDAP bind for authentication
492  *
493  * @param[in] request this bind relates to.
494  * @param[in] thread whose connection the bind should be performed on.
495  * @param[in] mechs SASL mechanisms to use.
496  * @param[in] identity Identity to bind with.
497  * @param[in] password Password to bind with.
498  * @param[in] proxy Identity to proxy.
499  * @param[in] realm SASL realm if applicable.
500  * @return
501  * - 0 on success.
502  * - -1 on failure.
503 */
505  char const *identity, char const *password, char const *proxy, char const *realm)
506 {
507  fr_ldap_bind_auth_ctx_t *bind_auth_ctx;
508  fr_trunk_request_t *treq;
510  fr_trunk_enqueue_t ret;
511 
512  if (!ttrunk) {
513  ERROR("Failed to get trunk connection for LDAP bind");
514  return UNLANG_ACTION_FAIL;
515  }
516 
517  treq = fr_trunk_request_alloc(ttrunk->trunk, request);
518  if (!treq) {
519  ERROR("Failed to allocate trunk request for LDAP bind");
520  return UNLANG_ACTION_FAIL;
521  }
522 
523  MEM(bind_auth_ctx = talloc_zero(treq, fr_ldap_bind_auth_ctx_t));
524  *bind_auth_ctx = (fr_ldap_bind_auth_ctx_t) {
525  .treq = treq,
526  .request = request,
527  .thread = thread,
528  .ret = LDAP_PROC_NO_RESULT,
529  .type = LDAP_BIND_SASL
530  };
531 
532  MEM(bind_auth_ctx->sasl_ctx = talloc(bind_auth_ctx, fr_ldap_sasl_ctx_t));
533  talloc_set_destructor(bind_auth_ctx->sasl_ctx, _sasl_ctx_free);
534  *bind_auth_ctx->sasl_ctx = (fr_ldap_sasl_ctx_t) {
535  .mechs = mechs,
536  .identity = identity,
537  .password = password,
538  .proxy = proxy,
539  .realm = realm,
540  };
541 
542  ret = fr_trunk_request_enqueue(&bind_auth_ctx->treq, ttrunk->trunk, request, bind_auth_ctx, NULL);
543 
544  switch (ret) {
545  case FR_TRUNK_ENQUEUE_OK:
547  break;
548 
549  default:
550  ERROR("Failed to enqueue bind request");
551  fr_trunk_request_free(&treq);
552  return UNLANG_ACTION_FAIL;
553  }
554 
555  return unlang_function_push(request,
559  ~FR_SIGNAL_CANCEL, UNLANG_SUB_FRAME,
560  bind_auth_ctx);
561 }
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition: action.h:35
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
Definition: action.h:36
@ UNLANG_ACTION_YIELD
Temporarily pause execution until an event occurs.
Definition: action.h:42
#define USES_APPLE_DEPRECATED_API
Definition: build.h:431
#define RCSID(id)
Definition: build.h:444
#define UNUSED
Definition: build.h:313
#define NUM_ELEMENTS(_t)
Definition: build.h:335
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition: debug.h:137
#define ERROR(fmt,...)
Definition: dhcpclient.c:41
#define fr_event_fd_insert(...)
Definition: event.h:232
#define unlang_function_repeat_set(_request, _repeat)
Set a new repeat function for an existing function frame.
Definition: function.h:89
#define unlang_function_push(_request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack.
Definition: function.h:111
#define UNLANG_SUB_FRAME
Definition: interpret.h:36
char const * proxy
Proxy identity, may be NULL in which case identity is used.
Definition: base.h:506
fr_ldap_rcode_t ret
Return code of bind operation.
Definition: base.h:619
int msgid
libldap msgid for this bind.
Definition: base.h:612
char * server
Initial server to bind to.
Definition: base.h:222
LDAP * handle
libldap handle.
Definition: base.h:331
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.
Definition: control.c:48
fr_connection_t * conn
Connection state handle.
Definition: base.h:343
char const * identity
of the user.
Definition: base.h:504
int fd
File descriptor for this connection.
Definition: base.h:347
void fr_ldap_state_error(fr_ldap_connection_t *c)
Signal that there's been an error on the connection.
Definition: state.c:134
LDAPMessage * result
Previous result.
Definition: base.h:512
fr_ldap_config_t const * config
rlm_ldap connection configuration.
Definition: base.h:342
fr_ldap_connection_t * c
to bind. Only used when binding as admin user.
Definition: base.h:502
LDAPControl ** clientctrls
Controls to pass to the client (library).
Definition: base.h:509
char const * realm
SASL realm (may be NULL).
Definition: base.h:507
char const * mechs
SASL mechanisms to run.
Definition: base.h:503
char const * password
of the user, may be NULL if no password is specified.
Definition: base.h:505
fr_ldap_state_t fr_ldap_state_next(fr_ldap_connection_t *c)
Move between LDAP connection states.
Definition: state.c:49
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.
Definition: connection.c:1367
int msgid
Last msgid. Only used when binding as admin user.
Definition: base.h:511
#define LDAP_MAX_CONTROLS
Maximum number of client/server controls.
Definition: base.h:94
char const * rmech
Mech we're continuing with.
Definition: base.h:513
LDAPControl ** serverctrls
Controls to pass to the server.
Definition: base.h:508
fr_trunk_t * trunk
Connection trunk.
Definition: base.h:403
int fr_ldap_connection_timeout_reset(fr_ldap_connection_t const *conn)
Definition: connection.c:425
fr_ldap_thread_t * thread
This bind is being run by.
Definition: base.h:610
fr_rb_tree_t * binds
Tree of outstanding bind auths.
Definition: base.h:386
fr_trunk_request_t * treq
Trunk request this bind is associated with.
Definition: base.h:611
fr_ldap_rcode_t
Codes returned by fr_ldap internal functions.
Definition: base.h:577
@ LDAP_PROC_CONTINUE
Operation is in progress.
Definition: base.h:579
@ LDAP_PROC_SUCCESS
Operation was successful.
Definition: base.h:580
@ LDAP_PROC_ERROR
Unrecoverable library/server error.
Definition: base.h:582
@ LDAP_PROC_NOT_PERMITTED
Operation was not permitted, either current user was locked out in the case of binds,...
Definition: base.h:587
@ LDAP_PROC_REJECT
Bind failed, user was rejected.
Definition: base.h:591
@ LDAP_PROC_BAD_DN
Specified an invalid object in a bind or search DN.
Definition: base.h:593
@ LDAP_PROC_NO_RESULT
Got no results.
Definition: base.h:595
Holds arguments for async bind auth requests.
Definition: base.h:608
Tracks the state of a libldap connection handle.
Definition: base.h:330
Holds arguments for the async SASL bind operation.
Definition: base.h:501
Thread specific structure to manage LDAP trunk connections.
Definition: base.h:379
Thread LDAP trunk structure.
Definition: base.h:397
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.
Definition: base.c:449
#define PERROR(_fmt,...)
Definition: log.h:228
#define DEBUG3(_fmt,...)
Definition: log.h:266
#define RWARN(fmt,...)
Definition: log.h:297
#define RPERROR(fmt,...)
Definition: log.h:302
talloc_free(reap)
Stores all information relating to an event list.
Definition: event.c:411
#define RDEBUG2(fmt,...)
Definition: radclient.h:54
#define DEBUG2(fmt,...)
Definition: radclient.h:43
void * fr_rb_remove(fr_rb_tree_t *tree, void const *data)
Remove an entry from the tree, without freeing the data.
Definition: rb.c:691
#define RETURN_MODULE_REJECT
Definition: rcode.h:55
#define RETURN_MODULE_INVALID
Definition: rcode.h:59
#define RETURN_MODULE_OK
Definition: rcode.h:57
#define RETURN_MODULE_DISALLOW
Definition: rcode.h:60
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
#define RETURN_MODULE_NOTFOUND
Definition: rcode.h:61
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.
Definition: sasl.c:200
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.
Definition: sasl.c:391
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.
Definition: sasl.c:42
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.
Definition: sasl.c:122
static int _sasl_interact(UNUSED LDAP *handle, UNUSED unsigned flags, void *uctx, void *sasl_callbacks)
Callback for fr_ldap_sasl_interactive_bind.
Definition: sasl.c:60
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.
Definition: sasl.c:504
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.
Definition: sasl.c:408
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.
Definition: sasl.c:308
static int _sasl_ctx_free(fr_ldap_sasl_ctx_t *sasl_ctx)
Ensure any outstanding messages are freed.
Definition: sasl.c:287
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.
Definition: sasl.c:367
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.
Definition: sasl.c:379
fr_signal_t
Definition: signal.h:48
RETURN_MODULE_FAIL
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
#define fr_time_delta_wrap(_time)
Definition: time.h:152
void fr_trunk_request_free(fr_trunk_request_t **treq_to_free)
If the trunk request is freed then update the target requests.
Definition: trunk.c:2217
void fr_trunk_request_signal_cancel(fr_trunk_request_t *treq)
Cancel a trunk request.
Definition: trunk.c:2047
fr_trunk_request_t * fr_trunk_request_alloc(fr_trunk_t *trunk, request_t *request)
(Pre-)Allocate a new trunk request
Definition: trunk.c:2369
fr_trunk_enqueue_t fr_trunk_request_enqueue(fr_trunk_request_t **treq_out, fr_trunk_t *trunk, request_t *request, void *preq, void *rctx)
Enqueue a request that needs data written to the trunk.
Definition: trunk.c:2481
void fr_trunk_request_signal_complete(fr_trunk_request_t *treq)
Signal that a trunk request is complete.
Definition: trunk.c:1995
fr_trunk_enqueue_t fr_trunk_request_requeue(fr_trunk_request_t *treq)
Re-enqueue a request on the same connection.
Definition: trunk.c:2568
Wraps a normal request.
Definition: trunk.c:97
fr_trunk_enqueue_t
Definition: trunk.h:148
@ FR_TRUNK_ENQUEUE_IN_BACKLOG
Request should be enqueued in backlog.
Definition: trunk.h:149
@ FR_TRUNK_ENQUEUE_OK
Operation was successful.
Definition: trunk.h:150
static fr_event_list_t * el
#define fr_box_strvalue_len(_val, _len)
Definition: value.h:279