EAP-TEAP peer: Add support for machine credentials using certificates

This allows EAP-TLS to be used within an EAP-TEAP tunnel when there is
an explicit request for machine credentials. The network profile
parameters are otherwise same as the Phase 1 parameters, but each one
uses a "machine_" prefix for the parameter name.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2019-09-01 16:44:51 +03:00
parent ebee8232d3
commit 6816182461
11 changed files with 113 additions and 18 deletions

View file

@ -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
*

View file

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

View file

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

View file

@ -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,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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