property_to_dbus() returns NULL when called with
NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED and the property is
not an agent-owned secrets. The function doesn't handle VPN secrets
correctly, since they are all stored as a hash in the vpn.secrets
property and the flag for each of them is a matching '*-flags' key in
the vpn.data property. VPN secrets must be handled differently; do it
in the VPN setting to_dbus_fcn() function.
Fixes: 71928a3e5c ('settings: avoid cloning the connection to maintain agent-owned secrets')
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/issues/230https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/280
Add test for checking the meta data for expected consistency.
This is also useful if you want to check something about the meta data
programatically.
For example, if you have the question which (if any) properties
are GObject based but also implement a to_dbus_fcn() function. Then you
can extend this code with some simple printf debugging to get a list of
those.
Or, if you want to find how many NMSettInfoProperty instances are in
static data (e.g. to determine how much memory is used). You can easily
modify this code to count them (and find 447 properties). Out of these,
326 are plain GObject based properties. Meaning, we could refactor the
code to create smaller NMSettInfoProperty instances for those, saving
thus (326 * 4 * sizeof (gpointer)) bytes (10K).
Such questions are interesting when refactoring the code.
At various places we only want to serialize agent-owned secrets. Without this
flag, we need to clone the setting first, then drop the secrets, then serialize
to D-Bus. Add a serialization flag to avoid that.
The name ("with") and the meaning of the flag is chosen in a way, that
there could be multiple such flags (NM_CONNECTION_SERIALIZE_WITH_SECRETS_NOT_REQUIRED),
and specifying at least one of them, would have the meaning to whitelist
flags of this kind. Specifying non of these "with" flags would have the
meaning of specifying *all*. Currently there is only one kind, so the name
and meaning is slightly counter intuitive.
We no longer add these. If you use Emacs, configure it yourself.
Also, due to our "smart-tab" usage the editor anyway does a subpar
job handling our tabs. However, on the upside every user can choose
whatever tab-width he/she prefers. If "smart-tabs" are used properly
(like we do), every tab-width will work.
No manual changes, just ran commands:
F=($(git grep -l -e '-\*-'))
sed '1 { /\/\* *-\*- *[mM]ode.*\*\/$/d }' -i "${F[@]}"
sed '1,4 { /^\(#\|--\|dnl\) *-\*- [mM]ode/d }' -i "${F[@]}"
Check remaining lines with:
git grep -e '-\*-'
The ultimate purpose of this is to cleanup our files and eventually use
SPDX license identifiers. For that, first get rid of the boilerplate lines.
Merge the function pointer get_func() into to_dbus_fcn().
Previously, get_func() as handled separately from to_dbus_fnc()
(formerly synth_func()). The notion was that synth-func would syntetize
properties that are D-Bus only. But that distinction does not seem
very helpful to me.
Instaed, we want to convert a property to D-Bus. Period. The
implementation should be handled uniformly. Hence, now that is
all done by property_to_dbus().
Note that property_to_dbus() is also called as default implementation
for compare-property. At least, for properties that are backed by a
GObject property.
The naming was not very clear. How does get_func(), synth_func()
and to_dbus() relate? What does synth_func() do anyway?
Answers:
- get_func() and synth_func() do very similar. They should be merged
in a next step.
synth_func() has the notion of "synthetize" a property for
D-Bus. As such, these properties are a bit unusual in that they
don't have a backing GObject property in the setting. But it'd
rather treat such properties like other properties. The step
in that direction will be to merge the to-dbus functions.
- to_dbus() converts a GValue of the GObject property go GVariant.
It's a simplified form of get_func()/synth_func() and a better name
is gprop_to_dbus_fcn().
The same for gprop_from_dbus_fcn().
For now, just rename.
We have certain artificial properties that not only depend on one
property alone or that depend on a property in another(!) setting.
For that, we have synth_func.
Other than that, synth_func and get_func are really fundamentally
similar and should be merged. That is because the distinction whether a
property value is "synthetized" or just based on a plain property is
minor. It's better to have the general concept of "convert property to
GVariant" in one form only.
Note that compare_property() is by default implemented based
on get_func. Hence, if get_func and synth_func get merged,
compare_property() will also require access to the NMConnection.
Also it makes some sense: some properties are artificial and actually
stored in "another" setting of the connection. But still, the property
descriptor for the property is in this setting. The example is the
"bond.interface-name" which only exists on D-Bus. It's stored as
"connection.interface-name".
I don't really like to say "exists on D-Bus only". It's still a valid
property, despite in NMSetting it's stored somehow differently (or not
at all). So, this is also just a regular property for which we have a
property-info vtable.
Does it make sense to compare such properties? Maybe. But the point is that
compare_property() function needs sometimes access to the entire
connection. So add the argument.
Always properly set NMSettInfoProperty.dbus_type, instead of leaving it
unspecified for GObject property based properties, and detect it each
time anew with variant_type_for_gtype().
Instead, autodetect and remember the dbus-type during _properties_override_add_struct().
For types that need special handling (GBytes, enums and flags) set a to_dbus() function.
This allows us to handle properties uniformly by either calling the to_dbus() function
or g_dbus_gvalue_to_gvariant().
- use cleanup attribute in get_property_for_dbus() and return early.
- use NM_FLAGS_HAS() macro in _nm_setting_to_dbus().
- in nm_setting_get_dbus_property_type() use g_return*() asserts
instead of crash or hard asserts.
- return early from variant_type_for_gtype().
This removes libnm-glib, libnm-glib-vpn, and libnm-util for good.
The it has been replaced with libnm since NetworkManager 1.0, disabled
by default since 1.12 and no up-to-date distributions ship it for years
now.
Removing the libraries allows us to:
* Remove the horrible hacks that were in place to deal with accidental use
of both the new and old library in a single process.
* Relief the translators of maintenance burden of similar yet different
strings.
* Get rid of known bad code without chances of ever getting fixed
(libnm-glib/nm-object.c and libnm-glib/nm-object-cache.c)
* Generally lower the footprint of the releases and our workspace
If there are some really really legacy users; they can just build
libnm-glib and friends from the NetworkManager-1.16 distribution. The
D-Bus API is stable and old libnm-glib will keep working forever.
https://github.com/NetworkManager/NetworkManager/pull/308
This removes libnm-glib, libnm-glib-vpn, and libnm-util for good.
The it has been replaced with libnm since NetworkManager 1.0, disabled
by default since 1.12 and no up-to-date distributions ship it for years
now.
Removing the libraries allows us to:
* Remove the horrible hacks that were in place to deal with accidental use
of both the new and old library in a single process.
* Relief the translators of maintenance burden of similar yet different
strings.
* Get rid of known bad code without chances of ever getting fixed
(libnm-glib/nm-object.c and libnm-glib/nm-object-cache.c)
* Generally lower the footprint of the releases and our workspace
If there are some really really legacy users; they can just build
libnm-glib and friends from the NetworkManager-1.16 distribution. The
D-Bus API is stable and old libnm-glib will keep working forever.
https://github.com/NetworkManager/NetworkManager/pull/308
We already need to special handle regular settings (with secrets as
GObject properties) and VPN secrets.
Next, we will also need to special handle WireGuard peers, which can
have secrets too.
Move the code to a virtual function, so that "nm-connection.c" and
"nm-setting.c" does not have explicit per-setting knowledge.
Instead of special-casing the aggregate implementation for NMSettingVpn,
delegate to a virtual function.
This will also work with other settings, that have properties/secrets
that are not GObject based properties.
While nm_setting_enumerate_values() should not be used anymore, still
extend it to make it workable also for properties that are not based on
GObject properties.
We want to emit a change notification when gendata-based settings (like
NMSettingEthtool) change. But instead of adding a separate signal, just
emit a fake "notify:name" notification.
And merge it with the version that uses no flags.
Previously, clear_secrets(_with_flags()) was only implemented
by NMSettingVpn. All other settings would only consider GObject-based
properties.
As we will add secrets that have no GObject property, call the virtual
function always, so that the setting can hook into this (for WireGuard
peers).
Add a hook so that we can overwrite the property info.
Yes, this is an API/ABI change for NMSettingClass, which is in a
header file. But this is not API that we want to support. Users must
not use this. Alternatively, I could hook the callback into
NMSettInfoSetting, but either works.
Order the code in our common way. No other changes.
- ensure to include the main header first (directly after
"nm-default.h").
- reorder function definitions: get_property(), set_property(),
*_init(), *_new(), finalize(), *_class_init().
_log_connection_get_property() is a hack, as it cannot meaningfully print complex
properties. Also, it uses _nm_setting_get_property() which can only work with GObject
base properties.
Don't assert against _nm_setting_get_property() returning success. Eventually
we should replace _nm_setting_get_property() by something better. But for the moment,
it's fine to being unable to print a property value.
Curreently all aggregate types only care about secrets.
The check for secets is done by checking for NM_SETTING_PARAM_SECRET
flag. Assert that this check is suitable to identify a secret.
NMSetting's compare_property() has and had two callers:
nm_setting_compare() and nm_setting_diff().
compare_property() accepts a NMSettingCompareFlags argument, but
at the same time, both callers have another complex (and
inconsistent!) set of pre-checks for shortcuting the call of
compare_property(): should_compare_prop().
Merge should_compare_prop() into compare_property(). This way,
nm_setting_compare() and nm_setting_diff() has less additional
code, and are simpler to follow. Especially nm_setting_compare()
is now trivial. And nm_setting_diff() is still complicated, but
not related to the question how the property compares or whether
it should be compared at all.
If you want to know whether it should be compared, all you need to do
now is follow NMSettingClass.compare_property().
This changes function pointer NMSettingClass.compare_property(),
which is public API. However, no user can actually use this (and shall
not!), because _nm_setting_class_commit_full() etc. is private API. A
user outside of libnm-core cannot create his/her own subclasses of
NMSetting, and never could in the past. So, this API/ABI change doesn't
matter.
nm_setting_compare() and nm_setting_diff() both call the virtual
function compare_property(). But their check for determining whether
to call the virtual function differs.
In a first step, merge the implementations so that the check is clearly
similar in both cases.
This bug had no effect, because NM_SETTING_COMPARE_FLAG_IGNORE_REAPPLY_IMMEDIATELY
has only one user, and it's used there in combination with
nm_setting_compare(). No caller passed this flag to nm_setting_diff().
Fixes: c9b3617c35
Secret-flags are flags, but most combinations don't actually make sense
and maybe should be rejected. Anyway, that is not done, and most places
just check that there are no unknown flags set.
Add _nm_setting_secret_flags_valid() to perform the check at one place
instead of having the implementation at various places.
Drop another use of nm_setting_enumerate_values().
Using nm_setting_enumerate_values() to duplicate a setting already
didn't work for gendata based settings.
Also, nm_setting_enumerate_values() would iterate the properties
in a particular order. We don't need that, the default order
(asciibetical sorted) is fine.
The property infos are already sorted by name. As nm_setting_enumerate_values()
now uses that information, in most cases there is nothing to sort.
The only instance is NMSettingConnection, which has a different
sort-order. At least for some purposes, not all:
- nm_setting_enumerate_values(), obviously.
- nm_setting_enumerate_values() is called by keyfile writer. That
means, keyfile writer will persist properties in a sorted way.
Cache the property list with alternative sorting also in the
setting-meta data, instead of calculating it each time.
Beside caching the information, this has the additional benefit that
this kind of sorting is now directly available, without calling
nm_setting_enumerate_values(). Meaning, we can implement keyfile writer
without using nm_setting_enumerate_values().
We should no longer use nm_connection_for_each_setting_value() and
nm_setting_for_each_value(). It's fundamentally broken as it does
not work with properties that are not backed by a GObject property
and it cannot be fixed because it is public API.
Add an internal function _nm_connection_aggregate() to replace it.
Compare the implementation of the aggregation functionality inside
libnm with the previous two checks for secret-flags that it replaces:
- previous approach broke abstraction and require detailed knowledge of
secret flags. Meaning, they must special case NMSettingVpn and
GObject-property based secrets.
If we implement a new way for implementing secrets (like we will need
for WireGuard), then this the new way should only affect libnm-core,
not require changes elsewhere.
- it's very inefficient to itereate over all settings. It involves
cloning and sorting the list of settings, and retrieve and clone all
GObject properties. Only to look at secret properties alone.
_nm_connection_aggregate() is supposed to be more flexible then just
the two new aggregate types that perform a "find-any" search. The
@arg argument and boolean return value can suffice to implement
different aggregation types in the future.
Also fixes the check of NMAgentManager for secret flags for VPNs
(NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS). A secret for VPNs
is a property that either has a secret or a secret-flag. The previous
implementation would only look at present secrets and
check their flags. It wouldn't check secret-flags that are
NM_SETTING_SECRET_FLAG_NONE, but have no secret.
There are 3 kinds of secret flag implementations:
1) regular properties have a GObject property and a corresponding
"-flags" property.
2) NMSettingVpn handles this entirely differently
3) NMSettingWirelessSecurity's WEP keys, where the secret keys
share a flags property that does not follow the same naming
scheme as 1).
The getter and setter had a boolean "verifiy_secret", only to
handle 3). Drop that parameter. Don't let NMSettingWirelessSecurity
call the parent's implementation for WEP keys. Just let it handle
it directly.
We have a concept of setting and property meta-data that extends plain
GObject properties. While most properties are indeed backed by an
implemented as a GObject property, some are not.
Reuse the object property meta-data instead of fetching the list of
properties. Note that there is not much change in behavior, because
at all places where this is done, properties which are not backed by a
GObject property are skipped for the moment.
If nothing else, we save needlessly cloning the property list.
Later possibly we may no longer want to do that and add virtual
functions that can handle all properties.
We will need access to the serialization flags from within the synth_func().
That will be for WireGuard's peers. Peers are a list of complex, structured
elements, and some fields (the peer's preshared-key) are secret and
others are not. So when serializing the peers, we need to know whether
to include secrets or not.
Instead of letting _nm_setting_to_dbus() check the flags, pass them
down.
While at it, don't pass the property_name argument. Instead, pass the
entire meta-data information we have. Most synth functions don't care
about the property or the name either way. But we should not pre-filter
information that we have at hand. Just pass it to the synth function.
If the synth function would be public API, that would be a reason to be
careful about what we pass. But it isn't and it only has one caller.
So passing it along is fine. Also, do it now when adding the flags
argument, as we touch all synth implementations anyway.
We shall not shortcut the synth function. If the synth function is
unhappy about a missing NMConnection argument, then that needs to be
fixed.
So, revert 395c385b9 and fix the issue in nm_setting_wireless_get_security()
differently. I presume that is the only place that caused problems,
since the history of the patch does not clealy show what the problem
was.
This reverts commit 395c385b9b.