]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
EAP-TEAP (server): Allow Phase 2 skip based on client certificate
authorJouni Malinen <jouni@codeaurora.org>
Sat, 20 Jun 2020 15:07:04 +0000 (18:07 +0300)
committerJouni Malinen <j@w1.fi>
Sat, 20 Jun 2020 15:07:04 +0000 (18:07 +0300)
eap_teap_auth=2 can now be used to configure hostapd to skip Phase 2 if
the peer can be authenticated based on client certificate during Phase
1.

Signed-off-by: Jouni Malinen <j@w1.fi>
hostapd/config_file.c
hostapd/hostapd.conf
src/eap_server/eap_server_teap.c

index 8f7fcd8b762c221e7ea6877dedc38770f8d1ac5a..1861b5203f0f81c5caa5ad9d4552d006476b5e82 100644 (file)
@@ -2555,7 +2555,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
        } else if (os_strcmp(buf, "eap_teap_auth") == 0) {
                int val = atoi(pos);
 
-               if (val < 0 || val > 1) {
+               if (val < 0 || val > 2) {
                        wpa_printf(MSG_ERROR,
                                   "Line %d: Invalid eap_teap_auth value",
                                   line);
index 2b0f762e544e82f5753f93c9e358432189092e77..060738c34acb5a8081660cc0cd0c29b18f382a35 100644 (file)
@@ -1229,6 +1229,8 @@ eap_server=0
 # EAP-TEAP authentication type
 # 0 = inner EAP (default)
 # 1 = Basic-Password-Auth
+# 2 = Do not require Phase 2 authentication if client can be authenticated
+#     during Phase 1
 #eap_teap_auth=0
 
 # EAP-TEAP authentication behavior when using PAC
index d7b1b0995196212f198b013b24c851235ecd2f86..691b44a8d3463d5c93cda2049bb837af15a22d55 100644 (file)
@@ -64,7 +64,7 @@ struct eap_teap_data {
        struct wpabuf *pending_phase2_resp;
        struct wpabuf *server_outer_tlvs;
        struct wpabuf *peer_outer_tlvs;
-       u8 *identity; /* from PAC-Opaque */
+       u8 *identity; /* from PAC-Opaque or client certificate */
        size_t identity_len;
        int eap_seq;
        int tnc_started;
@@ -365,7 +365,9 @@ static void * eap_teap_init(struct eap_sm *sm)
        data->teap_version = EAP_TEAP_VERSION;
        data->state = START;
 
-       if (eap_server_tls_ssl_init(sm, &data->ssl, 0, EAP_TYPE_TEAP)) {
+       if (eap_server_tls_ssl_init(sm, &data->ssl,
+                                   sm->cfg->eap_teap_auth == 2 ? 2 : 0,
+                                   EAP_TYPE_TEAP)) {
                wpa_printf(MSG_INFO, "EAP-TEAP: Failed to initialize SSL.");
                eap_teap_reset(sm, data);
                return NULL;
@@ -502,6 +504,19 @@ static int eap_teap_phase1_done(struct eap_sm *sm, struct eap_teap_data *data)
 
        wpa_printf(MSG_DEBUG, "EAP-TEAP: Phase 1 done, starting Phase 2");
 
+       if (!data->identity && sm->cfg->eap_teap_auth == 2) {
+               const char *subject;
+
+               subject = tls_connection_get_peer_subject(data->ssl.conn);
+               if (subject) {
+                       wpa_printf(MSG_DEBUG,
+                                  "EAP-TEAP: Peer subject from Phase 1 client certificate: '%s'",
+                                  subject);
+                       data->identity = (u8 *) os_strdup(subject);
+                       data->identity_len = os_strlen(subject);
+               }
+       }
+
        data->tls_cs = tls_connection_get_cipher_suite(data->ssl.conn);
        wpa_printf(MSG_DEBUG, "EAP-TEAP: TLS cipher suite 0x%04x",
                   data->tls_cs);
@@ -1775,9 +1790,10 @@ static int eap_teap_process_phase2_start(struct eap_sm *sm,
                        next_vendor = EAP_VENDOR_IETF;
                        next_type = EAP_TYPE_NONE;
                        eap_teap_state(data, PHASE2_METHOD);
-               } else if (sm->cfg->eap_teap_pac_no_inner) {
+               } else if (sm->cfg->eap_teap_pac_no_inner ||
+                       sm->cfg->eap_teap_auth == 2) {
                        wpa_printf(MSG_DEBUG,
-                                  "EAP-TEAP: Used PAC and identity already known - skip inner auth");
+                                  "EAP-TEAP: Used PAC or client certificate and identity already known - skip inner auth");
                        data->skipped_inner_auth = 1;
                        /* FIX: Need to derive CMK here. However, how is that
                         * supposed to be done? RFC 7170 does not tell that for