summary refs log tree commit diff
path: root/src/libnm-core-impl/nm-keyfile.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2022-05-04 15:35:24 +0200
committerMichael Biebl <biebl@debian.org>2022-05-04 15:35:24 +0200
commit9959fdb2e8ddd06f2161798ca0a39c77d67c652d (patch)
tree2ce24a336d2b1c5fd5dec3090db312eded6c78ba /src/libnm-core-impl/nm-keyfile.c
parent8c623dddbdebe354cb94bfc559a5371a14865317 (diff)
New upstream version 1.37.92 upstream/1.37.92
Diffstat (limited to 'src/libnm-core-impl/nm-keyfile.c')
-rw-r--r--src/libnm-core-impl/nm-keyfile.c759
1 files changed, 401 insertions, 358 deletions
diff --git a/src/libnm-core-impl/nm-keyfile.c b/src/libnm-core-impl/nm-keyfile.c
index dce53ae2..00fb8a33 100644
--- a/src/libnm-core-impl/nm-keyfile.c
+++ b/src/libnm-core-impl/nm-keyfile.c
@@ -115,12 +115,14 @@ _key_file_handler_data_init_write(NMKeyfileHandlerData *handler_data,
                                 &info->error);
 }
 
-_nm_printf(5, 6) static void _handle_warn(KeyfileReaderInfo    *info,
-                                          const char           *kf_key,
-                                          const char           *cur_property,
-                                          NMKeyfileWarnSeverity severity,
-                                          const char           *fmt,
-                                          ...)
+/*****************************************************************************/
+
+_nm_printf(5, 6) static void _read_handle_warn(KeyfileReaderInfo    *info,
+                                               const char           *kf_key,
+                                               const char           *cur_property,
+                                               NMKeyfileWarnSeverity severity,
+                                               const char           *fmt,
+                                               ...)
 {
     NMKeyfileHandlerData handler_data;
 
@@ -148,16 +150,75 @@ _nm_printf(5, 6) static void _handle_warn(KeyfileReaderInfo    *info,
     g_free(handler_data.warn.message);
 }
 
-#define handle_warn(arg_info, arg_kf_key, arg_property_name, arg_severity, ...)                  \
-    ({                                                                                           \
-        KeyfileReaderInfo *_info = (arg_info);                                                   \
-                                                                                                 \
-        nm_assert(!_info->error);                                                                \
-                                                                                                 \
-        if (_info->read_handler) {                                                               \
-            _handle_warn(_info, (arg_kf_key), (arg_property_name), (arg_severity), __VA_ARGS__); \
-        }                                                                                        \
-        _info->error == NULL;                                                                    \
+#define read_handle_warn(arg_info, arg_kf_key, arg_property_name, arg_severity, ...) \
+    ({                                                                               \
+        KeyfileReaderInfo *_info = (arg_info);                                       \
+                                                                                     \
+        nm_assert(!_info->error);                                                    \
+                                                                                     \
+        if (_info->read_handler) {                                                   \
+            _read_handle_warn(_info,                                                 \
+                              (arg_kf_key),                                          \
+                              (arg_property_name),                                   \
+                              (arg_severity),                                        \
+                              __VA_ARGS__);                                          \
+        }                                                                            \
+        _info->error == NULL;                                                        \
+    })
+
+/*****************************************************************************/
+
+_nm_printf(6, 7) static void _write_handle_warn(KeyfileWriterInfo    *info,
+                                                NMSetting            *setting,
+                                                const char           *kf_key,
+                                                const char           *cur_property,
+                                                NMKeyfileWarnSeverity severity,
+                                                const char           *fmt,
+                                                ...)
+{
+    NMKeyfileHandlerData handler_data;
+
+    _key_file_handler_data_init_write(&handler_data,
+                                      NM_KEYFILE_HANDLER_TYPE_WARN,
+                                      info,
+                                      nm_setting_get_name(setting),
+                                      cur_property,
+                                      setting,
+                                      kf_key);
+    handler_data.warn = (NMKeyfileHandlerDataWarn){
+        .severity = severity,
+        .message  = NULL,
+        .fmt      = fmt,
+    };
+
+    va_start(handler_data.warn.ap, fmt);
+
+    info->write_handler(info->connection,
+                        info->keyfile,
+                        NM_KEYFILE_HANDLER_TYPE_WARN,
+                        &handler_data,
+                        info->user_data);
+
+    va_end(handler_data.warn.ap);
+
+    g_free(handler_data.warn.message);
+}
+
+#define write_handle_warn(arg_info, arg_setting, arg_kf_key, arg_property_name, arg_severity, ...) \
+    ({                                                                                             \
+        KeyfileWriterInfo *_info = (arg_info);                                                     \
+                                                                                                   \
+        nm_assert(!_info->error);                                                                  \
+                                                                                                   \
+        if (_info->write_handler) {                                                                \
+            _write_handle_warn(_info,                                                              \
+                               (arg_setting),                                                      \
+                               (arg_kf_key),                                                       \
+                               (arg_property_name),                                                \
+                               (arg_severity),                                                     \
+                               __VA_ARGS__);                                                       \
+        }                                                                                          \
+        _info->error == NULL;                                                                      \
     })
 
 /*****************************************************************************/
@@ -264,11 +325,11 @@ get_one_int(KeyfileReaderInfo *info,
 
     if (!str || !str[0]) {
         if (info) {
-            handle_warn(info,
-                        kf_key,
-                        property_name,
-                        NM_KEYFILE_WARN_SEVERITY_WARN,
-                        _("ignoring missing number"));
+            read_handle_warn(info,
+                             kf_key,
+                             property_name,
+                             NM_KEYFILE_WARN_SEVERITY_WARN,
+                             _("ignoring missing number"));
         }
         return FALSE;
     }
@@ -276,12 +337,12 @@ get_one_int(KeyfileReaderInfo *info,
     tmp = _nm_utils_ascii_str_to_int64(str, 10, 0, max_val, -1);
     if (tmp == -1) {
         if (info) {
-            handle_warn(info,
-                        kf_key,
-                        property_name,
-                        NM_KEYFILE_WARN_SEVERITY_WARN,
-                        _("ignoring invalid number '%s'"),
-                        str);
+            read_handle_warn(info,
+                             kf_key,
+                             property_name,
+                             NM_KEYFILE_WARN_SEVERITY_WARN,
+                             _("ignoring invalid number '%s'"),
+                             str);
         }
         return FALSE;
     }
@@ -305,13 +366,13 @@ build_address(KeyfileReaderInfo *info,
 
     addr = nm_ip_address_new(family, address_str, plen, &error);
     if (!addr) {
-        handle_warn(info,
-                    kf_key,
-                    property_name,
-                    NM_KEYFILE_WARN_SEVERITY_WARN,
-                    _("ignoring invalid %s address: %s"),
-                    family == AF_INET ? "IPv4" : "IPv6",
-                    error->message);
+        read_handle_warn(info,
+                         kf_key,
+                         property_name,
+                         NM_KEYFILE_WARN_SEVERITY_WARN,
+                         _("ignoring invalid %s address: %s"),
+                         family == AF_INET ? "IPv4" : "IPv6",
+                         error->message);
         g_error_free(error);
     }
 
@@ -351,13 +412,13 @@ build_route(KeyfileReaderInfo *info,
                 metric      = u32;
                 gateway_str = NULL;
             } else {
-                handle_warn(info,
-                            kf_key,
-                            property_name,
-                            NM_KEYFILE_WARN_SEVERITY_WARN,
-                            _("ignoring invalid gateway '%s' for %s route"),
-                            gateway_str,
-                            family == AF_INET ? "IPv4" : "IPv6");
+                read_handle_warn(info,
+                                 kf_key,
+                                 property_name,
+                                 NM_KEYFILE_WARN_SEVERITY_WARN,
+                                 _("ignoring invalid gateway '%s' for %s route"),
+                                 gateway_str,
+                                 family == AF_INET ? "IPv4" : "IPv6");
                 return NULL;
             }
         }
@@ -373,13 +434,13 @@ build_route(KeyfileReaderInfo *info,
 
     route = nm_ip_route_new(family, dest_str, plen, gateway_str, metric, &error);
     if (!route) {
-        handle_warn(info,
-                    kf_key,
-                    property_name,
-                    NM_KEYFILE_WARN_SEVERITY_WARN,
-                    _("ignoring invalid %s route: %s"),
-                    family == AF_INET ? "IPv4" : "IPv6",
-                    error->message);
+        read_handle_warn(info,
+                         kf_key,
+                         property_name,
+                         NM_KEYFILE_WARN_SEVERITY_WARN,
+                         _("ignoring invalid %s route: %s"),
+                         family == AF_INET ? "IPv4" : "IPv6",
+                         error->message);
         g_error_free(error);
     }
 
@@ -551,15 +612,15 @@ read_one_ip_address_or_route(KeyfileReaderInfo *info,
     /* get address field */
     address_str = read_field(&current, &err_str, IP_ADDRESS_CHARS, DELIMITERS);
     if (err_str) {
-        handle_warn(info,
-                    kf_key,
-                    property_name,
-                    NM_KEYFILE_WARN_SEVERITY_WARN,
-                    _("unexpected character '%c' for address %s: '%s' (position %td)"),
-                    *err_str,
-                    kf_key,
-                    VALUE_ORIG(),
-                    err_str - current);
+        read_handle_warn(info,
+                         kf_key,
+                         property_name,
+                         NM_KEYFILE_WARN_SEVERITY_WARN,
+                         _("unexpected character '%c' for address %s: '%s' (position %td)"),
+                         *err_str,
+                         kf_key,
+                         VALUE_ORIG(),
+                         err_str - current);
         return NULL;
     }
     /* get prefix length field (skippable) */
@@ -567,30 +628,31 @@ read_one_ip_address_or_route(KeyfileReaderInfo *info,
     /* get gateway field */
     gateway_str = read_field(&current, &err_str, IP_ADDRESS_CHARS, DELIMITERS);
     if (err_str) {
-        handle_warn(info,
-                    kf_key,
-                    property_name,
-                    NM_KEYFILE_WARN_SEVERITY_WARN,
-                    _("unexpected character '%c' for %s: '%s' (position %td)"),
-                    *err_str,
-                    kf_key,
-                    VALUE_ORIG(),
-                    err_str - current);
+        read_handle_warn(info,
+                         kf_key,
+                         property_name,
+                         NM_KEYFILE_WARN_SEVERITY_WARN,
+                         _("unexpected character '%c' for %s: '%s' (position %td)"),
+                         *err_str,
+                         kf_key,
+                         VALUE_ORIG(),
+                         err_str - current);
         return NULL;
     }
     /* for routes, get metric */
     if (route) {
         metric_str = read_field(&current, &err_str, DIGITS, DELIMITERS);
         if (err_str) {
-            handle_warn(info,
-                        kf_key,
-                        property_name,
-                        NM_KEYFILE_WARN_SEVERITY_WARN,
-                        _("unexpected character '%c' in prefix length for %s: '%s' (position %td)"),
-                        *err_str,
-                        kf_key,
-                        VALUE_ORIG(),
-                        err_str - current);
+            read_handle_warn(
+                info,
+                kf_key,
+                property_name,
+                NM_KEYFILE_WARN_SEVERITY_WARN,
+                _("unexpected character '%c' in prefix length for %s: '%s' (position %td)"),
+                *err_str,
+                kf_key,
+                VALUE_ORIG(),
+                err_str - current);
             return NULL;
         }
     } else
@@ -599,23 +661,23 @@ read_one_ip_address_or_route(KeyfileReaderInfo *info,
         /* there is still some data */
         if (*current) {
             /* another field follows */
-            handle_warn(info,
-                        kf_key,
-                        property_name,
-                        NM_KEYFILE_WARN_SEVERITY_WARN,
-                        _("garbage at the end of value %s: '%s'"),
-                        kf_key,
-                        VALUE_ORIG());
-            return NULL;
-        } else {
-            /* semicolon at the end of input */
-            if (!handle_warn(info,
+            read_handle_warn(info,
                              kf_key,
                              property_name,
-                             NM_KEYFILE_WARN_SEVERITY_INFO,
-                             _("deprecated semicolon at the end of value %s: '%s'"),
+                             NM_KEYFILE_WARN_SEVERITY_WARN,
+                             _("garbage at the end of value %s: '%s'"),
                              kf_key,
-                             VALUE_ORIG()))
+                             VALUE_ORIG());
+            return NULL;
+        } else {
+            /* semicolon at the end of input */
+            if (!read_handle_warn(info,
+                                  kf_key,
+                                  property_name,
+                                  NM_KEYFILE_WARN_SEVERITY_INFO,
+                                  _("deprecated semicolon at the end of value %s: '%s'"),
+                                  kf_key,
+                                  VALUE_ORIG()))
                 return NULL;
         }
     }
@@ -628,26 +690,26 @@ read_one_ip_address_or_route(KeyfileReaderInfo *info,
         if (!get_one_int(info, kf_key, property_name, plen_str, ipv6 ? 128 : 32, &plen)) {
             plen = DEFAULT_PREFIX(route, ipv6);
             if (info->error
-                || !handle_warn(info,
-                                kf_key,
-                                property_name,
-                                NM_KEYFILE_WARN_SEVERITY_WARN,
-                                _("invalid prefix length for %s '%s', defaulting to %d"),
-                                kf_key,
-                                VALUE_ORIG(),
-                                plen))
+                || !read_handle_warn(info,
+                                     kf_key,
+                                     property_name,
+                                     NM_KEYFILE_WARN_SEVERITY_WARN,
+                                     _("invalid prefix length for %s '%s', defaulting to %d"),
+                                     kf_key,
+                                     VALUE_ORIG(),
+                                     plen))
                 return NULL;
         }
     } else {
         plen = DEFAULT_PREFIX(route, ipv6);
-        if (!handle_warn(info,
-                         kf_key,
-                         property_name,
-                         NM_KEYFILE_WARN_SEVERITY_WARN,
-                         _("missing prefix length for %s '%s', defaulting to %d"),
-                         kf_key,
-                         VALUE_ORIG(),
-                         plen))
+        if (!read_handle_warn(info,
+                              kf_key,
+                              property_name,
+                              NM_KEYFILE_WARN_SEVERITY_WARN,
+                              _("missing prefix length for %s '%s', defaulting to %d"),
+                              kf_key,
+                              VALUE_ORIG(),
+                              plen))
             return NULL;
     }
 
@@ -983,13 +1045,13 @@ ip_routing_rule_parser_full(KeyfileReaderInfo        *info,
             NULL,
             &local);
         if (!rule) {
-            if (!handle_warn(info,
-                             build_list[i_build_list].s_key,
-                             property_info->name,
-                             NM_KEYFILE_WARN_SEVERITY_WARN,
-                             _("invalid value for \"%s\": %s"),
-                             build_list[i_build_list].s_key,
-                             local->message))
+            if (!read_handle_warn(info,
+                                  build_list[i_build_list].s_key,
+                                  property_info->name,
+                                  NM_KEYFILE_WARN_SEVERITY_WARN,
+                                  _("invalid value for \"%s\": %s"),
+                                  build_list[i_build_list].s_key,
+                                  local->message))
                 return;
             continue;
         }
@@ -1061,13 +1123,13 @@ ip_dns_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key)
         NMIPAddr addr;
 
         if (inet_pton(addr_family, list[i], &addr) <= 0) {
-            if (!handle_warn(info,
-                             key,
-                             key,
-                             NM_KEYFILE_WARN_SEVERITY_WARN,
-                             _("ignoring invalid DNS server IPv%c address '%s'"),
-                             nm_utils_addr_family_to_char(addr_family),
-                             list[i])) {
+            if (!read_handle_warn(info,
+                                  key,
+                                  key,
+                                  NM_KEYFILE_WARN_SEVERITY_WARN,
+                                  _("ignoring invalid DNS server IPv%c address '%s'"),
+                                  nm_utils_addr_family_to_char(addr_family),
+                                  list[i])) {
                 do {
                     nm_clear_g_free(&list[i]);
                 } while (++i < length);
@@ -1098,13 +1160,13 @@ ip6_addr_gen_mode_parser(KeyfileReaderInfo *info, NMSetting *setting, const char
                                     s,
                                     (int *) &addr_gen_mode,
                                     NULL)) {
-            handle_warn(info,
-                        key,
-                        key,
-                        NM_KEYFILE_WARN_SEVERITY_WARN,
-                        _("invalid option '%s', use one of [%s]"),
-                        s,
-                        "eui64,stable-privacy");
+            read_handle_warn(info,
+                             key,
+                             key,
+                             NM_KEYFILE_WARN_SEVERITY_WARN,
+                             _("invalid option '%s', use one of [%s]"),
+                             s,
+                             "eui64,stable-privacy");
             return;
         }
     } else
@@ -1160,7 +1222,11 @@ mac_address_parser(KeyfileReaderInfo *info,
             goto good_addr_bin;
     }
 
-    handle_warn(info, key, key, NM_KEYFILE_WARN_SEVERITY_WARN, _("ignoring invalid MAC address"));
+    read_handle_warn(info,
+                     key,
+                     key,
+                     NM_KEYFILE_WARN_SEVERITY_WARN,
+                     _("ignoring invalid MAC address"));
     return;
 
 good_addr_bin:
@@ -1232,14 +1298,14 @@ read_hash_of_string(KeyfileReaderInfo *info,
                     gs_free_error GError *error = NULL;
 
                     if (!_nm_setting_bond_validate_option(name, value, &error)) {
-                        if (!handle_warn(info,
-                                         kf_key,
-                                         name,
-                                         NM_KEYFILE_WARN_SEVERITY_WARN,
-                                         _("ignoring invalid bond option %s%s%s = %s%s%s: %s"),
-                                         NM_PRINT_FMT_QUOTE_STRING(name),
-                                         NM_PRINT_FMT_QUOTE_STRING(value),
-                                         error->message))
+                        if (!read_handle_warn(info,
+                                              kf_key,
+                                              name,
+                                              NM_KEYFILE_WARN_SEVERITY_WARN,
+                                              _("ignoring invalid bond option %s%s%s = %s%s%s: %s"),
+                                              NM_PRINT_FMT_QUOTE_STRING(name),
+                                              NM_PRINT_FMT_QUOTE_STRING(value),
+                                              error->message))
                             return;
                     } else
                         nm_setting_bond_add_option(NM_SETTING_BOND(setting), name, value);
@@ -1426,7 +1492,7 @@ ssid_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key)
 
     bytes = get_bytes(info, setting_name, key, FALSE, TRUE);
     if (!bytes) {
-        handle_warn(info, key, key, NM_KEYFILE_WARN_SEVERITY_WARN, _("ignoring invalid SSID"));
+        read_handle_warn(info, key, key, NM_KEYFILE_WARN_SEVERITY_WARN, _("ignoring invalid SSID"));
         return;
     }
     g_object_set(setting, key, bytes, NULL);
@@ -1440,11 +1506,11 @@ password_raw_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key
 
     bytes = get_bytes(info, setting_name, key, FALSE, TRUE);
     if (!bytes) {
-        handle_warn(info,
-                    key,
-                    key,
-                    NM_KEYFILE_WARN_SEVERITY_WARN,
-                    _("ignoring invalid raw password"));
+        read_handle_warn(info,
+                         key,
+                         key,
+                         NM_KEYFILE_WARN_SEVERITY_WARN,
+                         _("ignoring invalid raw password"));
         return;
     }
     g_object_set(setting, key, bytes, NULL);
@@ -1585,7 +1651,11 @@ cert_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key)
         bin = g_bytes_get_data(bytes, &bin_len);
     if (bin_len == 0) {
         if (!info->error) {
-            handle_warn(info, key, key, NM_KEYFILE_WARN_SEVERITY_WARN, _("invalid key/cert value"));
+            read_handle_warn(info,
+                             key,
+                             key,
+                             NM_KEYFILE_WARN_SEVERITY_WARN,
+                             _("invalid key/cert value"));
         }
         return;
     }
@@ -1596,12 +1666,12 @@ cert_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key)
 
         if (nm_setting_802_1x_check_cert_scheme(bin, bin_len, NULL)
             != NM_SETTING_802_1X_CK_SCHEME_PATH) {
-            handle_warn(info,
-                        key,
-                        key,
-                        NM_KEYFILE_WARN_SEVERITY_WARN,
-                        _("invalid key/cert value path \"%s\""),
-                        bin);
+            read_handle_warn(info,
+                             key,
+                             key,
+                             NM_KEYFILE_WARN_SEVERITY_WARN,
+                             _("invalid key/cert value path \"%s\""),
+                             bin);
             return;
         }
 
@@ -1621,12 +1691,12 @@ cert_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key)
          * then by invoking a callback (and possibly keyfile settings plugin would
          * collect the file names to be checked and check them later). */
         if (!g_file_test(path2, G_FILE_TEST_EXISTS)) {
-            handle_warn(info,
-                        key,
-                        key,
-                        NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE,
-                        _("certificate or key file '%s' does not exist"),
-                        path2);
+            read_handle_warn(info,
+                             key,
+                             key,
+                             NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE,
+                             _("certificate or key file '%s' does not exist"),
+                             path2);
         }
         return;
     }
@@ -1634,12 +1704,12 @@ cert_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key)
     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,
-                        key,
-                        NM_KEYFILE_WARN_SEVERITY_WARN,
-                        _("invalid PKCS#11 URI \"%s\""),
-                        bin);
+            read_handle_warn(info,
+                             key,
+                             key,
+                             NM_KEYFILE_WARN_SEVERITY_WARN,
+                             _("invalid PKCS#11 URI \"%s\""),
+                             bin);
             return;
         }
 
