]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
EAP peer: Add framework for external SIM/USIM processing
authorJouni Malinen <j@w1.fi>
Sat, 19 Oct 2013 14:32:05 +0000 (17:32 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 20 Oct 2013 10:12:04 +0000 (13:12 +0300)
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>

18 files changed:
src/common/defs.h
src/eap_peer/eap.c
src/eap_peer/eap.h
src/eap_peer/eap_config.h
src/eap_peer/eap_i.h
src/eapol_supp/eapol_supp_sm.c
src/eapol_supp/eapol_supp_sm.h
wpa_supplicant/README-HS20
wpa_supplicant/config.c
wpa_supplicant/config.h
wpa_supplicant/config_file.c
wpa_supplicant/config_winreg.c
wpa_supplicant/eapol_test.c
wpa_supplicant/events.c
wpa_supplicant/interworking.c
wpa_supplicant/wpa_cli.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpas_glue.c

index 281dd8a5eb5c761796888ea9ba5d3ef4873e255c..0c90c2498addef498926fd50903fb95198fdf1eb 100644 (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
 };
 
index 554e7e94e6b2204b8b9fc68b9c0b5bc9ecae9056..3439c2dfc71279d4a88cc84138d4cdbf682c3c9f 100644 (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()
index f87f9b3b0cece8cb95a63bd38a087d5c2b24eece..711f41ff80cef4611d263e67a848c8d22866dd0b 100644 (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);
index 0392f871e83f54f8b53f7bafb1314f38a9f8473e..98ec1f7631bdff623210364ff09af178abac6675 100644 (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;
 };
 
 
index 62c867ca2fac9afbb255b84bdc58776ea0d03ce6..9307f3f60da9d6d9815b7a7566c1af1311ebb1bb 100644 (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);
index c4475e57ec93ee875d87d92e2552ebbe368f554a..03ec2cb4c806c698d0d6bcf102899c91bba09e5a 100644 (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);
        }
 }
 
index c4b87da1f6bf14b9296994bed9d45570cc24606a..6faf816d4232a7bad3c4b576e30b2ed43c600cc3 100644 (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;
index 940c57669afd064ac6a55323d0fffad30ec1540d..61e4a4dcc15301256a528923c2864dc113731239 100644 (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:
 
index 3c405be4b248f0b510acbb2e47e843b4485d3049..ea7ac5af81747cc0709bced70944bbe27eb17860 100644 (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 },
index e53c6367b522b0d6b352af5f345dfa34ffbf754e..2e558fdb4bc03fada4dcea2b577589ec54d885bf 100644 (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
         *
index f3eeca8d56dc4400f68d81e285d3a108f3cb1411..b8fff70ccddb11fc4be27ee91e54eaaf76064035 100644 (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 */
index 1b5e23797fb2a4c5f95a244fdd276d44eeca01fa..00a10045ee3e22cff04229e9ba18ce130a040921 100644 (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;
 }
 
index 0806e9cb9d46f3a5de561d94c7c79adccfa734a4..9024f23c6e2e2f95ea7c1a8a4984608c43c83ab2 100644 (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);
 
index 9c77ade073195aef0b3bb9a65d2d4194f07ed6fd..2e99af2c32dfded9be04f575802ab30189592b87 100644 (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) {
index 666e786a2517019d599f257728ef0ffd05d8960d..ec3d6cee6e7f01f20b86da1e43037ea5e0252a9c 100644 (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, '-');
index f84d1982e28c4586eccb65aa04743bcb4b6f2584..f95f7b1fe6083fa5a789199d5c8d81301c3d5a3c 100644 (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" },
index 06ba2c7a899ed71407f71ab5d1604071fa033379..ec938fe149d5fd93936a6aacde04b88e030cc33e 100644 (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;
index 61a42bd0c14e8e619c576a95bf137cf6f243a432..ab6cdca7c305cebcfc3a4e7004bb468e14e59ab0 100644 (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;
        }