/* * Add a handler to the set of active sessions. * * Since we're adding it to the list, we guess that this means * the packet needs a State attribute. So add one. */ static int eaplist_add(rlm_eap_t *inst, EAP_HANDLER *handler) { int i, status; uint32_t lvalue; VALUE_PAIR *state; rad_assert(handler != NULL); rad_assert(handler->request != NULL); /* * Generate State, since we've been asked to add it to * the list. */ state = pairmake("State", "0x00", T_OP_EQ); if (!state) return 0; pairadd(&(handler->request->reply->vps), state); state->length = EAP_STATE_LEN; /* * The time at which this request was made was the time * at which it was received by the RADIUS server. */ handler->timestamp = handler->request->timestamp; handler->src_ipaddr = handler->request->packet->src_ipaddr; /* * We don't need this any more. */ handler->request = NULL; /* * Playing with a data structure shared among threads * means that we need a lock, to avoid conflict. */ pthread_mutex_lock(&(inst->session_mutex)); /* * Create a completely random state. */ for (i = 0; i < 4; i++) { lvalue = eap_rand(&inst->rand_pool); memcpy(state->vp_octets + i * 4, &lvalue, sizeof(lvalue)); } memcpy(handler->state, state->vp_strvalue, sizeof(handler->state)); /* * Big-time failure. */ status = rbtree_insert(inst->session_tree, handler); if (status) { EAP_HANDLER *prev; prev = inst->session_tail; if (prev) { prev->next = handler; handler->prev = prev; handler->next = NULL; inst->session_tail = handler; } else { inst->session_head = inst->session_tail = handler; handler->next = handler->prev = NULL; } } /* * Now that we've finished mucking with the list, * unlock it. */ pthread_mutex_unlock(&(inst->session_mutex)); if (!status) { radlog(L_ERR, "rlm_eap2: Failed to remember handler!"); eap_handler_free(handler); return 0; } return 1; }
/* * Add a handler to the set of active sessions. * * Since we're adding it to the list, we guess that this means * the packet needs a State attribute. So add one. */ int eaplist_add(rlm_eap_t *inst, eap_handler_t *handler) { int status = 0; VALUE_PAIR *state; REQUEST *request = handler->request; rad_assert(handler != NULL); rad_assert(request != NULL); /* * Generate State, since we've been asked to add it to * the list. */ state = pairmake_reply("State", "0x00", T_OP_EQ); if (!state) return 0; /* * The time at which this request was made was the time * at which it was received by the RADIUS server. */ handler->timestamp = request->timestamp; handler->status = 1; handler->src_ipaddr = request->packet->src_ipaddr; handler->eap_id = handler->eap_ds->request->id; /* * Playing with a data structure shared among threads * means that we need a lock, to avoid conflict. */ PTHREAD_MUTEX_LOCK(&(inst->session_mutex)); /* * If we have a DoS attack, discard new sessions. */ if (rbtree_num_elements(inst->session_tree) >= inst->max_sessions) { status = -1; eaplist_expire(inst, request, handler->timestamp); goto done; } /* * Create a unique content for the State variable. * It will be modified slightly per round trip, but less so * than in 1.x. */ if (handler->trips == 0) { int i; for (i = 0; i < 4; i++) { uint32_t lvalue; lvalue = eap_rand(&inst->rand_pool); memcpy(handler->state + i * 4, &lvalue, sizeof(lvalue)); } } memcpy(state->vp_octets, handler->state, sizeof(handler->state)); state->length = EAP_STATE_LEN; /* * Add some more data to distinguish the sessions. */ state->vp_octets[4] = handler->trips ^ handler->state[0]; state->vp_octets[5] = handler->eap_id ^ handler->state[1]; state->vp_octets[6] = handler->type ^ handler->state[2]; /* * and copy the state back again. */ memcpy(handler->state, state->vp_octets, sizeof(handler->state)); /* * Big-time failure. */ status = rbtree_insert(inst->session_tree, handler); /* * Catch Access-Challenge without response. */ if (inst->handler_tree) { check_handler_t *check = rad_malloc(sizeof(*check)); check->inst = inst; check->handler = handler; check->trips = handler->trips; request_data_add(request, inst, 0, check, check_handler); } if (status) { eap_handler_t *prev; prev = inst->session_tail; if (prev) { prev->next = handler; handler->prev = prev; handler->next = NULL; inst->session_tail = handler; } else { inst->session_head = inst->session_tail = handler; handler->next = handler->prev = NULL; } } /* * Now that we've finished mucking with the list, * unlock it. */ done: /* * We don't need this any more. */ if (status > 0) handler->request = NULL; PTHREAD_MUTEX_UNLOCK(&(inst->session_mutex)); if (status <= 0) { pairfree(&state); if (status < 0) { static time_t last_logged = 0; if (last_logged < handler->timestamp) { last_logged = handler->timestamp; radlog(L_ERR, "rlm_eap (%s): Too many open " "sessions. Try increasing " "\"max_sessions\" in the EAP module " "configuration", inst->xlat_name); } } else { radlog(L_ERR, "rlm_eap (%s): Internal error: " "failed to store handler", inst->xlat_name); } return 0; } RDEBUG("New EAP session, adding 'State' attribute to reply " "0x%02x%02x%02x%02x%02x%02x%02x%02x", state->vp_octets[0], state->vp_octets[1], state->vp_octets[2], state->vp_octets[3], state->vp_octets[4], state->vp_octets[5], state->vp_octets[6], state->vp_octets[7]); return 1; }