EAP peer: Add framework for external SIM/USIM processing

The new configuration parameter external_sim=<0/1> can now be used to
configure wpa_supplicant to use external SIM/USIM processing (e.g., GSM
authentication for EAP-SIM or UMTS authentication for EAP-AKA). The
requests and responses for such operations are sent over the ctrl_iface
CTRL-REQ-SIM and CTRL-RSP-SIM commands similarly to the existing
password query mechanism.

Changes to the EAP methods to use this new mechanism will be added in
separate commits.

Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2013-10-19 17:32:05 +03:00
parent 7e8bc7d6fb
commit a5d44ac083
18 changed files with 122 additions and 4 deletions

View file

@ -312,6 +312,7 @@ enum wpa_ctrl_req_type {
WPA_CTRL_REQ_EAP_PIN,
WPA_CTRL_REQ_EAP_OTP,
WPA_CTRL_REQ_EAP_PASSPHRASE,
WPA_CTRL_REQ_SIM,
NUM_WPA_CTRL_REQS
};

View file

@ -1638,7 +1638,8 @@ static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
const char *msg, size_t msglen)
{
struct eap_peer_config *config;
char *txt = NULL, *tmp;
const char *txt = NULL;
char *tmp;
if (sm == NULL)
return;
@ -1681,6 +1682,9 @@ static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
case WPA_CTRL_REQ_EAP_PASSPHRASE:
config->pending_req_passphrase++;
break;
case WPA_CTRL_REQ_SIM:
txt = msg;
break;
default:
return;
}
@ -1791,6 +1795,17 @@ void eap_sm_request_passphrase(struct eap_sm *sm)
}
/**
* eap_sm_request_sim - Request external SIM processing
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
* @req: EAP method specific request
*/
void eap_sm_request_sim(struct eap_sm *sm, const char *req)
{
eap_sm_request(sm, WPA_CTRL_REQ_SIM, req, os_strlen(req));
}
/**
* eap_sm_notify_ctrl_attached - Notification of attached monitor
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
@ -2304,6 +2319,17 @@ void eap_set_force_disabled(struct eap_sm *sm, int disabled)
}
/**
* eap_set_external_sim - Set external_sim flag
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
* @external_sim: Whether external SIM/USIM processing is used
*/
void eap_set_external_sim(struct eap_sm *sm, int external_sim)
{
sm->external_sim = external_sim;
}
/**
* eap_notify_pending - Notify that EAP method is ready to re-process a request
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()

View file

@ -296,6 +296,7 @@ void eap_sm_request_new_password(struct eap_sm *sm);
void eap_sm_request_pin(struct eap_sm *sm);
void eap_sm_request_otp(struct eap_sm *sm, const char *msg, size_t msg_len);
void eap_sm_request_passphrase(struct eap_sm *sm);
void eap_sm_request_sim(struct eap_sm *sm, const char *req);
void eap_sm_notify_ctrl_attached(struct eap_sm *sm);
u32 eap_get_phase2_type(const char *name, int *vendor);
struct eap_method_type * eap_get_phase2_types(struct eap_peer_config *config,
@ -303,6 +304,7 @@ struct eap_method_type * eap_get_phase2_types(struct eap_peer_config *config,
void eap_set_fast_reauth(struct eap_sm *sm, int enabled);
void eap_set_workaround(struct eap_sm *sm, unsigned int workaround);
void eap_set_force_disabled(struct eap_sm *sm, int disabled);
void eap_set_external_sim(struct eap_sm *sm, int external_sim);
int eap_key_available(struct eap_sm *sm);
void eap_notify_success(struct eap_sm *sm);
void eap_notify_lower_layer_success(struct eap_sm *sm);

View file

@ -669,6 +669,15 @@ struct eap_peer_config {
* 2 = require valid OCSP stapling response
*/
int ocsp;
/**
* external_sim_resp - Response from external SIM processing
*
* This field should not be set in configuration step. It is only used
* internally when control interface is used to request external
* SIM/USIM processing.
*/
char *external_sim_resp;
};

View file

@ -348,6 +348,8 @@ struct eap_sm {
struct ext_password_data *ext_pw;
struct wpabuf *ext_pw_buf;
int external_sim;
};
const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len);

View file

@ -1479,6 +1479,7 @@ void eapol_sm_notify_config(struct eapol_sm *sm,
eap_set_fast_reauth(sm->eap, conf->fast_reauth);
eap_set_workaround(sm->eap, conf->workaround);
eap_set_force_disabled(sm->eap, conf->eap_disabled);
eap_set_external_sim(sm->eap, conf->external_sim);
}
}

View file

@ -53,6 +53,11 @@ struct eapol_config {
* eap_disabled - Whether EAP is disabled
*/
int eap_disabled;
/**
* external_sim - Use external processing for SIM/USIM operations
*/
int external_sim;
};
struct eapol_sm;

View file

@ -284,6 +284,17 @@ OK
Note: the return value of add_cred is used as the first argument to
the following set_cred commands.
Add a SIM credential using a external SIM/USIM processing:
> set external_sim 1
OK
> add_cred
1
> set_cred 1 imsi "23456-0000000000"
OK
> set_cred 1 eap SIM
OK
Add a WPA2-Enterprise network:

View file

