eap_proxy: Build realm from IMSI for proxy based EAP methods
For proxy based EAP methods, the EAP identity is constructed in eap_proxy layer from IMSI when required. Realm information from identity is used to do ERP eventually, hence construct the realm for proxy based methods from IMSI in core wpa_supplicant to enable the ERP use case. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
5e0c20ff3e
commit
0020876514
4 changed files with 121 additions and 49 deletions
|
@ -121,15 +121,17 @@ static void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* eap_allowed_method - Check whether EAP method is allowed
|
* eap_config_allowed_method - Check whether EAP method is allowed
|
||||||
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
|
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
|
||||||
|
* @config: EAP configuration
|
||||||
* @vendor: Vendor-Id for expanded types or 0 = IETF for legacy types
|
* @vendor: Vendor-Id for expanded types or 0 = IETF for legacy types
|
||||||
* @method: EAP type
|
* @method: EAP type
|
||||||
* Returns: 1 = allowed EAP method, 0 = not allowed
|
* Returns: 1 = allowed EAP method, 0 = not allowed
|
||||||
*/
|
*/
|
||||||
int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method)
|
static int eap_config_allowed_method(struct eap_sm *sm,
|
||||||
|
struct eap_peer_config *config,
|
||||||
|
int vendor, u32 method)
|
||||||
{
|
{
|
||||||
struct eap_peer_config *config = eap_get_config(sm);
|
|
||||||
int i;
|
int i;
|
||||||
struct eap_method_type *m;
|
struct eap_method_type *m;
|
||||||
|
|
||||||
|
@ -146,6 +148,57 @@ int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* eap_allowed_method - Check whether EAP method is allowed
|
||||||
|
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
|
||||||
|
* @vendor: Vendor-Id for expanded types or 0 = IETF for legacy types
|
||||||
|
* @method: EAP type
|
||||||
|
* Returns: 1 = allowed EAP method, 0 = not allowed
|
||||||
|
*/
|
||||||
|
int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method)
|
||||||
|
{
|
||||||
|
return eap_config_allowed_method(sm, eap_get_config(sm), vendor,
|
||||||
|
method);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(PCSC_FUNCS) || defined(CONFIG_EAP_PROXY)
|
||||||
|
static int eap_sm_append_3gpp_realm(struct eap_sm *sm, char *imsi,
|
||||||
|
size_t max_len, size_t *imsi_len,
|
||||||
|
int mnc_len)
|
||||||
|
{
|
||||||
|
char *pos, mnc[4];
|
||||||
|
|
||||||
|
if (*imsi_len + 36 > max_len) {
|
||||||
|
wpa_printf(MSG_WARNING, "No room for realm in IMSI buffer");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnc_len != 2 && mnc_len != 3)
|
||||||
|
mnc_len = 3;
|
||||||
|
|
||||||
|
if (mnc_len == 2) {
|
||||||
|
mnc[0] = '0';
|
||||||
|
mnc[1] = imsi[3];
|
||||||
|
mnc[2] = imsi[4];
|
||||||
|
} else if (mnc_len == 3) {
|
||||||
|
mnc[0] = imsi[3];
|
||||||
|
mnc[1] = imsi[4];
|
||||||
|
mnc[2] = imsi[5];
|
||||||
|
}
|
||||||
|
mnc[3] = '\0';
|
||||||
|
|
||||||
|
pos = imsi + *imsi_len;
|
||||||
|
pos += os_snprintf(pos, imsi + max_len - pos,
|
||||||
|
"@wlan.mnc%s.mcc%c%c%c.3gppnetwork.org",
|
||||||
|
mnc, imsi[0], imsi[1], imsi[2]);
|
||||||
|
*imsi_len = pos - imsi;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* PCSC_FUNCS || CONFIG_EAP_PROXY */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This state initializes state machine variables when the machine is
|
* This state initializes state machine variables when the machine is
|
||||||
* activated (portEnabled = TRUE). This is also used when re-starting
|
* activated (portEnabled = TRUE). This is also used when re-starting
|
||||||
|
@ -412,6 +465,44 @@ static char * eap_get_realm(struct eap_sm *sm, struct eap_peer_config *config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_EAP_PROXY
|
||||||
|
/* When identity is not provided in the config, build the realm from
|
||||||
|
* IMSI for eap_proxy based methods.
|
||||||
|
*/
|
||||||
|
if (!config->identity && !config->anonymous_identity &&
|
||||||
|
sm->eapol_cb->get_imsi &&
|
||||||
|
(eap_config_allowed_method(sm, config, EAP_VENDOR_IETF,
|
||||||
|
EAP_TYPE_SIM) ||
|
||||||
|
eap_config_allowed_method(sm, config, EAP_VENDOR_IETF,
|
||||||
|
EAP_TYPE_AKA) ||
|
||||||
|
eap_config_allowed_method(sm, config, EAP_VENDOR_IETF,
|
||||||
|
EAP_TYPE_AKA_PRIME))) {
|
||||||
|
char imsi[100];
|
||||||
|
size_t imsi_len;
|
||||||
|
int mnc_len, pos;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "EAP: Build realm from IMSI (eap_proxy)");
|
||||||
|
mnc_len = sm->eapol_cb->get_imsi(sm->eapol_ctx, imsi,
|
||||||
|
&imsi_len);
|
||||||
|
if (mnc_len < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
pos = imsi_len + 1; /* points to the beginning of the realm */
|
||||||
|
if (eap_sm_append_3gpp_realm(sm, imsi, sizeof(imsi), &imsi_len,
|
||||||
|
mnc_len) < 0) {
|
||||||
|
wpa_printf(MSG_WARNING, "Could not append realm");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
realm = os_strdup(&imsi[pos]);
|
||||||
|
if (!realm)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "EAP: Generated realm '%s'", realm);
|
||||||
|
return realm;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_EAP_PROXY */
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1401,48 +1492,6 @@ static int mnc_len_from_imsi(const char *imsi)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int eap_sm_append_3gpp_realm(struct eap_sm *sm, char *imsi,
|
|
||||||
size_t max_len, size_t *imsi_len)
|
|
||||||
{
|
|
||||||
int mnc_len;
|
|
||||||
char *pos, mnc[4];
|
|
||||||
|
|
||||||
if (*imsi_len + 36 > max_len) {
|
|
||||||
wpa_printf(MSG_WARNING, "No room for realm in IMSI buffer");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* MNC (2 or 3 digits) */
|
|
||||||
mnc_len = scard_get_mnc_len(sm->scard_ctx);
|
|
||||||
if (mnc_len < 0)
|
|
||||||
mnc_len = mnc_len_from_imsi(imsi);
|
|
||||||
if (mnc_len < 0) {
|
|
||||||
wpa_printf(MSG_INFO, "Failed to get MNC length from (U)SIM "
|
|
||||||
"assuming 3");
|
|
||||||
mnc_len = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mnc_len == 2) {
|
|
||||||
mnc[0] = '0';
|
|
||||||
mnc[1] = imsi[3];
|
|
||||||
mnc[2] = imsi[4];
|
|
||||||
} else if (mnc_len == 3) {
|
|
||||||
mnc[0] = imsi[3];
|
|
||||||
mnc[1] = imsi[4];
|
|
||||||
mnc[2] = imsi[5];
|
|
||||||
}
|
|
||||||
mnc[3] = '\0';
|
|
||||||
|
|
||||||
pos = imsi + *imsi_len;
|
|
||||||
pos += os_snprintf(pos, imsi + max_len - pos,
|
|
||||||
"@wlan.mnc%s.mcc%c%c%c.3gppnetwork.org",
|
|
||||||
mnc, imsi[0], imsi[1], imsi[2]);
|
|
||||||
*imsi_len = pos - imsi;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int eap_sm_imsi_identity(struct eap_sm *sm,
|
static int eap_sm_imsi_identity(struct eap_sm *sm,
|
||||||
struct eap_peer_config *conf)
|
struct eap_peer_config *conf)
|
||||||
{
|
{
|
||||||
|
@ -1450,7 +1499,7 @@ static int eap_sm_imsi_identity(struct eap_sm *sm,
|
||||||
char imsi[100];
|
char imsi[100];
|
||||||
size_t imsi_len;
|
size_t imsi_len;
|
||||||
struct eap_method_type *m = conf->eap_methods;
|
struct eap_method_type *m = conf->eap_methods;
|
||||||
int i;
|
int i, mnc_len;
|
||||||
|
|
||||||
imsi_len = sizeof(imsi);
|
imsi_len = sizeof(imsi);
|
||||||
if (scard_get_imsi(sm->scard_ctx, imsi, &imsi_len)) {
|
if (scard_get_imsi(sm->scard_ctx, imsi, &imsi_len)) {
|
||||||
|
@ -1465,7 +1514,18 @@ static int eap_sm_imsi_identity(struct eap_sm *sm,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eap_sm_append_3gpp_realm(sm, imsi, sizeof(imsi), &imsi_len) < 0) {
|
/* MNC (2 or 3 digits) */
|
||||||
|
mnc_len = scard_get_mnc_len(sm->scard_ctx);
|
||||||
|
if (mnc_len < 0)
|
||||||
|
mnc_len = mnc_len_from_imsi(imsi);
|
||||||
|
if (mnc_len < 0) {
|
||||||
|
wpa_printf(MSG_INFO, "Failed to get MNC length from (U)SIM "
|
||||||
|
"assuming 3");
|
||||||
|
mnc_len = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eap_sm_append_3gpp_realm(sm, imsi, sizeof(imsi), &imsi_len,
|
||||||
|
mnc_len) < 0) {
|
||||||
wpa_printf(MSG_WARNING, "Could not add realm to SIM identity");
|
wpa_printf(MSG_WARNING, "Could not add realm to SIM identity");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -260,6 +260,15 @@ struct eapol_callbacks {
|
||||||
*/
|
*/
|
||||||
void (*eap_proxy_notify_sim_status)(void *ctx,
|
void (*eap_proxy_notify_sim_status)(void *ctx,
|
||||||
enum eap_proxy_sim_state sim_state);
|
enum eap_proxy_sim_state sim_state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get_imsi - Get the IMSI value from eap_proxy
|
||||||
|
* @ctx: eapol_ctx from eap_peer_sm_init() call
|
||||||
|
* @imsi: Buffer for IMSI value
|
||||||
|
* @len: Buffer for returning IMSI length in octets
|
||||||
|
* Returns: MNC length (2 or 3) or -1 on error
|
||||||
|
*/
|
||||||
|
int (*get_imsi)(void *ctx, char *imsi, size_t *len);
|
||||||
#endif /* CONFIG_EAP_PROXY */
|
#endif /* CONFIG_EAP_PROXY */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2065,6 +2065,7 @@ static const struct eapol_callbacks eapol_cb =
|
||||||
#ifdef CONFIG_EAP_PROXY
|
#ifdef CONFIG_EAP_PROXY
|
||||||
eapol_sm_eap_proxy_cb,
|
eapol_sm_eap_proxy_cb,
|
||||||
eapol_sm_eap_proxy_notify_sim_status,
|
eapol_sm_eap_proxy_notify_sim_status,
|
||||||
|
eapol_sm_get_eap_proxy_imsi,
|
||||||
#endif /* CONFIG_EAP_PROXY */
|
#endif /* CONFIG_EAP_PROXY */
|
||||||
eapol_sm_set_anon_id
|
eapol_sm_set_anon_id
|
||||||
};
|
};
|
||||||
|
@ -2173,8 +2174,10 @@ int eapol_sm_failed(struct eapol_sm *sm)
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_EAP_PROXY
|
#ifdef CONFIG_EAP_PROXY
|
||||||
int eapol_sm_get_eap_proxy_imsi(struct eapol_sm *sm, char *imsi, size_t *len)
|
int eapol_sm_get_eap_proxy_imsi(void *ctx, char *imsi, size_t *len)
|
||||||
{
|
{
|
||||||
|
struct eapol_sm *sm = ctx;
|
||||||
|
|
||||||
if (sm->eap_proxy == NULL)
|
if (sm->eap_proxy == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
return eap_proxy_get_imsi(sm->eap_proxy, imsi, len);
|
return eap_proxy_get_imsi(sm->eap_proxy, imsi, len);
|
||||||
|
|
|
@ -339,7 +339,7 @@ void eapol_sm_erp_flush(struct eapol_sm *sm);
|
||||||
struct wpabuf * eapol_sm_build_erp_reauth_start(struct eapol_sm *sm);
|
struct wpabuf * eapol_sm_build_erp_reauth_start(struct eapol_sm *sm);
|
||||||
void eapol_sm_process_erp_finish(struct eapol_sm *sm, const u8 *buf,
|
void eapol_sm_process_erp_finish(struct eapol_sm *sm, const u8 *buf,
|
||||||
size_t len);
|
size_t len);
|
||||||
int eapol_sm_get_eap_proxy_imsi(struct eapol_sm *sm, char *imsi, size_t *len);
|
int eapol_sm_get_eap_proxy_imsi(void *ctx, char *imsi, size_t *len);
|
||||||
int eapol_sm_update_erp_next_seq_num(struct eapol_sm *sm, u16 next_seq_num);
|
int eapol_sm_update_erp_next_seq_num(struct eapol_sm *sm, u16 next_seq_num);
|
||||||
int eapol_sm_get_erp_info(struct eapol_sm *sm, struct eap_peer_config *config,
|
int eapol_sm_get_erp_info(struct eapol_sm *sm, struct eap_peer_config *config,
|
||||||
const u8 **username, size_t *username_len,
|
const u8 **username, size_t *username_len,
|
||||||
|
|
Loading…
Reference in a new issue