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 <j@w1.fi>
This commit is contained in:
Jouni Malinen 2020-06-20 18:07:04 +03:00 committed by Jouni Malinen
parent 5196293926
commit cd99a8c432
3 changed files with 23 additions and 5 deletions

View file

@ -2555,7 +2555,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "eap_teap_auth") == 0) { } else if (os_strcmp(buf, "eap_teap_auth") == 0) {
int val = atoi(pos); int val = atoi(pos);
if (val < 0 || val > 1) { if (val < 0 || val > 2) {
wpa_printf(MSG_ERROR, wpa_printf(MSG_ERROR,
"Line %d: Invalid eap_teap_auth value", "Line %d: Invalid eap_teap_auth value",
line); line);

View file

@ -1229,6 +1229,8 @@ eap_server=0
# EAP-TEAP authentication type # EAP-TEAP authentication type
# 0 = inner EAP (default) # 0 = inner EAP (default)
# 1 = Basic-Password-Auth # 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_auth=0
# EAP-TEAP authentication behavior when using PAC # EAP-TEAP authentication behavior when using PAC

View file

@ -64,7 +64,7 @@ struct eap_teap_data {
struct wpabuf *pending_phase2_resp; struct wpabuf *pending_phase2_resp;
struct wpabuf *server_outer_tlvs; struct wpabuf *server_outer_tlvs;
struct wpabuf *peer_outer_tlvs; struct wpabuf *peer_outer_tlvs;
u8 *identity; /* from PAC-Opaque */ u8 *identity; /* from PAC-Opaque or client certificate */
size_t identity_len; size_t identity_len;
int eap_seq; int eap_seq;
int tnc_started; int tnc_started;
@ -365,7 +365,9 @@ static void * eap_teap_init(struct eap_sm *sm)
data->teap_version = EAP_TEAP_VERSION; data->teap_version = EAP_TEAP_VERSION;
data->state = START; 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."); wpa_printf(MSG_INFO, "EAP-TEAP: Failed to initialize SSL.");
eap_teap_reset(sm, data); eap_teap_reset(sm, data);
return NULL; 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"); 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); data->tls_cs = tls_connection_get_cipher_suite(data->ssl.conn);
wpa_printf(MSG_DEBUG, "EAP-TEAP: TLS cipher suite 0x%04x", wpa_printf(MSG_DEBUG, "EAP-TEAP: TLS cipher suite 0x%04x",
data->tls_cs); data->tls_cs);
@ -1775,9 +1790,10 @@ static int eap_teap_process_phase2_start(struct eap_sm *sm,
next_vendor = EAP_VENDOR_IETF; next_vendor = EAP_VENDOR_IETF;
next_type = EAP_TYPE_NONE; next_type = EAP_TYPE_NONE;
eap_teap_state(data, PHASE2_METHOD); 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, 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; data->skipped_inner_auth = 1;
/* FIX: Need to derive CMK here. However, how is that /* FIX: Need to derive CMK here. However, how is that
* supposed to be done? RFC 7170 does not tell that for * supposed to be done? RFC 7170 does not tell that for