diff options
-rw-r--r-- | libnm-core/nm-utils.c | 78 | ||||
-rw-r--r-- | libnm-core/nm-utils.h | 2 | ||||
-rw-r--r-- | libnm-core/tests/certs/test-key-only-decrypted.pem | 27 | ||||
-rw-r--r-- | libnm-core/tests/test-crypto.c | 30 | ||||
-rw-r--r-- | libnm/libnm.ver | 2 |
5 files changed, 137 insertions, 2 deletions
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index dfa0d7cf81..a2c8cceb35 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -1888,17 +1888,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 + * 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 5dd3a84342..96bd340329 100644 --- a/libnm-core/nm-utils.h +++ b/libnm-core/nm-utils.h @@ -126,6 +126,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 cbca52c801..e5361f40d1 100644 --- a/libnm-core/tests/test-crypto.c +++ b/libnm-core/tests/test-crypto.c @@ -107,6 +107,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 * @@ -132,9 +134,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); @@ -176,6 +182,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); @@ -195,6 +203,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); @@ -229,6 +239,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); @@ -328,6 +340,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; @@ -416,6 +443,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 d735a30e38..445f063530 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -804,7 +804,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_hex2byte; nm_utils_hexstr2bin; nm_utils_hwaddr_atoba; |