@@ -1680,11 +1750,11 @@ cert_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key)
             bin_decoded = g_base64_decode(cdata, &bin_decoded_len);
 
         if (bin_decoded_len == 0) {
-            handle_warn(info,
-                        key,
-                        key,
-                        NM_KEYFILE_WARN_SEVERITY_WARN,
-                        _("invalid key/cert value data:;base64, is not base64"));
+            read_handle_warn(info,
+                             key,
+                             key,
+                             NM_KEYFILE_WARN_SEVERITY_WARN,
+                             _("invalid key/cert value data:;base64, is not base64"));
             return;
         }
 
@@ -1693,11 +1763,11 @@ cert_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key)
             /* 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,
-                        key,
-                        NM_KEYFILE_WARN_SEVERITY_WARN,
-                        _("invalid key/cert value data:;base64,file://"));
+            read_handle_warn(info,
+                             key,
+                             key,
+                             NM_KEYFILE_WARN_SEVERITY_WARN,
+                             _("invalid key/cert value data:;base64,file://"));
             return;
         }
 
@@ -1718,12 +1788,12 @@ cert_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key)
 
         /* Warn if the certificate didn't exist */
         if (!path_exists) {
-            handle_warn(info,
-                        key,
-                        key,
-                        NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE,
-                        _("certificate or key file '%s' does not exist"),
-                        path);
+            read_handle_warn(info,
+                             key,
+                             key,
+                             NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE,
+                             _("certificate or key file '%s' does not exist"),
+                             path);
         }
         return;
     }
