]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
eap_proxy: Build realm from IMSI for proxy based EAP methods
authorVidyullatha Kanchanapally <vkanchan@qti.qualcomm.com>
Fri, 2 Jun 2017 13:08:20 +0000 (18:38 +0530)
committerJouni Malinen <j@w1.fi>
Tue, 6 Jun 2017 00:41:23 +0000 (03:41 +0300)
For proxy based EAP methods, the EAP identity is constructed in
eap_proxy layer from IMSI when required. Realm information from identity
is used to do ERP eventually, hence construct the realm for proxy based
methods from IMSI in core wpa_supplicant to enable the ERP use case.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
src/eap_peer/eap.c
src/eap_peer/eap.h
src/eapol_supp/eapol_supp_sm.c
src/eapol_supp/eapol_supp_sm.h

index 359701c373c36dbd4fbf764b0b515b07115bc7da..59967fdd7da584a6f51a78e2aad235b1f566e7b8 100644 (file)
@@ -121,15 +121,17 @@ static void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
 
 
 /**
- * eap_allowed_method - Check whether EAP method is allowed
+ * eap_config_allowed_method - Check whether EAP method is allowed
  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
+ * @config: EAP configuration
  * @vendor: Vendor-Id for expanded types or 0 = IETF for legacy types
  * @method: EAP type
  * Returns: 1 = allowed EAP method, 0 = not allowed
  */
-int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method)
+static int eap_config_allowed_method(struct eap_sm *sm,
+                                    struct eap_peer_config *config,
+                                    int vendor, u32 method)
 {
-       struct eap_peer_config *config = eap_get_config(sm);
        int i;
        struct eap_method_type *m;
 
@@ -146,6 +148,57 @@ int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method)
 }
 
 
+/**
+ * eap_allowed_method - Check whether EAP method is allowed
+ * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
+ * @vendor: Vendor-Id for expanded types or 0 = IETF for legacy types
+ * @method: EAP type
+ * Returns: 1 = allowed EAP method, 0 = not allowed
+ */
+int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method)
+{
+       return eap_config_allowed_method(sm, eap_get_config(sm), vendor,
+                                        method);
+}
+
+
+#if defined(PCSC_FUNCS) || defined(CONFIG_EAP_PROXY)
+static int eap_sm_append_3gpp_realm(struct eap_sm *sm, char *imsi,
+                                   size_t max_len, size_t *imsi_len,
+                                   int mnc_len)
+{
+       char *pos, mnc[4];
+
+       if (*imsi_len + 36 > max_len) {
+               wpa_printf(MSG_WARNING, "No room for realm in IMSI buffer");
+               return -1;
+       }
+
+       if (mnc_len != 2 && mnc_len != 3)
+               mnc_len = 3;
+
+       if (mnc_len == 2) {
+               mnc[0] = '0';
+               mnc[1] = imsi[3];
+               mnc[2] = imsi[4];
+       } else if (mnc_len == 3) {
+               mnc[0] = imsi[3];
+               mnc[1] = imsi[4];
+               mnc[2] = imsi[5];
+       }
+       mnc[3] = '\0';
+
+       pos = imsi + *imsi_len;
+       pos += os_snprintf(pos, imsi + max_len - pos,
+                          "@wlan.mnc%s.mcc%c%c%c.3gppnetwork.org",
+                          mnc, imsi[0], imsi[1], imsi[2]);
+       *imsi_len = pos - imsi;
+
+       return 0;
+}
+#endif /* PCSC_FUNCS || CONFIG_EAP_PROXY */
+
+
 /*
  * This state initializes state machine variables when the machine is
  * activated (portEnabled = TRUE). This is also used when re-starting
@@ -412,6 +465,44 @@ static char * eap_get_realm(struct eap_sm *sm, struct eap_peer_config *config)
                }
        }
 
+#ifdef CONFIG_EAP_PROXY
+       /* When identity is not provided in the config, build the realm from
+        * IMSI for eap_proxy based methods.
+        */
+       if (!config->identity && !config->anonymous_identity &&
+           sm->eapol_cb->get_imsi &&
+           (eap_config_allowed_method(sm, config, EAP_VENDOR_IETF,
+                                      EAP_TYPE_SIM) ||
+            eap_config_allowed_method(sm, config, EAP_VENDOR_IETF,
+                                      EAP_TYPE_AKA) ||
+            eap_config_allowed_method(sm, config, EAP_VENDOR_IETF,
+                                      EAP_TYPE_AKA_PRIME))) {
+               char imsi[100];
+               size_t imsi_len;
+               int mnc_len, pos;
+
+               wpa_printf(MSG_DEBUG, "EAP: Build realm from IMSI (eap_proxy)");
+               mnc_len = sm->eapol_cb->get_imsi(sm->eapol_ctx, imsi,
+                                                &imsi_len);
+               if (mnc_len < 0)
+                       return NULL;
+
+               pos = imsi_len + 1; /* points to the beginning of the realm */
+               if (eap_sm_append_3gpp_realm(sm, imsi, sizeof(imsi), &imsi_len,
+                                            mnc_len) < 0) {
+                       wpa_printf(MSG_WARNING, "Could not append realm");
+                       return NULL;
+               }
+
+               realm = os_strdup(&imsi[pos]);
+               if (!realm)
+                       return NULL;
+
+               wpa_printf(MSG_DEBUG, "EAP: Generated realm '%s'", realm);
+               return realm;
+       }
+#endif /* CONFIG_EAP_PROXY */
+
        return NULL;
 }
 
