]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - src/ap/ieee802_1x.c
ERP: Add support for ERP on EAP server and authenticator
[thirdparty/hostap.git] / src / ap / ieee802_1x.c
index d29838564f682465c27e7aa74522c42293bbf223..84a98abc48232dbaef701da1390cdd819b4cedfa 100644 (file)
@@ -296,9 +296,15 @@ static void ieee802_1x_learn_identity(struct hostapd_data *hapd,
 {
        const u8 *identity;
        size_t identity_len;
+       const struct eap_hdr *hdr = (const struct eap_hdr *) eap;
 
        if (len <= sizeof(struct eap_hdr) ||
-           eap[sizeof(struct eap_hdr)] != EAP_TYPE_IDENTITY)
+           (hdr->code == EAP_CODE_RESPONSE &&
+            eap[sizeof(struct eap_hdr)] != EAP_TYPE_IDENTITY) ||
+           (hdr->code == EAP_CODE_INITIATE &&
+            eap[sizeof(struct eap_hdr)] != EAP_ERP_TYPE_REAUTH) ||
+           (hdr->code != EAP_CODE_RESPONSE &&
+            hdr->code != EAP_CODE_INITIATE))
                return;
 
        identity = eap_get_identity(sm->eap, &identity_len);
@@ -711,6 +717,39 @@ static void handle_eap_response(struct hostapd_data *hapd,
 }
 
 
+static void handle_eap_initiate(struct hostapd_data *hapd,
+                               struct sta_info *sta, struct eap_hdr *eap,
+                               size_t len)
+{
+#ifdef CONFIG_ERP
+       u8 type, *data;
+       struct eapol_state_machine *sm = sta->eapol_sm;
+
+       if (sm == NULL)
+               return;
+
+       if (len < sizeof(*eap) + 1) {
+               wpa_printf(MSG_INFO,
+                          "handle_eap_initiate: too short response data");
+               return;
+       }
+
+       data = (u8 *) (eap + 1);
+       type = data[0];
+
+       hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,
+                      HOSTAPD_LEVEL_DEBUG, "received EAP packet (code=%d "
+                      "id=%d len=%d) from STA: EAP Initiate type %u",
+                      eap->code, eap->identifier, be_to_host16(eap->length),
+                      type);
+
+       wpabuf_free(sm->eap_if->eapRespData);
+       sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len);
+       sm->eapolEap = TRUE;
+#endif /* CONFIG_ERP */
+}
+
+
 /* Process incoming EAP packet from Supplicant */
 static void handle_eap(struct hostapd_data *hapd, struct sta_info *sta,
                       u8 *buf, size_t len)
@@ -754,6 +793,13 @@ static void handle_eap(struct hostapd_data *hapd, struct sta_info *sta,
        case EAP_CODE_FAILURE:
                wpa_printf(MSG_DEBUG, " (failure)");
                return;
+       case EAP_CODE_INITIATE:
+               wpa_printf(MSG_DEBUG, " (initiate)");
+               handle_eap_initiate(hapd, sta, eap, eap_len);
+               break;
+       case EAP_CODE_FINISH:
+               wpa_printf(MSG_DEBUG, " (finish)");
+               break;
        default:
                wpa_printf(MSG_DEBUG, " (unknown code)");
                return;
@@ -1986,12 +2032,43 @@ static void ieee802_1x_eapol_event(void *ctx, void *sta_ctx,
 }
 
 
+#ifdef CONFIG_ERP
+
+static struct eap_server_erp_key *
+ieee802_1x_erp_get_key(void *ctx, const char *keyname)
+{
+       struct hostapd_data *hapd = ctx;
+       struct eap_server_erp_key *erp;
+
+       dl_list_for_each(erp, &hapd->erp_keys, struct eap_server_erp_key,
+                        list) {
+               if (os_strcmp(erp->keyname_nai, keyname) == 0)
+                       return erp;
+       }
+
+       return NULL;
+}
+
+
+static int ieee802_1x_erp_add_key(void *ctx, struct eap_server_erp_key *erp)
+{
+       struct hostapd_data *hapd = ctx;
+
+       dl_list_add(&hapd->erp_keys, &erp->list);
+       return 0;
+}
+
+#endif /* CONFIG_ERP */
+
+
 int ieee802_1x_init(struct hostapd_data *hapd)
 {
        int i;
        struct eapol_auth_config conf;
        struct eapol_auth_cb cb;
 
+       dl_list_init(&hapd->erp_keys);
+
        os_memset(&conf, 0, sizeof(conf));
        conf.ctx = hapd;
        conf.eap_reauth_period = hapd->conf->eap_reauth_period;
@@ -2005,6 +2082,7 @@ int ieee802_1x_init(struct hostapd_data *hapd)
        conf.eap_req_id_text_len = hapd->conf->eap_req_id_text_len;
        conf.erp_send_reauth_start = hapd->conf->erp_send_reauth_start;
        conf.erp_domain = hapd->conf->erp_domain;
+       conf.erp = hapd->conf->eap_server_erp;
        conf.pac_opaque_encr_key = hapd->conf->pac_opaque_encr_key;
        conf.eap_fast_a_id = hapd->conf->eap_fast_a_id;
        conf.eap_fast_a_id_len = hapd->conf->eap_fast_a_id_len;
@@ -2037,6 +2115,10 @@ int ieee802_1x_init(struct hostapd_data *hapd)
        cb.abort_auth = _ieee802_1x_abort_auth;
        cb.tx_key = _ieee802_1x_tx_key;
        cb.eapol_event = ieee802_1x_eapol_event;
+#ifdef CONFIG_ERP
+       cb.erp_get_key = ieee802_1x_erp_get_key;
+       cb.erp_add_key = ieee802_1x_erp_add_key;
+#endif /* CONFIG_ERP */
 
        hapd->eapol_auth = eapol_auth_init(&conf, &cb);
        if (hapd->eapol_auth == NULL)
@@ -2070,6 +2152,8 @@ int ieee802_1x_init(struct hostapd_data *hapd)
 
 void ieee802_1x_deinit(struct hostapd_data *hapd)
 {
+       struct eap_server_erp_key *erp;
+
        eloop_cancel_timeout(ieee802_1x_rekey, hapd, NULL);
 
        if (hapd->driver != NULL &&
@@ -2078,6 +2162,12 @@ void ieee802_1x_deinit(struct hostapd_data *hapd)
 
        eapol_auth_deinit(hapd->eapol_auth);
        hapd->eapol_auth = NULL;
+
+       while ((erp = dl_list_first(&hapd->erp_keys, struct eap_server_erp_key,
+                                   list)) != NULL) {
+               dl_list_del(&erp->list);
+               bin_clear_free(erp, sizeof(*erp));
+       }
 }