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