/*
- * rlm_ldap.c LDAP authorization and authentication module.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2 if the
+ * License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * $Id$
+ * @file rlm_ldap.c
+ * @brief LDAP authorization and authentication module.
*
- * Copyright 1999-2012 The FreeRADIUS Server Project.
- *
- * Copyright 2012 Alan DeKok <aland@freeradius.org>
- * Copyright 2012 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
+ * @copyright 1999-2013 The FreeRADIUS Server Project.
+ * @copyright 2012 Alan DeKok <aland@freeradius.org>
+ * @copyright 2012-2013 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
*/
-
#include <freeradius-devel/ident.h>
RCSID("$Id$")
int count;
} rlm_ldap_result_t;
-#define LDAP_PROC_SUCCESS 0
-#define LDAP_PROC_ERROR -1
-#define LDAP_PROC_RETRY -2
-#define LDAP_PROC_REJECT -3
+typedef enum {
+ LDAP_PROC_SUCCESS = 0,
+ LDAP_PROC_ERROR = -1,
+ LDAP_PROC_RETRY = -2,
+ LDAP_PROC_REJECT = -3
+} ldap_rcode_t;
-static int process_ldap_errno(ldap_instance *inst, LDAP_CONN **pconn,
+static ldap_rcode_t process_ldap_errno(ldap_instance *inst, LDAP_CONN **pconn,
const char *operation)
{
- int ldap_errno;
+ int ldap_errno;
ldap_get_option((*pconn)->handle, LDAP_OPT_ERROR_NUMBER,
&ldap_errno);
case LDAP_NO_SUCH_OBJECT:
return LDAP_PROC_SUCCESS;
- case LDAP_SERVER_DOWN:
- do_reconnect:
- *pconn = fr_connection_reconnect(inst->pool, *pconn);
- if (!*pconn) return -1;
- return LDAP_PROC_RETRY;
-
case LDAP_INSUFFICIENT_ACCESS:
radlog(L_ERR, "rlm_ldap (%s): %s failed: Insufficient access. "
"Check the identity and password configuration "
case LDAP_TIMELIMIT_EXCEEDED:
exec_trigger(NULL, inst->cs, "modules.ldap.timeout", TRUE);
+ /* FALL-THROUGH */
case LDAP_BUSY:
case LDAP_UNAVAILABLE:
*/
radlog(L_ERR, "rlm_ldap (%s): %s failed: %s",
inst->xlat_name, operation, ldap_err2string(ldap_errno));
- goto do_reconnect;
+ case LDAP_SERVER_DOWN:
+ return LDAP_PROC_RETRY;
case LDAP_INVALID_CREDENTIALS:
case LDAP_CONSTRAINT_VIOLATION:
return LDAP_PROC_REJECT;
+ case LDAP_OPERATIONS_ERROR:
+ DEBUGW("Please set 'chase_referrals=yes' and 'rebind=yes'");
+ DEBUGW("See the ldap module configuration for details");
+ /* FALL-THROUGH */
+
default:
radlog(L_ERR, "rlm_ldap (%s): %s failed: %s",
inst->xlat_name, operation, ldap_err2string(ldap_errno));
LDAPMessage *result = NULL;
struct timeval tv;
-bind:
+retry:
msg_id = ldap_bind(conn->handle, user, password, LDAP_AUTH_SIMPLE);
if (msg_id < 0) goto get_error;
break;
case LDAP_PROC_RETRY:
- if (retry) goto bind;
+ if (retry) {
+ *pconn = fr_connection_reconnect(inst->pool, *pconn);
+ if (*pconn) goto retry;
+ }
module_rcode = RLM_MODULE_FAIL;
break;
do_ldap_option(LDAP_OPT_REFERRALS, "chase_referrals",
LDAP_OPT_ON);
-#if LDAP_SET_REBIND_PROC_ARGS == 3
if (inst->rebind == 1) {
+#if LDAP_SET_REBIND_PROC_ARGS == 3
ldap_set_rebind_proc(handle, ldap_rebind, inst);
- }
+#else
+ DEBUGW("The flag 'rebind = yes' is not supported by the system LDAP library. Ignoring.");
#endif
+ }
} else {
do_ldap_option(LDAP_OPT_REFERRALS, "chase_referrals",
LDAP_OPT_OFF);
}
#endif /* HAVE_LDAP_START_TLS */
- conn = rad_malloc(sizeof(*conn));
+ conn = talloc(NULL, LDAP_CONN);
conn->inst = inst;
conn->handle = handle;
conn->rebound = FALSE;
LDAP_CONN *conn = connection;
ldap_unbind_s(conn->handle);
- free(conn);
+ talloc_free(conn);
return 0;
}
{
int ldap_errno;
int count = 0;
- LDAP_CONN *conn = *pconn;
struct timeval tv;
/*
/*
* Do all searches as the default admin user.
*/
- if (conn->rebound) {
+ if ((*pconn)->rebound) {
ldap_errno = ldap_bind_wrapper(pconn, inst->login,
inst->password, TRUE);
if (ldap_errno != RLM_MODULE_OK) {
return -1;
}
- rad_assert(*pconn != NULL);
- conn = *pconn;
- conn->rebound = FALSE;
+ rad_assert(*pconn);
+ (*pconn)->rebound = FALSE;
}
tv.tv_sec = inst->timeout;
filter);
retry:
- ldap_errno = ldap_search_ext_s(conn->handle, search_basedn, scope,
+ ldap_errno = ldap_search_ext_s((*pconn)->handle, search_basedn, scope,
filter, search_attrs, 0, NULL, NULL,
&tv, 0, presult);
if (ldap_errno != LDAP_SUCCESS) {
case LDAP_PROC_ERROR:
return -1;
case LDAP_PROC_RETRY:
- conn = *pconn;
- goto retry;
+ *pconn = fr_connection_reconnect(inst->pool, *pconn);
+ if (*pconn) goto retry;
+ return -1;
default:
rad_assert(0);
}
}
- count = ldap_count_entries(conn->handle, *presult);
+ count = ldap_count_entries((*pconn)->handle, *presult);
if (count == 0) {
ldap_msgfree(*presult);
RDEBUG("Search returned no results");
ldap_msgfree(result);
ldap_release_socket(inst, conn);
- if (!found){
+ if (!found) {
RDEBUG("User is not a member of specified group");
return 1;
}
static int ldap_detach(void *instance)
{
ldap_instance *inst = instance;
-
- if (inst->postauth) free(inst->postauth);
- if (inst->accounting) free(inst->accounting);
fr_connection_pool_delete(inst->pool);
-
+
if (inst->user_map) {
radius_mapfree(&inst->user_map);
}
- free(inst);
-
return 0;
}
return 0;
}
- *config = rad_calloc(sizeof(**config));
+ *config = talloc_zero(inst, ldap_acct_section_t);
if (cf_section_parse(cs, *config, acct_section_config) < 0) {
radlog(L_ERR, "rlm_ldap (%s): Failed parsing configuration for "
"section %s", inst->xlat_name, name);
-
- free(*config);
- *config = NULL;
-
return -1;
}
}
/*
* Attrmap only performs some basic validation checks, we need
- * to do rlm_cache specific checks here.
+ * to do rlm_ldap specific checks here.
*/
for (map = *head; map != NULL; map = map->next) {
if (map->dst->type != VPT_TYPE_ATTR) {
{
ldap_instance *inst;
- inst = rad_calloc(sizeof *inst);
+ *instance = inst = talloc_zero(conf, ldap_instance);
+ if (!inst) return -1;
+
inst->cs = conf;
inst->chase_referrals = 2; /* use OpenLDAP defaults */
if (!inst->xlat_name) {
inst->xlat_name = cf_section_name1(conf);
}
-
- rad_assert(inst->xlat_name);
/*
* If the configuration parameters can't be parsed, then fail.
*/
paircompare_register(PW_LDAP_GROUP, PW_USER_NAME, ldap_groupcmp, inst);
if (cf_section_name2(conf)) {
- DICT_ATTR *da;
+ const DICT_ATTR *da;
ATTR_FLAGS flags;
char buffer[256];
return -1;
}
- *instance = inst;
return 0;
-
- error:
+
+error:
ldap_detach(inst);
return -1;
}
* just use whatever was set in the attribute map.
*/
for (i = 0; i < self->count; i++) {
- vp = pairalloc(map->dst->da);
+ vp = pairalloc(NULL, map->dst->da);
rad_assert(vp);
pairparsevalue(vp, self->values[i]);
!pairfind(request->config_items, PW_USER_PASSWORD, 0, TAG_ANY) &&
!pairfind(request->config_items, PW_PASSWORD_WITH_HEADER, 0, TAG_ANY) &&
!pairfind(request->config_items, PW_CRYPT_PASSWORD, 0, TAG_ANY)) {
- RDEBUG("WARNING: No \"known good\" password "
+ RDEBUGW("No \"known good\" password "
"was found in LDAP. Are you sure that "
"the user is configured correctly?");
}
/* Add Cleartext-Password attribute to the request */
vp = radius_paircreate(request, &request->config_items,
- PW_CLEARTEXT_PASSWORD, 0,
- PW_TYPE_STRING);
+ PW_CLEARTEXT_PASSWORD, 0);
strlcpy(vp->vp_strvalue, buffer, sizeof(vp->vp_strvalue));
vp->length = strlen(vp->vp_strvalue);
RDEBUG2("Added eDirectory password in check items as %s = %s",
- vp->name, vp->vp_strvalue);
+ vp->da->name, vp->vp_strvalue);
if (inst->edir_autz) {
RDEBUG2("Binding as user for eDirectory authorization "
return RLM_MODULE_INVALID;
}
- if (request->password->attribute != PW_USER_PASSWORD) {
+ if (request->password->da->attr != PW_USER_PASSWORD) {
radlog(L_AUTH, "rlm_ldap (%s): Attribute \"User-Password\" "
"is required for authentication. Cannot use \"%s\".",
- inst->xlat_name, request->password->name);
+ inst->xlat_name, request->password->da->name);
return RLM_MODULE_INVALID;
}
int ldap_errno, rcode, msg_id;
LDAPMessage *result = NULL;
- LDAP_CONN *conn;
+ LDAP_CONN *conn = NULL;
LDAPMod *mod_p[MAX_ATTRMAP + 1], mod_s[MAX_ATTRMAP];
LDAPMod **modify = mod_p;