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 += \
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-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-autoip \
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ctc-static \
......@@ -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/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_client.p12 \
$(NULL)
# make target dependencies can't have colons in their names, which ends up
......
......@@ -3110,12 +3110,17 @@ eap_tls_reader (const char *eap_method,
gs_unref_bytes GBytes *privkey = NULL;
gs_unref_bytes GBytes *client_cert = 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,
NM_SETTING_802_1X_IDENTITY,
svGetValueStr (ifcfg, "IEEE_8021X_IDENTITY", &identity_free),
NULL);
/* CA certificate */
if (!_cert_set_from_ifcfg (s_8021x,
ifcfg,
phase2 ? "IEEE_8021X_INNER_CA_CERT" : "IEEE_8021X_CA_CERT",
......@@ -3129,6 +3134,7 @@ eap_tls_reader (const char *eap_method,
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);
/* Private key */
if (!_cert_set_from_ifcfg (s_8021x,
ifcfg,
phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY" : "IEEE_8021X_PRIVATE_KEY",
......@@ -3141,35 +3147,39 @@ eap_tls_reader (const char *eap_method,
keys_ifcfg,
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);
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,
ifcfg,
phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" : "IEEE_8021X_CLIENT_CERT",
phase2 ? NM_SETTING_802_1X_PHASE2_CLIENT_CERT : NM_SETTING_802_1X_CLIENT_CERT,
client_cert_var,
client_cert_prop,
&client_cert,
error))
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,
ifcfg,
keys_ifcfg,
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);
if (!client_cert) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Missing certificate for EAP method '%s'.",
eap_method);
return FALSE;
/* In the past when the private key and client certificate
* were the same PKCS #12 file we used to write only the
* private key variable. Still support that even if it means
* 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;
......
......@@ -209,6 +209,7 @@ write_object (NMSetting8021x *s_8021x,
GHashTable *secrets,
GHashTable *blobs,
const Setting8021xSchemeVtable *objtype,
gboolean force_write,
GError **error)
{
NMSetting8021xCKScheme scheme;
......@@ -287,7 +288,7 @@ write_object (NMSetting8021x *s_8021x,
*/
standard_file = utils_cert_path (svFileGetName (ifcfg), objtype->vtable->file_suffix, extension);
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;
}
......@@ -338,43 +339,41 @@ write_8021x_certs (NMSetting8021x *s_8021x,
shvarFile *ifcfg,
GError **error)
{
const Setting8021xSchemeVtable *otype = NULL;
const Setting8021xSchemeVtable *pk_otype = NULL;
gs_free char *value_to_free = NULL;
/* CA certificate */
if (!write_object (s_8021x, ifcfg, secrets, blobs,
phase2
? &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],
FALSE,
error))
return FALSE;
/* Private key */
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
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 */
if (!write_object (s_8021x, ifcfg, secrets, blobs, otype, error))
if (!write_object (s_8021x, ifcfg, secrets, blobs, pk_otype, FALSE, error))
return FALSE;
/* Client certificate */
if (otype->vtable->format_func (s_8021x) == NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
/* Don't need a client certificate with PKCS#12 since the file is both
* the client certificate and the private key in one file.
*/
svSetValueStr (ifcfg,
phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" : "IEEE_8021X_CLIENT_CERT",
NULL);
} else {
/* Save the client certificate */
if (!write_object (s_8021x, ifcfg, secrets, blobs,
phase2
? &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CLIENT_CERT]
: &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_CLIENT_CERT],
error))
return FALSE;
}
/* Save the client certificate.
* If there is a private key, always write a property for the
* client certificate even if it is empty, so that the reader
* doesn't have to read the private key file to determine if it
* is a PKCS #12 one which serves also as client certificate.
*/
if (!write_object (s_8021x, ifcfg, secrets, blobs,
phase2
? &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CLIENT_CERT]
: &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_CLIENT_CERT],
!!svGetValue (ifcfg, pk_otype->ifcfg_rh_key, &value_to_free),
error))
return FALSE;
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)
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
test_read_write_802_1x_password_raw (void)
{
......@@ -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/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/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/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);
......
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