[wpa_supplicant] Cumulative patch from 9fde14607
Changes include required updates to DPP R2.
Bug: 143479699
Test: Device boots up and connects to WPA3/OWE wifi networks, run traffic.
Test: Able to turn on/off softap, associate wifi STA, run traffic.
Test: Regression test Passed (Bug: 143485775)
9fde14607 Allow scans triggered by D-Bus to use MAC address randomization
10f8351d6 D-Bus: Add MAC address randomization endpoints
bb66d4675 Move ownership of MAC address randomization mask to scan params
6c2f70cc6 DPP: Mention ssid and pass parameters for DPP_AUTH_INIT in documentation
1030dec1f JSON: Fix escaping of characters that have MSB=1 with signed char
7800725af dbus: Export OWE capability and OWE BSS key_mgmt
b2ad4e6b2 D-Bus: Fix P2P NULL dereference after interface removal
937644aa2 nl80211: Indicate SUITE_B_192 capa only when CCMP-256/GCMP-256 supported
1b5865a53 SAE: Ignore commit message when waiting for confirm in STA mode
50a2c8c90 Do not indicate possible PSK failure when using SAE
df3b2e22a nl80211: Add STA node details in AP through QCA vendor subcommand
f273b2a5c Add QCA vendor cmd for setting BT coex chain mode
4dc860680 Extend QCA OEM data vendor subcmd to allow use as an event
93a1e275a SAE: Determine H2E vs. looping when restarting SAE auth in AP mode
de580bf6c crypto: Remove unused crypto_bignum_sqrtmod()
9b292a48f SAE: Drop sqrt() alternative from SSWU (H2E)
305369038 wpa_supplicant: Fix arithmetic on void pointer
00ddc1cc2 common: Fix same expression checked twice in fils_key_auth_sk()
327d09aa0 HE: Add 11ax info to ap mode ctrl iface STATUS command
d7678a084 Fix AP Extended Capability length determination
a592f2a9e P2P: Continue listening next request if no post-PD operations
a32acf391 Fix hostapd build with CONFIG_WPA_TRACE but no CONFIG_WPA_TRACE_BFD
b38c8c9cb dbus: Suppress to show NULL string
6807eee9c Interworking: Check NULL string to avoid compiler warning
ec1c0d154 Fix name of DBus interface in defconfig
f73dd0a69 FT-SAE: Add RSNXE into FT MIC
cb9925977 Add RSNXE into (Re)Association Response frames
865721c69 Merge wpa_supplicant and hostapd EAPOL-Key KDE parsers
898b6d58f SAE: Verify that STA negotiated H2E if it claims to support it
74866f537 RSN: Verify RSNXE match between (Re)AssocReq and EAPOL-Key msg 2/4
9981d5bf3 Add RSNXE into AP KDE parser
d3516cad7 Store a copy of Association Request RSNXE in AP mode for later use
6d6c88775 SAE: Add RSNXE in Association Request and EAPOL-Key msg 2/4
8401cdc8d Add RSNXE into IE parser
0b0ed907d WPS: Check SHA256 result success
8dda97c75 QCA vendor command for adding a STA node
b41dc61af Add a new QCA vendor attribute to carry device info for OEM data
bf185bfd5 QCA vendor attributes to indicate BW-based agile spectral capability
1317ea2c0 nl80211: Allow external auth based on SAE/FT-SAE key mgmt
cdb5774f4 FST: Update FST about MAC address change
49e95ee1e AP: Publish only HE capabilities and operation IEs on 6 GHz band
d7c2c5c98 AP: Add initial support for 6 GHz band
a5b2faa71 AP: Add op_class config item to specify 6 GHz channels uniquely
89450024a wpa_supplicant: Pass in operating class for channel validity checks
032c8264d SAE: Check that peer's rejected groups are not enabled in AP
a5dc2a5c1 SAE: H2E version of SAE commit message handling for AP
43b20b437 SAE: Derive H2E PT in AP when starting the AP
444d76f74 SAE: Check that peer's rejected groups are not enabled
cfe1ea5c9 SAE: H2E version of SAE commit message handling for STA
447cd5f2d SAE: Collect list of rejected groups for H2E in STA
05a2fb0d1 SAE: Derive H2E PT in STA before connection
146889e3c RSN: Verify RSNXE match between Beacon/ProbeResp and EAPOL-Key msg 3/4
3134bb13a SAE: Advertise Extended RSN Capabilities when H2E is enabled
293a01f3b SAE: Handle BSS membership selector indication for H2E-only in STA mode
cc0da0ff4 SAE: Advertise BSS membership selector for H2E-only case
85e64e634 SAE: Add sae_pwe configuration parameter for wpa_supplicant
a36e13a7c SAE: Add sae_pwe configuration parameter for hostapd
af4487148 tests: Module test for SAE hash-to-element crypto routines
cf84246eb SAE: Add Rejected Groups element into H2E Commit
efd428529 SAE: Hash algorithm selection for H2E KCK/CN()
aeb022f8e SAE: Implement hash-to-element PT/PWE crypto routines
ecd711407 SAE: Parse Rejected Groups element from H2E SAE commit
86f608486 SAE: Tell sae_parse_commit() whether H2E is used
316156739 SAE: H2E protocol defines
1766e608b wolfSSL: Fix crypto_bignum_sub()
2a1c84f4e crypto: Add more bignum/EC helper functions
9c08bfbd9 DPP: Fix confusing debug entry from Configurator
f7fe05522 SAE: Allow AP behavior for SAE Confirm to be configured
d6a7de60c wpa_cli: Clean up unnecessarily complex CONFIG_MESH use
8b426ab1e wpa_supplicant: Pass AP mode EDMG config to hostapd struct
a82aee1f4 wpa_supplicant: Add support for EDMG channels
35aed771f Indicate EDMG in scan results
f6f8c6ade AP: Show EDMG channel info in STATUS output
241dd76cf hostapd: Check EDMG configuration against capability
dc3457cc4 hostapd: Check usability of EDMG channel
bebd91e9c Add EDMG parameters to set_freq functions
fdd0fef2c EDMG: Helper functions for parameter encoding/checking
e8ff22f47 wpa_supplicant: Add EDMG channel configuration parameters
5c5ff22ef hostapd: Add EDMG channel configuration parameters
dda5d9e31 nl80211: Add support for EDMG channels
a19913c17 IEEE P802.11ay/D4.0 defines for EDMG
c34917403 MBO/OCE: Update disable_mbo_oce flag after association
b719a1568 DPP2: Parse AKM suite selector version of akm node
68fea9603 DPP2: Allow Configurator to use AKM suite selectors in Config Object
52d469de1 DPP2: Support multiple Config Objects in Enrollee
7eb06a336 DPP2: Allow multiple Config Objects to be build on Configurator
99918e069 DPP: Cleaned up netrole indication for config object building
e0d22c842 FILS+FT: Fix MFPR flag in RSNE during FILS exchange for FT
d0a4ed6a1 Allow SAE to be used in wpa_supplicant AP mode
7846e8d60 NetBSD: Fix compile
2e06cef80 MBO/OCE: Work around misbehaving MBO/OCE APs that use RSN without PMF
722c7d195 wlantest: Process VLAN tagged Data frames
83b83b461 nl80211: Migrate to current netlink key message format
7a4b01c87 AP: Provide correct keyid to wpa_send_eapol() for EAPOL-Key msg 3/4
a3ebf7175 BSD: Add support for route(4) message filtering
d9286d099 ACS: Stop before scan if no channels in chanlist are available
f32aa244e DPP: Debug print configRequest bandSupport on Configurator
8f8c423a5 DPP: Add bandSupport JSON array into config request
6d3dc9ba1 mka: Check OLPN for exhaustion on SAKuse decode
84851007d mka: Check OLPN for exhaustion on SAKuse encode
547ba732d mka: Clear out old/latest key values on CHANGE in CP state machine
536a7cfcf mka: Don't set newSAK to FALSE on ABANDON in CP state machine
0fedfba2e mka: Change RECEIVE and RETIRE states to match the standard
3f2641e7a Fix wpa_supplicant build with CONFIG_PCSC=y
5a5639b06 DPP: Allow name and mudurl to be configured for Config Request
3394def5a More consistent SA check for unexpected Data frames
16ef233bf DPP2: Connection status result (Enrollee)
b10e01a79 DPP2: Connection status result (Configurator)
e501a2eb5 DPP2: Connection status result defines
cc8399528 DPP2: Move dpp_build_conf_result() to be within ifdef block
3a6736fe8 DPP2: Fix a memory leak on error path for Config Result
21dc1627f wpa_supplicant: Don't return an error when successfully parsing WMM rules
8214b45ba P2P: Use latest BSS entry if multiple P2P Device Addr matches found
dc6c3be4e wpa_supplicant: Add support for 60 GHz band channels 5 and 6
018edec9b Remove IAPP functionality from hostapd
d86d66dc0 AP: Silently ignore management frame from unexpected source address
a84bf4438 HE: Send the AP's OBSS PD settings to the kernel
262b71eea Sync with mac80211-next.git include/uapi/linux/nl80211.h
8788a314d WPS: Update MAC address on address changes
39042d7f7 os_sleep: Use nanosleep for POSIX versions 2008 and higher
a69742c2f wpa_cli: Do not pick p2p-dev-* interfaces by default
d842e00bd SAE: Return result from confirm CN() operation to the caller
a8bfc6fff FILS: Update connect params after sending connection notification
0df82a3da Correct the type/usage of QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST
6bf6c6fec DPP: Fix hostapd build dependencies for DPP-only build
1eff2e7bf DPP2: Fix wpa_supplicant build dependencies for CONFIG_AP=y build
d2bae5763 DPP: Fix wpa_supplicant build dependencies for DPP-only build
7d2ed8bae Remove CONFIG_IEEE80211W build parameter
022926187 DFS offload: Fix hostapd state and CAC info in STATUS output
4d78ba990 EAP-TEAP peer: Clear Phase 2 EAP method on new Identity exchange
681618246 EAP-TEAP peer: Add support for machine credentials using certificates
ebee8232d Do not try to include net/ethernet.h in MinGW/Windows builds
bf15b1559 Fix Windows error code definition workaround
043de65f1 EAP peer config: Move ocsp param to phase1/phase2
8d76e0ad7 EAP server: Configurable maximum number of authentication message rounds
b99c4cadb EAP peer: Move certificate configuration params into shared struct
6e711e7ab mesh: Do not enable HE on 5 GHz without VHT
0497e4148 HE: Fix HE Capabilities element size
a2e0cc9e0 Add nl80211 vendor ACS trigger reasons related to interference
69e8e7817 HS 2.0: Do not add two copies of OSEN element into Beacon/Probe Resp
a762ba8b1 HS 2.0 AP: Do not mandate PMF for HS 2.0 Indication in open OSU network
e49ce2990 IEEE 802.1X authenticator: Coding style cleanup
31aaddc90 Clean up IEEE 802.1X authentication debug messages for EAP code
71419119f EAP-TEAP peer: Fix protected indication of inner EAP method failure
93cd29d2b EAP-TEAP server: Add support for requiring user and machine credentials
c38c62ff7 wlantest: Derive PMK-R1 and PTK for FT protocol cases
c41936566 EAP-TEAP peer: Add support for machine authentication
c724a0a16 EAP peer: Add a concept of a separate machine credential
9ce3bfaf4 RADIUS server: Abort startup on allocation failures
fa1f0751c RADIUS server: Use struct eap_config to avoid duplicated definitions
a00cb1b1f EAP-TEAP server: Fix eap_teap_pac_no_inner configuration
986033ff3 EAP-TEAP server: Fix Crypto-Binding check in PAC no-inner-auth case
e54cfbb56 EAP-TEAP server: Allow a specific Identity-Type to be requested/required
f186ec54c EAP-TEAP peer: Support Identity-Type TLV
cc661c160 EAP-TEAP: Add parsing and generation routines for Identity-Type TLV
100b2edb2 OpenSSL: Write peer certificate chain details in debug log
7eb157f1e EAP: Increase the maximum number of message exchanges
822e7c66a EAP server: Use struct eap_config to avoid duplicated definitions
62af2b18f EAP-TEAP peer: Support vendor EAP method in Phase 2
aba8dc82f EAP-PEAP server: Support vendor EAP types in Phase 2
357c1062d EAP-FAST peer: Support vendor EAP method in Phase 2
f32f76231 EAP-FAST server: Support vendor EAP types in Phase 2
887d8703b EAP-PEAP peer: Support vendor EAP method in Phase 2
f2ef4f255 EAP peer: Allow VENDOR-TEST method in Phase 2
5ddbd9e96 EAP-TTLS peer: Support vendor EAP method in Phase 2
5e94e7f23 EAP-TTLS server: Support vendor EAP types in Phase 2
5f2301a6d Replace EapType typedef with enum eap_type
76ddfae6e EAP-TEAP server: Testing mechanism for Result TLV in a separate message
4c327146f EAP-TEAP peer: Allow Result TLV without Crypto-Binding TLV
128d46be9 EAP-TEAP: Add parsing of Error TLV
234489efd EAP-TEAP server: Require Intermediate-Result TLV even with Result TLV
0f7c91f2b EAP-TEAP peer: Add Intermediate-Result TLV with Crypto-Binding TLV
a66e53c41 EAP-TEAP: Fix TLS-PRF for TLS ciphersuites that use SHA384
52069c7ef Add TLS-PRF using HMAC with P_SHA384 for TEAP
a647a0ad7 Extend server certificate TOD policy reporting to include TOD-TOFU
346d10cf8 SAE: Conditionally set PMKID while notifying the external auth status
b7cd64876 SAE: Use BSSID stored in ext_auth_bssid for set_pmk
e0b331d89 OWE: Update connect params with new DH attributes to the driver
c574a3ff1 nl80211: Request update connection params only for drivers with SME
528f263c4 FT: Reject over-the-DS response with MFPC=0 if PMF is required
ae05b6a21 RSN: Do not allow connection to proceed without MFPC=1 if PMF required
ded56f2fa FT: Fix MFPR flag in RSNE during FT protocol
0028d627c OCE: Mandate PMF for WPA2 association with OCE AP
84ebc759a HS 2.0: Match credentials based on required_roaming_consortium
d2b208384 SAE: Allow PMKID to be added into Association Request frame following SAE
2ca23faf1 Make wpa_insert_pmkid() more generic
05822609d HE: MCS size is always a minimum of 4 bytes
df4f95998 nl80211: Don't force VHT channel definition with HE
dd0153fce Check for LEAP before doing FT
6126e5f97 Fix a typo in hostapd config documentation
698a0067c Fix check_crl_strict documentation
485dd425b Add QCA vendor command for avoid frequency feature
6ae1247bf Update QCA vendor attributes for 6 GHz band support
aa23ece3d Add QCA vendor channel attribute to restart AP
85508ecf6 Add QCA vendor command to configure ACS policy
2395fdb67 Add QCA vendor attributes to enhance roaming configuration
1425caac2 Rename qca_wlan_vendor_attr_roam_subcmd to represent subcmds
f13119631 Document the attributes used by QCA_NL80211_VENDOR_SUBCMD_ROAM
b0b25c5bb Clear external eapSuccess setting in driver-authorized cases
fa1d5ec18 The master branch is now used for v2.10 development
ca8c2bd28 Preparations for v2.8 release
3263fca28 Set the default scan IEs on interface restart
d776bf8c6 EAP-TEAP peer: Fix fragmentation of final message
1c7e61a35 wolfssl: Avoid void pointer arithmetic
7122a02fa SAE: Fix order_len for FFC groups
422e73d62 DPP: Indicate authentication success on ConfReqRX if needed
d001fe31a OpenSSL: Handle EVP_PKEY_derive() secret_len changes for ECDH
29ef1c5ee DPP: Use a common helper function for ECDH operations
ac734a342 SAE: Fix KCK, PMK, and PMKID derivation for groups 22, 23, 24
c65168ccd OpenSSL: Fix crypto_bignum_to_bin() with padlen == 0
cb28bd52e nl80211: Use separate flag for 4-way handshake offload
6bb11c7a4 EAP-SIM/AKA server: Allow pseudonym/fast reauth to be disabled
c1b236521 EAP-SIM/AKA: Do not allow anonymous@realm "pseudonym" to be cleared
cc2fd9425 D-Bus: Demote timeout/flush messages to MSG_MSGDUMP
3b726df82 nl80211: Missing sysctl flags aren't fatal
f4111ff3d Extra RADIUS request attributes from SQLite
74707def8 Move hostapd_parse_radius_attr() into ap_config.c
1e5ea68d1 mka: Accept last two used MNs in Peers List of a received MKPDU
013686403 P2P: Pass HE flag to GO negotiation result
876c5eaa6 dragonfly: Disable use of groups using Brainpool curves
968520da8 nl80211: Add WMM parameters while updating TDLS peer entry
5a511924b wpa_cli: Add support to process DPP action events in action script
64e37be94 Avoid nested enum wpas_mode declaration to allow C++ compilation
fe2e1edf4 EAP-SIM server: Avoid void pointer arithmetic
cfc9ebea0 EAP-AKA server: Avoid void pointer arithmetic
bd0414043 trace: Avoid void pointer arithmetic
fc03ea2c1 DPP: Avoid void pointer arithmetic
d1b1f9fa9 Report WPA/RSN protocol and AKM suite selector in STA MIB
43aafef8d Add missed wpa_akm_to_suite() selectors
bfb6a482f dragonfly: SAE/EAP-pwd min PWE derivation iteration count to shared code
226da33d7 EAP-pwd peer: Configurable set of groups with reduced default
6a4406c01 Add QCA vendor attributes for ELNA bypass
176c133e9 Add a vendor attribute to configure disconnect IEs
123895228 Add QCA vendor command to support OEM data
Change-Id: Iaa497edcda7c5dcdad19db9d09ab09ef74e508bd
diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c
index ac15e0e..c78b214 100644
--- a/src/eap_peer/eap.c
+++ b/src/eap_peer/eap.c
@@ -1,6 +1,6 @@
/*
* EAP peer state machines (RFC 4137)
- * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -32,12 +32,13 @@
#define STATE_MACHINE_DATA struct eap_sm
#define STATE_MACHINE_DEBUG_PREFIX "EAP"
-#define EAP_MAX_AUTH_ROUNDS 50
+#define EAP_MAX_AUTH_ROUNDS 100
+#define EAP_MAX_AUTH_ROUNDS_SHORT 50
#define EAP_CLIENT_TIMEOUT_DEFAULT 60
static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,
- EapType method);
+ enum eap_type method);
static struct wpabuf * eap_sm_buildNak(struct eap_sm *sm, int id);
static void eap_sm_processIdentity(struct eap_sm *sm,
const struct wpabuf *req);
@@ -260,10 +261,12 @@
*/
sm->ignore = 0;
sm->num_rounds = 0;
+ sm->num_rounds_short = 0;
sm->prev_failure = 0;
sm->expected_failure = 0;
sm->reauthInit = FALSE;
sm->erp_seq = (u32) -1;
+ sm->use_machine_cred = 0;
}
@@ -276,6 +279,7 @@
{
SM_ENTRY(EAP, DISABLED);
sm->num_rounds = 0;
+ sm->num_rounds_short = 0;
/*
* RFC 4137 does not describe clearing of idleWhile here, but doing so
* allows the timer tick to be stopped more quickly when EAP is not in
@@ -309,6 +313,10 @@
/* parse rxReq, rxSuccess, rxFailure, reqId, reqMethod */
eap_sm_parseEapReq(sm, eapReqData);
sm->num_rounds++;
+ if (!eapReqData || wpabuf_len(eapReqData) < 20)
+ sm->num_rounds_short++;
+ else
+ sm->num_rounds_short = 0;
}
@@ -319,7 +327,7 @@
SM_STATE(EAP, GET_METHOD)
{
int reinit;
- EapType method;
+ enum eap_type method;
const struct eap_method *eap_method;
SM_ENTRY(EAP, GET_METHOD);
@@ -815,7 +823,8 @@
wpa_printf(MSG_DEBUG, "EAP: Valid ERP key found %s (SEQ=%u)",
erp->keyname_nai, erp->next_seq);
- msg = eap_msg_alloc(EAP_VENDOR_IETF, (EapType) EAP_ERP_TYPE_REAUTH,
+ msg = eap_msg_alloc(EAP_VENDOR_IETF,
+ (enum eap_type) EAP_ERP_TYPE_REAUTH,
1 + 2 + 2 + os_strlen(erp->keyname_nai) + 1 + 16,
EAP_CODE_INITIATE, eap_id);
if (msg == NULL)
@@ -949,6 +958,8 @@
SM_ENTRY(EAP, SEND_RESPONSE);
wpabuf_free(sm->lastRespData);
if (sm->eapRespData) {
+ if (wpabuf_len(sm->eapRespData) >= 20)
+ sm->num_rounds_short = 0;
if (sm->workaround)
os_memcpy(sm->last_sha1, sm->req_sha1, 20);
sm->lastId = sm->reqId;
@@ -1341,6 +1352,14 @@
sm->num_rounds++;
SM_ENTER_GLOBAL(EAP, FAILURE);
}
+ } else if (sm->num_rounds_short > EAP_MAX_AUTH_ROUNDS_SHORT) {
+ if (sm->num_rounds_short == EAP_MAX_AUTH_ROUNDS_SHORT + 1) {
+ wpa_msg(sm->msg_ctx, MSG_INFO,
+ "EAP: more than %d authentication rounds (short) - abort",
+ EAP_MAX_AUTH_ROUNDS_SHORT);
+ sm->num_rounds_short++;
+ SM_ENTER_GLOBAL(EAP, FAILURE);
+ }
} else {
/* Local transitions */
eap_peer_sm_step_local(sm);
@@ -1349,7 +1368,7 @@
static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,
- EapType method)
+ enum eap_type method)
{
if (!eap_allowed_method(sm, vendor, method)) {
wpa_printf(MSG_DEBUG, "EAP: configuration does not allow: "
@@ -1595,13 +1614,13 @@
static int eap_sm_set_scard_pin(struct eap_sm *sm,
struct eap_peer_config *conf)
{
- if (scard_set_pin(sm->scard_ctx, conf->pin)) {
+ if (scard_set_pin(sm->scard_ctx, conf->cert.pin)) {
/*
* Make sure the same PIN is not tried again in order to avoid
* blocking SIM.
*/
- os_free(conf->pin);
- conf->pin = NULL;
+ os_free(conf->cert.pin);
+ conf->cert.pin = NULL;
wpa_printf(MSG_WARNING, "PIN validation failed");
eap_sm_request_pin(sm);
@@ -1657,6 +1676,11 @@
identity_len = config->anonymous_identity_len;
wpa_hexdump_ascii(MSG_DEBUG, "EAP: using anonymous identity",
identity, identity_len);
+ } else if (sm->use_machine_cred) {
+ identity = config->machine_identity;
+ identity_len = config->machine_identity_len;
+ wpa_hexdump_ascii(MSG_DEBUG, "EAP: using machine identity",
+ identity, identity_len);
} else {
identity = config->identity;
identity_len = config->identity_len;
@@ -2600,6 +2624,8 @@
static int eap_allowed_phase2_type(int vendor, int type)
{
+ if (vendor == EAP_VENDOR_HOSTAP)
+ return 1;
if (vendor != EAP_VENDOR_IETF)
return 0;
return type != EAP_TYPE_PEAP && type != EAP_TYPE_TTLS &&
@@ -2662,7 +2688,7 @@
if (eap_allowed_phase2_type(vendor, method)) {
if (vendor == EAP_VENDOR_IETF &&
method == EAP_TYPE_TLS && config &&
- config->private_key2 == NULL)
+ !config->phase2_cert.private_key)
continue;
buf[*count].vendor = vendor;
buf[*count].method = method;
@@ -2721,8 +2747,15 @@
const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len)
{
struct eap_peer_config *config = eap_get_config(sm);
- if (config == NULL)
+
+ if (!config)
return NULL;
+
+ if (sm->use_machine_cred) {
+ *len = config->machine_identity_len;
+ return config->machine_identity;
+ }
+
*len = config->identity_len;
return config->identity;
}
@@ -2732,14 +2765,24 @@
struct eap_peer_config *config)
{
char *name;
+ const u8 *password;
+ size_t password_len;
- if (config->password == NULL)
+ if (sm->use_machine_cred) {
+ password = config->machine_password;
+ password_len = config->machine_password_len;
+ } else {
+ password = config->password;
+ password_len = config->password_len;
+ }
+
+ if (!password)
return -1;
- name = os_zalloc(config->password_len + 1);
- if (name == NULL)
+ name = os_zalloc(password_len + 1);
+ if (!name)
return -1;
- os_memcpy(name, config->password, config->password_len);
+ os_memcpy(name, password, password_len);
ext_password_free(sm->ext_pw_buf);
sm->ext_pw_buf = ext_password_get(sm->ext_pw, name);
@@ -2758,16 +2801,25 @@
const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len)
{
struct eap_peer_config *config = eap_get_config(sm);
- if (config == NULL)
+
+ if (!config)
return NULL;
- if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
+ if ((sm->use_machine_cred &&
+ (config->flags & EAP_CONFIG_FLAGS_EXT_MACHINE_PASSWORD)) ||
+ (!sm->use_machine_cred &&
+ (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD))) {
if (eap_get_ext_password(sm, config) < 0)
return NULL;
*len = wpabuf_len(sm->ext_pw_buf);
return wpabuf_head(sm->ext_pw_buf);
}
+ if (sm->use_machine_cred) {
+ *len = config->machine_password_len;
+ return config->machine_password;
+ }
+
*len = config->password_len;
return config->password;
}
@@ -2785,10 +2837,14 @@
const u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash)
{
struct eap_peer_config *config = eap_get_config(sm);
- if (config == NULL)
+
+ if (!config)
return NULL;
- if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
+ if ((sm->use_machine_cred &&
+ (config->flags & EAP_CONFIG_FLAGS_EXT_MACHINE_PASSWORD)) ||
+ (!sm->use_machine_cred &&
+ (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD))) {
if (eap_get_ext_password(sm, config) < 0)
return NULL;
if (hash)
@@ -2797,6 +2853,14 @@
return wpabuf_head(sm->ext_pw_buf);
}
+ if (sm->use_machine_cred) {
+ *len = config->machine_password_len;
+ if (hash)
+ *hash = !!(config->flags &
+ EAP_CONFIG_FLAGS_MACHINE_PASSWORD_NTHASH);
+ return config->machine_password;
+ }
+
*len = config->password_len;
if (hash)
*hash = !!(config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH);
diff --git a/src/eap_peer/eap_config.h b/src/eap_peer/eap_config.h
index 148c906..3238f74 100644
--- a/src/eap_peer/eap_config.h
+++ b/src/eap_peer/eap_config.h
@@ -1,6 +1,6 @@
/*
* EAP peer configuration data
- * Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -10,68 +10,9 @@
#define EAP_CONFIG_H
/**
- * struct eap_peer_config - EAP peer configuration/credentials
+ * struct eap_peer_cert_config - EAP peer certificate configuration/credential
*/
-struct eap_peer_config {
- /**
- * identity - EAP Identity
- *
- * This field is used to set the real user identity or NAI (for
- * EAP-PSK/PAX/SAKE/GPSK).
- */
- u8 *identity;
-
- /**
- * identity_len - EAP Identity length
- */
- size_t identity_len;
-
- /**
- * anonymous_identity - Anonymous EAP Identity
- *
- * This field is used for unencrypted use with EAP types that support
- * different tunnelled identity, e.g., EAP-TTLS, in order to reveal the
- * real identity (identity field) only to the authentication server.
- *
- * If not set, the identity field will be used for both unencrypted and
- * protected fields.
- *
- * This field can also be used with EAP-SIM/AKA/AKA' to store the
- * pseudonym identity.
- */
- u8 *anonymous_identity;
-
- /**
- * anonymous_identity_len - Length of anonymous_identity
- */
- size_t anonymous_identity_len;
-
- u8 *imsi_identity;
- size_t imsi_identity_len;
-
- /**
- * password - Password string for EAP
- *
- * This field can include either the plaintext password (default
- * option) or a NtPasswordHash (16-byte MD4 hash of the unicode
- * presentation of the password) if flags field has
- * EAP_CONFIG_FLAGS_PASSWORD_NTHASH bit set to 1. NtPasswordHash can
- * only be used with authentication mechanism that use this hash as the
- * starting point for operation: MSCHAP and MSCHAPv2 (EAP-MSCHAPv2,
- * EAP-TTLS/MSCHAPv2, EAP-TTLS/MSCHAP, LEAP).
- *
- * In addition, this field is used to configure a pre-shared key for
- * EAP-PSK/PAX/SAKE/GPSK. The length of the PSK must be 16 for EAP-PSK
- * and EAP-PAX and 32 for EAP-SAKE. EAP-GPSK can use a variable length
- * PSK.
- */
- u8 *password;
-
- /**
- * password_len - Length of password field
- */
- size_t password_len;
-
+struct eap_peer_cert_config {
/**
* ca_cert - File path to CA certificate file (PEM/DER)
*
@@ -231,14 +172,6 @@
char *check_cert_subject;
/**
- * check_cert_subject2 - Constraint for server certificate subject fields
- *
- * This field is like check_cert_subject, but used for phase 2 (inside
- * EAP-TTLS/PEAP/FAST tunnel) authentication.
- */
- char *check_cert_subject2;
-
- /**
* altsubject_match - Constraint for server certificate alt. subject
*
* Semicolon separated string of entries to be matched against the
@@ -299,115 +232,181 @@
char *domain_match;
/**
- * ca_cert2 - File path to CA certificate file (PEM/DER) (Phase 2)
+ * pin - PIN for USIM, GSM SIM, and smartcards
*
- * This file can have one or more trusted CA certificates. If ca_cert2
- * and ca_path2 are not included, server certificate will not be
- * verified. This is insecure and a trusted CA certificate should
- * always be configured. Full path to the file should be used since
- * working directory may change when wpa_supplicant is run in the
- * background.
+ * This field is used to configure PIN for SIM and smartcards for
+ * EAP-SIM and EAP-AKA. In addition, this is used with EAP-TLS if a
+ * smartcard is used for private key operations.
*
- * This field is like ca_cert, but used for phase 2 (inside
- * EAP-TTLS/PEAP/FAST tunnel) authentication.
- *
- * Alternatively, a named configuration blob can be used by setting
- * this to blob://blob_name.
+ * If left out, this will be asked through control interface.
*/
- char *ca_cert2;
+ char *pin;
/**
- * ca_path2 - Directory path for CA certificate files (PEM) (Phase 2)
+ * engine - Enable OpenSSL engine (e.g., for smartcard access)
*
- * This path may contain multiple CA certificates in OpenSSL format.
- * Common use for this is to point to system trusted CA list which is
- * often installed into directory like /etc/ssl/certs. If configured,
- * these certificates are added to the list of trusted CAs. ca_cert
- * may also be included in that case, but it is not required.
- *
- * This field is like ca_path, but used for phase 2 (inside
- * EAP-TTLS/PEAP/FAST tunnel) authentication.
+ * This is used if private key operations for EAP-TLS are performed
+ * using a smartcard.
*/
- char *ca_path2;
+ int engine;
/**
- * client_cert2 - File path to client certificate file
+ * engine_id - Engine ID for OpenSSL engine
*
- * This field is like client_cert, but used for phase 2 (inside
- * EAP-TTLS/PEAP/FAST tunnel) authentication. Full path to the
- * file should be used since working directory may change when
- * wpa_supplicant is run in the background.
+ * "opensc" to select OpenSC engine or "pkcs11" to select PKCS#11
+ * engine.
*
- * Alternatively, a named configuration blob can be used by setting
- * this to blob://blob_name.
+ * This is used if private key operations for EAP-TLS are performed
+ * using a smartcard.
*/
- char *client_cert2;
+ char *engine_id;
+
/**
- * private_key2 - File path to client private key file
+ * key_id - Key ID for OpenSSL engine
*
- * This field is like private_key, but used for phase 2 (inside
- * EAP-TTLS/PEAP/FAST tunnel) authentication. Full path to the
- * file should be used since working directory may change when
- * wpa_supplicant is run in the background.
- *
- * Alternatively, a named configuration blob can be used by setting
- * this to blob://blob_name.
+ * This is used if private key operations for EAP-TLS are performed
+ * using a smartcard.
*/
- char *private_key2;
+ char *key_id;
/**
- * private_key2_passwd - Password for private key file
+ * cert_id - Cert ID for OpenSSL engine
*
- * This field is like private_key_passwd, but used for phase 2 (inside
- * EAP-TTLS/PEAP/FAST tunnel) authentication.
+ * This is used if the certificate operations for EAP-TLS are performed
+ * using a smartcard.
*/
- char *private_key2_passwd;
+ char *cert_id;
/**
- * dh_file2 - File path to DH/DSA parameters file (in PEM format)
+ * ca_cert_id - CA Cert ID for OpenSSL engine
*
- * This field is like dh_file, but used for phase 2 (inside
- * EAP-TTLS/PEAP/FAST tunnel) authentication. Full path to the
- * file should be used since working directory may change when
- * wpa_supplicant is run in the background.
- *
- * Alternatively, a named configuration blob can be used by setting
- * this to blob://blob_name.
+ * This is used if the CA certificate for EAP-TLS is on a smartcard.
*/
- char *dh_file2;
+ char *ca_cert_id;
/**
- * subject_match2 - Constraint for server certificate subject
+ * ocsp - Whether to use/require OCSP to check server certificate
*
- * This field is like subject_match, but used for phase 2 (inside
- * EAP-TTLS/PEAP/FAST tunnel) authentication.
+ * 0 = do not use OCSP stapling (TLS certificate status extension)
+ * 1 = try to use OCSP stapling, but not require response
+ * 2 = require valid OCSP stapling response
*/
- char *subject_match2;
+ int ocsp;
+};
+
+/**
+ * struct eap_peer_config - EAP peer configuration/credentials
+ */
+struct eap_peer_config {
+ /**
+ * identity - EAP Identity
+ *
+ * This field is used to set the real user identity or NAI (for
+ * EAP-PSK/PAX/SAKE/GPSK).
+ */
+ u8 *identity;
/**
- * altsubject_match2 - Constraint for server certificate alt. subject
- *
- * This field is like altsubject_match, but used for phase 2 (inside
- * EAP-TTLS/PEAP/FAST tunnel) authentication.
+ * identity_len - EAP Identity length
*/
- char *altsubject_match2;
+ size_t identity_len;
/**
- * domain_suffix_match2 - Constraint for server domain name
+ * anonymous_identity - Anonymous EAP Identity
*
- * This field is like domain_suffix_match, but used for phase 2 (inside
- * EAP-TTLS/PEAP/FAST tunnel) authentication.
+ * This field is used for unencrypted use with EAP types that support
+ * different tunnelled identity, e.g., EAP-TTLS, in order to reveal the
+ * real identity (identity field) only to the authentication server.
+ *
+ * If not set, the identity field will be used for both unencrypted and
+ * protected fields.
+ *
+ * This field can also be used with EAP-SIM/AKA/AKA' to store the
+ * pseudonym identity.
*/
- char *domain_suffix_match2;
+ u8 *anonymous_identity;
/**
- * domain_match2 - Constraint for server domain name
- *
- * This field is like domain_match, but used for phase 2 (inside
- * EAP-TTLS/PEAP/FAST tunnel) authentication.
+ * anonymous_identity_len - Length of anonymous_identity
*/
- char *domain_match2;
+ size_t anonymous_identity_len;
+
+ u8 *imsi_identity;
+ size_t imsi_identity_len;
+
+ /**
+ * machine_identity - EAP Identity for machine credential
+ *
+ * This field is used to set the machine identity or NAI for cases where
+ * and explicit machine credential (instead of or in addition to a user
+ * credential (from %identity) is needed.
+ */
+ u8 *machine_identity;
+
+ /**
+ * machine_identity_len - EAP Identity length for machine credential
+ */
+ size_t machine_identity_len;
+
+ /**
+ * password - Password string for EAP
+ *
+ * This field can include either the plaintext password (default
+ * option) or a NtPasswordHash (16-byte MD4 hash of the unicode
+ * presentation of the password) if flags field has
+ * EAP_CONFIG_FLAGS_PASSWORD_NTHASH bit set to 1. NtPasswordHash can
+ * only be used with authentication mechanism that use this hash as the
+ * starting point for operation: MSCHAP and MSCHAPv2 (EAP-MSCHAPv2,
+ * EAP-TTLS/MSCHAPv2, EAP-TTLS/MSCHAP, LEAP).
+ *
+ * In addition, this field is used to configure a pre-shared key for
+ * EAP-PSK/PAX/SAKE/GPSK. The length of the PSK must be 16 for EAP-PSK
+ * and EAP-PAX and 32 for EAP-SAKE. EAP-GPSK can use a variable length
+ * PSK.
+ */
+ u8 *password;
+
+ /**
+ * password_len - Length of password field
+ */
+ size_t password_len;
+
+ /**
+ * machine_password - Password string for EAP machine credential
+ *
+ * This field is used when machine credential based on username/password
+ * is needed instead of a user credential (from %password). See
+ * %password for more details on the format.
+ */
+ u8 *machine_password;
+
+ /**
+ * machine_password_len - Length of machine credential password field
+ */
+ size_t machine_password_len;
+
+ /**
+ * cert - Certificate parameters for Phase 1
+ */
+ struct eap_peer_cert_config cert;
+
+ /**
+ * phase2_cert - Certificate parameters for Phase 2
+ *
+ * This is like cert, but used for Phase 2 (inside
+ * EAP-TTLS/PEAP/FAST/TEAP tunnel) authentication.
+ */
+ struct eap_peer_cert_config phase2_cert;
+
+ /**
+ * machine_cert - Certificate parameters for Phase 2 machine credential
+ *
+ * This is like cert, but used for Phase 2 (inside EAP-TEAP tunnel)
+ * authentication with machine credentials (while phase2_cert is used
+ * for user credentials).
+ */
+ struct eap_peer_cert_config machine_cert;
/**
* eap_methods - Allowed EAP methods
@@ -496,6 +495,13 @@
char *phase2;
/**
+ * machine_phase2 - Phase2 parameters for machine credentials
+ *
+ * See phase2 for more details.
+ */
+ char *machine_phase2;
+
+ /**
* pcsc - Parameters for PC/SC smartcard interface for USIM and GSM SIM
*
* This field is used to configure PC/SC smartcard interface.
@@ -507,123 +513,6 @@
char *pcsc;
/**
- * pin - PIN for USIM, GSM SIM, and smartcards
- *
- * This field is used to configure PIN for SIM and smartcards for
- * EAP-SIM and EAP-AKA. In addition, this is used with EAP-TLS if a
- * smartcard is used for private key operations.
- *
- * If left out, this will be asked through control interface.
- */
- char *pin;
-
- /**
- * engine - Enable OpenSSL engine (e.g., for smartcard access)
- *
- * This is used if private key operations for EAP-TLS are performed
- * using a smartcard.
- */
- int engine;
-
- /**
- * engine_id - Engine ID for OpenSSL engine
- *
- * "opensc" to select OpenSC engine or "pkcs11" to select PKCS#11
- * engine.
- *
- * This is used if private key operations for EAP-TLS are performed
- * using a smartcard.
- */
- char *engine_id;
-
- /**
- * engine2 - Enable OpenSSL engine (e.g., for smartcard) (Phase 2)
- *
- * This is used if private key operations for EAP-TLS are performed
- * using a smartcard.
- *
- * This field is like engine, but used for phase 2 (inside
- * EAP-TTLS/PEAP/FAST tunnel) authentication.
- */
- int engine2;
-
-
- /**
- * pin2 - PIN for USIM, GSM SIM, and smartcards (Phase 2)
- *
- * This field is used to configure PIN for SIM and smartcards for
- * EAP-SIM and EAP-AKA. In addition, this is used with EAP-TLS if a
- * smartcard is used for private key operations.
- *
- * This field is like pin2, but used for phase 2 (inside
- * EAP-TTLS/PEAP/FAST tunnel) authentication.
- *
- * If left out, this will be asked through control interface.
- */
- char *pin2;
-
- /**
- * engine2_id - Engine ID for OpenSSL engine (Phase 2)
- *
- * "opensc" to select OpenSC engine or "pkcs11" to select PKCS#11
- * engine.
- *
- * This is used if private key operations for EAP-TLS are performed
- * using a smartcard.
- *
- * This field is like engine_id, but used for phase 2 (inside
- * EAP-TTLS/PEAP/FAST tunnel) authentication.
- */
- char *engine2_id;
-
-
- /**
- * key_id - Key ID for OpenSSL engine
- *
- * This is used if private key operations for EAP-TLS are performed
- * using a smartcard.
- */
- char *key_id;
-
- /**
- * cert_id - Cert ID for OpenSSL engine
- *
- * This is used if the certificate operations for EAP-TLS are performed
- * using a smartcard.
- */
- char *cert_id;
-
- /**
- * ca_cert_id - CA Cert ID for OpenSSL engine
- *
- * This is used if the CA certificate for EAP-TLS is on a smartcard.
- */
- char *ca_cert_id;
-
- /**
- * key2_id - Key ID for OpenSSL engine (phase2)
- *
- * This is used if private key operations for EAP-TLS are performed
- * using a smartcard.
- */
- char *key2_id;
-
- /**
- * cert2_id - Cert ID for OpenSSL engine (phase2)
- *
- * This is used if the certificate operations for EAP-TLS are performed
- * using a smartcard.
- */
- char *cert2_id;
-
- /**
- * ca_cert2_id - CA Cert ID for OpenSSL engine (phase2)
- *
- * This is used if the CA certificate for EAP-TLS is on a smartcard.
- */
- char *ca_cert2_id;
-
- /**
* otp - One-time-password
*
* This field should not be set in configuration step. It is only used
@@ -751,6 +640,8 @@
#define EAP_CONFIG_FLAGS_PASSWORD_NTHASH BIT(0)
#define EAP_CONFIG_FLAGS_EXT_PASSWORD BIT(1)
+#define EAP_CONFIG_FLAGS_MACHINE_PASSWORD_NTHASH BIT(2)
+#define EAP_CONFIG_FLAGS_EXT_MACHINE_PASSWORD BIT(3)
/**
* flags - Network configuration flags (bitfield)
*
@@ -760,19 +651,14 @@
* instead of plaintext password
* bit 1 = password is stored in external storage; the value in the
* password field is the name of that external entry
+ * bit 2 = machine password is represented as a 16-byte NtPasswordHash
+ * value instead of plaintext password
+ * bit 3 = machine password is stored in external storage; the value in
+ * the password field is the name of that external entry
*/
u32 flags;
/**
- * ocsp - Whether to use/require OCSP to check server certificate
- *
- * 0 = do not use OCSP stapling (TLS certificate status extension)
- * 1 = try to use OCSP stapling, but not require response
- * 2 = require valid OCSP stapling response
- */
- int ocsp;
-
- /**
* external_sim_resp - Response from external SIM processing
*
* This field should not be set in configuration step. It is only used
diff --git a/src/eap_peer/eap_fast.c b/src/eap_peer/eap_fast.c
index 94ce57d..0ed4a2b 100644
--- a/src/eap_peer/eap_fast.c
+++ b/src/eap_peer/eap_fast.c
@@ -162,7 +162,7 @@
if (eap_peer_select_phase2_methods(config, "auth=",
&data->phase2_types,
- &data->num_phase2_types) < 0) {
+ &data->num_phase2_types, 0) < 0) {
eap_fast_deinit(sm, data);
return NULL;
}
@@ -364,22 +364,24 @@
}
-static int eap_fast_select_phase2_method(struct eap_fast_data *data, u8 type)
+static int eap_fast_select_phase2_method(struct eap_fast_data *data,
+ int vendor, enum eap_type type)
{
size_t i;
/* TODO: TNC with anonymous provisioning; need to require both
* completed MSCHAPv2 and TNC */
- if (data->anon_provisioning && type != EAP_TYPE_MSCHAPV2) {
- wpa_printf(MSG_INFO, "EAP-FAST: Only EAP-MSCHAPv2 is allowed "
- "during unauthenticated provisioning; reject phase2"
- " type %d", type);
+ if (data->anon_provisioning &&
+ (vendor != EAP_VENDOR_IETF || type != EAP_TYPE_MSCHAPV2)) {
+ wpa_printf(MSG_INFO,
+ "EAP-FAST: Only EAP-MSCHAPv2 is allowed during unauthenticated provisioning; reject phase2 type %u:%u",
+ vendor, type);
return -1;
}
#ifdef EAP_TNC
- if (type == EAP_TYPE_TNC) {
+ if (vendor == EAP_VENDOR_IETF && type == EAP_TYPE_TNC) {
data->phase2_type.vendor = EAP_VENDOR_IETF;
data->phase2_type.method = EAP_TYPE_TNC;
wpa_printf(MSG_DEBUG, "EAP-FAST: Selected Phase 2 EAP "
@@ -391,7 +393,7 @@
#endif /* EAP_TNC */
for (i = 0; i < data->num_phase2_types; i++) {
- if (data->phase2_types[i].vendor != EAP_VENDOR_IETF ||
+ if (data->phase2_types[i].vendor != vendor ||
data->phase2_types[i].method != type)
continue;
@@ -404,7 +406,9 @@
break;
}
- if (type != data->phase2_type.method || type == EAP_TYPE_NONE)
+ if (vendor != data->phase2_type.vendor ||
+ type != data->phase2_type.method ||
+ (vendor == EAP_VENDOR_IETF && type == EAP_TYPE_NONE))
return -1;
return 0;
@@ -422,6 +426,8 @@
struct eap_method_ret iret;
struct eap_peer_config *config = eap_get_config(sm);
struct wpabuf msg;
+ int vendor = EAP_VENDOR_IETF;
+ enum eap_type method;
if (len <= sizeof(struct eap_hdr)) {
wpa_printf(MSG_INFO, "EAP-FAST: too short "
@@ -429,14 +435,27 @@
return -1;
}
pos = (u8 *) (hdr + 1);
- wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 Request: type=%d", *pos);
- if (*pos == EAP_TYPE_IDENTITY) {
+ method = *pos;
+ if (method == EAP_TYPE_EXPANDED) {
+ if (len < sizeof(struct eap_hdr) + 8) {
+ wpa_printf(MSG_INFO,
+ "EAP-FAST: Too short Phase 2 request (expanded header) (len=%lu)",
+ (unsigned long) len);
+ return -1;
+ }
+ vendor = WPA_GET_BE24(pos + 1);
+ method = WPA_GET_BE32(pos + 4);
+ }
+ wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 Request: type=%u:%u",
+ vendor, method);
+ if (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_IDENTITY) {
*resp = eap_sm_buildIdentity(sm, hdr->identifier, 1);
return 0;
}
if (data->phase2_priv && data->phase2_method &&
- *pos != data->phase2_type.method) {
+ (vendor != data->phase2_type.vendor ||
+ method != data->phase2_type.method)) {
wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 EAP sequence - "
"deinitialize previous method");
data->phase2_method->deinit(sm, data->phase2_priv);
@@ -448,7 +467,7 @@
if (data->phase2_type.vendor == EAP_VENDOR_IETF &&
data->phase2_type.method == EAP_TYPE_NONE &&
- eap_fast_select_phase2_method(data, *pos) < 0) {
+ eap_fast_select_phase2_method(data, vendor, method) < 0) {
if (eap_peer_tls_phase2_nak(data->phase2_types,
data->num_phase2_types,
hdr, resp))
@@ -459,8 +478,9 @@
if ((data->phase2_priv == NULL &&
eap_fast_init_phase2_method(sm, data) < 0) ||
data->phase2_method == NULL) {
- wpa_printf(MSG_INFO, "EAP-FAST: Failed to initialize "
- "Phase 2 EAP method %d", *pos);
+ wpa_printf(MSG_INFO,
+ "EAP-FAST: Failed to initialize Phase 2 EAP method %u:%u",
+ vendor, method);
ret->methodState = METHOD_DONE;
ret->decision = DECISION_FAIL;
return -1;
diff --git a/src/eap_peer/eap_i.h b/src/eap_peer/eap_i.h
index 096f0f2..8f29d4a 100644
--- a/src/eap_peer/eap_i.h
+++ b/src/eap_peer/eap_i.h
@@ -72,7 +72,7 @@
/**
* method - EAP type number (EAP_TYPE_*)
*/
- EapType method;
+ enum eap_type method;
/**
* name - Name of the method (e.g., "TLS")
@@ -312,7 +312,7 @@
EAP_FAILURE
} EAP_state;
/* Long-term local variables */
- EapType selectedMethod;
+ enum eap_type selectedMethod;
EapMethodState methodState;
int lastId;
struct wpabuf *lastRespData;
@@ -322,7 +322,7 @@
Boolean rxSuccess;
Boolean rxFailure;
int reqId;
- EapType reqMethod;
+ enum eap_type reqMethod;
int reqVendor;
u32 reqVendorMethod;
Boolean ignore;
@@ -366,6 +366,7 @@
u8 *peer_challenge, *auth_challenge;
int num_rounds;
+ int num_rounds_short;
int force_disabled;
struct wps_context *wps;
@@ -381,6 +382,7 @@
unsigned int expected_failure:1;
unsigned int ext_cert_check:1;
unsigned int waiting_ext_cert_check:1;
+ unsigned int use_machine_cred:1;
struct dl_list erp_keys; /* struct eap_erp_key */
};
diff --git a/src/eap_peer/eap_methods.c b/src/eap_peer/eap_methods.c
index 9747954..f2d2947 100644
--- a/src/eap_peer/eap_methods.c
+++ b/src/eap_peer/eap_methods.c
@@ -27,7 +27,8 @@
* @method: EAP type number
* Returns: Pointer to EAP method or %NULL if not found
*/
-const struct eap_method * eap_peer_get_eap_method(int vendor, EapType method)
+const struct eap_method * eap_peer_get_eap_method(int vendor,
+ enum eap_type method)
{
struct eap_method *m;
for (m = eap_methods; m; m = m->next) {
@@ -47,7 +48,7 @@
* This function maps EAP type names into EAP type numbers based on the list of
* EAP methods included in the build.
*/
-EapType eap_peer_get_type(const char *name, int *vendor)
+enum eap_type eap_peer_get_type(const char *name, int *vendor)
{
struct eap_method *m;
for (m = eap_methods; m; m = m->next) {
@@ -70,7 +71,7 @@
* This function maps EAP type numbers into EAP type names based on the list of
* EAP methods included in the build.
*/
-const char * eap_get_name(int vendor, EapType type)
+const char * eap_get_name(int vendor, enum eap_type type)
{
struct eap_method *m;
if (vendor == EAP_VENDOR_IETF && type == EAP_TYPE_EXPANDED)
@@ -169,7 +170,7 @@
for (m = eap_methods; m; m = m->next)
c++;
-
+
*count = c;
return eap_methods;
}
@@ -279,7 +280,8 @@
* is not needed anymore.
*/
struct eap_method * eap_peer_method_alloc(int version, int vendor,
- EapType method, const char *name)
+ enum eap_type method,
+ const char *name)
{
struct eap_method *eap;
eap = os_zalloc(sizeof(*eap));
diff --git a/src/eap_peer/eap_methods.h b/src/eap_peer/eap_methods.h
index 09e08d3..e94f3d7 100644
--- a/src/eap_peer/eap_methods.h
+++ b/src/eap_peer/eap_methods.h
@@ -11,31 +11,33 @@
#include "eap_common/eap_defs.h"
-const struct eap_method * eap_peer_get_eap_method(int vendor, EapType method);
+const struct eap_method * eap_peer_get_eap_method(int vendor,
+ enum eap_type method);
const struct eap_method * eap_peer_get_methods(size_t *count);
struct eap_method * eap_peer_method_alloc(int version, int vendor,
- EapType method, const char *name);
+ enum eap_type method,
+ const char *name);
int eap_peer_method_register(struct eap_method *method);
#ifdef IEEE8021X_EAPOL
-EapType eap_peer_get_type(const char *name, int *vendor);
-const char * eap_get_name(int vendor, EapType type);
+enum eap_type eap_peer_get_type(const char *name, int *vendor);
+const char * eap_get_name(int vendor, enum eap_type type);
size_t eap_get_names(char *buf, size_t buflen);
char ** eap_get_names_as_string_array(size_t *num);
void eap_peer_unregister_methods(void);
#else /* IEEE8021X_EAPOL */
-static inline EapType eap_peer_get_type(const char *name, int *vendor)
+static inline enum eap_type eap_peer_get_type(const char *name, int *vendor)
{
*vendor = EAP_VENDOR_IETF;
return EAP_TYPE_NONE;
}
-static inline const char * eap_get_name(int vendor, EapType type)
+static inline const char * eap_get_name(int vendor, enum eap_type type)
{
return NULL;
}
diff --git a/src/eap_peer/eap_peap.c b/src/eap_peer/eap_peap.c
index 6453afe..92b15ec 100644
--- a/src/eap_peer/eap_peap.c
+++ b/src/eap_peer/eap_peap.c
@@ -148,7 +148,7 @@
if (eap_peer_select_phase2_methods(config, "auth=",
&data->phase2_types,
- &data->num_phase2_types) < 0) {
+ &data->num_phase2_types, 0) < 0) {
eap_peap_deinit(sm, data);
return NULL;
}
@@ -603,6 +603,8 @@
u8 *pos;
struct eap_method_ret iret;
struct eap_peer_config *config = eap_get_config(sm);
+ int vendor;
+ enum eap_type method;
if (len <= sizeof(struct eap_hdr)) {
wpa_printf(MSG_INFO, "EAP-PEAP: too short "
@@ -666,13 +668,26 @@
#endif /* EAP_TNC */
/* fall through */
default:
+ vendor = EAP_VENDOR_IETF;
+ method = *pos;
+
+ if (method == EAP_TYPE_EXPANDED) {
+ if (len < sizeof(struct eap_hdr) + 8) {
+ wpa_printf(MSG_INFO,
+ "EAP-PEAP: Too short Phase 2 request (expanded header) (len=%lu)",
+ (unsigned long) len);
+ return -1;
+ }
+ vendor = WPA_GET_BE24(pos + 1);
+ method = WPA_GET_BE32(pos + 4);
+ }
+
if (data->phase2_type.vendor == EAP_VENDOR_IETF &&
data->phase2_type.method == EAP_TYPE_NONE) {
size_t i;
for (i = 0; i < data->num_phase2_types; i++) {
- if (data->phase2_types[i].vendor !=
- EAP_VENDOR_IETF ||
- data->phase2_types[i].method != *pos)
+ if (data->phase2_types[i].vendor != vendor ||
+ data->phase2_types[i].method != method)
continue;
data->phase2_type.vendor =
@@ -686,8 +701,9 @@
break;
}
}
- if (*pos != data->phase2_type.method ||
- *pos == EAP_TYPE_NONE) {
+ if (vendor != data->phase2_type.vendor ||
+ method != data->phase2_type.method ||
+ (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_NONE)) {
if (eap_peer_tls_phase2_nak(data->phase2_types,
data->num_phase2_types,
hdr, resp))
diff --git a/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c
index 6cd72e0..54f102a 100644
--- a/src/eap_peer/eap_pwd.c
+++ b/src/eap_peer/eap_pwd.c
@@ -30,6 +30,7 @@
u8 *password;
size_t password_len;
int password_hash;
+ struct wpa_freq_range_list allowed_groups;
u16 group_num;
u8 prep;
u8 token[4];
@@ -54,6 +55,9 @@
};
+static void eap_pwd_deinit(struct eap_sm *sm, void *priv);
+
+
#ifndef CONFIG_NO_STDOUT_DEBUG
static const char * eap_pwd_state_txt(int state)
{
@@ -92,6 +96,7 @@
size_t identity_len, password_len;
int fragment_size;
int pwhash;
+ const char *phase1;
password = eap_get_config_password2(sm, &password_len, &pwhash);
if (password == NULL) {
@@ -129,6 +134,30 @@
data->password_len = password_len;
data->password_hash = pwhash;
+ phase1 = eap_get_config_phase1(sm);
+ if (phase1) {
+ const char *pos, *end;
+ char *copy = NULL;
+ int res;
+
+ pos = os_strstr(phase1, "eap_pwd_groups=");
+ if (pos) {
+ pos += 15;
+ end = os_strchr(pos, ' ');
+ if (end) {
+ copy = os_zalloc(end - pos + 1);
+ if (!copy)
+ goto fail;
+ os_memcpy(copy, pos, end - pos);
+ pos = copy;
+ }
+ res = freq_range_list_parse(&data->allowed_groups, pos);
+ os_free(copy);
+ if (res)
+ goto fail;
+ }
+ }
+
data->out_frag_pos = data->in_frag_pos = 0;
data->inbuf = data->outbuf = NULL;
fragment_size = eap_get_config_fragment_size(sm);
@@ -140,6 +169,9 @@
data->state = PWD_ID_Req;
return data;
+fail:
+ eap_pwd_deinit(sm, data);
+ return NULL;
}
@@ -163,6 +195,7 @@
}
wpabuf_free(data->inbuf);
wpabuf_free(data->outbuf);
+ os_free(data->allowed_groups.range);
bin_clear_free(data, sizeof(*data));
}
@@ -203,6 +236,18 @@
}
+static int eap_pwd_allowed_group(struct eap_pwd_data *data, u16 group)
+{
+ if (!data->allowed_groups.range) {
+ /* By default, allow the groups using NIST curves P-256, P-384,
+ * and P-521. */
+ return group == 19 || group == 20 || group == 21;
+ }
+
+ return freq_range_list_includes(&data->allowed_groups, group);
+}
+
+
static void
eap_pwd_perform_id_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
struct eap_method_ret *ret,
@@ -228,9 +273,11 @@
wpa_printf(MSG_DEBUG,
"EAP-PWD: Server EAP-pwd-ID proposal: group=%u random=%u prf=%u prep=%u",
data->group_num, id->random_function, id->prf, id->prep);
- if ((id->random_function != EAP_PWD_DEFAULT_RAND_FUNC) ||
- (id->prf != EAP_PWD_DEFAULT_PRF)) {
- ret->ignore = TRUE;
+ if (id->random_function != EAP_PWD_DEFAULT_RAND_FUNC ||
+ id->prf != EAP_PWD_DEFAULT_PRF ||
+ !eap_pwd_allowed_group(data, data->group_num)) {
+ wpa_printf(MSG_INFO,
+ "EAP-pwd: Unsupported or disabled proposal");
eap_pwd_state(data, FAILURE);
return;
}
diff --git a/src/eap_peer/eap_teap.c b/src/eap_peer/eap_teap.c
index eea7d6e..f751fbe 100644
--- a/src/eap_peer/eap_teap.c
+++ b/src/eap_peer/eap_teap.c
@@ -35,7 +35,9 @@
void *phase2_priv;
int phase2_success;
int inner_method_done;
+ int iresult_verified;
int result_success_done;
+ int on_tx_completion;
struct eap_method_type phase2_type;
struct eap_method_type *phase2_types;
@@ -167,7 +169,7 @@
eap_teap_parse_phase1(data, config->phase1);
if ((data->provisioning_allowed & EAP_TEAP_PROV_AUTH) &&
- !config->ca_cert && !config->ca_path) {
+ !config->cert.ca_cert && !config->cert.ca_path) {
/* Prevent PAC provisioning without mutual authentication
* (either by validating server certificate or by suitable
* inner EAP method). */
@@ -178,7 +180,7 @@
if (eap_peer_select_phase2_methods(config, "auth=",
&data->phase2_types,
- &data->num_phase2_types) < 0) {
+ &data->num_phase2_types, 0) < 0) {
eap_teap_deinit(sm, data);
return NULL;
}
@@ -276,8 +278,10 @@
{
/* FIX: RFC 7170 does not describe whether MSK or EMSK based S-IMCK[j]
* is used in this derivation */
- if (eap_teap_derive_eap_msk(data->simck_msk, data->key_data) < 0 ||
- eap_teap_derive_eap_emsk(data->simck_msk, data->emsk) < 0)
+ if (eap_teap_derive_eap_msk(data->tls_cs, data->simck_msk,
+ data->key_data) < 0 ||
+ eap_teap_derive_eap_emsk(data->tls_cs, data->simck_msk,
+ data->emsk) < 0)
return -1;
data->success = 1;
return 0;
@@ -308,6 +312,7 @@
struct eap_teap_data *data)
{
data->inner_method_done = 0;
+ data->iresult_verified = 0;
data->phase2_method =
eap_peer_get_eap_method(data->phase2_type.vendor,
data->phase2_type.method);
@@ -322,7 +327,8 @@
}
-static int eap_teap_select_phase2_method(struct eap_teap_data *data, u8 type)
+static int eap_teap_select_phase2_method(struct eap_teap_data *data,
+ int vendor, enum eap_type type)
{
size_t i;
@@ -330,15 +336,15 @@
* completed inner EAP authentication (EAP-pwd or EAP-EKE) and TNC */
if (data->anon_provisioning &&
- !eap_teap_allowed_anon_prov_phase2_method(type)) {
+ !eap_teap_allowed_anon_prov_phase2_method(vendor, type)) {
wpa_printf(MSG_INFO,
- "EAP-TEAP: EAP type %u not allowed during unauthenticated provisioning",
- type);
+ "EAP-TEAP: EAP type %u:%u not allowed during unauthenticated provisioning",
+ vendor, type);
return -1;
}
#ifdef EAP_TNC
- if (type == EAP_TYPE_TNC) {
+ if (vendor == EAP_VENDOR_IETF && type == EAP_TYPE_TNC) {
data->phase2_type.vendor = EAP_VENDOR_IETF;
data->phase2_type.method = EAP_TYPE_TNC;
wpa_printf(MSG_DEBUG,
@@ -350,7 +356,7 @@
#endif /* EAP_TNC */
for (i = 0; i < data->num_phase2_types; i++) {
- if (data->phase2_types[i].vendor != EAP_VENDOR_IETF ||
+ if (data->phase2_types[i].vendor != vendor ||
data->phase2_types[i].method != type)
continue;
@@ -363,13 +369,31 @@
break;
}
- if (type != data->phase2_type.method || type == EAP_TYPE_NONE)
+ if (vendor != data->phase2_type.vendor ||
+ type != data->phase2_type.method ||
+ (vendor == EAP_VENDOR_IETF && type == EAP_TYPE_NONE))
return -1;
return 0;
}
+static void eap_teap_deinit_inner_eap(struct eap_sm *sm,
+ struct eap_teap_data *data)
+{
+ if (!data->phase2_priv || !data->phase2_method)
+ return;
+
+ wpa_printf(MSG_DEBUG,
+ "EAP-TEAP: Phase 2 EAP sequence - deinitialize previous method");
+ data->phase2_method->deinit(sm, data->phase2_priv);
+ data->phase2_method = NULL;
+ data->phase2_priv = NULL;
+ data->phase2_type.vendor = EAP_VENDOR_IETF;
+ data->phase2_type.method = EAP_TYPE_NONE;
+}
+
+
static int eap_teap_phase2_request(struct eap_sm *sm,
struct eap_teap_data *data,
struct eap_method_ret *ret,
@@ -381,6 +405,8 @@
struct eap_method_ret iret;
struct eap_peer_config *config = eap_get_config(sm);
struct wpabuf msg;
+ int vendor = EAP_VENDOR_IETF;
+ enum eap_type method;
if (len <= sizeof(struct eap_hdr)) {
wpa_printf(MSG_INFO,
@@ -389,26 +415,33 @@
return -1;
}
pos = (u8 *) (hdr + 1);
- wpa_printf(MSG_DEBUG, "EAP-TEAP: Phase 2 Request: type=%d", *pos);
- if (*pos == EAP_TYPE_IDENTITY) {
+ method = *pos;
+ if (method == EAP_TYPE_EXPANDED) {
+ if (len < sizeof(struct eap_hdr) + 8) {
+ wpa_printf(MSG_INFO,
+ "EAP-TEAP: Too short Phase 2 request (expanded header) (len=%lu)",
+ (unsigned long) len);
+ return -1;
+ }
+ vendor = WPA_GET_BE24(pos + 1);
+ method = WPA_GET_BE32(pos + 4);
+ }
+ wpa_printf(MSG_DEBUG, "EAP-TEAP: Phase 2 Request: type=%u:%u",
+ vendor, method);
+ if (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_IDENTITY) {
+ eap_teap_deinit_inner_eap(sm, data);
*resp = eap_sm_buildIdentity(sm, hdr->identifier, 1);
return 0;
}
if (data->phase2_priv && data->phase2_method &&
- *pos != data->phase2_type.method) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Phase 2 EAP sequence - deinitialize previous method");
- data->phase2_method->deinit(sm, data->phase2_priv);
- data->phase2_method = NULL;
- data->phase2_priv = NULL;
- data->phase2_type.vendor = EAP_VENDOR_IETF;
- data->phase2_type.method = EAP_TYPE_NONE;
- }
+ (vendor != data->phase2_type.vendor ||
+ method != data->phase2_type.method))
+ eap_teap_deinit_inner_eap(sm, data);
if (data->phase2_type.vendor == EAP_VENDOR_IETF &&
data->phase2_type.method == EAP_TYPE_NONE &&
- eap_teap_select_phase2_method(data, *pos) < 0) {
+ eap_teap_select_phase2_method(data, vendor, method) < 0) {
if (eap_peer_tls_phase2_nak(data->phase2_types,
data->num_phase2_types,
hdr, resp))
@@ -419,8 +452,8 @@
if ((!data->phase2_priv && eap_teap_init_phase2_method(sm, data) < 0) ||
!data->phase2_method) {
wpa_printf(MSG_INFO,
- "EAP-TEAP: Failed to initialize Phase 2 EAP method %d",
- *pos);
+ "EAP-TEAP: Failed to initialize Phase 2 EAP method %u:%u",
+ vendor, method);
ret->methodState = METHOD_DONE;
ret->decision = DECISION_FAIL;
return -1;
@@ -435,7 +468,8 @@
if (!(*resp) ||
(iret.methodState == METHOD_DONE &&
iret.decision == DECISION_FAIL)) {
- ret->methodState = METHOD_DONE;
+ /* Wait for protected indication of failure */
+ ret->methodState = METHOD_MAY_CONT;
ret->decision = DECISION_FAIL;
} else if ((iret.methodState == METHOD_DONE ||
iret.methodState == METHOD_MAY_CONT) &&
@@ -499,10 +533,23 @@
}
+static struct wpabuf * eap_teap_add_identity_type(struct eap_sm *sm,
+ struct wpabuf *msg)
+{
+ struct wpabuf *tlv;
+
+ tlv = eap_teap_tlv_identity_type(sm->use_machine_cred ?
+ TEAP_IDENTITY_TYPE_MACHINE :
+ TEAP_IDENTITY_TYPE_USER);
+ return wpabuf_concat(msg, tlv);
+}
+
+
static struct wpabuf * eap_teap_process_eap_payload_tlv(
struct eap_sm *sm, struct eap_teap_data *data,
struct eap_method_ret *ret,
- u8 *eap_payload_tlv, size_t eap_payload_tlv_len)
+ u8 *eap_payload_tlv, size_t eap_payload_tlv_len,
+ enum teap_identity_types req_id_type)
{
struct eap_hdr *hdr;
struct wpabuf *resp = NULL;
@@ -534,13 +581,18 @@
return NULL;
}
- return eap_teap_tlv_eap_payload(resp);
+ resp = eap_teap_tlv_eap_payload(resp);
+ if (req_id_type)
+ resp = eap_teap_add_identity_type(sm, resp);
+
+ return resp;
}
static struct wpabuf * eap_teap_process_basic_auth_req(
struct eap_sm *sm, struct eap_teap_data *data,
- u8 *basic_auth_req, size_t basic_auth_req_len)
+ u8 *basic_auth_req, size_t basic_auth_req_len,
+ enum teap_identity_types req_id_type)
{
const u8 *identity, *password;
size_t identity_len, password_len, plen;
@@ -570,6 +622,8 @@
wpabuf_put_data(resp, password, password_len);
wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TEAP: Basic-Password-Auth-Resp",
resp);
+ if (req_id_type)
+ resp = eap_teap_add_identity_type(sm, resp);
/* Assume this succeeds so that Result TLV(Success) from the server can
* be used to terminate TEAP. */
@@ -679,7 +733,8 @@
data->simck_idx + 1);
if (!data->phase2_method)
- return eap_teap_derive_cmk_basic_pw_auth(data->simck_msk,
+ return eap_teap_derive_cmk_basic_pw_auth(data->tls_cs,
+ data->simck_msk,
cmk_msk);
if (!data->phase2_method || !data->phase2_priv) {
@@ -711,7 +766,8 @@
&emsk_len);
}
- res = eap_teap_derive_imck(data->simck_msk, data->simck_emsk,
+ res = eap_teap_derive_imck(data->tls_cs,
+ data->simck_msk, data->simck_emsk,
msk, msk_len, emsk, emsk_len,
data->simck_msk, cmk_msk,
data->simck_emsk, cmk_emsk);
@@ -1188,6 +1244,7 @@
struct eap_teap_tlv_parse tlv;
int failed = 0;
enum teap_error_codes error = 0;
+ int iresult_added = 0;
if (eap_teap_parse_decrypted(decrypted, &tlv, &resp) < 0) {
/* Parsing failed - no response available */
@@ -1211,14 +1268,21 @@
goto send_resp;
}
- if ((tlv.iresult == TEAP_STATUS_SUCCESS ||
- (!data->result_success_done &&
- tlv.result == TEAP_STATUS_SUCCESS)) &&
- !tlv.crypto_binding) {
- /* Result TLV or Intermediate-Result TLV indicating success,
- * but no Crypto-Binding TLV */
+ if (tlv.iresult == TEAP_STATUS_SUCCESS && !tlv.crypto_binding) {
+ /* Intermediate-Result TLV indicating success, but no
+ * Crypto-Binding TLV */
wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Result TLV or Intermediate-Result TLV indicating success, but no Crypto-Binding TLV");
+ "EAP-TEAP: Intermediate-Result TLV indicating success, but no Crypto-Binding TLV");
+ failed = 1;
+ error = TEAP_ERROR_TUNNEL_COMPROMISE_ERROR;
+ goto done;
+ }
+
+ if (!data->iresult_verified && !data->result_success_done &&
+ tlv.result == TEAP_STATUS_SUCCESS && !tlv.crypto_binding) {
+ /* Result TLV indicating success, but no Crypto-Binding TLV */
+ wpa_printf(MSG_DEBUG,
+ "EAP-TEAP: Result TLV indicating success, but no Crypto-Binding TLV");
failed = 1;
error = TEAP_ERROR_TUNNEL_COMPROMISE_ERROR;
goto done;
@@ -1234,17 +1298,45 @@
goto done;
}
+ if (tlv.identity_type == TEAP_IDENTITY_TYPE_MACHINE) {
+ struct eap_peer_config *config = eap_get_config(sm);
+
+ sm->use_machine_cred = config && config->machine_identity &&
+ config->machine_identity_len;
+ } else if (tlv.identity_type) {
+ sm->use_machine_cred = 0;
+ }
+ if (tlv.identity_type) {
+ struct eap_peer_config *config = eap_get_config(sm);
+
+ os_free(data->phase2_types);
+ data->phase2_types = NULL;
+ data->num_phase2_types = 0;
+ if (config &&
+ eap_peer_select_phase2_methods(config, "auth=",
+ &data->phase2_types,
+ &data->num_phase2_types,
+ sm->use_machine_cred) < 0) {
+ wpa_printf(MSG_INFO,
+ "EAP-TEAP: Failed to update Phase 2 EAP types");
+ failed = 1;
+ goto done;
+ }
+ }
+
if (tlv.basic_auth_req) {
tmp = eap_teap_process_basic_auth_req(sm, data,
tlv.basic_auth_req,
- tlv.basic_auth_req_len);
+ tlv.basic_auth_req_len,
+ tlv.identity_type);
if (!tmp)
failed = 1;
resp = wpabuf_concat(resp, tmp);
} else if (tlv.eap_payload_tlv) {
tmp = eap_teap_process_eap_payload_tlv(sm, data, ret,
tlv.eap_payload_tlv,
- tlv.eap_payload_tlv_len);
+ tlv.eap_payload_tlv_len,
+ tlv.identity_type);
if (!tmp)
failed = 1;
resp = wpabuf_concat(resp, tmp);
@@ -1257,6 +1349,7 @@
resp = wpabuf_concat(resp, tmp);
if (tlv.iresult == TEAP_STATUS_FAILURE)
failed = 1;
+ iresult_added = 1;
}
}
@@ -1280,8 +1373,10 @@
resp = wpabuf_concat(resp, tmp);
if (tlv.result == TEAP_STATUS_SUCCESS && !failed)
data->result_success_done = 1;
- if (tlv.iresult == TEAP_STATUS_SUCCESS && !failed)
+ if (tlv.iresult == TEAP_STATUS_SUCCESS && !failed) {
data->inner_method_done = 0;
+ data->iresult_verified = 1;
+ }
}
}
@@ -1315,6 +1410,7 @@
data->phase2_method->vendor == 0 &&
eap_teap_allowed_anon_prov_cipher_suite(data->tls_cs) &&
eap_teap_allowed_anon_prov_phase2_method(
+ data->phase2_method->vendor,
data->phase2_method->method))) &&
(tlv.iresult == TEAP_STATUS_SUCCESS ||
tlv.result == TEAP_STATUS_SUCCESS)) {
@@ -1343,13 +1439,22 @@
tmp = eap_teap_tlv_result(TEAP_STATUS_SUCCESS, 0);
resp = wpabuf_concat(tmp, resp);
}
+ if ((tlv.iresult == TEAP_STATUS_SUCCESS ||
+ tlv.iresult == TEAP_STATUS_FAILURE) && !iresult_added) {
+ tmp = eap_teap_tlv_result((!failed && data->phase2_success) ?
+ TEAP_STATUS_SUCCESS :
+ TEAP_STATUS_FAILURE, 1);
+ resp = wpabuf_concat(tmp, resp);
+ }
if (resp && tlv.result == TEAP_STATUS_SUCCESS && !failed &&
- tlv.crypto_binding && data->phase2_success) {
+ (tlv.crypto_binding || data->iresult_verified) &&
+ data->phase2_success) {
/* Successfully completed Phase 2 */
wpa_printf(MSG_DEBUG,
"EAP-TEAP: Authentication completed successfully");
- ret->methodState = data->provisioning ?
+ ret->methodState = METHOD_MAY_CONT;
+ data->on_tx_completion = data->provisioning ?
METHOD_MAY_CONT : METHOD_DONE;
ret->decision = DECISION_UNCOND_SUCC;
}
@@ -1402,9 +1507,18 @@
if (wpabuf_len(in_data) == 0) {
/* Received TLS ACK - requesting more fragments */
- return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TEAP,
- data->teap_version,
- identifier, NULL, out_data);
+ res = eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TEAP,
+ data->teap_version,
+ identifier, NULL, out_data);
+ if (res == 0 && !data->ssl.tls_out &&
+ data->on_tx_completion) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-TEAP: Mark authentication completed at full TX of fragments");
+ ret->methodState = data->on_tx_completion;
+ data->on_tx_completion = 0;
+ ret->decision = DECISION_UNCOND_SUCC;
+ }
+ return res;
}
res = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted);
@@ -1904,6 +2018,8 @@
data->phase2_success = 0;
data->inner_method_done = 0;
data->result_success_done = 0;
+ data->iresult_verified = 0;
+ data->done_on_tx_completion = 0;
data->resuming = 1;
data->provisioning = 0;
data->anon_provisioning = 0;
diff --git a/src/eap_peer/eap_tls.c b/src/eap_peer/eap_tls.c
index 15d60d7..d9771f6 100644
--- a/src/eap_peer/eap_tls.c
+++ b/src/eap_peer/eap_tls.c
@@ -1,6 +1,6 @@
/*
* EAP peer method: EAP-TLS (RFC 2716)
- * Copyright (c) 2004-2008, 2012-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2008, 2012-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -33,10 +33,17 @@
{
struct eap_tls_data *data;
struct eap_peer_config *config = eap_get_config(sm);
- if (config == NULL ||
- ((sm->init_phase2 ? config->private_key2 : config->private_key)
- == NULL &&
- (sm->init_phase2 ? config->engine2 : config->engine) == 0)) {
+ struct eap_peer_cert_config *cert;
+
+ if (!config)
+ return NULL;
+ if (!sm->init_phase2)
+ cert = &config->cert;
+ else if (sm->use_machine_cred)
+ cert = &config->machine_cert;
+ else
+ cert = &config->phase2_cert;
+ if (!cert->private_key && cert->engine == 0) {
wpa_printf(MSG_INFO, "EAP-TLS: Private key not configured");
return NULL;
}
@@ -51,13 +58,12 @@
if (eap_peer_tls_ssl_init(sm, &data->ssl, config, EAP_TYPE_TLS)) {
wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
eap_tls_deinit(sm, data);
- if (config->engine) {
+ if (cert->engine) {
wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting Smartcard "
"PIN");
eap_sm_request_pin(sm);
sm->ignore = TRUE;
- } else if (config->private_key && !config->private_key_passwd)
- {
+ } else if (cert->private_key && !cert->private_key_passwd) {
wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting private "
"key passphrase");
eap_sm_request_passphrase(sm);
diff --git a/src/eap_peer/eap_tls_common.c b/src/eap_peer/eap_tls_common.c
index 7e0690c..80e2d71 100644
--- a/src/eap_peer/eap_tls_common.c
+++ b/src/eap_peer/eap_tls_common.c
@@ -16,7 +16,7 @@
#include "eap_config.h"
-static struct wpabuf * eap_tls_msg_alloc(EapType type, size_t payload_len,
+static struct wpabuf * eap_tls_msg_alloc(enum eap_type type, size_t payload_len,
u8 code, u8 identifier)
{
if (type == EAP_UNAUTH_TLS_TYPE)
@@ -105,8 +105,8 @@
}
-static void eap_tls_params_from_conf1(struct tls_connection_params *params,
- struct eap_peer_config *config)
+static void eap_tls_cert_params_from_conf(struct tls_connection_params *params,
+ struct eap_peer_cert_config *config)
{
params->ca_cert = config->ca_cert;
params->ca_path = config->ca_path;
@@ -125,6 +125,19 @@
params->key_id = config->key_id;
params->cert_id = config->cert_id;
params->ca_cert_id = config->ca_cert_id;
+ if (config->ocsp)
+ params->flags |= TLS_CONN_REQUEST_OCSP;
+ if (config->ocsp >= 2)
+ params->flags |= TLS_CONN_REQUIRE_OCSP;
+ if (config->ocsp == 3)
+ params->flags |= TLS_CONN_REQUIRE_OCSP_ALL;
+}
+
+
+static void eap_tls_params_from_conf1(struct tls_connection_params *params,
+ struct eap_peer_config *config)
+{
+ eap_tls_cert_params_from_conf(params, &config->cert);
eap_tls_params_flags(params, config->phase1);
}
@@ -132,27 +145,19 @@
static void eap_tls_params_from_conf2(struct tls_connection_params *params,
struct eap_peer_config *config)
{
- params->ca_cert = config->ca_cert2;
- params->ca_path = config->ca_path2;
- params->client_cert = config->client_cert2;
- params->private_key = config->private_key2;
- params->private_key_passwd = config->private_key2_passwd;
- params->dh_file = config->dh_file2;
- params->subject_match = config->subject_match2;
- params->altsubject_match = config->altsubject_match2;
- params->check_cert_subject = config->check_cert_subject2;
- params->suffix_match = config->domain_suffix_match2;
- params->domain_match = config->domain_match2;
- params->engine = config->engine2;
- params->engine_id = config->engine2_id;
- params->pin = config->pin2;
- params->key_id = config->key2_id;
- params->cert_id = config->cert2_id;
- params->ca_cert_id = config->ca_cert2_id;
+ eap_tls_cert_params_from_conf(params, &config->phase2_cert);
eap_tls_params_flags(params, config->phase2);
}
+static void eap_tls_params_from_conf2m(struct tls_connection_params *params,
+ struct eap_peer_config *config)
+{
+ eap_tls_cert_params_from_conf(params, &config->machine_cert);
+ eap_tls_params_flags(params, config->machine_phase2);
+}
+
+
static int eap_tls_params_from_conf(struct eap_sm *sm,
struct eap_ssl_data *data,
struct tls_connection_params *params,
@@ -199,7 +204,10 @@
*/
params->flags |= TLS_CONN_DISABLE_TLSv1_3;
}
- if (phase2) {
+ if (phase2 && sm->use_machine_cred) {
+ wpa_printf(MSG_DEBUG, "TLS: using machine config options");
+ eap_tls_params_from_conf2m(params, config);
+ } else if (phase2) {
wpa_printf(MSG_DEBUG, "TLS: using phase2 config options");
eap_tls_params_from_conf2(params, config);
} else {
@@ -242,12 +250,6 @@
{
int res;
- if (config->ocsp)
- params->flags |= TLS_CONN_REQUEST_OCSP;
- if (config->ocsp >= 2)
- params->flags |= TLS_CONN_REQUIRE_OCSP;
- if (config->ocsp == 3)
- params->flags |= TLS_CONN_REQUIRE_OCSP_ALL;
data->conn = tls_connection_init(data->ssl_ctx);
if (data->conn == NULL) {
wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS "
@@ -264,8 +266,8 @@
*/
wpa_printf(MSG_INFO,
"TLS: Bad PIN provided, requesting a new one");
- os_free(config->pin);
- config->pin = NULL;
+ os_free(config->cert.pin);
+ config->cert.pin = NULL;
eap_sm_request_pin(sm);
sm->ignore = TRUE;
} else if (res == TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED) {
@@ -619,7 +621,8 @@
* @out_data: Buffer for returning the allocated output buffer
* Returns: ret (0 or 1) on success, -1 on failure
*/
-static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type,
+static int eap_tls_process_output(struct eap_ssl_data *data,
+ enum eap_type eap_type,
int peap_version, u8 id, int ret,
struct wpabuf **out_data)
{
@@ -717,7 +720,7 @@
* the tunneled data is used.
*/
int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
- EapType eap_type, int peap_version,
+ enum eap_type eap_type, int peap_version,
u8 id, const struct wpabuf *in_data,
struct wpabuf **out_data)
{
@@ -809,7 +812,7 @@
* @peap_version: Version number for EAP-PEAP/TTLS
* Returns: Pointer to the allocated ACK frame or %NULL on failure
*/
-struct wpabuf * eap_peer_tls_build_ack(u8 id, EapType eap_type,
+struct wpabuf * eap_peer_tls_build_ack(u8 id, enum eap_type eap_type,
int peap_version)
{
struct wpabuf *resp;
@@ -899,7 +902,7 @@
*/
const u8 * eap_peer_tls_process_init(struct eap_sm *sm,
struct eap_ssl_data *data,
- EapType eap_type,
+ enum eap_type eap_type,
struct eap_method_ret *ret,
const struct wpabuf *reqData,
size_t *len, u8 *flags)
@@ -1056,7 +1059,7 @@
* Returns: 0 on success, -1 on failure
*/
int eap_peer_tls_encrypt(struct eap_sm *sm, struct eap_ssl_data *data,
- EapType eap_type, int peap_version, u8 id,
+ enum eap_type eap_type, int peap_version, u8 id,
const struct wpabuf *in_data,
struct wpabuf **out_data)
{
@@ -1092,17 +1095,21 @@
int eap_peer_select_phase2_methods(struct eap_peer_config *config,
const char *prefix,
struct eap_method_type **types,
- size_t *num_types)
+ size_t *num_types, int use_machine_cred)
{
char *start, *pos, *buf;
struct eap_method_type *methods = NULL, *_methods;
u32 method;
size_t num_methods = 0, prefix_len;
+ const char *phase2;
- if (config == NULL || config->phase2 == NULL)
+ if (!config)
+ goto get_defaults;
+ phase2 = use_machine_cred ? config->machine_phase2 : config->phase2;
+ if (!phase2)
goto get_defaults;
- start = buf = os_strdup(config->phase2);
+ start = buf = os_strdup(phase2);
if (buf == NULL)
return -1;
diff --git a/src/eap_peer/eap_tls_common.h b/src/eap_peer/eap_tls_common.h
index d96eff1..183b7de 100644
--- a/src/eap_peer/eap_tls_common.h
+++ b/src/eap_peer/eap_tls_common.h
@@ -107,17 +107,17 @@
struct eap_ssl_data *data, u8 eap_type,
size_t *len);
int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
- EapType eap_type, int peap_version,
+ enum eap_type eap_type, int peap_version,
u8 id, const struct wpabuf *in_data,
struct wpabuf **out_data);
-struct wpabuf * eap_peer_tls_build_ack(u8 id, EapType eap_type,
+struct wpabuf * eap_peer_tls_build_ack(u8 id, enum eap_type eap_type,
int peap_version);
int eap_peer_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data);
int eap_peer_tls_status(struct eap_sm *sm, struct eap_ssl_data *data,
char *buf, size_t buflen, int verbose);
const u8 * eap_peer_tls_process_init(struct eap_sm *sm,
struct eap_ssl_data *data,
- EapType eap_type,
+ enum eap_type eap_type,
struct eap_method_ret *ret,
const struct wpabuf *reqData,
size_t *len, u8 *flags);
@@ -127,13 +127,13 @@
const struct wpabuf *in_data,
struct wpabuf **in_decrypted);
int eap_peer_tls_encrypt(struct eap_sm *sm, struct eap_ssl_data *data,
- EapType eap_type, int peap_version, u8 id,
+ enum eap_type eap_type, int peap_version, u8 id,
const struct wpabuf *in_data,
struct wpabuf **out_data);
int eap_peer_select_phase2_methods(struct eap_peer_config *config,
const char *prefix,
struct eap_method_type **types,
- size_t *num_types);
+ size_t *num_types, int use_machine_cred);
int eap_peer_tls_phase2_nak(struct eap_method_type *types, size_t num_types,
struct eap_hdr *hdr, struct wpabuf **resp);
diff --git a/src/eap_peer/eap_ttls.c b/src/eap_peer/eap_ttls.c
index 1c8dbe2..662676f 100644
--- a/src/eap_peer/eap_ttls.c
+++ b/src/eap_peer/eap_ttls.c
@@ -146,8 +146,8 @@
if (data->phase2_type == EAP_TTLS_PHASE2_EAP) {
if (eap_peer_select_phase2_methods(config, "autheap=",
&data->phase2_eap_types,
- &data->num_phase2_eap_types)
- < 0) {
+ &data->num_phase2_eap_types,
+ 0) < 0) {
eap_ttls_deinit(sm, data);
return NULL;
}
@@ -311,11 +311,11 @@
static void eap_ttls_phase2_select_eap_method(struct eap_ttls_data *data,
- u8 method)
+ int vendor, enum eap_type method)
{
size_t i;
for (i = 0; i < data->num_phase2_eap_types; i++) {
- if (data->phase2_eap_types[i].vendor != EAP_VENDOR_IETF ||
+ if (data->phase2_eap_types[i].vendor != vendor ||
data->phase2_eap_types[i].method != method)
continue;
@@ -362,17 +362,19 @@
struct eap_ttls_data *data,
struct eap_method_ret *ret,
struct eap_hdr *hdr, size_t len,
- u8 method, struct wpabuf **resp)
+ int vendor, enum eap_type method,
+ struct wpabuf **resp)
{
#ifdef EAP_TNC
if (data->tnc_started && data->phase2_method &&
- data->phase2_priv && method == EAP_TYPE_TNC &&
+ data->phase2_priv &&
+ vendor == EAP_VENDOR_IETF && method == EAP_TYPE_TNC &&
data->phase2_eap_type.method == EAP_TYPE_TNC)
return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len,
resp);
if (data->ready_for_tnc && !data->tnc_started &&
- method == EAP_TYPE_TNC) {
+ vendor == EAP_VENDOR_IETF && method == EAP_TYPE_TNC) {
wpa_printf(MSG_DEBUG, "EAP-TTLS: Start TNC after completed "
"EAP method");
data->tnc_started = 1;
@@ -386,7 +388,7 @@
return -1;
}
- data->phase2_eap_type.vendor = EAP_VENDOR_IETF;
+ data->phase2_eap_type.vendor = vendor;
data->phase2_eap_type.method = method;
wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected "
"Phase 2 EAP vendor %d method %d (TNC)",
@@ -400,10 +402,11 @@
if (data->phase2_eap_type.vendor == EAP_VENDOR_IETF &&
data->phase2_eap_type.method == EAP_TYPE_NONE)
- eap_ttls_phase2_select_eap_method(data, method);
+ eap_ttls_phase2_select_eap_method(data, vendor, method);
- if (method != data->phase2_eap_type.method || method == EAP_TYPE_NONE)
- {
+ if (vendor != data->phase2_eap_type.vendor ||
+ method != data->phase2_eap_type.method ||
+ (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_NONE)) {
if (eap_peer_tls_phase2_nak(data->phase2_eap_types,
data->num_phase2_eap_types,
hdr, resp))
@@ -412,8 +415,7 @@
}
if (data->phase2_priv == NULL) {
- data->phase2_method = eap_peer_get_eap_method(
- EAP_VENDOR_IETF, method);
+ data->phase2_method = eap_peer_get_eap_method(vendor, method);
if (data->phase2_method) {
sm->init_phase2 = 1;
data->phase2_priv = data->phase2_method->init(sm);
@@ -421,8 +423,9 @@
}
}
if (data->phase2_priv == NULL || data->phase2_method == NULL) {
- wpa_printf(MSG_INFO, "EAP-TTLS: failed to initialize "
- "Phase 2 EAP method %d", method);
+ wpa_printf(MSG_INFO,
+ "EAP-TTLS: failed to initialize Phase 2 EAP method %u:%u",
+ vendor, method);
return -1;
}
@@ -451,9 +454,23 @@
case EAP_TYPE_IDENTITY:
*resp = eap_sm_buildIdentity(sm, hdr->identifier, 1);
break;
+ case EAP_TYPE_EXPANDED:
+ if (len < sizeof(struct eap_hdr) + 8) {
+ wpa_printf(MSG_INFO,
+ "EAP-TTLS: Too short Phase 2 request (expanded header) (len=%lu)",
+ (unsigned long) len);
+ return -1;
+ }
+ if (eap_ttls_phase2_request_eap_method(sm, data, ret, hdr, len,
+ WPA_GET_BE24(pos + 1),
+ WPA_GET_BE32(pos + 4),
+ resp) < 0)
+ return -1;
+ break;
default:
if (eap_ttls_phase2_request_eap_method(sm, data, ret, hdr, len,
- *pos, resp) < 0)
+ EAP_VENDOR_IETF, *pos,
+ resp) < 0)
return -1;
break;
}