Allow PC/SC reader to be selected and initialized at start
New global configuration parameters pcsc_reader and pcsc_pin can now be used to initialize PC/SC reader context at start of wpa_supplicant. Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
3825a19bfa
commit
f64adcd71e
9 changed files with 115 additions and 18 deletions
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* WPA Supplicant / PC/SC smartcard interface for USIM, GSM SIM
|
* WPA Supplicant / PC/SC smartcard interface for USIM, GSM SIM
|
||||||
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2004-2007, 2012, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -417,6 +417,7 @@ static int scard_get_aid(struct scard_data *scard, unsigned char *aid,
|
||||||
/**
|
/**
|
||||||
* scard_init - Initialize SIM/USIM connection using PC/SC
|
* scard_init - Initialize SIM/USIM connection using PC/SC
|
||||||
* @sim_type: Allowed SIM types (SIM, USIM, or both)
|
* @sim_type: Allowed SIM types (SIM, USIM, or both)
|
||||||
|
* @reader: Reader name prefix to search for
|
||||||
* Returns: Pointer to private data structure, or %NULL on failure
|
* Returns: Pointer to private data structure, or %NULL on failure
|
||||||
*
|
*
|
||||||
* This function is used to initialize SIM/USIM connection. PC/SC is used to
|
* This function is used to initialize SIM/USIM connection. PC/SC is used to
|
||||||
|
@ -425,10 +426,10 @@ static int scard_get_aid(struct scard_data *scard, unsigned char *aid,
|
||||||
* access some of the card functions. Once the connection is not needed
|
* access some of the card functions. Once the connection is not needed
|
||||||
* anymore, scard_deinit() can be used to close it.
|
* anymore, scard_deinit() can be used to close it.
|
||||||
*/
|
*/
|
||||||
struct scard_data * scard_init(scard_sim_type sim_type)
|
struct scard_data * scard_init(scard_sim_type sim_type, const char *reader)
|
||||||
{
|
{
|
||||||
long ret;
|
long ret;
|
||||||
unsigned long len;
|
unsigned long len, pos;
|
||||||
struct scard_data *scard;
|
struct scard_data *scard;
|
||||||
#ifdef CONFIG_NATIVE_WINDOWS
|
#ifdef CONFIG_NATIVE_WINDOWS
|
||||||
TCHAR *readers = NULL;
|
TCHAR *readers = NULL;
|
||||||
|
@ -482,17 +483,39 @@ struct scard_data * scard_init(scard_sim_type sim_type)
|
||||||
"available.");
|
"available.");
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
/* readers is a list of available reader. Last entry is terminated with
|
wpa_hexdump_ascii(MSG_DEBUG, "SCARD: Readers", (u8 *) readers, len);
|
||||||
* double NUL.
|
/*
|
||||||
* TODO: add support for selecting the reader; now just use the first
|
* readers is a list of available readers. The last entry is terminated
|
||||||
* one.. */
|
* with double null.
|
||||||
|
*/
|
||||||
|
pos = 0;
|
||||||
#ifdef UNICODE
|
#ifdef UNICODE
|
||||||
wpa_printf(MSG_DEBUG, "SCARD: Selected reader='%S'", readers);
|
/* TODO */
|
||||||
#else /* UNICODE */
|
#else /* UNICODE */
|
||||||
wpa_printf(MSG_DEBUG, "SCARD: Selected reader='%s'", readers);
|
while (pos < len) {
|
||||||
|
if (reader == NULL ||
|
||||||
|
os_strncmp(&readers[pos], reader, os_strlen(reader)) == 0)
|
||||||
|
break;
|
||||||
|
while (pos < len && readers[pos])
|
||||||
|
pos++;
|
||||||
|
pos++; /* skip separating null */
|
||||||
|
if (pos < len && readers[pos] == '\0')
|
||||||
|
pos = len; /* double null terminates list */
|
||||||
|
}
|
||||||
|
#endif /* UNICODE */
|
||||||
|
if (pos >= len) {
|
||||||
|
wpa_printf(MSG_WARNING, "SCARD: No reader with prefix '%s' "
|
||||||
|
"found", reader);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef UNICODE
|
||||||
|
wpa_printf(MSG_DEBUG, "SCARD: Selected reader='%S'", &readers[pos]);
|
||||||
|
#else /* UNICODE */
|
||||||
|
wpa_printf(MSG_DEBUG, "SCARD: Selected reader='%s'", &readers[pos]);
|
||||||
#endif /* UNICODE */
|
#endif /* UNICODE */
|
||||||
|
|
||||||
ret = SCardConnect(scard->ctx, readers, SCARD_SHARE_SHARED,
|
ret = SCardConnect(scard->ctx, &readers[pos], SCARD_SHARE_SHARED,
|
||||||
SCARD_PROTOCOL_T0, &scard->card, &scard->protocol);
|
SCARD_PROTOCOL_T0, &scard->card, &scard->protocol);
|
||||||
if (ret != SCARD_S_SUCCESS) {
|
if (ret != SCARD_S_SUCCESS) {
|
||||||
if (ret == (long) SCARD_E_NO_SMARTCARD)
|
if (ret == (long) SCARD_E_NO_SMARTCARD)
|
||||||
|
|
|
@ -37,7 +37,7 @@ typedef enum {
|
||||||
|
|
||||||
|
|
||||||
#ifdef PCSC_FUNCS
|
#ifdef PCSC_FUNCS
|
||||||
struct scard_data * scard_init(scard_sim_type sim_type);
|
struct scard_data * scard_init(scard_sim_type sim_type, const char *reader);
|
||||||
void scard_deinit(struct scard_data *scard);
|
void scard_deinit(struct scard_data *scard);
|
||||||
|
|
||||||
int scard_set_pin(struct scard_data *scard, const char *pin);
|
int scard_set_pin(struct scard_data *scard, const char *pin);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* WPA Supplicant / Configuration parser and common functions
|
* WPA Supplicant / Configuration parser and common functions
|
||||||
* Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -1832,6 +1832,8 @@ void wpa_config_free(struct wpa_config *config)
|
||||||
os_free(config->opensc_engine_path);
|
os_free(config->opensc_engine_path);
|
||||||
os_free(config->pkcs11_engine_path);
|
os_free(config->pkcs11_engine_path);
|
||||||
os_free(config->pkcs11_module_path);
|
os_free(config->pkcs11_module_path);
|
||||||
|
os_free(config->pcsc_reader);
|
||||||
|
os_free(config->pcsc_pin);
|
||||||
os_free(config->driver_param);
|
os_free(config->driver_param);
|
||||||
os_free(config->device_name);
|
os_free(config->device_name);
|
||||||
os_free(config->manufacturer);
|
os_free(config->manufacturer);
|
||||||
|
@ -2704,6 +2706,8 @@ static const struct global_parse_data global_fields[] = {
|
||||||
{ STR(opensc_engine_path), 0 },
|
{ STR(opensc_engine_path), 0 },
|
||||||
{ STR(pkcs11_engine_path), 0 },
|
{ STR(pkcs11_engine_path), 0 },
|
||||||
{ STR(pkcs11_module_path), 0 },
|
{ STR(pkcs11_module_path), 0 },
|
||||||
|
{ STR(pcsc_reader), 0 },
|
||||||
|
{ STR(pcsc_pin), 0 },
|
||||||
{ STR(driver_param), 0 },
|
{ STR(driver_param), 0 },
|
||||||
{ INT(dot11RSNAConfigPMKLifetime), 0 },
|
{ INT(dot11RSNAConfigPMKLifetime), 0 },
|
||||||
{ INT(dot11RSNAConfigPMKReauthThreshold), 0 },
|
{ INT(dot11RSNAConfigPMKReauthThreshold), 0 },
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* WPA Supplicant / Configuration file structures
|
* WPA Supplicant / Configuration file structures
|
||||||
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -290,6 +290,23 @@ struct wpa_config {
|
||||||
*/
|
*/
|
||||||
char *pkcs11_module_path;
|
char *pkcs11_module_path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pcsc_reader - PC/SC reader name prefix
|
||||||
|
*
|
||||||
|
* If not %NULL, PC/SC reader with a name that matches this prefix is
|
||||||
|
* initialized for SIM/USIM access. Empty string can be used to match
|
||||||
|
* the first available reader.
|
||||||
|
*/
|
||||||
|
char *pcsc_reader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pcsc_pin - PIN for USIM, GSM SIM, and smartcards
|
||||||
|
*
|
||||||
|
* This field is used to configure PIN for SIM/USIM for EAP-SIM and
|
||||||
|
* EAP-AKA. If left out, this will be asked through control interface.
|
||||||
|
*/
|
||||||
|
char *pcsc_pin;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* driver_param - Driver interface parameters
|
* driver_param - Driver interface parameters
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* WPA Supplicant / Configuration backend: text file
|
* WPA Supplicant / Configuration backend: text file
|
||||||
* Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -716,6 +716,10 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
|
||||||
if (config->pkcs11_module_path)
|
if (config->pkcs11_module_path)
|
||||||
fprintf(f, "pkcs11_module_path=%s\n",
|
fprintf(f, "pkcs11_module_path=%s\n",
|
||||||
config->pkcs11_module_path);
|
config->pkcs11_module_path);
|
||||||
|
if (config->pcsc_reader)
|
||||||
|
fprintf(f, "pcsc_reader=%s\n", config->pcsc_reader);
|
||||||
|
if (config->pcsc_pin)
|
||||||
|
fprintf(f, "pcsc_pin=%s\n", config->pcsc_pin);
|
||||||
if (config->driver_param)
|
if (config->driver_param)
|
||||||
fprintf(f, "driver_param=%s\n", config->driver_param);
|
fprintf(f, "driver_param=%s\n", config->driver_param);
|
||||||
if (config->dot11RSNAConfigPMKLifetime)
|
if (config->dot11RSNAConfigPMKLifetime)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* WPA Supplicant - test code
|
* WPA Supplicant - test code
|
||||||
* Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -856,7 +856,7 @@ static int scard_test(void)
|
||||||
unsigned char aka_ik[IK_LEN];
|
unsigned char aka_ik[IK_LEN];
|
||||||
unsigned char aka_ck[CK_LEN];
|
unsigned char aka_ck[CK_LEN];
|
||||||
|
|
||||||
scard = scard_init(SCARD_TRY_BOTH);
|
scard = scard_init(SCARD_TRY_BOTH, NULL);
|
||||||
if (scard == NULL)
|
if (scard == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
if (scard_set_pin(scard, "1234")) {
|
if (scard_set_pin(scard, "1234")) {
|
||||||
|
@ -956,7 +956,7 @@ static int scard_get_triplets(int argc, char *argv[])
|
||||||
wpa_debug_level = 99;
|
wpa_debug_level = 99;
|
||||||
}
|
}
|
||||||
|
|
||||||
scard = scard_init(SCARD_GSM_SIM_ONLY);
|
scard = scard_init(SCARD_GSM_SIM_ONLY, NULL);
|
||||||
if (scard == NULL) {
|
if (scard == NULL) {
|
||||||
printf("Failed to open smartcard connection\n");
|
printf("Failed to open smartcard connection\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -266,7 +266,7 @@ int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s,
|
||||||
else
|
else
|
||||||
type = SCARD_GSM_SIM_ONLY;
|
type = SCARD_GSM_SIM_ONLY;
|
||||||
|
|
||||||
wpa_s->scard = scard_init(type);
|
wpa_s->scard = scard_init(type, NULL);
|
||||||
if (wpa_s->scard == NULL) {
|
if (wpa_s->scard == NULL) {
|
||||||
wpa_msg(wpa_s, MSG_WARNING, "Failed to initialize SIM "
|
wpa_msg(wpa_s, MSG_WARNING, "Failed to initialize SIM "
|
||||||
"(pcsc-lite)");
|
"(pcsc-lite)");
|
||||||
|
|
|
@ -2342,6 +2342,48 @@ void wpa_supplicant_apply_ht_overrides(
|
||||||
#endif /* CONFIG_HT_OVERRIDES */
|
#endif /* CONFIG_HT_OVERRIDES */
|
||||||
|
|
||||||
|
|
||||||
|
static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
#ifdef PCSC_FUNCS
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (!wpa_s->conf->pcsc_reader)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
wpa_s->scard = scard_init(SCARD_TRY_BOTH, wpa_s->conf->pcsc_reader);
|
||||||
|
if (!wpa_s->scard)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (wpa_s->conf->pcsc_pin &&
|
||||||
|
scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
|
||||||
|
scard_deinit(wpa_s->scard);
|
||||||
|
wpa_s->scard = NULL;
|
||||||
|
wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = sizeof(wpa_s->imsi) - 1;
|
||||||
|
if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
|
||||||
|
scard_deinit(wpa_s->scard);
|
||||||
|
wpa_s->scard = NULL;
|
||||||
|
wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
wpa_s->imsi[len] = '\0';
|
||||||
|
|
||||||
|
wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
|
||||||
|
wpa_s->imsi, wpa_s->mnc_len);
|
||||||
|
|
||||||
|
wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
|
||||||
|
eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
|
||||||
|
#endif /* PCSC_FUNCS */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
|
static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
|
||||||
struct wpa_interface *iface)
|
struct wpa_interface *iface)
|
||||||
{
|
{
|
||||||
|
@ -2563,6 +2605,9 @@ next_driver:
|
||||||
if (wpa_bss_init(wpa_s) < 0)
|
if (wpa_bss_init(wpa_s) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (pcsc_reader_init(wpa_s) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -334,6 +334,10 @@ struct wpa_supplicant {
|
||||||
* previous association event */
|
* previous association event */
|
||||||
|
|
||||||
struct scard_data *scard;
|
struct scard_data *scard;
|
||||||
|
#ifdef PCSC_FUNCS
|
||||||
|
char imsi[20];
|
||||||
|
int mnc_len;
|
||||||
|
#endif /* PCSC_FUNCS */
|
||||||
|
|
||||||
unsigned char last_eapol_src[ETH_ALEN];
|
unsigned char last_eapol_src[ETH_ALEN];
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue