Propagate the EAP method error code
In the current implementation, upon an EAP method failure, followed by an EAP failure, the EAP Status is propagated up in wpa_supplicant with a general failure parameter string "failure". This parameter is used for a notification on the dbus. This commit reports the EAP method failure error code in a separate callback. The solution in this commit is generic to all EAP methods, and can be used by any method that need to pass its error code. However, this commit only implements the reporting for EAP-SIM and EAP-AKA methods where the Notification Code (in AT_NOTIFICATION) is used as the method specific error code value. Signed-off-by: Ahmed ElArabawy <arabawy@google.com>
This commit is contained in:
parent
c9aba19bd3
commit
45f7574d31
11 changed files with 118 additions and 0 deletions
|
@ -95,6 +95,14 @@ static void eap_notify_status(struct eap_sm *sm, const char *status,
|
|||
}
|
||||
|
||||
|
||||
static void eap_report_error(struct eap_sm *sm, int error_code)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "EAP: Error notification: %d", error_code);
|
||||
if (sm->eapol_cb->notify_eap_error)
|
||||
sm->eapol_cb->notify_eap_error(sm->eapol_ctx, error_code);
|
||||
}
|
||||
|
||||
|
||||
static void eap_sm_free_key(struct eap_sm *sm)
|
||||
{
|
||||
if (sm->eapKeyData) {
|
||||
|
@ -2018,6 +2026,15 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req)
|
|||
case EAP_CODE_FAILURE:
|
||||
wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure");
|
||||
eap_notify_status(sm, "completion", "failure");
|
||||
|
||||
/* Get the error code from method */
|
||||
if (sm->m && sm->m->get_error_code) {
|
||||
int error_code;
|
||||
|
||||
error_code = sm->m->get_error_code(sm->eap_method_priv);
|
||||
if (error_code != NO_EAP_METHOD_ERROR)
|
||||
eap_report_error(sm, error_code);
|
||||
}
|
||||
sm->rxFailure = TRUE;
|
||||
break;
|
||||
case EAP_CODE_INITIATE:
|
||||
|
|
|
@ -246,6 +246,13 @@ struct eapol_callbacks {
|
|||
void (*notify_status)(void *ctx, const char *status,
|
||||
const char *parameter);
|
||||
|
||||
/**
|
||||
* notify_eap_error - Report EAP method error code
|
||||
* @ctx: eapol_ctx from eap_peer_sm_init() call
|
||||
* @error_code: Error code from the used EAP method
|
||||
*/
|
||||
void (*notify_eap_error)(void *ctx, int error_code);
|
||||
|
||||
#ifdef CONFIG_EAP_PROXY
|
||||
/**
|
||||
* eap_proxy_cb - Callback signifying any updates from eap_proxy
|
||||
|
|
|
@ -56,6 +56,7 @@ struct eap_aka_data {
|
|||
int kdf_negotiation;
|
||||
u16 last_kdf_attrs[EAP_AKA_PRIME_KDF_MAX];
|
||||
size_t last_kdf_count;
|
||||
int error_code;
|
||||
};
|
||||
|
||||
|
||||
|
@ -99,6 +100,9 @@ static void * eap_aka_init(struct eap_sm *sm)
|
|||
|
||||
data->eap_method = EAP_TYPE_AKA;
|
||||
|
||||
/* Zero is a valid error code, so we need to initialize */
|
||||
data->error_code = NO_EAP_METHOD_ERROR;
|
||||
|
||||
eap_aka_state(data, CONTINUE);
|
||||
data->prev_id = -1;
|
||||
|
||||
|
@ -1180,6 +1184,7 @@ static struct wpabuf * eap_aka_process_notification(
|
|||
|
||||
eap_sim_report_notification(sm->msg_ctx, attr->notification, 1);
|
||||
if (attr->notification >= 0 && attr->notification < 32768) {
|
||||
data->error_code = attr->notification;
|
||||
eap_aka_state(data, FAILURE);
|
||||
} else if (attr->notification == EAP_SIM_SUCCESS &&
|
||||
data->state == RESULT_SUCCESS)
|
||||
|
@ -1524,6 +1529,23 @@ static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
|
|||
}
|
||||
|
||||
|
||||
static int eap_aka_get_error_code(void *priv)
|
||||
{
|
||||
struct eap_aka_data *data = priv;
|
||||
int current_data_error;
|
||||
|
||||
if (!data)
|
||||
return NO_EAP_METHOD_ERROR;
|
||||
|
||||
current_data_error = data->error_code;
|
||||
|
||||
/* Now reset for next transaction */
|
||||
data->error_code = NO_EAP_METHOD_ERROR;
|
||||
|
||||
return current_data_error;
|
||||
}
|
||||
|
||||
|
||||
int eap_peer_aka_register(void)
|
||||
{
|
||||
struct eap_method *eap;
|
||||
|
@ -1544,6 +1566,7 @@ int eap_peer_aka_register(void)
|
|||
eap->init_for_reauth = eap_aka_init_for_reauth;
|
||||
eap->get_identity = eap_aka_get_identity;
|
||||
eap->get_emsk = eap_aka_get_emsk;
|
||||
eap->get_error_code = eap_aka_get_error_code;
|
||||
|
||||
return eap_peer_method_register(eap);
|
||||
}
|
||||
|
@ -1571,6 +1594,7 @@ int eap_peer_aka_prime_register(void)
|
|||
eap->init_for_reauth = eap_aka_init_for_reauth;
|
||||
eap->get_identity = eap_aka_get_identity;
|
||||
eap->get_emsk = eap_aka_get_emsk;
|
||||
eap->get_error_code = eap_aka_get_error_code;
|
||||
|
||||
return eap_peer_method_register(eap);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include "eap_peer/eap.h"
|
||||
#include "eap_common/eap_common.h"
|
||||
|
||||
#define NO_EAP_METHOD_ERROR (-1)
|
||||
|
||||
/* RFC 4137 - EAP Peer state machine */
|
||||
|
||||
typedef enum {
|
||||
|
@ -205,6 +207,17 @@ struct eap_method {
|
|||
*/
|
||||
const u8 * (*get_identity)(struct eap_sm *sm, void *priv, size_t *len);
|
||||
|
||||
/**
|
||||
* get_error_code - Get the latest EAP method error code
|
||||
* @priv: Pointer to private EAP method data from eap_method::init()
|
||||
* Returns: An int for the EAP method specific error code if exists or
|
||||
* NO_EAP_METHOD_ERROR otherwise.
|
||||
*
|
||||
* This method is an optional handler that only EAP methods that need to
|
||||
* report their error code need to implement.
|
||||
*/
|
||||
int (*get_error_code)(void *priv);
|
||||
|
||||
/**
|
||||
* free - Free EAP method data
|
||||
* @method: Pointer to the method data registered with
|
||||
|
|
|
@ -47,6 +47,7 @@ struct eap_sim_data {
|
|||
} state;
|
||||
int result_ind, use_result_ind;
|
||||
int use_pseudonym;
|
||||
int error_code;
|
||||
};
|
||||
|
||||
|
||||
|
@ -94,6 +95,9 @@ static void * eap_sim_init(struct eap_sm *sm)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Zero is a valid error code, so we need to initialize */
|
||||
data->error_code = NO_EAP_METHOD_ERROR;
|
||||
|
||||
data->min_num_chal = 2;
|
||||
if (config && config->phase1) {
|
||||
char *pos = os_strstr(config->phase1, "sim_min_num_chal=");
|
||||
|
@ -920,6 +924,7 @@ static struct wpabuf * eap_sim_process_notification(
|
|||
|
||||
eap_sim_report_notification(sm->msg_ctx, attr->notification, 0);
|
||||
if (attr->notification >= 0 && attr->notification < 32768) {
|
||||
data->error_code = attr->notification;
|
||||
eap_sim_state(data, FAILURE);
|
||||
} else if (attr->notification == EAP_SIM_SUCCESS &&
|
||||
data->state == RESULT_SUCCESS)
|
||||
|
@ -1244,6 +1249,23 @@ static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
|
|||
}
|
||||
|
||||
|
||||
static int eap_sim_get_error_code(void *priv)
|
||||
{
|
||||
struct eap_sim_data *data = priv;
|
||||
int current_data_error;
|
||||
|
||||
if (!data)
|
||||
return NO_EAP_METHOD_ERROR;
|
||||
|
||||
current_data_error = data->error_code;
|
||||
|
||||
/* Now reset for next transaction */
|
||||
data->error_code = NO_EAP_METHOD_ERROR;
|
||||
|
||||
return current_data_error;
|
||||
}
|
||||
|
||||
|
||||
int eap_peer_sim_register(void)
|
||||
{
|
||||
struct eap_method *eap;
|
||||
|
@ -1264,6 +1286,7 @@ int eap_peer_sim_register(void)
|
|||
eap->init_for_reauth = eap_sim_init_for_reauth;
|
||||
eap->get_identity = eap_sim_get_identity;
|
||||
eap->get_emsk = eap_sim_get_emsk;
|
||||
eap->get_error_code = eap_sim_get_error_code;
|
||||
|
||||
return eap_peer_method_register(eap);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue