summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Winship <danw@gnome.org>2014-10-30 11:15:44 -0400
committerDan Winship <danw@redhat.com>2014-11-21 08:46:07 -0500
commit1c4f41c61013d79a32eeac246d204c2f378e6915 (patch)
tree2066f0d46a8bdae01684cdb3db3a03283e082a3f
parent7c74e71e9133f3d9c5d55cf7156340d0f7857e3a (diff)
downloadNetworkManager-1c4f41c61013d79a32eeac246d204c2f378e6915.tar.gz
libnm-core: add nm_utils_file_is_certificate() and _file_is_private_key()
Add nm-utils methods to check if a file is a certificate or private key file. nm-applet currently has its own internal versions of these, but they ended up having to duplicate a bunch of logic that we already have in crypto.c.
-rw-r--r--libnm-core/nm-utils.c76
-rw-r--r--libnm-core/nm-utils.h2
-rw-r--r--libnm-core/tests/certs/test-key-only-decrypted.pem27
-rw-r--r--libnm-core/tests/test-crypto.c30
-rw-r--r--libnm/libnm.ver2
5 files changed, 136 insertions, 1 deletions
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
index a6bf2f9e3e..d91de32141 100644
--- a/libnm-core/nm-utils.c
+++ b/libnm-core/nm-utils.c
@@ -2236,17 +2236,91 @@ nm_utils_rsa_key_encrypt_aes (const guint8 *data,
error);
}
+static gboolean
+file_has_extension (const char *filename, const char *extensions[])
+{
+ const char *ext;
+ int i;
+
+ ext = strrchr (filename, '.');
+ if (!ext)
+ return FALSE;
+
+ for (i = 0; extensions[i]; i++) {
+ if (!g_ascii_strcasecmp (ext, extensions[i]))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * nm_utils_file_is_certificate:
+ * @filename: name of the file to test
+ *
+ * Tests if @filename has a valid extension for an X.509 certificate file
+ * (".cer", ".crt", ".der", or ".pem"), and contains a certificate in a format
+ * recognized by NetworkManager.
+ *
+ * Returns: %TRUE if the file is a certificate, %FALSE if it is not
+ **/
+gboolean
+nm_utils_file_is_certificate (const char *filename)
+{
+ const char *extensions[] = { ".der", ".pem", ".crt", ".cer", NULL };
+ NMCryptoFileFormat file_format;
+ GByteArray *cert;
+
+ g_return_val_if_fail (filename != NULL, FALSE);
+
+ if (!file_has_extension (filename, extensions))
+ return FALSE;
+
+ cert = crypto_load_and_verify_certificate (filename, &file_format, NULL);
+ if (cert)
+ g_byte_array_unref (cert);
+
+ return file_format = NM_CRYPTO_FILE_FORMAT_X509;
+}
+
+/**
+ * nm_utils_file_is_private_key:
+ * @filename: name of the file to test
+ * @out_encrypted: (out): on return, whether the file is encrypted
+ *
+ * Tests if @filename has a valid extension for an X.509 private key file
+ * (".der", ".key", ".pem", or ".p12"), and contains a private key in a format
+ * recognized by NetworkManager.
+ *
+ * Returns: %TRUE if the file is a private key, %FALSE if it is not
+ **/
+gboolean
+nm_utils_file_is_private_key (const char *filename, gboolean *out_encrypted)
+{
+ const char *extensions[] = { ".der", ".pem", ".p12", ".key", NULL };
+
+ g_return_val_if_fail (filename != NULL, FALSE);
+ g_return_val_if_fail (out_encrypted == NULL || *out_encrypted == FALSE, FALSE);
+
+ if (!file_has_extension (filename, extensions))
+ return FALSE;
+
+ return crypto_verify_private_key (filename, NULL, out_encrypted, NULL) != NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+}
+
/**
* nm_utils_file_is_pkcs12:
* @filename: name of the file to test
*
- * Utility function to find out if the @filename is in PKCS#<!-- -->12 format.
+ * Tests if @filename is a PKCS#<!-- -->12 file.
*
* Returns: %TRUE if the file is PKCS#<!-- -->12, %FALSE if it is not
**/
gboolean
nm_utils_file_is_pkcs12 (const char *filename)
{
+ g_return_val_if_fail (filename != NULL, FALSE);
+
return crypto_is_pkcs12_file (filename, NULL);
}
diff --git a/libnm-core/nm-utils.h b/libnm-core/nm-utils.h
index a4253927be..dcfae00e09 100644
--- a/libnm-core/nm-utils.h
+++ b/libnm-core/nm-utils.h
@@ -137,6 +137,8 @@ GByteArray *nm_utils_rsa_key_encrypt_aes (const guint8 *data,
const char *in_password,
char **out_password,
GError **error);
+gboolean nm_utils_file_is_certificate (const char *filename);
+gboolean nm_utils_file_is_private_key (const char *filename, gboolean *out_encrypted);
gboolean nm_utils_file_is_pkcs12 (const char *filename);
guint32 nm_utils_wifi_freq_to_channel (guint32 freq);
diff --git a/libnm-core/tests/certs/test-key-only-decrypted.pem b/libnm-core/tests/certs/test-key-only-decrypted.pem
new file mode 100644
index 0000000000..1a25da5e7d
--- /dev/null
+++ b/libnm-core/tests/certs/test-key-only-decrypted.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAztLp+/SkzmaHzIst0sO4+r7qUwiVnidKBHgxoTbS5UL1dvck
+cbjTEP23V4ZoKQIb6ZMrr8B+PVgWNBAlhX4oLUL8NH/WTwrntrlAUcjliWDNc1Fj
+Z+FZNjFe0IdLXZeKQiLTQvKDYnmERVvYIJfi0TQjXuy/ikF8rYBQ85scUV3kKRzB
+xnyhAHAP9nl3AyL1S6t2yiCr4U5TbIZo6dYPbpVLtbXP02zUc9vAPR0gIHKrPiW7
+P81fLXf91wuo6wxzwD90JxdWzzGaqe3BOSfHqul3SPRtVok1XHlb9i+Mn5O8ExzQ
+dF8wGxVDcY7/Gt9lZWnCilqrBEqA3iApjUgcgwIDAQABAoIBAQC77HCmepf04ryp
+Yhz00NoXG7mWUMqBtXlPrlaKAWKG5dxbiBwZKLK/UYlxgbLK8BuklBCx1Nnfq1Yh
+YDp3nTWsSp0WpsF3eJUqNhD3Pu8xcD+9dEo6bUu+LgXUu9oC5Fq/1RzYS7qNk5RX
+4Sf0FY4GQLWS3tL7MJ20mE71yg5k7qRbDydOyhTh1m1CpRYONWxSsWVLM8KGRDJp
+iF0cdPfD5yoPFpgDk8gwzrnXJH2Wqzv8GvyYykRK5AW7tE50y0rTAM42WZ7YS6aZ
+FNMmtYxeyzXLY3LgPP0uko5anz3OXRcqCfHfFANG0y7B9MehbrjMgI6S1BbzFl07
+V1zVQVqhAoGBAPIfrWMlh1fHlRh4iRGXK2Hvxyv2oNz9KvQ4qRaLV9ejRDzdt7Pi
+/utbi5LGBuDw9016nXM3I77b6PukHzsHFnWGRnyRSbkMMt6mE17nggmNqcpFWfE8
+E7HcKMhk4gbuo5AHD3Ee1Gac2AUDnzYiE+sS6WI3O9d77cc5ych5jZ+nAoGBANqt
+VZCttjY0E+hEyTP37eaE8u0jfdK8AflTJlNUHWKXglES525iu8I/Bso8KaQYsYF3
+SezGRd3KQepQhtMjFKfSpF+tbnboP57Y3XGo8xhbxqV4kRX+XGsVoW3Vg2nPKBrR
++dIY5nMwua+gkHWp9RDcemD2reiIZBVx95fK8dfFAoGAdCSH2pBs/MlrFqLzNTHr
+iH4pb0hN39O9YAsx6POMfo79s6izbyHLIID4Ub6WHB7ashrIHjVr+yin+NXAeWMr
+/dIcS7Kxx4c3e5/0mMi6kvSWZsWfoF0uIVo3YfEqjyK36OXKHXwpbNN9t+IF5ESy
+g0e+FfPiy7nR1Ig+5+CO8+8CgYEAp/75+Ug677FaidouaMpT7gC9UAkwJLFjItQK
+YYIBgTi8WOSY/2jCrhwVb1CA/RwrYjbuiARasGUt9oEe0x3kRHnC5e4rKxaJqdMZ
+bLRK7a+0EHNrouXiwjG/7s1VQ/ht6wzdS9btVBlezdogoQSMzQNU0SExwa7mlMMV
+X3v+B7ECgYAK+Yt4jnLH1LNWoDTU0Ug5hyXsQXV8lVBSnrkvS7GtP6ZA/4OqG7lJ
+/bTYFZGoiAGzOnC+YlAqSIu45CEnpr2xBsThQiWUVxspmQD1lEWWFcd77DPUwn3C
+59pLgx0AqJE3n6lBOwehiXbFKBdVzX8PfPZpuCK6qc/RiTILktwURA==
+-----END RSA PRIVATE KEY-----
diff --git a/libnm-core/tests/test-crypto.c b/libnm-core/tests/test-crypto.c
index c159cc2057..b9e958d7b8 100644
--- a/libnm-core/tests/test-crypto.c
+++ b/libnm-core/tests/test-crypto.c
@@ -109,6 +109,8 @@ test_cert (gconstpointer test_data)
g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_X509);
g_byte_array_free (array, TRUE);
+
+ g_assert (nm_utils_file_is_certificate (path));
}
static GByteArray *
@@ -134,9 +136,13 @@ test_load_private_key (const char *path,
int expected_error)
{
NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN;
+ gboolean is_encrypted = FALSE;
GByteArray *array, *decrypted;
GError *error = NULL;
+ g_assert (nm_utils_file_is_private_key (path, &is_encrypted));
+ g_assert (is_encrypted);
+
array = crypto_decrypt_openssl_private_key (path, password, &key_type, &error);
/* Even if the password is wrong, we should determine the key type */
g_assert_cmpint (key_type, ==, NM_CRYPTO_KEY_TYPE_RSA);
@@ -178,6 +184,8 @@ test_load_pkcs12 (const char *path,
gboolean is_encrypted = FALSE;
GError *error = NULL;
+ g_assert (nm_utils_file_is_private_key (path, NULL));
+
format = crypto_verify_private_key (path, password, &is_encrypted, &error);
if (expected_error != -1) {
g_assert_error (error, NM_CRYPTO_ERROR, expected_error);
@@ -197,6 +205,8 @@ test_load_pkcs12_no_password (const char *path)
gboolean is_encrypted = FALSE;
GError *error = NULL;
+ g_assert (nm_utils_file_is_private_key (path, NULL));
+
/* We should still get a valid returned crypto file format */
format = crypto_verify_private_key (path, NULL, &is_encrypted, &error);
g_assert_no_error (error);
@@ -231,6 +241,8 @@ test_load_pkcs8 (const char *path,
gboolean is_encrypted = FALSE;
GError *error = NULL;
+ g_assert (nm_utils_file_is_private_key (path, NULL));
+
format = crypto_verify_private_key (path, password, &is_encrypted, &error);
if (expected_error != -1) {
g_assert_error (error, NM_CRYPTO_ERROR, expected_error);
@@ -330,6 +342,21 @@ test_key (gconstpointer test_data)
}
static void
+test_key_decrypted (gconstpointer test_data)
+{
+ const char *file = (const char *) test_data;
+ gboolean is_encrypted = FALSE;
+ char *path;
+
+ path = g_build_filename (TEST_CERT_DIR, file, NULL);
+
+ g_assert (nm_utils_file_is_private_key (path, &is_encrypted));
+ g_assert (!is_encrypted);
+
+ g_free (path);
+}
+
+static void
test_pkcs12 (gconstpointer test_data)
{
char **parts, *path, *password;
@@ -418,6 +445,9 @@ main (int argc, char **argv)
g_test_add_data_func ("/libnm/crypto/key/aes",
"test-aes-key.pem, test-aes-password",
test_key);
+ g_test_add_data_func ("/libnm/crypto/key/decrypted",
+ "test-key-only-decrypted.pem",
+ test_key_decrypted);
g_test_add_data_func ("/libnm/crypto/PKCS#12/1",
"test-cert.p12, test",
diff --git a/libnm/libnm.ver b/libnm/libnm.ver
index ae28e58e3e..f8baca50f8 100644
--- a/libnm/libnm.ver
+++ b/libnm/libnm.ver
@@ -756,7 +756,9 @@ global:
nm_utils_check_virtual_device_compatibility;
nm_utils_deinit;
nm_utils_escape_ssid;
+ nm_utils_file_is_certificate;
nm_utils_file_is_pkcs12;
+ nm_utils_file_is_private_key;
nm_utils_hexstr2bin;
nm_utils_hwaddr_atoba;
nm_utils_hwaddr_aton;