Commit 835c5bf4 authored by Beniamino Galvani's avatar Beniamino Galvani

ifcfg-rh: merge branch 'bg/802-1x-client-cert-rh1705054'

!148
https://bugzilla.redhat.com/show_bug.cgi?id=1705054
(cherry picked from commit 7502fb0f)
(cherry picked from commit eb9dec78)
parents c71b4726 53f1490b
Pipeline #39097 passed with stage
in 21 minutes and 31 seconds
...@@ -2907,6 +2907,7 @@ EXTRA_DIST += \ ...@@ -2907,6 +2907,7 @@ EXTRA_DIST += \
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-peap-mschapv2 \ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-peap-mschapv2 \
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-agent \ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-agent \
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-always \ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-always \
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-p12-no-client-cert \
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-auto-negotiate-on \ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-auto-negotiate-on \
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-autoip \ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-autoip \
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ctc-static \ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ctc-static \
...@@ -2976,6 +2977,7 @@ EXTRA_DIST += \ ...@@ -2976,6 +2977,7 @@ EXTRA_DIST += \
src/settings/plugins/ifcfg-rh/tests/network-scripts/route6-test-wired-ipv6-manual \ src/settings/plugins/ifcfg-rh/tests/network-scripts/route6-test-wired-ipv6-manual \
src/settings/plugins/ifcfg-rh/tests/network-scripts/test1_key_and_cert.pem \ src/settings/plugins/ifcfg-rh/tests/network-scripts/test1_key_and_cert.pem \
src/settings/plugins/ifcfg-rh/tests/network-scripts/test_ca_cert.pem \ src/settings/plugins/ifcfg-rh/tests/network-scripts/test_ca_cert.pem \
src/settings/plugins/ifcfg-rh/tests/network-scripts/test_client.p12 \
$(NULL) $(NULL)
# make target dependencies can't have colons in their names, which ends up # make target dependencies can't have colons in their names, which ends up
......
...@@ -3110,12 +3110,17 @@ eap_tls_reader (const char *eap_method, ...@@ -3110,12 +3110,17 @@ eap_tls_reader (const char *eap_method,
gs_unref_bytes GBytes *privkey = NULL; gs_unref_bytes GBytes *privkey = NULL;
gs_unref_bytes GBytes *client_cert = NULL; gs_unref_bytes GBytes *client_cert = NULL;
gs_free char *identity_free = NULL; gs_free char *identity_free = NULL;
gs_free char *value_to_free = NULL;
const char *client_cert_var;
const char *client_cert_prop;
NMSetting8021xCKFormat format;
g_object_set (s_8021x, g_object_set (s_8021x,
NM_SETTING_802_1X_IDENTITY, NM_SETTING_802_1X_IDENTITY,
svGetValueStr (ifcfg, "IEEE_8021X_IDENTITY", &identity_free), svGetValueStr (ifcfg, "IEEE_8021X_IDENTITY", &identity_free),
NULL); NULL);
/* CA certificate */
if (!_cert_set_from_ifcfg (s_8021x, if (!_cert_set_from_ifcfg (s_8021x,
ifcfg, ifcfg,
phase2 ? "IEEE_8021X_INNER_CA_CERT" : "IEEE_8021X_CA_CERT", phase2 ? "IEEE_8021X_INNER_CA_CERT" : "IEEE_8021X_CA_CERT",
...@@ -3129,6 +3134,7 @@ eap_tls_reader (const char *eap_method, ...@@ -3129,6 +3134,7 @@ eap_tls_reader (const char *eap_method,
phase2 ? "IEEE_8021X_INNER_CA_CERT_PASSWORD" : "IEEE_8021X_CA_CERT_PASSWORD", phase2 ? "IEEE_8021X_INNER_CA_CERT_PASSWORD" : "IEEE_8021X_CA_CERT_PASSWORD",
phase2 ? NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD : NM_SETTING_802_1X_CA_CERT_PASSWORD); phase2 ? NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD : NM_SETTING_802_1X_CA_CERT_PASSWORD);
/* Private key */
if (!_cert_set_from_ifcfg (s_8021x, if (!_cert_set_from_ifcfg (s_8021x,
ifcfg, ifcfg,
phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY" : "IEEE_8021X_PRIVATE_KEY", phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY" : "IEEE_8021X_PRIVATE_KEY",
...@@ -3141,35 +3147,39 @@ eap_tls_reader (const char *eap_method, ...@@ -3141,35 +3147,39 @@ eap_tls_reader (const char *eap_method,
keys_ifcfg, keys_ifcfg,
phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD" : "IEEE_8021X_PRIVATE_KEY_PASSWORD", phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD" : "IEEE_8021X_PRIVATE_KEY_PASSWORD",
phase2 ? NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD : NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD); phase2 ? NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD : NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD);
if (!privkey) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Missing %s for EAP method '%s'.",
phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY" : "IEEE_8021X_PRIVATE_KEY",
eap_method);
return FALSE;
}
/* Client certificate */
client_cert_var = phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" : "IEEE_8021X_CLIENT_CERT";
client_cert_prop = phase2 ? NM_SETTING_802_1X_PHASE2_CLIENT_CERT : NM_SETTING_802_1X_CLIENT_CERT;
if (!_cert_set_from_ifcfg (s_8021x, if (!_cert_set_from_ifcfg (s_8021x,
ifcfg, ifcfg,
phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" : "IEEE_8021X_CLIENT_CERT", client_cert_var,
phase2 ? NM_SETTING_802_1X_PHASE2_CLIENT_CERT : NM_SETTING_802_1X_CLIENT_CERT, client_cert_prop,
&client_cert, &client_cert,
error)) error))
return FALSE; return FALSE;
/* FIXME: writer does not actually write IEEE_8021X_CLIENT_CERT_PASSWORD and other
* certificate related passwords. It should, because otherwise persisting such profiles
* to ifcfg looses information. As this currently only matters for PKCS11 URIs, it seems
* a seldom used feature so that it is not fixed yet. */
_secret_set_from_ifcfg (s_8021x, _secret_set_from_ifcfg (s_8021x,
ifcfg, ifcfg,
keys_ifcfg, keys_ifcfg,
phase2 ? "IEEE_8021X_INNER_CLIENT_CERT_PASSWORD" : "IEEE_8021X_CLIENT_CERT_PASSWORD", phase2 ? "IEEE_8021X_INNER_CLIENT_CERT_PASSWORD" : "IEEE_8021X_CLIENT_CERT_PASSWORD",
phase2 ? NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD : NM_SETTING_802_1X_CLIENT_CERT_PASSWORD); phase2 ? NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD : NM_SETTING_802_1X_CLIENT_CERT_PASSWORD);
if (!client_cert) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, /* In the past when the private key and client certificate
"Missing certificate for EAP method '%s'.", * were the same PKCS #12 file we used to write only the
eap_method); * private key variable. Still support that even if it means
return FALSE; * that we have to look into the file content, which makes
* the connection not self-contained.
*/
if ( !client_cert
&& privkey
&& !svGetValue (ifcfg, client_cert_var, &value_to_free)) {
if (phase2)
format = nm_setting_802_1x_get_phase2_private_key_format (s_8021x);
else
format = nm_setting_802_1x_get_private_key_format (s_8021x);
if (format == NM_SETTING_802_1X_CK_FORMAT_PKCS12)
g_object_set (s_8021x, client_cert_prop, privkey, NULL);
} }
return TRUE; return TRUE;
......
...@@ -209,6 +209,7 @@ write_object (NMSetting8021x *s_8021x, ...@@ -209,6 +209,7 @@ write_object (NMSetting8021x *s_8021x,
GHashTable *secrets, GHashTable *secrets,
GHashTable *blobs, GHashTable *blobs,
const Setting8021xSchemeVtable *objtype, const Setting8021xSchemeVtable *objtype,
gboolean force_write,
GError **error) GError **error)
{ {
NMSetting8021xCKScheme scheme; NMSetting8021xCKScheme scheme;
...@@ -287,7 +288,7 @@ write_object (NMSetting8021x *s_8021x, ...@@ -287,7 +288,7 @@ write_object (NMSetting8021x *s_8021x,
*/ */
standard_file = utils_cert_path (svFileGetName (ifcfg), objtype->vtable->file_suffix, extension); standard_file = utils_cert_path (svFileGetName (ifcfg), objtype->vtable->file_suffix, extension);
g_hash_table_replace (blobs, standard_file, NULL); g_hash_table_replace (blobs, standard_file, NULL);
svUnsetValue (ifcfg, objtype->ifcfg_rh_key); svSetValue (ifcfg, objtype->ifcfg_rh_key, force_write ? "" : NULL);
return TRUE; return TRUE;
} }
...@@ -338,43 +339,41 @@ write_8021x_certs (NMSetting8021x *s_8021x, ...@@ -338,43 +339,41 @@ write_8021x_certs (NMSetting8021x *s_8021x,
shvarFile *ifcfg, shvarFile *ifcfg,
GError **error) GError **error)
{ {
const Setting8021xSchemeVtable *otype = NULL; const Setting8021xSchemeVtable *pk_otype = NULL;
gs_free char *value_to_free = NULL;
/* CA certificate */ /* CA certificate */
if (!write_object (s_8021x, ifcfg, secrets, blobs, if (!write_object (s_8021x, ifcfg, secrets, blobs,
phase2 phase2
? &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CA_CERT] ? &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CA_CERT]
: &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_CA_CERT], : &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_CA_CERT],
FALSE,
error)) error))
return FALSE; return FALSE;
/* Private key */ /* Private key */
if (phase2) if (phase2)
otype = &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_PRIVATE_KEY]; pk_otype = &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_PRIVATE_KEY];
else else
otype = &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PRIVATE_KEY]; pk_otype = &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PRIVATE_KEY];
/* Save the private key */ /* Save the private key */
if (!write_object (s_8021x, ifcfg, secrets, blobs, otype, error)) if (!write_object (s_8021x, ifcfg, secrets, blobs, pk_otype, FALSE, error))
return FALSE; return FALSE;
/* Client certificate */ /* Save the client certificate.
if (otype->vtable->format_func (s_8021x) == NM_SETTING_802_1X_CK_FORMAT_PKCS12) { * If there is a private key, always write a property for the
/* Don't need a client certificate with PKCS#12 since the file is both * client certificate even if it is empty, so that the reader
* the client certificate and the private key in one file. * doesn't have to read the private key file to determine if it
*/ * is a PKCS #12 one which serves also as client certificate.
svSetValueStr (ifcfg, */
phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" : "IEEE_8021X_CLIENT_CERT", if (!write_object (s_8021x, ifcfg, secrets, blobs,
NULL); phase2
} else { ? &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CLIENT_CERT]
/* Save the client certificate */ : &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_CLIENT_CERT],
if (!write_object (s_8021x, ifcfg, secrets, blobs, !!svGetValue (ifcfg, pk_otype->ifcfg_rh_key, &value_to_free),
phase2 error))
? &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CLIENT_CERT] return FALSE;
: &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_CLIENT_CERT],
error))
return FALSE;
}
return TRUE; return TRUE;
} }
......
# Intel Corporation 82540EP Gigabit Ethernet Controller (Mobile)
TYPE=Ethernet
DEVICE=eth0
HWADDR=00:11:22:33:44:ee
BOOTPROTO=dhcp
ONBOOT=yes
NM_CONTROLLED=yes
KEY_MGMT=IEEE8021X
IEEE_8021X_EAP_METHODS=TLS
IEEE_8021X_IDENTITY="David Smith"
IEEE_8021X_CA_CERT=test_ca_cert.pem
IEEE_8021X_PRIVATE_KEY=test_client.p12
IEEE_8021X_PRIVATE_KEY_PASSWORD="test1"
...@@ -1973,6 +1973,27 @@ test_read_802_1x_ttls_eapgtc (void) ...@@ -1973,6 +1973,27 @@ test_read_802_1x_ttls_eapgtc (void)
g_object_unref (connection); g_object_unref (connection);
} }
static void
test_read_802_1x_tls_p12_no_client_cert (void)
{
gs_unref_object NMConnection *connection = NULL;
NMSetting8021x *s_8021x;
const char *path;
connection = _connection_from_file (TEST_IFCFG_DIR"/ifcfg-test-wired-8021x-tls-p12-no-client-cert",
NULL, TYPE_ETHERNET, NULL);
s_8021x = nm_connection_get_setting_802_1x (connection);
g_assert (s_8021x);
g_assert_cmpint (nm_setting_802_1x_get_private_key_scheme (s_8021x), ==, NM_SETTING_802_1X_CK_SCHEME_PATH);
path = nm_setting_802_1x_get_private_key_path (s_8021x);
g_assert (path);
g_assert_cmpint (nm_setting_802_1x_get_client_cert_scheme (s_8021x), ==, NM_SETTING_802_1X_CK_SCHEME_PATH);
g_assert_cmpstr (path, ==, nm_setting_802_1x_get_client_cert_path (s_8021x));
}
static void static void
test_read_write_802_1x_password_raw (void) test_read_write_802_1x_password_raw (void)
{ {
...@@ -10096,6 +10117,8 @@ int main (int argc, char **argv) ...@@ -10096,6 +10117,8 @@ int main (int argc, char **argv)
g_test_add_func (TPATH "802-1x/subj-matches", test_read_write_802_1X_subj_matches); g_test_add_func (TPATH "802-1x/subj-matches", test_read_write_802_1X_subj_matches);
g_test_add_func (TPATH "802-1x/ttls-eapgtc", test_read_802_1x_ttls_eapgtc); g_test_add_func (TPATH "802-1x/ttls-eapgtc", test_read_802_1x_ttls_eapgtc);
g_test_add_func (TPATH "802-1x/password_raw", test_read_write_802_1x_password_raw); g_test_add_func (TPATH "802-1x/password_raw", test_read_write_802_1x_password_raw);
g_test_add_func (TPATH "802-1x/tls-p12-no-client-cert", test_read_802_1x_tls_p12_no_client_cert);
g_test_add_data_func (TPATH "wired/read/aliases/good/0", GINT_TO_POINTER (0), test_read_wired_aliases_good); g_test_add_data_func (TPATH "wired/read/aliases/good/0", GINT_TO_POINTER (0), test_read_wired_aliases_good);
g_test_add_data_func (TPATH "wired/read/aliases/good/3", GINT_TO_POINTER (3), test_read_wired_aliases_good); g_test_add_data_func (TPATH "wired/read/aliases/good/3", GINT_TO_POINTER (3), test_read_wired_aliases_good);
g_test_add_func (TPATH "wired/read/aliases/bad1", test_read_wired_aliases_bad_1); g_test_add_func (TPATH "wired/read/aliases/bad1", test_read_wired_aliases_bad_1);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment