libnm-core/8021x: fix up scheme handling in setters

Fixes: 690e33bdf2
This commit is contained in:
Lubomir Rintel 2017-01-06 16:00:11 +01:00
parent 8386cb6ca6
commit 2b09cee6fa

View file

@ -644,8 +644,8 @@ value_with_scheme (const char *path, const char *scheme)
len = strlen (path);
/* Add the path scheme tag to the front, then the filename */
array = g_byte_array_sized_new (len + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH) + 1);
g_byte_array_append (array, (const guint8 *) NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH));
array = g_byte_array_sized_new (len + strlen (scheme) + 1);
g_byte_array_append (array, (const guint8 *) scheme, strlen (scheme));
g_byte_array_append (array, (const guint8 *) path, len);
g_byte_array_append (array, (const guint8 *) "\0", 1);
@ -655,7 +655,7 @@ value_with_scheme (const char *path, const char *scheme)
/**
* nm_setting_802_1x_set_ca_cert:
* @setting: the #NMSetting8021x
* @cert_path: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH
* @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH
* or %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the CA certificate
* file (PEM or DER format). The path must be UTF-8 encoded; use
* g_filename_to_utf8() to convert if needed. Passing %NULL with any @scheme
@ -1020,7 +1020,7 @@ nm_setting_802_1x_get_client_cert_uri (NMSetting8021x *setting)
/**
* nm_setting_802_1x_set_client_cert:
* @setting: the #NMSetting8021x
* @cert_path: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH
* @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH
* or %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the client
* certificate file (PEM, DER, or PKCS#<!-- -->12 format). The path must be UTF-8
* encoded; use g_filename_to_utf8() to convert if needed. Passing %NULL with
@ -1042,7 +1042,7 @@ nm_setting_802_1x_get_client_cert_uri (NMSetting8021x *setting)
**/
gboolean
nm_setting_802_1x_set_client_cert (NMSetting8021x *setting,
const char *cert_path,
const char *value,
NMSetting8021xCKScheme scheme,
NMSetting8021xCKFormat *out_format,
GError **error)
@ -1053,8 +1053,8 @@ nm_setting_802_1x_set_client_cert (NMSetting8021x *setting,
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
if (cert_path) {
g_return_val_if_fail (g_utf8_validate (cert_path, -1, NULL), FALSE);
if (value) {
g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE);
g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
|| scheme == NM_SETTING_802_1X_CK_SCHEME_PATH
|| scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11,
@ -1068,18 +1068,18 @@ nm_setting_802_1x_set_client_cert (NMSetting8021x *setting,
g_clear_pointer (&priv->client_cert, g_bytes_unref);
if (!cert_path) {
if (!value) {
g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_CLIENT_CERT);
return TRUE;
}
if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) {
priv->client_cert = value_with_scheme (cert_path, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
priv->client_cert = value_with_scheme (value, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11);
g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_CLIENT_CERT);
return TRUE;
}
data = load_and_verify_certificate (cert_path, scheme, &format, error);
data = load_and_verify_certificate (value, scheme, &format, error);
if (data) {
gboolean valid = FALSE;
@ -1108,7 +1108,7 @@ nm_setting_802_1x_set_client_cert (NMSetting8021x *setting,
priv->client_cert = g_byte_array_free_to_bytes (data);
data = NULL;
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
priv->client_cert = value_with_scheme (cert_path, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
priv->client_cert = value_with_scheme (value, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
else
g_assert_not_reached ();
}
@ -1328,7 +1328,7 @@ nm_setting_802_1x_get_phase2_ca_cert_uri (NMSetting8021x *setting)
/**
* nm_setting_802_1x_set_phase2_ca_cert:
* @setting: the #NMSetting8021x
* @cert_path: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH
* @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH
* or %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the "phase2" CA
* certificate file (PEM or DER format). The path must be UTF-8 encoded; use
* g_filename_to_utf8() to convert if needed. Passing %NULL with any @scheme
@ -1346,7 +1346,7 @@ nm_setting_802_1x_get_phase2_ca_cert_uri (NMSetting8021x *setting)
**/
gboolean
nm_setting_802_1x_set_phase2_ca_cert (NMSetting8021x *setting,
const char *cert_path,
const char *value,
NMSetting8021xCKScheme scheme,
NMSetting8021xCKFormat *out_format,
GError **error)
@ -1357,10 +1357,11 @@ nm_setting_802_1x_set_phase2_ca_cert (NMSetting8021x *setting,
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
if (cert_path) {
g_return_val_if_fail (g_utf8_validate (cert_path, -1, NULL), FALSE);
if (value) {
g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE);
g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
|| scheme == NM_SETTING_802_1X_CK_SCHEME_PATH,
|| scheme == NM_SETTING_802_1X_CK_SCHEME_PATH
|| scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11,
FALSE);
}
@ -1371,12 +1372,19 @@ nm_setting_802_1x_set_phase2_ca_cert (NMSetting8021x *setting,
g_clear_pointer (&priv->phase2_ca_cert, g_bytes_unref);
if (!cert_path) {
if (!value) {
g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CA_CERT);
return TRUE;
}
data = load_and_verify_certificate (cert_path, scheme, &format, error);
data = load_and_verify_certificate (value, scheme, &format, error);
if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) {
priv->phase2_ca_cert = value_with_scheme (value, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11);
g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CA_CERT);
return TRUE;
}
data = load_and_verify_certificate (value, scheme, &format, error);
if (data) {
/* wpa_supplicant can only use raw x509 CA certs */
if (format == NM_CRYPTO_FILE_FORMAT_X509) {
@ -1387,7 +1395,7 @@ nm_setting_802_1x_set_phase2_ca_cert (NMSetting8021x *setting,
priv->phase2_ca_cert = g_byte_array_free_to_bytes (data);
data = NULL;
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
priv->phase2_ca_cert = value_with_scheme (cert_path, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
priv->phase2_ca_cert = value_with_scheme (value, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
else
g_assert_not_reached ();
} else {
@ -1691,7 +1699,7 @@ nm_setting_802_1x_get_phase2_client_cert_uri (NMSetting8021x *setting)
/**
* nm_setting_802_1x_set_phase2_client_cert:
* @setting: the #NMSetting8021x
* @cert_path: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH
* @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH
* or %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the "phase2" client
* certificate file (PEM, DER, or PKCS#<!-- -->12 format). The path must be UTF-8
* encoded; use g_filename_to_utf8() to convert if needed. Passing %NULL with
@ -1713,7 +1721,7 @@ nm_setting_802_1x_get_phase2_client_cert_uri (NMSetting8021x *setting)
**/
gboolean
nm_setting_802_1x_set_phase2_client_cert (NMSetting8021x *setting,
const char *cert_path,
const char *value,
NMSetting8021xCKScheme scheme,
NMSetting8021xCKFormat *out_format,
GError **error)
@ -1724,10 +1732,11 @@ nm_setting_802_1x_set_phase2_client_cert (NMSetting8021x *setting,
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
if (cert_path) {
g_return_val_if_fail (g_utf8_validate (cert_path, -1, NULL), FALSE);
if (value) {
g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE);
g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
|| scheme == NM_SETTING_802_1X_CK_SCHEME_PATH,
|| scheme == NM_SETTING_802_1X_CK_SCHEME_PATH
|| scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11,
FALSE);
}
@ -1738,12 +1747,18 @@ nm_setting_802_1x_set_phase2_client_cert (NMSetting8021x *setting,
g_clear_pointer (&priv->phase2_client_cert, g_bytes_unref);
if (!cert_path) {
if (!value) {
g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
return TRUE;
}
data = load_and_verify_certificate (cert_path, scheme, &format, error);
if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) {
priv->phase2_client_cert = value_with_scheme (value, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11);
g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
return TRUE;
}
data = load_and_verify_certificate (value, scheme, &format, error);
if (data) {
gboolean valid = FALSE;
@ -1773,7 +1788,7 @@ nm_setting_802_1x_set_phase2_client_cert (NMSetting8021x *setting,
priv->phase2_client_cert = g_byte_array_free_to_bytes (data);
data = NULL;
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
priv->phase2_client_cert = value_with_scheme (cert_path, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
priv->phase2_client_cert = value_with_scheme (value, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
else
g_assert_not_reached ();
}
@ -2009,7 +2024,7 @@ file_to_secure_bytes (const char *filename)
/**
* nm_setting_802_1x_set_private_key:
* @setting: the #NMSetting8021x
* @key_path: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH or
* @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH or
* %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the private key file
* (PEM, DER, or PKCS#<!-- -->12 format). The path must be UTF-8 encoded; use
* g_filename_to_utf8() to convert if needed. Passing %NULL with any @scheme
@ -2356,7 +2371,7 @@ nm_setting_802_1x_get_phase2_private_key_uri (NMSetting8021x *setting)
/**
* nm_setting_802_1x_set_phase2_private_key:
* @setting: the #NMSetting8021x
* @key_path: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH or
* @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH or
* %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the "phase2" private
* key file (PEM, DER, or PKCS#<!-- -->12 format). The path must be UTF-8 encoded;
* use g_filename_to_utf8() to convert if needed. Passing %NULL with any
@ -2394,7 +2409,7 @@ nm_setting_802_1x_get_phase2_private_key_uri (NMSetting8021x *setting)
**/
gboolean
nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *setting,
const char *key_path,
const char *value,
const char *password,
NMSetting8021xCKScheme scheme,
NMSetting8021xCKFormat *out_format,
@ -2407,10 +2422,11 @@ nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *setting,
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
if (key_path) {
g_return_val_if_fail (g_utf8_validate (key_path, -1, NULL), FALSE);
if (value) {
g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE);
g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
|| scheme == NM_SETTING_802_1X_CK_SCHEME_PATH,
|| scheme == NM_SETTING_802_1X_CK_SCHEME_PATH
|| scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11,
FALSE);
}
@ -2420,8 +2436,8 @@ nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *setting,
/* Ensure the private key is a recognized format and if the password was
* given, that it decrypts the private key.
*/
if (key_path) {
format = crypto_verify_private_key (key_path, password, NULL, &local_err);
if (value && scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11) {
format = crypto_verify_private_key (value, password, NULL, &local_err);
if (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN) {
g_set_error_literal (error,
NM_CONNECTION_ERROR,
@ -2448,7 +2464,7 @@ nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *setting,
password_cleared = TRUE;
}
if (key_path == NULL) {
if (value == NULL) {
if (key_cleared)
g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
if (password_cleared)
@ -2460,17 +2476,18 @@ nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *setting,
if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
/* FIXME: potential race after verifying the private key above */
/* FIXME: ensure blob doesn't start with file:// */
priv->phase2_private_key = file_to_secure_bytes (key_path);
priv->phase2_private_key = file_to_secure_bytes (value);
g_assert (priv->phase2_private_key);
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
priv->phase2_private_key = value_with_scheme (key_path, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
priv->phase2_private_key = value_with_scheme (value, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11)
priv->phase2_private_key = value_with_scheme (value, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11);
else
g_assert_not_reached ();
/* As required by NM and wpa_supplicant, set the client-cert
* property to the same PKCS#12 data.
*/
g_assert (format != NM_CRYPTO_FILE_FORMAT_UNKNOWN);
if (format == NM_CRYPTO_FILE_FORMAT_PKCS12) {
if (priv->phase2_client_cert)
g_bytes_unref (priv->phase2_client_cert);