diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c index a555bd6d5..5bafe2d7c 100644 --- a/libnm-core/nm-connection.c +++ b/libnm-core/nm-connection.c @@ -1881,7 +1881,7 @@ GVariant * _nm_connection_for_each_secret (NMConnection *self, GVariant *secrets, gboolean remove_non_secrets, - NMConnectionForEachSecretFunc callback, + _NMConnectionForEachSecretFunc callback, gpointer callback_data) { GVariantBuilder secrets_builder; @@ -1900,10 +1900,8 @@ _nm_connection_for_each_secret (NMConnection *self, * The one complexity is that the VPN setting's 'secrets' property is * *also* a dict (since the key/value pairs are arbitrary and known * only to the VPN plugin itself). That means we have three levels of - * dicts that we potentially have to traverse here. When we hit the - * VPN setting's 'secrets' property, we special-case that and iterate over - * each item in that 'secrets' dict, calling the supplied callback - * each time. + * dicts that we potentially have to traverse here. The differences + * are handled by the virtual for_each_secret() function. */ g_return_val_if_fail (callback, NULL); @@ -1923,49 +1921,14 @@ _nm_connection_for_each_secret (NMConnection *self, g_variant_builder_init (&setting_builder, NM_VARIANT_TYPE_SETTING); while (g_variant_iter_next (setting_iter, "{&sv}", &secret_name, &val)) { _nm_unused gs_unref_variant GVariant *val_free = val; - NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; - /* VPN secrets need slightly different treatment here since the - * "secrets" property is actually a hash table of secrets. - */ - if (NM_IS_SETTING_VPN (setting) && !g_strcmp0 (secret_name, NM_SETTING_VPN_SECRETS)) { - GVariantBuilder vpn_secrets_builder; - GVariantIter vpn_secrets_iter; - const char *vpn_secret_name, *secret; - - if (!g_variant_is_of_type (val, G_VARIANT_TYPE ("a{ss}"))) { - /* invalid type. Silently ignore the secrets as we cannot find out the - * secret-flags. */ - g_variant_unref (val); - continue; - } - - /* Iterate through each secret from the VPN dict in the overall secrets dict */ - g_variant_builder_init (&vpn_secrets_builder, G_VARIANT_TYPE ("a{ss}")); - g_variant_iter_init (&vpn_secrets_iter, val); - while (g_variant_iter_next (&vpn_secrets_iter, "{&s&s}", &vpn_secret_name, &secret)) { - - /* we ignore the return value of get_secret_flags. The function may determine - * that this is not a secret, based on having not secret-flags and no secrets. - * But we have the secret at hand. We know it would be a valid secret, if we - * only would add it to the VPN settings. */ - nm_setting_get_secret_flags (setting, vpn_secret_name, &secret_flags, NULL); - - if (callback (secret_flags, callback_data)) - g_variant_builder_add (&vpn_secrets_builder, "{ss}", vpn_secret_name, secret); - } - - g_variant_builder_add (&setting_builder, "{sv}", - secret_name, g_variant_builder_end (&vpn_secrets_builder)); - } else { - if (!nm_setting_get_secret_flags (setting, secret_name, &secret_flags, NULL)) { - if (!remove_non_secrets) - g_variant_builder_add (&setting_builder, "{sv}", secret_name, val); - continue; - } - if (callback (secret_flags, callback_data)) - g_variant_builder_add (&setting_builder, "{sv}", secret_name, val); - } + NM_SETTING_GET_CLASS (setting)->for_each_secret (setting, + secret_name, + val, + remove_non_secrets, + callback, + callback_data, + &setting_builder); } g_variant_builder_add (&secrets_builder, "{sa{sv}}", setting_name, &setting_builder); diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index 870ec7813..2d66eb83f 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -733,14 +733,10 @@ GBytes *_nm_setting_802_1x_cert_value_to_bytes (NMSetting8021xCKScheme scheme, /*****************************************************************************/ -/* Return TRUE to keep (copy to the result), FALSE to drop. */ -typedef gboolean (*NMConnectionForEachSecretFunc) (NMSettingSecretFlags flags, - gpointer user_data); - GVariant *_nm_connection_for_each_secret (NMConnection *self, GVariant *secrets, gboolean remove_non_secrets, - NMConnectionForEachSecretFunc callback, + _NMConnectionForEachSecretFunc callback, gpointer callback_data); typedef gboolean (*NMConnectionFindSecretFunc) (NMSettingSecretFlags flags, diff --git a/libnm-core/nm-setting-vpn.c b/libnm-core/nm-setting-vpn.c index 133620b7d..e3612c13b 100644 --- a/libnm-core/nm-setting-vpn.c +++ b/libnm-core/nm-setting-vpn.c @@ -684,6 +684,57 @@ update_one_secret (NMSetting *setting, const char *key, GVariant *value, GError return success; } +static void +for_each_secret (NMSetting *setting, + const char *secret_name, + GVariant *val, + gboolean remove_non_secrets, + _NMConnectionForEachSecretFunc callback, + gpointer callback_data, + GVariantBuilder *setting_builder) +{ + GVariantBuilder vpn_secrets_builder; + GVariantIter vpn_secrets_iter; + const char *vpn_secret_name; + const char *secret; + + if (!nm_streq (secret_name, NM_SETTING_VPN_SECRETS)) { + NM_SETTING_CLASS (nm_setting_vpn_parent_class)->for_each_secret (setting, + secret_name, + val, + remove_non_secrets, + callback, + callback_data, + setting_builder); + return; + } + + if (!g_variant_is_of_type (val, G_VARIANT_TYPE ("a{ss}"))) { + /* invalid type. Silently ignore the secrets as we cannot find out the + * secret-flags. */ + return; + } + + /* Iterate through each secret from the VPN dict in the overall secrets dict */ + g_variant_builder_init (&vpn_secrets_builder, G_VARIANT_TYPE ("a{ss}")); + g_variant_iter_init (&vpn_secrets_iter, val); + while (g_variant_iter_next (&vpn_secrets_iter, "{&s&s}", &vpn_secret_name, &secret)) { + NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; + + /* we ignore the return value of get_secret_flags. The function may determine + * that this is not a secret, based on having not secret-flags and no secrets. + * But we have the secret at hand. We know it would be a valid secret, if we + * only add it to the VPN settings. */ + nm_setting_get_secret_flags (setting, vpn_secret_name, &secret_flags, NULL); + + if (callback (secret_flags, callback_data)) + g_variant_builder_add (&vpn_secrets_builder, "{ss}", vpn_secret_name, secret); + } + + g_variant_builder_add (setting_builder, "{sv}", + secret_name, g_variant_builder_end (&vpn_secrets_builder)); +} + static gboolean get_secret_flags (NMSetting *setting, const char *secret_name, @@ -976,6 +1027,7 @@ nm_setting_vpn_class_init (NMSettingVpnClass *klass) setting_class->verify = verify; setting_class->update_one_secret = update_one_secret; + setting_class->for_each_secret = for_each_secret; setting_class->get_secret_flags = get_secret_flags; setting_class->set_secret_flags = set_secret_flags; setting_class->need_secrets = need_secrets; diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c index c679e89d3..126c25d8a 100644 --- a/libnm-core/nm-setting.c +++ b/libnm-core/nm-setting.c @@ -2094,6 +2094,26 @@ _nm_setting_update_secrets (NMSetting *setting, GVariant *secrets, GError **erro return result; } +static void +for_each_secret (NMSetting *setting, + const char *secret_name, + GVariant *val, + gboolean remove_non_secrets, + _NMConnectionForEachSecretFunc callback, + gpointer callback_data, + GVariantBuilder *setting_builder) +{ + NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; + + if (!nm_setting_get_secret_flags (setting, secret_name, &secret_flags, NULL)) { + if (!remove_non_secrets) + g_variant_builder_add (setting_builder, "{sv}", secret_name, val); + return; + } + if (callback (secret_flags, callback_data)) + g_variant_builder_add (setting_builder, "{sv}", secret_name, val); +} + static void _set_error_secret_property_not_found (GError **error, NMSetting *setting, @@ -2629,6 +2649,7 @@ nm_setting_class_init (NMSettingClass *setting_class) setting_class->set_secret_flags = set_secret_flags; setting_class->compare_property = compare_property; setting_class->clear_secrets = clear_secrets; + setting_class->for_each_secret = for_each_secret; setting_class->duplicate_copy_properties = duplicate_copy_properties; setting_class->enumerate_values = enumerate_values; setting_class->aggregate = aggregate; diff --git a/libnm-core/nm-setting.h b/libnm-core/nm-setting.h index 96868731e..fdf4a4c51 100644 --- a/libnm-core/nm-setting.h +++ b/libnm-core/nm-setting.h @@ -187,6 +187,10 @@ typedef void (*NMSettingValueIterFn) (NMSetting *setting, GParamFlags flags, gpointer user_data); +/*< private >*/ +typedef gboolean (*_NMConnectionForEachSecretFunc) (NMSettingSecretFlags flags, + gpointer user_data); + typedef struct { GObjectClass parent; @@ -253,10 +257,19 @@ typedef struct { gpointer arg); /*< private >*/ - const struct _NMMetaSettingInfo *setting_info; + void (*for_each_secret) (NMSetting *setting, + const char *secret_name, + GVariant *val, + gboolean remove_non_secrets, + _NMConnectionForEachSecretFunc callback, + gpointer callback_data, + GVariantBuilder *setting_builder); /*< private >*/ - gpointer padding[3]; + gpointer padding[2]; + + /*< private >*/ + const struct _NMMetaSettingInfo *setting_info; } NMSettingClass; GType nm_setting_get_type (void);