summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-08-30 15:38:47 +0200
committerThomas Haller <thaller@redhat.com>2018-09-03 18:07:59 +0200
commit50de8501425701745ba6765a439accad8c9f1ec2 (patch)
treed6fc9a0befd1985bd1f867d73cd316eff9589385
parentb5932892d57413ec2c496c981b70b7ccf5272491 (diff)
downloadNetworkManager-50de8501425701745ba6765a439accad8c9f1ec2.tar.gz
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.
-rw-r--r--libnm-core/nm-crypto.c13
-rw-r--r--libnm-core/nm-crypto.h3
-rw-r--r--libnm-core/nm-setting-8021x.c30
3 files changed, 18 insertions, 28 deletions
diff --git a/libnm-core/nm-crypto.c b/libnm-core/nm-crypto.c
index e1235ccbbe..776a6d6858 100644
--- a/libnm-core/nm-crypto.c
+++ b/libnm-core/nm-crypto.c
@@ -359,6 +359,19 @@ file_read_contents (const char *filename,
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.
*/
diff --git a/libnm-core/nm-crypto.h b/libnm-core/nm-crypto.h
index 1b9e039484..59c2f7c3e1 100644
--- a/libnm-core/nm-crypto.h
+++ b/libnm-core/nm-crypto.h
@@ -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,
NMCryptoFileFormat *out_file_format,
GBytes **out_certificat,
diff --git a/libnm-core/nm-setting-8021x.c b/libnm-core/nm-setting-8021x.c
index 4fae2c64e6..7218e7e536 100644
--- a/libnm-core/nm-setting-8021x.c
+++ b/libnm-core/nm-setting-8021x.c
@@ -2165,32 +2165,6 @@ nm_setting_802_1x_get_private_key_uri (NMSetting8021x *setting)
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:
* @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) {
/* FIXME: potential race after verifying the private key above */
/* 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);
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
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) {
/* 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 (value);
+ priv->phase2_private_key = nm_crypto_read_file (value, NULL);
nm_assert (priv->phase2_private_key);
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
priv->phase2_private_key = path_to_scheme_value (value);