diff options
Diffstat (limited to 'libnm-util/nm-setting-8021x.c')
| -rw-r--r-- | libnm-util/nm-setting-8021x.c | 86 |
1 files changed, 56 insertions, 30 deletions
diff --git a/libnm-util/nm-setting-8021x.c b/libnm-util/nm-setting-8021x.c index 6d5268a1..678d70ab 100644 --- a/libnm-util/nm-setting-8021x.c +++ b/libnm-util/nm-setting-8021x.c @@ -33,6 +33,7 @@ #include "crypto.h" #include "nm-utils-private.h" #include "nm-setting-private.h" +#include "nm-macros-internal.h" /** * SECTION:nm-setting-8021x @@ -430,13 +431,52 @@ get_cert_scheme (GByteArray *array) if (!array || !array->len) return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; - if ( (array->len > strlen (SCHEME_PATH)) - && !memcmp (array->data, SCHEME_PATH, strlen (SCHEME_PATH))) - return NM_SETTING_802_1X_CK_SCHEME_PATH; + /* interpret the blob as PATH if it starts with "file://". */ + if ( array->len >= STRLEN (SCHEME_PATH) + && !memcmp (array->data, SCHEME_PATH, STRLEN (SCHEME_PATH))) { + /* But it must also be NUL terminated, contain at least + * one non-NUL character, and contain only one trailing NUL + * chracter. + * And ensure it's UTF-8 valid too so we can pass it through + * D-Bus and stuff like that. */ + if ( array->len > STRLEN (SCHEME_PATH) + 1 + && array->data[array->len - 1] == '\0' + && g_utf8_validate ((const char *) &array->data[STRLEN (SCHEME_PATH)], array->len - (STRLEN (SCHEME_PATH) + 1), NULL)) + return NM_SETTING_802_1X_CK_SCHEME_PATH; + return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; + } return NM_SETTING_802_1X_CK_SCHEME_BLOB; } +static GByteArray * +load_and_verify_certificate (const char *cert_path, + NMSetting8021xCKScheme scheme, + NMCryptoFileFormat *out_file_format, + GError **error) +{ + NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + GByteArray *array; + + array = crypto_load_and_verify_certificate (cert_path, &format, error); + + if (!array || !array->len || format == NM_CRYPTO_FILE_FORMAT_UNKNOWN) + format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { + /* If we load the file as blob, we must ensure that the binary data does not + * start with file://. NMSetting8021x cannot represent blobs that start with + * file://. + * If that's the case, coerce the format to UNKNOWN. The callers will take care + * of that and not set the blob. */ + if (get_cert_scheme (array) != NM_SETTING_802_1X_CK_SCHEME_BLOB) + format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + } + + if (out_file_format) + *out_file_format = format; + return array; +} + /** * nm_setting_802_1x_get_ca_cert_scheme: * @setting: the #NMSetting8021x @@ -511,14 +551,16 @@ static GByteArray * path_to_scheme_value (const char *path) { GByteArray *array; + gsize len; + + g_return_val_if_fail (path != NULL && path[0], NULL); - g_return_val_if_fail (path != NULL, NULL); + len = strlen (path); - /* Add the path scheme tag to the front, then the fielname */ - array = g_byte_array_sized_new (strlen (path) + strlen (SCHEME_PATH) + 1); - g_assert (array); + /* Add the path scheme tag to the front, then the filename */ + array = g_byte_array_sized_new (len + strlen (SCHEME_PATH) + 1); g_byte_array_append (array, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH)); - g_byte_array_append (array, (const guint8 *) path, strlen (path)); + g_byte_array_append (array, (const guint8 *) path, len); g_byte_array_append (array, (const guint8 *) "\0", 1); return array; } @@ -578,7 +620,7 @@ nm_setting_802_1x_set_ca_cert (NMSetting8021x *setting, return TRUE; } - data = crypto_load_and_verify_certificate (cert_path, &format, error); + data = load_and_verify_certificate (cert_path, scheme, &format, error); if (data) { /* wpa_supplicant can only use raw x509 CA certs */ if (format == NM_CRYPTO_FILE_FORMAT_X509) { @@ -894,7 +936,7 @@ nm_setting_802_1x_set_client_cert (NMSetting8021x *setting, return TRUE; } - data = crypto_load_and_verify_certificate (cert_path, &format, error); + data = load_and_verify_certificate (cert_path, scheme, &format, error); if (data) { gboolean valid = FALSE; @@ -1159,7 +1201,7 @@ nm_setting_802_1x_set_phase2_ca_cert (NMSetting8021x *setting, return TRUE; } - data = crypto_load_and_verify_certificate (cert_path, &format, error); + data = load_and_verify_certificate (cert_path, scheme, &format, error); if (data) { /* wpa_supplicant can only use raw x509 CA certs */ if (format == NM_CRYPTO_FILE_FORMAT_X509) { @@ -1479,7 +1521,7 @@ nm_setting_802_1x_set_phase2_client_cert (NMSetting8021x *setting, return TRUE; } - data = crypto_load_and_verify_certificate (cert_path, &format, error); + data = load_and_verify_certificate (cert_path, scheme, &format, error); if (data) { gboolean valid = FALSE; @@ -2604,25 +2646,9 @@ need_secrets (NMSetting *setting) static gboolean verify_cert (GByteArray *array, const char *prop_name, GError **error) { - if (!array) - return TRUE; - - switch (get_cert_scheme (array)) { - case NM_SETTING_802_1X_CK_SCHEME_BLOB: + if ( !array + || get_cert_scheme (array) != NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) return TRUE; - case NM_SETTING_802_1X_CK_SCHEME_PATH: - /* For path-based schemes, verify that the path is zero-terminated */ - if (array->data[array->len - 1] == '\0') { - /* And ensure it's UTF-8 valid too so we can pass it through - * D-Bus and stuff like that. - */ - if (g_utf8_validate ((const char *) (array->data + strlen (SCHEME_PATH)), -1, NULL)) - return TRUE; - } - break; - default: - break; - } g_set_error_literal (error, NM_SETTING_802_1X_ERROR, |