@@ -1734,11 +1804,11 @@ cert_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key)
          * Setting the cert data will confuse NMSetting8021x.
          * In fact, NMSetting8021x does not support setting such binary data, so just warn and
          * continue. */
-        handle_warn(info,
-                    key,
-                    key,
-                    NM_KEYFILE_WARN_SEVERITY_WARN,
-                    _("invalid key/cert value is not a valid blob"));
+        read_handle_warn(info,
+                         key,
+                         key,
+                         NM_KEYFILE_WARN_SEVERITY_WARN,
+                         _("invalid key/cert value is not a valid blob"));
         return;
     }
 
@@ -1836,12 +1906,12 @@ parity_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key)
         goto parity_good;
     }
 
-    handle_warn(info,
-                key,
-                key,
-                NM_KEYFILE_WARN_SEVERITY_WARN,
-                _("invalid parity value '%s'"),
-                tmp_str ?: "");
+    read_handle_warn(info,
+                     key,
+                     key,
+                     NM_KEYFILE_WARN_SEVERITY_WARN,
+                     _("invalid parity value '%s'"),
+                     tmp_str ?: "");
     return;
 
 parity_good:
@@ -1858,12 +1928,12 @@ out_err:
         /* ignore such errors. The key is not present. */
         return;
     }
-    handle_warn(info,
-                key,
-                key,
-                NM_KEYFILE_WARN_SEVERITY_WARN,
-                _("invalid setting: %s"),
-                err->message);
+    read_handle_warn(info,
+                     key,
+                     key,
+                     NM_KEYFILE_WARN_SEVERITY_WARN,
+                     _("invalid setting: %s"),
+                     err->message);
 }
 
 static void
