]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Allow PC/SC reader to be selected and initialized at start
authorJouni Malinen <j@w1.fi>
Sun, 26 Feb 2012 11:07:05 +0000 (13:07 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 26 Feb 2012 11:09:30 +0000 (13:09 +0200)
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>

src/utils/pcsc_funcs.c
src/utils/pcsc_funcs.h
wpa_supplicant/config.c
wpa_supplicant/config.h
wpa_supplicant/config_file.c
wpa_supplicant/eapol_test.c
wpa_supplicant/events.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index a97f9fa22066390121ffa6d67e959a18a527ac36..4b43a3795aede34b447abc12de595aa1a4bc8ddc 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * 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.
  * 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
  * @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
  *
  * 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
  * 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;
-       unsigned long len;
+       unsigned long len, pos;
        struct scard_data *scard;
 #ifdef CONFIG_NATIVE_WINDOWS
        TCHAR *readers = NULL;
@@ -482,17 +483,39 @@ struct scard_data * scard_init(scard_sim_type sim_type)
                           "available.");
                goto failed;
        }
-       /* readers is a list of available reader. Last entry is terminated with
-        * double NUL.
-        * TODO: add support for selecting the reader; now just use the first
-        * one.. */
+       wpa_hexdump_ascii(MSG_DEBUG, "SCARD: Readers", (u8 *) readers, len);
+       /*
+        * readers is a list of available readers. The last entry is terminated
+        * with double null.
+        */
+       pos = 0;
 #ifdef UNICODE
-       wpa_printf(MSG_DEBUG, "SCARD: Selected reader='%S'", readers);
+       /* TODO */
 #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 */
 
-       ret = SCardConnect(scard->ctx, readers, SCARD_SHARE_SHARED,
+       ret = SCardConnect(scard->ctx, &readers[pos], SCARD_SHARE_SHARED,
                           SCARD_PROTOCOL_T0, &scard->card, &scard->protocol);
        if (ret != SCARD_S_SUCCESS) {
                if (ret == (long) SCARD_E_NO_SMARTCARD)
index 2fd3610512a41146d1ec57ef3ffaba95ce26b350..507dab31636b553f8f5a18ec0b3528bd89cd949e 100644 (file)
@@ -37,7 +37,7 @@ typedef enum {
 
 
 #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);
 
 int scard_set_pin(struct scard_data *scard, const char *pin);
index 72387f85b3058fc2c22c4da88baecdc7da482e71..9fd2a700197a95cb2cafa1ca2da4c6c4f46e3084 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * 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.
  * 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->pkcs11_engine_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->device_name);
        os_free(config->manufacturer);
@@ -2704,6 +2706,8 @@ static const struct global_parse_data global_fields[] = {
        { STR(opensc_engine_path), 0 },
        { STR(pkcs11_engine_path), 0 },
        { STR(pkcs11_module_path), 0 },
+       { STR(pcsc_reader), 0 },
+       { STR(pcsc_pin), 0 },
        { STR(driver_param), 0 },
        { INT(dot11RSNAConfigPMKLifetime), 0 },
        { INT(dot11RSNAConfigPMKReauthThreshold), 0 },
index 72906fb7f424116a2a20e3a251ff0f688fcbe349..0e654fc49e28a531243c4320a23f66e7dd8cb4fa 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * 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.
  * See README for more details.
@@ -290,6 +290,23 @@ struct wpa_config {
         */
        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
         *
index f8f4ff14d49dfb737f2c6e448e32291013d24773..12e909ae4301e6b8cec98c41f9052c2e667e41d8 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * 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.
  * 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)
                fprintf(f, "pkcs11_module_path=%s\n",
                        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)
                fprintf(f, "driver_param=%s\n", config->driver_param);
        if (config->dot11RSNAConfigPMKLifetime)
index 65e6742fe2e2e4854b82573a0915cd941c2b9db8..e92dc12f9e07285b5f823bf08296d69dac4b06db 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * 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.
  * See README for more details.
@@ -856,7 +856,7 @@ static int scard_test(void)
        unsigned char aka_ik[IK_LEN];
        unsigned char aka_ck[CK_LEN];
 
-       scard = scard_init(SCARD_TRY_BOTH);
+       scard = scard_init(SCARD_TRY_BOTH, NULL);
        if (scard == NULL)
                return -1;
        if (scard_set_pin(scard, "1234")) {
@@ -956,7 +956,7 @@ static int scard_get_triplets(int argc, char *argv[])
                wpa_debug_level = 99;
        }
 
-       scard = scard_init(SCARD_GSM_SIM_ONLY);
+       scard = scard_init(SCARD_GSM_SIM_ONLY, NULL);
        if (scard == NULL) {
                printf("Failed to open smartcard connection\n");
                return -1;
index ec027020cdef4530f208c2413f5ceda69c6ab715..3af6dc1a8e3901e84230714ed7084041107df59c 100644 (file)
@@ -266,7 +266,7 @@ int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s,
        else
                type = SCARD_GSM_SIM_ONLY;
 
-       wpa_s->scard = scard_init(type);
+       wpa_s->scard = scard_init(type, NULL);
        if (wpa_s->scard == NULL) {
                wpa_msg(wpa_s, MSG_WARNING, "Failed to initialize SIM "
                        "(pcsc-lite)");
index 4c365dd45f5bcf53976d47b643784f740083a540..d02ce6ae50b12277b31c04b97f079f2ed5a217ff 100644 (file)
@@ -2342,6 +2342,48 @@ void wpa_supplicant_apply_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,
                                     struct wpa_interface *iface)
 {
@@ -2563,6 +2605,9 @@ next_driver:
        if (wpa_bss_init(wpa_s) < 0)
                return -1;
 
+       if (pcsc_reader_init(wpa_s) < 0)
+               return -1;
+
        return 0;
 }
 
index 91e5741865ca7986e95e6c2ecb5fab5ebcfb7745..cb9fd52905f84a5fe3e5f549492c050c76182593 100644 (file)
@@ -334,6 +334,10 @@ struct wpa_supplicant {
                             * previous association event */
 
        struct scard_data *scard;
+#ifdef PCSC_FUNCS
+       char imsi[20];
+       int mnc_len;
+#endif /* PCSC_FUNCS */
 
        unsigned char last_eapol_src[ETH_ALEN];