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.
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.
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
19 * @brief LDAP authorization and authentication module.
21 * @copyright 1999-2013 The FreeRADIUS Server Project.
22 * @copyright 2012 Alan DeKok <aland@freeradius.org>
23 * @copyright 2012-2013 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
25 #include <freeradius-devel/ident.h>
28 #include <freeradius-devel/radiusd.h>
29 #include <freeradius-devel/modules.h>
30 #include <freeradius-devel/rad_assert.h>
38 #define MAX_ATTRMAP 128
39 #define MAX_ATTR_STR_LEN 256
40 #define MAX_FILTER_STR_LEN 1024
43 extern int nmasldap_get_password(LDAP *ld,char *objectDN, char *pwd, size_t *pwdSize);
47 typedef struct ldap_acct_section {
50 const char *reference;
51 } ldap_acct_section_t;
56 fr_connection_pool_t *pool;
70 int ldap_debug; //!< Debug flag for the SDK.
72 const char *xlat_name; //!< Instance name.
77 * RADIUS attribute to LDAP attribute maps
79 value_pair_map_t *user_map; //!< Attribute map applied to users and
83 * Access related configuration
86 int positive_access_attr;
92 char *default_profile;
99 char *groupmemb_filter;
100 char *groupmemb_attr;
105 ldap_acct_section_t *postauth;
106 ldap_acct_section_t *accounting;
109 * TLS items. We should really normalize these with the
114 char *tls_cacertfile;
119 char *tls_require_cert;
139 #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
142 #ifdef LDAP_OPT_X_KEEPALIVE_PROBES
143 int keepalive_probes;
145 #ifdef LDAP_OPT_ERROR_NUMBER
146 int keepalive_interval;
151 /* The default setting for TLS Certificate Verification */
152 #define TLS_DEFAULT_VERIFY "allow"
157 static CONF_PARSER tls_config[] = {
158 {"start_tls", PW_TYPE_BOOLEAN,
159 offsetof(ldap_instance,start_tls), NULL, "no"},
160 {"cacertfile", PW_TYPE_FILENAME,
161 offsetof(ldap_instance,tls_cacertfile), NULL, NULL},
162 {"cacertdir", PW_TYPE_FILENAME,
163 offsetof(ldap_instance,tls_cacertdir), NULL, NULL},
164 {"certfile", PW_TYPE_FILENAME,
165 offsetof(ldap_instance,tls_certfile), NULL, NULL},
166 {"keyfile", PW_TYPE_FILENAME,
167 offsetof(ldap_instance,tls_keyfile), NULL, NULL},
168 {"randfile", PW_TYPE_STRING_PTR, /* OK if it changes on HUP */
169 offsetof(ldap_instance,tls_randfile), NULL, NULL},
170 {"require_cert", PW_TYPE_STRING_PTR,
171 offsetof(ldap_instance,tls_require_cert), NULL, TLS_DEFAULT_VERIFY},
172 { NULL, -1, 0, NULL, NULL }
176 static CONF_PARSER attr_config[] = {
180 /* LDAP attribute name that controls remote access */
181 {"access_attr", PW_TYPE_STRING_PTR,
182 offsetof(ldap_instance,access_attr), NULL, NULL},
183 {"positive_access_attr", PW_TYPE_BOOLEAN,
184 offsetof(ldap_instance,positive_access_attr), NULL, "yes"},
186 {"base_filter", PW_TYPE_STRING_PTR,
187 offsetof(ldap_instance,base_filter), NULL,
188 "(objectclass=radiusprofile)"},
189 {"default_profile", PW_TYPE_STRING_PTR,
190 offsetof(ldap_instance,default_profile), NULL, NULL},
191 {"profile_attribute", PW_TYPE_STRING_PTR,
192 offsetof(ldap_instance,profile_attr), NULL, NULL},
194 { NULL, -1, 0, NULL, NULL }
199 * Group configuration
201 static CONF_PARSER group_config[] = {
203 * Group checks. These could probably be done
204 * via dynamic xlat's.
206 {"name_attribute", PW_TYPE_STRING_PTR,
207 offsetof(ldap_instance,groupname_attr), NULL, "cn"},
208 {"membership_filter", PW_TYPE_STRING_PTR,
209 offsetof(ldap_instance,groupmemb_filter), NULL,
210 "(|(&(objectClass=GroupOfNames)(member=%{Ldap-UserDn}))"
211 "(&(objectClass=GroupOfUniqueNames)(uniquemember=%{Ldap-UserDn})))"},
212 {"membership_attribute", PW_TYPE_STRING_PTR,
213 offsetof(ldap_instance,groupmemb_attr), NULL, NULL},
216 { NULL, -1, 0, NULL, NULL }
220 * Reference for accounting updates
222 static const CONF_PARSER acct_section_config[] = {
223 {"reference", PW_TYPE_STRING_PTR,
224 offsetof(ldap_acct_section_t, reference), NULL, "."},
225 {NULL, -1, 0, NULL, NULL}
229 * Various options that don't belong in the main configuration.
231 * Note that these overlap a bit with the connection pool code!
233 static CONF_PARSER option_config[] = {
235 * Debugging flags to the server
237 {"ldap_debug", PW_TYPE_INTEGER,
238 offsetof(ldap_instance,ldap_debug), NULL, "0x0000"},
240 {"chase_referrals", PW_TYPE_BOOLEAN,
241 offsetof(ldap_instance,chase_referrals), NULL, NULL},
243 {"rebind", PW_TYPE_BOOLEAN,
244 offsetof(ldap_instance,rebind), NULL, NULL},
246 /* timeout on network activity */
247 {"net_timeout", PW_TYPE_INTEGER,
248 offsetof(ldap_instance,net_timeout), NULL, "10"},
250 /* timeout for search results */
251 {"timeout", PW_TYPE_INTEGER,
252 offsetof(ldap_instance,timeout), NULL, "20"},
254 /* allow server unlimited time for search (server-side limit) */
255 {"timelimit", PW_TYPE_INTEGER,
256 offsetof(ldap_instance,timelimit), NULL, "20"},
258 #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
259 {"idle", PW_TYPE_INTEGER,
260 offsetof(ldap_instance,keepalive_idle), NULL, "60"},
262 #ifdef LDAP_OPT_X_KEEPALIVE_PROBES
263 {"probes", PW_TYPE_INTEGER,
264 offsetof(ldap_instance,keepalive_probes), NULL, "3"},
266 #ifdef LDAP_OPT_ERROR_NUMBER
267 {"interval", PW_TYPE_INTEGER,
268 offsetof(ldap_instance,keepalive_interval), NULL, "30"},
270 { NULL, -1, 0, NULL, NULL }
274 static const CONF_PARSER module_config[] = {
275 {"server", PW_TYPE_STRING_PTR,
276 offsetof(ldap_instance,server), NULL, "localhost"},
277 {"port", PW_TYPE_INTEGER,
278 offsetof(ldap_instance,port), NULL, "389"},
280 {"password", PW_TYPE_STRING_PTR,
281 offsetof(ldap_instance,password), NULL, ""},
282 {"identity", PW_TYPE_STRING_PTR,
283 offsetof(ldap_instance,login), NULL, ""},
288 {"basedn", PW_TYPE_STRING_PTR,
289 offsetof(ldap_instance,basedn), NULL, "o=notexist"},
291 {"filter", PW_TYPE_STRING_PTR,
292 offsetof(ldap_instance,filter), NULL, "(uid=%u)"},
294 /* turn off the annoying warning if we don't expect a password */
295 {"expect_password", PW_TYPE_BOOLEAN,
296 offsetof(ldap_instance,expect_password), NULL, "yes"},
299 /* support for eDirectory Universal Password */
300 {"edir", PW_TYPE_BOOLEAN,
301 offsetof(ldap_instance,edir), NULL, NULL}, /* NULL defaults to "no" */
304 * Attempt to bind with the Cleartext password we got from eDirectory
305 * Universal password for additional authorization checks.
307 {"edir_autz", PW_TYPE_BOOLEAN,
308 offsetof(ldap_instance,edir_autz), NULL, NULL}, /* NULL defaults to "no" */
312 * Terrible things which should be deleted.
314 { "profiles", PW_TYPE_SUBSECTION, 0, NULL, (const void *) attr_config },
316 { "group", PW_TYPE_SUBSECTION, 0, NULL, (const void *) group_config },
318 { "options", PW_TYPE_SUBSECTION, 0, NULL,
319 (const void *) option_config },
321 { "tls", PW_TYPE_SUBSECTION, 0, NULL, (const void *) tls_config },
323 {NULL, -1, 0, NULL, NULL}
326 typedef struct ldap_conn {
333 typedef struct xlat_attrs {
334 const value_pair_map_t *maps;
335 const char *attrs[MAX_ATTRMAP];
338 typedef struct rlm_ldap_result {
344 LDAP_PROC_SUCCESS = 0,
345 LDAP_PROC_ERROR = -1,
346 LDAP_PROC_RETRY = -2,
347 LDAP_PROC_REJECT = -3
350 static ldap_rcode_t process_ldap_errno(ldap_instance *inst, LDAP_CONN **pconn,
351 const char *operation)
355 ldap_get_option((*pconn)->handle, LDAP_OPT_ERROR_NUMBER,
357 switch (ldap_errno) {
359 case LDAP_NO_SUCH_OBJECT:
360 return LDAP_PROC_SUCCESS;
362 case LDAP_INSUFFICIENT_ACCESS:
363 radlog(L_ERR, "rlm_ldap (%s): %s failed: Insufficient access. "
364 "Check the identity and password configuration "
365 "directives", inst->xlat_name, operation);
366 return LDAP_PROC_ERROR;
369 exec_trigger(NULL, inst->cs, "modules.ldap.timeout", TRUE);
370 radlog(L_ERR, "rlm_ldap (%s): %s failed: Timed out "
371 "while waiting for server to respond", inst->xlat_name,
373 return LDAP_PROC_ERROR;
375 case LDAP_FILTER_ERROR:
376 radlog(L_ERR, "rlm_ldap (%s): %s failed: Bad search "
377 "filter", inst->xlat_name, operation);
378 return LDAP_PROC_ERROR;
380 case LDAP_TIMELIMIT_EXCEEDED:
381 exec_trigger(NULL, inst->cs, "modules.ldap.timeout", TRUE);
385 case LDAP_UNAVAILABLE:
387 * Reconnect. There's an issue with the socket
390 radlog(L_ERR, "rlm_ldap (%s): %s failed: %s",
391 inst->xlat_name, operation, ldap_err2string(ldap_errno));
392 case LDAP_SERVER_DOWN:
393 return LDAP_PROC_RETRY;
395 case LDAP_INVALID_CREDENTIALS:
396 case LDAP_CONSTRAINT_VIOLATION:
397 return LDAP_PROC_REJECT;
399 case LDAP_OPERATIONS_ERROR:
400 DEBUGW("Please set 'chase_referrals=yes' and 'rebind=yes'");
401 DEBUGW("See the ldap module configuration for details");
405 radlog(L_ERR, "rlm_ldap (%s): %s failed: %s",
406 inst->xlat_name, operation, ldap_err2string(ldap_errno));
407 return LDAP_PROC_ERROR;
412 static int ldap_bind_wrapper(LDAP_CONN **pconn, const char *user,
413 const char *password, int retry)
416 int module_rcode = RLM_MODULE_OK;
417 LDAP_CONN *conn = *pconn;
418 ldap_instance *inst = conn->inst;
419 LDAPMessage *result = NULL;
423 msg_id = ldap_bind(conn->handle, user, password, LDAP_AUTH_SIMPLE);
424 if (msg_id < 0) goto get_error;
426 DEBUG3("rlm_ldap (%s): Waiting for bind result...", inst->xlat_name);
428 tv.tv_sec = inst->timeout;
431 rcode = ldap_result(conn->handle, msg_id, 1, &tv, &result);
432 ldap_msgfree(result);
435 switch (process_ldap_errno(inst, &conn, "Bind"))
437 case LDAP_PROC_SUCCESS:
439 case LDAP_PROC_REJECT:
440 module_rcode = RLM_MODULE_REJECT;
442 case LDAP_PROC_ERROR:
443 module_rcode = RLM_MODULE_FAIL;
445 #ifdef HAVE_LDAP_INITIALIZE
447 radlog(L_ERR, "rlm_ldap (%s): bind "
448 "with %s to %s failed",
449 inst->xlat_name, user,
454 radlog(L_ERR, "rlm_ldap (%s): bind "
455 "with %s to %s:%d failed",
456 inst->xlat_name, user,
457 inst->server, inst->port);
461 case LDAP_PROC_RETRY:
463 *pconn = fr_connection_reconnect(inst->pool, *pconn);
464 if (*pconn) goto retry;
467 module_rcode = RLM_MODULE_FAIL;
474 return module_rcode; /* caller closes the connection */
477 #if LDAP_SET_REBIND_PROC_ARGS == 3
479 * Rebind && chase referral stuff
481 static int ldap_rebind(LDAP *handle, LDAP_CONST char *url,
482 UNUSED ber_tag_t request, UNUSED ber_int_t msgid,
485 int rcode, ldap_errno;
486 LDAP_CONN *conn = ctx;
488 conn->referred = TRUE;
489 conn->rebound = TRUE; /* not really, but oh well... */
490 rad_assert(handle == conn->handle);
492 DEBUG("rlm_ldap (%s): Rebinding to URL %s", conn->inst->xlat_name, url);
495 rcode = ldap_bind_wrapper(&conn, conn->inst->login,
496 conn->inst->password, FALSE);
498 if (rcode == RLM_MODULE_OK) {
502 ldap_get_option(handle, LDAP_OPT_ERROR_NUMBER, &ldap_errno);
508 /** Create and return a new connection
509 * This function is probably too big.
511 static void *ldap_conn_create(void *ctx)
514 int ldap_errno, ldap_version;
516 ldap_instance *inst = ctx;
518 LDAP_CONN *conn = NULL;
520 #ifdef HAVE_LDAP_INITIALIZE
522 DEBUG("rlm_ldap (%s): Connecting to %s", inst->xlat_name,
525 ldap_errno = ldap_initialize(&handle, inst->server);
526 if (ldap_errno != LDAP_SUCCESS) {
527 radlog(L_ERR, "rlm_ldap (%s): ldap_initialize() "
529 inst->xlat_name, ldap_err2string(ldap_errno));
535 DEBUG("rlm_ldap (%s): Connecting to %s:%d", inst->xlat_name,
536 inst->server, inst->port);
538 handle = ldap_init(inst->server, inst->port);
540 radlog(L_ERR, "rlm_ldap (%s): ldap_init() failed",
543 if (handle) ldap_unbind_s(handle);
549 * We now have a connection structure, but no actual TCP connection.
551 * Set a bunch of LDAP options, using common code.
553 #define do_ldap_option(_option, _name, _value) \
554 if (ldap_set_option(handle, _option, _value) != LDAP_OPT_SUCCESS) { \
555 ldap_get_option(handle, LDAP_OPT_ERROR_NUMBER, &ldap_errno); \
556 radlog(L_ERR, "rlm_ldap (%s): Could not set %s: %s", \
557 inst->xlat_name, _name, ldap_err2string(ldap_errno)); \
560 if (inst->ldap_debug) {
561 do_ldap_option(LDAP_OPT_DEBUG_LEVEL, "ldap_debug",
562 &(inst->ldap_debug));
566 * Leave "chase_referrals" unset to use the OpenLDAP
569 if (inst->chase_referrals != 2) {
570 if (inst->chase_referrals) {
571 do_ldap_option(LDAP_OPT_REFERRALS, "chase_referrals",
574 if (inst->rebind == 1) {
575 #if LDAP_SET_REBIND_PROC_ARGS == 3
576 ldap_set_rebind_proc(handle, ldap_rebind, inst);
578 DEBUGW("The flag 'rebind = yes' is not supported by the system LDAP library. Ignoring.");
582 do_ldap_option(LDAP_OPT_REFERRALS, "chase_referrals",
587 tv.tv_sec = inst->net_timeout;
589 do_ldap_option(LDAP_OPT_NETWORK_TIMEOUT, "net_timeout", &tv);
591 do_ldap_option(LDAP_OPT_TIMELIMIT, "timelimit", &(inst->timelimit));
593 ldap_version = LDAP_VERSION3;
594 do_ldap_option(LDAP_OPT_PROTOCOL_VERSION, "ldap_version",
597 #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
598 do_ldap_option(LDAP_OPT_X_KEEPALIVE_IDLE, "keepalive idle",
599 &(inst->keepalive_idle));
602 #ifdef LDAP_OPT_X_KEEPALIVE_PROBES
603 do_ldap_option(LDAP_OPT_X_KEEPALIVE_PROBES, "keepalive probes",
604 &(inst->keepalive_probes));
607 #ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL
608 do_ldap_option(LDAP_OPT_X_KEEPALIVE_INTERVAL, "keepalive interval",
609 &(inst->keepalive_interval));
612 #ifdef HAVE_LDAP_START_TLS
614 * Set all of the TLS options
616 if (inst->tls_mode) {
617 do_ldap_option(LDAP_OPT_X_TLS, "tls_mode", &(inst->tls_mode));
620 #define maybe_ldap_option(_option, _name, _value) \
621 if (_value) do_ldap_option(_option, _name, _value)
623 maybe_ldap_option(LDAP_OPT_X_TLS_CACERTFILE,
624 "cacertfile", inst->tls_cacertfile);
625 maybe_ldap_option(LDAP_OPT_X_TLS_CACERTDIR,
626 "cacertdir", inst->tls_cacertdir);
628 #ifdef HAVE_LDAP_INT_TLS_CONFIG
629 if (ldap_int_tls_config(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT,
630 (inst->tls_require_cert)) != LDAP_OPT_SUCCESS) {
631 ldap_get_option(handle, LDAP_OPT_ERROR_NUMBER, &ldap_errno);
632 radlog(L_ERR, "rlm_ldap (%s): could not set "
633 "LDAP_OPT_X_TLS_REQUIRE_CERT option to %s: %s",
635 inst->tls_require_cert,
636 ldap_err2string(ldap_errno));
640 maybe_ldap_option(LDAP_OPT_X_TLS_CERTFILE,
641 "certfile", inst->tls_certfile);
642 maybe_ldap_option(LDAP_OPT_X_TLS_KEYFILE,
643 "keyfile", inst->tls_keyfile);
644 maybe_ldap_option(LDAP_OPT_X_TLS_RANDOM_FILE,
645 "randfile", inst->tls_randfile);
648 * And finally start the TLS code.
650 if (inst->start_tls && (inst->port != 636)) {
651 ldap_errno = ldap_start_tls_s(handle, NULL, NULL);
652 if (ldap_errno != LDAP_SUCCESS) {
653 ldap_get_option(handle, LDAP_OPT_ERROR_NUMBER,
655 radlog(L_ERR, "rlm_ldap (%s): could not start TLS: %s",
657 ldap_err2string(ldap_errno));
661 #endif /* HAVE_LDAP_START_TLS */
663 conn = talloc(NULL, LDAP_CONN);
665 conn->handle = handle;
666 conn->rebound = FALSE;
667 conn->referred = FALSE;
669 module_rcode = ldap_bind_wrapper(&conn, inst->login, inst->password,
671 if (module_rcode != RLM_MODULE_OK) {
679 /** Close and delete a connection
682 static int ldap_conn_delete(UNUSED void *ctx, void *connection)
684 LDAP_CONN *conn = connection;
686 ldap_unbind_s(conn->handle);
693 /** Gets an LDAP socket from the connection pool
696 static LDAP_CONN *ldap_get_socket(ldap_instance *inst)
700 conn = fr_connection_get(inst->pool);
702 radlog(L_ERR, "rlm_ldap (%s): all ldap connections are in use",
710 /** Frees an LDAP socket back to the connection pool
713 static void ldap_release_socket(ldap_instance *inst, LDAP_CONN *conn)
716 * Could have already been free'd due to a previous error.
721 * We chased a referral to another server.
723 * This connection is no longer part of the pool which is
724 * connected to and bound to the configured server.
727 * Note that we do NOT close it if it was bound to
728 * another user. Instead, we let the next caller do the
731 if (conn->referred) {
732 fr_connection_del(inst->pool, conn);
736 fr_connection_release(inst->pool, conn);
741 /* Converts "bad" strings into ones which are safe for LDAP
744 static size_t ldap_escape_func(UNUSED REQUEST *request, char *out,
745 size_t outlen, const char *in, UNUSED void *arg)
751 * Encode unsafe characters.
754 ((in[0] == ' ') || (in[0] == '#'))) ||
755 (strchr(",+\"\\<>;*=()", *in))) {
756 static const char hex[] = "0123456789abcdef";
759 * Only 3 or less bytes available.
766 *(out++) = hex[((*in) >> 4) & 0x0f];
767 *(out++) = hex[(*in) & 0x0f];
775 * Only one byte left.
792 /** Do a search and get a response
795 static int perform_search(ldap_instance *inst, REQUEST *request,
796 LDAP_CONN **pconn, const char *search_basedn,
797 int scope, const char *filter,
798 const char * const *attrs, LDAPMessage **presult)
805 * OpenLDAP library doesn't declare attrs array as const, but
806 * it really should be *sigh*.
809 memcpy(&search_attrs, &attrs, sizeof(attrs));
814 * Do all searches as the default admin user.
816 if ((*pconn)->rebound) {
817 ldap_errno = ldap_bind_wrapper(pconn, inst->login,
818 inst->password, TRUE);
819 if (ldap_errno != RLM_MODULE_OK) {
824 (*pconn)->rebound = FALSE;
827 tv.tv_sec = inst->timeout;
829 RDEBUG2("Performing search in '%s' with filter '%s'",
830 search_basedn ? search_basedn : "(null)" ,
834 ldap_errno = ldap_search_ext_s((*pconn)->handle, search_basedn, scope,
835 filter, search_attrs, 0, NULL, NULL,
837 if (ldap_errno != LDAP_SUCCESS) {
838 ldap_msgfree(*presult);
839 switch (process_ldap_errno(inst, pconn, "Search"))
841 case LDAP_PROC_SUCCESS:
843 case LDAP_PROC_REJECT:
844 case LDAP_PROC_ERROR:
846 case LDAP_PROC_RETRY:
847 *pconn = fr_connection_reconnect(inst->pool, *pconn);
848 if (*pconn) goto retry;
855 count = ldap_count_entries((*pconn)->handle, *presult);
857 ldap_msgfree(*presult);
858 RDEBUG("Search returned no results");
864 ldap_msgfree(*presult);
865 RDEBUG("Got ambiguous search result (%d results)", count);
873 /** Expand an LDAP URL into a query, and return a string result from that query.
876 static size_t ldap_xlat(void *instance, REQUEST *request, const char *fmt,
877 char *out, size_t freespace)
881 ldap_instance *inst = instance;
882 LDAPURLDesc *ldap_url;
883 LDAPMessage *result = NULL;
884 LDAPMessage *entry = NULL;
890 char buffer[MAX_FILTER_STR_LEN];
892 if (strchr(fmt, '%') != NULL) {
893 if (!radius_xlat(buffer, sizeof(buffer), fmt, request,
894 ldap_escape_func, NULL)) {
896 "rlm_ldap (%s): Unable to create LDAP URL",
905 if (!ldap_is_ldap_url(url)) {
906 radlog(L_ERR, "rlm_ldap (%s): String passed does not look "
907 "like an LDAP URL", inst->xlat_name);
911 if (ldap_url_parse(url, &ldap_url)){
912 radlog(L_ERR, "rlm_ldap (%s): Parsing LDAP URL failed",
918 * Nothing, empty string, "*" string, or got 2 things, die.
920 if (!ldap_url->lud_attrs || !ldap_url->lud_attrs[0] ||
921 !*ldap_url->lud_attrs[0] ||
922 (strcmp(ldap_url->lud_attrs[0], "*") == 0) ||
923 ldap_url->lud_attrs[1]) {
924 radlog(L_ERR, "rlm_ldap (%s): Bad attributes list in LDAP "
925 "URL. URL must specify exactly one attribute to "
932 if (ldap_url->lud_host &&
933 ((strncmp(inst->server, ldap_url->lud_host,
934 strlen(inst->server)) != 0) ||
935 (ldap_url->lud_port != inst->port))) {
936 RDEBUG("Requested server/port is \"%s:%i\"", ldap_url->lud_host,
942 conn = ldap_get_socket(inst);
943 if (!conn) goto free_urldesc;
945 memcpy(&attrs, &ldap_url->lud_attrs, sizeof(attrs));
947 rcode = perform_search(inst, request, &conn, ldap_url->lud_dn,
948 ldap_url->lud_scope, ldap_url->lud_filter, attrs,
952 RDEBUG("Search returned not found", inst->xlat_name);
959 entry = ldap_first_entry(conn->handle, result);
961 ldap_get_option(conn->handle, LDAP_OPT_RESULT_CODE,
963 radlog(L_ERR, "rlm_ldap (%s): Failed retrieving entry: %s",
965 ldap_err2string(ldap_errno));
969 vals = ldap_get_values(conn->handle, entry, ldap_url->lud_attrs[0]);
971 RDEBUG("No \"%s\" attributes found in specified object",
972 inst->xlat_name, ldap_url->lud_attrs[0]);
976 length = strlen(vals[0]);
977 if (length >= freespace){
982 strlcpy(out, vals[0], freespace);
985 ldap_value_free(vals);
987 ldap_msgfree(result);
989 ldap_release_socket(inst, conn);
991 ldap_free_urldesc(ldap_url);
997 static char *get_userdn(LDAP_CONN **pconn, REQUEST *request,
998 rlm_rcode_t *module_rcode)
1002 ldap_instance *inst = (*pconn)->inst;
1003 LDAPMessage *result, *entry;
1005 static char firstattr[] = "uid";
1007 const char *attrs[] = {firstattr, NULL};
1008 char filter[MAX_FILTER_STR_LEN];
1009 char basedn[MAX_FILTER_STR_LEN];
1011 *module_rcode = RLM_MODULE_FAIL;
1013 vp = pairfind(request->config_items, PW_LDAP_USERDN, 0, TAG_ANY);
1015 *module_rcode = RLM_MODULE_OK;
1016 return vp->vp_strvalue;
1019 if (!radius_xlat(filter, sizeof(filter), inst->filter,
1020 request, ldap_escape_func, NULL)) {
1021 radlog(L_ERR, "rlm_ldap (%s): Unable to create filter",
1023 *module_rcode = RLM_MODULE_INVALID;
1027 if (!radius_xlat(basedn, sizeof(basedn), inst->basedn,
1028 request, ldap_escape_func, NULL)) {
1029 radlog(L_ERR, "rlm_ldap (%s): Unable to create basedn",
1031 *module_rcode = RLM_MODULE_INVALID;
1035 rcode = perform_search(inst, request, pconn, basedn, LDAP_SCOPE_SUBTREE,
1036 filter, attrs, &result);
1039 *module_rcode = RLM_MODULE_NOTFOUND;
1045 if ((entry = ldap_first_entry((*pconn)->handle, result)) == NULL) {
1046 ldap_get_option((*pconn)->handle, LDAP_OPT_RESULT_CODE,
1048 radlog(L_ERR, "rlm_ldap (%s): Failed retrieving entry: %s",
1050 ldap_err2string(ldap_errno));
1051 ldap_msgfree(result);
1055 if ((user_dn = ldap_get_dn((*pconn)->handle, entry)) == NULL) {
1056 ldap_get_option((*pconn)->handle, LDAP_OPT_RESULT_CODE,
1058 radlog(L_ERR, "rlm_ldap (%s): ldap_get_dn() failed: %s",
1060 ldap_err2string(ldap_errno));
1062 ldap_msgfree(result);
1066 vp = pairmake("LDAP-UserDn", user_dn, T_OP_EQ);
1068 ldap_memfree(user_dn);
1069 ldap_msgfree(result);
1073 *module_rcode = RLM_MODULE_OK;
1075 pairadd(&request->config_items, vp);
1076 ldap_memfree(user_dn);
1077 ldap_msgfree(result);
1079 return vp->vp_strvalue;
1083 /** Perform LDAP-Group comparison checking
1086 static int ldap_groupcmp(void *instance, REQUEST *request,
1087 UNUSED VALUE_PAIR *thing, VALUE_PAIR *check,
1088 UNUSED VALUE_PAIR *check_pairs,
1089 UNUSED VALUE_PAIR **reply_pairs)
1091 ldap_instance *inst = instance;
1092 int i, rcode, found;
1093 rlm_rcode_t module_rcode;
1094 LDAPMessage *result = NULL;
1095 LDAPMessage *entry = NULL;
1097 int check_is_dn = FALSE, value_is_dn = FALSE;
1098 static char firstattr[] = "dn";
1099 const char *attrs[] = {firstattr, NULL};
1101 const char *group_attrs[] = {inst->groupmemb_attr, NULL};
1105 char gr_filter[MAX_FILTER_STR_LEN];
1106 char filter[MAX_FILTER_STR_LEN];
1107 char basedn[MAX_FILTER_STR_LEN];
1109 RDEBUG("Searching for user in group \"%s\"", check->vp_strvalue);
1111 if (check->length == 0) {
1112 RDEBUG("Cannot do comparison (group name is empty)");
1116 conn = ldap_get_socket(inst);
1117 if (!conn) return 1;
1120 * This is used in the default membership filter.
1122 user_dn = get_userdn(&conn, request, &module_rcode);
1124 ldap_release_socket(inst, conn);
1128 if (!inst->groupmemb_filter) goto check_attr;
1130 if (!radius_xlat(gr_filter, sizeof(gr_filter),
1131 inst->groupmemb_filter, request, ldap_escape_func,
1133 radlog(L_ERR, "rlm_ldap (%s): Failed creating group filter",
1139 * If it's a DN, use that.
1141 check_is_dn = strchr(check->vp_strvalue,',') == NULL ? FALSE : TRUE;
1144 strlcpy(filter, gr_filter, sizeof(filter));
1145 strlcpy(basedn, check->vp_strvalue, sizeof(basedn));
1147 snprintf(filter, sizeof(filter), "(&(%s=%s)%s)",
1148 inst->groupname_attr,
1149 check->vp_strvalue, gr_filter);
1152 * get_userdn does this, too. Oh well.
1154 if (!radius_xlat(basedn, sizeof(basedn), inst->basedn,
1155 request, ldap_escape_func, NULL)) {
1156 radlog(L_ERR, "rlm_ldap (%s): Failed creating basedn",
1162 rcode = perform_search(inst, request, &conn, basedn, LDAP_SCOPE_SUBTREE,
1163 filter, attrs, &result);
1165 ldap_release_socket(inst, conn);
1166 ldap_msgfree(result);
1168 RDEBUG("User found in group object");
1174 ldap_release_socket(inst, conn);
1178 /* else the search returned -2, for "not found" */
1181 * Else the search returned NOTFOUND. See if we're
1182 * configured to search for group membership using user
1185 if (!inst->groupmemb_attr) {
1186 ldap_release_socket(inst, conn);
1187 RDEBUG("Group object \"%s\" not found, or user is not a member",
1188 check->vp_strvalue);
1193 RDEBUG2("Checking user object membership (%s) attributes",
1194 inst->groupmemb_attr);
1196 snprintf(filter ,sizeof(filter), "(objectclass=*)");
1198 rcode = perform_search(inst, request, &conn, user_dn, LDAP_SCOPE_BASE,
1199 filter, group_attrs, &result);
1202 RDEBUG("Can't check membership attributes, user object "
1205 ldap_release_socket(inst, conn);
1209 entry = ldap_first_entry(conn->handle, result);
1211 ldap_get_option(conn->handle, LDAP_OPT_RESULT_CODE,
1213 radlog(L_ERR, "rlm_ldap (%s): Failed retrieving entry: %s",
1215 ldap_err2string(ldap_errno));
1217 ldap_release_socket(inst, conn);
1218 ldap_msgfree(result);
1222 vals = ldap_get_values(conn->handle, entry, inst->groupmemb_attr);
1224 RDEBUG("No group membership attribute(s) found in user object");
1225 ldap_release_socket(inst, conn);
1226 ldap_msgfree(result);
1231 * Loop over the list of groups the user is a member of,
1232 * looking for a match.
1235 for (i = 0; i < ldap_count_values(vals); i++) {
1236 LDAPMessage *gr_result = NULL;
1238 value_is_dn = strchr(vals[i], ',') == NULL ? FALSE : TRUE;
1240 RDEBUG2("Processing group membership value \"%s\"", vals[i]);
1243 * Both literal group names, do case sensitive comparison
1245 if (!check_is_dn && !value_is_dn) {
1246 if (strcmp(vals[i], check->vp_strvalue) == 0){
1247 RDEBUG("User found (membership value matches "
1258 * Both DNs, do case insensitive comparison
1260 if (check_is_dn && value_is_dn) {
1261 if (strcasecmp(vals[i], check->vp_strvalue) == 0){
1262 RDEBUG("User found (membership DN matches "
1273 * If the value is not a DN, or the check item is a DN
1274 * there's nothing more we can do.
1276 if (!value_is_dn && check_is_dn) continue;
1279 * We have a value which is a DN, and a check item which
1280 * specifies the name of a group, search using the value
1281 * DN for the group, and see if it has a groupname_attr
1282 * which matches our check val.
1284 RDEBUG2("Searching with membership DN and group name");
1286 snprintf(filter,sizeof(filter), "(%s=%s)",
1287 inst->groupname_attr, check->vp_strvalue);
1289 rcode = perform_search(inst, request, &conn, vals[i],
1290 LDAP_SCOPE_BASE, filter, attrs,
1293 ldap_msgfree(gr_result);
1295 /* Error occurred */
1297 ldap_value_free(vals);
1298 ldap_msgfree(result);
1299 ldap_release_socket(inst, conn);
1304 * Either the group DN wasn't found, or it didn't have the
1305 * correct name. Continue looping over the attributes.
1308 ldap_msgfree(gr_result);
1314 RDEBUG("User found (group name in membership DN matches check "
1320 ldap_value_free(vals);
1321 ldap_msgfree(result);
1322 ldap_release_socket(inst, conn);
1325 RDEBUG("User is not a member of specified group");
1332 /** Detach from the LDAP server and cleanup internal state.
1335 static int ldap_detach(void *instance)
1337 ldap_instance *inst = instance;
1339 fr_connection_pool_delete(inst->pool);
1341 if (inst->user_map) {
1342 radius_mapfree(&inst->user_map);
1348 static int parse_sub_section(CONF_SECTION *parent,
1349 ldap_instance *inst,
1350 ldap_acct_section_t **config,
1351 rlm_components_t comp)
1355 const char *name = section_type_value[comp].section;
1357 cs = cf_section_sub_find(parent, name);
1359 radlog(L_INFO, "rlm_ldap (%s): Couldn't find configuration for "
1360 "%s, will return NOOP for calls from this section",
1361 inst->xlat_name, name);
1366 *config = talloc_zero(inst, ldap_acct_section_t);
1367 if (cf_section_parse(cs, *config, acct_section_config) < 0) {
1368 radlog(L_ERR, "rlm_ldap (%s): Failed parsing configuration for "
1369 "section %s", inst->xlat_name, name);
1378 static int ldap_map_verify(ldap_instance *inst, value_pair_map_t **head)
1380 value_pair_map_t *map;
1382 if (radius_attrmap(inst->cs, head, PAIR_LIST_REPLY,
1383 PAIR_LIST_REQUEST, MAX_ATTRMAP) < 0) {
1387 * Attrmap only performs some basic validation checks, we need
1388 * to do rlm_ldap specific checks here.
1390 for (map = *head; map != NULL; map = map->next) {
1391 if (map->dst->type != VPT_TYPE_ATTR) {
1392 cf_log_err(map->ci, "Left operand must be an "
1398 if (map->src->type == VPT_TYPE_LIST) {
1399 cf_log_err(map->ci, "Right operand must not be "
1405 switch (map->src->type)
1408 * Only =, :=, += and -= operators are supported for
1411 case VPT_TYPE_LITERAL:
1422 cf_log_err(map->ci, "Operator \"%s\" not "
1423 "allowed for %s values",
1424 fr_int2str(fr_tokens, map->op,
1426 fr_int2str(vpt_types, map->src->type,
1438 * Uses section of radiusd config file passed as parameter to create an
1439 * instance of the module.
1441 static int ldap_instantiate(CONF_SECTION * conf, void **instance)
1443 ldap_instance *inst;
1445 *instance = inst = talloc_zero(conf, ldap_instance);
1446 if (!inst) return -1;
1450 inst->chase_referrals = 2; /* use OpenLDAP defaults */
1453 inst->xlat_name = cf_section_name2(conf);
1454 if (!inst->xlat_name) {
1455 inst->xlat_name = cf_section_name1(conf);
1459 * If the configuration parameters can't be parsed, then fail.
1461 if ((cf_section_parse(conf, inst, module_config) < 0) ||
1462 (parse_sub_section(conf, inst,
1464 RLM_COMPONENT_ACCT) < 0) ||
1465 (parse_sub_section(conf, inst,
1467 RLM_COMPONENT_POST_AUTH) < 0)) {
1468 radlog(L_ERR, "rlm_ldap (%s): Failed parsing configuration",
1473 if (inst->server == NULL) {
1474 radlog(L_ERR, "rlm_ldap (%s): Missing 'server' directive",
1480 * Check for URLs. If they're used and the library doesn't
1481 * support them, then complain.
1484 if (ldap_is_ldap_url(inst->server)) {
1485 #ifdef HAVE_LDAP_INITIALIZE
1489 radlog(L_ERR, "rlm_ldap (%s): 'server' directive is in URL "
1490 "form but ldap_initialize() is not available",
1496 /* workaround for servers which support LDAPS but not START TLS */
1497 if (inst->port == LDAPS_PORT || inst->tls_mode) {
1498 inst->tls_mode = LDAP_OPT_X_TLS_HARD;
1503 #if LDAP_SET_REBIND_PROC_ARGS != 3
1505 * The 2-argument rebind doesn't take an instance
1506 * variable. Our rebind function needs the instance
1507 * variable for the username, password, etc.
1509 if (inst->rebind == 1) {
1510 radlog(L_ERR, "rlm_ldap (%s): Cannot use 'rebind' directive "
1511 "as this version of libldap does not support the API "
1512 "that we need", inst->xlat-name);
1518 * Build the attribute map
1520 if (ldap_map_verify(inst, &(inst->user_map)) < 0) {
1525 * Group comparison checks.
1527 paircompare_register(PW_LDAP_GROUP, PW_USER_NAME, ldap_groupcmp, inst);
1528 if (cf_section_name2(conf)) {
1529 const DICT_ATTR *da;
1533 snprintf(buffer, sizeof(buffer), "%s-Ldap-Group",
1535 memset(&flags, 0, sizeof(flags));
1537 dict_addattr(buffer, -1, 0, PW_TYPE_STRING, flags);
1538 da = dict_attrbyname(buffer);
1540 radlog(L_ERR, "rlm_ldap (%s): Failed creating "
1541 "attribute %s", inst->xlat_name, buffer);
1545 paircompare_register(da->attr, PW_USER_NAME, ldap_groupcmp,
1549 xlat_register(inst->xlat_name, ldap_xlat, inst);
1552 * Initialize the socket pool.
1554 inst->pool = fr_connection_pool_init(inst->cs, inst,
1570 static int check_access(ldap_instance *inst, REQUEST* request, LDAP_CONN *conn,
1576 vals = ldap_get_values(conn->handle, entry, inst->access_attr);
1578 if (inst->positive_access_attr) {
1579 if (strncmp(vals[0], "FALSE", 5) == 0) {
1580 RDEBUG("Dialup access disabled");
1587 RDEBUG("\"%s\" attribute exists - access denied by"
1588 " default", inst->access_attr);
1591 ldap_value_free(vals);
1593 } else if (inst->positive_access_attr) {
1594 RDEBUG("No %s attribute - access denied by default",
1605 static VALUE_PAIR *ldap_getvalue(REQUEST *request, const value_pair_map_t *map,
1608 rlm_ldap_result_t *self = ctx;
1609 VALUE_PAIR *head, **tail, *vp;
1618 * Iterate over all the retrieved values,
1619 * don't try and be clever about changing operators
1620 * just use whatever was set in the attribute map.
1622 for (i = 0; i < self->count; i++) {
1623 vp = pairalloc(NULL, map->dst->da);
1626 pairparsevalue(vp, self->values[i]);
1636 static void xlat_attrsfree(const xlat_attrs_t *expanded)
1638 const value_pair_map_t *map;
1639 unsigned int total = 0;
1643 for (map = expanded->maps; map != NULL; map = map->next)
1645 name = expanded->attrs[total++];
1648 switch (map->src->type)
1661 static int xlat_attrs(REQUEST *request, const value_pair_map_t *maps,
1662 xlat_attrs_t *expanded)
1664 const value_pair_map_t *map;
1665 unsigned int total = 0;
1670 VALUE_PAIR *found, **from = NULL;
1673 for (map = maps; map != NULL; map = map->next)
1675 switch (map->src->type)
1678 buffer = rad_malloc(MAX_ATTR_STR_LEN);
1679 len = radius_xlat(buffer, MAX_ATTR_STR_LEN,
1680 map->src->name, request, NULL, NULL);
1683 RDEBUG("Expansion of LDAP attribute "
1684 "\"%s\" failed", map->src->name);
1689 expanded->attrs[total++] = buffer;
1695 if (radius_request(&context, map->src->request) == 0) {
1696 from = radius_list(context, map->src->list);
1698 if (!from) continue;
1700 found = pairfind(*from, map->src->da->attr,
1701 map->src->da->vendor, TAG_ANY);
1702 if (!found) continue;
1704 buffer = rad_malloc(MAX_ATTR_STR_LEN);
1705 strlcpy(buffer, found->vp_strvalue, MAX_ATTR_STR_LEN);
1707 expanded->attrs[total++] = buffer;
1710 case VPT_TYPE_LITERAL:
1711 expanded->attrs[total++] = map->src->name;
1716 expanded->attrs[total] = NULL;
1718 xlat_attrsfree(expanded);
1725 expanded->attrs[total] = NULL;
1726 expanded->maps = maps;
1732 /** Convert attribute map into valuepairs
1734 * Use the attribute map built earlier to convert LDAP values into valuepairs
1735 * and insert them into whichever list they need to go into.
1737 * This is *NOT* atomic, but there's no condition in which we should error
1740 static void do_attrmap(UNUSED ldap_instance *inst, REQUEST *request,
1741 LDAP *handle, const xlat_attrs_t *expanded,
1744 const value_pair_map_t *map;
1745 unsigned int total = 0;
1747 rlm_ldap_result_t result;
1750 for (map = expanded->maps; map != NULL; map = map->next)
1752 name = expanded->attrs[total++];
1754 result.values = ldap_get_values(handle, entry, name);
1755 if (!result.values) {
1756 RDEBUG2("Attribute \"%s\" not found in LDAP object",
1763 * Find out how many values there are for the
1764 * attribute and extract all of them.
1766 result.count = ldap_count_values(result.values);
1769 * If something bad happened, just skip, this is probably
1770 * a case of the dst being incorrect for the current
1773 if (radius_map2request(request, map, name, ldap_getvalue,
1780 ldap_value_free(result.values);
1785 static void do_check_reply(ldap_instance *inst, REQUEST *request)
1788 * More warning messages for people who can't be bothered
1789 * to read the documentation.
1791 if (inst->expect_password && (debug_flag > 1)) {
1792 if (!pairfind(request->config_items, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY) &&
1793 !pairfind(request->config_items, PW_NT_PASSWORD, 0, TAG_ANY) &&
1794 !pairfind(request->config_items, PW_USER_PASSWORD, 0, TAG_ANY) &&
1795 !pairfind(request->config_items, PW_PASSWORD_WITH_HEADER, 0, TAG_ANY) &&
1796 !pairfind(request->config_items, PW_CRYPT_PASSWORD, 0, TAG_ANY)) {
1797 RDEBUGW("No \"known good\" password "
1798 "was found in LDAP. Are you sure that "
1799 "the user is configured correctly?");
1805 static void apply_profile(ldap_instance *inst, REQUEST *request,
1806 LDAP_CONN **pconn, const char *profile,
1807 const xlat_attrs_t *expanded)
1810 LDAPMessage *result, *entry;
1812 LDAP *handle = (*pconn)->handle;
1813 char filter[MAX_FILTER_STR_LEN];
1815 if (!profile || !*profile) return;
1817 strlcpy(filter, inst->base_filter, sizeof(filter));
1819 rcode = perform_search(inst, request, pconn, profile, LDAP_SCOPE_BASE,
1820 filter, expanded->attrs, &result);
1824 RDEBUG("Profile \"%s\" not found", profile);
1829 entry = ldap_first_entry(handle, result);
1831 ldap_get_option(handle, LDAP_OPT_RESULT_CODE,
1833 radlog(L_ERR, "rlm_ldap (%s): Failed retrieving entry: %s",
1835 ldap_err2string(ldap_errno));
1840 do_attrmap(inst, request, handle, expanded, entry);
1843 ldap_msgfree(result);
1847 /** Check if user is authorized for remote access
1850 static rlm_rcode_t ldap_authorize(void *instance, REQUEST * request)
1853 int module_rcode = RLM_MODULE_OK;
1854 ldap_instance *inst = instance;
1855 char *user_dn = NULL;
1859 LDAPMessage *result, *entry;
1861 char filter[MAX_FILTER_STR_LEN];
1862 char basedn[MAX_FILTER_STR_LEN];
1863 xlat_attrs_t expanded; /* faster that mallocing every time */
1865 if (!request->username) {
1866 RDEBUG2("Attribute \"User-Name\" is required for "
1868 return RLM_MODULE_NOOP;
1872 * Check for valid input, zero length names not permitted
1874 if (request->username->length == 0) {
1875 RDEBUG2("Zero length username not permitted");
1876 return RLM_MODULE_INVALID;
1879 if (!radius_xlat(filter, sizeof(filter), inst->filter,
1880 request, ldap_escape_func, NULL)) {
1881 radlog(L_ERR, "rlm_ldap (%s): Failed creating filter",
1883 return RLM_MODULE_INVALID;
1886 if (!radius_xlat(basedn, sizeof(basedn), inst->basedn,
1887 request, ldap_escape_func, NULL)) {
1888 radlog(L_ERR, "rlm_ldap (%s): Failed creating basedn",
1890 return RLM_MODULE_INVALID;
1893 if (xlat_attrs(request, inst->user_map, &expanded) < 0) {
1894 return RLM_MODULE_FAIL;
1898 conn = ldap_get_socket(inst);
1899 if (!conn) return RLM_MODULE_FAIL;
1901 rcode = perform_search(inst, request, &conn, basedn,
1902 LDAP_SCOPE_SUBTREE, filter, expanded.attrs,
1907 module_failure_msg(request,
1908 "rlm_ldap (%s): User object not "
1912 RDEBUG("User object not found", inst->xlat_name);
1914 module_rcode = RLM_MODULE_NOTFOUND;
1921 entry = ldap_first_entry(conn->handle, result);
1923 ldap_get_option(conn->handle, LDAP_OPT_RESULT_CODE,
1925 radlog(L_ERR, "rlm_ldap (%s): Failed retrieving entry: %s",
1927 ldap_err2string(ldap_errno));
1932 user_dn = ldap_get_dn(conn->handle, entry);
1934 ldap_get_option(conn->handle, LDAP_OPT_RESULT_CODE,
1936 radlog(L_ERR, "rlm_ldap (%s): ldap_get_dn() failed: %s",
1938 ldap_err2string(ldap_errno));
1942 RDEBUG2("User found at DN \"%s\"", user_dn);
1944 * Adding attribute containing the Users' DN.
1946 pairadd(&request->config_items,
1947 pairmake("Ldap-UserDn", user_dn, T_OP_EQ));
1951 * We already have a Cleartext-Password. Skip edir.
1953 if (inst->edir && pairfind(request->config_items, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) {
1958 * Retrieve Universal Password if we use eDirectory
1965 bufsize = sizeof(buffer);
1967 /* retrive universal password */
1968 res = nmasldap_get_password(conn->handle, user_dn,
1971 RDEBUG2("Failed to retrieve eDirectory password. Check "
1972 "your configuration !");
1973 module_rcode = RLM_MODULE_NOOP;
1977 /* Add Cleartext-Password attribute to the request */
1978 vp = radius_paircreate(request, &request->config_items,
1979 PW_CLEARTEXT_PASSWORD, 0);
1980 strlcpy(vp->vp_strvalue, buffer, sizeof(vp->vp_strvalue));
1981 vp->length = strlen(vp->vp_strvalue);
1983 RDEBUG2("Added eDirectory password in check items as %s = %s",
1984 vp->da->name, vp->vp_strvalue);
1986 if (inst->edir_autz) {
1987 RDEBUG2("Binding as user for eDirectory authorization "
1992 conn->rebound = TRUE;
1993 module_rcode = ldap_bind_wrapper(&conn, user_dn,
1996 if (module_rcode != RLM_MODULE_OK) {
2000 RDEBUG("Bind as user \"%s\" was successful", user_dn);
2010 if (inst->access_attr) {
2011 if (check_access(inst, request, conn, entry) < 0) {
2012 module_rcode = RLM_MODULE_USERLOCK;
2018 * Apply ONE user profile, or a default user profile.
2020 vp = pairfind(request->config_items, PW_USER_PROFILE, 0, TAG_ANY);
2021 if (vp || inst->default_profile) {
2022 char *profile = inst->default_profile;
2024 if (vp) profile = vp->vp_strvalue;
2026 apply_profile(inst, request, &conn, profile, &expanded);
2030 * Apply a SET of user profiles.
2032 if (inst->profile_attr) {
2033 vals = ldap_get_values(conn->handle, entry, inst->profile_attr);
2037 for (i = 0; (vals[i] != NULL) && (*vals[i] != '\0');
2039 apply_profile(inst, request, &conn, vals[i],
2043 ldap_value_free(vals);
2047 if (inst->user_map) {
2048 do_attrmap(inst, request, conn->handle, &expanded, entry);
2049 do_check_reply(inst, request);
2053 if (user_dn) ldap_memfree(user_dn);
2054 xlat_attrsfree(&expanded);
2055 ldap_msgfree(result);
2057 ldap_release_socket(inst, conn);
2059 return module_rcode;
2063 /** Check the user's password against ldap database
2066 static rlm_rcode_t ldap_authenticate(void *instance, REQUEST * request)
2068 rlm_rcode_t module_rcode;
2069 const char *user_dn;
2070 ldap_instance *inst = instance;
2074 * Ensure that we're being passed a plain-text password, and not
2078 if (!request->username) {
2079 radlog(L_AUTH, "rlm_ldap (%s): Attribute \"User-Name\" is "
2080 "required for authentication", inst->xlat_name);
2081 return RLM_MODULE_INVALID;
2084 if (!request->password) {
2085 radlog(L_AUTH, "rlm_ldap (%s): Attribute \"User-Password\" "
2086 "is required for authentication.", inst->xlat_name);
2087 RDEBUG2(" You have set \"Auth-Type := LDAP\" somewhere.");
2088 RDEBUG2(" *********************************************");
2089 RDEBUG2(" * THAT CONFIGURATION IS WRONG. DELETE IT. ");
2090 RDEBUG2(" * YOU ARE PREVENTING THE SERVER FROM WORKING.");
2091 RDEBUG2(" *********************************************");
2092 return RLM_MODULE_INVALID;
2095 if (request->password->da->attr != PW_USER_PASSWORD) {
2096 radlog(L_AUTH, "rlm_ldap (%s): Attribute \"User-Password\" "
2097 "is required for authentication. Cannot use \"%s\".",
2098 inst->xlat_name, request->password->da->name);
2099 return RLM_MODULE_INVALID;
2102 if (request->password->length == 0) {
2103 module_failure_msg(request,
2104 "rlm_ldap (%s): Empty password supplied",
2106 return RLM_MODULE_INVALID;
2109 RDEBUG("Login attempt by \"%s\" with password \"%s\"",
2110 request->username->vp_strvalue, request->password->vp_strvalue);
2112 conn = ldap_get_socket(inst);
2113 if (!conn) return RLM_MODULE_FAIL;
2116 * Get the DN by doing a search.
2118 user_dn = get_userdn(&conn, request, &module_rcode);
2120 ldap_release_socket(inst, conn);
2121 return module_rcode;
2127 conn->rebound = TRUE;
2128 module_rcode = ldap_bind_wrapper(&conn, user_dn,
2129 request->password->vp_strvalue,
2131 if (module_rcode == RLM_MODULE_OK) {
2132 RDEBUG("Bind as user \"%s\" was successful", user_dn);
2135 ldap_release_socket(inst, conn);
2136 return module_rcode;
2139 /** Modify user's object in LDAP
2142 static rlm_rcode_t user_modify(ldap_instance *inst, REQUEST *request,
2143 ldap_acct_section_t *section)
2145 rlm_rcode_t module_rcode = RLM_MODULE_OK;
2146 int ldap_errno, rcode, msg_id;
2147 LDAPMessage *result = NULL;
2149 LDAP_CONN *conn = NULL;
2151 LDAPMod *mod_p[MAX_ATTRMAP + 1], mod_s[MAX_ATTRMAP];
2152 LDAPMod **modify = mod_p;
2154 char *passed[MAX_ATTRMAP * 2];
2155 int i, total = 0, last_pass = 0;
2157 char *expanded[MAX_ATTRMAP];
2165 const char *user_dn;
2168 * Build our set of modifications using the update sections in
2175 char path[MAX_STRING_LEN];
2179 rad_assert(section);
2182 * Locate the update section were going to be using
2184 if (section->reference[0] != '.') {
2188 if (!radius_xlat(p, (sizeof(path) - (p - path)) - 1,
2189 section->reference, request, NULL, NULL)) {
2193 ci = cf_reference_item(NULL, section->cs, path);
2198 if (!cf_item_is_section(ci)){
2199 radlog(L_ERR, "rlm_ldap (%s): Reference must resolve to a "
2200 "section", inst->xlat_name);
2205 cs = cf_section_sub_find(cf_itemtosection(ci), "update");
2207 radlog(L_ERR, "rlm_ldap (%s): Section must contain 'update' "
2215 * Iterate over all the pairs, building our mods array
2217 for (ci = cf_item_find_next(cs, NULL);
2219 ci = cf_item_find_next(cs, ci)) {
2220 int do_xlat = FALSE;
2222 if (total == MAX_ATTRMAP) {
2223 radlog(L_ERR, "rlm_ldap (%s): Modify map size exceeded",
2229 if (!cf_item_is_pair(ci)) {
2230 radlog(L_ERR, "rlm_ldap (%s): Entry is not in "
2231 "\"ldap-attribute = value\" format",
2238 * Retrieve all the information we need about the pair
2240 cp = cf_itemtopair(ci);
2241 value = cf_pair_value(cp);
2242 attr = cf_pair_attr(cp);
2243 op = cf_pair_operator(cp);
2245 if ((value == NULL) || (*value == '\0')) {
2246 RDEBUG("empty value string, "
2247 "skipping attribute \"%s\"", attr);
2252 switch (cf_pair_value_type(cp))
2255 case T_SINGLE_QUOTED_STRING:
2257 case T_BACK_QUOTED_STRING:
2258 case T_DOUBLE_QUOTED_STRING:
2266 if (op == T_OP_CMP_FALSE) {
2267 passed[last_pass] = NULL;
2268 } else if (do_xlat) {
2269 p = rad_malloc(1024);
2270 if (radius_xlat(p, 1024, value, request, NULL, NULL) <= 0) {
2271 RDEBUG("xlat failed or empty value string, "
2272 "skipping attribute \"%s\"", attr);
2279 expanded[last_exp++] = p;
2280 passed[last_pass] = p;
2285 memcpy(&(passed[last_pass]), &value,
2286 sizeof(passed[last_pass]));
2289 passed[last_pass + 1] = NULL;
2291 mod_s[total].mod_values = &(passed[last_pass]);
2298 * T_OP_EQ is *NOT* supported, it is impossible to
2299 * support because of the lack of transactions in LDAP
2302 mod_s[total].mod_op = LDAP_MOD_ADD;
2306 mod_s[total].mod_op = LDAP_MOD_REPLACE;
2310 case T_OP_CMP_FALSE:
2311 mod_s[total].mod_op = LDAP_MOD_DELETE;
2314 #ifdef LDAP_MOD_INCREMENT
2316 mod_s[total].mod_op = LDAP_MOD_INCREMENT;
2320 radlog(L_ERR, "rlm_ldap (%s): Operator '%s' "
2321 "is not supported for LDAP modify "
2322 "operations", inst->xlat_name,
2323 fr_int2str(fr_tokens, op, "¿unknown?"));
2329 * Now we know the value is ok, copy the pointers into
2330 * the ldapmod struct.
2332 memcpy(&(mod_s[total].mod_type), &(attr),
2333 sizeof(mod_s[total].mod_type));
2335 mod_p[total] = &(mod_s[total]);
2340 module_rcode = RLM_MODULE_NOOP;
2344 mod_p[total] = NULL;
2346 conn = ldap_get_socket(inst);
2347 if (!conn) return RLM_MODULE_FAIL;
2350 * Perform all modifications as the default admin user.
2352 if (conn->rebound) {
2353 ldap_errno = ldap_bind_wrapper(&conn, inst->login,
2354 inst->password, TRUE);
2355 if (ldap_errno != RLM_MODULE_OK) {
2359 rad_assert(conn != NULL);
2360 conn->rebound = FALSE;
2363 user_dn = get_userdn(&conn, request, &module_rcode);
2365 module_rcode = RLM_MODULE_NOTFOUND;
2369 RDEBUG2("Modifying user object with DN \"%s\"", user_dn);
2371 ldap_errno = ldap_modify_ext(conn->handle, user_dn, modify, NULL, NULL,
2373 if (ldap_errno != LDAP_SUCCESS) {
2374 switch (process_ldap_errno(inst, &conn, "Modify"))
2376 case LDAP_PROC_SUCCESS:
2378 case LDAP_PROC_REJECT:
2379 case LDAP_PROC_ERROR:
2381 case LDAP_PROC_RETRY:
2388 DEBUG3("rlm_ldap (%s): Waiting for modify result...", inst->xlat_name);
2390 tv.tv_sec = inst->timeout;
2394 rcode = ldap_result(conn->handle, msg_id, 1, &tv, &result);
2395 ldap_msgfree(result);
2397 switch (process_ldap_errno(inst, &conn, "Modify"))
2399 case LDAP_PROC_SUCCESS:
2401 case LDAP_PROC_REJECT:
2402 case LDAP_PROC_ERROR:
2404 module_rcode = RLM_MODULE_FAIL;
2406 case LDAP_PROC_RETRY:
2413 RDEBUG2("Modification successful!");
2417 * Free up any buffers we allocated for xlat expansion
2419 for (i = 0; i < last_exp; i++) {
2424 ldap_release_socket(inst, conn);
2426 return module_rcode;
2430 static rlm_rcode_t ldap_accounting(void *instance, REQUEST * request) {
2431 ldap_instance *inst = instance;
2433 if (inst->accounting) {
2434 return user_modify(inst, request, inst->accounting);
2437 return RLM_MODULE_NOOP;
2441 /** Check the user's password against ldap database
2444 static rlm_rcode_t ldap_postauth(void *instance, REQUEST * request)
2446 ldap_instance *inst = instance;
2448 if (inst->postauth) {
2449 return user_modify(inst, request, inst->postauth);
2452 return RLM_MODULE_NOOP;
2456 /* globally exported name */
2457 module_t rlm_ldap = {
2460 RLM_TYPE_THREAD_SAFE, /* type: reserved */
2461 ldap_instantiate, /* instantiation */
2462 ldap_detach, /* detach */
2464 ldap_authenticate, /* authentication */
2465 ldap_authorize, /* authorization */
2466 NULL, /* preaccounting */
2467 ldap_accounting, /* accounting */
2468 NULL, /* checksimul */
2469 NULL, /* pre-proxy */
2470 NULL, /* post-proxy */
2471 ldap_postauth /* post-auth */