@ -1815,6 +1815,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap)
os_free(eap->pending_req_otp);
os_free(eap->pac_file);
os_free(eap->new_password);
os_free(eap->external_sim_resp);
}
#endif /* IEEE8021X_EAPOL */
@ -3194,6 +3195,7 @@ static const struct global_parse_data global_fields[] = {
{ STR(pkcs11_module_path), 0 },
{ STR(pcsc_reader), 0 },
{ STR(pcsc_pin), 0 },
{ INT(external_sim), 0 },
{ STR(driver_param), 0 },
{ INT(dot11RSNAConfigPMKLifetime), 0 },
{ INT(dot11RSNAConfigPMKReauthThreshold), 0 },

View file

@ -452,6 +452,11 @@ struct wpa_config {
*/
char *pcsc_pin;
/**
* external_sim - Use external processing for SIM/USIM operations
*/
int external_sim;
/**
* driver_param - Driver interface parameters
*

View file

@ -1055,6 +1055,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
if (config->sched_scan_interval)
fprintf(f, "sched_scan_interval=%u\n",
config->sched_scan_interval);
if (config->external_sim)
fprintf(f, "external_sim=%d\n", config->external_sim);
}
#endif /* CONFIG_NO_CONFIG_WRITE */

View file

@ -623,6 +623,9 @@ static int wpa_config_write_global(struct wpa_config *config, HKEY hk)
wpa_config_write_reg_dword(hk, TEXT("okc"), config->okc, 0);
wpa_config_write_reg_dword(hk, TEXT("pmf"), config->pmf, 0);
wpa_config_write_reg_dword(hk, TEXT("external_sim"),
config->external_sim, 0);
return 0;
}

View file

@ -551,6 +551,7 @@ static int test_eapol(struct eapol_test_data *e, struct wpa_supplicant *wpa_s,
eapol_conf.required_keys = 0;
eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
eapol_conf.workaround = ssid->eap_workaround;
eapol_conf.external_sim = wpa_s->conf->external_sim;
eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);

View file

@ -275,7 +275,8 @@ int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s,
#ifdef PCSC_FUNCS
int aka = 0, sim = 0;
if (ssid->eap.pcsc == NULL || wpa_s->scard != NULL)
if (ssid->eap.pcsc == NULL || wpa_s->scard != NULL ||
wpa_s->conf->external_sim)
return 0;
if (ssid->eap.eap_methods == NULL) {

View file

@ -1407,7 +1407,8 @@ static struct wpa_cred * interworking_credentials_available_3gpp(
#endif /* CONFIG_EAP_PROXY */
if (cred->imsi == NULL || !cred->imsi[0] ||
cred->milenage == NULL || !cred->milenage[0])
(!wpa_s->conf->external_sim &&
(cred->milenage == NULL || !cred->milenage[0])))
continue;
sep = os_strchr(cred->imsi, '-');

View file

@ -625,7 +625,7 @@ static char ** wpa_cli_complete_set(const char *str, int pos)
"wps_nfc_dev_pw", "ext_password_backend",
"p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
"sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
"ignore_old_scan_res", "freq_list"
"ignore_old_scan_res", "freq_list", "external_sim"
};
int i, num_fields = sizeof(fields) / sizeof(fields[0]);
@ -1270,6 +1270,38 @@ static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
char cmd[256], *pos, *end;
int i, ret;
if (argc < 2) {
printf("Invalid SIM command: needs two arguments "
"(network id and SIM operation response)\n");
return -1;
}
end = cmd + sizeof(cmd);
pos = cmd;
ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s",
argv[0], argv[1]);
if (ret < 0 || ret >= end - pos) {
printf("Too long SIM command.\n");
return -1;
}
pos += ret;
for (i = 2; i < argc; i++) {
ret = os_snprintf(pos, end - pos, " %s", argv[i]);
if (ret < 0 || ret >= end - pos) {
printf("Too long SIM command.\n");
return -1;
}
pos += ret;
}
return wpa_ctrl_command(ctrl, cmd);
}
static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@ -2466,6 +2498,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
cli_cmd_flag_sensitive,
"<network id> <passphrase> = configure private key passphrase\n"
" for an SSID" },
{ "sim", wpa_cli_cmd_sim, NULL,
cli_cmd_flag_sensitive,
"<network id> <pin> = report SIM operation result" },
{ "bssid", wpa_cli_cmd_bssid, NULL,
cli_cmd_flag_none,
"<network id> <BSSID> = set preferred BSSID for an SSID" },

View file

@ -303,6 +303,7 @@ void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
!wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
eapol_conf.external_sim = wpa_s->conf->external_sim;
eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
#endif /* IEEE8021X_EAPOL */
}
@ -3750,6 +3751,10 @@ int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
if (ssid == wpa_s->current_ssid)
wpa_s->reassociate = 1;
break;
case WPA_CTRL_REQ_SIM:
os_free(eap->external_sim_resp);
eap->external_sim_resp = os_strdup(value);
break;
default:
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
return -1;

View file

@ -611,6 +611,8 @@ enum wpa_ctrl_req_type wpa_supplicant_ctrl_req_from_string(const char *field)
return WPA_CTRL_REQ_EAP_OTP;
else if (os_strcmp(field, "PASSPHRASE") == 0)
return WPA_CTRL_REQ_EAP_PASSPHRASE;
else if (os_strcmp(field, "SIM") == 0)
return WPA_CTRL_REQ_SIM;
return WPA_CTRL_REQ_UNKNOWN;
}
@ -647,6 +649,9 @@ const char * wpa_supplicant_ctrl_req_to_string(enum wpa_ctrl_req_type field,
*txt = "Private key passphrase";
ret = "PASSPHRASE";
break;
case WPA_CTRL_REQ_SIM:
ret = "SIM";
break;
default:
break;
}