Fix parameter passing issue. closes bug #105
[freeradius.git] / src / modules / rlm_ldap / rlm_ldap.c
index b813973..fabe118 100644 (file)
@@ -146,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;
@@ -173,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"},
@@ -259,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
@@ -315,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}
 };
 
@@ -367,6 +391,18 @@ static inline void ldap_release_conn(int i, ldap_instance *inst)
        pthread_mutex_unlock(&(conns[i].mutex));
 }
 
+#ifdef NOVELL
+static inline void ldap_release_apc_conn(int i, ldap_instance *inst)
+                                    
+{
+       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
+
 /*************************************************************************
  *
  *     Function: rlm_ldap_instantiate
@@ -482,13 +518,13 @@ 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, "LDAP");
+               if (!dv) dv = dict_valbyname(PW_AUTH_TYPE, 0, "LDAP");
                if (!dv) {
                        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;
@@ -1503,40 +1539,12 @@ 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 ((size_t)(p - value + 1) >= sizeof(autobuf))
-                                               continue; /* paranoia */
-                                       memcpy(autobuf, value, p - value + 1);
-                                       autobuf[p - value + 1] = '\0';
-
-                                       attr = fr_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 {
-                                               RDEBUG("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));
@@ -1571,16 +1579,6 @@ static int ldap_authorize(void *instance, REQUEST * request)
 
                                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
-                                                       RDEBUG("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));
@@ -1654,7 +1652,7 @@ static int ldap_authorize(void *instance, REQUEST * request)
                                if ((vp_auth_opt = paircreate(auth_opt_attr, PW_TYPE_STRING)) == NULL){
                                        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]);
@@ -1721,7 +1719,9 @@ static int ldap_authorize(void *instance, REQUEST * request)
        */
        if (debug_flag > 1) {
               if (!pairfind(request->config_items, PW_CLEARTEXT_PASSWORD, 0) &&
-                  !pairfind(request->config_items, PW_USER_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?");
               }
        }
@@ -1820,7 +1820,7 @@ static int ldap_authenticate(void *instance, REQUEST * request)
               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, "  [%s] unable to create filter.\n", inst->xlat_name);
@@ -1883,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");
@@ -2157,7 +2157,7 @@ static int ldap_postauth(void *instance, REQUEST * request)
                                                }
 
                                                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;
@@ -2174,11 +2174,11 @@ static int ldap_postauth(void *instance, REQUEST * request)
                                                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;
                        }
        }
@@ -2276,6 +2276,30 @@ static LDAP *ldap_connect(void *instance, const char *dn, const char *password,
                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("  [%s] setting TLS mode to %d", inst->xlat_name, inst->tls_mode);
@@ -2466,6 +2490,14 @@ 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,"  [%s] %s bind to %s failed %s", inst->xlat_name,
@@ -2764,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);
                        }