From cd99a8c432e3261855e5856cd5a605ea95d1b135 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 20 Jun 2020 18:07:04 +0300 Subject: [PATCH] EAP-TEAP (server): Allow Phase 2 skip based on client certificate 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 --- hostapd/config_file.c | 2 +- hostapd/hostapd.conf | 2 ++ src/eap_server/eap_server_teap.c | 24 ++++++++++++++++++++---- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 8f7fcd8b7..1861b5203 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -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); diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 2b0f762e5..060738c34 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -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 diff --git a/src/eap_server/eap_server_teap.c b/src/eap_server/eap_server_teap.c index d7b1b0995..691b44a8d 100644 --- a/src/eap_server/eap_server_teap.c +++ b/src/eap_server/eap_server_teap.c @@ -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