]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
EAP-TEAP peer: Add support for machine credentials using certificates
authorJouni Malinen <j@w1.fi>
Sun, 1 Sep 2019 13:44:51 +0000 (16:44 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 1 Sep 2019 14:19:43 +0000 (17:19 +0300)
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>
src/eap_peer/eap_config.h
src/eap_peer/eap_fast.c
src/eap_peer/eap_peap.c
src/eap_peer/eap_teap.c
src/eap_peer/eap_tls.c
src/eap_peer/eap_tls_common.c
src/eap_peer/eap_tls_common.h
src/eap_peer/eap_ttls.c
wpa_supplicant/config.c
wpa_supplicant/config_file.c
wpa_supplicant/wpa_supplicant.conf

index ae1de914a014d7e4ca9161d55c64c842b80e0383..3238f74f955ae6514a4f37627550559ccf5e3e7c 100644 (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
         *
index 61d0a6b102deb74af4c69599ebf559c5d27d8b9a..0ed4a2b700c68e0128fdff61b794e94381a9a066 100644 (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;
        }
index 5ca61459d274b198808519b9909eae2fc381af5c..92b15ec34d298a4e5fe1e5c26536c97423c7477e 100644 (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;
        }
index 1695833865eff36dc84d528f6c47591ee0923a2c..06665b9ef22857fdbf59f791405ecd18879177b5 100644 (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,
index 1bde9973044dac5662037daa2656c7ee69f91a16..d9771f601acebbac144021459c523a113b9911b4 100644 (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);
index a59c3a0eebf5763d4655e0aed9ac95ea57f8f0a4..80e2d71e9c22283bc467d0d33ad56fbe164da1a8 100644 (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;
 
index e3c9e0331b1ce05ce27e33246e6e2e99bfa9d016..183b7de00ae513d7f3beef458bc4a017efba1da8 100644 (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);
 
index bed4094a9764f6e660d6085c787d55bb22390993..662676f8f2e67e76809ee1c5f986a2988f375a9b 100644 (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;
                }
index 067585b81a3345a92461e22aa9f8ec67d63f3e2a..cc197ae37e380f04ade5143017cba21baffb8761 100644 (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);
index c47300b1ac6d6a53ff8e4657d14d0eebc9583d9f..a1f8b7f0681216c89a9e600b2229137a1259db04 100644 (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);
index f7a365267a97ea2f8eb6675ccc5139462b3f5bad..26df78a227bcee6ada9daf12fd8f928c40421740 100644 (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