From: Arran Cudbard-Bell Date: Fri, 15 Dec 2017 23:51:21 +0000 (+0000) Subject: Start plumbing in rlm_sim fast reauthentication X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=87abf5e2e7031ea4a89ea845cee08c7787e63bee;p=thirdparty%2Ffreeradius-server.git Start plumbing in rlm_sim fast reauthentication --- diff --git a/src/modules/rlm_eap/types/rlm_eap_sim/eap_sim.h b/src/modules/rlm_eap/types/rlm_eap_sim/eap_sim.h index 1c7644e1eab..110b5ed5b22 100644 --- a/src/modules/rlm_eap/types/rlm_eap_sim/eap_sim.h +++ b/src/modules/rlm_eap/types/rlm_eap_sim/eap_sim.h @@ -35,6 +35,7 @@ RCSIDH(rlm_eap_sim_eap_sim_h, "$Id$") typedef enum { EAP_SIM_SERVER_START = 0, EAP_SIM_SERVER_CHALLENGE, + EAP_SIM_SERVER_REAUTHENTICATE, EAP_SIM_SERVER_SUCCESS_NOTIFICATION, EAP_SIM_SERVER_SUCCESS, EAP_SIM_SERVER_FAILURE_NOTIFICATION, diff --git a/src/modules/rlm_eap/types/rlm_eap_sim/rlm_eap_sim.c b/src/modules/rlm_eap/types/rlm_eap_sim/rlm_eap_sim.c index 2dfa4c11431..e364a85a622 100644 --- a/src/modules/rlm_eap/types/rlm_eap_sim/rlm_eap_sim.c +++ b/src/modules/rlm_eap/types/rlm_eap_sim/rlm_eap_sim.c @@ -42,6 +42,7 @@ RCSID("$Id$") FR_NAME_NUMBER const sim_state_table[] = { { "START", EAP_SIM_SERVER_START }, { "CHALLENGE", EAP_SIM_SERVER_CHALLENGE }, + { "REAUTHENTICATE", EAP_SIM_SERVER_REAUTHENTICATE }, { "SUCCESS-NOTIFICATION", EAP_SIM_SERVER_SUCCESS_NOTIFICATION }, { "SUCCESS", EAP_SIM_SERVER_SUCCESS }, { "FAILURE-NOTIFICATION", EAP_SIM_SERVER_FAILURE_NOTIFICATION }, @@ -301,34 +302,19 @@ static int eap_sim_send_challenge(eap_session_t *eap_session) return 0; } +/** Send NONCE_S and re-key + * + */ static int eap_sim_send_reauthentication(eap_session_t *eap_session) { REQUEST *request = eap_session->request; eap_sim_session_t *eap_sim_session = talloc_get_type_abort(eap_session->opaque, eap_sim_session_t); - VALUE_PAIR **to_peer, *vp; + VALUE_PAIR **to_peer, *vp, *mk, *counter; RADIUS_PACKET *packet; - fr_sim_vector_src_t src = SIM_VECTOR_SRC_AUTO; rad_assert(eap_session->request != NULL); rad_assert(eap_session->request->reply); - RDEBUG2("Acquiring GSM vector(s)"); - if ((fr_sim_vector_gsm_from_attrs(eap_session, request->control, 0, &eap_sim_session->keys, &src) != 0) || - (fr_sim_vector_gsm_from_attrs(eap_session, request->control, 1, &eap_sim_session->keys, &src) != 0) || - (fr_sim_vector_gsm_from_attrs(eap_session, request->control, 2, &eap_sim_session->keys, &src) != 0)) { - REDEBUG("Failed retrieving SIM vectors"); - return RLM_MODULE_FAIL; - } - - /* - * All set, calculate keys! - */ - fr_sim_crypto_kdf_0_gsm(&eap_sim_session->keys); - if (RDEBUG_ENABLED3) fr_sim_crypto_keys_log(request, &eap_sim_session->keys); - - RDEBUG2("Sending SIM-Challenge"); - eap_session->this_round->request->code = FR_EAP_CODE_REQUEST; - /* * to_peer is the data to the client */ @@ -336,25 +322,48 @@ static int eap_sim_send_reauthentication(eap_session_t *eap_session) to_peer = &packet->vps; /* - * Okay, we got the challenges! Put them into attributes. + * If any of the session resumption inputs (on our side) + * are missing or malformed, return an error code + * and the state machine will jump to the start state. */ - MEM(vp = fr_pair_afrom_child_num(packet, dict_sim_root, FR_EAP_SIM_RAND)); - fr_pair_value_memcpy(vp, eap_sim_session->keys.gsm.vector[0].rand, SIM_VECTOR_GSM_RAND_SIZE); - fr_pair_add(to_peer, vp); + mk = fr_pair_find_by_child_num(request->control, dict_sim_root, FR_EAP_SIM_MK, TAG_ANY); + if (!mk) { + RWDEBUG2("Missing &control:EAP-SIM-MK, skipping session resumption"); + return -1; + } + if (mk->vp_length != SIM_MK_SIZE) { + RWDEBUG("&control:EAP-SIM-MK has incorrect length, expected %u bytes got %zu bytes", + SIM_MK_SIZE, mk->vp_length); + return -1; + } + counter = fr_pair_find_by_child_num(request->control, dict_sim_root, FR_EAP_SIM_COUNTER, TAG_ANY); + if (!counter) { + RWDEBUG2("Missing &control:EAP-SIM-Counter, skipping session resumption"); + return -1; + } - MEM(vp = fr_pair_afrom_child_num(packet, dict_sim_root, FR_EAP_SIM_RAND)); - fr_pair_value_memcpy(vp, eap_sim_session->keys.gsm.vector[1].rand, SIM_VECTOR_GSM_RAND_SIZE); - fr_pair_add(to_peer, vp); + /* + * All set, calculate keys! + */ + fr_sim_crypto_keys_init_kdf_0_reauth(&eap_sim_session->keys, mk->vp_octets, counter->vp_uint16); + fr_sim_crypto_kdf_0_reauth(&eap_sim_session->keys); + if (RDEBUG_ENABLED3) fr_sim_crypto_keys_log(request, &eap_sim_session->keys); - MEM(vp = fr_pair_afrom_child_num(packet, dict_sim_root, FR_EAP_SIM_RAND)); - fr_pair_value_memcpy(vp, eap_sim_session->keys.gsm.vector[2].rand, SIM_VECTOR_GSM_RAND_SIZE); - fr_pair_add(to_peer, vp); + RDEBUG2("Sending SIM-Reauthentication"); + eap_session->this_round->request->code = FR_EAP_CODE_REQUEST; /* * Set subtype to challenge. */ vp = fr_pair_afrom_child_num(packet, dict_sim_root, FR_EAP_SIM_SUBTYPE); - vp->vp_uint16 = EAP_SIM_CHALLENGE; + vp->vp_uint16 = EAP_SIM_REAUTH; + fr_pair_replace(to_peer, vp); + + /* + * Add nonce_s + */ + MEM(vp = fr_pair_afrom_child_num(packet, dict_sim_root, FR_EAP_SIM_NONCE_S)); + fr_pair_value_memcpy(vp, eap_sim_session->keys.reauth.nonce_s, sizeof(eap_sim_session->keys.reauth.nonce_s)); fr_pair_replace(to_peer, vp); /* @@ -382,8 +391,7 @@ static int eap_sim_send_reauthentication(eap_session_t *eap_session) /* * Encode the packet */ - if (eap_sim_compose(eap_session, - eap_sim_session->keys.gsm.nonce_mt, sizeof(eap_sim_session->keys.gsm.nonce_mt)) < 0) { + if (eap_sim_compose(eap_session, NULL, 0) < 0) { fr_pair_list_free(&packet->vps); return -1; } @@ -558,6 +566,7 @@ static void eap_sim_state_enter(eap_session_t *eap_session, eap_sim_server_state * Send our version list */ case EAP_SIM_SERVER_START: + start: if (eap_sim_send_start(eap_session) < 0) { notify_failure: eap_sim_state_enter(eap_session, EAP_SIM_SERVER_FAILURE_NOTIFICATION); @@ -572,6 +581,10 @@ static void eap_sim_state_enter(eap_session_t *eap_session, eap_sim_server_state if (eap_sim_send_challenge(eap_session) < 0) goto notify_failure; break; + case EAP_SIM_SERVER_REAUTHENTICATE: + if (eap_sim_send_reauthentication(eap_session) < 0) goto start; + break; + /* * Sent a protected success notification */