libnm/crypto: fix loading certificates from file securely

file_to_secure_bytes() tried to load the file from disk and ensure that
the data will be cleared. It did so poorely, because g_file_get_contents()
cannot be used for that.

Add a helper function nm_crypto_read_file() to get this right.
This commit is contained in:
Thomas Haller
2018-08-30 15:38:47 +02:00
parent b5abc8a1d5
commit 2be0bb8287
3 changed files with 18 additions and 28 deletions

View File

@@ -359,6 +359,19 @@ file_read_contents (const char *filename,
error) >= 0; error) >= 0;
} }
GBytes *
nm_crypto_read_file (const char *filename,
GError **error)
{
nm_auto_clear_secret_ptr NMSecretPtr contents = { 0 };
g_return_val_if_fail (filename, NULL);
if (!file_read_contents (filename, &contents, error))
return NULL;
return nm_secret_copy_to_gbytes (contents.bin, contents.len);
}
/* /*
* Convert a hex string into bytes. * Convert a hex string into bytes.
*/ */

View File

@@ -51,6 +51,9 @@ typedef enum {
/*****************************************************************************/ /*****************************************************************************/
GBytes *nm_crypto_read_file (const char *filename,
GError **error);
gboolean nm_crypto_load_and_verify_certificate (const char *file, gboolean nm_crypto_load_and_verify_certificate (const char *file,
NMCryptoFileFormat *out_file_format, NMCryptoFileFormat *out_file_format,
GBytes **out_certificat, GBytes **out_certificat,

View File

@@ -2165,32 +2165,6 @@ nm_setting_802_1x_get_private_key_uri (NMSetting8021x *setting)
return (const char *)data; return (const char *)data;
} }
static void
free_secure_bytes (gpointer data)
{
GByteArray *array = data;
memset (array->data, 0, array->len);
g_byte_array_unref (array);
}
static GBytes *
file_to_secure_bytes (const char *filename)
{
char *contents;
GByteArray *array = NULL;
gsize length = 0;
if (g_file_get_contents (filename, &contents, &length, NULL)) {
array = g_byte_array_sized_new (length);
g_byte_array_append (array, (guint8 *) contents, length);
memset (contents, 0, length);
g_free (contents);
return g_bytes_new_with_free_func (array->data, array->len, free_secure_bytes, array);
}
return NULL;
}
/** /**
* nm_setting_802_1x_set_private_key: * nm_setting_802_1x_set_private_key:
* @setting: the #NMSetting8021x * @setting: the #NMSetting8021x
@@ -2295,7 +2269,7 @@ nm_setting_802_1x_set_private_key (NMSetting8021x *setting,
if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
/* FIXME: potential race after verifying the private key above */ /* FIXME: potential race after verifying the private key above */
/* FIXME: ensure blob doesn't start with file:// */ /* FIXME: ensure blob doesn't start with file:// */
priv->private_key = file_to_secure_bytes (value); priv->private_key = nm_crypto_read_file (value, NULL);
nm_assert (priv->private_key); nm_assert (priv->private_key);
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
priv->private_key = path_to_scheme_value (value); priv->private_key = path_to_scheme_value (value);
@@ -2637,7 +2611,7 @@ nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *setting,
if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
/* FIXME: potential race after verifying the private key above */ /* FIXME: potential race after verifying the private key above */
/* FIXME: ensure blob doesn't start with file:// */ /* FIXME: ensure blob doesn't start with file:// */
priv->phase2_private_key = file_to_secure_bytes (value); priv->phase2_private_key = nm_crypto_read_file (value, NULL);
nm_assert (priv->phase2_private_key); nm_assert (priv->phase2_private_key);
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
priv->phase2_private_key = path_to_scheme_value (value); priv->phase2_private_key = path_to_scheme_value (value);