+
+ res = 0;
+
+ dattr = dict_attrbyname("eDir-Auth-Option");
+ auth_opt_attr = dattr->attr;
+
+ vp_auth_opt = pairfind(request->config_items, auth_opt_attr);
+
+ if(vp_auth_opt )
+ {
+ 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( strcasecmp(seq, "<No Default>") ){
+
+ /* Get the client IP address to check for packet validity */
+ inet_ntop(AF_INET, &request->packet->src_ipaddr, host_ipaddr, sizeof(host_ipaddr));
+
+ /* challenge variable is used to receive the challenge from the
+ * Token method (if any) and also to send the state attribute
+ * in case the request packet is a reply to a challenge
+ */
+ 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, 0))!= NULL ){
+ RDEBUG("Response to Access-Challenge");
+ strncpy(challenge, vp_state->vp_strvalue, sizeof(challenge));
+ challenge_len = vp_state->length;
+ challenge[challenge_len] = 0;
+ auth_state = -2;
+ }
+
+ if ((conn_id = ldap_get_conn(inst->conns, &conn1, inst)) == -1){
+ radlog(L_ERR, " [%s] All ldap connections are in use", inst->xlat_name);
+ res = RLM_MODULE_FAIL;
+ }
+
+ if(!conn1){
+ radlog(L_ERR, " [%s] NULL connection handle passed", inst->xlat_name);
+ return RLM_MODULE_FAIL;
+ }
+
+ if (conn1->failed_conns > MAX_FAILED_CONNS_START){
+ conn1->failed_conns++;
+ if (conn1->failed_conns >= MAX_FAILED_CONNS_END){
+ conn1->failed_conns = MAX_FAILED_CONNS_RESTART;
+ conn1->bound = 0;
+ }
+ }
+retry:
+ if (!conn1->bound || conn1->ld == NULL) {
+ DEBUG2(" [%s] attempting LDAP reconnection", inst->xlat_name);
+ if (conn1->ld){
+ 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, " [%s] (re)connection attempt failed", inst->xlat_name);
+ conn1->failed_conns++;
+ return (RLM_MODULE_FAIL);
+ }
+ conn1->bound = 1;
+ conn1->failed_conns = 0;
+ }
+ 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);
+ if ( auth_state == -1)
+ res = RLM_MODULE_FAIL;
+ if ( auth_state != REQUEST_CHALLENGED){
+ if (auth_state == REQUEST_ACCEPTED){
+ RDEBUG("user %s authenticated succesfully",request->username->vp_strvalue);
+ res = RLM_MODULE_OK;
+ }else if(auth_state == REQUEST_REJECTED){
+ RDEBUG("user %s authentication failed",request->username->vp_strvalue);
+ res = RLM_MODULE_REJECT;
+ }
+ }else{
+ /* Request challenged. Generate Reply-Message attribute with challenge data */
+ pairadd(&request->reply->vps,pairmake("Reply-Message", challenge, T_OP_EQ));
+ /* Generate state attribute */
+ state = rad_malloc(MAX_CHALLENGE_LEN);
+ (void) sprintf(state, "%s%s", challenge, challenge);
+ vp_state = paircreate(PW_STATE, PW_TYPE_OCTETS);
+ memcpy(vp_state->vp_strvalue, state, strlen(state));
+ vp_state->length = strlen(state);
+ pairadd(&request->reply->vps, vp_state);
+ free(state);
+ /* Mark the packet as a Acceess-Challenge Packet */
+ request->reply->code = PW_ACCESS_CHALLENGE;
+ RDEBUG("Sending Access-Challenge.");
+ res = RLM_MODULE_HANDLED;
+ }
+ if(challenge)
+ free(challenge);
+ return res;
+ case LDAP_SERVER_DOWN:
+ 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, " [%s] Attempting reconnect", inst->xlat_name);
+ conn->bound = 0;
+ goto retry;
+ }
+ if(challenge)
+ free(challenge);
+ return RLM_MODULE_FAIL;
+ default:
+ ldap_release_conn(conn_id,inst);
+ if(challenge)
+ free(challenge);
+ return RLM_MODULE_FAIL;
+ }
+ }
+ }
+ }
+
+ ld_user = ldap_connect(instance, user_dn, request->password->vp_strvalue,
+ 1, &res, &err);
+
+ if(err != NULL){
+ /* 'err' contains the LDAP connection error description */
+ RDEBUG("%s", err);
+ pairadd(&request->reply->vps, pairmake("Reply-Message", err, T_OP_EQ));
+ ldap_memfree((void *)err);