Remove param documentation from all connection callbacks
[freeradius.git] / src / modules / rlm_ldap / ldap.c
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, version 2 if the
4  *   License as published by the Free Software Foundation.
5  *
6  *   This program is distributed in the hope that it will be useful,
7  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
8  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9  *   GNU General Public License for more details.
10  *
11  *   You should have received a copy of the GNU General Public License
12  *   along with this program; if not, write to the Free Software
13  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
14  */
15
16 /**
17  * $Id$
18  * @file ldap.c
19  * @brief LDAP module library functions.
20  *
21  * @author Arran Cudbard-Bell <a.cudbardb@freeradius.org>
22  * @copyright 2013 Network RADIUS SARL <info@networkradius.com>
23  * @copyright 2013 The FreeRADIUS Server Project.
24  */
25 #include <freeradius-devel/radiusd.h>
26 #include <freeradius-devel/modules.h>
27 #include <freeradius-devel/rad_assert.h>
28
29 #include <stdarg.h>
30 #include <ctype.h>
31
32 #include <lber.h>
33 #include <ldap.h>
34 #include "ldap.h"
35
36 /** Converts "bad" strings into ones which are safe for LDAP
37  *
38  * This is a callback for xlat operations.
39  *
40  * Will escape any characters in input strings that would cause the string to be interpreted as part of a DN and or
41  * filter. Escape sequence is @verbatim \<hex><hex> @endverbatim
42  *
43  * @param request The current request.
44  * @param out Pointer to output buffer.
45  * @param outlen Size of the output buffer.
46  * @param in Raw unescaped string.
47  * @param arg Any additional arguments (unused).
48  */
49 size_t rlm_ldap_escape_func(UNUSED REQUEST *request, char *out, size_t outlen, char const *in, UNUSED void *arg)
50 {
51         static char const encode[] = ",+\"\\<>;*=()";
52         static char const hextab[] = "0123456789abcdef";
53         size_t left = outlen;
54
55         if (*in && ((*in == ' ') || (*in == '#'))) {
56                 goto encode;
57         }
58
59         while (*in) {
60                 /*
61                  *      Encode unsafe characters.
62                  */
63                 if (memchr(encode, *in, sizeof(encode) - 1)) {
64                         encode:
65
66                         /*
67                          *      Only 3 or less bytes available.
68                          */
69                         if (left <= 3) break;
70
71                         *out++ = '\\';
72                         *out++ = hextab[(*in >> 4) & 0x0f];
73                         *out++ = hextab[*in & 0x0f];
74                         in++;
75                         left -= 3;
76
77                         continue;
78                 }
79
80                 if (left <= 1) break;
81
82                 /*
83                  *      Doesn't need encoding
84                  */
85                 *out++ = *in++;
86                 left--;
87         }
88
89         *out = '\0';
90
91         return outlen - left;
92 }
93
94 /** Check whether a string is a DN
95  *
96  * @param str to check.
97  * @return true if string is a DN, else false.
98  */
99 int rlm_ldap_is_dn(char const *str)
100 {
101         return strrchr(str, ',') == NULL ? false : true;
102 }
103
104 /** Find the place at which the two DN strings diverge
105  *
106  * Returns the length of the non matching string in full.
107  *
108  * @param full DN.
109  * @param part Partial DN as returned by ldap_parse_result.
110  * @return the length of the portion of full which wasn't matched or -1 on error.
111  */
112 static size_t rlm_ldap_common_dn(char const *full, char const *part)
113 {
114         size_t f_len, p_len, i;
115
116         if (!full) {
117                 return -1;
118         }
119
120         f_len = strlen(full);
121
122         if (!part) {
123                 return -1;
124         }
125
126         p_len = strlen(part);
127         if (!p_len) {
128                 return f_len;
129         }
130
131         if ((f_len < p_len) || !f_len) {
132                 return -1;
133         }
134
135         for (i = 0; i < p_len; i++) {
136                 if (part[p_len - i] != full[f_len - i]) {
137                         return -1;
138                 }
139         }
140
141         return f_len - p_len;
142 }
143
144 /** Combine and expand filters
145  *
146  * @param request Current request.
147  * @param out Where to write the expanded string.
148  * @param outlen Length of output buffer.
149  * @param sub Array of subfilters (may contain NULLs).
150  * @param sublen Number of potential subfilters in array.
151  * @return length of expanded data.
152  */
153 ssize_t rlm_ldap_xlat_filter(REQUEST *request, char const **sub, size_t sublen, char *out, size_t outlen)
154 {
155         char buffer[LDAP_MAX_FILTER_STR_LEN + 1];
156         char const *in = NULL;
157         char *p = buffer;
158
159         ssize_t len = 0;
160
161         unsigned int i;
162         int cnt = 0;
163
164         /*
165          *      Figure out how many filter elements we need to integrate
166          */
167         for (i = 0; i < sublen; i++) {
168                 if (sub[i] && *sub[i]) {
169                         in = sub[i];
170                         cnt++;
171                 }
172         }
173
174         if (!cnt) {
175                 out[0] = '\0';
176                 return 0;
177         }
178
179         if (cnt > 1) {
180                 if (outlen < 3) {
181                         goto oob;
182                 }
183
184                 p[len++] = '(';
185                 p[len++] = '&';
186
187                 for (i = 0; i < sublen; i++) {
188                         if (sub[i] && (*sub[i] != '\0')) {
189                                 len += strlcpy(p + len, sub[i], outlen - len);
190
191                                 if ((size_t) len >= outlen) {
192                                         oob:
193                                         REDEBUG("Out of buffer space creating filter");
194
195                                         return -1;
196                                 }
197                         }
198                 }
199
200                 if ((outlen - len) < 2) {
201                         goto oob;
202                 }
203
204                 p[len++] = ')';
205                 p[len] = '\0';
206
207                 in = buffer;
208         }
209
210         len = radius_xlat(out, outlen, request, in, rlm_ldap_escape_func, NULL);
211         if (len < 0) {
212                 REDEBUG("Failed creating filter");
213
214                 return -1;
215         }
216
217         return len;
218 }
219
220 /** Return the error string associated with a handle
221  *
222  * @param conn to retrieve error from.
223  * @return error string.
224  */
225 char const *rlm_ldap_error_str(ldap_handle_t const *conn)
226 {
227         int lib_errno;
228         ldap_get_option(conn->handle, LDAP_OPT_ERROR_NUMBER, &lib_errno);
229         if (lib_errno == LDAP_SUCCESS) {
230                 return "unknown";
231         }
232
233         return ldap_err2string(lib_errno);
234 }
235
236 /** Parse response from LDAP server dealing with any errors
237  *
238  * Should be called after an LDAP operation. Will check result of operation and if it was successful, then attempt
239  * to retrieve and parse the result.
240  *
241  * Will also produce extended error output including any messages the server sent, and information about partial
242  * DN matches.
243  *
244  * @param[in] inst of LDAP module.
245  * @param[in] conn Current connection.
246  * @param[in] msgid returned from last operation.
247  * @param[in] dn Last search or bind DN.
248  * @param[out] result Where to write result, if NULL result will be freed.
249  * @param[out] error Where to write the error string, may be NULL, must not be freed.
250  * @param[out] extra Where to write additional error string to, may be NULL (faster) or must be freed
251  *      (with talloc_free).
252  * @return One of the LDAP_PROC_* codes.
253  */
254 static ldap_rcode_t rlm_ldap_result(ldap_instance_t const *inst, ldap_handle_t const *conn, int msgid, char const *dn,
255                                     LDAPMessage **result, char const **error, char **extra)
256 {
257         ldap_rcode_t status = LDAP_PROC_SUCCESS;
258
259         int lib_errno = LDAP_SUCCESS;   // errno returned by the library.
260         int srv_errno = LDAP_SUCCESS;   // errno in the result message.
261
262         char *part_dn = NULL;           // Partial DN match.
263         char *our_err = NULL;           // Our extended error message.
264         char *srv_err = NULL;           // Server's extended error message.
265         char *p, *a;
266
267         bool freeit = false;            // Whether the message should be freed after being processed.
268         int len;
269
270         struct timeval tv;              // Holds timeout values.
271
272         LDAPMessage *tmp_msg;           // Temporary message pointer storage if we weren't provided with one.
273
274         char const *tmp_err;            // Temporary error pointer storage if we weren't provided with one.
275
276         if (!error) {
277                 error = &tmp_err;
278         }
279         *error = NULL;
280
281         if (extra) {
282                 *extra = NULL;
283         }
284
285         /*
286          *      We always need the result, but our caller may not
287          */
288         if (!result) {
289                 result = &tmp_msg;
290                 freeit = true;
291         }
292
293         *result = NULL;
294
295         /*
296          *      Check if there was an error sending the request
297          */
298         ldap_get_option(conn->handle, LDAP_OPT_ERROR_NUMBER,
299                         &lib_errno);
300         if (lib_errno != LDAP_SUCCESS) {
301                 goto process_error;
302         }
303
304         memset(&tv, 0, sizeof(tv));
305         tv.tv_sec = inst->res_timeout;
306
307         /*
308          *      Now retrieve the result and check for errors
309          *      ldap_result returns -1 on error, and 0 on timeout
310          */
311         lib_errno = ldap_result(conn->handle, msgid, 1, &tv, result);
312         if (lib_errno == 0) {
313                 lib_errno = LDAP_TIMEOUT;
314
315                 goto process_error;
316         }
317
318         if (lib_errno == -1) {
319                 ldap_get_option(conn->handle, LDAP_OPT_ERROR_NUMBER,
320                                 &lib_errno);
321                 goto process_error;
322         }
323
324         /*
325          *      Parse the result and check for errors sent by the server
326          */
327         lib_errno = ldap_parse_result(conn->handle, *result,
328                                       &srv_errno,
329                                       extra ? &part_dn : NULL,
330                                       extra ? &srv_err : NULL,
331                                       NULL, NULL, freeit);
332         if (freeit) {
333                 *result = NULL;
334         }
335
336         if (lib_errno != LDAP_SUCCESS) {
337                 ldap_get_option(conn->handle, LDAP_OPT_ERROR_NUMBER,
338                                 &lib_errno);
339                 goto process_error;
340         }
341
342 process_error:
343         if ((lib_errno == LDAP_SUCCESS) && (srv_errno != LDAP_SUCCESS)) {
344                 lib_errno = srv_errno;
345         } else if ((lib_errno != LDAP_SUCCESS) && (srv_errno == LDAP_SUCCESS)) {
346                 srv_errno = lib_errno;
347         }
348
349         switch (lib_errno) {
350         case LDAP_SUCCESS:
351                 *error = "Success";
352
353                 break;
354
355         case LDAP_NO_SUCH_OBJECT:
356                 *error = "The specified DN wasn't found, check base_dn and identity";
357
358                 status = LDAP_PROC_BAD_DN;
359
360                 if (!extra) break;
361
362                 /*
363                  *      Build our own internal diagnostic string
364                  */
365                 len = rlm_ldap_common_dn(dn, part_dn);
366                 if (len < 0) break;
367
368                 our_err = talloc_typed_asprintf(conn, "Match stopped here: [%.*s]%s", len, dn, part_dn ? part_dn : "");
369
370                 goto error_string;
371
372         case LDAP_INSUFFICIENT_ACCESS:
373                 *error = "Insufficient access. Check the identity and password configuration directives";
374
375                 status = LDAP_PROC_NOT_PERMITTED;
376                 break;
377
378         case LDAP_UNWILLING_TO_PERFORM:
379                 *error = "Server was unwilling to perform";
380
381                 status = LDAP_PROC_NOT_PERMITTED;
382                 break;
383
384         case LDAP_TIMEOUT:
385                 exec_trigger(NULL, inst->cs, "modules.ldap.timeout", true);
386
387                 *error = "Timed out while waiting for server to respond";
388
389                 status = LDAP_PROC_ERROR;
390                 break;
391
392         case LDAP_FILTER_ERROR:
393                 *error = "Bad search filter";
394
395                 status = LDAP_PROC_ERROR;
396                 break;
397
398         case LDAP_TIMELIMIT_EXCEEDED:
399                 exec_trigger(NULL, inst->cs, "modules.ldap.timeout", true);
400
401                 *error = "Time limit exceeded";
402                 /* FALL-THROUGH */
403
404         case LDAP_BUSY:
405         case LDAP_UNAVAILABLE:
406         case LDAP_SERVER_DOWN:
407                 status = LDAP_PROC_RETRY;
408
409                 goto error_string;
410
411         case LDAP_INVALID_CREDENTIALS:
412         case LDAP_CONSTRAINT_VIOLATION:
413                 status = LDAP_PROC_REJECT;
414
415                 goto error_string;
416
417         case LDAP_OPERATIONS_ERROR:
418                 *error = "Please set 'chase_referrals=yes' and 'rebind=yes'. See the ldap module configuration "
419                          "for details.";
420
421                 /* FALL-THROUGH */
422         default:
423                 status = LDAP_PROC_ERROR;
424
425                 error_string:
426
427                 if (!*error) {
428                         *error = ldap_err2string(lib_errno);
429                 }
430
431                 if (!extra || ((lib_errno == srv_errno) && !our_err && !srv_err)) {
432                         break;
433                 }
434
435                 /*
436                  *      Output the error codes from the library and server
437                  */
438                 p = talloc_zero_array(conn, char, 1);
439                 if (!p) break;
440
441                 if (lib_errno != srv_errno) {
442                         a = talloc_asprintf_append(p, "LDAP lib error: %s (%u), srv error: %s (%u). ",
443                                                    ldap_err2string(lib_errno), lib_errno,
444                                                    ldap_err2string(srv_errno), srv_errno);
445                         if (!a) {
446                                 talloc_free(p);
447                                 break;
448                         }
449
450                         p = a;
451                 }
452
453                 if (our_err) {
454                         a = talloc_asprintf_append_buffer(p, "%s. ", our_err);
455                         if (!a) {
456                                 talloc_free(p);
457                                 break;
458                         }
459
460                         p = a;
461                 }
462
463                 if (srv_err) {
464                         a = talloc_asprintf_append_buffer(p, "Server said: %s. ", srv_err);
465                         if (!a) {
466                                 talloc_free(p);
467                                 break;
468                         }
469
470                         p = a;
471                 }
472
473                 *extra = p;
474
475                 break;
476         }
477
478         /*
479          *      Cleanup memory
480          */
481         if (srv_err) {
482                 ldap_memfree(srv_err);
483         }
484
485         if (part_dn) {
486                 ldap_memfree(part_dn);
487         }
488
489         talloc_free(our_err);
490
491         if ((lib_errno || srv_errno) && *result) {
492                 ldap_msgfree(*result);
493                 *result = NULL;
494         }
495
496         return status;
497 }
498
499 /** Bind to the LDAP directory as a user
500  *
501  * Performs a simple bind to the LDAP directory, and handles any errors that occur.
502  *
503  * @param[in] inst rlm_ldap configuration.
504  * @param[in] request Current request, this may be NULL, in which case all debug logging is done with radlog.
505  * @param[in,out] pconn to use. May change as this function calls functions which auto re-connect.
506  * @param[in] dn of the user, may be NULL to bind anonymously.
507  * @param[in] password of the user, may be NULL if no password is specified.
508  * @param[in] retry if the server is down.
509  * @return one of the LDAP_PROC_* values.
510  */
511 ldap_rcode_t rlm_ldap_bind(ldap_instance_t const *inst, REQUEST *request, ldap_handle_t **pconn, char const *dn,
512                            char const *password, bool retry)
513 {
514         ldap_rcode_t    status = LDAP_PROC_ERROR;
515
516         int             msgid;
517
518         char const      *error = NULL;
519         char            *extra = NULL;
520
521         int             i, num;
522
523         rad_assert(*pconn && (*pconn)->handle);
524         rad_assert(!retry || inst->pool);
525
526         /*
527          *      Bind as anonymous user
528          */
529         if (!dn) dn = "";
530
531         /*
532          *      For sanity, for when no connections are viable,
533          *      and we can't make a new one.
534          */
535         num = retry ? fr_connection_get_num(inst->pool) : 0;
536         for (i = num; i >= 0; i--) {
537                 msgid = ldap_bind((*pconn)->handle, dn, password, LDAP_AUTH_SIMPLE);
538                 /* We got a valid message ID */
539                 if (msgid >= 0) {
540                         if (request) {
541                                 RDEBUG2("Waiting for bind result...");
542                         } else {
543                                 DEBUG2("rlm_ldap (%s): Waiting for bind result...", inst->xlat_name);
544                         }
545                 }
546
547                 status = rlm_ldap_result(inst, *pconn, msgid, dn, NULL, &error, &extra);
548                 switch (status) {
549                 case LDAP_PROC_SUCCESS:
550                         LDAP_DBG_REQ("Bind successful");
551                         break;
552
553                 case LDAP_PROC_NOT_PERMITTED:
554                         LDAP_ERR_REQ("Bind was not permitted: %s", error);
555                         LDAP_EXT_REQ();
556
557                         break;
558
559                 case LDAP_PROC_REJECT:
560                         LDAP_ERR_REQ("Bind credentials incorrect: %s", error);
561                         LDAP_EXT_REQ();
562
563                         break;
564
565                 case LDAP_PROC_RETRY:
566                         if (retry) {
567                                 *pconn = fr_connection_reconnect(inst->pool, *pconn);
568                                 if (*pconn) {
569                                         LDAP_DBGW_REQ("Bind with %s to %s:%d failed: %s. Got new socket, retrying...",
570                                                       dn, inst->server, inst->port, error);
571
572                                         talloc_free(extra); /* don't leak debug info */
573
574                                         continue;
575                                 }
576                         };
577                         status = LDAP_PROC_ERROR;
578
579                         /*
580                          *      Were not allowed to retry, or there are no more
581                          *      sockets, treat this as a hard failure.
582                          */
583                         /* FALL-THROUGH */
584                 default:
585 #ifdef HAVE_LDAP_INITIALIZE
586                         if (inst->is_url) {
587                                 LDAP_ERR_REQ("Bind with %s to %s failed: %s", dn, inst->server, error);
588                         } else
589 #endif
590                         {
591                                 LDAP_ERR_REQ("Bind with %s to %s:%d failed: %s", dn, inst->server,
592                                              inst->port, error);
593                         }
594                         LDAP_EXT_REQ();
595
596                         break;
597                 }
598
599                 break;
600         }
601
602         if (retry && (i < 0)) {
603                 LDAP_ERR_REQ("Hit reconnection limit");
604                 status = LDAP_PROC_ERROR;
605         }
606
607         talloc_free(extra);
608
609         return status; /* caller closes the connection */
610 }
611
612 /** Search for something in the LDAP directory
613  *
614  * Binds as the administrative user and performs a search, dealing with any errors.
615  *
616  * @param[in] inst rlm_ldap configuration.
617  * @param[in] request Current request.
618  * @param[in,out] pconn to use. May change as this function calls functions which auto re-connect.
619  * @param[in] dn to use as base for the search.
620  * @param[in] scope to use (LDAP_SCOPE_BASE, LDAP_SCOPE_ONE, LDAP_SCOPE_SUB).
621  * @param[in] filter to use, should be pre-escaped.
622  * @param[in] attrs to retrieve.
623  * @param[out] result Where to store the result. Must be freed with ldap_msgfree if LDAP_PROC_SUCCESS is returned.
624  *      May be NULL in which case result will be automatically freed after use.
625  * @return One of the LDAP_PROC_* values.
626  */
627 ldap_rcode_t rlm_ldap_search(ldap_instance_t const *inst, REQUEST *request, ldap_handle_t **pconn,
628                              char const *dn, int scope, char const *filter, char const * const *attrs,
629                              LDAPMessage **result)
630 {
631         ldap_rcode_t    status;
632         LDAPMessage     *our_result = NULL;
633
634         int             msgid;          // Message id returned by
635                                         // ldap_search_ext.
636
637         int             count = 0;      // Number of results we got.
638
639         struct timeval  tv;             // Holds timeout values.
640
641         char const      *error = NULL;
642         char            *extra = NULL;
643
644         int             i;
645
646
647         rad_assert(*pconn && (*pconn)->handle);
648
649         /*
650          *      OpenLDAP library doesn't declare attrs array as const, but
651          *      it really should be *sigh*.
652          */
653         char **search_attrs;
654         memcpy(&search_attrs, &attrs, sizeof(attrs));
655
656         /*
657          *      Do all searches as the admin user.
658          */
659         if ((*pconn)->rebound) {
660                 status = rlm_ldap_bind(inst, request, pconn, inst->admin_dn, inst->password, true);
661                 if (status != LDAP_PROC_SUCCESS) {
662                         return LDAP_PROC_ERROR;
663                 }
664
665                 rad_assert(*pconn);
666
667                 (*pconn)->rebound = false;
668         }
669
670         if (filter) {
671                 LDAP_DBG_REQ("Performing search in '%s' with filter '%s', scope '%s'", dn, filter,
672                              fr_int2str(ldap_scope, scope, "<INVALID>"));
673         } else {
674                 LDAP_DBG_REQ("Performing unfiltered search in '%s', scope '%s'", dn,
675                              fr_int2str(ldap_scope, scope, "<INVALID>"));
676         }
677         /*
678          *      If LDAP search produced an error it should also be logged
679          *      to the ld. result should pick it up without us
680          *      having to pass it explicitly.
681          */
682         memset(&tv, 0, sizeof(tv));
683         tv.tv_sec = inst->res_timeout;
684
685         /*
686          *      For sanity, for when no connections are viable,
687          *      and we can't make a new one.
688          */
689         for (i = fr_connection_get_num(inst->pool); i >= 0; i--) {
690                 (void) ldap_search_ext((*pconn)->handle, dn, scope, filter, search_attrs,
691                                        0, NULL, NULL, &tv, 0, &msgid);
692
693                 LDAP_DBG_REQ("Waiting for search result...");
694                 status = rlm_ldap_result(inst, *pconn, msgid, dn, &our_result, &error, &extra);
695                 switch (status) {
696                 case LDAP_PROC_SUCCESS:
697                         break;
698
699                 case LDAP_PROC_RETRY:
700                         *pconn = fr_connection_reconnect(inst->pool, *pconn);
701                         if (*pconn) {
702                                 LDAP_DBGW_REQ("Search failed: %s. Got new socket, retrying...", error);
703
704                                 talloc_free(extra); /* don't leak debug info */
705
706                                 continue;
707                         }
708
709                         status = LDAP_PROC_ERROR;
710
711                         /* FALL-THROUGH */
712                 default:
713                         LDAP_ERR_REQ("Failed performing search: %s", error);
714                         if (extra) LDAP_ERR_REQ("%s", extra);
715
716                         goto finish;
717                 }
718
719                 break;
720         }
721
722         if (i < 0) {
723                 LDAP_ERR_REQ("Hit reconnection limit");
724                 status = LDAP_PROC_ERROR;
725
726                 goto finish;
727         }
728
729         count = ldap_count_entries((*pconn)->handle, our_result);
730         if (count < 0) {
731                 LDAP_ERR_REQ("Error counting results: %s", rlm_ldap_error_str(*pconn));
732                 status = LDAP_PROC_ERROR;
733
734                 ldap_msgfree(our_result);
735                 our_result = NULL;
736         } else if (count == 0) {
737                 LDAP_DBG_REQ("Search returned no results");
738                 status = LDAP_PROC_NO_RESULT;
739
740                 ldap_msgfree(our_result);
741                 our_result = NULL;
742         }
743
744 finish:
745         talloc_free(extra);
746
747         /*
748          *      We always need to get the result to count entries, but the caller
749          *      may not of requested one. If that's the case, free it, else write
750          *      it to where our caller said.
751          */
752         if (!result) {
753                 if (our_result) {
754                         ldap_msgfree(our_result);
755                 }
756         } else {
757                 *result = our_result;
758         }
759
760         return status;
761 }
762
763 /** Modify something in the LDAP directory
764  *
765  * Binds as the administrative user and attempts to modify an LDAP object.
766  *
767  * @param[in] inst rlm_ldap configuration.
768  * @param[in] request Current request.
769  * @param[in,out] pconn to use. May change as this function calls functions which auto re-connect.
770  * @param[in] dn of the object to modify.
771  * @param[in] mods to make, see 'man ldap_modify' for more information.
772  * @return One of the LDAP_PROC_* values.
773  */
774 ldap_rcode_t rlm_ldap_modify(ldap_instance_t const *inst, REQUEST *request, ldap_handle_t **pconn,
775                              char const *dn, LDAPMod *mods[])
776 {
777         ldap_rcode_t    status;
778
779         int             msgid;          // Message id returned by ldap_search_ext.
780
781         char const      *error = NULL;
782         char            *extra = NULL;
783
784         int             i;
785
786         rad_assert(*pconn && (*pconn)->handle);
787
788         /*
789          *      Perform all modifications as the admin user.
790          */
791         if ((*pconn)->rebound) {
792                 status = rlm_ldap_bind(inst, request, pconn, inst->admin_dn, inst->password, true);
793                 if (status != LDAP_PROC_SUCCESS) {
794                         return LDAP_PROC_ERROR;
795                 }
796
797                 rad_assert(*pconn);
798
799                 (*pconn)->rebound = false;
800         }
801
802         /*
803          *      For sanity, for when no connections are viable,
804          *      and we can't make a new one.
805          */
806         for (i = fr_connection_get_num(inst->pool); i >= 0; i--) {
807                 RDEBUG2("Modifying object with DN \"%s\"", dn);
808                 (void) ldap_modify_ext((*pconn)->handle, dn, mods, NULL, NULL, &msgid);
809
810                 RDEBUG2("Waiting for modify result...");
811                 status = rlm_ldap_result(inst, *pconn, msgid, dn, NULL, &error, &extra);
812                 switch (status) {
813                         case LDAP_PROC_SUCCESS:
814                                 break;
815
816                         case LDAP_PROC_RETRY:
817                                 *pconn = fr_connection_reconnect(inst->pool, *pconn);
818                                 if (*pconn) {
819                                         RWDEBUG("Modify failed: %s. Got new socket, retrying...", error);
820
821                                         talloc_free(extra); /* don't leak debug info */
822
823                                         continue;
824                                 }
825
826                                 status = LDAP_PROC_ERROR;
827
828                                 /* FALL-THROUGH */
829                         default:
830                                 REDEBUG("Failed modifying object: %s", error);
831                                 REDEBUG("%s", extra);
832
833                                 goto finish;
834                 }
835
836                 break;
837         }
838
839         if (i < 0) {
840                 LDAP_ERR_REQ("Hit reconnection limit");
841                 status = LDAP_PROC_ERROR;
842         }
843
844 finish:
845         talloc_free(extra);
846
847         return status;
848 }
849
850 /** Retrieve the DN of a user object
851  *
852  * Retrieves the DN of a user and adds it to the control list as LDAP-UserDN. Will also retrieve any attributes
853  * passed and return the result in *result.
854  *
855  * This potentially allows for all authorization and authentication checks to be performed in one ldap search
856  * operation, which is a big bonus given the number of crappy, slow *cough*AD*cough* LDAP directory servers out there.
857  *
858  * @param[in] inst rlm_ldap configuration.
859  * @param[in] request Current request.
860  * @param[in,out] pconn to use. May change as this function calls functions which auto re-connect.
861  * @param[in] attrs Additional attributes to retrieve, may be NULL.
862  * @param[in] force Query even if the User-DN already exists.
863  * @param[out] result Where to write the result, may be NULL in which case result is discarded.
864  * @param[out] rcode The status of the operation, one of the RLM_MODULE_* codes.
865  * @return The user's DN or NULL on error.
866  */
867 char const *rlm_ldap_find_user(ldap_instance_t const *inst, REQUEST *request, ldap_handle_t **pconn,
868                                char const *attrs[], int force, LDAPMessage **result, rlm_rcode_t *rcode)
869 {
870         static char const *tmp_attrs[] = { NULL };
871
872         ldap_rcode_t    status;
873         VALUE_PAIR      *vp = NULL;
874         LDAPMessage     *tmp_msg = NULL, *entry = NULL;
875         int             ldap_errno;
876         char            *dn = NULL;
877         char            filter[LDAP_MAX_FILTER_STR_LEN];
878         char            base_dn[LDAP_MAX_DN_STR_LEN];
879
880         bool freeit = false;                                    //!< Whether the message should
881                                                                 //!< be freed after being processed.
882
883         *rcode = RLM_MODULE_FAIL;
884
885         if (!result) {
886                 result = &tmp_msg;
887                 freeit = true;
888         }
889         *result = NULL;
890
891         if (!attrs) {
892                 memset(&attrs, 0, sizeof(tmp_attrs));
893         }
894
895         /*
896          *      If the caller isn't looking for the result we can just return the current userdn value.
897          */
898         if (!force) {
899                 vp = pairfind(request->config_items, PW_LDAP_USERDN, 0, TAG_ANY);
900                 if (vp) {
901                         RDEBUG("Using user DN from request \"%s\"", vp->vp_strvalue);
902                         *rcode = RLM_MODULE_OK;
903                         return vp->vp_strvalue;
904                 }
905         }
906
907         /*
908          *      Perform all searches as the admin user.
909          */
910         if ((*pconn)->rebound) {
911                 status = rlm_ldap_bind(inst, request, pconn, inst->admin_dn, inst->password, true);
912                 if (status != LDAP_PROC_SUCCESS) {
913                         *rcode = RLM_MODULE_FAIL;
914                         return NULL;
915                 }
916
917                 rad_assert(*pconn);
918
919                 (*pconn)->rebound = false;
920         }
921
922         if (radius_xlat(filter, sizeof(filter), request, inst->userobj_filter, rlm_ldap_escape_func, NULL) < 0) {
923                 REDEBUG("Unable to create filter");
924                 *rcode = RLM_MODULE_INVALID;
925
926                 return NULL;
927         }
928
929         if (radius_xlat(base_dn, sizeof(base_dn), request, inst->userobj_base_dn, rlm_ldap_escape_func, NULL) < 0) {
930                 REDEBUG("Unable to create base_dn");
931                 *rcode = RLM_MODULE_INVALID;
932
933                 return NULL;
934         }
935
936         status = rlm_ldap_search(inst, request, pconn, base_dn, inst->userobj_scope, filter, attrs, result);
937         switch (status) {
938                 case LDAP_PROC_SUCCESS:
939                         break;
940
941                 case LDAP_PROC_NO_RESULT:
942                         *rcode = RLM_MODULE_NOTFOUND;
943                         return NULL;
944
945                 default:
946                         *rcode = RLM_MODULE_FAIL;
947                         return NULL;
948         }
949
950         rad_assert(*pconn);
951
952         entry = ldap_first_entry((*pconn)->handle, *result);
953         if (!entry) {
954                 ldap_get_option((*pconn)->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
955                 REDEBUG("Failed retrieving entry: %s",
956                         ldap_err2string(ldap_errno));
957
958                 goto finish;
959         }
960
961         dn = ldap_get_dn((*pconn)->handle, entry);
962         if (!dn) {
963                 ldap_get_option((*pconn)->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
964
965                 REDEBUG("Retrieving object DN from entry failed: %s",
966                         ldap_err2string(ldap_errno));
967
968                 goto finish;
969         }
970
971         RDEBUG("User object found at DN \"%s\"", dn);
972         vp = pairmake(request, &request->config_items, "LDAP-UserDN", dn, T_OP_EQ);
973         if (vp) {
974                 *rcode = RLM_MODULE_OK;
975         }
976
977         finish:
978         ldap_memfree(dn);
979
980         if ((freeit || (*rcode != RLM_MODULE_OK)) && *result) {
981                 ldap_msgfree(*result);
982                 *result = NULL;
983         }
984
985         return vp ? vp->vp_strvalue : NULL;
986 }
987
988 /** Check for presence of access attribute in result
989  *
990  * @param[in] inst rlm_ldap configuration.
991  * @param[in] request Current request.
992  * @param[in] conn used to retrieve access attributes.
993  * @param[in] entry retrieved by rlm_ldap_find_user or rlm_ldap_search.
994  * @return RLM_MODULE_USERLOCK if the user was denied access, else RLM_MODULE_OK.
995  */
996 rlm_rcode_t rlm_ldap_check_access(ldap_instance_t const *inst, REQUEST *request,
997                                   ldap_handle_t const *conn, LDAPMessage *entry)
998 {
999         rlm_rcode_t rcode = RLM_MODULE_OK;
1000         char **vals = NULL;
1001
1002         vals = ldap_get_values(conn->handle, entry, inst->userobj_access_attr);
1003         if (vals) {
1004                 if (inst->access_positive) {
1005                         if (strncasecmp(vals[0], "false", 5) == 0) {
1006                                 RDEBUG("\"%s\" attribute exists but is set to 'false' - user locked out",
1007                                        inst->userobj_access_attr);
1008                                 rcode = RLM_MODULE_USERLOCK;
1009                         }
1010                         /* RLM_MODULE_OK set above... */
1011                 } else if (strncasecmp(vals[0], "false", 5) != 0) {
1012                         RDEBUG("\"%s\" attribute exists - user locked out", inst->userobj_access_attr);
1013                         rcode = RLM_MODULE_USERLOCK;
1014                 }
1015
1016                 ldap_value_free(vals);
1017         } else if (inst->access_positive) {
1018                 RDEBUG("No \"%s\" attribute - user locked out", inst->userobj_access_attr);
1019                 rcode = RLM_MODULE_USERLOCK;
1020         }
1021
1022         return rcode;
1023 }
1024
1025 /** Verify we got a password from the search
1026  *
1027  * Checks to see if after the LDAP to RADIUS mapping has been completed that a reference password.
1028  *
1029  * @param inst rlm_ldap configuration.
1030  * @param request Current request.
1031  */
1032 void rlm_ldap_check_reply(ldap_instance_t const *inst, REQUEST *request)
1033 {
1034        /*
1035         *       More warning messages for people who can't be bothered to read the documentation.
1036         *
1037         *       Expect_password is set when we process the mapping, and is only true if there was a mapping between
1038         *       an LDAP attribute and a password reference attribute in the control list.
1039         */
1040         if (inst->expect_password && (debug_flag > 1)) {
1041                 if (!pairfind(request->config_items, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY) &&
1042                     !pairfind(request->config_items, PW_NT_PASSWORD, 0, TAG_ANY) &&
1043                     !pairfind(request->config_items, PW_USER_PASSWORD, 0, TAG_ANY) &&
1044                     !pairfind(request->config_items, PW_PASSWORD_WITH_HEADER, 0, TAG_ANY) &&
1045                     !pairfind(request->config_items, PW_CRYPT_PASSWORD, 0, TAG_ANY)) {
1046                         RWDEBUG("No \"known good\" password added. Ensure the admin user has permission to "
1047                                 "read the password attribute");
1048                         RWDEBUG("PAP authentication will *NOT* work with Active Directory (if that is what you "
1049                                 "were trying to configure)");
1050                 }
1051        }
1052 }
1053
1054 #if LDAP_SET_REBIND_PROC_ARGS == 3
1055 /** Callback for OpenLDAP to rebind and chase referrals
1056  *
1057  * Called by OpenLDAP when it receives a referral and has to rebind.
1058  *
1059  * @param handle to rebind.
1060  * @param url to bind to.
1061  * @param request that triggered the rebind.
1062  * @param msgid that triggered the rebind.
1063  * @param ctx rlm_ldap configuration.
1064  */
1065 static int rlm_ldap_rebind(LDAP *handle, LDAP_CONST char *url, UNUSED ber_tag_t request, UNUSED ber_int_t msgid,
1066                            void *ctx)
1067 {
1068         ldap_rcode_t status;
1069         ldap_handle_t *conn = talloc_get_type_abort(ctx, ldap_handle_t);
1070
1071         int ldap_errno;
1072
1073         conn->referred = true;
1074         conn->rebound = true;   /* not really, but oh well... */
1075         rad_assert(handle == conn->handle);
1076
1077         DEBUG("rlm_ldap (%s): Rebinding to URL %s", conn->inst->xlat_name, url);
1078
1079         status = rlm_ldap_bind(conn->inst, NULL, &conn, conn->inst->admin_dn, conn->inst->password, false);
1080         if (status != LDAP_PROC_SUCCESS) {
1081                 ldap_get_option(handle, LDAP_OPT_ERROR_NUMBER, &ldap_errno);
1082
1083                 return ldap_errno;
1084         }
1085
1086
1087         return LDAP_SUCCESS;
1088 }
1089 #endif
1090
1091 /** Close and delete a connection
1092  *
1093  * Unbinds the LDAP connection, informing the server and freeing any memory, then releases the memory used by the
1094  * connection handle.
1095  *
1096  * @param conn to destroy.
1097  * @return always indicates success.
1098  */
1099 static int _mod_conn_free(ldap_handle_t *conn)
1100 {
1101         if (conn->handle) {
1102                 DEBUG3("rlm_ldap: Closing libldap handle %p", conn->handle);
1103                 ldap_unbind_s(conn->handle);
1104         }
1105
1106         return 0;
1107 }
1108
1109 /** Create and return a new connection
1110  *
1111  * Create a new ldap connection and allocate memory for a new rlm_handle_t
1112  */
1113 void *mod_conn_create(TALLOC_CTX *ctx, void *instance)
1114 {
1115         ldap_rcode_t status;
1116
1117         int ldap_errno, ldap_version;
1118         struct timeval tv;
1119
1120         ldap_instance_t *inst = instance;
1121         ldap_handle_t *conn;
1122
1123         /*
1124          *      Allocate memory for the handle.
1125          */
1126         conn = talloc_zero(ctx, ldap_handle_t);
1127         if (!conn) return NULL;
1128         talloc_set_destructor(conn, _mod_conn_free);
1129
1130         conn->inst = inst;
1131         conn->rebound = false;
1132         conn->referred = false;
1133
1134 #ifdef HAVE_LDAP_INITIALIZE
1135         if (inst->is_url) {
1136                 DEBUG("rlm_ldap (%s): Connecting to %s", inst->xlat_name, inst->server);
1137
1138                 ldap_errno = ldap_initialize(&conn->handle, inst->server);
1139                 if (ldap_errno != LDAP_SUCCESS) {
1140                         LDAP_ERR("ldap_initialize failed: %s", ldap_err2string(ldap_errno));
1141                         goto error;
1142                 }
1143         } else
1144 #endif
1145         {
1146                 DEBUG("rlm_ldap (%s): Connecting to %s:%d", inst->xlat_name, inst->server, inst->port);
1147
1148                 conn->handle = ldap_init(inst->server, inst->port);
1149                 if (!conn->handle) {
1150                         LDAP_ERR("ldap_init() failed");
1151                         goto error;
1152                 }
1153         }
1154         DEBUG3("rlm_ldap: New libldap handle %p", conn->handle);
1155
1156         /*
1157          *      We now have a connection structure, but no actual TCP connection.
1158          *
1159          *      Set a bunch of LDAP options, using common code.
1160          */
1161 #define do_ldap_option(_option, _name, _value) \
1162         if (ldap_set_option(conn->handle, _option, _value) != LDAP_OPT_SUCCESS) { \
1163                 ldap_get_option(conn->handle, LDAP_OPT_ERROR_NUMBER, &ldap_errno); \
1164                 LDAP_ERR("Could not set %s: %s", _name, ldap_err2string(ldap_errno)); \
1165         }
1166
1167 #define do_ldap_global_option(_option, _name, _value) \
1168         if (ldap_set_option(NULL, _option, _value) != LDAP_OPT_SUCCESS) { \
1169                 ldap_get_option(conn->handle, LDAP_OPT_ERROR_NUMBER, &ldap_errno); \
1170                 LDAP_ERR("Could not set %s: %s", _name, ldap_err2string(ldap_errno)); \
1171         }
1172
1173
1174         if (inst->ldap_debug) {
1175                 do_ldap_global_option(LDAP_OPT_DEBUG_LEVEL, "ldap_debug", &(inst->ldap_debug));
1176         }
1177
1178         /*
1179          *      Leave "dereference" unset to use the OpenLDAP default.
1180          */
1181         if (inst->dereference_str) {
1182                 do_ldap_option(LDAP_OPT_DEREF, "dereference", &(inst->dereference));
1183         }
1184
1185         /*
1186          *      Leave "chase_referrals" unset to use the OpenLDAP default.
1187          */
1188         if (!inst->chase_referrals_unset) {
1189                 if (inst->chase_referrals) {
1190                         do_ldap_option(LDAP_OPT_REFERRALS, "chase_referrals", LDAP_OPT_ON);
1191
1192                         if (inst->rebind == true) {
1193 #if LDAP_SET_REBIND_PROC_ARGS == 3
1194                                 ldap_set_rebind_proc(conn->handle, rlm_ldap_rebind, conn);
1195 #endif
1196                         }
1197                 } else {
1198                         do_ldap_option(LDAP_OPT_REFERRALS, "chase_referrals", LDAP_OPT_OFF);
1199                 }
1200         }
1201
1202 #ifdef LDAP_OPT_NETWORK_TIMEOUT
1203         if (inst->net_timeout) {
1204                 memset(&tv, 0, sizeof(tv));
1205                 tv.tv_sec = inst->net_timeout;
1206
1207                 do_ldap_option(LDAP_OPT_NETWORK_TIMEOUT, "net_timeout", &tv);
1208         }
1209 #endif
1210
1211         do_ldap_option(LDAP_OPT_TIMELIMIT, "srv_timelimit", &(inst->srv_timelimit));
1212
1213         ldap_version = LDAP_VERSION3;
1214         do_ldap_option(LDAP_OPT_PROTOCOL_VERSION, "ldap_version", &ldap_version);
1215
1216 #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
1217         do_ldap_option(LDAP_OPT_X_KEEPALIVE_IDLE, "keepalive idle", &(inst->keepalive_idle));
1218 #endif
1219
1220 #ifdef LDAP_OPT_X_KEEPALIVE_PROBES
1221         do_ldap_option(LDAP_OPT_X_KEEPALIVE_PROBES, "keepalive probes", &(inst->keepalive_probes));
1222 #endif
1223
1224 #ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL
1225         do_ldap_option(LDAP_OPT_X_KEEPALIVE_INTERVAL, "keepalive interval", &(inst->keepalive_interval));
1226 #endif
1227
1228 #ifdef HAVE_LDAP_START_TLS
1229         /*
1230          *      Set all of the TLS options
1231          */
1232         if (inst->tls_mode) {
1233                 do_ldap_option(LDAP_OPT_X_TLS, "tls_mode", &(inst->tls_mode));
1234         }
1235
1236 #  define maybe_ldap_option(_option, _name, _value) \
1237         if (_value) do_ldap_option(_option, _name, _value)
1238
1239         maybe_ldap_option(LDAP_OPT_X_TLS_CACERTFILE, "ca_file", inst->tls_ca_file);
1240         maybe_ldap_option(LDAP_OPT_X_TLS_CACERTDIR, "ca_path", inst->tls_ca_path);
1241
1242
1243         /*
1244          *      Set certificate options
1245          */
1246         maybe_ldap_option(LDAP_OPT_X_TLS_CERTFILE, "certificate_file", inst->tls_certificate_file);
1247         maybe_ldap_option(LDAP_OPT_X_TLS_KEYFILE, "private_key_file", inst->tls_private_key_file);
1248         maybe_ldap_option(LDAP_OPT_X_TLS_RANDOM_FILE, "random_file", inst->tls_random_file);
1249
1250 #  ifdef LDAP_OPT_X_TLS_NEVER
1251         if (inst->tls_require_cert_str) {
1252                 do_ldap_option(LDAP_OPT_X_TLS_REQUIRE_CERT, "require_cert", &inst->tls_require_cert);
1253         }
1254 #  endif
1255
1256         /*
1257          *      Counter intuitively the TLS context appears to need to be initialised
1258          *      after all the TLS options are set on the handle.
1259          */
1260 #  ifdef LDAP_OPT_X_TLS_NEWCTX
1261         {
1262                 /* Always use the new TLS configuration context */
1263                 int is_server = 0;
1264                 do_ldap_option(LDAP_OPT_X_TLS_NEWCTX, "new TLS context", &is_server);
1265
1266         }
1267 #  endif
1268
1269         /*
1270          *      And finally start the TLS code.
1271          */
1272         if (inst->start_tls) {
1273                 if (inst->port == 636) {
1274                         WARN("Told to Start TLS on LDAPS port this will probably fail, please correct the "
1275                                "configuration");
1276                 }
1277
1278                 if (ldap_start_tls_s(conn->handle, NULL, NULL) != LDAP_SUCCESS) {
1279                         ldap_get_option(conn->handle, LDAP_OPT_ERROR_NUMBER, &ldap_errno);
1280
1281                         LDAP_ERR("Could not start TLS: %s", ldap_err2string(ldap_errno));
1282                         goto error;
1283                 }
1284         }
1285 #endif /* HAVE_LDAP_START_TLS */
1286
1287         status = rlm_ldap_bind(inst, NULL, &conn, inst->admin_dn, inst->password, false);
1288         if (status != LDAP_PROC_SUCCESS) {
1289                 goto error;
1290         }
1291
1292         return conn;
1293
1294 error:
1295         talloc_free(conn);
1296
1297         return NULL;
1298 }
1299
1300 /** Gets an LDAP socket from the connection pool
1301  *
1302  * Retrieve a socket from the connection pool, or NULL on error (of if no sockets are available).
1303  *
1304  * @param inst rlm_ldap configuration.
1305  * @param request Current request (may be NULL).
1306  */
1307 ldap_handle_t *rlm_ldap_get_socket(ldap_instance_t const *inst, UNUSED REQUEST *request)
1308 {
1309         return fr_connection_get(inst->pool);
1310 }
1311
1312 /** Frees an LDAP socket back to the connection pool
1313  *
1314  * If the socket was rebound chasing a referral onto another server then we destroy it.
1315  * If the socket was rebound to another user on the same server, we let the next caller rebind it.
1316  *
1317  * @param inst rlm_ldap configuration.
1318  * @param conn to release.
1319  */
1320 void rlm_ldap_release_socket(ldap_instance_t const *inst, ldap_handle_t *conn)
1321 {
1322         /*
1323          *      Could have already been free'd due to a previous error.
1324          */
1325         if (!conn) return;
1326
1327         /*
1328          *      We chased a referral to another server.
1329          *
1330          *      This connection is no longer part of the pool which is connected to and bound to the configured server.
1331          *      Close it.
1332          *
1333          *      Note that we do NOT close it if it was bound to another user.  Instead, we let the next caller do the
1334          *      rebind.
1335          */
1336         if (conn->referred) {
1337                 fr_connection_del(inst->pool, conn);
1338                 return;
1339         }
1340
1341         fr_connection_release(inst->pool, conn);
1342         return;
1343 }