diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index fc3205e6a..0350b8e0a 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -2229,6 +2229,11 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var, return 0; } + if (os_strcmp(var, "pcsc") == 0) { + cred->pcsc = atoi(value); + return 0; + } + val = wpa_config_parse_string(value, &len); if (val == NULL) { wpa_printf(MSG_ERROR, "Line %d: invalid field '%s' string " diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 0dcb4c853..5b002a204 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -60,6 +60,11 @@ struct wpa_cred { */ int priority; + /** + * pcsc - Use PC/SC and SIM/USIM card + */ + int pcsc; + /** * realm - Home Realm for Interworking */ diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 12e909ae4..b3dd40e06 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -659,6 +659,8 @@ static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred) { if (cred->priority) fprintf(f, "\tpriority=%d\n", cred->priority); + if (cred->pcsc) + fprintf(f, "\tpcsc=%d\n", cred->pcsc); if (cred->realm) fprintf(f, "\trealm=\"%s\"\n", cred->realm); if (cred->username) diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c index 74d9a1a67..a721e5d30 100644 --- a/wpa_supplicant/interworking.c +++ b/wpa_supplicant/interworking.c @@ -599,6 +599,17 @@ static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s, for (cred = wpa_s->conf->cred; cred; cred = cred->next) { char *sep; + const char *imsi; + int mnc_len; + +#ifdef PCSC_FUNCS + if (cred->pcsc && wpa_s->conf->pcsc_reader && wpa_s->scard && + wpa_s->imsi[0]) { + imsi = wpa_s->imsi; + mnc_len = wpa_s->mnc_len; + goto compare; + } +#endif /* PCSC_FUNCS */ if (cred->imsi == NULL || !cred->imsi[0] || cred->milenage == NULL || !cred->milenage[0]) @@ -608,9 +619,13 @@ static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s, if (sep == NULL || (sep - cred->imsi != 5 && sep - cred->imsi != 6)) continue; + mnc_len = sep - cred->imsi - 3; + imsi = cred->imsi; - if (plmn_id_match(bss->anqp_3gpp, cred->imsi, - sep - cred->imsi - 3)) +#ifdef PCSC_FUNCS + compare: +#endif /* PCSC_FUNCS */ + if (plmn_id_match(bss->anqp_3gpp, imsi, mnc_len)) break; } if (cred == NULL) @@ -641,7 +656,7 @@ static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s, wpa_printf(MSG_DEBUG, "EAP-SIM not supported"); goto fail; } - if (set_root_nai(ssid, cred->imsi, '1') < 0) { + if (!cred->pcsc && set_root_nai(ssid, cred->imsi, '1') < 0) { wpa_printf(MSG_DEBUG, "Failed to set Root NAI"); goto fail; } @@ -650,10 +665,13 @@ static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s, if (wpa_config_set_quoted(ssid, "password", cred->milenage) < 0) goto fail; - } else { - /* TODO: PIN */ + } else if (cred->pcsc) { if (wpa_config_set_quoted(ssid, "pcsc", "") < 0) goto fail; + if (wpa_s->conf->pcsc_pin && + wpa_config_set_quoted(ssid, "pin", wpa_s->conf->pcsc_pin) + < 0) + goto fail; } if (cred->password && cred->password[0] && @@ -871,6 +889,17 @@ static struct wpa_cred * interworking_credentials_available_3gpp( for (cred = wpa_s->conf->cred; cred; cred = cred->next) { char *sep; + const char *imsi; + int mnc_len; + +#ifdef PCSC_FUNCS + if (cred->pcsc && wpa_s->conf->pcsc_reader && wpa_s->scard && + wpa_s->imsi[0]) { + imsi = wpa_s->imsi; + mnc_len = wpa_s->mnc_len; + goto compare; + } +#endif /* PCSC_FUNCS */ if (cred->imsi == NULL || !cred->imsi[0] || cred->milenage == NULL || !cred->milenage[0]) @@ -880,11 +909,15 @@ static struct wpa_cred * interworking_credentials_available_3gpp( if (sep == NULL || (sep - cred->imsi != 5 && sep - cred->imsi != 6)) continue; + mnc_len = sep - cred->imsi - 3; + imsi = cred->imsi; +#ifdef PCSC_FUNCS + compare: +#endif /* PCSC_FUNCS */ wpa_printf(MSG_DEBUG, "Interworking: Parsing 3GPP info from " MACSTR, MAC2STR(bss->bssid)); - ret = plmn_id_match(bss->anqp_3gpp, cred->imsi, - sep - cred->imsi - 3); + ret = plmn_id_match(bss->anqp_3gpp, imsi, mnc_len); wpa_printf(MSG_DEBUG, "PLMN match %sfound", ret ? "" : "not "); if (ret) { if (selected == NULL || diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index 279991a7e..70d3030e5 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -255,6 +255,8 @@ fast_reauth=1 # network (based on either an enabled network block or a credential) # with the highest priority value will be selected. # +# pcsc: Use PC/SC and SIM/USIM card +# # realm: Home Realm for Interworking # # username: Username for Interworking network selection