libnm,core: merge branch 'th/various-for-wireguard-2'

https://github.com/NetworkManager/NetworkManager/pull/291
This commit is contained in:
Thomas Haller 2019-02-04 20:15:42 +01:00
commit 2727c713ca
7 changed files with 366 additions and 226 deletions

View file

@ -1873,6 +1873,108 @@ nm_connection_clear_secrets_with_flags (NMConnection *connection,
g_signal_emit (connection, signals[SECRETS_CLEARED], 0);
}
/*****************************************************************************/
/* Returns always a non-NULL, floating variant that must
* be unrefed by the caller. */
GVariant *
_nm_connection_for_each_secret (NMConnection *self,
GVariant *secrets,
gboolean remove_non_secrets,
_NMConnectionForEachSecretFunc callback,
gpointer callback_data)
{
GVariantBuilder secrets_builder;
GVariantBuilder setting_builder;
GVariantIter secrets_iter;
GVariantIter *setting_iter;
const char *setting_name;
/* This function, given a dict of dicts representing new secrets of
* an NMConnection, walks through each toplevel dict (which represents a
* NMSetting), and for each setting, walks through that setting dict's
* properties. For each property that's a secret, it will check that
* secret's flags in the backing NMConnection object, and call a supplied
* callback.
*
* 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. The differences
* are handled by the virtual for_each_secret() function.
*/
g_return_val_if_fail (callback, NULL);
g_variant_iter_init (&secrets_iter, secrets);
g_variant_builder_init (&secrets_builder, NM_VARIANT_TYPE_CONNECTION);
while (g_variant_iter_next (&secrets_iter, "{&sa{sv}}", &setting_name, &setting_iter)) {
_nm_unused nm_auto_free_variant_iter GVariantIter *setting_iter_free = setting_iter;
NMSetting *setting;
const char *secret_name;
GVariant *val;
setting = nm_connection_get_setting_by_name (self, setting_name);
if (!setting)
continue;
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;
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);
}
return g_variant_builder_end (&secrets_builder);
}
/*****************************************************************************/
typedef struct {
NMConnectionFindSecretFunc find_func;
gpointer find_func_data;
gboolean found;
} FindSecretData;
static gboolean
find_secret_for_each_func (NMSettingSecretFlags flags,
gpointer user_data)
{
FindSecretData *data = user_data;
if (!data->found)
data->found = data->find_func (flags, data->find_func_data);
return FALSE;
}
gboolean
_nm_connection_find_secret (NMConnection *self,
GVariant *secrets,
NMConnectionFindSecretFunc callback,
gpointer callback_data)
{
gs_unref_variant GVariant *dummy = NULL;
FindSecretData data = {
.find_func = callback,
.find_func_data = callback_data,
.found = FALSE,
};
dummy = _nm_connection_for_each_secret (self, secrets, FALSE, find_secret_for_each_func, &data);
return data.found;
}
/*****************************************************************************/
/**
* nm_connection_to_dbus:
* @connection: the #NMConnection

View file

@ -614,7 +614,8 @@ gboolean _nm_setting_sriov_sort_vfs (NMSettingSriov *setting);
/*****************************************************************************/
typedef struct _NMSettInfoSetting NMSettInfoSetting;
typedef struct _NMSettInfoSetting NMSettInfoSetting;
typedef struct _NMSettInfoProperty NMSettInfoProperty;
typedef GVariant *(*NMSettingPropertyGetFunc) (NMSetting *setting,
const char *property);
@ -638,7 +639,7 @@ typedef GVariant *(*NMSettingPropertyTransformToFunc) (const GValue *from);
typedef void (*NMSettingPropertyTransformFromFunc) (GVariant *from,
GValue *to);
typedef struct {
struct _NMSettInfoProperty {
const char *name;
GParamSpec *param_spec;
const GVariantType *dbus_type;
@ -650,7 +651,7 @@ typedef struct {
NMSettingPropertyTransformToFunc to_dbus;
NMSettingPropertyTransformFromFunc from_dbus;
} NMSettInfoProperty;
};
typedef struct {
const GVariantType *(*get_variant_type) (const struct _NMSettInfoSetting *sett_info,
@ -732,4 +733,20 @@ GBytes *_nm_setting_802_1x_cert_value_to_bytes (NMSetting8021xCKScheme scheme,
/*****************************************************************************/
GVariant *_nm_connection_for_each_secret (NMConnection *self,
GVariant *secrets,
gboolean remove_non_secrets,
_NMConnectionForEachSecretFunc callback,
gpointer callback_data);
typedef gboolean (*NMConnectionFindSecretFunc) (NMSettingSecretFlags flags,
gpointer user_data);
gboolean _nm_connection_find_secret (NMConnection *self,
GVariant *secrets,
NMConnectionFindSecretFunc callback,
gpointer callback_data);
/*****************************************************************************/
#endif

View file

@ -39,6 +39,8 @@ int _nm_setting_compare_priority (gconstpointer a, gconstpointer b);
/*****************************************************************************/
void _nm_setting_emit_property_changed (NMSetting *setting);
typedef enum NMSettingUpdateSecretResult {
NM_SETTING_UPDATE_SECRET_ERROR = FALSE,
NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED = TRUE,
@ -99,9 +101,6 @@ gboolean _nm_setting_verify_secret_string (const char *str,
gboolean _nm_setting_aggregate (NMSetting *setting,
NMConnectionAggregateType type,
gpointer arg);
gboolean _nm_setting_vpn_aggregate (NMSettingVpn *setting,
NMConnectionAggregateType type,
gpointer arg);
gboolean _nm_setting_slave_type_is_valid (const char *slave_type, const char **out_port_type);

View file

@ -449,20 +449,17 @@ nm_setting_vpn_foreach_secret (NMSettingVpn *setting,
foreach_item_helper (setting, TRUE, func, user_data);
}
gboolean
_nm_setting_vpn_aggregate (NMSettingVpn *setting,
NMConnectionAggregateType type,
gpointer arg)
static gboolean
aggregate (NMSetting *setting,
int type_i,
gpointer arg)
{
NMSettingVpnPrivate *priv;
NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting);
NMConnectionAggregateType type = type_i;
NMSettingSecretFlags secret_flags;
const char *key_name;
GHashTableIter iter;
g_return_val_if_fail (NM_IS_SETTING_VPN (setting), FALSE);
priv = NM_SETTING_VPN_GET_PRIVATE (setting);
switch (type) {
case NM_CONNECTION_AGGREGATE_ANY_SECRETS:
@ -687,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,
@ -979,11 +1027,13 @@ 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;
setting_class->compare_property = compare_property;
setting_class->clear_secrets = clear_secrets;
setting_class->aggregate = aggregate;
/**
* NMSettingVpn:service-type:

View file

@ -32,15 +32,6 @@
#include "nm-utils-private.h"
#include "nm-property-compare.h"
#include "nm-setting-connection.h"
#include "nm-setting-bond.h"
#include "nm-setting-bridge.h"
#include "nm-setting-bridge-port.h"
#include "nm-setting-pppoe.h"
#include "nm-setting-team.h"
#include "nm-setting-team-port.h"
#include "nm-setting-vpn.h"
/**
* SECTION:nm-setting
* @short_description: Describes related configuration information
@ -67,7 +58,7 @@ typedef struct {
NMSettingPriority priority;
} SettingInfo;
NM_GOBJECT_PROPERTIES_DEFINE_BASE (
NM_GOBJECT_PROPERTIES_DEFINE (NMSetting,
PROP_NAME,
);
@ -553,6 +544,35 @@ _nm_setting_class_get_sett_info (NMSettingClass *setting_class)
/*****************************************************************************/
void
_nm_setting_emit_property_changed (NMSetting *setting)
{
/* Some settings have "properties" that are not implemented as GObject properties.
*
* For example:
*
* - gendata-base settings like NMSettingEthtool. Here properties are just
* GVariant values in the gendata hash.
*
* - NMSettingWireGuard's peers are not backed by a GObject property. Instead
* there is C-API to access/modify peers.
*
* We still want to emit property-changed notifications for such properties,
* in particular because NMConnection registers to such signals to re-emit
* it as NM_CONNECTION_CHANGED signal. In fact, there are unlikely any other
* uses of such a property-changed signal, because generally it doesn't make
* too much sense.
*
* So, instead of adding yet another (artificial) signal "setting-changed",
* hijack the "notify" signal and just notify about changes of the "name".
* Of course, the "name" doesn't really ever change, because it's tied to
* the GObject's type.
*/
_notify (setting, PROP_NAME);
}
/*****************************************************************************/
gboolean
_nm_setting_use_legacy_property (NMSetting *setting,
GVariant *connection_dict,
@ -1082,6 +1102,8 @@ duplicate_copy_properties (const NMSettInfoSetting *sett_info,
if (sett_info->detail.gendata_info) {
GenData *gendata = _gendata_hash (src, FALSE);
nm_assert (!_gendata_hash (dst, FALSE));
if ( gendata
&& g_hash_table_size (gendata->hash) > 0) {
GHashTableIter iter;
@ -1698,6 +1720,27 @@ nm_setting_diff (NMSetting *a,
}
}
static void
enumerate_values (const NMSettInfoProperty *property_info,
NMSetting *setting,
NMSettingValueIterFn func,
gpointer user_data)
{
GValue value = G_VALUE_INIT;
if (!property_info->param_spec)
return;
g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (property_info->param_spec));
g_object_get_property (G_OBJECT (setting), property_info->param_spec->name, &value);
func (setting,
property_info->param_spec->name,
&value,
property_info->param_spec->flags,
user_data);
g_value_unset (&value);
}
/**
* nm_setting_enumerate_values:
* @setting: the #NMSetting
@ -1753,50 +1796,24 @@ nm_setting_enumerate_values (NMSetting *setting,
}
for (i = 0; i < sett_info->property_infos_len; i++) {
GParamSpec *prop_spec = _nm_sett_info_property_info_get_sorted (sett_info, i)->param_spec;
GValue value = G_VALUE_INIT;
if (!prop_spec)
continue;
g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (prop_spec));
g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
func (setting, prop_spec->name, &value, prop_spec->flags, user_data);
g_value_unset (&value);
NM_SETTING_GET_CLASS (setting)->enumerate_values (_nm_sett_info_property_info_get_sorted (sett_info, i),
setting,
func,
user_data);
}
}
/**
* _nm_setting_aggregate:
* @setting: the #NMSetting to aggregate.
* @type: the #NMConnectionAggregateType aggregate type.
* @arg: the in/out arguments for aggregation. They depend on @type.
*
* This is the implementation detail of _nm_connection_aggregate(). It
* makes no sense to call this function directly outside of _nm_connection_aggregate().
*
* Returns: %TRUE if afterwards the aggregation is complete. That means,
* the only caller _nm_connection_aggregate() will not visit other settings
* after a setting returns %TRUE (indicating that there is nothing further
* to aggregate). Note that is very different from the boolean return
* argument of _nm_connection_aggregate(), which serves a different purpose.
*/
gboolean
_nm_setting_aggregate (NMSetting *setting,
NMConnectionAggregateType type,
gpointer arg)
static gboolean
aggregate (NMSetting *setting,
int type_i,
gpointer arg)
{
NMConnectionAggregateType type = type_i;
const NMSettInfoSetting *sett_info;
guint i;
g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
g_return_val_if_fail (arg, FALSE);
g_return_val_if_fail (NM_IN_SET (type, NM_CONNECTION_AGGREGATE_ANY_SECRETS,
NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS),
FALSE);
if (NM_IS_SETTING_VPN (setting))
return _nm_setting_vpn_aggregate (NM_SETTING_VPN (setting), type, arg);
nm_assert (NM_IN_SET (type, NM_CONNECTION_AGGREGATE_ANY_SECRETS,
NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS));
sett_info = _nm_setting_class_get_sett_info (NM_SETTING_GET_CLASS (setting));
for (i = 0; i < sett_info->property_infos_len; i++) {
@ -1840,6 +1857,35 @@ _nm_setting_aggregate (NMSetting *setting,
return FALSE;
}
/**
* _nm_setting_aggregate:
* @setting: the #NMSetting to aggregate.
* @type: the #NMConnectionAggregateType aggregate type.
* @arg: the in/out arguments for aggregation. They depend on @type.
*
* This is the implementation detail of _nm_connection_aggregate(). It
* makes no sense to call this function directly outside of _nm_connection_aggregate().
*
* Returns: %TRUE if afterwards the aggregation is complete. That means,
* the only caller _nm_connection_aggregate() will not visit other settings
* after a setting returns %TRUE (indicating that there is nothing further
* to aggregate). Note that is very different from the boolean return
* argument of _nm_connection_aggregate(), which serves a different purpose.
*/
gboolean
_nm_setting_aggregate (NMSetting *setting,
NMConnectionAggregateType type,
gpointer arg)
{
g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
g_return_val_if_fail (arg, FALSE);
g_return_val_if_fail (NM_IN_SET (type, NM_CONNECTION_AGGREGATE_ANY_SECRETS,
NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS),
FALSE);
return NM_SETTING_GET_CLASS (setting)->aggregate (setting, type, arg);
}
static gboolean
clear_secrets (const NMSettInfoSetting *sett_info,
guint property_idx,
@ -2039,6 +2085,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,
@ -2293,7 +2359,7 @@ _nm_setting_gendata_notify (NMSetting *setting,
gendata = _gendata_hash (setting, FALSE);
if (!gendata)
return;
goto out;
nm_clear_g_free (&gendata->values);
@ -2303,7 +2369,7 @@ _nm_setting_gendata_notify (NMSetting *setting,
nm_clear_g_free (&gendata->names);
}
/* Note, that currently there is now way to notify the subclass when gendata changed.
/* Note, currently there is no way to notify the subclass when gendata changed.
* gendata is only changed in two situations:
* 1) from within NMSetting itself, for example when creating a NMSetting instance
* from keyfile or a D-Bus GVariant.
@ -2316,6 +2382,9 @@ _nm_setting_gendata_notify (NMSetting *setting,
*
* If we ever need it, then we would need to call a virtual function to notify the subclass
* that gendata changed. */
out:
_nm_setting_emit_property_changed (setting);
}
GVariant *
@ -2438,7 +2507,7 @@ nm_setting_gendata_get_all_values (NMSetting *setting)
void
_nm_setting_gendata_to_gvalue (NMSetting *setting,
GValue *value)
GValue *value)
{
GenData *gendata;
GHashTable *new;
@ -2571,7 +2640,10 @@ 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;
/**
* NMSetting:name:

View file

@ -170,6 +170,26 @@ typedef gboolean (*NMSettingClearSecretsWithFlagsFn) (NMSetting *setting,
struct _NMMetaSettingInfo;
struct _NMSettInfoSetting;
struct _NMSettInfoProperty;
/**
* NMSettingValueIterFn:
* @setting: The setting for which properties are being iterated, given to
* nm_setting_enumerate_values()
* @key: The value/property name
* @value: The property's value
* @flags: The property's flags, like %NM_SETTING_PARAM_SECRET
* @user_data: User data passed to nm_setting_enumerate_values()
*/
typedef void (*NMSettingValueIterFn) (NMSetting *setting,
const char *key,
const GValue *value,
GParamFlags flags,
gpointer user_data);
/*< private >*/
typedef gboolean (*_NMConnectionForEachSecretFunc) (NMSettingSecretFlags flags,
gpointer user_data);
typedef struct {
GObjectClass parent;
@ -226,26 +246,31 @@ typedef struct {
NMSetting *dst);
/*< private >*/
const struct _NMMetaSettingInfo *setting_info;
void (*enumerate_values) (const struct _NMSettInfoProperty *property_info,
NMSetting *setting,
NMSettingValueIterFn func,
gpointer user_data);
/*< private >*/
gpointer padding[5];
} NMSettingClass;
gboolean (*aggregate) (NMSetting *setting,
int type_i,
gpointer arg);
/**
* NMSettingValueIterFn:
* @setting: The setting for which properties are being iterated, given to
* nm_setting_enumerate_values()
* @key: The value/property name
* @value: The property's value
* @flags: The property's flags, like %NM_SETTING_PARAM_SECRET
* @user_data: User data passed to nm_setting_enumerate_values()
*/
typedef void (*NMSettingValueIterFn) (NMSetting *setting,
const char *key,
const GValue *value,
GParamFlags flags,
gpointer user_data);
/*< private >*/
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[2];
/*< private >*/
const struct _NMMetaSettingInfo *setting_info;
} NMSettingClass;
GType nm_setting_get_type (void);

View file

@ -208,141 +208,6 @@ nm_settings_connection_get_last_secret_agent_version_id (NMSettingsConnection *s
/*****************************************************************************/
/* Return TRUE to keep, FALSE to drop */
typedef gboolean (*ForEachSecretFunc) (NMSettingSecretFlags flags,
gpointer user_data);
/* Returns always a non-NULL, non-floating variant that must
* be unrefed by the caller. */
static GVariant *
for_each_secret (NMConnection *self,
GVariant *secrets,
gboolean remove_non_secrets,
ForEachSecretFunc callback,
gpointer callback_data)
{
GVariantBuilder secrets_builder, setting_builder;
GVariantIter secrets_iter, *setting_iter;
const char *setting_name;
/* This function, given a dict of dicts representing new secrets of
* an NMConnection, walks through each toplevel dict (which represents a
* NMSetting), and for each setting, walks through that setting dict's
* properties. For each property that's a secret, it will check that
* secret's flags in the backing NMConnection object, and call a supplied
* callback.
*
* 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.
*/
g_return_val_if_fail (callback, NULL);
g_variant_iter_init (&secrets_iter, secrets);
g_variant_builder_init (&secrets_builder, NM_VARIANT_TYPE_CONNECTION);
while (g_variant_iter_next (&secrets_iter, "{&sa{sv}}", &setting_name, &setting_iter)) {
NMSetting *setting;
const char *secret_name;
GVariant *val;
setting = nm_connection_get_setting_by_name (self, setting_name);
if (setting == NULL) {
g_variant_iter_free (setting_iter);
continue;
}
g_variant_builder_init (&setting_builder, NM_VARIANT_TYPE_SETTING);
while (g_variant_iter_next (setting_iter, "{&sv}", &secret_name, &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;
/* 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)) {
if (!nm_setting_get_secret_flags (setting, vpn_secret_name, &secret_flags, NULL)) {
if (!remove_non_secrets)
g_variant_builder_add (&vpn_secrets_builder, "{ss}", vpn_secret_name, secret);
continue;
}
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);
}
g_variant_unref (val);
}
g_variant_iter_free (setting_iter);
g_variant_builder_add (&secrets_builder, "{sa{sv}}", setting_name, &setting_builder);
}
return g_variant_ref_sink (g_variant_builder_end (&secrets_builder));
}
typedef gboolean (*FindSecretFunc) (NMSettingSecretFlags flags,
gpointer user_data);
typedef struct {
FindSecretFunc find_func;
gpointer find_func_data;
gboolean found;
} FindSecretData;
static gboolean
find_secret_for_each_func (NMSettingSecretFlags flags,
gpointer user_data)
{
FindSecretData *data = user_data;
if (!data->found)
data->found = data->find_func (flags, data->find_func_data);
return FALSE;
}
static gboolean
find_secret (NMConnection *self,
GVariant *secrets,
FindSecretFunc callback,
gpointer callback_data)
{
FindSecretData data;
GVariant *dummy;
data.find_func = callback;
data.find_func_data = callback_data;
data.found = FALSE;
dummy = for_each_secret (self, secrets, FALSE, find_secret_for_each_func, &data);
g_variant_unref (dummy);
return data.found;
}
/*****************************************************************************/
static void
set_visible (NMSettingsConnection *self, gboolean new_visible)
{
@ -938,8 +803,8 @@ typedef struct {
} ForEachSecretFlags;
static gboolean
validate_secret_flags (NMSettingSecretFlags flags,
gpointer user_data)
validate_secret_flags_cb (NMSettingSecretFlags flags,
gpointer user_data)
{
ForEachSecretFlags *cmp_flags = user_data;
@ -950,6 +815,18 @@ validate_secret_flags (NMSettingSecretFlags flags,
return TRUE;
}
static GVariant *
validate_secret_flags (NMConnection *connection,
GVariant *secrets,
ForEachSecretFlags *cmp_flags)
{
return g_variant_ref_sink (_nm_connection_for_each_secret (connection,
secrets,
TRUE,
validate_secret_flags_cb,
cmp_flags));
}
static gboolean
secret_is_system_owned (NMSettingSecretFlags flags,
gpointer user_data)
@ -992,7 +869,7 @@ get_cmp_flags (NMSettingsConnection *self, /* only needed for logging */
* save those system-owned secrets. If not, discard them and use the
* existing secrets, or fail the connection.
*/
*agent_had_system = find_secret (connection, secrets, secret_is_system_owned, NULL);
*agent_had_system = _nm_connection_find_secret (connection, secrets, secret_is_system_owned, NULL);
if (*agent_had_system) {
if (flags == NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE) {
/* No user interaction was allowed when requesting secrets; the
@ -1151,14 +1028,14 @@ get_secrets_done_cb (NMAgentManager *manager,
/* Update the connection with our existing secrets from backing storage */
nm_connection_clear_secrets (nm_settings_connection_get_connection (self));
if (!dict || nm_connection_update_secrets (nm_settings_connection_get_connection (self), setting_name, dict, &local)) {
GVariant *filtered_secrets;
gs_unref_variant GVariant *filtered_secrets = NULL;
/* Update the connection with the agent's secrets; by this point if any
* system-owned secrets exist in 'secrets' the agent that provided them
* will have been authenticated, so those secrets can replace the existing
* system secrets.
*/
filtered_secrets = for_each_secret (nm_settings_connection_get_connection (self), secrets, TRUE, validate_secret_flags, &cmp_flags);
filtered_secrets = validate_secret_flags (nm_settings_connection_get_connection (self), secrets, &cmp_flags);
if (nm_connection_update_secrets (nm_settings_connection_get_connection (self), setting_name, filtered_secrets, &local)) {
/* Now that all secrets are updated, copy and cache new secrets,
* then save them to backing storage.
@ -1194,7 +1071,6 @@ get_secrets_done_cb (NMAgentManager *manager,
call_id,
local->message);
}
g_variant_unref (filtered_secrets);
} else {
_LOGD ("(%s:%p) failed to update with existing secrets: %s",
setting_name,
@ -1218,11 +1094,10 @@ get_secrets_done_cb (NMAgentManager *manager,
nm_connection_clear_secrets (applied_connection);
if (!dict || nm_connection_update_secrets (applied_connection, setting_name, dict, NULL)) {
GVariant *filtered_secrets;
gs_unref_variant GVariant *filtered_secrets = NULL;
filtered_secrets = for_each_secret (applied_connection, secrets, TRUE, validate_secret_flags, &cmp_flags);
filtered_secrets = validate_secret_flags (applied_connection, secrets, &cmp_flags);
nm_connection_update_secrets (applied_connection, setting_name, filtered_secrets, NULL);
g_variant_unref (filtered_secrets);
}
}