X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Frlm_ldap%2Frlm_ldap.c;h=fabe11802831bdf8b8801860d35a1184ad83ecf7;hb=85e88c91a8dac12781b629576829022f1ef044e6;hp=2ff912f5fd0f029f238055b873e8ad2e041d3dff;hpb=442ba845b26f7ed4ac762184198c22cf6717f073;p=freeradius.git diff --git a/src/modules/rlm_ldap/rlm_ldap.c b/src/modules/rlm_ldap/rlm_ldap.c index 2ff912f..fabe118 100644 --- a/src/modules/rlm_ldap/rlm_ldap.c +++ b/src/modules/rlm_ldap/rlm_ldap.c @@ -106,7 +106,7 @@ int radLdapXtnNMASAuth( LDAP *, char *, char *, char *, char *, size_t *, char * struct TLDAP_RADIUS { char* attr; char* radius_attr; - LRAD_TOKEN operator; + FR_TOKEN operator; struct TLDAP_RADIUS* next; }; typedef struct TLDAP_RADIUS TLDAP_RADIUS; @@ -125,8 +125,8 @@ typedef struct { char *server; int port; int timelimit; - struct timeval net_timeout; - struct timeval timeout; + int net_timeout; + int timeout; int debug; int tls_mode; int start_tls; @@ -136,6 +136,8 @@ typedef struct { int default_allow; int failed_conns; int is_url; + int chase_referrals; + int rebind; char *login; char *password; char *filter; @@ -144,9 +146,7 @@ typedef struct { char *default_profile; char *profile_attr; char *access_attr; - char *passwd_hdr; char *passwd_attr; - int auto_header; char *dictionary_mapping; char *groupname_attr; char *groupmemb_filt; @@ -160,6 +160,7 @@ typedef struct { #endif int ldap_debug; /* Debug flag for LDAP SDK */ char *xlat_name; /* name used to xlat */ + char *auth_type; char *tls_cacertfile; char *tls_cacertdir; char *tls_certfile; @@ -170,11 +171,39 @@ typedef struct { int edir_account_policy_check; #endif int set_auth_type; + + /* + * For keep-alives. + */ +#ifdef LDAP_OPT_X_KEEPALIVE_IDLE + int keepalive_idle; +#endif +#ifdef LDAP_OPT_X_KEEPALIVE_PROBES + int keepalive_probes; +#endif +#ifdef LDAP_OPT_ERROR_NUMBER + int keepalive_interval; +#endif + } ldap_instance; /* The default setting for TLS Certificate Verification */ #define TLS_DEFAULT_VERIFY "allow" +static CONF_PARSER keepalive_config[] = { +#ifdef LDAP_OPT_X_KEEPALIVE_IDLE + {"idle", PW_TYPE_INTEGER, offsetof(ldap_instance,keepalive_idle), NULL, "60"}, +#endif +#ifdef LDAP_OPT_X_KEEPALIVE_PROBES + {"probes", PW_TYPE_INTEGER, offsetof(ldap_instance,keepalive_probes), NULL, "3"}, +#endif +#ifdef LDAP_OPT_ERROR_NUMBER + {"interval", PW_TYPE_INTEGER, offsetof(ldap_instance,keepalive_interval), NULL, "30"}, +#endif + + { NULL, -1, 0, NULL, NULL } +}; + static CONF_PARSER tls_config[] = { {"start_tls", PW_TYPE_BOOLEAN, offsetof(ldap_instance,start_tls), NULL, "no"}, @@ -208,10 +237,10 @@ static const CONF_PARSER module_config[] = { */ /* wait forever on network activity */ {"net_timeout", PW_TYPE_INTEGER, - offsetof(ldap_instance,net_timeout.tv_sec), NULL, "10"}, + offsetof(ldap_instance,net_timeout), NULL, "10"}, /* wait forever for search results */ {"timeout", PW_TYPE_INTEGER, - offsetof(ldap_instance,timeout.tv_sec), NULL, "20"}, + offsetof(ldap_instance,timeout), NULL, "20"}, /* allow server unlimited time for search (server-side limit) */ {"timelimit", PW_TYPE_INTEGER, offsetof(ldap_instance,timelimit), NULL, "20"}, @@ -256,12 +285,8 @@ static const CONF_PARSER module_config[] = { /* * Getting passwords from the database */ - {"password_header", PW_TYPE_STRING_PTR, - offsetof(ldap_instance,passwd_hdr), NULL, NULL}, {"password_attribute", PW_TYPE_STRING_PTR, offsetof(ldap_instance,passwd_attr), NULL, NULL}, - {"auto_header", PW_TYPE_BOOLEAN, - offsetof(ldap_instance,auto_header), NULL, "no"}, /* * Access limitations @@ -271,6 +296,10 @@ static const CONF_PARSER module_config[] = { offsetof(ldap_instance,access_attr), NULL, NULL}, {"access_attr_used_for_allow", PW_TYPE_BOOLEAN, offsetof(ldap_instance,default_allow), NULL, "yes"}, + {"chase_referrals", PW_TYPE_BOOLEAN, + offsetof(ldap_instance,chase_referrals), NULL, NULL}, + {"rebind", PW_TYPE_BOOLEAN, + offsetof(ldap_instance,rebind), NULL, NULL}, /* * Group checks. These could probably be done @@ -308,6 +337,8 @@ static const CONF_PARSER module_config[] = { #endif {"set_auth_type", PW_TYPE_BOOLEAN, offsetof(ldap_instance,set_auth_type), NULL, "yes"}, + + { "keepalive", PW_TYPE_SUBSECTION, 0, NULL, (const void *) keepalive_config }, {NULL, -1, 0, NULL, NULL} }; @@ -318,19 +349,20 @@ static const CONF_PARSER module_config[] = { #ifdef FIELDCPY static void fieldcpy(char *, char **); #endif -static VALUE_PAIR *ldap_pairget(LDAP *, LDAPMessage *, TLDAP_RADIUS *,VALUE_PAIR **,int); +static VALUE_PAIR *ldap_pairget(LDAP *, LDAPMessage *, TLDAP_RADIUS *,VALUE_PAIR **,int, ldap_instance *); static int ldap_groupcmp(void *, REQUEST *, VALUE_PAIR *, VALUE_PAIR *, VALUE_PAIR *, VALUE_PAIR **); -static int ldap_xlat(void *, REQUEST *, char *, char *, size_t, RADIUS_ESCAPE_STRING); +static size_t ldap_xlat(void *, REQUEST *, char *, char *, size_t, RADIUS_ESCAPE_STRING); static LDAP *ldap_connect(void *instance, const char *, const char *, int, int *, char **); static int read_mappings(ldap_instance* inst); -static inline int ldap_get_conn(LDAP_CONN *conns,LDAP_CONN **ret,void *instance) +static inline int ldap_get_conn(LDAP_CONN *conns,LDAP_CONN **ret, + ldap_instance *inst) { - ldap_instance *inst = instance; register int i = 0; for(i=0;inum_conns;i++){ - DEBUG("rlm_ldap: ldap_get_conn: Checking Id: %d",i); + DEBUG(" [%s] ldap_get_conn: Checking Id: %d", + inst->xlat_name, i); if ((pthread_mutex_trylock(&conns[i].mutex) == 0)) { if (conns[i].locked == 1) { /* connection is already being used */ @@ -340,7 +372,8 @@ static inline int ldap_get_conn(LDAP_CONN *conns,LDAP_CONN **ret,void *instance) /* found an unused connection */ *ret = &conns[i]; conns[i].locked = 1; - DEBUG("rlm_ldap: ldap_get_conn: Got Id: %d",i); + DEBUG(" [%s] ldap_get_conn: Got Id: %d", + inst->xlat_name, i); return i; } } @@ -348,12 +381,27 @@ static inline int ldap_get_conn(LDAP_CONN *conns,LDAP_CONN **ret,void *instance) return -1; } -static inline void ldap_release_conn(int i, LDAP_CONN *conns) +static inline void ldap_release_conn(int i, ldap_instance *inst) + +{ + LDAP_CONN *conns = inst->conns; + + DEBUG(" [%s] ldap_release_conn: Release Id: %d", inst->xlat_name, i); + conns[i].locked = 0; + pthread_mutex_unlock(&(conns[i].mutex)); +} + +#ifdef NOVELL +static inline void ldap_release_apc_conn(int i, ldap_instance *inst) + { - DEBUG("rlm_ldap: ldap_release_conn: Release Id: %d",i); + LDAP_CONN *conns = inst->apc_conns; + + DEBUG(" [%s] ldap_release_conn: Release Id: %d", inst->xlat_name, i); conns[i].locked = 0; pthread_mutex_unlock(&(conns[i].mutex)); } +#endif /************************************************************************* * @@ -381,6 +429,8 @@ ldap_instantiate(CONF_SECTION * conf, void **instance) return -1; } memset(inst, 0, sizeof(*inst)); + inst->chase_referrals = 2; /* use OpenLDAP defaults */ + inst->rebind = 2; if (cf_section_parse(conf, inst, module_config) < 0) { free(inst); @@ -404,8 +454,6 @@ ldap_instantiate(CONF_SECTION * conf, void **instance) #endif } - inst->timeout.tv_usec = 0; - inst->net_timeout.tv_usec = 0; /* workaround for servers which support LDAPS but not START TLS */ if(inst->port == LDAPS_PORT || inst->tls_mode) inst->tls_mode = LDAP_OPT_X_TLS_HARD; @@ -416,6 +464,19 @@ ldap_instantiate(CONF_SECTION * conf, void **instance) inst->conns = NULL; inst->failed_conns = 0; +#if LDAP_SET_REBIND_PROC_ARGS != 3 + /* + * The 2-argument rebind doesn't take an instance + * variable. Our rebind function needs the instance + * variable for the username, password, etc. + */ + if (inst->rebind == 1) { + radlog(L_ERR, "rlm_ldap: Cannot use 'rebind' directive as this version of libldap does not support the API that we need."); + free(inst); + return -1; + } +#endif + DEBUG("rlm_ldap: Registering ldap_groupcmp for Ldap-Group"); paircompare_register(PW_LDAP_GROUP, PW_USER_NAME, ldap_groupcmp, inst); memset(&flags, 0, sizeof(flags)); @@ -431,7 +492,7 @@ ldap_instantiate(CONF_SECTION * conf, void **instance) group_name = rad_malloc((strlen(xlat_name) + 1 + 11) * sizeof(char)); sprintf(group_name,"%s-Ldap-Group",xlat_name); DEBUG("rlm_ldap: Creating new attribute %s",group_name); - dict_addattr(group_name, 0, PW_TYPE_STRING, -1, flags); + dict_addattr(group_name, -1, 0, PW_TYPE_STRING, flags); dattr = dict_attrbyname(group_name); if (dattr == NULL){ radlog(L_ERR, "rlm_ldap: Failed to create attribute %s",group_name); @@ -457,10 +518,18 @@ ldap_instantiate(CONF_SECTION * conf, void **instance) * in "authorize", but not "authenticate". */ if (inst->set_auth_type) { - DICT_VALUE *dv = dict_valbyname(PW_AUTH_TYPE, xlat_name); + DICT_VALUE *dv = dict_valbyname(PW_AUTH_TYPE, 0, xlat_name); + + /* + * No section of *my* name, but maybe there's an + * LDAP section... + */ + if (!dv) dv = dict_valbyname(PW_AUTH_TYPE, 0, "LDAP"); if (!dv) { - DEBUG2("rlm_ldap: Over-riding set_auth_type, as we're not listed in the \"authenticate\" section."); + DEBUG2("rlm_ldap: Over-riding set_auth_type, as there is no module %s listed in the \"authenticate\" section.", xlat_name); inst->set_auth_type = 0; + } else { + inst->auth_type = dv->name; /* doesn't change on HUP */ } } /* else no need to look up the value */ @@ -471,7 +540,7 @@ ldap_instantiate(CONF_SECTION * conf, void **instance) * instance 'V1' of the LDAP module has processed this * request. */ - dict_addattr("LDAP-Instance", 0, PW_TYPE_STRING, -1, flags); + dict_addattr("LDAP-Instance", -1, 0, PW_TYPE_STRING, flags); /* * ('eDir-APC', '1') in config items list @@ -483,11 +552,11 @@ ldap_instantiate(CONF_SECTION * conf, void **instance) * ('eDir-APC', '3') in config items list * eDirectory APC has been completed */ - dict_addattr("eDir-APC", 0, PW_TYPE_STRING, -1, flags); + dict_addattr("eDir-APC", -1, 0, PW_TYPE_STRING, flags); /* * eDir-Auth-Option allows for a different NMAS Authentication method to be used instead of password */ - dict_addattr("eDir-Auth-Option", 0, PW_TYPE_STRING, -1, flags); + dict_addattr("eDir-Auth-Option", -1, 0, PW_TYPE_STRING, flags); #endif if (inst->num_conns <= 0){ @@ -641,7 +710,7 @@ read_mappings(ldap_instance* inst) char buf[MAX_LINE_LEN], itemType[MAX_LINE_LEN]; char radiusAttribute[MAX_LINE_LEN], ldapAttribute[MAX_LINE_LEN]; int linenumber; - LRAD_TOKEN operator; + FR_TOKEN operator; char opstring[MAX_LINE_LEN]; /* open the mappings file for reading */ @@ -695,8 +764,6 @@ read_mappings(ldap_instance* inst) if (token_count == 3) { operator = T_OP_INVALID; /* use defaults */ } else { - char *ptr; - ptr = opstring; operator = gettoken(&ptr, buf, sizeof(buf)); if ((operator < T_OP_ADD) || (operator > T_OP_CMP_EQ)) { @@ -755,11 +822,13 @@ static int perform_search(void *instance, LDAP_CONN *conn, int ldap_errno = 0; ldap_instance *inst = instance; int search_retry = 0; + struct timeval tv; *result = NULL; if (!conn){ - radlog(L_ERR, "rlm_ldap: NULL connection handle passed"); + radlog(L_ERR, " [%s] NULL connection handle passed", + inst->xlat_name); return RLM_MODULE_FAIL; } if (conn->failed_conns > MAX_FAILED_CONNS_START){ @@ -771,14 +840,16 @@ static int perform_search(void *instance, LDAP_CONN *conn, } retry: if (!conn->bound || conn->ld == NULL) { - DEBUG2("rlm_ldap: attempting LDAP reconnection"); + DEBUG2(" [%s] attempting LDAP reconnection", inst->xlat_name); if (conn->ld){ - DEBUG2("rlm_ldap: closing existing LDAP connection"); + DEBUG2(" [%s] closing existing LDAP connection", + inst->xlat_name); ldap_unbind_s(conn->ld); } if ((conn->ld = ldap_connect(instance, inst->login, inst->password, 0, &res, NULL)) == NULL) { - radlog(L_ERR, "rlm_ldap: (re)connection attempt failed"); + radlog(L_ERR, " [%s] (re)connection attempt failed", + inst->xlat_name); if (search_retry == 0) conn->failed_conns++; return (RLM_MODULE_FAIL); @@ -786,19 +857,22 @@ retry: conn->bound = 1; conn->failed_conns = 0; } - DEBUG2("rlm_ldap: performing search in %s, with filter %s", + + tv.tv_sec = inst->timeout; + tv.tv_usec = 0; + DEBUG2(" [%s] performing search in %s, with filter %s", inst->xlat_name, search_basedn ? search_basedn : "(null)" , filter); switch (ldap_search_st(conn->ld, search_basedn, scope, filter, - attrs, 0, &(inst->timeout), result)) { + attrs, 0, &tv, result)) { case LDAP_SUCCESS: case LDAP_NO_SUCH_OBJECT: break; case LDAP_SERVER_DOWN: - radlog(L_ERR, "rlm_ldap: ldap_search() failed: LDAP connection lost."); + radlog(L_ERR, " [%s] ldap_search() failed: LDAP connection lost.", inst->xlat_name); conn->failed_conns++; if (search_retry == 0){ if (conn->failed_conns <= MAX_FAILED_CONNS_START){ - radlog(L_INFO, "rlm_ldap: Attempting reconnect"); + radlog(L_INFO, " [%s] Attempting reconnect", inst->xlat_name); search_retry = 1; conn->bound = 0; ldap_msgfree(*result); @@ -808,15 +882,15 @@ retry: ldap_msgfree(*result); return RLM_MODULE_FAIL; case LDAP_INSUFFICIENT_ACCESS: - radlog(L_ERR, "rlm_ldap: ldap_search() failed: Insufficient access. Check the identity and password configuration directives."); + radlog(L_ERR, " [%s] ldap_search() failed: Insufficient access. Check the identity and password configuration directives.", inst->xlat_name); ldap_msgfree(*result); return RLM_MODULE_FAIL; case LDAP_TIMEOUT: - radlog(L_ERR, "rlm_ldap: ldap_search() failed: Timed out while waiting for server to respond. Please increase the timeout."); + radlog(L_ERR, " [%s] ldap_search() failed: Timed out while waiting for server to respond. Please increase the timeout.", inst->xlat_name); ldap_msgfree(*result); return RLM_MODULE_FAIL; case LDAP_FILTER_ERROR: - radlog(L_ERR, "rlm_ldap: ldap_search() failed: Bad search filter: %s",filter); + radlog(L_ERR, " [%s] ldap_search() failed: Bad search filter: %s", inst->xlat_name,filter); ldap_msgfree(*result); return RLM_MODULE_FAIL; case LDAP_TIMELIMIT_EXCEEDED: @@ -824,21 +898,26 @@ retry: case LDAP_UNAVAILABLE: /* We don't need to reconnect in these cases so we don't set conn->bound */ ldap_get_option(conn->ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); - radlog(L_ERR, "rlm_ldap: ldap_search() failed: %s", + radlog(L_ERR, " [%s] ldap_search() failed: %s", inst->xlat_name, ldap_err2string(ldap_errno)); ldap_msgfree(*result); return (RLM_MODULE_FAIL); default: ldap_get_option(conn->ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); - radlog(L_ERR, "rlm_ldap: ldap_search() failed: %s", + radlog(L_ERR, " [%s] ldap_search() failed: %s", inst->xlat_name, ldap_err2string(ldap_errno)); conn->bound = 0; ldap_msgfree(*result); return (RLM_MODULE_FAIL); } - if ((ldap_count_entries(conn->ld, *result)) != 1) { - DEBUG("rlm_ldap: object not found or got ambiguous search result"); + ldap_errno = ldap_count_entries(conn->ld, *result); + if (ldap_errno != 1) { + if (ldap_errno == 0) { + DEBUG(" [%s] object not found", inst->xlat_name); + } else { + DEBUG(" [%s] got ambiguous search result (%d results)", inst->xlat_name, ldap_errno); + } res = RLM_MODULE_NOTFOUND; ldap_msgfree(*result); } @@ -849,9 +928,9 @@ retry: /* * Translate the LDAP queries. */ -static int ldap_escape_func(char *out, int outlen, const char *in) +static size_t ldap_escape_func(char *out, size_t outlen, const char *in) { - int len = 0; + size_t len = 0; while (in[0]) { /* @@ -921,7 +1000,7 @@ static int ldap_groupcmp(void *instance, REQUEST *req, request_pairs = &req->config_items; - DEBUG("rlm_ldap: Entering ldap_groupcmp()"); + DEBUG(" [%s] Entering ldap_groupcmp()", inst->xlat_name); if (check->vp_strvalue == NULL || check->length == 0){ DEBUG("rlm_ldap::ldap_groupcmp: Illegal group name"); @@ -938,7 +1017,7 @@ static int ldap_groupcmp(void *instance, REQUEST *req, return 1; } - while((vp_user_dn = pairfind(*request_pairs, PW_LDAP_USERDN)) == NULL){ + while((vp_user_dn = pairfind(*request_pairs, PW_LDAP_USERDN, 0)) == NULL){ char *user_dn = NULL; if (!radius_xlat(filter, sizeof(filter), inst->filter, @@ -947,28 +1026,28 @@ static int ldap_groupcmp(void *instance, REQUEST *req, return 1; } if ((conn_id = ldap_get_conn(inst->conns,&conn,inst)) == -1){ - radlog(L_ERR, "rlm_ldap: All ldap connections are in use"); + radlog(L_ERR, " [%s] All ldap connections are in use", inst->xlat_name); return 1; } if ((res = perform_search(inst, conn, basedn, LDAP_SCOPE_SUBTREE, filter, attrs, &result)) != RLM_MODULE_OK){ DEBUG("rlm_ldap::ldap_groupcmp: search failed"); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); return 1; } if ((msg = ldap_first_entry(conn->ld, result)) == NULL) { DEBUG("rlm_ldap::ldap_groupcmp: ldap_first_entry() failed"); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); ldap_msgfree(result); return 1; } if ((user_dn = ldap_get_dn(conn->ld, msg)) == NULL) { DEBUG("rlm_ldap:ldap_groupcmp:: ldap_get_dn() failed"); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); ldap_msgfree(result); return 1; } - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); /* * Adding new attribute containing DN for LDAP @@ -996,7 +1075,7 @@ static int ldap_groupcmp(void *instance, REQUEST *req, (char *)check->vp_strvalue,gr_filter); if ((conn_id = ldap_get_conn(inst->conns,&conn,inst)) == -1) { - radlog(L_ERR, "rlm_ldap: All ldap connections are in use"); + radlog(L_ERR, " [%s] All ldap connections are in use", inst->xlat_name); return 1; } @@ -1005,11 +1084,11 @@ static int ldap_groupcmp(void *instance, REQUEST *req, DEBUG("rlm_ldap::ldap_groupcmp: User found in group %s", (char *)check->vp_strvalue); ldap_msgfree(result); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); return 0; } - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); if (res != RLM_MODULE_NOTFOUND ) { DEBUG("rlm_ldap::ldap_groupcmp: Search returned error"); @@ -1028,26 +1107,26 @@ static int ldap_groupcmp(void *instance, REQUEST *req, snprintf(filter,sizeof(filter), "(objectclass=*)"); if ((conn_id = ldap_get_conn(inst->conns,&conn,inst)) == -1){ - radlog(L_ERR, "rlm_ldap: Add ldap connections are in use"); + radlog(L_ERR, " [%s] Add ldap connections are in use", inst->xlat_name); return 1; } if ((res = perform_search(inst, conn, vp_user_dn->vp_strvalue, LDAP_SCOPE_BASE, filter, group_attrs, &result)) != RLM_MODULE_OK) { DEBUG("rlm_ldap::ldap_groupcmp: Search returned error"); - ldap_release_conn(conn_id, inst->conns); + ldap_release_conn(conn_id, inst); return 1; } if ((msg = ldap_first_entry(conn->ld, result)) == NULL) { DEBUG("rlm_ldap::ldap_groupcmp: ldap_first_entry() failed"); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); ldap_msgfree(result); return 1; } if ((vals = ldap_get_values(conn->ld, msg, inst->groupmemb_attr)) != NULL) { - unsigned int i = 0; + int i = 0; char found = 0; for (;i < ldap_count_values(vals);i++){ @@ -1064,7 +1143,7 @@ static int ldap_groupcmp(void *instance, REQUEST *req, DEBUG("rlm_ldap::ldap_groupcmp: Search returned error"); ldap_value_free(vals); ldap_msgfree(result); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); return 1; } } else { @@ -1084,18 +1163,18 @@ static int ldap_groupcmp(void *instance, REQUEST *req, if (found == 0){ DEBUG("rlm_ldap::groupcmp: Group %s not found or user not a member", (char *)check->vp_strvalue); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); return 1; } } else { DEBUG("rlm_ldap::ldap_groupcmp: ldap_get_values() failed"); ldap_msgfree(result); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); return 1; } DEBUG("rlm_ldap::ldap_groupcmp: User found in group %s",(char *)check->vp_strvalue); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); return 0; } @@ -1104,12 +1183,12 @@ static int ldap_groupcmp(void *instance, REQUEST *req, * ldap_xlat() * Do an xlat on an LDAP URL */ -static int ldap_xlat(void *instance, REQUEST *request, char *fmt, +static size_t ldap_xlat(void *instance, REQUEST *request, char *fmt, char *out, size_t freespace, RADIUS_ESCAPE_STRING func) { char url[MAX_FILTER_STR_LEN]; int res; - int ret = 0; + size_t ret = 0; ldap_instance *inst = instance; LDAPURLDesc *ldap_url; LDAPMessage *result = NULL; @@ -1118,24 +1197,24 @@ static int ldap_xlat(void *instance, REQUEST *request, char *fmt, int conn_id = -1; LDAP_CONN *conn; - DEBUG("rlm_ldap: - ldap_xlat"); + DEBUG(" [%s] - ldap_xlat", inst->xlat_name); if (!radius_xlat(url, sizeof(url), fmt, request, func)) { - radlog (L_ERR, "rlm_ldap: Unable to create LDAP URL.\n"); + radlog (L_ERR, " [%s] Unable to create LDAP URL.\n", inst->xlat_name); return 0; } if (!ldap_is_ldap_url(url)){ - radlog (L_ERR, "rlm_ldap: String passed does not look like an LDAP URL.\n"); + radlog (L_ERR, " [%s] String passed does not look like an LDAP URL.\n", inst->xlat_name); return 0; } if (ldap_url_parse(url,&ldap_url)){ - radlog (L_ERR, "rlm_ldap: LDAP URL parse failed.\n"); + radlog (L_ERR, " [%s] LDAP URL parse failed.\n", inst->xlat_name); return 0; } if (ldap_url->lud_attrs == NULL || ldap_url->lud_attrs[0] == NULL || ( ldap_url->lud_attrs[1] != NULL || ( ! strlen(ldap_url->lud_attrs[0]) || ! strcmp(ldap_url->lud_attrs[0],"*") ) ) ){ - radlog (L_ERR, "rlm_ldap: Invalid Attribute(s) request.\n"); + radlog (L_ERR, " [%s] Invalid Attribute(s) request.\n", inst->xlat_name); ldap_free_urldesc(ldap_url); return 0; } @@ -1143,46 +1222,46 @@ static int ldap_xlat(void *instance, REQUEST *request, char *fmt, if (strncmp(inst->server,ldap_url->lud_host, strlen(inst->server)) != 0 || ldap_url->lud_port != inst->port) { - DEBUG("rlm_ldap: Requested server/port is not known to this module instance."); + DEBUG(" [%s] Requested server/port is not known to this module instance.", inst->xlat_name); ldap_free_urldesc(ldap_url); return 0; } } if ((conn_id = ldap_get_conn(inst->conns,&conn,inst)) == -1){ - radlog(L_ERR, "rlm_ldap: All ldap connections are in use"); + radlog(L_ERR, " [%s] All ldap connections are in use", inst->xlat_name); ldap_free_urldesc(ldap_url); return 0; } if ((res = perform_search(inst, conn, ldap_url->lud_dn, ldap_url->lud_scope, ldap_url->lud_filter, ldap_url->lud_attrs, &result)) != RLM_MODULE_OK){ if (res == RLM_MODULE_NOTFOUND){ - DEBUG("rlm_ldap: Search returned not found"); + DEBUG(" [%s] Search returned not found", inst->xlat_name); ldap_free_urldesc(ldap_url); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); return 0; } - DEBUG("rlm_ldap: Search returned error"); + DEBUG(" [%s] Search returned error", inst->xlat_name); ldap_free_urldesc(ldap_url); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); return 0; } if ((msg = ldap_first_entry(conn->ld, result)) == NULL){ - DEBUG("rlm_ldap: ldap_first_entry() failed"); + DEBUG(" [%s] ldap_first_entry() failed", inst->xlat_name); ldap_msgfree(result); ldap_free_urldesc(ldap_url); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); return 0; } if ((vals = ldap_get_values(conn->ld, msg, ldap_url->lud_attrs[0])) != NULL) { ret = strlen(vals[0]); if (ret >= freespace){ - DEBUG("rlm_ldap: Insufficient string space"); + DEBUG(" [%s] Insufficient string space", inst->xlat_name); ldap_free_urldesc(ldap_url); ldap_value_free(vals); ldap_msgfree(result); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); return 0; } - DEBUG("rlm_ldap: Adding attribute %s, value: %s",ldap_url->lud_attrs[0],vals[0]); + DEBUG(" [%s] Adding attribute %s, value: %s", inst->xlat_name,ldap_url->lud_attrs[0],vals[0]); strlcpy(out,vals[0],freespace); ldap_value_free(vals); } @@ -1191,9 +1270,9 @@ static int ldap_xlat(void *instance, REQUEST *request, char *fmt, ldap_msgfree(result); ldap_free_urldesc(ldap_url); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); - DEBUG("rlm_ldap: - ldap_xlat end"); + DEBUG(" [%s] - ldap_xlat end", inst->xlat_name); return ret; } @@ -1202,7 +1281,7 @@ static int ldap_xlat(void *instance, REQUEST *request, char *fmt, /* * For auto-header discovery. */ -static const LRAD_NAME_NUMBER header_names[] = { +static const FR_NAME_NUMBER header_names[] = { { "{clear}", PW_CLEARTEXT_PASSWORD }, { "{cleartext}", PW_CLEARTEXT_PASSWORD }, { "{md5}", PW_MD5_PASSWORD }, @@ -1247,11 +1326,9 @@ static int ldap_authorize(void *instance, REQUEST * request) int conn_id = -1; int added_known_password = 0; - DEBUG("rlm_ldap: - authorize"); - if (!request->username){ - radlog(L_AUTH, "rlm_ldap: Attribute \"User-Name\" is required for authentication.\n"); - return RLM_MODULE_INVALID; + RDEBUG2("Attribute \"User-Name\" is required for authorization.\n"); + return RLM_MODULE_NOOP; } check_pairs = &request->config_items; @@ -1261,48 +1338,48 @@ static int ldap_authorize(void *instance, REQUEST * request) * Check for valid input, zero length names not permitted */ if (request->username->vp_strvalue == 0) { - radlog(L_ERR, "rlm_ldap: zero length username not permitted\n"); + DEBUG2("zero length username not permitted\n"); return RLM_MODULE_INVALID; } - DEBUG("rlm_ldap: performing user authorization for %s", + RDEBUG("performing user authorization for %s", request->username->vp_strvalue); if (!radius_xlat(filter, sizeof(filter), inst->filter, request, ldap_escape_func)) { - radlog (L_ERR, "rlm_ldap: unable to create filter.\n"); + radlog(L_ERR, " [%s] unable to create filter.\n", inst->xlat_name); return RLM_MODULE_INVALID; } if (!radius_xlat(basedn, sizeof(basedn), inst->basedn, request, ldap_escape_func)) { - radlog (L_ERR, "rlm_ldap: unable to create basedn.\n"); + radlog(L_ERR, " [%s] unable to create basedn.\n", inst->xlat_name); return RLM_MODULE_INVALID; } if ((conn_id = ldap_get_conn(inst->conns,&conn,inst)) == -1){ - radlog(L_ERR, "rlm_ldap: All ldap connections are in use"); + radlog(L_ERR, " [%s] All ldap connections are in use", inst->xlat_name); return RLM_MODULE_FAIL; } if ((res = perform_search(instance, conn, basedn, LDAP_SCOPE_SUBTREE, filter, inst->atts, &result)) != RLM_MODULE_OK) { - DEBUG("rlm_ldap: search failed"); + RDEBUG("search failed"); if (res == RLM_MODULE_NOTFOUND){ - snprintf(module_fmsg,sizeof(module_fmsg),"rlm_ldap: User not found"); + snprintf(module_fmsg,sizeof(module_fmsg)," [%s] User not found", inst->xlat_name); module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ); pairadd(&request->packet->vps, module_fmsg_vp); } - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); return (res); } if ((msg = ldap_first_entry(conn->ld, result)) == NULL) { - DEBUG("rlm_ldap: ldap_first_entry() failed"); + RDEBUG("ldap_first_entry() failed"); ldap_msgfree(result); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); return RLM_MODULE_FAIL; } if ((user_dn = ldap_get_dn(conn->ld, msg)) == NULL) { - DEBUG("rlm_ldap: ldap_get_dn() failed"); + RDEBUG("ldap_get_dn() failed"); ldap_msgfree(result); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); return RLM_MODULE_FAIL; } /* @@ -1317,37 +1394,37 @@ static int ldap_authorize(void *instance, REQUEST * request) if (inst->access_attr) { if ((vals = ldap_get_values(conn->ld, msg, inst->access_attr)) != NULL) { if (inst->default_allow){ - DEBUG("rlm_ldap: checking if remote access for %s is allowed by %s", request->username->vp_strvalue, inst->access_attr); + RDEBUG("checking if remote access for %s is allowed by %s", request->username->vp_strvalue, inst->access_attr); if (!strncmp(vals[0], "FALSE", 5)) { - DEBUG("rlm_ldap: dialup access disabled"); - snprintf(module_fmsg,sizeof(module_fmsg),"rlm_ldap: Access Attribute denies access"); + RDEBUG("dialup access disabled"); + snprintf(module_fmsg,sizeof(module_fmsg)," [%s] Access Attribute denies access", inst->xlat_name); module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ); pairadd(&request->packet->vps, module_fmsg_vp); ldap_msgfree(result); ldap_value_free(vals); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); return RLM_MODULE_USERLOCK; } ldap_value_free(vals); } else{ - DEBUG("rlm_ldap: %s attribute exists - access denied by default", inst->access_attr); - snprintf(module_fmsg,sizeof(module_fmsg),"rlm_ldap: Access Attribute denies access"); + RDEBUG("%s attribute exists - access denied by default", inst->access_attr); + snprintf(module_fmsg,sizeof(module_fmsg)," [%s] Access Attribute denies access", inst->xlat_name); module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ); pairadd(&request->packet->vps, module_fmsg_vp); ldap_msgfree(result); ldap_value_free(vals); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); return RLM_MODULE_USERLOCK; } } else { if (inst->default_allow){ - DEBUG("rlm_ldap: no %s attribute - access denied by default", inst->access_attr); - snprintf(module_fmsg,sizeof(module_fmsg),"rlm_ldap: Access Attribute denies access"); + RDEBUG("no %s attribute - access denied by default", inst->access_attr); + snprintf(module_fmsg,sizeof(module_fmsg)," [%s] Access Attribute denies access", inst->xlat_name); module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ); pairadd(&request->packet->vps, module_fmsg_vp); ldap_msgfree(result); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); return RLM_MODULE_USERLOCK; } } @@ -1358,7 +1435,7 @@ static int ldap_authorize(void *instance, REQUEST * request) * attributes it contains in the check and reply pairs */ - user_profile = pairfind(request->config_items, PW_USER_PROFILE); + user_profile = pairfind(request->config_items, PW_USER_PROFILE, 0); if (inst->default_profile || user_profile){ char *profile = inst->default_profile; @@ -1370,7 +1447,7 @@ static int ldap_authorize(void *instance, REQUEST * request) profile, LDAP_SCOPE_BASE, filter, inst->atts, &def_result)) == RLM_MODULE_OK){ if ((def_msg = ldap_first_entry(conn->ld,def_result))){ - if ((check_tmp = ldap_pairget(conn->ld,def_msg,inst->check_item_map,check_pairs,1))) { + if ((check_tmp = ldap_pairget(conn->ld,def_msg,inst->check_item_map,check_pairs,1, inst))) { if (inst->do_xlat){ pairxlatmove(request, check_pairs, &check_tmp); pairfree(&check_tmp); @@ -1378,7 +1455,7 @@ static int ldap_authorize(void *instance, REQUEST * request) else pairadd(check_pairs,check_tmp); } - if ((reply_tmp = ldap_pairget(conn->ld,def_msg,inst->reply_item_map,reply_pairs,0))) { + if ((reply_tmp = ldap_pairget(conn->ld,def_msg,inst->reply_item_map,reply_pairs,0, inst))) { if (inst->do_xlat){ pairxlatmove(request, reply_pairs, &reply_tmp); pairfree(&reply_tmp); @@ -1389,7 +1466,7 @@ static int ldap_authorize(void *instance, REQUEST * request) } ldap_msgfree(def_result); } else - DEBUG("rlm_ldap: default_profile/user-profile search failed"); + RDEBUG("default_profile/user-profile search failed"); } } @@ -1409,7 +1486,7 @@ static int ldap_authorize(void *instance, REQUEST * request) vals[i], LDAP_SCOPE_BASE, filter, inst->atts, &def_attr_result)) == RLM_MODULE_OK){ if ((def_attr_msg = ldap_first_entry(conn->ld,def_attr_result))){ - if ((check_tmp = ldap_pairget(conn->ld,def_attr_msg,inst->check_item_map,check_pairs,1))) { + if ((check_tmp = ldap_pairget(conn->ld,def_attr_msg,inst->check_item_map,check_pairs,1, inst))) { if (inst->do_xlat){ pairxlatmove(request, check_pairs, &check_tmp); pairfree(&check_tmp); @@ -1417,7 +1494,7 @@ static int ldap_authorize(void *instance, REQUEST * request) else pairadd(check_pairs,check_tmp); } - if ((reply_tmp = ldap_pairget(conn->ld,def_attr_msg,inst->reply_item_map,reply_pairs,0))) { + if ((reply_tmp = ldap_pairget(conn->ld,def_attr_msg,inst->reply_item_map,reply_pairs,0, inst))) { if (inst->do_xlat){ pairxlatmove(request, reply_pairs, &reply_tmp); pairfree(&reply_tmp); @@ -1428,7 +1505,7 @@ static int ldap_authorize(void *instance, REQUEST * request) } ldap_msgfree(def_attr_result); } else - DEBUG("rlm_ldap: profile_attribute search failed"); + RDEBUG("profile_attribute search failed"); i++; } ldap_value_free(vals); @@ -1462,45 +1539,17 @@ static int ldap_authorize(void *instance, REQUEST * request) continue; value = passwd_vals[i]; - - if (inst->auto_header) { - char *p; - char autobuf[16]; - - p = strchr(value, '}'); - if (!p) continue; - if ((p - value + 1) >= sizeof(autobuf)) - continue; /* paranoia */ - memcpy(autobuf, value, p - value + 1); - autobuf[p - value + 1] = '\0'; - - attr = lrad_str2int(header_names, - autobuf, 0); - if (!attr) continue; - value = p + 1; - goto create_attr; - - } else if (inst->passwd_hdr && - strlen(inst->passwd_hdr)) { - if (strncasecmp(value, - inst->passwd_hdr, - strlen(inst->passwd_hdr)) == 0) { - value += strlen(inst->passwd_hdr); - } else { - DEBUG("rlm_ldap: Password header not found in password %s for user %s", passwd_vals[0], request->username->vp_strvalue); - } - } if (!value) continue; create_attr: passwd_item = radius_paircreate(request, &request->config_items, - attr, + attr, 0, PW_TYPE_STRING); strlcpy(passwd_item->vp_strvalue, value, sizeof(passwd_item->vp_strvalue)); passwd_item->length = strlen(passwd_item->vp_strvalue); - DEBUG("rlm_ldap: Added %s = %s in check items", + RDEBUG("Added %s = %s in check items", passwd_item->name, passwd_item->vp_strvalue); added_known_password = 1; @@ -1514,33 +1563,22 @@ static int ldap_authorize(void *instance, REQUEST * request) */ VALUE_PAIR *passwd_item; VALUE_PAIR *vp_user_dn; - int passwd_len; char *universal_password = NULL; - int universal_password_len = UNIVERSAL_PASS_LEN; + size_t universal_password_len = UNIVERSAL_PASS_LEN; char *passwd_val = NULL; res = 0; - if ((passwd_item = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD)) == NULL){ + if ((passwd_item = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD, 0)) == NULL){ universal_password = rad_malloc(universal_password_len); memset(universal_password, 0, universal_password_len); - vp_user_dn = pairfind(request->config_items,PW_LDAP_USERDN); + vp_user_dn = pairfind(request->config_items,PW_LDAP_USERDN, 0); res = nmasldap_get_password(conn->ld,vp_user_dn->vp_strvalue,&universal_password_len,universal_password); if (res == 0){ passwd_val = universal_password; - - if (inst->passwd_hdr && strlen(inst->passwd_hdr)){ - passwd_val = strstr(passwd_val,inst->passwd_hdr); - - if (passwd_val != NULL) - passwd_val += strlen((char*)inst->passwd_hdr); - else - DEBUG("rlm_ldap: Password header not found in password %s for user %s ",passwd_val,request->username->vp_strvalue); - } - if (passwd_val){ passwd_item = radius_paircreate(request, &request->config_items, PW_CLEARTEXT_PASSWORD, PW_TYPE_STRING); strlcpy(passwd_item->vp_strvalue,passwd_val,sizeof(passwd_item->vp_strvalue)); @@ -1586,11 +1624,11 @@ static int ldap_authorize(void *instance, REQUEST * request) } #endif - DEBUG("rlm_ldap: Added the eDirectory password %s in check items as %s",passwd_item->vp_strvalue,passwd_item->name); + RDEBUG("Added the eDirectory password %s in check items as %s",passwd_item->vp_strvalue,passwd_item->name); } } else { - DEBUG("rlm_ldap: Error reading Universal Password.Return Code = %d",res); + RDEBUG("Error reading Universal Password.Return Code = %d",res); } memset(universal_password, 0, universal_password_len); @@ -1612,23 +1650,23 @@ static int ldap_authorize(void *instance, REQUEST * request) if(pairfind(*check_pairs, auth_opt_attr) == NULL){ if ((auth_option = ldap_get_values(conn->ld, msg, "sasDefaultLoginSequence")) != NULL) { if ((vp_auth_opt = paircreate(auth_opt_attr, PW_TYPE_STRING)) == NULL){ - radlog(L_ERR, "rlm_ldap: Could not allocate memory. Aborting."); + radlog(L_ERR, " [%s] Could not allocate memory. Aborting.", inst->xlat_name); ldap_msgfree(result); - ldap_release_conn(conn_id, inst->conns); + ldap_release_conn(conn_id, inst); } strcpy(vp_auth_opt->vp_strvalue, auth_option[0]); vp_auth_opt->length = strlen(auth_option[0]); pairadd(&request->config_items, vp_auth_opt); }else{ - DEBUG("rlm_ldap: No default NMAS login sequence"); + RDEBUG("No default NMAS login sequence"); } } } #endif - DEBUG("rlm_ldap: looking for check items in directory..."); + RDEBUG("looking for check items in directory..."); - if ((check_tmp = ldap_pairget(conn->ld, msg, inst->check_item_map,check_pairs,1)) != NULL) { + if ((check_tmp = ldap_pairget(conn->ld, msg, inst->check_item_map,check_pairs,1, inst)) != NULL) { if (inst->do_xlat){ pairxlatmove(request, check_pairs, &check_tmp); pairfree(&check_tmp); @@ -1638,10 +1676,10 @@ static int ldap_authorize(void *instance, REQUEST * request) } - DEBUG("rlm_ldap: looking for reply items in directory..."); + RDEBUG("looking for reply items in directory..."); - if ((reply_tmp = ldap_pairget(conn->ld, msg, inst->reply_item_map,reply_pairs,0)) != NULL) { + if ((reply_tmp = ldap_pairget(conn->ld, msg, inst->reply_item_map,reply_pairs,0, inst)) != NULL) { if (inst->do_xlat){ pairxlatmove(request, reply_pairs, &reply_tmp); pairfree(&reply_tmp); @@ -1665,12 +1703,12 @@ static int ldap_authorize(void *instance, REQUEST * request) vp_apc->vp_strvalue[0] = '1'; #endif - DEBUG("rlm_ldap: Pairs do not match. Rejecting user."); - snprintf(module_fmsg,sizeof(module_fmsg),"rlm_ldap: Pairs do not match"); + RDEBUG("Pairs do not match. Rejecting user."); + snprintf(module_fmsg,sizeof(module_fmsg)," [%s] Pairs do not match", inst->xlat_name); module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ); pairadd(&request->packet->vps, module_fmsg_vp); ldap_msgfree(result); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); return RLM_MODULE_REJECT; } @@ -1680,8 +1718,10 @@ static int ldap_authorize(void *instance, REQUEST * request) * to read the documentation. */ if (debug_flag > 1) { - if (!pairfind(request->config_items, PW_CLEARTEXT_PASSWORD) && - !pairfind(request->config_items, PW_USER_PASSWORD)) { + if (!pairfind(request->config_items, PW_CLEARTEXT_PASSWORD, 0) && + !pairfind(request->config_items, PW_USER_PASSWORD, 0) && + !pairfind(request->config_items, PW_PASSWORD_WITH_HEADER, 0) && + !pairfind(request->config_items, PW_CRYPT_PASSWORD, 0)) { DEBUG("WARNING: No \"known good\" password was found in LDAP. Are you sure that the user is configured correctly?"); } } @@ -1693,18 +1733,18 @@ static int ldap_authorize(void *instance, REQUEST * request) * ldap instances to work. */ if (inst->set_auth_type && - (pairfind(*check_pairs, PW_AUTH_TYPE) == NULL) && + (pairfind(*check_pairs, PW_AUTH_TYPE, 0) == NULL) && request->password && (request->password->attribute == PW_USER_PASSWORD) && !added_known_password) { - pairadd(check_pairs, pairmake("Auth-Type", inst->xlat_name, T_OP_EQ)); - DEBUG("rlm_ldap: Setting Auth-Type = %s", inst->xlat_name); + pairadd(check_pairs, pairmake("Auth-Type", inst->auth_type, T_OP_EQ)); + RDEBUG("Setting Auth-Type = %s", inst->auth_type); } - DEBUG("rlm_ldap: user %s authorized to use remote access", + RDEBUG("user %s authorized to use remote access", request->username->vp_strvalue); ldap_msgfree(result); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); return RLM_MODULE_OK; } @@ -1734,20 +1774,18 @@ static int ldap_authenticate(void *instance, REQUEST * request) char *err = NULL; #endif - DEBUG("rlm_ldap: - authenticate"); - /* * Ensure that we're being passed a plain-text password, and not * anything else. */ if (!request->username) { - radlog(L_AUTH, "rlm_ldap: Attribute \"User-Name\" is required for authentication.\n"); + radlog(L_AUTH, " [%s] Attribute \"User-Name\" is required for authentication.\n", inst->xlat_name); return RLM_MODULE_INVALID; } if (!request->password){ - radlog(L_AUTH, "rlm_ldap: Attribute \"User-Password\" is required for authentication."); + radlog(L_AUTH, " [%s] Attribute \"User-Password\" is required for authentication.", inst->xlat_name); DEBUG2(" You seem to have set \"Auth-Type := LDAP\" somewhere."); DEBUG2(" THAT CONFIGURATION IS WRONG. DELETE IT."); DEBUG2(" YOU ARE PREVENTING THE SERVER FROM WORKING PROPERLY."); @@ -1755,12 +1793,12 @@ static int ldap_authenticate(void *instance, REQUEST * request) } if(request->password->attribute != PW_USER_PASSWORD) { - radlog(L_AUTH, "rlm_ldap: Attribute \"User-Password\" is required for authentication. Cannot use \"%s\".", request->password->name); + radlog(L_AUTH, " [%s] Attribute \"User-Password\" is required for authentication. Cannot use \"%s\".", inst->xlat_name, request->password->name); return RLM_MODULE_INVALID; } if (request->password->length == 0) { - snprintf(module_fmsg,sizeof(module_fmsg),"rlm_ldap: empty password supplied"); + snprintf(module_fmsg,sizeof(module_fmsg)," [%s] empty password supplied", inst->xlat_name); module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ); pairadd(&request->packet->vps, module_fmsg_vp); return RLM_MODULE_INVALID; @@ -1778,48 +1816,48 @@ static int ldap_authenticate(void *instance, REQUEST * request) } - DEBUG("rlm_ldap: login attempt by \"%s\" with password \"%s\"", + RDEBUG("login attempt by \"%s\" with password \"%s\"", request->username->vp_strvalue, request->password->vp_strvalue); while ((vp_user_dn = pairfind(request->config_items, - PW_LDAP_USERDN)) == NULL) { + PW_LDAP_USERDN, 0)) == NULL) { if (!radius_xlat(filter, sizeof(filter), inst->filter, request, ldap_escape_func)) { - radlog (L_ERR, "rlm_ldap: unable to create filter.\n"); + radlog(L_ERR, " [%s] unable to create filter.\n", inst->xlat_name); return RLM_MODULE_INVALID; } if (!radius_xlat(basedn, sizeof(basedn), inst->basedn, request, ldap_escape_func)) { - radlog (L_ERR, "rlm_ldap: unable to create basedn.\n"); + radlog(L_ERR, " [%s] unable to create basedn.\n", inst->xlat_name); return RLM_MODULE_INVALID; } if ((conn_id = ldap_get_conn(inst->conns,&conn,inst)) == -1){ - radlog(L_ERR, "rlm_ldap: All ldap connections are in use"); + radlog(L_ERR, " [%s] All ldap connections are in use", inst->xlat_name); return RLM_MODULE_FAIL; } if ((res = perform_search(instance, conn, basedn, LDAP_SCOPE_SUBTREE, filter, attrs, &result)) != RLM_MODULE_OK) { if (res == RLM_MODULE_NOTFOUND){ - snprintf(module_fmsg,sizeof(module_fmsg),"rlm_ldap: User not found"); + snprintf(module_fmsg,sizeof(module_fmsg)," [%s] User not found", inst->xlat_name); module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ); pairadd(&request->packet->vps, module_fmsg_vp); } - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); return (res); } if ((msg = ldap_first_entry(conn->ld, result)) == NULL) { ldap_msgfree(result); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); return RLM_MODULE_FAIL; } if ((user_dn = ldap_get_dn(conn->ld, msg)) == NULL) { - DEBUG("rlm_ldap: ldap_get_dn() failed"); + RDEBUG("ldap_get_dn() failed"); ldap_msgfree(result); - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); return RLM_MODULE_FAIL; } - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); pairadd(&request->config_items, pairmake("Ldap-UserDn", user_dn, T_OP_EQ)); ldap_memfree(user_dn); ldap_msgfree(result); @@ -1827,7 +1865,7 @@ static int ldap_authenticate(void *instance, REQUEST * request) user_dn = vp_user_dn->vp_strvalue; - DEBUG("rlm_ldap: user DN: %s", user_dn); + RDEBUG("user DN: %s", user_dn); #ifndef NOVELL ld_user = ldap_connect(instance, user_dn, request->password->vp_strvalue, @@ -1845,7 +1883,7 @@ static int ldap_authenticate(void *instance, REQUEST * request) LDAP_CONN *conn1; int auth_state = -1; char *challenge = NULL; - int challenge_len = MAX_CHALLENGE_LEN; + size_t challenge_len = MAX_CHALLENGE_LEN; char *state = NULL; dattr = dict_attrbyname("eDir-APC"); @@ -1863,10 +1901,10 @@ static int ldap_authenticate(void *instance, REQUEST * request) if(vp_auth_opt ) { - DEBUG("rlm_ldap: ldap auth option = %s", vp_auth_opt->vp_strvalue); + RDEBUG("ldap auth option = %s", vp_auth_opt->vp_strvalue); strncpy(seq, vp_auth_opt->vp_strvalue, vp_auth_opt->length); seq[vp_auth_opt->length] = '\0'; - if( strcmp(seq, "") ){ + if( strcasecmp(seq, "") ){ /* Get the client IP address to check for packet validity */ inet_ntop(AF_INET, &request->packet->src_ipaddr, host_ipaddr, sizeof(host_ipaddr)); @@ -1878,8 +1916,8 @@ static int ldap_authenticate(void *instance, REQUEST * request) challenge = rad_malloc(MAX_CHALLENGE_LEN); /* If state attribute present in request it is a reply to challenge. */ - if((vp_state = pairfind(request->packet->vps, PW_STATE))!= NULL ){ - DEBUG("rlm_ldap: Response to Access-Challenge"); + if((vp_state = pairfind(request->packet->vps, PW_STATE, 0))!= NULL ){ + RDEBUG("Response to Access-Challenge"); strncpy(challenge, vp_state->vp_strvalue, sizeof(challenge)); challenge_len = vp_state->length; challenge[challenge_len] = 0; @@ -1887,12 +1925,12 @@ static int ldap_authenticate(void *instance, REQUEST * request) } if ((conn_id = ldap_get_conn(inst->conns, &conn1, inst)) == -1){ - radlog(L_ERR, "rlm_ldap: All ldap connections are in use"); + radlog(L_ERR, " [%s] All ldap connections are in use", inst->xlat_name); res = RLM_MODULE_FAIL; } if(!conn1){ - radlog(L_ERR, "rlm_ldap: NULL connection handle passed"); + radlog(L_ERR, " [%s] NULL connection handle passed", inst->xlat_name); return RLM_MODULE_FAIL; } @@ -1905,34 +1943,34 @@ static int ldap_authenticate(void *instance, REQUEST * request) } retry: if (!conn1->bound || conn1->ld == NULL) { - DEBUG2("rlm_ldap: attempting LDAP reconnection"); + DEBUG2(" [%s] attempting LDAP reconnection", inst->xlat_name); if (conn1->ld){ - DEBUG2("rlm_ldap: closing existing LDAP connection"); + DEBUG2(" [%s] closing existing LDAP connection", inst->xlat_name); ldap_unbind_s(conn1->ld); } if ((conn1->ld = ldap_connect(instance, inst->login,inst->password, 0, &res, NULL)) == NULL) { - radlog(L_ERR, "rlm_ldap: (re)connection attempt failed"); + radlog(L_ERR, " [%s] (re)connection attempt failed", inst->xlat_name); conn1->failed_conns++; return (RLM_MODULE_FAIL); } conn1->bound = 1; conn1->failed_conns = 0; } - DEBUG("rlm_ldap: Performing NMAS Authentication for user: %s, seq: %s \n", user_dn,seq); + RDEBUG("Performing NMAS Authentication for user: %s, seq: %s \n", user_dn,seq); res = radLdapXtnNMASAuth(conn1->ld, user_dn, request->password->vp_strvalue, seq, host_ipaddr, &challenge_len, challenge, &auth_state ); switch(res){ case LDAP_SUCCESS: - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); if ( auth_state == -1) res = RLM_MODULE_FAIL; if ( auth_state != REQUEST_CHALLENGED){ if (auth_state == REQUEST_ACCEPTED){ - DEBUG("rlm_ldap: user %s authenticated succesfully",request->username->vp_strvalue); + RDEBUG("user %s authenticated succesfully",request->username->vp_strvalue); res = RLM_MODULE_OK; }else if(auth_state == REQUEST_REJECTED){ - DEBUG("rlm_ldap: user %s authentication failed",request->username->vp_strvalue); + RDEBUG("user %s authentication failed",request->username->vp_strvalue); res = RLM_MODULE_REJECT; } }else{ @@ -1948,16 +1986,16 @@ retry: free(state); /* Mark the packet as a Acceess-Challenge Packet */ request->reply->code = PW_ACCESS_CHALLENGE; - DEBUG("rlm_ldap: Sending Access-Challenge."); + RDEBUG("Sending Access-Challenge."); res = RLM_MODULE_HANDLED; } if(challenge) free(challenge); return res; case LDAP_SERVER_DOWN: - radlog(L_ERR, "rlm_ldap: nmas authentication failed: LDAP connection lost."); conn->failed_conns++; + radlog(L_ERR, " [%s] nmas authentication failed: LDAP connection lost.", inst->xlat_name); conn->failed_conns++; if (conn->failed_conns <= MAX_FAILED_CONNS_START){ - radlog(L_INFO, "rlm_ldap: Attempting reconnect"); + radlog(L_INFO, " [%s] Attempting reconnect", inst->xlat_name); conn->bound = 0; goto retry; } @@ -1965,7 +2003,7 @@ retry: free(challenge); return RLM_MODULE_FAIL; default: - ldap_release_conn(conn_id,inst->conns); + ldap_release_conn(conn_id,inst); if(challenge) free(challenge); return RLM_MODULE_FAIL; @@ -1979,7 +2017,7 @@ retry: if(err != NULL){ /* 'err' contains the LDAP connection error description */ - DEBUG("rlm_ldap: %s", err); + RDEBUG("%s", err); pairadd(&request->reply->vps, pairmake("Reply-Message", err, T_OP_EQ)); ldap_memfree((void *)err); } @@ -1988,18 +2026,18 @@ retry: if (ld_user == NULL){ if (res == RLM_MODULE_REJECT){ inst->failed_conns = 0; - snprintf(module_fmsg,sizeof(module_fmsg),"rlm_ldap: Bind as user failed"); + snprintf(module_fmsg,sizeof(module_fmsg)," [%s] Bind as user failed", inst->xlat_name); module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ); pairadd(&request->packet->vps, module_fmsg_vp); } if (res == RLM_MODULE_FAIL){ - DEBUG("rlm_ldap: ldap_connect() failed"); + RDEBUG("ldap_connect() failed"); inst->failed_conns++; } return (res); } - DEBUG("rlm_ldap: user %s authenticated succesfully", + RDEBUG("user %s authenticated succesfully", request->username->vp_strvalue); ldap_unbind_s(ld_user); inst->failed_conns = 0; @@ -2058,7 +2096,7 @@ static int ldap_postauth(void *instance, REQUEST * request) if (request->reply->code == PW_AUTHENTICATION_REJECT) { /* Bind to eDirectory as the RADIUS user with a wrong password. */ - vp_pwd = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD); + vp_pwd = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD, 0); strcpy(password, vp_pwd->vp_strvalue); if (strlen(password) > 0) { if (password[0] != 'a') { @@ -2072,27 +2110,27 @@ static int ldap_postauth(void *instance, REQUEST * request) res = RLM_MODULE_REJECT; } else { /* Bind to eDirectory as the RADIUS user using the user's UP */ - vp_pwd = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD); + vp_pwd = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD, 0); if (vp_pwd == NULL) { - DEBUG("rlm_ldap: User's Universal Password not in config items list."); + RDEBUG("User's Universal Password not in config items list."); return RLM_MODULE_FAIL; } strcpy(password, vp_pwd->vp_strvalue); } if ((da = dict_attrbyname("Ldap-UserDn")) == NULL) { - DEBUG("rlm_ldap: Attribute for user FDN not found in dictionary. Unable to proceed"); + RDEBUG("Attribute for user FDN not found in dictionary. Unable to proceed"); return RLM_MODULE_FAIL; } - vp_fdn = pairfind(request->packet->vps, da->attr); + vp_fdn = pairfind(request->config_items, da->attr); if (vp_fdn == NULL) { - DEBUG("rlm_ldap: User's FQDN not in config items list."); + RDEBUG("User's FQDN not in config items list."); return RLM_MODULE_FAIL; } if ((conn_id = ldap_get_conn(inst->apc_conns, &conn, inst)) == -1){ - radlog(L_ERR, "rlm_ldap: All ldap connections are in use"); + radlog(L_ERR, " [%s] All ldap connections are in use", inst->xlat_name); return RLM_MODULE_FAIL; } @@ -2104,22 +2142,22 @@ static int ldap_postauth(void *instance, REQUEST * request) */ postauth_reconnect: if (!conn->bound || conn->ld == NULL) { - DEBUG2("rlm_ldap: attempting LDAP reconnection"); + DEBUG2(" [%s] attempting LDAP reconnection", inst->xlat_name); if (conn->ld){ - DEBUG2("rlm_ldap: closing existing LDAP connection"); + DEBUG2(" [%s] closing existing LDAP connection", inst->xlat_name); ldap_unbind_s(conn->ld); } if ((conn->ld = ldap_connect(instance, (char *)vp_fdn->vp_strvalue, password, 0, &res, &error_msg)) == NULL) { - radlog(L_ERR, "rlm_ldap: eDirectory account policy check failed."); + radlog(L_ERR, " [%s] eDirectory account policy check failed.", inst->xlat_name); if (error_msg != NULL) { - DEBUG("rlm_ldap: %s", error_msg); + RDEBUG("%s", error_msg); pairadd(&request->reply->vps, pairmake("Reply-Message", error_msg, T_OP_EQ)); ldap_memfree((void *)error_msg); } vp_apc->vp_strvalue[0] = '3'; - ldap_release_conn(conn_id, inst->apc_conns); + ldap_release_apc_conn(conn_id, inst); return RLM_MODULE_REJECT; } conn->bound = 1; @@ -2128,19 +2166,19 @@ static int ldap_postauth(void *instance, REQUEST * request) conn->bound = 0; goto postauth_reconnect; } - DEBUG("rlm_ldap: eDirectory account policy check failed."); + RDEBUG("eDirectory account policy check failed."); ldap_get_option(conn->ld, LDAP_OPT_ERROR_STRING, &error_msg); if (error_msg != NULL) { - DEBUG("rlm_ldap: %s", error_msg); + RDEBUG("%s", error_msg); pairadd(&request->reply->vps, pairmake("Reply-Message", error_msg, T_OP_EQ)); ldap_memfree((void *)error_msg); } vp_apc->vp_strvalue[0] = '3'; - ldap_release_conn(conn_id, inst->apc_conns); + ldap_release_apc_conn(conn_id, inst); return RLM_MODULE_REJECT; } vp_apc->vp_strvalue[0] = '3'; - ldap_release_conn(conn_id, inst->apc_conns); + ldap_release_apc_conn(conn_id, inst); return RLM_MODULE_OK; } } @@ -2148,6 +2186,18 @@ static int ldap_postauth(void *instance, REQUEST * request) } #endif +#if LDAP_SET_REBIND_PROC_ARGS == 3 +static int ldap_rebind(LDAP *ld, LDAP_CONST char *url, + UNUSED ber_tag_t request, UNUSED ber_int_t msgid, + void *params ) +{ + ldap_instance *inst = params; + + DEBUG(" [%s] rebind to URL %s", inst->xlat_name,url); + return ldap_bind_s(ld, inst->login, inst->password, LDAP_AUTH_SIMPLE); +} +#endif + static LDAP *ldap_connect(void *instance, const char *dn, const char *password, int auth, int *result, char **err) { @@ -2156,78 +2206,142 @@ static LDAP *ldap_connect(void *instance, const char *dn, const char *password, int msgid, rc, ldap_version; int ldap_errno = 0; LDAPMessage *res; + struct timeval tv; if (inst->is_url){ #ifdef HAVE_LDAP_INITIALIZE - DEBUG("rlm_ldap: (re)connect to %s, authentication %d", inst->server, auth); + DEBUG(" [%s] (re)connect to %s, authentication %d", inst->xlat_name, inst->server, auth); if (ldap_initialize(&ld, inst->server) != LDAP_SUCCESS) { - radlog(L_ERR, "rlm_ldap: ldap_initialize() failed"); + radlog(L_ERR, " [%s] ldap_initialize() failed", inst->xlat_name); *result = RLM_MODULE_FAIL; return (NULL); } #endif } else { - DEBUG("rlm_ldap: (re)connect to %s:%d, authentication %d", inst->server, inst->port, auth); + DEBUG(" [%s] (re)connect to %s:%d, authentication %d", inst->xlat_name, inst->server, inst->port, auth); if ((ld = ldap_init(inst->server, inst->port)) == NULL) { - radlog(L_ERR, "rlm_ldap: ldap_init() failed"); + radlog(L_ERR, " [%s] ldap_init() failed", inst->xlat_name); *result = RLM_MODULE_FAIL; return (NULL); } } + tv.tv_sec = inst->net_timeout; + tv.tv_usec = 0; if (ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, - (void *) &(inst->net_timeout)) != LDAP_OPT_SUCCESS) { - radlog(L_ERR, "rlm_ldap: Could not set LDAP_OPT_NETWORK_TIMEOUT %ld.%ld", inst->net_timeout.tv_sec, inst->net_timeout.tv_usec); + (void *) &tv) != LDAP_OPT_SUCCESS) { + ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); + radlog(L_ERR, " [%s] Could not set LDAP_OPT_NETWORK_TIMEOUT %d: %s", inst->xlat_name, inst->net_timeout, ldap_err2string(ldap_errno)); + } + + /* + * Leave "chase_referrals" unset to use the OpenLDAP + * default. + */ + if (inst->chase_referrals != 2) { + if (inst->chase_referrals) { + rc=ldap_set_option(ld, LDAP_OPT_REFERRALS, + LDAP_OPT_ON); + +#if LDAP_SET_REBIND_PROC_ARGS == 3 + if (inst->rebind == 1) { + ldap_set_rebind_proc(ld, ldap_rebind, + inst); + } +#endif + } else { + rc=ldap_set_option(ld, LDAP_OPT_REFERRALS, + LDAP_OPT_OFF); + } + if (rc != LDAP_OPT_SUCCESS) { + ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); + radlog(L_ERR, " [%s] Could not set LDAP_OPT_REFERRALS=%d %s", inst->xlat_name, inst->chase_referrals, ldap_err2string(ldap_errno)); + } } if (ldap_set_option(ld, LDAP_OPT_TIMELIMIT, (void *) &(inst->timelimit)) != LDAP_OPT_SUCCESS) { - radlog(L_ERR, "rlm_ldap: Could not set LDAP_OPT_TIMELIMIT %d", inst->timelimit); + ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); + radlog(L_ERR, " [%s] Could not set LDAP_OPT_TIMELIMIT %d: %s", inst->xlat_name, inst->timelimit, ldap_err2string(ldap_errno)); } if (inst->ldap_debug && ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &(inst->ldap_debug)) != LDAP_OPT_SUCCESS) { - radlog(L_ERR, "rlm_ldap: Could not set LDAP_OPT_DEBUG_LEVEL %d", inst->ldap_debug); + ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); + radlog(L_ERR, " [%s] Could not set LDAP_OPT_DEBUG_LEVEL %d: %s", inst->xlat_name, inst->ldap_debug, ldap_err2string(ldap_errno)); } ldap_version = LDAP_VERSION3; if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldap_version) != LDAP_OPT_SUCCESS) { - radlog(L_ERR, "rlm_ldap: Could not set LDAP version to V3"); + ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); + radlog(L_ERR, " [%s] Could not set LDAP version to V3: %s", inst->xlat_name, ldap_err2string(ldap_errno)); + } + +#ifdef LDAP_OPT_X_KEEPALIVE_IDLE + if (ldap_set_option(ld, LDAP_OPT_X_KEEPALIVE_IDLE, + (void *) &(inst->keepalive_idle)) != LDAP_OPT_SUCCESS) { + ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); + radlog(L_ERR, " [%s] Could not set LDAP_OPT_X_KEEPALIVE_IDLE %d: %s", inst->xlat_name, inst->keepalive_idle, ldap_err2string(ldap_errno)); } +#endif + +#ifdef LDAP_OPT_X_KEEPALIVE_PROBES + if (ldap_set_option(ld, LDAP_OPT_X_KEEPALIVE_PROBES, + (void *) &(inst->keepalive_probes)) != LDAP_OPT_SUCCESS) { + ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); + radlog(L_ERR, " [%s] Could not set LDAP_OPT_X_KEEPALIVE_PROBES %d: %s", inst->xlat_name, inst->keepalive_probes, ldap_err2string(ldap_errno)); + } +#endif + +#ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL + if (ldap_set_option(ld, LDAP_OPT_X_KEEPALIVE_INTERVAL, + (void *) &(inst->keepalive_interval)) != LDAP_OPT_SUCCESS) { + ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); + radlog(L_ERR, " [%s] Could not set LDAP_OPT_X_KEEPALIVE_INTERVAL %d: %s", inst->xlat_name, inst->keepalive_interval, ldap_err2string(ldap_errno)); + } +#endif #ifdef HAVE_LDAP_START_TLS if (inst->tls_mode) { - DEBUG("rlm_ldap: setting TLS mode to %d", inst->tls_mode); + DEBUG(" [%s] setting TLS mode to %d", inst->xlat_name, inst->tls_mode); if (ldap_set_option(ld, LDAP_OPT_X_TLS, (void *) &(inst->tls_mode)) != LDAP_OPT_SUCCESS) { ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); - radlog(L_ERR, "rlm_ldap: could not set LDAP_OPT_X_TLS option %s", ldap_err2string(ldap_errno)); + radlog(L_ERR, " [%s] could not set LDAP_OPT_X_TLS option %s:", inst->xlat_name, ldap_err2string(ldap_errno)); } } if (inst->tls_cacertfile != NULL) { - DEBUG("rlm_ldap: setting TLS CACert File to %s", inst->tls_cacertfile); + DEBUG(" [%s] setting TLS CACert File to %s", inst->xlat_name, inst->tls_cacertfile); if ( ldap_set_option( NULL, LDAP_OPT_X_TLS_CACERTFILE, (void *) inst->tls_cacertfile ) != LDAP_OPT_SUCCESS) { - radlog(L_ERR, "rlm_ldap: could not set " - "LDAP_OPT_X_TLS_CACERTFILE option to %s", inst->tls_cacertfile); + ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); + radlog(L_ERR, " [%s] could not set " + "LDAP_OPT_X_TLS_CACERTFILE option to %s: %s", + inst->xlat_name, + inst->tls_cacertfile, + ldap_err2string(ldap_errno)); } } if (inst->tls_cacertdir != NULL) { - DEBUG("rlm_ldap: setting TLS CACert Directory to %s", inst->tls_cacertdir); + DEBUG(" [%s] setting TLS CACert Directory to %s", inst->xlat_name, inst->tls_cacertdir); if ( ldap_set_option( NULL, LDAP_OPT_X_TLS_CACERTDIR, (void *) inst->tls_cacertdir ) != LDAP_OPT_SUCCESS) { - radlog(L_ERR, "rlm_ldap: could not set " - "LDAP_OPT_X_TLS_CACERTDIR option to %s", inst->tls_cacertdir); + ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); + radlog(L_ERR, " [%s] could not set " + "LDAP_OPT_X_TLS_CACERTDIR option to %s: %s", + inst->xlat_name, + inst->tls_cacertdir, + ldap_err2string(ldap_errno)); } } if (strcmp(TLS_DEFAULT_VERIFY, inst->tls_require_cert ) != 0 ) { - DEBUG("rlm_ldap: setting TLS Require Cert to %s", + DEBUG(" [%s] setting TLS Require Cert to %s", inst->xlat_name, inst->tls_require_cert); } @@ -2235,58 +2349,68 @@ static LDAP *ldap_connect(void *instance, const char *dn, const char *password, #ifdef HAVE_LDAP_INT_TLS_CONFIG if (ldap_int_tls_config(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, (inst->tls_require_cert)) != LDAP_OPT_SUCCESS) { - radlog(L_ERR, "rlm_ldap: could not set " - "LDAP_OPT_X_TLS_REQUIRE_CERT option to %s", - inst->tls_require_cert); + ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); + radlog(L_ERR, " [%s] could not set ", + "LDAP_OPT_X_TLS_REQUIRE_CERT option to %s: %s", + inst->xlat_name, + inst->tls_require_cert, + ldap_err2string(ldap_errno)); } #endif if (inst->tls_certfile != NULL) { - DEBUG("rlm_ldap: setting TLS Cert File to %s", inst->tls_certfile); + DEBUG(" [%s] setting TLS Cert File to %s", inst->xlat_name, inst->tls_certfile); if (ldap_set_option(NULL, LDAP_OPT_X_TLS_CERTFILE, (void *) inst->tls_certfile) != LDAP_OPT_SUCCESS) { - radlog(L_ERR, "rlm_ldap: could not set " - "LDAP_OPT_X_TLS_CERTFILE option to %s", - inst->tls_certfile); + ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); + radlog(L_ERR, " [%s] could not set " + "LDAP_OPT_X_TLS_CERTFILE option to %s: %s", + inst->xlat_name, + inst->tls_certfile, + ldap_err2string(ldap_errno)); } } if (inst->tls_keyfile != NULL) { - DEBUG("rlm_ldap: setting TLS Key File to %s", + DEBUG(" [%s] setting TLS Key File to %s", inst->xlat_name, inst->tls_keyfile); if ( ldap_set_option( NULL, LDAP_OPT_X_TLS_KEYFILE, (void *) inst->tls_keyfile ) != LDAP_OPT_SUCCESS) { - radlog(L_ERR, "rlm_ldap: could not set " - "LDAP_OPT_X_TLS_KEYFILE option to %s", - inst->tls_keyfile); + ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); + radlog(L_ERR, " [%s] could not set " + "LDAP_OPT_X_TLS_KEYFILE option to %s: %s", + inst->xlat_name, + inst->tls_keyfile, ldap_err2string(ldap_errno)); } } if (inst->tls_randfile != NULL) { - DEBUG("rlm_ldap: setting TLS Key File to %s", + DEBUG(" [%s] setting TLS Key File to %s", inst->xlat_name, inst->tls_randfile); if (ldap_set_option(NULL, LDAP_OPT_X_TLS_RANDOM_FILE, (void *) inst->tls_randfile) != LDAP_OPT_SUCCESS) { - radlog(L_ERR, "rlm_ldap: could not set " - "LDAP_OPT_X_TLS_RANDOM_FILE option to %s", - inst->tls_randfile); + ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); + radlog(L_ERR, " [%s] could not set " + "LDAP_OPT_X_TLS_RANDOM_FILE option to %s: %s", + inst->xlat_name, + inst->tls_randfile, ldap_err2string(ldap_errno)); } } if (inst->start_tls) { - DEBUG("rlm_ldap: starting TLS"); + DEBUG(" [%s] starting TLS", inst->xlat_name); rc = ldap_start_tls_s(ld, NULL, NULL); if (rc != LDAP_SUCCESS) { - DEBUG("rlm_ldap: ldap_start_tls_s()"); + DEBUG(" [%s] ldap_start_tls_s()", inst->xlat_name); ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); - radlog(L_ERR, "rlm_ldap: could not start TLS %s", + radlog(L_ERR, " [%s] could not start TLS %s", inst->xlat_name, ldap_err2string(ldap_errno)); *result = RLM_MODULE_FAIL; ldap_unbind_s(ld); @@ -2296,10 +2420,10 @@ static LDAP *ldap_connect(void *instance, const char *dn, const char *password, #endif /* HAVE_LDAP_START_TLS */ if (inst->is_url){ - DEBUG("rlm_ldap: bind as %s/%s to %s", + DEBUG(" [%s] bind as %s/%s to %s", inst->xlat_name, dn, password, inst->server); } else { - DEBUG("rlm_ldap: bind as %s/%s to %s:%d", + DEBUG(" [%s] bind as %s/%s to %s:%d", inst->xlat_name, dn, password, inst->server, inst->port); } @@ -2310,10 +2434,10 @@ static LDAP *ldap_connect(void *instance, const char *dn, const char *password, ldap_get_option(ld, LDAP_OPT_ERROR_STRING, err); } if (inst->is_url) { - radlog(L_ERR, "rlm_ldap: %s bind to %s failed: %s", + radlog(L_ERR, " [%s] %s bind to %s failed: %s", inst->xlat_name, dn, inst->server, ldap_err2string(ldap_errno)); } else { - radlog(L_ERR, "rlm_ldap: %s bind to %s:%d failed: %s", + radlog(L_ERR, " [%s] %s bind to %s:%d failed: %s", inst->xlat_name, dn, inst->server, inst->port, ldap_err2string(ldap_errno)); } @@ -2321,21 +2445,23 @@ static LDAP *ldap_connect(void *instance, const char *dn, const char *password, ldap_unbind_s(ld); return (NULL); } - DEBUG("rlm_ldap: waiting for bind result ..."); + DEBUG(" [%s] waiting for bind result ...", inst->xlat_name); - rc = ldap_result(ld, msgid, 1, &(inst->timeout), &res); + tv.tv_sec = inst->timeout; + tv.tv_usec = 0; + rc = ldap_result(ld, msgid, 1, &tv, &res); if (rc < 1) { - DEBUG("rlm_ldap: ldap_result()"); + DEBUG(" [%s] ldap_result()", inst->xlat_name); ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); if(err != NULL){ ldap_get_option(ld, LDAP_OPT_ERROR_STRING, err); } if (inst->is_url) { - radlog(L_ERR, "rlm_ldap: %s bind to %s failed: %s", + radlog(L_ERR, " [%s] %s bind to %s failed: %s", inst->xlat_name, dn, inst->server, (rc == 0) ? "timeout" : ldap_err2string(ldap_errno)); } else { - radlog(L_ERR, "rlm_ldap: %s bind to %s:%d failed: %s", + radlog(L_ERR, " [%s] %s bind to %s:%d failed: %s", inst->xlat_name, dn, inst->server, inst->port, (rc == 0) ? "timeout" : ldap_err2string(ldap_errno)); } @@ -2347,16 +2473,16 @@ static LDAP *ldap_connect(void *instance, const char *dn, const char *password, ldap_errno = ldap_result2error(ld, res, 1); switch (ldap_errno) { case LDAP_SUCCESS: - DEBUG("rlm_ldap: Bind was successful"); + DEBUG(" [%s] Bind was successful", inst->xlat_name); *result = RLM_MODULE_OK; break; case LDAP_INVALID_CREDENTIALS: if (auth){ - DEBUG("rlm_ldap: Bind failed with invalid credentials"); + DEBUG(" [%s] Bind failed with invalid credentials", inst->xlat_name); *result = RLM_MODULE_REJECT; } else { - radlog(L_ERR, "rlm_ldap: LDAP login failed: check identity, password settings in ldap section of radiusd.conf"); + radlog(L_ERR, " [%s] LDAP login failed: check identity, password settings in ldap section of radiusd.conf", inst->xlat_name); *result = RLM_MODULE_FAIL; } if(err != NULL){ @@ -2364,12 +2490,20 @@ static LDAP *ldap_connect(void *instance, const char *dn, const char *password, } break; + case LDAP_CONSTRAINT_VIOLATION: + DEBUG("rlm_ldap: Bind failed with constraint violation"); + *result = RLM_MODULE_REJECT; + if(err != NULL){ + ldap_get_option(ld, LDAP_OPT_ERROR_STRING, err); + } + break; + default: if (inst->is_url) { - radlog(L_ERR,"rlm_ldap: %s bind to %s failed %s", + radlog(L_ERR," [%s] %s bind to %s failed %s", inst->xlat_name, dn, inst->server, ldap_err2string(ldap_errno)); } else { - radlog(L_ERR,"rlm_ldap: %s bind to %s:%d failed %s", + radlog(L_ERR," [%s] %s bind to %s:%d failed %s", inst->xlat_name, dn, inst->server, inst->port, ldap_err2string(ldap_errno)); } @@ -2491,7 +2625,7 @@ fieldcpy(char *string, char **uptr) /* * Copied from src/lib/token.c */ -static const LRAD_NAME_NUMBER tokens[] = { +static const FR_NAME_NUMBER tokens[] = { { "=~", T_OP_REG_EQ, }, /* order is important! */ { "!~", T_OP_REG_NE, }, { "{", T_LCBRACE, }, @@ -2522,15 +2656,16 @@ static const LRAD_NAME_NUMBER tokens[] = { *****************************************************************************/ static VALUE_PAIR *ldap_pairget(LDAP *ld, LDAPMessage *entry, TLDAP_RADIUS *item_map, - VALUE_PAIR **pairs, int is_check) + VALUE_PAIR **pairs, int is_check, + ldap_instance *inst) { char **vals; int vals_count; int vals_idx; - char *ptr; - char *value; + const char *ptr; + const char *value; TLDAP_RADIUS *element; - LRAD_TOKEN token, operator; + FR_TOKEN token, operator; int is_generic_attribute; char buf[MAX_STRING_LEN]; VALUE_PAIR *pairlist = NULL; @@ -2572,15 +2707,15 @@ static VALUE_PAIR *ldap_pairget(LDAP *ld, LDAPMessage *entry, /* * This is a generic attribute. */ - LRAD_TOKEN dummy; /* makes pairread happy */ + FR_TOKEN dummy; /* makes pairread happy */ /* not sure if using pairread here is ok ... */ if ( (newpair = pairread(&value, &dummy)) != NULL) { - DEBUG("rlm_ldap: extracted attribute %s from generic item %s", + DEBUG(" [%s] extracted attribute %s from generic item %s", inst->xlat_name, newpair->name, vals[vals_idx]); pairadd(&pairlist, newpair); } else { - radlog(L_ERR, "rlm_ldap: parsing %s failed: %s", + radlog(L_ERR, " [%s] parsing %s failed: %s", inst->xlat_name, element->attr, vals[vals_idx]); } } else { @@ -2630,7 +2765,7 @@ static VALUE_PAIR *ldap_pairget(LDAP *ld, LDAPMessage *entry, } } if (value[0] == '\0') { - DEBUG("rlm_ldap: Attribute %s has no value", element->attr); + DEBUG(" [%s] Attribute %s has no value", inst->xlat_name, element->attr); continue; } @@ -2641,7 +2776,7 @@ static VALUE_PAIR *ldap_pairget(LDAP *ld, LDAPMessage *entry, do_xlat ? NULL : value, operator); if (newpair == NULL) { - radlog(L_ERR, "rlm_ldap: Failed to create the pair: %s", librad_errstr); + radlog(L_ERR, " [%s] Failed to create the pair: %s", inst->xlat_name, fr_strerror()); continue; } @@ -2653,7 +2788,7 @@ static VALUE_PAIR *ldap_pairget(LDAP *ld, LDAPMessage *entry, } vp_prints(print_buffer, sizeof(print_buffer), newpair); - DEBUG("rlm_ldap: LDAP attribute %s as RADIUS attribute %s", + DEBUG(" [%s] %s -> %s", inst->xlat_name, element->attr, print_buffer); @@ -2661,7 +2796,7 @@ static VALUE_PAIR *ldap_pairget(LDAP *ld, LDAPMessage *entry, * Add the pair into the packet. */ if (!vals_idx){ - pairdelete(pairs, newpair->attribute); + pairdelete(pairs, newpair->attribute, newpair->vendor); } pairadd(&pairlist, newpair); }