diff --git a/src/libcharon/plugins/eap_aka/eap_aka_peer.c b/src/libcharon/plugins/eap_aka/eap_aka_peer.c index 8c392405e..8a5fbe690 100644 --- a/src/libcharon/plugins/eap_aka/eap_aka_peer.c +++ b/src/libcharon/plugins/eap_aka/eap_aka_peer.c @@ -80,13 +80,31 @@ struct private_eap_aka_peer_t { u_int16_t counter; }; +/** + * Generate a payload from a message, destroy message + */ +static bool generate_payload(simaka_message_t *message, chunk_t data, + eap_payload_t **out) +{ + chunk_t chunk; + bool ok; + + ok = message->generate(message, data, &chunk); + if (ok) + { + *out = eap_payload_create_data_own(chunk); + } + message->destroy(message); + return ok; +} + /** * Create a AKA_CLIENT_ERROR: "Unable to process" */ -static eap_payload_t* create_client_error(private_eap_aka_peer_t *this) +static bool create_client_error(private_eap_aka_peer_t *this, + eap_payload_t **out) { simaka_message_t *message; - eap_payload_t *out; u_int16_t encoded; DBG1(DBG_IKE, "sending client error '%N'", @@ -97,9 +115,8 @@ static eap_payload_t* create_client_error(private_eap_aka_peer_t *this) encoded = htons(AKA_UNABLE_TO_PROCESS); message->add_attribute(message, AT_CLIENT_ERROR_CODE, chunk_create((char*)&encoded, sizeof(encoded))); - out = eap_payload_create_data_own(message->generate(message, chunk_empty)); - message->destroy(message); - return out; + + return generate_payload(message, chunk_empty, out); } /** @@ -134,8 +151,11 @@ static status_t process_identity(private_eap_aka_peer_t *this, default: if (!simaka_attribute_skippable(type)) { - *out = create_client_error(this); enumerator->destroy(enumerator); + if (!create_client_error(this, out)) + { + return FAILED; + } return NEED_MORE; } break; @@ -175,9 +195,10 @@ static status_t process_identity(private_eap_aka_peer_t *this, { message->add_attribute(message, AT_IDENTITY, id); } - *out = eap_payload_create_data_own(message->generate(message, chunk_empty)); - message->destroy(message); - + if (!generate_payload(message, chunk_empty, out)) + { + return FAILED; + } return NEED_MORE; } @@ -210,8 +231,11 @@ static status_t process_challenge(private_eap_aka_peer_t *this, default: if (!simaka_attribute_skippable(type)) { - *out = create_client_error(this); enumerator->destroy(enumerator); + if (!create_client_error(this, out)) + { + return FAILED; + } return NEED_MORE; } break; @@ -222,7 +246,10 @@ static status_t process_challenge(private_eap_aka_peer_t *this, if (!rand.len || !autn.len) { DBG1(DBG_IKE, "received invalid EAP-AKA challenge message"); - *out = create_client_error(this); + if (!create_client_error(this, out)) + { + return FAILED; + } return NEED_MORE; } @@ -237,9 +264,10 @@ static status_t process_challenge(private_eap_aka_peer_t *this, AKA_SYNCHRONIZATION_FAILURE, this->crypto); message->add_attribute(message, AT_AUTS, chunk_create(auts, AKA_AUTS_LEN)); - *out = eap_payload_create_data_own(message->generate(message, - chunk_empty)); - message->destroy(message); + if (!generate_payload(message, chunk_empty, out)) + { + return FAILED; + } return NEED_MORE; } if (status != SUCCESS) @@ -248,9 +276,10 @@ static status_t process_challenge(private_eap_aka_peer_t *this, this->permanent, simaka_subtype_names, AKA_AUTHENTICATION_REJECT); message = simaka_message_create(FALSE, in->get_identifier(in), EAP_AKA, AKA_AUTHENTICATION_REJECT, this->crypto); - *out = eap_payload_create_data_own(message->generate(message, - chunk_empty)); - message->destroy(message); + if (!generate_payload(message, chunk_empty, out)) + { + return FAILED; + } return NEED_MORE; } @@ -270,7 +299,10 @@ static status_t process_challenge(private_eap_aka_peer_t *this, * reading encrypted attributes */ if (!in->verify(in, chunk_empty) || !in->parse(in)) { - *out = create_client_error(this); + if (!create_client_error(this, out)) + { + return FAILED; + } return NEED_MORE; } @@ -300,8 +332,10 @@ static status_t process_challenge(private_eap_aka_peer_t *this, message = simaka_message_create(FALSE, this->identifier, EAP_AKA, AKA_CHALLENGE, this->crypto); message->add_attribute(message, AT_RES, chunk_create(res, res_len)); - *out = eap_payload_create_data_own(message->generate(message, chunk_empty)); - message->destroy(message); + if (!generate_payload(message, chunk_empty, out)) + { + return FAILED; + } return NEED_MORE; } @@ -332,7 +366,10 @@ static status_t process_reauthentication(private_eap_aka_peer_t *this, { DBG1(DBG_IKE, "received %N, but not expected", simaka_subtype_names, AKA_REAUTHENTICATION); - *out = create_client_error(this); + if (!create_client_error(this, out)) + { + return FAILED; + } return NEED_MORE; } @@ -342,7 +379,10 @@ static status_t process_reauthentication(private_eap_aka_peer_t *this, /* verify MAC and parse again with decryption key */ if (!in->verify(in, chunk_empty) || !in->parse(in)) { - *out = create_client_error(this); + if (!create_client_error(this, out)) + { + return FAILED; + } return NEED_MORE; } @@ -363,8 +403,11 @@ static status_t process_reauthentication(private_eap_aka_peer_t *this, default: if (!simaka_attribute_skippable(type)) { - *out = create_client_error(this); enumerator->destroy(enumerator); + if (!create_client_error(this, out)) + { + return FAILED; + } return NEED_MORE; } break; @@ -375,7 +418,10 @@ static status_t process_reauthentication(private_eap_aka_peer_t *this, if (!nonce.len || !counter.len) { DBG1(DBG_IKE, "EAP-AKA/Request/Reauthentication message incomplete"); - *out = create_client_error(this); + if (!create_client_error(this, out)) + { + return FAILED; + } return NEED_MORE; } @@ -403,8 +449,10 @@ static status_t process_reauthentication(private_eap_aka_peer_t *this, } } message->add_attribute(message, AT_COUNTER, counter); - *out = eap_payload_create_data_own(message->generate(message, nonce)); - message->destroy(message); + if (!generate_payload(message, nonce, out)) + { + return FAILED; + } return NEED_MORE; } @@ -454,13 +502,17 @@ static status_t process_notification(private_eap_aka_peer_t *this, { /* empty notification reply */ message = simaka_message_create(FALSE, this->identifier, EAP_AKA, AKA_NOTIFICATION, this->crypto); - *out = eap_payload_create_data_own(message->generate(message, - chunk_empty)); - message->destroy(message); + if (!generate_payload(message, chunk_empty, out)) + { + return FAILED; + } } else { - *out = create_client_error(this); + if (!create_client_error(this, out)) + { + return FAILED; + } } return NEED_MORE; } @@ -478,13 +530,19 @@ METHOD(eap_method_t, process, status_t, message = simaka_message_create_from_payload(in->get_data(in), this->crypto); if (!message) { - *out = create_client_error(this); + if (!create_client_error(this, out)) + { + return FAILED; + } return NEED_MORE; } if (!message->parse(message)) { message->destroy(message); - *out = create_client_error(this); + if (!create_client_error(this, out)) + { + return FAILED; + } return NEED_MORE; } switch (message->get_subtype(message)) @@ -504,8 +562,14 @@ METHOD(eap_method_t, process, status_t, default: DBG1(DBG_IKE, "unable to process EAP-AKA subtype %N", simaka_subtype_names, message->get_subtype(message)); - *out = create_client_error(this); - status = NEED_MORE; + if (!create_client_error(this, out)) + { + status = FAILED; + } + else + { + status = NEED_MORE; + } break; } message->destroy(message); diff --git a/src/libcharon/plugins/eap_aka/eap_aka_server.c b/src/libcharon/plugins/eap_aka/eap_aka_server.c index 319cc45be..ac4cd15d7 100644 --- a/src/libcharon/plugins/eap_aka/eap_aka_server.c +++ b/src/libcharon/plugins/eap_aka/eap_aka_server.c @@ -118,6 +118,24 @@ struct private_eap_aka_server_t { bool synchronized; }; +/** + * Generate a payload from a message, destroy message + */ +static bool generate_payload(simaka_message_t *message, chunk_t data, + eap_payload_t **out) +{ + chunk_t chunk; + bool ok; + + ok = message->generate(message, data, &chunk); + if (ok) + { + *out = eap_payload_create_data_own(chunk); + } + message->destroy(message); + return ok; +} + /** * Create EAP-AKA/Request/Identity message */ @@ -139,9 +157,10 @@ static status_t identity(private_eap_aka_server_t *this, eap_payload_t **out) { message->add_attribute(message, AT_PERMANENT_ID_REQ, chunk_empty); } - *out = eap_payload_create_data_own(message->generate(message, chunk_empty)); - message->destroy(message); - + if (!generate_payload(message, chunk_empty, out)) + { + return FAILED; + } this->pending = AKA_IDENTITY; return NEED_MORE; } @@ -190,6 +209,7 @@ static status_t challenge(private_eap_aka_server_t *this, eap_payload_t **out) message->add_attribute(message, AT_RAND, this->rand); message->add_attribute(message, AT_AUTN, chunk_create(autn, AKA_AUTN_LEN)); id = this->mgr->provider_gen_reauth(this->mgr, this->permanent, mk.ptr); + free(mk.ptr); if (id) { message->add_attribute(message, AT_NEXT_REAUTH_ID, @@ -203,10 +223,10 @@ static status_t challenge(private_eap_aka_server_t *this, eap_payload_t **out) id->get_encoding(id)); id->destroy(id); } - *out = eap_payload_create_data_own(message->generate(message, chunk_empty)); - message->destroy(message); - - free(mk.ptr); + if (!generate_payload(message, chunk_empty, out)) + { + return FAILED; + } this->pending = AKA_CHALLENGE; return NEED_MORE; } @@ -247,9 +267,10 @@ static status_t reauthenticate(private_eap_aka_server_t *this, next->get_encoding(next)); next->destroy(next); } - *out = eap_payload_create_data_own(message->generate(message, chunk_empty)); - message->destroy(message); - + if (!generate_payload(message, chunk_empty, out)) + { + return FAILED; + } this->pending = SIM_REAUTHENTICATION; return NEED_MORE; } diff --git a/src/libcharon/plugins/eap_sim/eap_sim_peer.c b/src/libcharon/plugins/eap_sim/eap_sim_peer.c index 1d1ab99e0..f0a48255d 100644 --- a/src/libcharon/plugins/eap_sim/eap_sim_peer.c +++ b/src/libcharon/plugins/eap_sim/eap_sim_peer.c @@ -105,14 +105,31 @@ struct private_eap_sim_peer_t { /* version of SIM protocol we speak */ static chunk_t version = chunk_from_chars(0x00,0x01); +/** + * Generate a payload from a message, destroy message + */ +static bool generate_payload(simaka_message_t *message, chunk_t data, + eap_payload_t **out) +{ + chunk_t chunk; + bool ok; + + ok = message->generate(message, data, &chunk); + if (ok) + { + *out = eap_payload_create_data_own(chunk); + } + message->destroy(message); + return ok; +} + /** * Create a SIM_CLIENT_ERROR */ -static eap_payload_t* create_client_error(private_eap_sim_peer_t *this, - simaka_client_error_t code) +static bool create_client_error(private_eap_sim_peer_t *this, + simaka_client_error_t code, eap_payload_t **out) { simaka_message_t *message; - eap_payload_t *out; u_int16_t encoded; DBG1(DBG_IKE, "sending client error '%N'", simaka_client_error_names, code); @@ -122,9 +139,7 @@ static eap_payload_t* create_client_error(private_eap_sim_peer_t *this, encoded = htons(code); message->add_attribute(message, AT_CLIENT_ERROR_CODE, chunk_create((char*)&encoded, sizeof(encoded))); - out = eap_payload_create_data_own(message->generate(message, chunk_empty)); - message->destroy(message); - return out; + return generate_payload(message, chunk_empty, out); } /** @@ -175,8 +190,11 @@ static status_t process_start(private_eap_sim_peer_t *this, default: if (!simaka_attribute_skippable(type)) { - *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); enumerator->destroy(enumerator); + if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out)) + { + return FAILED; + } return NEED_MORE; } break; @@ -187,7 +205,10 @@ static status_t process_start(private_eap_sim_peer_t *this, if (!supported) { DBG1(DBG_IKE, "server does not support EAP-SIM version number 1"); - *out = create_client_error(this, SIM_UNSUPPORTED_VERSION); + if (!create_client_error(this, SIM_UNSUPPORTED_VERSION, out)) + { + return FAILED; + } return NEED_MORE; } @@ -234,9 +255,10 @@ static status_t process_start(private_eap_sim_peer_t *this, { message->add_attribute(message, AT_IDENTITY, id); } - *out = eap_payload_create_data_own(message->generate(message, chunk_empty)); - message->destroy(message); - + if (!generate_payload(message, chunk_empty, out)) + { + return FAILED; + } return NEED_MORE; } @@ -270,8 +292,11 @@ static status_t process_challenge(private_eap_sim_peer_t *this, default: if (!simaka_attribute_skippable(type)) { - *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); enumerator->destroy(enumerator); + if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out)) + { + return FAILED; + } return NEED_MORE; } break; @@ -285,7 +310,10 @@ static status_t process_challenge(private_eap_sim_peer_t *this, memeq(rands.ptr, rands.ptr + SIM_RAND_LEN, SIM_RAND_LEN)) { DBG1(DBG_IKE, "no valid AT_RAND received"); - *out = create_client_error(this, SIM_INSUFFICIENT_CHALLENGES); + if (!create_client_error(this, SIM_INSUFFICIENT_CHALLENGES, out)) + { + return FAILED; + } return NEED_MORE; } /* get two or three KCs/SRESes from SIM using RANDs */ @@ -297,7 +325,10 @@ static status_t process_challenge(private_eap_sim_peer_t *this, rands.ptr, sres.ptr, kc.ptr)) { DBG1(DBG_IKE, "unable to get EAP-SIM triplet"); - *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); + if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out)) + { + return FAILED; + } return NEED_MORE; } DBG3(DBG_IKE, "got triplet for RAND %b\n Kc %b\n SRES %b", @@ -322,7 +353,10 @@ static status_t process_challenge(private_eap_sim_peer_t *this, * parse() again after key derivation, reading encrypted attributes */ if (!in->verify(in, this->nonce) || !in->parse(in)) { - *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); + if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out)) + { + return FAILED; + } return NEED_MORE; } @@ -352,8 +386,10 @@ static status_t process_challenge(private_eap_sim_peer_t *this, /* build response with AT_MAC, built over "EAP packet | n*SRES" */ message = simaka_message_create(FALSE, this->identifier, EAP_SIM, SIM_CHALLENGE, this->crypto); - *out = eap_payload_create_data_own(message->generate(message, sreses)); - message->destroy(message); + if (!generate_payload(message, sreses, out)) + { + return FAILED; + } return NEED_MORE; } @@ -384,7 +420,10 @@ static status_t process_reauthentication(private_eap_sim_peer_t *this, { DBG1(DBG_IKE, "received %N, but not expected", simaka_subtype_names, SIM_REAUTHENTICATION); - *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); + if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out)) + { + return FAILED; + } return NEED_MORE; } @@ -394,7 +433,10 @@ static status_t process_reauthentication(private_eap_sim_peer_t *this, /* verify MAC and parse again with decryption key */ if (!in->verify(in, chunk_empty) || !in->parse(in)) { - *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); + if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out)) + { + return FAILED; + } return NEED_MORE; } @@ -415,8 +457,11 @@ static status_t process_reauthentication(private_eap_sim_peer_t *this, default: if (!simaka_attribute_skippable(type)) { - *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); enumerator->destroy(enumerator); + if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out)) + { + return FAILED; + } return NEED_MORE; } break; @@ -427,7 +472,10 @@ static status_t process_reauthentication(private_eap_sim_peer_t *this, if (!nonce.len || !counter.len) { DBG1(DBG_IKE, "EAP-SIM/Request/Re-Authentication message incomplete"); - *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); + if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out)) + { + return FAILED; + } return NEED_MORE; } @@ -455,8 +503,10 @@ static status_t process_reauthentication(private_eap_sim_peer_t *this, } } message->add_attribute(message, AT_COUNTER, counter); - *out = eap_payload_create_data_own(message->generate(message, nonce)); - message->destroy(message); + if (!generate_payload(message, nonce, out)) + { + return FAILED; + } return NEED_MORE; } @@ -506,13 +556,17 @@ static status_t process_notification(private_eap_sim_peer_t *this, { /* empty notification reply */ message = simaka_message_create(FALSE, this->identifier, EAP_SIM, SIM_NOTIFICATION, this->crypto); - *out = eap_payload_create_data_own(message->generate(message, - chunk_empty)); - message->destroy(message); + if (!generate_payload(message, chunk_empty, out)) + { + return FAILED; + } } else { - *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); + if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out)) + { + return FAILED; + } } return NEED_MORE; } @@ -529,13 +583,19 @@ METHOD(eap_method_t, process, status_t, message = simaka_message_create_from_payload(in->get_data(in), this->crypto); if (!message) { - *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); + if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out)) + { + return FAILED; + } return NEED_MORE; } if (!message->parse(message)) { message->destroy(message); - *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); + if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out)) + { + return FAILED; + } return NEED_MORE; } switch (message->get_subtype(message)) @@ -555,8 +615,14 @@ METHOD(eap_method_t, process, status_t, default: DBG1(DBG_IKE, "unable to process EAP-SIM subtype %N", simaka_subtype_names, message->get_subtype(message)); - *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); - status = NEED_MORE; + if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out)) + { + status = FAILED; + } + else + { + status = NEED_MORE; + } break; } message->destroy(message); diff --git a/src/libcharon/plugins/eap_sim/eap_sim_server.c b/src/libcharon/plugins/eap_sim/eap_sim_server.c index a965476eb..a88ce5706 100644 --- a/src/libcharon/plugins/eap_sim/eap_sim_server.c +++ b/src/libcharon/plugins/eap_sim/eap_sim_server.c @@ -113,6 +113,24 @@ struct private_eap_sim_server_t { /* version of SIM protocol we speak */ static chunk_t version = chunk_from_chars(0x00,0x01); +/** + * Generate a payload from a message, destroy message + */ +static bool generate_payload(simaka_message_t *message, chunk_t data, + eap_payload_t **out) +{ + chunk_t chunk; + bool ok; + + ok = message->generate(message, data, &chunk); + if (ok) + { + *out = eap_payload_create_data_own(chunk); + } + message->destroy(message); + return ok; +} + METHOD(eap_method_t, initiate, status_t, private_eap_sim_server_t *this, eap_payload_t **out) { @@ -133,9 +151,10 @@ METHOD(eap_method_t, initiate, status_t, { message->add_attribute(message, AT_PERMANENT_ID_REQ, chunk_empty); } - *out = eap_payload_create_data_own(message->generate(message, chunk_empty)); - message->destroy(message); - + if (!generate_payload(message, chunk_empty, out)) + { + return FAILED; + } this->pending = SIM_START; return NEED_MORE; } @@ -176,9 +195,10 @@ static status_t reauthenticate(private_eap_sim_server_t *this, next->get_encoding(next)); next->destroy(next); } - *out = eap_payload_create_data_own(message->generate(message, chunk_empty)); - message->destroy(message); - + if (!generate_payload(message, chunk_empty, out)) + { + return FAILED; + } this->pending = SIM_REAUTHENTICATION; return NEED_MORE; } @@ -393,6 +413,7 @@ static status_t process_start(private_eap_sim_server_t *this, SIM_CHALLENGE, this->crypto); message->add_attribute(message, AT_RAND, rands); id = this->mgr->provider_gen_reauth(this->mgr, this->permanent, mk.ptr); + free(mk.ptr); if (id) { message->add_attribute(message, AT_NEXT_REAUTH_ID, @@ -406,10 +427,10 @@ static status_t process_start(private_eap_sim_server_t *this, id->get_encoding(id)); id->destroy(id); } - *out = eap_payload_create_data_own(message->generate(message, nonce)); - message->destroy(message); - - free(mk.ptr); + if (!generate_payload(message, nonce, out)) + { + return FAILED; + } this->pending = SIM_CHALLENGE; return NEED_MORE; } diff --git a/src/libsimaka/simaka_message.c b/src/libsimaka/simaka_message.c index a5754b985..745f4d76c 100644 --- a/src/libsimaka/simaka_message.c +++ b/src/libsimaka/simaka_message.c @@ -599,8 +599,8 @@ METHOD(simaka_message_t, verify, bool, return TRUE; } -METHOD(simaka_message_t, generate, chunk_t, - private_simaka_message_t *this, chunk_t sigdata) +METHOD(simaka_message_t, generate, bool, + private_simaka_message_t *this, chunk_t sigdata, chunk_t *gen) { /* buffers large enough for messages we generate */ char out_buf[1024], encr_buf[512]; @@ -827,7 +827,8 @@ METHOD(simaka_message_t, generate, chunk_t, call_hook(this, FALSE, FALSE); - return chunk_clone(out); + *gen = chunk_clone(out); + return TRUE; } METHOD(simaka_message_t, destroy, void, diff --git a/src/libsimaka/simaka_message.h b/src/libsimaka/simaka_message.h index 28fe21823..209067c70 100644 --- a/src/libsimaka/simaka_message.h +++ b/src/libsimaka/simaka_message.h @@ -236,9 +236,10 @@ struct simaka_message_t { * Generate a message, optionally encrypt attributes and create a MAC. * * @param sigdata additional data to include in signature, if any - * @return allocated data of generated message + * @param gen allocated generated data, if successful + * @return TRUE if successful */ - chunk_t (*generate)(simaka_message_t *this, chunk_t sigdata); + bool (*generate)(simaka_message_t *this, chunk_t sigdata, chunk_t *gen); /** * Destroy a simaka_message_t.