@@ -1878,12 +1948,12 @@ team_config_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key)
     g_object_set(G_OBJECT(setting), key, conf, NULL);
 
     if (conf && !nm_setting_verify(setting, NULL, &error)) {
-        handle_warn(info,
-                    key,
-                    key,
-                    NM_KEYFILE_WARN_SEVERITY_WARN,
-                    _("ignoring invalid team configuration: %s"),
-                    error->message);
+        read_handle_warn(info,
+                         key,
+                         key,
+                         NM_KEYFILE_WARN_SEVERITY_WARN,
+                         _("ignoring invalid team configuration: %s"),
+                         error->message);
         g_object_set(G_OBJECT(setting), key, NULL, NULL);
     }
 }
@@ -1909,12 +1979,12 @@ bridge_vlan_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key)
         for (iter = strv; *iter; iter++) {
             vlan = nm_bridge_vlan_from_str(*iter, &local);
             if (!vlan) {
-                handle_warn(info,
-                            key,
-                            key,
-                            NM_KEYFILE_WARN_SEVERITY_WARN,
-                            "invalid bridge VLAN: %s",
-                            local->message);
+                read_handle_warn(info,
+                                 key,
+                                 key,
+                                 NM_KEYFILE_WARN_SEVERITY_WARN,
+                                 "invalid bridge VLAN: %s",
+                                 local->message);
                 g_clear_error(&local);
                 continue;
             }
@@ -1961,12 +2031,12 @@ qdisc_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key)
 
         qdisc = nm_utils_tc_qdisc_from_str(qdisc_str, &err);
         if (!qdisc) {
-            handle_warn(info,
-                        keys[i],
-                        key,
-                        NM_KEYFILE_WARN_SEVERITY_WARN,
-                        _("invalid qdisc: %s"),
-                        err->message);
+            read_handle_warn(info,
+                             keys[i],
+                             key,
+                             NM_KEYFILE_WARN_SEVERITY_WARN,
+                             _("invalid qdisc: %s"),
+                             err->message);
         } else {
             g_ptr_array_add(qdiscs, qdisc);
         }
