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