wpa_supplicant AP: Add management frame RX for nl80211
[wpasupplicant] / src / eap_server / eap_fast.c
index b091441..3563908 100644 (file)
@@ -241,12 +241,20 @@ static int eap_fast_session_ticket_cb(void *ctx, const u8 *ticket, size_t len,
        if (os_get_time(&now) < 0 || lifetime <= 0 || now.sec > lifetime) {
                wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Key not valid anymore "
                           "(lifetime=%ld now=%ld)", lifetime, now.sec);
-               os_free(buf);
-               return 0;
-       }
-
-       if (lifetime - now.sec < data->pac_key_refresh_time)
+               data->send_new_pac = 2;
+               /*
+                * Allow PAC to be used to allow a PAC update with some level
+                * of server authentication (i.e., do not fall back to full TLS
+                * handshake since we cannot be sure that the peer would be
+                * able to validate server certificate now). However, reject
+                * the authentication since the PAC was not valid anymore. Peer
+                * can connect again with the newly provisioned PAC after this.
+                */
+       } else if (lifetime - now.sec < data->pac_key_refresh_time) {
+               wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Key soft timeout; send "
+                          "an update if authentication succeeds");
                data->send_new_pac = 1;
+       }
 
        eap_fast_derive_master_secret(pac_key, server_random, client_random,
                                      master_secret);
@@ -346,7 +354,18 @@ static int eap_fast_get_phase2_key(struct eap_sm *sm,
 
        if (key_len > isk_len)
                key_len = isk_len;
-       os_memcpy(isk, key, key_len);
+       if (key_len == 32 &&
+           data->phase2_method->vendor == EAP_VENDOR_IETF &&
+           data->phase2_method->method == EAP_TYPE_MSCHAPV2) {
+               /*
+                * EAP-FAST uses reverse order for MS-MPPE keys when deriving
+                * MSK from EAP-MSCHAPv2. Swap the keys here to get the correct
+                * ISK for EAP-FAST cryptobinding.
+                */
+               os_memcpy(isk, key + 16, 16);
+               os_memcpy(isk + 16, key, 16);
+       } else
+               os_memcpy(isk, key, key_len);
        os_free(key);
 
        return 0;
@@ -923,7 +942,7 @@ static void eap_fast_process_phase2_response(struct eap_sm *sm,
                left = in_len - sizeof(*hdr);
                wpa_hexdump(MSG_DEBUG, "EAP-FAST: Phase2 type Nak'ed; "
                            "allowed types", pos + 1, left - 1);
-#ifdef EAP_TNC
+#ifdef EAP_SERVER_TNC
                if (m && m->vendor == EAP_VENDOR_IETF &&
                    m->method == EAP_TYPE_TNC) {
                        wpa_printf(MSG_DEBUG, "EAP-FAST: Peer Nak'ed required "
@@ -932,7 +951,7 @@ static void eap_fast_process_phase2_response(struct eap_sm *sm,
                        eap_fast_phase2_init(sm, data, next_type);
                        return;
                }
-#endif /* EAP_TNC */
+#endif /* EAP_SERVER_TNC */
                eap_sm_process_nak(sm, pos + 1, left - 1);
                if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
                    sm->user->methods[sm->user_eap_method_index].method !=
@@ -1000,13 +1019,13 @@ static void eap_fast_process_phase2_response(struct eap_sm *sm,
                eap_fast_state(data, CRYPTO_BINDING);
                data->eap_seq++;
                next_type = EAP_TYPE_NONE;
-#ifdef EAP_TNC
+#ifdef EAP_SERVER_TNC
                if (sm->tnc && !data->tnc_started) {
                        wpa_printf(MSG_DEBUG, "EAP-FAST: Initialize TNC");
                        next_type = EAP_TYPE_TNC;
                        data->tnc_started = 1;
                }
-#endif /* EAP_TNC */
+#endif /* EAP_SERVER_TNC */
                break;
        case FAILURE:
                break;
@@ -1218,7 +1237,8 @@ static void eap_fast_process_phase2_tlvs(struct eap_sm *sm,
 
                wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Acknowledgement received "
                           "- PAC provisioning succeeded");
-               eap_fast_state(data, data->anon_provisioning ?
+               eap_fast_state(data, (data->anon_provisioning ||
+                                     data->send_new_pac == 2) ?
                               FAILURE : SUCCESS);
                return;
        }