summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libnm-core/nm-keyfile-reader.c276
1 files changed, 118 insertions, 158 deletions
diff --git a/libnm-core/nm-keyfile-reader.c b/libnm-core/nm-keyfile-reader.c
index 93258355e4..1e75cbf922 100644
--- a/libnm-core/nm-keyfile-reader.c
+++ b/libnm-core/nm-keyfile-reader.c
@@ -990,126 +990,6 @@ has_cert_ext (const char *path)
return FALSE;
}
-static gboolean
-handle_as_scheme (KeyfileReaderInfo *info, GBytes *bytes, NMSetting *setting, const char *key)
-{
- const char *bin;
- gsize bin_len;
- gsize bin_len0;
-
- bin = g_bytes_get_data (bytes, &bin_len);
-
- g_return_val_if_fail (bin && bin_len > 0, FALSE);
-
-#define HAS_SCHEME_PREFIX(bin, bin_len, scheme) \
- ({ \
- const char *const _bin = (bin); \
- const gsize _bin_len = (bin_len); \
- \
- nm_assert (_bin && _bin_len > 0); \
- \
- ( _bin_len > NM_STRLEN (scheme) + 1 \
- && _bin[_bin_len - 1] == '\0' \
- && memcmp (_bin, scheme, NM_STRLEN (scheme)) == 0); \
- })
-
- bin_len0 = bin_len - 1;
-
- /* It's the PATH scheme, can just set plain data.
- * In this case, @bin_len0 includes */
- if (HAS_SCHEME_PREFIX (bin, bin_len, NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)) {
- if (nm_setting_802_1x_check_cert_scheme (bin, bin_len0 + 1, NULL) == NM_SETTING_802_1X_CK_SCHEME_PATH) {
- const char *path2 = &bin[NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)];
- gs_free char *path2_free = NULL;
-
- if (path2[0] != '/') {
- /* we want to read absolute paths because we use keyfile as exchange
- * between different processes which might not have the same cwd. */
- path2 = path2_free = get_cert_path (info->base_dir, (const guint8 *) path2,
- bin_len0 - NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH));
- }
-
- g_object_set (setting, key, bytes, NULL);
- if (!g_file_test (path2, G_FILE_TEST_EXISTS)) {
- handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE,
- _("certificate or key file '%s' does not exist"),
- path2);
- }
- } else {
- handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
- _("invalid key/cert value path \"%s\""), bin);
- }
- return TRUE;
- }
-
- if (HAS_SCHEME_PREFIX (bin, bin_len, NM_KEYFILE_CERT_SCHEME_PREFIX_PKCS11)) {
- if (nm_setting_802_1x_check_cert_scheme (bin, bin_len0 + 1, NULL) == NM_SETTING_802_1X_CK_SCHEME_PKCS11) {
- g_object_set (setting, key, bytes, NULL);
- } else {
- handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
- _("invalid PKCS#11 URI \"%s\""), bin);
- }
- return TRUE;
- }
-
- if (HAS_SCHEME_PREFIX (bin, bin_len, NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB)) {
- const char *cdata = bin + NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB);
- gs_unref_bytes GBytes *bytes2 = NULL;
- gs_free guchar *bin_decoded = NULL;
- gsize i;
- gboolean valid_base64;
- gsize bin_decoded_len = 0;
-
- bin_len0 -= NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB);
-
- /* Let's be strict here. We expect valid base64, no funny stuff!!
- * We didn't write such invalid data ourselfes and refuse to read it as blob. */
- if ((valid_base64 = (bin_len0 % 4 == 0))) {
- for (i = 0; i < bin_len0; i++) {
- char c = cdata[i];
-
- if (!( (c >= 'a' && c <= 'z')
- || (c >= 'A' && c <= 'Z')
- || (c >= '0' && c <= '9')
- || (c == '+' || c == '/'))) {
- if (c != '=' || i < bin_len0 - 2)
- valid_base64 = FALSE;
- else {
- for (; i < bin_len0; i++) {
- if (cdata[i] != '=')
- valid_base64 = FALSE;
- }
- }
- break;
- }
- }
- }
- if (valid_base64)
- bin_decoded = g_base64_decode (cdata, &bin_decoded_len);
-
- if (bin_decoded_len == 0) {
- handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
- _("invalid key/cert value data:;base64, is not base64"));
- return TRUE;
- }
-
- if (nm_setting_802_1x_check_cert_scheme (bin_decoded, bin_decoded_len, NULL) != NM_SETTING_802_1X_CK_SCHEME_BLOB) {
- /* The blob probably starts with "file://". Setting the cert data will confuse NMSetting8021x.
- * In fact this is a limitation of NMSetting8021x which does not support setting blobs that start
- * with file://. Just warn and return TRUE to signal that we ~handled~ the setting. */
- handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
- _("invalid key/cert value data:;base64,file://"));
- return TRUE;
- }
-
- bytes2 = g_bytes_new_take (g_steal_pointer (&bin_decoded), bin_decoded_len);
- g_object_set (setting, key, bytes2, NULL);
- return TRUE;
- }
-
- return FALSE;
-}
-
char *
nm_keyfile_detect_unqualified_path_scheme (const char *base_dir,
gconstpointer pdata,
@@ -1184,38 +1064,17 @@ out:
return path;
}
-static gboolean
-handle_as_path (KeyfileReaderInfo *info,
- GBytes *bytes,
- NMSetting *setting,
- const char *key)
-{
- const guint8 *data;
- gsize data_len;
- char *path;
- gboolean exists = FALSE;
-
- data = g_bytes_get_data (bytes, &data_len);
-
- path = nm_keyfile_detect_unqualified_path_scheme (info->base_dir, data, data_len, TRUE, &exists);
- if (path) {
- gs_unref_bytes GBytes *val = NULL;
-
- /* Construct the proper value as required for the PATH scheme */
- val = g_bytes_new_take (path, strlen (path) + 1);
- g_object_set (setting, key, val, NULL);
-
- /* Warn if the certificate didn't exist */
- if (!exists) {
- handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE,
- _("certificate or key file '%s' does not exist"),
- path);
- }
- return TRUE;
- }
-
- return FALSE;
-}
+#define HAS_SCHEME_PREFIX(bin, bin_len, scheme) \
+ ({ \
+ const char *const _bin = (bin); \
+ const gsize _bin_len = (bin_len); \
+ \
+ nm_assert (_bin && _bin_len > 0); \
+ \
+ ( _bin_len > NM_STRLEN (scheme) + 1 \
+ && _bin[_bin_len - 1] == '\0' \
+ && memcmp (_bin, scheme, NM_STRLEN (scheme)) == 0); \
+ })
static void
cert_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
@@ -1224,6 +1083,8 @@ cert_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
gs_unref_bytes GBytes *bytes = NULL;
const char *bin = NULL;
gsize bin_len = 0;
+ char *path;
+ gboolean path_exists;
bytes = get_bytes (info, setting_name, key, TRUE, FALSE);
if (bytes)
@@ -1236,17 +1097,116 @@ cert_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
return;
}
- /* Try as a path + scheme (ie, starts with "file://") */
- if (handle_as_scheme (info, bytes, setting, key))
+ if (HAS_SCHEME_PREFIX (bin, bin_len, NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)) {
+ const char *path2 = &bin[NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)];
+ gs_free char *path2_free = NULL;
+
+ if (nm_setting_802_1x_check_cert_scheme (bin, bin_len, NULL) != NM_SETTING_802_1X_CK_SCHEME_PATH) {
+ handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
+ _("invalid key/cert value path \"%s\""), bin);
+ return;
+ }
+
+ g_object_set (setting, key, bytes, NULL);
+
+ if (path2[0] != '/') {
+ /* we want to read absolute paths because we use keyfile as exchange
+ * between different processes which might not have the same cwd. */
+ path2_free = get_cert_path (info->base_dir, (const guint8 *) path2,
+ bin_len - NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH) - 1);
+ path2 = path2_free;
+ }
+
+ if (!g_file_test (path2, G_FILE_TEST_EXISTS)) {
+ handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE,
+ _("certificate or key file '%s' does not exist"),
+ path2);
+ }
return;
- if (info->error)
+ }
+
+ if (HAS_SCHEME_PREFIX (bin, bin_len, NM_KEYFILE_CERT_SCHEME_PREFIX_PKCS11)) {
+ if (nm_setting_802_1x_check_cert_scheme (bin, bin_len, NULL) != NM_SETTING_802_1X_CK_SCHEME_PKCS11) {
+ handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
+ _("invalid PKCS#11 URI \"%s\""), bin);
+ return;
+ }
+
+ g_object_set (setting, key, bytes, NULL);
return;
+ }
- /* If not, it might be a plain path */
- if (handle_as_path (info, bytes, setting, key))
+ if (HAS_SCHEME_PREFIX (bin, bin_len, NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB)) {
+ const char *cdata = bin + NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB);
+ gsize cdata_len = bin_len - NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB) - 1;
+ gs_free guchar *bin_decoded = NULL;
+ gsize bin_decoded_len = 0;
+ gsize i;
+ gboolean valid_base64;
+ gs_unref_bytes GBytes *val = NULL;
+
+ /* Let's be strict here. We expect valid base64, no funny stuff!!
+ * We didn't write such invalid data ourselfes and refuse to read it as blob. */
+ if ((valid_base64 = (cdata_len % 4 == 0))) {
+ for (i = 0; i < cdata_len; i++) {
+ char c = cdata[i];
+
+ if (!( (c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= '0' && c <= '9')
+ || (c == '+' || c == '/'))) {
+ if (c != '=' || i < cdata_len - 2)
+ valid_base64 = FALSE;
+ else {
+ for (; i < cdata_len; i++) {
+ if (cdata[i] != '=')
+ valid_base64 = FALSE;
+ }
+ }
+ break;
+ }
+ }
+ }
+ if (valid_base64)
+ bin_decoded = g_base64_decode (cdata, &bin_decoded_len);
+
+ if (bin_decoded_len == 0) {
+ handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
+ _("invalid key/cert value data:;base64, is not base64"));
+ return;
+ }
+
+ if (nm_setting_802_1x_check_cert_scheme (bin_decoded, bin_decoded_len, NULL) != NM_SETTING_802_1X_CK_SCHEME_BLOB) {
+ /* The blob probably starts with "file://". Setting the cert data will confuse NMSetting8021x.
+ * In fact this is a limitation of NMSetting8021x which does not support setting blobs that start
+ * with file://. Just warn and return TRUE to signal that we ~handled~ the setting. */
+ handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
+ _("invalid key/cert value data:;base64,file://"));
+ return;
+ }
+
+ val = g_bytes_new_take (g_steal_pointer (&bin_decoded), bin_decoded_len);
+ g_object_set (setting, key, val, NULL);
return;
- if (info->error)
+ }
+
+ /* If not, it might be a plain path */
+ path = nm_keyfile_detect_unqualified_path_scheme (info->base_dir, bin, bin_len, TRUE, &path_exists);
+ if (path) {
+ gs_unref_bytes GBytes *val = NULL;
+
+ /* Construct the proper value as required for the PATH scheme */
+ val = g_bytes_new_take (path, strlen (path) + 1);
+ g_object_set (setting, key, val, NULL);
+
+ /* Warn if the certificate didn't exist */
+ if (!path_exists) {
+ handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE,
+ _("certificate or key file '%s' does not exist"),
+ path);
+ }
return;
+ }
if (nm_setting_802_1x_check_cert_scheme (bin, bin_len, NULL) != NM_SETTING_802_1X_CK_SCHEME_BLOB) {
/* The blob probably starts with "file://" but contains invalid characters for a path.