@@ -1401,48 +1492,6 @@ static int mnc_len_from_imsi(const char *imsi)
 }
 
 
-static int eap_sm_append_3gpp_realm(struct eap_sm *sm, char *imsi,
-                                   size_t max_len, size_t *imsi_len)
-{
-       int mnc_len;
-       char *pos, mnc[4];
-
-       if (*imsi_len + 36 > max_len) {
-               wpa_printf(MSG_WARNING, "No room for realm in IMSI buffer");
-               return -1;
-       }
-
-       /* MNC (2 or 3 digits) */
-       mnc_len = scard_get_mnc_len(sm->scard_ctx);
-       if (mnc_len < 0)
-               mnc_len = mnc_len_from_imsi(imsi);
-       if (mnc_len < 0) {
-               wpa_printf(MSG_INFO, "Failed to get MNC length from (U)SIM "
-                          "assuming 3");
-               mnc_len = 3;
-       }
-
-       if (mnc_len == 2) {
-               mnc[0] = '0';
-               mnc[1] = imsi[3];
-               mnc[2] = imsi[4];
-       } else if (mnc_len == 3) {
-               mnc[0] = imsi[3];
-               mnc[1] = imsi[4];
-               mnc[2] = imsi[5];
-       }
-       mnc[3] = '\0';
-
-       pos = imsi + *imsi_len;
-       pos += os_snprintf(pos, imsi + max_len - pos,
-                          "@wlan.mnc%s.mcc%c%c%c.3gppnetwork.org",
-                          mnc, imsi[0], imsi[1], imsi[2]);
-       *imsi_len = pos - imsi;
-
-       return 0;
-}
-
-
 static int eap_sm_imsi_identity(struct eap_sm *sm,
                                struct eap_peer_config *conf)
 {
@@ -1450,7 +1499,7 @@ static int eap_sm_imsi_identity(struct eap_sm *sm,
        char imsi[100];
        size_t imsi_len;
        struct eap_method_type *m = conf->eap_methods;
-       int i;
+       int i, mnc_len;
 
        imsi_len = sizeof(imsi);
        if (scard_get_imsi(sm->scard_ctx, imsi, &imsi_len)) {
@@ -1465,7 +1514,18 @@ static int eap_sm_imsi_identity(struct eap_sm *sm,
                return -1;
        }
 
-       if (eap_sm_append_3gpp_realm(sm, imsi, sizeof(imsi), &imsi_len) < 0) {
+       /* MNC (2 or 3 digits) */
+       mnc_len = scard_get_mnc_len(sm->scard_ctx);
+       if (mnc_len < 0)
+               mnc_len = mnc_len_from_imsi(imsi);
+       if (mnc_len < 0) {
+               wpa_printf(MSG_INFO, "Failed to get MNC length from (U)SIM "
+                          "assuming 3");
+               mnc_len = 3;
+       }
+
+       if (eap_sm_append_3gpp_realm(sm, imsi, sizeof(imsi), &imsi_len,
+                                    mnc_len) < 0) {
                wpa_printf(MSG_WARNING, "Could not add realm to SIM identity");
                return -1;
        }
index 80fbbf260a5f08b21761f175720b2e5450ed65af..6d415dcb9ea8c3b6021939085399f889060d2b7b 100644 (file)
@@ -260,6 +260,15 @@ struct eapol_callbacks {
         */
        void (*eap_proxy_notify_sim_status)(void *ctx,
                                            enum eap_proxy_sim_state sim_state);
+
+       /**
+        * get_imsi - Get the IMSI value from eap_proxy
+        * @ctx: eapol_ctx from eap_peer_sm_init() call
+        * @imsi: Buffer for IMSI value
+        * @len: Buffer for returning IMSI length in octets
+        * Returns: MNC length (2 or 3) or -1 on error
+        */
+       int (*get_imsi)(void *ctx, char *imsi, size_t *len);
 #endif /* CONFIG_EAP_PROXY */
 
        /**
index ade43d8ef62226ccf281cf6e55bbba49e0303740..75c3429f7cf02ec20687d94faabcb123863bb662 100644 (file)
@@ -2065,6 +2065,7 @@ static const struct eapol_callbacks eapol_cb =
 #ifdef CONFIG_EAP_PROXY
        eapol_sm_eap_proxy_cb,
        eapol_sm_eap_proxy_notify_sim_status,
+       eapol_sm_get_eap_proxy_imsi,
 #endif /* CONFIG_EAP_PROXY */
        eapol_sm_set_anon_id
 };
@@ -2173,8 +2174,10 @@ int eapol_sm_failed(struct eapol_sm *sm)
 
 
 #ifdef CONFIG_EAP_PROXY
-int eapol_sm_get_eap_proxy_imsi(struct eapol_sm *sm, char *imsi, size_t *len)
+int eapol_sm_get_eap_proxy_imsi(void *ctx, char *imsi, size_t *len)
 {
+       struct eapol_sm *sm = ctx;
+
        if (sm->eap_proxy == NULL)
                return -1;
        return eap_proxy_get_imsi(sm->eap_proxy, imsi, len);
index aa91b8cd545186d0465e4c4bb9ac700425789940..458d51dd1ccfb4a06daa4daa4ae27515b899bd8f 100644 (file)
@@ -339,7 +339,7 @@ void eapol_sm_erp_flush(struct eapol_sm *sm);
 struct wpabuf * eapol_sm_build_erp_reauth_start(struct eapol_sm *sm);
 void eapol_sm_process_erp_finish(struct eapol_sm *sm, const u8 *buf,
                                 size_t len);
-int eapol_sm_get_eap_proxy_imsi(struct eapol_sm *sm, char *imsi, size_t *len);
+int eapol_sm_get_eap_proxy_imsi(void *ctx, char *imsi, size_t *len);
 int eapol_sm_update_erp_next_seq_num(struct eapol_sm *sm, u16 next_seq_num);
 int eapol_sm_get_erp_info(struct eapol_sm *sm, struct eap_peer_config *config,
                          const u8 **username, size_t *username_len,