diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index 471353e741..2a1c69d94b 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -329,7 +329,6 @@ gboolean _nm_utils_inet6_is_token (const struct in6_addr *in6addr); /***********************************************************/ -gboolean _nm_utils_check_valid_json (const char *json, GError **error); gboolean _nm_utils_team_config_equal (const char *conf1, const char *conf2, gboolean port); #endif diff --git a/libnm-core/nm-keyfile-reader.c b/libnm-core/nm-keyfile-reader.c index 16f0c225b9..f25fa0e1a4 100644 --- a/libnm-core/nm-keyfile-reader.c +++ b/libnm-core/nm-keyfile-reader.c @@ -1175,7 +1175,7 @@ team_config_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key gs_free_error GError *error = NULL; conf = nm_keyfile_plugin_kf_get_string (info->keyfile, setting_name, key, NULL); - if (conf && conf[0] && !_nm_utils_check_valid_json (conf, &error)) { + if (conf && conf[0] && !nm_utils_is_json_object (conf, &error)) { handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, _("ignoring invalid team configuration: %s"), error->message); diff --git a/libnm-core/nm-setting-team-port.c b/libnm-core/nm-setting-team-port.c index e3ddbdad7c..649d958273 100644 --- a/libnm-core/nm-setting-team-port.c +++ b/libnm-core/nm-setting-team-port.c @@ -117,7 +117,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } if (priv->config) { - if (!_nm_utils_check_valid_json (priv->config, error)) { + if (!nm_utils_is_json_object (priv->config, error)) { g_prefix_error (error, "%s.%s: ", NM_SETTING_TEAM_PORT_SETTING_NAME, diff --git a/libnm-core/nm-setting-team.c b/libnm-core/nm-setting-team.c index 5bf11ed921..c49ebff2b2 100644 --- a/libnm-core/nm-setting-team.c +++ b/libnm-core/nm-setting-team.c @@ -89,7 +89,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; if (priv->config) { - if (!_nm_utils_check_valid_json (priv->config, error)) { + if (!nm_utils_is_json_object (priv->config, error)) { g_prefix_error (error, "%s.%s: ", NM_SETTING_TEAM_SETTING_NAME, diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index 818b0c43ec..cd54ba6b5f 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -4407,8 +4407,20 @@ const char **nm_utils_enum_get_values (GType type, gint from, gint to) } #if WITH_JANSSON +/** + * nm_utils_is_json_object: + * @str: the JSON string to test + * @error: optional error reason + * + * Returns: whether the passed string is valid JSON. + * If libnm is not compiled with libjansson support, this check will + * also return %TRUE for possibly invalid inputs. If that is a problem + * for you, you must validate the JSON yourself. + * + * Since: 1.6 + */ gboolean -_nm_utils_check_valid_json (const char *str, GError **error) +nm_utils_is_json_object (const char *str, GError **error) { json_t *json; json_error_t jerror; @@ -4419,7 +4431,7 @@ _nm_utils_check_valid_json (const char *str, GError **error) g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, - "value is NULL or empty"); + str ? _("value is NULL") : _("value is empty")); return FALSE; } @@ -4428,9 +4440,19 @@ _nm_utils_check_valid_json (const char *str, GError **error) g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, - "%s at position %d", - jerror.text, - jerror.position); + _("invalid JSON at position %d (%s)"), + jerror.position, + jerror.text); + return FALSE; + } + + /* valid JSON (depending on the definition) can also be a literal. + * Here we only allow objects. */ + if (!json_is_object (json)) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("is not a JSON object")); return FALSE; } @@ -4522,17 +4544,48 @@ out: #else /* WITH_JANSSON */ gboolean -_nm_utils_check_valid_json (const char *str, GError **error) +nm_utils_is_json_object (const char *str, GError **error) { + g_return_val_if_fail (!error || !*error, FALSE); + + if (str) { + /* libjansson also requires only utf-8 encoding. */ + if (!g_utf8_validate (str, -1, NULL)) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("not valid utf-8")); + return FALSE; + } + while (g_ascii_isspace (str[0])) + str++; + } + if (!str || !str[0]) { g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, - "value is NULL or empty"); + str ? _("value is NULL") : _("value is empty")); return FALSE; } - return TRUE; + /* do some very basic validation to see if this might be a JSON object. */ + if (str[0] == '{') { + g_size l; + + l = strlen (str) - 1; + while (l > 0 && g_ascii_isspace (str[l])) + l--; + + if (str[l] == '}') + return TRUE; + } + + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("is not a JSON object")); + return FALSE; } gboolean diff --git a/libnm-core/nm-utils.h b/libnm-core/nm-utils.h index 407c14e2c4..4fabfdb7b7 100644 --- a/libnm-core/nm-utils.h +++ b/libnm-core/nm-utils.h @@ -90,6 +90,9 @@ gboolean nm_utils_ap_mode_security_valid (NMUtilsSecurityType type, gboolean nm_utils_wep_key_valid (const char *key, NMWepKeyType wep_type); gboolean nm_utils_wpa_psk_valid (const char *psk); +NM_AVAILABLE_IN_1_6 +gboolean nm_utils_is_json_object (const char *json, GError **error); + GVariant *nm_utils_ip4_dns_to_variant (char **dns); char **nm_utils_ip4_dns_from_variant (GVariant *value); GVariant *nm_utils_ip4_addresses_to_variant (GPtrArray *addresses, diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index e8a9404bf3..c75abbf999 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -4685,7 +4685,7 @@ _json_config_check_valid (const char *conf, gboolean expected) gs_free_error GError *error = NULL; gboolean res; - res = _nm_utils_check_valid_json (conf, &error); + res = nm_utils_is_json_object (conf, &error); g_assert_cmpint (res, ==, expected); g_assert (res || error); } diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 6c149f6587..bc47e8625d 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -1086,4 +1086,5 @@ global: libnm_1_6_0 { nm_capability_get_type; + nm_utils_is_json_object; } libnm_1_4_0; diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c index 5a351cfa06..80c6ca1553 100644 --- a/src/settings/plugins/ifcfg-rh/reader.c +++ b/src/settings/plugins/ifcfg-rh/reader.c @@ -4258,7 +4258,7 @@ read_team_config (shvarFile *ifcfg, const char *key, GError **error) } svUnescape (value); - if (value && value[0] && !_nm_utils_check_valid_json (value, &local_error)) { + if (value && value[0] && !nm_utils_is_json_object (value, &local_error)) { PARSE_WARNING ("ignoring invalid team configuration: %s", local_error->message); g_clear_pointer (&value, g_free); }