diff --git a/src/eap_peer/eap_config.h b/src/eap_peer/eap_config.h index ae1de914a..3238f74f9 100644 --- a/src/eap_peer/eap_config.h +++ b/src/eap_peer/eap_config.h @@ -399,6 +399,15 @@ struct eap_peer_config { */ 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 * @@ -485,6 +494,13 @@ struct eap_peer_config { */ 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 * diff --git a/src/eap_peer/eap_fast.c b/src/eap_peer/eap_fast.c index 61d0a6b10..0ed4a2b70 100644 --- a/src/eap_peer/eap_fast.c +++ b/src/eap_peer/eap_fast.c @@ -162,7 +162,7 @@ static void * eap_fast_init(struct eap_sm *sm) 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; } diff --git a/src/eap_peer/eap_peap.c b/src/eap_peer/eap_peap.c index 5ca61459d..92b15ec34 100644 --- a/src/eap_peer/eap_peap.c +++ b/src/eap_peer/eap_peap.c @@ -148,7 +148,7 @@ static void * eap_peap_init(struct eap_sm *sm) 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; } diff --git a/src/eap_peer/eap_teap.c b/src/eap_peer/eap_teap.c index 169583386..06665b9ef 100644 --- a/src/eap_peer/eap_teap.c +++ b/src/eap_peer/eap_teap.c @@ -180,7 +180,7 @@ static void * eap_teap_init(struct eap_sm *sm) 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; } @@ -1296,6 +1296,23 @@ static int eap_teap_process_decrypted(struct eap_sm *sm, } 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, diff --git a/src/eap_peer/eap_tls.c b/src/eap_peer/eap_tls.c index 1bde99730..d9771f601 100644 --- a/src/eap_peer/eap_tls.c +++ b/src/eap_peer/eap_tls.c @@ -33,11 +33,17 @@ static void * eap_tls_init(struct eap_sm *sm) { struct eap_tls_data *data; struct eap_peer_config *config = eap_get_config(sm); - if (config == NULL || - ((sm->init_phase2 ? config->phase2_cert.private_key : - config->cert.private_key) == NULL && - (sm->init_phase2 ? config->phase2_cert.engine : - config->cert.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; } @@ -52,13 +58,12 @@ static void * eap_tls_init(struct eap_sm *sm) 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->cert.engine) { + if (cert->engine) { wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting Smartcard " "PIN"); eap_sm_request_pin(sm); sm->ignore = TRUE; - } else if (config->cert.private_key && - !config->cert.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 a59c3a0ee..80e2d71e9 100644 --- a/src/eap_peer/eap_tls_common.c +++ b/src/eap_peer/eap_tls_common.c @@ -150,6 +150,14 @@ static void eap_tls_params_from_conf2(struct tls_connection_params *params, } +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, @@ -196,7 +204,10 @@ static int eap_tls_params_from_conf(struct eap_sm *sm, */ 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 { @@ -1084,17 +1095,21 @@ int eap_peer_tls_encrypt(struct eap_sm *sm, struct eap_ssl_data *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) { 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 e3c9e0331..183b7de00 100644 --- a/src/eap_peer/eap_tls_common.h +++ b/src/eap_peer/eap_tls_common.h @@ -133,7 +133,7 @@ int eap_peer_tls_encrypt(struct eap_sm *sm, struct eap_ssl_data *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 bed4094a9..662676f8f 100644 --- a/src/eap_peer/eap_ttls.c +++ b/src/eap_peer/eap_ttls.c @@ -146,8 +146,8 @@ static void * eap_ttls_init(struct eap_sm *sm) 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; } diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 067585b81..cc197ae37 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -2415,6 +2415,7 @@ static const struct parse_data ssid_fields[] = { { STRe(domain_match2, phase2_cert.domain_match) }, { STRe(phase1, phase1) }, { STRe(phase2, phase2) }, + { STRe(machine_phase2, machine_phase2) }, { STRe(pcsc, pcsc) }, { STR_KEYe(pin, cert.pin) }, { STRe(engine_id, cert.engine_id) }, @@ -2428,6 +2429,26 @@ static const struct parse_data ssid_fields[] = { { STRe(ca_cert_id2, phase2_cert.ca_cert_id) }, { INTe(engine, cert.engine) }, { INTe(engine2, phase2_cert.engine) }, + { STRe(machine_ca_cert, machine_cert.ca_cert) }, + { STRe(machine_ca_path, machine_cert.ca_path) }, + { STRe(machine_client_cert, machine_cert.client_cert) }, + { STRe(machine_private_key, machine_cert.private_key) }, + { STR_KEYe(machine_private_key_passwd, + machine_cert.private_key_passwd) }, + { STRe(machine_dh_file, machine_cert.dh_file) }, + { STRe(machine_subject_match, machine_cert.subject_match) }, + { STRe(machine_check_cert_subject, machine_cert.check_cert_subject) }, + { STRe(machine_altsubject_match, machine_cert.altsubject_match) }, + { STRe(machine_domain_suffix_match, + machine_cert.domain_suffix_match) }, + { STRe(machine_domain_match, machine_cert.domain_match) }, + { STR_KEYe(machine_pin, machine_cert.pin) }, + { STRe(machine_engine_id, machine_cert.engine_id) }, + { STRe(machine_key_id, machine_cert.key_id) }, + { STRe(machine_cert_id, machine_cert.cert_id) }, + { STRe(machine_ca_cert_id, machine_cert.ca_cert_id) }, + { INTe(machine_engine, machine_cert.engine) }, + { INTe(machine_ocsp, machine_cert.ocsp) }, { INT(eapol_flags) }, { INTe(sim_num, sim_num) }, { STRe(openssl_ciphers, openssl_ciphers) }, @@ -2689,8 +2710,10 @@ static void eap_peer_config_free(struct eap_peer_config *eap) bin_clear_free(eap->machine_password, eap->machine_password_len); eap_peer_config_free_cert(&eap->cert); eap_peer_config_free_cert(&eap->phase2_cert); + eap_peer_config_free_cert(&eap->machine_cert); os_free(eap->phase1); os_free(eap->phase2); + os_free(eap->machine_phase2); os_free(eap->pcsc); os_free(eap->otp); os_free(eap->pending_req_otp); diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index c47300b1a..a1f8b7f06 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -799,8 +799,20 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) STR(altsubject_match2); STR(domain_suffix_match2); STR(domain_match2); + STR(machine_ca_cert); + STR(machine_ca_path); + STR(machine_client_cert); + STR(machine_private_key); + STR(machine_private_key_passwd); + STR(machine_dh_file); + STR(machine_subject_match); + STR(machine_check_cert_subject); + STR(machine_altsubject_match); + STR(machine_domain_suffix_match); + STR(machine_domain_match); STR(phase1); STR(phase2); + STR(machine_phase2); STR(pcsc); STR(pin); STR(engine_id); @@ -814,6 +826,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) STR(ca_cert2_id); INTe(engine, cert.engine); INTe(engine2, phase2_cert.engine); + INTe(machine_engine, machine_cert.engine); INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS); STR(openssl_ciphers); INTe(erp, erp); @@ -828,6 +841,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) INT_DEFe(fragment_size, fragment_size, DEFAULT_FRAGMENT_SIZE); INTe(ocsp, cert.ocsp); INTe(ocsp2, phase2_cert.ocsp); + INTe(machine_ocsp, machine_cert.ocsp); INT_DEFe(sim_num, sim_num, DEFAULT_USER_SELECTED_SIM); #endif /* IEEE8021X_EAPOL */ INT(mode); diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index f7a365267..26df78a22 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -1325,6 +1325,11 @@ fast_reauth=1 # domain_suffix_match for more details. # ocsp2: See ocsp for more details. # +# Separate machine credentials can be configured for EAP-TEAP Phase 2 with +# "machine_" prefix (e.g., "machine_identity") in the configuration parameters. +# See the parameters without that prefix for more details on the meaning and +# format of each such parameter. +# # fragment_size: Maximum EAP fragment size in bytes (default 1398). # This value limits the fragment size for EAP methods that support # fragmentation (e.g., EAP-TLS and EAP-PEAP). This value should be set