3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-12-22 13:02:44 +01:00

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.
This commit is contained in:
Denis Kenzior 2023-01-03 09:58:29 -06:00
parent 58d70a8c10
commit eda02fb929
5 changed files with 19 additions and 5 deletions

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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];

View File

@ -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];