Massive rewrite of the LDAP module.
[freeradius.git] / src / modules / rlm_ldap / rlm_ldap.c
1 /*
2  * rlm_ldap.c   LDAP authorization and authentication module.
3  *
4  *   This program is free software; you can redistribute it and/or modify
5  *   it under the terms of the GNU General Public License as published by
6  *   the Free Software Foundation; either version 2 of the License, or
7  *   (at your option) any later version.
8  *
9  *   This program is distributed in the hope that it will be useful,
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *   GNU General Public License for more details.
13  *
14  *   You should have received a copy of the GNU General Public License
15  *   along with this program; if not, write to the Free Software
16  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  *
18  *   Copyright 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,
19  *             2009,2010,2011,1012 The FreeRADIUS Server Project.
20  *
21  *   Copyright 2012 Alan DeKok <aland@freeradius.org>
22  */
23
24 #include <freeradius-devel/ident.h>
25 RCSID("$Id$")
26
27 #include        <freeradius-devel/radiusd.h>
28 #include        <freeradius-devel/modules.h>
29 #include        <freeradius-devel/rad_assert.h>
30
31 #include        <stdarg.h>
32 #include        <ctype.h>
33
34 #include        "mapping.h"
35
36 #define MAX_FILTER_STR_LEN      1024
37
38 typedef struct {
39         CONF_SECTION   *cs;
40         fr_connection_pool_t *pool;
41         char           *server;
42         int             port;
43
44         char           *login;
45         char           *password;
46
47         char           *filter;
48         char           *basedn;
49
50         int             chase_referrals;
51         int             rebind;
52
53         int             ldap_debug; /* Debug flag for LDAP SDK */
54         const char      *xlat_name; /* name used to xlat */
55
56         const char      *map_file;
57         TLDAP_RADIUS    *check_map;
58         TLDAP_RADIUS    *reply_map;
59         char            **attrs;
60
61         int             do_xlat;
62
63         /*
64          *      Access related configuration
65          */
66         char           *access_attr;
67         int             positive_access_attr;
68
69         /*
70          *      Profiles
71          */
72         char           *base_filter;
73         char           *default_profile;
74         char           *profile_attr;
75
76         /*
77          *      Group checking.
78          */
79         char           *groupname_attr;
80         char           *groupmemb_filt;
81         char           *groupmemb_attr;
82
83         /*
84          *      TLS items.  We should really normalize these with the
85          *      TLS code in 3.0.
86          */
87         int             tls_mode;
88         int             start_tls;
89         char            *tls_cacertfile;
90         char            *tls_cacertdir;
91         char            *tls_certfile;
92         char            *tls_keyfile;
93         char            *tls_randfile;
94         char            *tls_require_cert;
95
96         /*
97          *      Options
98          */
99         int             timelimit;
100         int             net_timeout;
101         int             timeout;
102         int             is_url;
103
104         /*
105          *      For keep-alives.
106          */
107 #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
108         int             keepalive_idle;
109 #endif
110 #ifdef LDAP_OPT_X_KEEPALIVE_PROBES
111         int             keepalive_probes;
112 #endif
113 #ifdef LDAP_OPT_ERROR_NUMBER
114         int             keepalive_interval;
115 #endif
116
117 }  ldap_instance;
118
119 /* The default setting for TLS Certificate Verification */
120 #define TLS_DEFAULT_VERIFY "allow"
121
122 /*
123  *      TLS Configuration
124  */
125 static CONF_PARSER tls_config[] = {
126         {"start_tls", PW_TYPE_BOOLEAN,
127          offsetof(ldap_instance,start_tls), NULL, "no"},
128         {"cacertfile", PW_TYPE_FILENAME,
129          offsetof(ldap_instance,tls_cacertfile), NULL, NULL},
130         {"cacertdir", PW_TYPE_FILENAME,
131          offsetof(ldap_instance,tls_cacertdir), NULL, NULL},
132         {"certfile", PW_TYPE_FILENAME,
133          offsetof(ldap_instance,tls_certfile), NULL, NULL},
134         {"keyfile", PW_TYPE_FILENAME,
135          offsetof(ldap_instance,tls_keyfile), NULL, NULL},
136         {"randfile", PW_TYPE_STRING_PTR, /* OK if it changes on HUP */
137          offsetof(ldap_instance,tls_randfile), NULL, NULL},
138         {"require_cert", PW_TYPE_STRING_PTR,
139          offsetof(ldap_instance,tls_require_cert), NULL, TLS_DEFAULT_VERIFY},
140         { NULL, -1, 0, NULL, NULL }
141 };
142
143
144 static CONF_PARSER attr_config[] = {
145         /*
146          *      Access limitations
147          */
148         /* LDAP attribute name that controls remote access */
149         {"access_attr", PW_TYPE_STRING_PTR,
150          offsetof(ldap_instance,access_attr), NULL, NULL},
151         {"positive_access_attr", PW_TYPE_BOOLEAN,
152          offsetof(ldap_instance,positive_access_attr), NULL, "yes"},
153
154         {"base_filter", PW_TYPE_STRING_PTR,
155          offsetof(ldap_instance,base_filter), NULL, "(objectclass=radiusprofile)"},
156         {"default_profile", PW_TYPE_STRING_PTR,
157          offsetof(ldap_instance,default_profile), NULL, NULL},
158         {"profile_attribute", PW_TYPE_STRING_PTR,
159          offsetof(ldap_instance,profile_attr), NULL, NULL},
160
161         { NULL, -1, 0, NULL, NULL }
162 };
163
164
165 /*
166  *      Group configuration
167  */
168 static CONF_PARSER group_config[] = {
169         /*
170          *      Group checks.  These could probably be done
171          *      via dynamic xlat's.
172          */
173         {"name_attribute", PW_TYPE_STRING_PTR,
174          offsetof(ldap_instance,groupname_attr), NULL, "cn"},
175         {"membership_filter", PW_TYPE_STRING_PTR,
176          offsetof(ldap_instance,groupmemb_filt), NULL, "(|(&(objectClass=GroupOfNames)(member=%{Ldap-UserDn}))(&(objectClass=GroupOfUniqueNames)(uniquemember=%{Ldap-UserDn})))"},
177         {"membership_attribute", PW_TYPE_STRING_PTR,
178          offsetof(ldap_instance,groupmemb_attr), NULL, NULL},
179
180
181         { NULL, -1, 0, NULL, NULL }
182 };
183
184 /*
185  *      Various options that don't belong in the main configuration.
186  *
187  *      Note that these overlap a bit with the connection pool code!
188  */
189 static CONF_PARSER option_config[] = {
190         /*
191          *      Debugging flags to the server
192          */
193         {"ldap_debug", PW_TYPE_INTEGER,
194          offsetof(ldap_instance,ldap_debug), NULL, "0x0000"},
195
196         {"chase_referrals", PW_TYPE_BOOLEAN,
197          offsetof(ldap_instance,chase_referrals), NULL, NULL},
198
199         {"rebind", PW_TYPE_BOOLEAN,
200          offsetof(ldap_instance,rebind), NULL, NULL},
201
202         /* timeout on network activity */
203         {"net_timeout", PW_TYPE_INTEGER,
204          offsetof(ldap_instance,net_timeout), NULL, "10"},
205
206         /* timeout for search results */
207         {"timeout", PW_TYPE_INTEGER,
208          offsetof(ldap_instance,timeout), NULL, "20"},
209
210         /* allow server unlimited time for search (server-side limit) */
211         {"timelimit", PW_TYPE_INTEGER,
212          offsetof(ldap_instance,timelimit), NULL, "20"},
213
214 #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
215         {"idle", PW_TYPE_INTEGER, offsetof(ldap_instance,keepalive_idle), NULL, "60"},
216 #endif
217 #ifdef LDAP_OPT_X_KEEPALIVE_PROBES
218         {"probes", PW_TYPE_INTEGER, offsetof(ldap_instance,keepalive_probes), NULL, "3"},
219 #endif
220 #ifdef LDAP_OPT_ERROR_NUMBER
221         {"interval", PW_TYPE_INTEGER, offsetof(ldap_instance,keepalive_interval), NULL, "30"},
222 #endif
223         { NULL, -1, 0, NULL, NULL }
224 };
225
226
227 static const CONF_PARSER module_config[] = {
228         {"server", PW_TYPE_STRING_PTR,
229          offsetof(ldap_instance,server), NULL, "localhost"},
230         {"port", PW_TYPE_INTEGER,
231          offsetof(ldap_instance,port), NULL, "389"},
232
233         {"password", PW_TYPE_STRING_PTR,
234          offsetof(ldap_instance,password), NULL, ""},
235         {"identity", PW_TYPE_STRING_PTR,
236          offsetof(ldap_instance,login), NULL, ""},
237
238         /*
239          *      DN's and filters.
240          */
241         {"basedn", PW_TYPE_STRING_PTR,
242          offsetof(ldap_instance,basedn), NULL, "o=notexist"},
243
244         {"filter", PW_TYPE_STRING_PTR,
245          offsetof(ldap_instance,filter), NULL, "(uid=%u)"},
246
247         /* file with mapping between LDAP and RADIUS attributes */
248         {"dictionary_mapping", PW_TYPE_FILENAME,
249          offsetof(ldap_instance, map_file), NULL, NULL},
250
251         /*
252          *      Terrible things which should be deleted.
253          */
254         {"do_xlat", PW_TYPE_BOOLEAN,
255          offsetof(ldap_instance,do_xlat), NULL, "yes"},
256
257         { "profiles", PW_TYPE_SUBSECTION, 0, NULL, (const void *) attr_config },
258
259         { "group", PW_TYPE_SUBSECTION, 0, NULL, (const void *) group_config },
260
261         { "options", PW_TYPE_SUBSECTION, 0, NULL, (const void *) option_config },
262
263         { "tls", PW_TYPE_SUBSECTION, 0, NULL, (const void *) tls_config },
264
265         { "profiles", PW_TYPE_SUBSECTION, 0, NULL, (const void *) attr_config },
266
267         {NULL, -1, 0, NULL, NULL}
268 };
269
270 typedef struct ldap_conn {
271         LDAP    *ld;
272         int     rebound;
273         int     referred;
274         ldap_instance *inst;
275 } LDAP_CONN;
276
277
278 #if LDAP_SET_REBIND_PROC_ARGS == 3
279 /*
280  *      Rebind && chase referral stuff
281  */
282 static int ldap_rebind(LDAP *ld, LDAP_CONST char *url,
283                        UNUSED ber_tag_t request, UNUSED ber_int_t msgid,
284                        void *ctx )
285 {
286         LDAP_CONN *conn = ctx;
287
288         conn->referred = TRUE;
289         conn->rebound = TRUE;   /* not really, but oh well... */
290         rad_assert(ld == conn->ld);
291
292         DEBUG("  [%s] rebind to URL %s", conn->inst->xlat_name, url);
293         return ldap_bind_s(ld, conn->inst->login, conn->inst->password,
294                            LDAP_AUTH_SIMPLE);
295 }
296 #endif
297
298 static int ldap_bind_wrapper(LDAP_CONN **pconn, const char *user,
299                              const char *password,
300                              const char **perror_str, int do_rebind)
301 {
302         int             rcode, ldap_errno;
303         int             module_rcode = RLM_MODULE_FAIL;
304         int             reconnect = FALSE;
305         const char      *error_string;
306         LDAP_CONN       *conn = *pconn;
307         ldap_instance   *inst = conn->inst;
308         LDAPMessage     *result = NULL;
309         struct timeval tv;
310
311 redo:
312         ldap_errno = ldap_bind(conn->ld, user, password, LDAP_AUTH_SIMPLE);
313         if (ldap_errno < 0) {
314         get_error:
315                 ldap_get_option(conn->ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno);
316                 error_string = ldap_err2string(ldap_errno);
317
318                 if (do_rebind && !reconnect) {
319                         conn = fr_connection_reconnect(inst->pool, conn);
320                         *pconn = conn;
321                         if (!conn) return RLM_MODULE_FAIL;
322                         goto redo;
323                 }
324
325         print_error:
326                 if (perror_str) *perror_str = error_string;
327
328 #ifdef HAVE_LDAP_INITIALIZE
329                 if (inst->is_url) {
330                         radlog(L_ERR, "  [%s] %s bind to %s failed: %s",
331                                inst->xlat_name, user,
332                                inst->server, error_string);
333                 } else
334 #endif
335                 {
336                         radlog(L_ERR, "  [%s] %s bind to %s:%d failed: %s",
337                                inst->xlat_name, user,
338                                inst->server, inst->port,
339                                error_string);
340                 }
341
342                 return module_rcode; /* caller closes the connection */
343         }
344
345         DEBUG3("  [%s] waiting for bind result ...", inst->xlat_name);
346
347         tv.tv_sec = inst->timeout;
348         tv.tv_usec = 0;
349         rcode = ldap_result(conn->ld, ldap_errno, 1, &tv, &result);
350         if (rcode < 0) goto get_error;
351
352         if (rcode == 0) {
353                 error_string = "timeout";
354                 goto print_error;
355         }
356
357         ldap_errno = ldap_result2error(conn->ld, result, 1);
358         switch (ldap_errno) {
359         case LDAP_SUCCESS:
360                 break;
361
362         case LDAP_INVALID_CREDENTIALS:
363         case LDAP_CONSTRAINT_VIOLATION:
364                 rcode = RLM_MODULE_REJECT;
365                 /* FALL-THROUGH */
366
367         default:
368                 goto get_error;
369         }
370
371         return RLM_MODULE_OK;
372 }
373
374 /*************************************************************************
375  *
376  *      Function: ldap_conn_create
377  *
378  *      Purpose: Create and return a new connection
379  *      This function is probably too big.
380  *
381  *************************************************************************/
382 static void *ldap_conn_create(void *ctx)
383 {
384         int module_rcode;
385         int ldap_errno, ldap_version;
386         struct timeval tv;
387         ldap_instance *inst = ctx;
388         LDAP *ld = NULL;
389         LDAP_CONN *conn = NULL;
390         const char *error;
391
392 #ifdef HAVE_LDAP_INITIALIZE
393         if (inst->is_url) {
394                 DEBUG("  [%s] Connect to %s", inst->xlat_name, inst->server);
395
396                 ldap_errno = ldap_initialize(&ld, inst->server);
397
398                 if (ldap_errno != LDAP_SUCCESS) {
399                         radlog(L_ERR, "  [%s] ldap_initialize() failed: %s",
400                                inst->xlat_name, ldap_err2string(ldap_errno));
401                         goto conn_fail;
402                 }
403         } else
404 #endif
405         {
406                 DEBUG("  [%s] Connect to %s:%d", inst->xlat_name,
407                       inst->server, inst->port);
408
409                 ld = ldap_init(inst->server, inst->port);
410                 if (!ld) {
411                         radlog(L_ERR, "  [%s] ldap_init() failed", inst->xlat_name);
412                 conn_fail:
413                         if (ld) ldap_unbind_s(ld);
414                         return NULL;
415                 }
416         }
417
418         /*
419          *      We now have a connection structure, but no actual TCP connection.
420          *
421          *      Set a bunch of LDAP options, using common code.
422          */
423
424 #define do_ldap_option(_option, _name, _value) if (ldap_set_option(ld, _option, _value) != LDAP_OPT_SUCCESS) { \
425                 ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); \
426                 radlog(L_ERR, "  [%s] Could not set %s: %s", inst->xlat_name, _name, ldap_err2string(ldap_errno)); \
427         }
428                 
429         if (inst->ldap_debug) {
430                 do_ldap_option(LDAP_OPT_DEBUG_LEVEL, "ldap_debug", &(inst->ldap_debug));
431         }
432
433         /*
434          *      Leave "chase_referrals" unset to use the OpenLDAP
435          *      default.
436          */
437         if (inst->chase_referrals != 2) {
438                 if (inst->chase_referrals) {
439                         do_ldap_option(LDAP_OPT_REFERRALS, "chase_referrals", LDAP_OPT_ON);
440                         
441 #if LDAP_SET_REBIND_PROC_ARGS == 3
442                         if (inst->rebind == 1) {
443                                 ldap_set_rebind_proc(ld, ldap_rebind, inst);
444                         }
445 #endif
446                 } else {
447                         do_ldap_option(LDAP_OPT_REFERRALS, "chase_referrals", LDAP_OPT_OFF);
448                 }
449         }
450
451         tv.tv_sec = inst->net_timeout;
452         tv.tv_usec = 0;
453         do_ldap_option(LDAP_OPT_NETWORK_TIMEOUT, "net_timeout", &tv);
454
455         do_ldap_option(LDAP_OPT_TIMELIMIT, "timelimit", &(inst->timelimit));
456
457         ldap_version = LDAP_VERSION3;
458         do_ldap_option(LDAP_OPT_PROTOCOL_VERSION, "ldap_version", &ldap_version);
459
460 #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
461         do_ldap_option(LDAP_OPT_X_KEEPALIVE_IDLE, "keepalive idle", &(inst->keepalive_idle));
462 #endif
463
464 #ifdef LDAP_OPT_X_KEEPALIVE_PROBES
465         do_ldap_option(LDAP_OPT_X_KEEPALIVE_PROBES, "keepalive probes", &(inst->keepalive_probes));
466 #endif
467
468 #ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL
469         do_ldap_option(LDAP_OPT_X_KEEPALIVE_INTERVAL, "keepalive interval", &(inst->keepalive_interval));
470 #endif
471
472 #ifdef HAVE_LDAP_START_TLS
473         /*
474          *      Set all of the TLS options
475          */
476         if (inst->tls_mode) {
477                 do_ldap_option(LDAP_OPT_X_TLS, "tls_mode", &(inst->tls_mode));
478         }
479
480 #define maybe_ldap_option(_option, _name, _value) if (_value) do_ldap_option(_option, _name, _value)
481
482         maybe_ldap_option(LDAP_OPT_X_TLS_CACERTFILE,
483                           "cacertfile", inst->tls_cacertfile);
484         maybe_ldap_option(LDAP_OPT_X_TLS_CACERTDIR,
485                           "cacertdir", inst->tls_cacertdir);
486
487 #ifdef HAVE_LDAP_INT_TLS_CONFIG
488         if (ldap_int_tls_config(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT,
489                                 (inst->tls_require_cert)) != LDAP_OPT_SUCCESS) {
490                 ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno);
491                 radlog(L_ERR, "  [%s] could not set ", 
492                        "LDAP_OPT_X_TLS_REQUIRE_CERT option to %s: %s",
493                        inst->xlat_name, 
494                        inst->tls_require_cert,
495                        ldap_err2string(ldap_errno));
496         }
497 #endif
498
499         maybe_ldap_option(LDAP_OPT_X_TLS_CERTFILE,
500                           "certfile", inst->tls_certfile);
501         maybe_ldap_option(LDAP_OPT_X_TLS_KEYFILE,
502                           "keyfile", inst->tls_keyfile);
503         maybe_ldap_option(LDAP_OPT_X_TLS_RANDOM_FILE,
504                           "randfile", inst->tls_randfile);
505
506         /*
507          *      And finally start the TLS code.
508          */
509         if (inst->start_tls && (inst->port != 636)) {
510                 ldap_errno = ldap_start_tls_s(ld, NULL, NULL);
511                 if (ldap_errno != LDAP_SUCCESS) {
512                         ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER,
513                                         &ldap_errno);
514                         radlog(L_ERR, "  [%s] could not start TLS: %s",
515                                inst->xlat_name,
516                                ldap_err2string(ldap_errno));
517                         goto conn_fail;
518                 }
519         }
520 #endif /* HAVE_LDAP_START_TLS */
521
522         conn = rad_malloc(sizeof(*conn));
523         conn->inst = inst;
524         conn->ld = ld;
525         conn->rebound = FALSE;
526         conn->referred = FALSE;
527
528         module_rcode = ldap_bind_wrapper(&conn, inst->login, inst->password,
529                                          &error, FALSE);
530         if (module_rcode != RLM_MODULE_OK) {
531                 radlog(L_ERR, "  [%s] Failed binding to LDAP server: %s",
532                        inst->xlat_name, error);
533
534                 /*
535                  *      FIXME: print "check config, morians!
536                  */
537                 goto conn_fail;
538         }
539
540         return conn;
541 }
542
543
544 /*************************************************************************
545  *
546  *      Function: ldap_conn_delete
547  *
548  *      Purpose: Close and delete a connection
549  *
550  *************************************************************************/
551 static int ldap_conn_delete(UNUSED void *ctx, void *connection)
552 {
553         LDAP_CONN *conn = connection;
554
555         ldap_unbind_s(conn->ld);
556         free(conn);
557
558         return 0;
559 }
560
561
562 /*************************************************************************
563  *
564  *      Function: ldap_get_socket
565  *
566  *      Purpose: Gets an LDAP socket from the connection pool
567  *
568  *************************************************************************/
569 static LDAP_CONN *ldap_get_socket(ldap_instance *inst)
570 {
571         LDAP_CONN *conn;
572
573         conn = fr_connection_get(inst->pool);
574         if (!conn) {
575                 radlog(L_ERR, "  [%s] All ldap connections are in use",
576                        inst->xlat_name);
577                 return NULL;
578         }
579
580         return conn;
581 }
582
583 /*************************************************************************
584  *
585  *      Function: ldap_release_socket
586  *
587  *      Purpose: Frees an LDAP socket back to the connection pool
588  *
589  *************************************************************************/
590 static void ldap_release_socket(ldap_instance *inst, LDAP_CONN *conn)
591 {
592         /*
593          *      Could have already been free'd due to a previous error.
594          */
595         if (!conn) return;
596
597         /*
598          *      We chased a referral to another server.
599          *
600          *      This connection is no longer part of the pool which is
601          *      connected to and bound to the configured server.
602          *      Close it.
603          *
604          *      Note that we do NOT close it if it was bound to
605          *      another user.  Instead, we let the next caller do the
606          *      rebind.
607          */
608         if (conn->referred) {
609                 fr_connection_del(inst->pool, conn);
610                 return;
611         }
612
613         fr_connection_release(inst->pool, conn);
614         return;
615 }
616
617
618 /*************************************************************************
619  *
620  *      Function: ldap_escape_func
621  *
622  *      Purpose: Converts "bad" strings into ones which are safe for LDAP
623  *
624  *************************************************************************/
625 static size_t ldap_escape_func(char *out, size_t outlen, const char *in)
626 {
627         size_t len = 0;
628
629         while (in[0]) {
630                 /*
631                  *      Encode unsafe characters.
632                  */
633                 if (((len == 0) &&
634                     ((in[0] == ' ') || (in[0] == '#'))) ||
635                     (strchr(",+\"\\<>;*=()", *in))) {
636                         static const char hex[] = "0123456789abcdef";
637
638                         /*
639                          *      Only 3 or less bytes available.
640                          */
641                         if (outlen <= 3) {
642                                 break;
643                         }
644
645                         *(out++) = '\\';
646                         *(out++) = hex[((*in) >> 4) & 0x0f];
647                         *(out++) = hex[(*in) & 0x0f];
648                         outlen -= 3;
649                         len += 3;
650                         in++;
651                         continue;
652                 }
653
654                 /*
655                  *      Only one byte left.
656                  */
657                 if (outlen <= 1) {
658                         break;
659                 }
660
661                 /*
662                  *      Allowed character.
663                  */
664                 *(out++) = *(in++);
665                 outlen--;
666                 len++;
667         }
668         *out = '\0';
669         return len;
670 }
671
672 /*************************************************************************
673  *
674  *      Function: perform_search
675  *
676  *      Purpose: Do a search and get a response
677  *
678  *************************************************************************/
679 static int perform_search(ldap_instance *inst, LDAP_CONN **pconn,
680                           char *search_basedn, int scope, char *filter,
681                           char **attrs, LDAPMessage **presult)
682 {
683         int             ldap_errno;
684         int             reconnect = FALSE;
685         LDAP_CONN       *conn = *pconn;
686         struct timeval  tv;
687
688         *presult = NULL;
689
690         /*
691          *      Do all searches as the default admin user.
692          */
693         if (conn->rebound) {
694                 ldap_errno = ldap_bind_wrapper(pconn,
695                                                inst->login, inst->password,
696                                                NULL, TRUE);
697                 if (ldap_errno != RLM_MODULE_OK) {
698                         return -1;
699                 }
700
701                 rad_assert(*pconn != NULL);
702                 conn = *pconn;
703                 conn->rebound = FALSE;
704         }
705
706         tv.tv_sec = inst->timeout;
707         tv.tv_usec = 0;
708         DEBUG2("  [%s] Performing search in '%s' with filter '%s'", inst->xlat_name, 
709                search_basedn ? search_basedn : "(null)" , filter);
710
711 retry:
712         ldap_errno = ldap_search_st(conn->ld, search_basedn, scope, filter,
713                                     attrs, 0, &tv, presult);
714         switch (ldap_errno) {
715         case LDAP_SUCCESS:
716         case LDAP_NO_SUCH_OBJECT:
717                 break;
718
719         case LDAP_SERVER_DOWN:
720         do_reconnect:
721                 ldap_msgfree(*presult);
722
723                 if (reconnect) return -1;
724                 reconnect = TRUE;
725
726                 conn = fr_connection_reconnect(inst->pool, conn);
727                 *pconn = conn;  /* tell the caller we have a new connection */
728                 if (!conn) return -1;
729                 goto retry;
730
731         case LDAP_INSUFFICIENT_ACCESS:
732                 radlog(L_ERR, "  [%s] ldap_search() failed: Insufficient access. Check the identity and password configuration directives.", inst->xlat_name);
733                 ldap_msgfree(*presult);
734                 return -1;
735
736         case LDAP_TIMEOUT:
737                 exec_trigger(NULL, inst->cs, "modules.ldap.timeout", TRUE);
738                 radlog(L_ERR, "  [%s] ldap_search() failed: Timed out while waiting for server to respond. Please increase the timeout.", inst->xlat_name);
739                 ldap_msgfree(*presult);
740                 return -1;
741
742         case LDAP_FILTER_ERROR:
743                 radlog(L_ERR, "  [%s] ldap_search() failed: Bad search filter: %s", inst->xlat_name,filter);
744                 ldap_msgfree(*presult);
745                 return -1;
746
747         case LDAP_TIMELIMIT_EXCEEDED:
748                 exec_trigger(NULL, inst->cs, "modules.ldap.timeout", TRUE);
749
750         case LDAP_BUSY:
751         case LDAP_UNAVAILABLE:
752                 /*
753                  *      Reconnect.  There's an issue with the socket
754                  *      or LDAP server.
755                  */
756                 ldap_get_option(conn->ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno);
757                 radlog(L_ERR, "  [%s] ldap_search() failed: %s", inst->xlat_name,
758                        ldap_err2string(ldap_errno));
759                 goto do_reconnect;
760
761         default:
762                 ldap_get_option(conn->ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno);
763                 radlog(L_ERR, "  [%s] ldap_search() failed: %s", inst->xlat_name,
764                        ldap_err2string(ldap_errno));
765                 ldap_msgfree(*presult);
766                 return -1;
767         }
768
769         ldap_errno = ldap_count_entries(conn->ld, *presult);
770         if (ldap_errno == 0) {
771                 ldap_msgfree(*presult);
772                 DEBUG("  [%s] object not found", inst->xlat_name);
773                 return -2;
774         }
775
776         if (ldap_errno != 1) {
777                 ldap_msgfree(*presult);
778                 DEBUG("  [%s] got ambiguous search result (%d results)", inst->xlat_name, ldap_errno);
779                 return -2;
780         }
781
782         return 0;
783 }
784
785 /*************************************************************************
786  *
787  *      Function: ldap_xlat
788  *
789  *      Purpose: Expand an LDAP URL into a query, and return a string
790  *              result from that query.
791  *
792  *************************************************************************/
793 static size_t ldap_xlat(void *instance, REQUEST *request, const char *fmt,
794                         char *out, size_t freespace, RADIUS_ESCAPE_STRING func)
795 {
796         int rcode;
797         size_t length = 0;
798         ldap_instance *inst = instance;
799         LDAPURLDesc *ldap_url;
800         LDAPMessage *result = NULL;
801         LDAPMessage *msg = NULL;
802         char **vals;
803         LDAP_CONN *conn;
804         const char *url;
805         char buffer[MAX_FILTER_STR_LEN];
806
807         if (strchr(fmt, '%') != NULL) {
808                 if (!radius_xlat(buffer, sizeof(buffer), fmt, request, func)) {
809                         radlog (L_ERR, "  [%s] Unable to create LDAP URL.", inst->xlat_name);
810                         return 0;
811                 }
812                 url = buffer;
813         } else {
814                 url = fmt;
815         }
816
817         if (!ldap_is_ldap_url(url)) {
818                 radlog (L_ERR, "  [%s] String passed does not look like an LDAP URL.",
819                         inst->xlat_name);
820                 return 0;
821         }
822
823         if (ldap_url_parse(url, &ldap_url)){
824                 radlog (L_ERR, "  [%s] LDAP URL parse failed.", inst->xlat_name);
825                 return 0;
826         }
827
828         /*
829          *      Nothing, empty string, "*" string, or got 2 things, die.
830          */
831         if (!ldap_url->lud_attrs || !ldap_url->lud_attrs[0] ||
832             !*ldap_url->lud_attrs[0] || (strcmp(ldap_url->lud_attrs[0], "*") == 0) ||
833             ldap_url->lud_attrs[1]) {
834                 radlog (L_ERR, "  [%s] Invalid Attribute(s) request.",
835                         inst->xlat_name);
836                 goto free_urldesc;
837         }
838
839         if (ldap_url->lud_host &&
840             ((strncmp(inst->server, ldap_url->lud_host, strlen(inst->server)) != 0) ||
841              (ldap_url->lud_port != inst->port))) {
842                 DEBUG("  [%s] Requested server/port is .", inst->xlat_name);
843                 goto free_urldesc;
844         }
845
846         conn = ldap_get_socket(inst);
847         if (!conn) goto free_urldesc;
848
849         rcode = perform_search(inst, &conn, ldap_url->lud_dn, ldap_url->lud_scope,
850                                ldap_url->lud_filter, ldap_url->lud_attrs, &result);
851         if (rcode < 0) {
852                 if (rcode == -2) {
853                         DEBUG("  [%s] Search returned not found", inst->xlat_name);
854                         goto free_socket;
855                 }
856                 DEBUG("  [%s] Search returned error", inst->xlat_name);
857                 goto free_socket;
858         }
859
860         msg = ldap_first_entry(conn->ld, result);
861         if (!msg) {
862                 DEBUG("  [%s] ldap_first_entry() failed", inst->xlat_name);
863                 goto free_result;
864         }
865
866         vals = ldap_get_values(conn->ld, msg, ldap_url->lud_attrs[0]);
867         if (!vals) {
868                 DEBUG("  [%s] ldap_get_values failed", inst->xlat_name);
869                 goto free_result;
870         }
871
872         length = strlen(vals[0]);
873         if (length >= freespace){
874
875                 goto free_vals;
876         }
877
878         strlcpy(out, vals[0], freespace);
879
880 free_vals:
881         ldap_value_free(vals);
882 free_result:
883         ldap_msgfree(result);
884 free_socket:
885         ldap_release_socket(inst, conn);
886 free_urldesc:
887         ldap_free_urldesc(ldap_url);
888
889         return length;
890 }
891
892
893 static char *get_userdn(LDAP_CONN **pconn, REQUEST *request, int *module_rcode)
894 {
895         int             rcode;
896         VALUE_PAIR      *vp;
897         ldap_instance   *inst = (*pconn)->inst;
898         LDAPMessage    *result, *msg;
899         static char     firstattr[] = "uid";
900         char           *user_dn, *attrs[] = {firstattr, NULL};
901         char            filter[MAX_FILTER_STR_LEN];     
902         char            basedn[MAX_FILTER_STR_LEN];     
903
904         *module_rcode = RLM_MODULE_FAIL;
905
906         vp = pairfind(request->config_items, PW_LDAP_USERDN, 0);
907         if (vp) return vp->vp_strvalue;
908
909         if (!radius_xlat(filter, sizeof(filter), inst->filter,
910                          request, ldap_escape_func)) {
911                 radlog(L_ERR, "  [%s] unable to create filter.", inst->xlat_name);
912                 *module_rcode = RLM_MODULE_INVALID;
913                 return NULL;
914         }
915
916         if (!radius_xlat(basedn, sizeof(basedn), inst->basedn,
917                          request, ldap_escape_func)) {
918                 radlog(L_ERR, "  [%s] unable to create basedn.", inst->xlat_name);
919                 *module_rcode = RLM_MODULE_INVALID;
920                 return NULL;
921         }
922
923         rcode = perform_search(inst, pconn, basedn, LDAP_SCOPE_SUBTREE,
924                                filter, attrs, &result);
925         if (rcode < 0) {
926                 if (rcode == -2) {
927                         *module_rcode = RLM_MODULE_NOTFOUND;
928                 }
929
930                 return NULL;
931         }
932
933         if ((msg = ldap_first_entry((*pconn)->ld, result)) == NULL) {
934                 ldap_msgfree(result);
935                 return NULL;
936         }
937
938         if ((user_dn = ldap_get_dn((*pconn)->ld, msg)) == NULL) {
939                 ldap_msgfree(result);
940                 return NULL;
941         }
942
943         vp = pairmake("LDAP-UserDn", user_dn, T_OP_EQ);
944         if (!vp) {
945                 ldap_memfree(user_dn);
946                 ldap_msgfree(result);
947                 return NULL;
948         }
949         
950         pairadd(&request->config_items, vp);
951         ldap_memfree(user_dn);
952         ldap_msgfree(result);
953
954         return vp->vp_strvalue;
955 }
956
957
958 /*****************************************************************************
959  *
960  *      Perform LDAP-Group comparison checking
961  *
962  *****************************************************************************/
963 static int ldap_groupcmp(void *instance, REQUEST *request,
964                          UNUSED VALUE_PAIR *thing, VALUE_PAIR *check,
965                          UNUSED VALUE_PAIR *check_pairs,
966                          UNUSED VALUE_PAIR **reply_pairs)
967 {
968         ldap_instance   *inst = instance;
969         int             i, rcode, found;
970         LDAPMessage     *result = NULL;
971         LDAPMessage     *msg = NULL;
972         static char     firstattr[] = "dn";
973         char            *attrs[] = {firstattr,NULL};
974         char            **vals;
975         char            *group_attrs[] = {inst->groupmemb_attr,NULL};
976         LDAP_CONN       *conn;
977         char            *user_dn;
978         int             module_rcode;
979         char            gr_filter[MAX_FILTER_STR_LEN];
980         char            filter[MAX_FILTER_STR_LEN];
981         char            basedn[MAX_FILTER_STR_LEN];
982         
983         if (check->length == 0) {
984                 RDEBUG("Cannot do comparison: group name is empty");
985                 return 1;
986         }
987
988         conn = ldap_get_socket(inst);
989         if (!conn) return 1;
990
991         /*
992          *      This is used in the default membership filter.
993          */
994         user_dn = get_userdn(&conn, request, &module_rcode);
995         if (!user_dn) {
996                 ldap_release_socket(inst, conn);
997                 return 1;
998         }
999
1000         if (!inst->groupmemb_filt) goto check_attr;
1001
1002         if (!radius_xlat(filter, sizeof(filter),
1003                          inst->groupmemb_filt, request, ldap_escape_func)) {
1004                 RDEBUG("Failed creating group filter");
1005                 return 1;
1006         }
1007
1008         /*
1009          *      If it's a DN, use that.
1010          */
1011         if (strchr(check->vp_strvalue,',') != NULL) {
1012                 strlcpy(filter, gr_filter, sizeof(filter));
1013                 strlcpy(basedn, check->vp_strvalue, sizeof(basedn));
1014                 
1015         } else {
1016                 snprintf(filter, sizeof(filter), "(&(%s=%s)%s)",
1017                          inst->groupname_attr,
1018                          check->vp_strvalue, gr_filter);
1019
1020                 /*
1021                  *      get_userdn does this, too.  Oh well.
1022                  */
1023                 if (!radius_xlat(basedn, sizeof(basedn), inst->basedn,
1024                                  request, ldap_escape_func)) {
1025                         radlog(L_ERR, "  [%s] unable to create basedn.\n",
1026                                inst->xlat_name);
1027                         return 1;
1028                 }
1029         }
1030
1031         rcode = perform_search(inst, &conn, basedn, LDAP_SCOPE_SUBTREE,
1032                                filter, attrs, &result);
1033         if (rcode == 0) {
1034                 ldap_release_socket(inst, conn);
1035                 ldap_msgfree(result);
1036                 RDEBUG("User found in group %s", check->vp_strvalue);
1037                 return 0;
1038         }
1039
1040         if (rcode == -1) {
1041                 ldap_release_socket(inst, conn);
1042                 RDEBUG("Failed performing search");
1043                 return 1;
1044         }
1045
1046         /* else the search returned -2, for "not found" */
1047
1048         /*
1049          *      Else the search returned NOTFOUND.  See if we're
1050          *      configured to search for group membership using user
1051          *      object attribute.
1052          */
1053         if (!inst->groupmemb_attr) {
1054                 ldap_release_socket(inst, conn);
1055                 RDEBUG("Group %s was not found, or user is not a member",
1056                        check->vp_strvalue);
1057                 return 1;
1058         }
1059
1060 check_attr:
1061         snprintf(filter ,sizeof(filter), "(objectclass=*)");
1062
1063         rcode = perform_search(inst, &conn, user_dn, LDAP_SCOPE_BASE,
1064                                filter, group_attrs, &result);
1065         if (rcode < 0) {
1066                 RDEBUG("Search failed for group attrs");
1067                 ldap_release_socket(inst, conn);
1068                 return 1;
1069         }
1070
1071         msg = ldap_first_entry(conn->ld, result);
1072         if (!msg) {
1073                 RDEBUG("First entry failed for group attrs");
1074                 ldap_release_socket(inst, conn);
1075                 ldap_msgfree(result);
1076                 return 1;
1077         }
1078
1079         vals = ldap_get_values(conn->ld, msg, inst->groupmemb_attr);
1080         if (!vals) {
1081                 RDEBUG("Get values failed for group attrs");
1082                 ldap_release_socket(inst, conn);
1083                 ldap_msgfree(result);
1084                 return 1;
1085         }
1086
1087         /*
1088          *      Loop over the list of groups the user is a member of,
1089          *      looking for a match.
1090          */
1091         found = FALSE;
1092         for (i = 0; i < ldap_count_values(vals); i++){
1093                 LDAPMessage *gr_result = NULL;
1094
1095                 if (strcmp(vals[i], check->vp_strvalue) == 0){
1096                         found = TRUE;
1097                         break;
1098                 }
1099
1100                 /*
1101                  *      The group isn't a DN: ignore it.
1102                  */
1103                 if (strchr(vals[i], ',') == NULL) continue;
1104
1105                 /* This looks like a DN.  Do tons more work. */
1106                 snprintf(filter,sizeof(filter), "(%s=%s)",
1107                          inst->groupname_attr, check->vp_strvalue);
1108
1109                 rcode = perform_search(inst, &conn, vals[i], LDAP_SCOPE_BASE,
1110                                        filter, attrs, &gr_result);
1111                 if (rcode == -1) {
1112                         RDEBUG("Failed doing group search");
1113                         ldap_value_free(vals);
1114                         ldap_msgfree(result);
1115                         ldap_release_socket(inst, conn);
1116                         return 1;
1117                 }
1118
1119                 ldap_msgfree(gr_result);
1120                 found = TRUE;
1121                 break;
1122         }
1123         ldap_value_free(vals);
1124         ldap_msgfree(result);
1125         ldap_release_socket(inst, conn);
1126
1127         if (!found){
1128                 RDEBUG("groupcmp: Group %s not found, or user is not a member",
1129                        check->vp_strvalue);
1130                 return 1;
1131         }
1132
1133         return 0;
1134 }
1135
1136
1137 /*****************************************************************************
1138  *
1139  *      Detach from the LDAP server and cleanup internal state.
1140  *
1141  *****************************************************************************/
1142 static int ldap_detach(void *instance)
1143 {
1144         ldap_instance *inst = instance;
1145
1146         fr_connection_pool_delete(inst->pool);
1147
1148         if (inst->map_file) {
1149                 rlm_ldap_map_free(&inst->check_map);
1150                 rlm_ldap_map_free(&inst->reply_map);
1151                 free(inst->attrs);
1152         }
1153
1154         free(inst);
1155
1156         return 0;
1157 }
1158
1159 /*************************************************************************
1160  *
1161  *      Function: rlm_ldap_instantiate
1162  *
1163  *      Purpose: Uses section of radiusd config file passed as parameter
1164  *               to create an instance of the module.
1165  *
1166  *************************************************************************/
1167 static int ldap_instantiate(CONF_SECTION * conf, void **instance)
1168 {
1169         ldap_instance *inst;
1170
1171         inst = rad_malloc(sizeof *inst);
1172         if (!inst) {
1173                 return -1;
1174         }
1175         memset(inst, 0, sizeof(*inst));
1176         inst->cs = conf;
1177
1178         inst->chase_referrals = 2; /* use OpenLDAP defaults */
1179         inst->rebind = 2;
1180
1181         if (cf_section_parse(conf, inst, module_config) < 0) {
1182                 free(inst);
1183                 return -1;
1184         }
1185
1186         if (inst->server == NULL) {
1187                 radlog(L_ERR, "rlm_ldap: missing 'server' directive.");
1188                 ldap_detach(inst);
1189                 return -1;
1190         }
1191
1192         /*
1193          *      Check for URLs.  If they're used and the library doesn't
1194          *      support them, then complain.
1195          */
1196         inst->is_url = 0;
1197         if (ldap_is_ldap_url(inst->server)) {
1198 #ifdef HAVE_LDAP_INITIALIZE
1199                 inst->is_url = 1;
1200                 inst->port = 0;
1201 #else
1202                 radlog(L_ERR, "rlm_ldap: 'server' directive is in URL form but ldap_initialize() is not available.");
1203                 ldap_detach(inst);
1204                 return -1;
1205 #endif
1206         }
1207
1208         /* workaround for servers which support LDAPS but not START TLS */
1209         if (inst->port == LDAPS_PORT || inst->tls_mode) {
1210                 inst->tls_mode = LDAP_OPT_X_TLS_HARD;
1211         } else {
1212                 inst->tls_mode = 0;
1213         }
1214
1215         inst->xlat_name = cf_section_name2(conf);
1216         if (!inst->xlat_name) inst->xlat_name = cf_section_name1(conf);
1217
1218 #if LDAP_SET_REBIND_PROC_ARGS != 3
1219         /*
1220          *      The 2-argument rebind doesn't take an instance
1221          *      variable.  Our rebind function needs the instance
1222          *      variable for the username, password, etc.
1223          */
1224         if (inst->rebind == 1) {
1225                 radlog(L_ERR, "%s: Cannot use 'rebind' directive as this version of libldap does not support the API that we need.", inst->xlat-name);
1226                 ldap_detach(inst);
1227                 return -1;
1228         }
1229 #endif
1230
1231         if (inst->map_file) {
1232                 int offset = 0;
1233
1234                 inst->attrs = rad_malloc(sizeof(inst->attrs[0]) * MAX_ATTRMAP);
1235                 inst->attrs[0] = NULL;
1236
1237                 if (inst->profile_attr) inst->attrs[offset++] = inst->profile_attr;
1238                 if (inst->access_attr) inst->attrs[offset++] = inst->access_attr;
1239
1240                 if (rlm_ldap_map_read(inst->xlat_name, inst->map_file,
1241                                       &inst->check_map, &inst->reply_map,
1242                                       offset,
1243                                       inst->attrs) < 0) {
1244                         ldap_detach(inst);
1245                         return -1;
1246                 }
1247
1248                 if (!inst->check_map || !inst->reply_map) {
1249                         radlog(L_ERR, "%s: Empty file: %s",
1250                                inst->xlat_name, inst->map_file);
1251                         ldap_detach(inst);
1252                         return -1;
1253                 }
1254
1255         } else {
1256                 if (inst->default_profile || inst->profile_attr) {
1257                         radlog(L_ERR, "%s: You MUST specify \"dictionary_mapping\" to use the profile attributes", inst->xlat_name);
1258                         ldap_detach(inst);
1259                         return -1;
1260                 }
1261         }
1262
1263         /*
1264          *      Group comparison checks.
1265          */
1266         paircompare_register(PW_LDAP_GROUP, PW_USER_NAME, ldap_groupcmp, inst); 
1267         if (cf_section_name2(conf)) {
1268                 DICT_ATTR *da;
1269                 ATTR_FLAGS flags;
1270                 char buffer[256];
1271
1272                 snprintf(buffer, sizeof(buffer), "%s-Ldap-Group", inst->xlat_name);
1273                 memset(&flags, 0, sizeof(flags));
1274
1275                 dict_addattr(buffer, -1, 0, PW_TYPE_STRING, flags);
1276                 da = dict_attrbyname(buffer);
1277                 if (!da) {
1278                         radlog(L_ERR, "%s: Failed creating attribute %s",
1279                                inst->xlat_name, buffer);
1280                         ldap_detach(inst);
1281                         return -1;
1282                 }
1283
1284                 paircompare_register(da->attr, PW_USER_NAME, ldap_groupcmp, inst);
1285         }
1286
1287         xlat_register(inst->xlat_name, ldap_xlat, inst);
1288
1289         /*
1290          *      Initialize the socket pool.
1291          */
1292         inst->pool = fr_connection_pool_init(inst->cs, inst,
1293                                              ldap_conn_create,
1294                                              NULL,
1295                                              ldap_conn_delete);
1296         if (!inst->pool) {
1297                 ldap_detach(inst);
1298                 return -1;
1299         }
1300         
1301         *instance = inst;
1302         return 0;
1303 }
1304
1305
1306 static void module_failure_msg(VALUE_PAIR **vps, const char *fmt, ...)
1307 {
1308         va_list ap;
1309         VALUE_PAIR *vp;
1310
1311         va_start(ap, fmt);
1312         vp = paircreate(PW_MODULE_FAILURE_MESSAGE, 0, PW_TYPE_STRING);
1313         if (!vp) {
1314                 va_end(ap);
1315                 return;
1316         }
1317
1318         vsnprintf(vp->vp_strvalue, sizeof(vp->vp_strvalue), fmt, ap);
1319
1320         pairadd(vps, vp);
1321 }
1322
1323
1324 static int check_access(ldap_instance *inst, LDAP_CONN *conn, LDAPMessage *msg)
1325 {
1326         int rcode = -1;
1327         char **vals = NULL;
1328
1329         vals = ldap_get_values(conn->ld, msg, inst->access_attr);
1330         if (vals) {
1331                 if (inst->positive_access_attr) {
1332                         if (strncmp(vals[0], "FALSE", 5) == 0) {
1333                                 DEBUG("dialup access disabled");
1334
1335                         } else {
1336                                 rcode = 0;
1337                         }
1338
1339                 } else {
1340                         DEBUG("%s attribute exists - access denied by default",
1341                                 inst->access_attr);
1342                 }
1343
1344                 ldap_value_free(vals);
1345
1346         } else if (inst->positive_access_attr) {
1347                 DEBUG("No %s attribute - access denied by default", inst->access_attr);
1348
1349         } else {
1350                 rcode = 0;
1351         }
1352
1353         return rcode;
1354 }
1355
1356
1357 static void apply_profile(ldap_instance *inst, LDAP_CONN **pconn,
1358                           REQUEST *request, char *profile)
1359 {
1360         int rcode;
1361         LDAPMessage     *result, *msg;
1362         VALUE_PAIR      *check_tmp, *reply_tmp;
1363         char            filter[MAX_FILTER_STR_LEN];
1364
1365         if (!profile || !*profile) return;
1366
1367         strlcpy(filter,inst->base_filter,sizeof(filter));
1368
1369         rcode = perform_search(inst, pconn, profile, LDAP_SCOPE_BASE, filter,
1370                                inst->attrs, &result);
1371         if (rcode < 0) {
1372                 RDEBUG("FAILED Searching profile %s", profile);
1373                 return;
1374         }
1375
1376         msg = ldap_first_entry((*pconn)->ld, result);
1377         if (!msg) goto free_result;
1378
1379         check_tmp = rlm_ldap_pairget(inst->xlat_name, (*pconn)->ld, msg,
1380                                      inst->check_map, &request->config_items, 1);
1381         if (check_tmp) {
1382                 pairfree(&check_tmp);
1383         }
1384
1385         reply_tmp = rlm_ldap_pairget(inst->xlat_name, (*pconn)->ld, msg,
1386                                      inst->reply_map, &request->packet->vps, 0);
1387         if (reply_tmp) {
1388                 pairfree(&reply_tmp);
1389         }
1390
1391 free_result:
1392         ldap_msgfree(result);
1393 }
1394
1395
1396 static void do_one_map(ldap_instance *inst, LDAP *ld, REQUEST *request,
1397                        LDAPMessage *msg, TLDAP_RADIUS *map, VALUE_PAIR **vps,
1398                        int is_check)
1399 {
1400         VALUE_PAIR *vp;
1401
1402         vp = rlm_ldap_pairget(inst->xlat_name, ld, msg, map, vps, is_check);
1403         if (vp) {
1404                 if (inst->do_xlat) {
1405                         pairxlatmove(request, vps, &vp);
1406                         pairfree(&vp);
1407
1408                 } else {
1409                         pairadd(vps, vp);
1410                 }
1411         }
1412
1413 }
1414
1415 static void do_check_reply(ldap_instance *inst, LDAP *ld, REQUEST *request,
1416                            LDAPMessage *msg)
1417 {
1418         do_one_map(inst, ld, request, msg, inst->check_map, &request->config_items, 1);
1419         do_one_map(inst, ld, request, msg, inst->reply_map, &request->reply->vps, 0);
1420
1421        /*
1422         *       More warning messages for people who can't be bothered
1423         *       to read the documentation.
1424         */
1425        if (debug_flag > 1) {
1426                if (!pairfind(request->config_items, PW_CLEARTEXT_PASSWORD, 0) &&
1427                    !pairfind(request->config_items, PW_NT_PASSWORD, 0) &&
1428                    !pairfind(request->config_items, PW_USER_PASSWORD, 0) &&
1429                    !pairfind(request->config_items, PW_PASSWORD_WITH_HEADER, 0) &&
1430                    !pairfind(request->config_items, PW_CRYPT_PASSWORD, 0)) {
1431                        DEBUG("WARNING: No \"known good\" password was found in LDAP.  Are you sure that the user is configured correctly?");
1432                }
1433        }
1434 }
1435
1436
1437 /******************************************************************************
1438  *
1439  *      Function: ldap_authorize
1440  *
1441  *      Purpose: Check if user is authorized for remote access
1442  *
1443  ******************************************************************************/
1444 static int ldap_authorize(void *instance, REQUEST * request)
1445 {
1446         int rcode, did_work;
1447         int module_rcode = RLM_MODULE_NOOP;
1448         ldap_instance   *inst = instance;
1449         char            *user_dn;
1450         char            **vals;
1451         VALUE_PAIR      *vp;
1452         LDAP_CONN       *conn;
1453         LDAPMessage     *result, *msg;
1454         char            filter[MAX_FILTER_STR_LEN];
1455         char            basedn[MAX_FILTER_STR_LEN];
1456
1457         did_work = FALSE;       /* for debugging user problems */
1458
1459         if (!request->username) {
1460                 RDEBUG2("Attribute \"User-Name\" is required for authorization.\n");
1461                 return RLM_MODULE_NOOP;
1462         }
1463
1464         /*
1465          *      Check for valid input, zero length names not permitted
1466          */
1467         if (request->username->length == 0) {
1468                 RDEBUG2("zero length username not permitted\n");
1469                 return RLM_MODULE_INVALID;
1470         }
1471
1472         if (!radius_xlat(filter, sizeof(filter), inst->filter,
1473                          request, ldap_escape_func)) {
1474                 radlog(L_ERR, "  [%s] Failed creating filter.\n", inst->xlat_name);
1475                 return RLM_MODULE_INVALID;
1476         }
1477
1478         if (!radius_xlat(basedn, sizeof(basedn), inst->basedn,
1479                          request, ldap_escape_func)) {
1480                 radlog(L_ERR, "  [%s] Failed creating basedn.\n", inst->xlat_name);
1481                 return RLM_MODULE_INVALID;
1482         }
1483
1484         conn = ldap_get_socket(inst);
1485         if (!conn) return RLM_MODULE_FAIL;
1486
1487         rcode = perform_search(inst, &conn, basedn, LDAP_SCOPE_SUBTREE, filter,
1488                                inst->attrs, &result);
1489         if (rcode < 0) {
1490                 if (rcode == -2) {
1491                         module_failure_msg(&request->packet->vps,
1492                                            "[%s] Search returned not found",
1493                                            inst->xlat_name);
1494                         DEBUG("  [%s] Search returned not found", inst->xlat_name);
1495                         module_rcode = RLM_MODULE_NOTFOUND;
1496                         goto free_socket;
1497                 }
1498                 DEBUG("  [%s] Search returned error", inst->xlat_name);
1499                 goto free_socket;
1500         }
1501
1502         msg = ldap_first_entry(conn->ld, result);
1503         if (!msg) {
1504                 RDEBUG2("ldap_first_entry() failed");
1505                 goto free_result;
1506         }
1507
1508         user_dn = ldap_get_dn(conn->ld, msg);
1509         if (!user_dn) {
1510                 RDEBUG2("ldap_get_dn() failed");
1511                 goto free_result;
1512         }
1513
1514         /*
1515          *      Adding attribute containing the Users' DN.
1516          */
1517         pairadd(&request->config_items, pairmake("Ldap-UserDn", user_dn, T_OP_EQ));
1518         ldap_memfree(user_dn);
1519
1520         /*
1521          *      Check for access.
1522          */
1523         if (inst->access_attr) {
1524                 did_work = TRUE;
1525
1526                 if (check_access(inst, conn, msg) < 0) {
1527                         module_rcode = RLM_MODULE_USERLOCK;
1528                         goto free_result;
1529                 }
1530         }
1531
1532         /*
1533          *      Apply ONE user profile, or a default user profile.
1534          */
1535         vp = pairfind(request->config_items, PW_USER_PROFILE, 0);
1536         if (vp || inst->default_profile) {
1537                 char *profile = inst->default_profile;
1538
1539                 if (vp) profile = vp->vp_strvalue;
1540
1541                 did_work = TRUE;
1542                 apply_profile(inst, &conn, request, profile);
1543         }
1544
1545         /*
1546          *      Apply a SET of user profiles.
1547          */
1548         if (inst->profile_attr &&
1549             (vals = ldap_get_values(conn->ld, msg, inst->profile_attr)) != NULL) {
1550
1551                 int i;
1552
1553                 for (i = 0; (vals[i] != NULL) && (*vals[i] != '\0'); i++) {
1554                         apply_profile(inst, &conn, request, vals[i]);
1555                 }
1556
1557                 did_work = TRUE;
1558                 ldap_value_free(vals);
1559         }
1560
1561         if (inst->map_file) {
1562                 did_work = TRUE;
1563                 do_check_reply(inst, conn->ld, request, msg);
1564         }
1565
1566         if (!did_work) {
1567                 RDEBUG("WARNING: The module did NOTHING in the 'authorize' section.  Why is it listed?");
1568                 RDEBUG("WARNING: You can probably delete '%s' from 'authorize'",
1569                        inst->xlat_name);
1570         }       
1571
1572 free_result:
1573         ldap_msgfree(result);
1574 free_socket:
1575         ldap_release_socket(inst, conn);
1576
1577         return module_rcode;
1578 }
1579
1580
1581 /*****************************************************************************
1582  *
1583  *      Function: ldap_authenticate
1584  *
1585  *      Purpose: Check the user's password against ldap database
1586  *
1587  *****************************************************************************/
1588 static int ldap_authenticate(void *instance, REQUEST * request)
1589 {
1590         int             module_rcode;
1591         const char      *user_dn;
1592         ldap_instance   *inst = instance;
1593         LDAP_CONN       *conn;
1594
1595         /*
1596          * Ensure that we're being passed a plain-text password, and not
1597          * anything else.
1598          */
1599
1600         if (!request->username) {
1601                 radlog(L_AUTH, "  [%s] Attribute \"User-Name\" is required for authentication.", inst->xlat_name);
1602                 return RLM_MODULE_INVALID;
1603         }
1604
1605         if (!request->password) {
1606                 radlog(L_AUTH, "  [%s] Attribute \"User-Password\" is required for authentication.", inst->xlat_name);
1607                 RDEBUG2("  You seem to have set \"Auth-Type := LDAP\" somewhere.");
1608                 RDEBUG2("  *******************************************************");
1609                 RDEBUG2("  * THAT CONFIGURATION IS WRONG.  DELETE IT.");
1610                 RDEBUG2("  * YOU ARE PREVENTING THE SERVER FROM WORKING PROPERLY.");
1611                 RDEBUG2("  *******************************************************");
1612                 return RLM_MODULE_INVALID;
1613         }
1614
1615         if (request->password->attribute != PW_USER_PASSWORD) {
1616                 radlog(L_AUTH, "  [%s] Attribute \"User-Password\" is required for authentication. Cannot use \"%s\".", inst->xlat_name, request->password->name);
1617                 return RLM_MODULE_INVALID;
1618         }
1619
1620         if (request->password->length == 0) {
1621                 module_failure_msg(&request->packet->vps,
1622                                    "[%s] empty password supplied", inst->xlat_name);
1623                 return RLM_MODULE_INVALID;
1624         }
1625
1626         conn = ldap_get_socket(inst);
1627         if (!conn) return RLM_MODULE_FAIL;
1628
1629         RDEBUG("login attempt by \"%s\" with password \"%s\"",
1630                request->username->vp_strvalue, request->password->vp_strvalue);
1631
1632         /*
1633          *      Get the DN by doing a search.
1634          */
1635         user_dn = get_userdn(&conn, request, &module_rcode);
1636         if (!user_dn) {
1637                 ldap_release_socket(inst, conn);
1638                 return module_rcode;
1639         }
1640
1641         /*
1642          *      Bind as the user
1643          */
1644         conn->rebound = TRUE;
1645         module_rcode = ldap_bind_wrapper(&conn, user_dn,
1646                                          request->password->vp_strvalue,
1647                                          NULL, TRUE);
1648         if (module_rcode == RLM_MODULE_OK) {
1649                 RDEBUG("  [%s] Bind as user '%s' was successful", inst->xlat_name,
1650                         user_dn);
1651         }
1652
1653         ldap_release_socket(inst, conn);
1654         return module_rcode;
1655 }
1656
1657
1658 /* globally exported name */
1659 module_t rlm_ldap = {
1660         RLM_MODULE_INIT,
1661         "ldap",
1662         RLM_TYPE_THREAD_SAFE,   /* type: reserved        */
1663         ldap_instantiate,       /* instantiation         */
1664         ldap_detach,            /* detach                */
1665         {
1666                 ldap_authenticate,      /* authentication        */
1667                 ldap_authorize,         /* authorization         */
1668                 NULL,                   /* preaccounting         */
1669                 NULL,                   /* accounting            */
1670                 NULL,                   /* checksimul            */
1671                 NULL,                   /* pre-proxy             */
1672                 NULL,                   /* post-proxy            */
1673                 NULL
1674         },
1675 };