Proper handling of non-skippable attributes and client error codes in EAP-SIM

This commit is contained in:
Martin Willi
2009-11-12 10:33:59 +01:00
parent fad4e5f393
commit 6d90881573
2 changed files with 65 additions and 33 deletions
+46 -23
View File
@@ -81,10 +81,6 @@ struct private_eap_sim_peer_t {
/* version of SIM protocol we speak */ /* version of SIM protocol we speak */
static chunk_t version = chunk_from_chars(0x00,0x01); static chunk_t version = chunk_from_chars(0x00,0x01);
/* client error codes used in AT_CLIENT_ERROR_CODE */
static chunk_t client_error_general = chunk_from_chars(0x00, 0x01);
static chunk_t client_error_unsupported = chunk_from_chars(0x00, 0x02);
static chunk_t client_error_insufficient = chunk_from_chars(0x00, 0x03);
/** /**
* Read a triplet from the SIM card * Read a triplet from the SIM card
@@ -114,17 +110,22 @@ static bool get_card_triplet(private_eap_sim_peer_t *this,
} }
/** /**
* Send a SIM_CLIENT_ERROR * Create a SIM_CLIENT_ERROR
*/ */
static eap_payload_t* create_client_error(private_eap_sim_peer_t *this, static eap_payload_t* create_client_error(private_eap_sim_peer_t *this,
u_int8_t identifier, chunk_t code) u_int8_t identifier, simaka_client_error_t code)
{ {
simaka_message_t *message; simaka_message_t *message;
eap_payload_t *out; eap_payload_t *out;
u_int16_t encoded;
DBG1(DBG_IKE, "sending client error '%N'", simaka_client_error_names, code);
message = simaka_message_create(FALSE, identifier, message = simaka_message_create(FALSE, identifier,
EAP_SIM, SIM_CLIENT_ERROR); EAP_SIM, SIM_CLIENT_ERROR);
message->add_attribute(message, AT_CLIENT_ERROR_CODE, code); encoded = htons(code);
message->add_attribute(message, AT_CLIENT_ERROR_CODE,
chunk_create((char*)&encoded, sizeof(encoded)));
out = message->generate(message, this->crypto, chunk_empty); out = message->generate(message, this->crypto, chunk_empty);
message->destroy(message); message->destroy(message);
return out; return out;
@@ -163,8 +164,13 @@ static status_t process_start(private_eap_sim_peer_t *this,
break; break;
} }
default: default:
DBG1(DBG_IKE, "ignoring EAP-SIM attribute %N", if (!simaka_attribute_skippable(type))
simaka_attribute_names, type); {
*out = create_client_error(this, in->get_identifier(in),
SIM_UNABLE_TO_PROCESS);
enumerator->destroy(enumerator);
return NEED_MORE;
}
break; break;
} }
} }
@@ -174,7 +180,7 @@ static status_t process_start(private_eap_sim_peer_t *this,
{ {
DBG1(DBG_IKE, "server does not support EAP-SIM version number 1"); DBG1(DBG_IKE, "server does not support EAP-SIM version number 1");
*out = create_client_error(this, in->get_identifier(in), *out = create_client_error(this, in->get_identifier(in),
client_error_unsupported); SIM_UNSUPPORTED_VERSION);
return NEED_MORE; return NEED_MORE;
} }
@@ -217,13 +223,16 @@ static status_t process_challenge(private_eap_sim_peer_t *this,
switch (type) switch (type)
{ {
case AT_RAND: case AT_RAND:
{
rands = data; rands = data;
break; break;
}
default: default:
DBG1(DBG_IKE, "ignoring EAP-SIM attribute %N", if (!simaka_attribute_skippable(type))
simaka_attribute_names, type); {
*out = create_client_error(this, in->get_identifier(in),
SIM_UNABLE_TO_PROCESS);
enumerator->destroy(enumerator);
return NEED_MORE;
}
break; break;
} }
} }
@@ -236,7 +245,7 @@ static status_t process_challenge(private_eap_sim_peer_t *this,
{ {
DBG1(DBG_IKE, "no valid AT_RAND received"); DBG1(DBG_IKE, "no valid AT_RAND received");
*out = create_client_error(this, in->get_identifier(in), *out = create_client_error(this, in->get_identifier(in),
client_error_insufficient); SIM_INSUFFICIENT_CHALLENGES);
return NEED_MORE; return NEED_MORE;
} }
/* get two or three KCs/SRESes from SIM using RANDs */ /* get two or three KCs/SRESes from SIM using RANDs */
@@ -248,7 +257,7 @@ static status_t process_challenge(private_eap_sim_peer_t *this,
{ {
DBG1(DBG_IKE, "unable to get EAP-SIM triplet"); DBG1(DBG_IKE, "unable to get EAP-SIM triplet");
*out = create_client_error(this, in->get_identifier(in), *out = create_client_error(this, in->get_identifier(in),
client_error_general); SIM_UNABLE_TO_PROCESS);
return NEED_MORE; return NEED_MORE;
} }
DBG3(DBG_IKE, "got triplet for RAND %b\n Kc %b\n SRES %b", DBG3(DBG_IKE, "got triplet for RAND %b\n Kc %b\n SRES %b",
@@ -267,7 +276,7 @@ static status_t process_challenge(private_eap_sim_peer_t *this,
{ {
DBG1(DBG_IKE, "AT_MAC verification failed"); DBG1(DBG_IKE, "AT_MAC verification failed");
*out = create_client_error(this, in->get_identifier(in), *out = create_client_error(this, in->get_identifier(in),
client_error_general); SIM_UNABLE_TO_PROCESS);
return NEED_MORE; return NEED_MORE;
} }
@@ -296,17 +305,29 @@ static status_t process_notification(private_eap_sim_peer_t *this,
{ {
if (type == AT_NOTIFICATION) if (type == AT_NOTIFICATION)
{ {
u_int16_t code;
memcpy(&code, data.ptr, sizeof(code));
code = ntohs(code);
/* test success bit */ /* test success bit */
if (!(data.ptr[0] & 0x80)) if (!(data.ptr[0] & 0x80))
{ {
success = FALSE; success = FALSE;
DBG1(DBG_IKE, "received EAP-SIM notification error %#B", &data); DBG1(DBG_IKE, "received EAP-SIM notification error '%N'",
simaka_notification_names, code);
} }
else else
{ {
DBG1(DBG_IKE, "received EAP-SIM notification code %#B", &data); DBG1(DBG_IKE, "received EAP-SIM notification '%N'",
simaka_notification_names, code);
} }
} }
else if (!simaka_attribute_skippable(type))
{
success = FALSE;
break;
}
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
@@ -320,7 +341,7 @@ static status_t process_notification(private_eap_sim_peer_t *this,
else else
{ {
*out = create_client_error(this, in->get_identifier(in), *out = create_client_error(this, in->get_identifier(in),
client_error_general); SIM_UNABLE_TO_PROCESS);
} }
return NEED_MORE; return NEED_MORE;
} }
@@ -338,14 +359,14 @@ static status_t process(private_eap_sim_peer_t *this,
if (!message) if (!message)
{ {
*out = create_client_error(this, in->get_identifier(in), *out = create_client_error(this, in->get_identifier(in),
client_error_general); SIM_UNABLE_TO_PROCESS);
return NEED_MORE; return NEED_MORE;
} }
if (!message->parse(message, this->crypto)) if (!message->parse(message, this->crypto))
{ {
message->destroy(message); message->destroy(message);
*out = create_client_error(this, in->get_identifier(in), *out = create_client_error(this, in->get_identifier(in),
client_error_general); SIM_UNABLE_TO_PROCESS);
return NEED_MORE; return NEED_MORE;
} }
switch (message->get_subtype(message)) switch (message->get_subtype(message))
@@ -360,8 +381,10 @@ static status_t process(private_eap_sim_peer_t *this,
status = process_notification(this, message, out); status = process_notification(this, message, out);
break; break;
default: default:
DBG1(DBG_IKE, "unable to process EAP-SIM subtype %N",
simaka_subtype_names, message->get_subtype(message));
*out = create_client_error(this, in->get_identifier(in), *out = create_client_error(this, in->get_identifier(in),
client_error_general); SIM_UNABLE_TO_PROCESS);
status = NEED_MORE; status = NEED_MORE;
break; break;
} }
+19 -10
View File
@@ -127,8 +127,11 @@ static status_t process_start(private_eap_sim_server_t *this,
} }
break; break;
default: default:
DBG1(DBG_IKE, "ignoring EAP-SIM attribute %N", if (!simaka_attribute_skippable(type))
simaka_attribute_names, type); {
enumerator->destroy(enumerator);
return FAILED;
}
break; break;
} }
} }
@@ -188,8 +191,11 @@ static status_t process_challenge(private_eap_sim_server_t *this,
enumerator = in->create_attribute_enumerator(in); enumerator = in->create_attribute_enumerator(in);
while (enumerator->enumerate(enumerator, &type, &data)) while (enumerator->enumerate(enumerator, &type, &data))
{ {
DBG1(DBG_IKE, "ignoring EAP-SIM attribute %N", if (!simaka_attribute_skippable(type))
simaka_attribute_names, type); {
enumerator->destroy(enumerator);
return FAILED;
}
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
@@ -206,7 +212,7 @@ static status_t process_challenge(private_eap_sim_server_t *this,
* EAP-SIM/Response/ClientErrorCode message * EAP-SIM/Response/ClientErrorCode message
*/ */
static status_t process_client_error(private_eap_sim_server_t *this, static status_t process_client_error(private_eap_sim_server_t *this,
simaka_message_t *in, eap_payload_t **out) simaka_message_t *in)
{ {
enumerator_t *enumerator; enumerator_t *enumerator;
simaka_attribute_t type; simaka_attribute_t type;
@@ -217,12 +223,15 @@ static status_t process_client_error(private_eap_sim_server_t *this,
{ {
if (type == AT_CLIENT_ERROR_CODE) if (type == AT_CLIENT_ERROR_CODE)
{ {
DBG1(DBG_IKE, "received EAP-SIM client error code %#B", &data); u_int16_t code;
memcpy(&code, data.ptr, sizeof(code));
DBG1(DBG_IKE, "received EAP-SIM client error '%N'",
simaka_client_error_names, ntohs(code));
} }
else else if (!simaka_attribute_skippable(type))
{ {
DBG1(DBG_IKE, "ignoring EAP-SIM attribute %N", break;
simaka_attribute_names, type);
} }
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
@@ -257,7 +266,7 @@ static status_t process(private_eap_sim_server_t *this,
status = process_challenge(this, message, out); status = process_challenge(this, message, out);
break; break;
case SIM_CLIENT_ERROR: case SIM_CLIENT_ERROR:
status = process_client_error(this, message, out); status = process_client_error(this, message);
break; break;
default: default:
DBG1(DBG_IKE, "unable to process EAP-SIM subtype %N", DBG1(DBG_IKE, "unable to process EAP-SIM subtype %N",