@@ -2011,12 +2081,12 @@ tfilter_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key)
 
         tfilter = nm_utils_tc_tfilter_from_str(tfilter_str, &err);
         if (!tfilter) {
-            handle_warn(info,
-                        keys[i],
-                        key,
-                        NM_KEYFILE_WARN_SEVERITY_WARN,
-                        _("invalid tfilter: %s"),
-                        err->message);
+            read_handle_warn(info,
+                             keys[i],
+                             key,
+                             NM_KEYFILE_WARN_SEVERITY_WARN,
+                             _("invalid tfilter: %s"),
+                             err->message);
         } else {
             g_ptr_array_add(tfilters, tfilter);
         }
@@ -2689,16 +2759,10 @@ cert_writer_default(NMConnection                     *connection,
 static void
 cert_writer(KeyfileWriterInfo *info, NMSetting *setting, const char *key, const GValue *value)
 {
-    const NMSetting8021xSchemeVtable *vtable = NULL;
+    const NMSetting8021xSchemeVtable *vtable;
     const char                       *setting_name;
-    guint                             i;
 
-    for (i = 0; nm_setting_8021x_scheme_vtable[i].setting_key; i++) {
-        if (nm_streq0(nm_setting_8021x_scheme_vtable[i].setting_key, key)) {
-            vtable = &nm_setting_8021x_scheme_vtable[i];
-            break;
-        }
-    }
+    vtable = nm_setting_8021x_scheme_vtable_by_setting_key(key);
     if (!vtable)
         g_return_if_reached();
 
@@ -3181,12 +3245,12 @@ read_one_setting_value(KeyfileReaderInfo        *info,
         && !nm_keyfile_plugin_kf_has_key(keyfile, setting_info->setting_name, key, &err)) {
         /* Key doesn't exist or an error occurred, thus nothing to do. */
         if (err) {
-            if (!handle_warn(info,
-                             key,
-                             key,
-                             NM_KEYFILE_WARN_SEVERITY_WARN,
-                             _("error loading setting value: %s"),
-                             err->message))
+            if (!read_handle_warn(info,
+                                  key,
+                                  key,
+                                  NM_KEYFILE_WARN_SEVERITY_WARN,
+                                  _("error loading setting value: %s"),
+                                  err->message))
                 return;
         }
         return;
@@ -3296,7 +3360,7 @@ read_one_setting_value(KeyfileReaderInfo        *info,
 
             if (val > 255u) {
                 if (!already_warned
-                    && !handle_warn(
+                    && !read_handle_warn(
                         info,
                         key,
                         key,
@@ -3356,12 +3420,12 @@ read_one_setting_value(KeyfileReaderInfo        *info,
         if (nm_keyfile_error_is_not_found(err)) {
             /* ignore such errors. The key is not present. */
         } else {
-            handle_warn(info,
-                        key,
-                        key,
-                        NM_KEYFILE_WARN_SEVERITY_WARN,
-                        _("invalid setting: %s"),
-                        err->message);
+            read_handle_warn(info,
+                             key,
+                             key,
+                             NM_KEYFILE_WARN_SEVERITY_WARN,
+                             _("invalid setting: %s"),
+                             err->message);
         }
     }
 }
@@ -3381,12 +3445,12 @@ _read_setting(KeyfileReaderInfo *info)
 
     type = nm_setting_lookup_type(alias);
     if (!type) {
-        handle_warn(info,
-                    NULL,
-                    NULL,
-                    NM_KEYFILE_WARN_SEVERITY_WARN,
-                    _("invalid setting name '%s'"),
-                    info->group);
+        read_handle_warn(info,
+                         NULL,
+                         NULL,
+                         NM_KEYFILE_WARN_SEVERITY_WARN,
+                         _("invalid setting name '%s'"),
+                         info->group);
         return;
     }
 
@@ -3428,13 +3492,13 @@ _read_setting(KeyfileReaderInfo *info)
                 variant_type =
                     sett_info->detail.gendata_info->get_variant_type(sett_info, key, &local);
                 if (!variant_type) {
-                    if (!handle_warn(info,
-                                     key,
-                                     NULL,
-                                     NM_KEYFILE_WARN_SEVERITY_WARN,
-                                     _("invalid key '%s.%s'"),
-                                     info->group,
-                                     key))
+                    if (!read_handle_warn(info,
+                                          key,
+                                          NULL,
+                                          NM_KEYFILE_WARN_SEVERITY_WARN,
+                                          _("invalid key '%s.%s'"),
+                                          info->group,
+                                          key))
                         break;
                     continue;
                 }
@@ -3444,13 +3508,13 @@ _read_setting(KeyfileReaderInfo *info)
 
                     v = g_key_file_get_boolean(info->keyfile, info->group, key, &local);
                     if (local) {
-                        if (!handle_warn(info,
-                                         key,
-                                         key,
-                                         NM_KEYFILE_WARN_SEVERITY_WARN,
-                                         _("key '%s.%s' is not boolean"),
-                                         info->group,
-                                         key))
+                        if (!read_handle_warn(info,
+                                              key,
+                                              key,
+                                              NM_KEYFILE_WARN_SEVERITY_WARN,
+                                              _("key '%s.%s' is not boolean"),
+                                              info->group,
+                                              key))
                             break;
                         continue;
                     }
@@ -3461,13 +3525,13 @@ _read_setting(KeyfileReaderInfo *info)
                     v = g_key_file_get_uint64(info->keyfile, info->group, key, &local);
 
                     if (local) {
-                        if (!handle_warn(info,
-                                         key,
-                                         key,
-                                         NM_KEYFILE_WARN_SEVERITY_WARN,
-                                         _("key '%s.%s' is not a uint32"),
-                                         info->group,
-                                         key))
+                        if (!read_handle_warn(info,
+                                              key,
+                                              key,
+                                              NM_KEYFILE_WARN_SEVERITY_WARN,
+                                              _("key '%s.%s' is not a uint32"),
+                                              info->group,
+                                              key))
                             break;
                         continue;
                     }
@@ -3518,12 +3582,12 @@ _read_setting_wireguard_peer(KeyfileReaderInfo *info)
         || !nm_streq0(str, cstr)) {
         /* the group name must be identical to the normalized(!) key, so that it
          * is uniquely identified. */
-        handle_warn(info,
-                    NULL,
-                    NM_SETTING_WIREGUARD_PEERS,
-                    NM_KEYFILE_WARN_SEVERITY_WARN,
-                    _("invalid peer public key in section '%s'"),
-                    info->group);
+        read_handle_warn(info,
+                         NULL,
+                         NM_SETTING_WIREGUARD_PEERS,
+                         NM_KEYFILE_WARN_SEVERITY_WARN,
+                         _("invalid peer public key in section '%s'"),
+                         info->group);
         return;
     }
     nm_wireguard_peer_set_public_key(peer, cstr, TRUE);
@@ -3533,13 +3597,13 @@ _read_setting_wireguard_peer(KeyfileReaderInfo *info)
     str = nm_keyfile_plugin_kf_get_string(info->keyfile, info->group, key, NULL);
     if (str) {
         if (!nm_wireguard_peer_set_preshared_key(peer, str, FALSE)) {
-            if (!handle_warn(info,
-                             key,
-                             NM_SETTING_WIREGUARD_PEERS,
-                             NM_KEYFILE_WARN_SEVERITY_WARN,
-                             _("key '%s.%s' is not a valid 256 bit key in base64 encoding"),
-                             info->group,
-                             key))
+            if (!read_handle_warn(info,
+                                  key,
+                                  NM_SETTING_WIREGUARD_PEERS,
+                                  NM_KEYFILE_WARN_SEVERITY_WARN,
+                                  _("key '%s.%s' is not a valid 256 bit key in base64 encoding"),
+                                  info->group,
+                                  key))
                 return;
         }
         nm_clear_g_free(&str);
@@ -3556,13 +3620,13 @@ _read_setting_wireguard_peer(KeyfileReaderInfo *info)
                                          NULL);
     if (errno != ENODATA) {
         if (i64 == -1 || !_nm_setting_secret_flags_valid(i64)) {
-            if (!handle_warn(info,
-                             key,
-                             NM_SETTING_WIREGUARD_PEERS,
-                             NM_KEYFILE_WARN_SEVERITY_WARN,
-                             _("key '%s.%s' is not a valid secret flag"),
-                             info->group,
-                             key))
+            if (!read_handle_warn(info,
+                                  key,
+                                  NM_SETTING_WIREGUARD_PEERS,
+                                  NM_KEYFILE_WARN_SEVERITY_WARN,
+                                  _("key '%s.%s' is not a valid secret flag"),
+                                  info->group,
+                                  key))
                 return;
         } else
             nm_wireguard_peer_set_preshared_key_flags(peer, i64);
@@ -3579,13 +3643,13 @@ _read_setting_wireguard_peer(KeyfileReaderInfo *info)
                                          NULL);
     if (errno != ENODATA) {
         if (i64 == -1) {
-            if (!handle_warn(info,
-                             key,
-                             NM_SETTING_WIREGUARD_PEERS,
-                             NM_KEYFILE_WARN_SEVERITY_WARN,
-                             _("key '%s.%s' is not a integer in range 0 to 2^32"),
-                             info->group,
-                             key))
+            if (!read_handle_warn(info,
+                                  key,
+                                  NM_SETTING_WIREGUARD_PEERS,
+                                  NM_KEYFILE_WARN_SEVERITY_WARN,
+                                  _("key '%s.%s' is not a integer in range 0 to 2^32"),
+                                  info->group,
+                                  key))
                 return;
         } else
             nm_wireguard_peer_set_persistent_keepalive(peer, i64);
@@ -3595,13 +3659,13 @@ _read_setting_wireguard_peer(KeyfileReaderInfo *info)
     str = nm_keyfile_plugin_kf_get_string(info->keyfile, info->group, key, NULL);
     if (str && str[0]) {
         if (!nm_wireguard_peer_set_endpoint(peer, str, FALSE)) {
-            if (!handle_warn(info,
-                             key,
-                             NM_SETTING_WIREGUARD_PEERS,
-                             NM_KEYFILE_WARN_SEVERITY_WARN,
-                             _("key '%s.%s' is not a valid endpoint"),
-                             info->group,
-                             key))
+            if (!read_handle_warn(info,
+                                  key,
+                                  NM_SETTING_WIREGUARD_PEERS,
+                                  NM_KEYFILE_WARN_SEVERITY_WARN,
+                                  _("key '%s.%s' is not a valid endpoint"),
+                                  info->group,
+                                  key))
                 return;
         }
     }
@@ -3621,13 +3685,13 @@ _read_setting_wireguard_peer(KeyfileReaderInfo *info)
             nm_wireguard_peer_append_allowed_ip(peer, sa[i], TRUE);
         }
         if (has_error) {
-            if (!handle_warn(info,
-                             key,
-                             NM_SETTING_WIREGUARD_PEERS,
-                             NM_KEYFILE_WARN_SEVERITY_WARN,
-                             _("key '%s.%s' has invalid allowed-ips"),
-                             info->group,
-                             key))
+            if (!read_handle_warn(info,
+                                  key,
+                                  NM_SETTING_WIREGUARD_PEERS,
+                                  NM_KEYFILE_WARN_SEVERITY_WARN,
+                                  _("key '%s.%s' has invalid allowed-ips"),
+                                  info->group,
+                                  key))
                 return;
         }
     }
@@ -3636,13 +3700,13 @@ _read_setting_wireguard_peer(KeyfileReaderInfo *info)
         return;
 
     if (!nm_wireguard_peer_is_valid(peer, TRUE, TRUE, &error)) {
-        handle_warn(info,
-                    NULL,
-                    NM_SETTING_WIREGUARD_PEERS,
-                    NM_KEYFILE_WARN_SEVERITY_WARN,
-                    _("peer '%s' is invalid: %s"),
-                    info->group,
-                    error->message);
+        read_handle_warn(info,
+                         NULL,
+                         NM_SETTING_WIREGUARD_PEERS,
+                         NM_KEYFILE_WARN_SEVERITY_WARN,
+                         _("peer '%s' is invalid: %s"),
+                         info->group,
+                         error->message);
         return;
     }
 
@@ -3855,29 +3919,24 @@ write_setting_value(KeyfileWriterInfo        *info,
 
     _parse_info_find(setting, key, &setting_info, NULL, &pip);
 
+    if (pip && pip->has_writer_full) {
+        pip->writer_full(info, setting_info, property_info, pip, setting);
+        return;
+    }
+
+    if (pip && pip->writer_skip)
+        return;
+
     if (!pip) {
         if (!setting_info) {
-            /* the setting type is unknown. That is highly unexpected
-             * (and as this is currently only called from NetworkManager
-             * daemon, not possible).
-             *
-             * Still, handle it gracefully, because later keyfile writer will become
-             * public API of libnm, where @setting is (untrusted) user input.
-             *
-             * Gracefully here just means: ignore the setting. */
+            /* the setting type is unknown. Handle this gracefully by
+             * ignoring the setting. */
             return;
         }
         if (!property_info->param_spec)
             return;
         if (nm_streq(key, NM_SETTING_NAME))
             return;
-    } else {
-        if (pip->has_writer_full) {
-            pip->writer_full(info, setting_info, property_info, pip, setting);
-            return;
-        }
-        if (pip->writer_skip)
-            return;
     }
 
     nm_assert(property_info->param_spec);
@@ -4089,8 +4148,10 @@ _write_setting_wireguard(NMSetting *setting, KeyfileWriterInfo *info)
  * @user_data: argument for @handler.
  * @error: the #GError in case writing fails.
  *
- * @connection must verify as a valid profile according to
- * nm_connection_verify().
+ * @connection should verify as a valid profile according to
+ * nm_connection_verify(). If it does not verify, the keyfile may
+ * be incomplete and the parser may not be able to fully recreate
+ * the original profile.
  *
  * Returns: (transfer full): a new #GKeyFile or %NULL on error.
  *
@@ -4104,7 +4165,6 @@ nm_keyfile_write(NMConnection         *connection,
                  GError              **error)
 {
     nm_auto_unref_keyfile GKeyFile *keyfile = NULL;
-    GError                         *local   = NULL;
     KeyfileWriterInfo               info;
     NMSetting                     **settings;
     int                             i;
@@ -4114,28 +4174,6 @@ nm_keyfile_write(NMConnection         *connection,
     g_return_val_if_fail(!error || !*error, NULL);
     g_return_val_if_fail(handler_flags == NM_KEYFILE_HANDLER_FLAGS_NONE, NULL);
 
-    /* Technically, we might not require that a profile is valid in
-     * order to serialize it. Like also nm_keyfile_read() does not
-     * ensure that the read profile validates.
-     *
-     * However, if the profile does not validate, then there might be
-     * unexpected edge cases when we try to serialize it. Edge cases
-     * that might result in dangerous crash.
-     *
-     * So, for now we require valid profiles. */
-    if (!nm_connection_verify(connection, error ? &local : NULL)) {
-        if (error) {
-            g_set_error(error,
-                        NM_CONNECTION_ERROR,
-                        NM_CONNECTION_ERROR_FAILED,
-                        _("the profile is not valid: %s"),
-                        local->message);
-            g_error_free(local);
-        } else
-            nm_assert(!local);
-        return NULL;
-    }
-
     keyfile = g_key_file_new();
 
     info = (KeyfileWriterInfo){
@@ -4189,11 +4227,16 @@ nm_keyfile_write(NMConnection         *connection,
                                               key,
                                               (guint64) g_variant_get_uint32(v));
                     } else {
-                        /* BUG: The variant type is not implemented. Since the connection
-                         * verifies, this can only mean we either wrongly didn't reject
-                         * the connection as invalid, or we didn't properly implement the
-                         * variant type. */
-                        nm_assert_not_reached();
+                        if (!write_handle_warn(&info,
+                                               setting,
+                                               NULL,
+                                               key,
+                                               NM_KEYFILE_WARN_SEVERITY_WARN,
+                                               _("unsupported option \"%s.%s\" of variant type %s"),
+                                               setting_name,
+                                               key,
+                                               g_variant_get_type_string(v)))
+                            goto out_with_info_error;
                         continue;
                     }
                 }