From eda02fb92987b95fd4d045c7193bd648b8107b0e Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Tue, 3 Jan 2023 09:58:29 -0600 Subject: [PATCH] eap-peap: Fix failures with session resumption The PEAP RFC wants implementations to enforce that Phase2 methods have been successfully completed prior to accepting a successful result TLV. However, when TLS session resumption is used, some servers will skip phase2 methods entirely and simply send a Result TLV with a success code. This results in iwd (erroneously) rejecting the authentication attempt. Fix this by marking phase2 method as successful if session resumption is being used. --- src/eap-peap.c | 12 +++++++++++- src/eap-tls-common.c | 3 ++- src/eap-tls-common.h | 3 ++- src/eap-tls.c | 3 ++- src/eap-ttls.c | 3 ++- 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/eap-peap.c b/src/eap-peap.c index 38ecd6a9..785bfc81 100644 --- a/src/eap-peap.c +++ b/src/eap-peap.c @@ -468,7 +468,8 @@ static void eap_extensions_handle_request(struct eap_state *eap, } static bool eap_peap_tunnel_ready(struct eap_state *eap, - const char *peer_identity) + const char *peer_identity, + bool resumed) { struct peap_state *peap_state = eap_tls_common_get_variant_data(eap); @@ -480,6 +481,15 @@ static bool eap_peap_tunnel_ready(struct eap_state *eap, */ eap_discard_success_and_failure(eap, true); + /* + * In case of a resumed session, the server will typically not run + * phase2 methods at all, but will instead send a result TLV right + * away. Treat this like a successful phase2. In case the server + * does proceed with phase2, the success/failure state will be updated. + */ + if (resumed) + eap_method_success(peap_state->phase2); + /* MSK, EMSK and challenge derivation */ eap_tls_common_tunnel_prf_get_bytes(eap, true, "client EAP encryption", peap_state->key, 128); diff --git a/src/eap-tls-common.c b/src/eap-tls-common.c index 9a4450e9..784a57ee 100644 --- a/src/eap-tls-common.c +++ b/src/eap-tls-common.c @@ -244,6 +244,7 @@ static void eap_tls_tunnel_ready(const char *peer_identity, void *user_data) { struct eap_state *eap = user_data; struct eap_tls_state *eap_tls = eap_get_data(eap); + bool resumed = l_tls_get_session_resumed(eap_tls->tunnel); if (eap_tls->ca_cert && !peer_identity) { l_error("%s: TLS did not verify AP identity", @@ -264,7 +265,7 @@ static void eap_tls_tunnel_ready(const char *peer_identity, void *user_data) if (!eap_tls->variant_ops->tunnel_ready) return; - if (!eap_tls->variant_ops->tunnel_ready(eap, peer_identity)) + if (!eap_tls->variant_ops->tunnel_ready(eap, peer_identity, resumed)) l_tls_close(eap_tls->tunnel); } diff --git a/src/eap-tls-common.h b/src/eap-tls-common.h index 25f668e2..bfc23c08 100644 --- a/src/eap-tls-common.h +++ b/src/eap-tls-common.h @@ -33,7 +33,8 @@ enum eap_tls_version { struct eap_tls_variant_ops { enum eap_tls_version version_max_supported; - bool (*tunnel_ready)(struct eap_state *eap, const char *peer_identity); + bool (*tunnel_ready)(struct eap_state *eap, const char *peer_identity, + bool resumed); bool (*tunnel_handle_request)(struct eap_state *eap, const uint8_t *data, size_t data_len); void (*reset)(void *variant_data); diff --git a/src/eap-tls.c b/src/eap-tls.c index ecea94d9..56fdc67f 100644 --- a/src/eap-tls.c +++ b/src/eap-tls.c @@ -35,7 +35,8 @@ #include "src/eap-tls-common.h" static bool eap_tls_tunnel_ready(struct eap_state *eap, - const char *peer_identity) + const char *peer_identity, + bool resumed) { uint8_t msk_emsk[128]; uint8_t iv[64]; diff --git a/src/eap-ttls.c b/src/eap-ttls.c index 672a47c6..43a6c118 100644 --- a/src/eap-ttls.c +++ b/src/eap-ttls.c @@ -902,7 +902,8 @@ static const struct phase2_method_ops phase2_eap_ops = { }; static bool eap_ttls_tunnel_ready(struct eap_state *eap, - const char *peer_identity) + const char *peer_identity, + bool resumed) { struct phase2_method *phase2 = eap_tls_common_get_variant_data(eap); uint8_t msk_emsk[128];