Commit graph

332 commits

Author SHA1 Message Date
Thomas Haller
915e923928
libnm: normalize empty strings in 802-1x setting
Supplicant does not allow setting certain properties to empty values.
It also does not make sense.

Also, ifcfg-rh writer uses svSetValueStr() for these properties, so
the ifcfg plugin would always loose having hte values set to "".

Also, you couldn't enter these strings in nmcli.

It's fair to assume that it makes no sense to have these values set to
an empty value. Since we cannot just tighten up verification to reject
them, normalize them.

It also seems that some GUI now starts setting domain_suffix_match to an
empty string. Or maybe it was always doing it, and ifcfg plugin just hid
the problem? Anyway, we have users out there who set these properties to
"".

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/973
2022-04-06 13:48:04 +02:00
Thomas Haller
445e783771
libnm: fix printing NULL value in NMSetting8021x.verify() 2022-04-06 13:47:21 +02:00
Thomas Haller
79f676c83a
crypto: move nm_crypto_read_file() to "libnm-glib-aux"
It has no actual dependency on the crypto library. All it does, is
to be careful about not leaking secrets in memory. We have code
for that in libnm-glib-aux already. Move.

The goal is to reduce the number of places where we use libnm-crypto,
because that has a large dependency. libnm-glib-aux is a very light
dependency instead.
2022-03-29 11:56:04 +02:00
Thomas Haller
723e1fc76f
libnm: move dependency to libnm-crypto out of libnm-core's "nm-utils.c"
libnm-core is also used by the daemon, thus currently dragging in
libnm-crypto there. But could we ever drop that dependency?

One use of the libnm-crypto is in functions like nm_utils_file_is_certificate()
in "nm-utils.h". These are part of the public API of libnm.

But this is not used by the daemon. Move it to "libnm-client-core"
to be closer to where it's actually used.

As we have unit tests in "libnm-core-impl/tests" that test this function,
those unit tests also would need to move to "libnm-client-impl".
Instead, add the actual implementation of these function to "libnm-crypto"
and test it there.

This patch moves forward declarations from public header "nm-utils.h" to
"nm-client.h". Arguably, "nm-client.h" is not a great name, but we don't
have a general purpose header in "libnm-client-public", so use this.
Note that libnm users can only include <NetworkManager.h> and including
individual files is not supported (and even prevented). Thus moving
the declarations won't break any users.
2022-03-29 11:56:04 +02:00
Thomas Haller
901787e06f
build: move nm-crypto to separate directory "src/libnm-crypto"
libnm-core currently has a dependency on crypto libraries (either
"gnutls", "nss" or "null"). We need this huge dependency for few cases.

Move the crypto code to a separate static library"src/libnm-crypto/libnm-crypto.la".
The reasoning is that it becomes clearer where we have this dependency,
to use it more consciously, and to be better see how it's used.

We clearly need the crypto functionality in libnm. But do we also need
it in the daemon? Could we ever link the daemon without crypto libraries?

The goal of splitting the crypto part out, to better understand the
crypto dependency.
2022-03-29 11:56:04 +02:00
Thomas Haller
3a97604a27
libnm: don't depend nm-crypto on "nm-error.h"
"nm-error.h" is public API of libnm, and contains error numbers and
quarks. Clearly our "nm-crypto" implementation wants to use those
errors.

I want to move "nm-crypto" out of libnm, and as it's more basic, I think
it should not have a dependency on all of libnm-core. Also because
libnm-core currently uses nm-crypto, so there would be a circular
dependency. Which would be possible to do (libnm-core-aux-intern is
also used in such a way). But it's better avoided, to have clear
hierarchy of dependencies.

Add a version of the same error codes to libnm-base. libnm-base is a
very basic dependency (just one step above libnm-glib-aux).
2022-03-29 11:56:03 +02:00
Thomas Haller
34b4496028
libnm: no longer use "nm-utils.h" from "nm-crypto.c"
The goal is to make "nm-crypto.c" independent of libnm-core.
2022-03-29 11:56:03 +02:00
Thomas Haller
526a05d6f2
glib-aux: add _nm_utils_bin2hexstr() and use from nm_utils_bin2hexstr()
nm_utils_bin2hexstr() is part of public libnm API.
That means, if we want to use this function, we need to link with
libnm-core-impl.

This is used by "nm-crypto.c". That file is currently part of
libnm-core, but that will change.

Move the implementation to libnm-glib-aux, so that we can use this code
from all our glib-based code (because all our glib-based code is allowed
to link with libnm-glib-aux).
2022-03-29 11:56:03 +02:00
Thomas Haller
ee1467fcdb
libnm/802-1x: check is-pkcs12 only for blob certificates in verify_tls()
If the certificate is not a blob, it makes no sense to call
nm_crypto_is_pkcs12_data().
2022-03-29 11:52:38 +02:00
Thomas Haller
d3a6b9e7cc
libnm/802-1x: move need_private_key_password() to need_secrets_tls()
When a static function only has one caller, it is often simpler to not
have the code in a separate function. Drop need_private_key_password()
and move it to need_secrets_tls().
2022-03-29 11:52:37 +02:00
Thomas Haller
bcb1ab9e1c
libnm/802-1x: don't use g_warning() in need_secrets_tls()
g_warning() for unexpected scheme is not right. Either, this should be an
assertion (and never be hit), or the library should be silent about conditions
that can happen regularly.
2022-03-29 11:52:37 +02:00
Thomas Haller
e4a7b671d6
libnm/802-1x: cleanup duplicate code paths in need_secrets_tls()
I think code is easier to understand, if the difference (between phase1
and phase2) is pushed to the bottom. Having one large "if(phase2){}else{}"
at the top makes it harder to compare the two branches and see where
they differ.
2022-03-29 11:52:37 +02:00
Thomas Haller
47f2c5e5db
libnm/802-1x: cleanup need_secrets_phase2() 2022-03-29 11:52:37 +02:00
Thomas Haller
a3aec9dc5c
libnm/802-1x: reuse verify_identity() in verify_ttls() implementation 2022-03-29 11:52:37 +02:00
Thomas Haller
d5ee67981c
libnm/802-1x: simplify verify_tls() for phase1 and phase2
The checks are duplicated and verbose. Combine them.
2022-03-29 11:52:33 +02:00
Thomas Haller
782f2fa8ef
keyfile: don't require verified profile in nm_keyfile_write()
Previously, only the daemon was writing keyfiles, and it ensures
that they are always valid.

As we now have this function as public API of libnm, we should drop this
restriction and write the profile the best we can. Granted, an invalid
profile may not be expressed in keyfile format, and the result is
undefined. But make the best of it.
2022-03-28 18:27:37 +02:00
Thomas Haller
b07bf1a8bb
keyfile: add write_handle_warn() helper 2022-03-28 18:27:37 +02:00
Thomas Haller
cec1269795
keyfile: rename handle_warn() to read_handle_warn()
We will also want to warn during write.
2022-03-28 18:27:36 +02:00
Thomas Haller
cfe594903e
keyfile: simplify code path in write_setting_value()
Avoid nested blocks. Check one condition after the other and handle it.
2022-03-28 18:27:36 +02:00
Thomas Haller
a0db72bf6d
keyfile: use nm_setting_8021x_scheme_vtable_by_setting_key() helper in cert_writer() 2022-03-28 18:27:36 +02:00
Thomas Haller
e965aa2536
libnm: add nm_setting_8021x_scheme_vtable_by_setting_key() helper
Add function to lookup the vtable by name. Implement a binary search.
2022-03-28 18:27:36 +02:00
Thomas Haller
22dcfb3a67
libnm: fix update of cached option names in nm_setting_option_set()
This is severe. We cache the list of names, and we must invalidate the
cache when the names change. Otherwise, out-of-bound access and crash.

Fixes: d0192b698e ('libnm: add nm_setting_option_set(), nm_setting_option_get_boolean(), nm_setting_option_set_boolean()')
Fixes: 150af44e10 ('libnm: add nm_setting_option_get_uint32(), nm_setting_option_set_uint32()')
2022-03-28 18:27:35 +02:00
Thomas Haller
aaf2155023
libnm/docs: fix documentation for "proxy.pac-script" 2022-03-21 15:21:37 +01:00
Thomas Haller
2ffa6f7693
libnm/doc: clarify behavior for autoconnect in man nm-settings 2022-03-16 10:10:13 +01:00
Thomas Haller
20060327d4
libnm/docs: add reference to secret-key in description for stable-id 2022-03-11 09:27:33 +01:00
Thomas Haller
b8f689ac53
all: add support for route type "throw"
After adding support for "blackhole", "unreachable" and "prohibit" route
types, let's also add support for "throw" type. It works basically the
same as the other types, so supporting it seems very straight forward.

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1124
2022-02-28 17:17:03 +01:00
Thomas Haller
dab2ee8ac5
all: suppress wrong gcc-12 warning "-Wdangling-pointer"
gcc-12.0.1-0.8.fc36 is annoying with false positives.
It's related to g_error() and its `for(;;) ;`.

For example:

    ../src/libnm-glib-aux/nm-shared-utils.c: In function 'nm_utils_parse_inaddr_bin_full':
    ../src/libnm-glib-aux/nm-shared-utils.c:1145:26: error: dangling pointer to 'error' may be used [-Werror=dangling-pointer=]
     1145 |                     error->message);
          |                          ^~
    /usr/include/glib-2.0/glib/gmessages.h:343:32: note: in definition of macro 'g_error'
      343 |                                __VA_ARGS__);         \
          |                                ^~~~~~~~~~~
    ../src/libnm-glib-aux/nm-shared-utils.c:1133:31: note: 'error' declared here
     1133 |         gs_free_error GError *error = NULL;
          |                               ^~~~~
    /usr/include/glib-2.0/glib/gmessages.h:341:25: error: dangling pointer to 'addrbin' may be used [-Werror=dangling-pointer=]
      341 |                         g_log (G_LOG_DOMAIN,         \
          |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      342 |                                G_LOG_LEVEL_ERROR,    \
          |                                ~~~~~~~~~~~~~~~~~~~~~~~
      343 |                                __VA_ARGS__);         \
          |                                ~~~~~~~~~~~~
    ../src/libnm-glib-aux/nm-shared-utils.c:1141:13: note: in expansion of macro 'g_error'
     1141 |             g_error("unexpected assertion failure: could parse \"%s\" as %s, but not accepted by "
          |             ^~~~~~~
    ../src/libnm-glib-aux/nm-shared-utils.c:1112:14: note: 'addrbin' declared here
     1112 |     NMIPAddr addrbin;
          |              ^~~~~~~

I think the warning could potentially be useful and prevent real bugs.
So don't disable it altogether, but go through the effort to suppress it
at the places where it currently happens.

Note that NM_PRAGMA_WARNING_DISABLE_DANGLING_POINTER macro only expands
to suppressing the warning with __GNUC__ equal to 12. The purpose is to
only suppress the warning where we know we want to. Hopefully other gcc
versions don't have this problem.

I guess, we could also write a NM_COMPILER_WARNING() check in
"m4/compiler_options.m4", to disable the warning if we detect it. But
that seems too cumbersome.
2022-02-21 19:50:52 +01:00
Christian Eggers
b26c9723d9
libnm-crypto: add new option for no cryptography
For some embedded systems, no cryptography is required at all (e.g when
only using Ethernet).

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1108
2022-02-21 19:12:27 +01:00
Thomas Haller
700e4daf12
libnm: change error message about routing-rules without priority
When you do

  $ nmcli connection modify "$PROFILE" +ipv4.routing-rules 'uidrange 1000-1000 lookup 12345'
  Error: failed to modify ipv4.routing-rules: rule is invalid: invalid priority.

That message seems confusing. Reword.
2022-02-18 20:12:43 +01:00
Ana Cabral
27c33d15ef keyfile: do not write empty string list properties
https://bugzilla.redhat.com/show_bug.cgi?id=2022623
2022-02-11 12:26:01 +01:00
Ana Cabral
20aa8d049c keyfile: write ethernet group always on the top of the file 2022-02-11 12:26:01 +01:00
Thomas Haller
98da5e0491
libnm: rework strv properties of NMSetting as "direct" properties
Make use of direct strv property in some cases. It doesn't work for
other cases yet, because they are implemented differently, and porting
them is more effort and needs to be done one by one.

The goal is to have a unified, standard implementation for our
properties. One that requires a minimal amount of property-specific
code. For strv properties, that is a bit more cumbersome, because
usually there are multiple C accessor functions. Still, make an effort
to have a "direct" strv property.

What this also gives, is that we no longer need to clone the strv array
for various operations. We know how to access the data, and can do it
directly without g_object_get()/g_object_set().
2022-02-10 22:30:27 +01:00
Thomas Haller
61ff2b03df
libnm: add direct strv type for NMSetting and use it for "match.interface-name"
G_TYPE_STRV is the last property type in NMSetting that is implemented
by directly accessing the GObect property. Note that we have lots of
override, non-default implementations that still use GObject properties,
but I am talking here about properties that don't have a special
implementation and use a G_TYPE_STRV GObject property.

Add a "direct" implementation also for strv arrays.

The advantage is that we no longer call g_value_get() for various
operations, which requires a deep-copy of the strv array. The other
advantage is that we will get a unified approach for implementing strv
properties. In particular strv arrays need a lot of code to implement,
and most settings do it differently. By adding a general mechanism,
this code (and behavior) can be unified.

Showcase it on "match.interface-name".
2022-02-10 22:30:27 +01:00
Thomas Haller
948c2b0fb1
libnm/doc: describe routing-rules in man nm-settings-nmcli 2022-02-09 23:10:58 +01:00
Thomas Haller
7b1e9a5c3d
libnm/doc: list route attributes in man nm-settings-nmcli
IPv4:

       routes
           A list of IPv4 destination addresses, prefix length, optional IPv4
           next hop addresses, optional route metric, optional attribute. The
           valid syntax is: "ip[/prefix] [next-hop] [metric]
           [attribute=val]...[,ip[/prefix]...]". For example "192.0.2.0/24
           10.1.1.1 77, 198.51.100.0/24".

           Various attributes are supported:

           •   "cwnd" - an unsigned 32 bit integer.

           •   "initcwnd" - an unsigned 32 bit integer.

           •   "initrwnd" - an unsigned 32 bit integer.

           •   "lock-cwnd" - a boolean value.

           •   "lock-initcwnd" - a boolean value.

           •   "lock-initrwnd" - a boolean value.

           •   "lock-mtu" - a boolean value.

           •   "lock-window" - a boolean value.

           •   "mtu" - an unsigned 32 bit integer.

           •   "onlink" - a boolean value.

           •   "scope" - an unsigned 8 bit integer. IPv4 only.

           •   "src" - an IPv4 address.

           •   "table" - an unsigned 32 bit integer. The default depends on
               ipv4.route-table.

           •   "tos" - an unsigned 8 bit integer. IPv4 only.

           •   "type" - one of unicast, local, blackhole, unavailable,
               prohibit. The default is unicast.

           •   "window" - an unsigned 32 bit integer.

           For details see also `man ip-route`.

           Format: a comma separated list of routes

IPv6:

       routes
           A list of IPv6 destination addresses, prefix length, optional IPv6
           next hop addresses, optional route metric, optional attribute. The
           valid syntax is: "ip[/prefix] [next-hop] [metric]
           [attribute=val]...[,ip[/prefix]...]".

           Various attributes are supported:

           •   "cwnd" - an unsigned 32 bit integer.

           •   "from" - an IPv6 address with optional prefix. IPv6 only.

           •   "initcwnd" - an unsigned 32 bit integer.

           •   "initrwnd" - an unsigned 32 bit integer.

           •   "lock-cwnd" - a boolean value.

           •   "lock-initcwnd" - a boolean value.

           •   "lock-initrwnd" - a boolean value.

           •   "lock-mtu" - a boolean value.

           •   "lock-window" - a boolean value.

           •   "mtu" - an unsigned 32 bit integer.

           •   "onlink" - a boolean value.

           •   "src" - an IPv6 address.

           •   "table" - an unsigned 32 bit integer. The default depends on
               ipv6.route-table.

           •   "type" - one of unicast, local, blackhole, unavailable,
               prohibit. The default is unicast.

           •   "window" - an unsigned 32 bit integer.

           For details see also `man ip-route`.

           Format: a comma separated list of routes
2022-02-09 22:33:23 +01:00
Thomas Haller
84598adddf
libnm: allow configuring blackhole/unreachable/prohibit routes 2022-02-09 19:13:05 +01:00
Thomas Haller
0413b1bf8a
libnm: rework validating route attributes to avoid duplicate check
_nm_ip_route_attribute_validate_all() validates all attributes together.
As such, it calls to nm_ip_route_attribute_validate(), which in turn
validates one attribute at a time.

Such full validation needs to check that (potentially conflicting)
attributes are valid together. Hence, _nm_ip_route_attribute_validate_all()
needs again peek into the attributes.

Refactor the code, so that we can extract the pieces that we need and
not need to parse them twice.
2022-02-09 19:13:02 +01:00
Thomas Haller
6f277d8fa6
libnm: change NMVariantAttributeSpec.str_type to work for attributes of any type
First of all, all of NMVariantAttributeSpec is internal API. We only
expose the typedef itself as public API, but not its fields nor
their meaning. So we can change things.

Change "str_type" to "type_detail", so that it can work for any kind of
attribute, not only for strings. Usually, we want to avoid special
cases and treat all attributes the same, based on their GVariant type.
But sometimes, it is necessary to do something special with an
attribute. This is what the "type_detail" encodes, but it's not only
relevant for strings.
2022-02-09 19:13:02 +01:00
Thomas Haller
00e4f21629
libnm: avoid parsing IP addresses twice in NMIPAddress/NMIPRoute API
Usually the normalization (canonicalize) and validation of the IP
address string both requires to parse the string. As we always do
validation first, we can use the parsed address and don't need to parse
it a second time.
2022-02-09 19:13:02 +01:00
Thomas Haller
6208a1bb84
libnm: reorder fields in NMIPAddress/NMIPRoute struct
Order the fields by their size, to minimize the alignment gaps.
I guess, that doesn't matter because the alignment of the heap
allocation is larger than what we can safe here. Still, there is
on reason to do it any other way.

Also, it's not possible via API to set family/prefix to values outside
their range, so an 8bit integer is always sufficient. And we don't want
that invariant to change. We don't ever want to allow the caller to set
values that are clearly invalid, and will assert against that early (g_return()).
Point is, we can do this and there is no danger of future problems.
And even if we will support larger values, it's all an implementation
detail anyway.
2022-02-09 19:13:02 +01:00
Thomas Haller
e62792ff38
all: adjust glib-mkenums annotations for automated formatting
The annotation results in bad formatting. Work around.
2022-02-08 11:14:01 +01:00
Thomas Haller
b5b9a109e1
libnm: fix bug verifying private-key for WireGuard setting
Fixes: aea47ed206 ('libnm: implement "wireguard.private-key" as direct string property')
2022-01-20 22:22:41 +01:00
Thomas Haller
6f0e22a64a
libnm/tests: fix maybe-uninitialized warning in "test-setting"
In function '_nm_auto_g_free',
      inlined from 'test_tc_config_tfilter_matchall_mirred' at src/libnm-core-impl/tests/test-setting.c:2955:24:
  ./src/libnm-glib-aux/nm-macros-internal.h:58:1: error: 'str' may be used uninitialized [-Werror=maybe-uninitialized]
     58 | NM_AUTO_DEFINE_FCN_VOID0(void *, _nm_auto_g_free, g_free);
        | ^
  src/libnm-core-impl/tests/test-setting.c: In function 'test_tc_config_tfilter_matchall_mirred':
  src/libnm-core-impl/tests/test-setting.c:2955:24: note: 'str' was declared here
   2955 |     gs_free char      *str;
        |                        ^
  lto1: all warnings being treated as errors
  lto-wrapper: fatal error: gcc returned 1 exit status
2022-01-20 21:53:23 +01:00
Thomas Haller
25aa6c0552
libnm: don't clear secrets during NMSimpleConnection:dispose()
NMConnection is an interface, implemented by NMSimpleConnection
and NMRemoteConnection. A connection is basically a set of NMSetting
instances.

Usually you would expect that one NMSetting instance only gets added to
zero or one NMConnection. It seems a bit ugly, to have one setting tracked by
multiple NMConnection. Still, technically I am not aware of a single problem
with doing that, where it not for NMSimpleConnection:dispose() to clear the
secrets.

There is no need to clear the secrets of an NMSetting, when the
NMConnection gets destroyed. Either this destroys the NMSetting instance
right away (and NMSetting's destructor will clear the secrets anyway), or
somebody else (e.g. another NMConnection instance), keeps the setting
alive. In the latter case, it is wrong to clear the secrets at
this point.

This was done since commit 6a19e68a7d ('libnm-core: clear secrets from
NMSimpleConnection and NMSettingsConnection dispose()'), but let's stop
doing that.

This also causes problems in practice, see [1].

[1] https://gitlab.gnome.org/GNOME/gnome-control-center/-/merge_requests/1099#note_1334333

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/876

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1056
2022-01-19 13:42:17 +01:00
Thomas Haller
87ca5875d0
libnm: add and use _nm_setting_get_private_field() helper
All callers of _nm_setting_get_private() got the offset from the
property info. Add a wrapper _nm_setting_get_private_field() that
takes the property info. This way, it can add some assertions.
2022-01-18 16:25:24 +01:00
Thomas Haller
68b6aa64fd
libnm: for embedded private structure in NMSetting set the offset to zero
Preferably, we embed the private struct in the GObject struct itself.
In the past, we didn't do that, because the struct was in public headers
and changing that would have been an ABI break. For those struct, we
still use g_type_class_add_private().

We have some structs, where the private struct is embedded. An
alternative to that would be, to not have the private struct at all,
like done for NMSettingOvsBridge.

Anyway. So for direct properties we need to capture the offset of the
field (in the private struct). We can either set the offset of the
private struct in _nm_setting_class_commit() to zero and let the field
offset include the private structure offset. Or, the offset of the
private struct is accounted during _nm_setting_class_commit().

Both approaches are basically the same. Just do it consistently. For no
particular reason, choose to set the offset of the private data to zero
for those types.
2022-01-18 16:22:45 +01:00
Thomas Haller
9cf9ab3cf0
libnm/tests: add test for direct string property of kind NMRefString
In particular, that the NMRefString gets destroyed when we destroy
all NMSetting instances.
2022-01-18 16:22:42 +01:00
Thomas Haller
d36aaf91fa
libnm: make "connection.type" property a NMRefString 2022-01-18 16:22:40 +01:00
Thomas Haller
419be57dbc
libnm: support direct string properties as NMRefString
Several properties like "connection.type" are enum-like and only take a few
known values. We can use a NMRefString to share their instances.

Currently nm_setting_duplicate() does not yet explicitly handle direct properties.
But it should, because it can handle them more efficiently. If it would do that, it
would be very cheap to "copy" a NMRefString. But even with the current implementation
will the result be deduplicated.
2022-01-18 16:22:38 +01:00
Thomas Haller
39c308f370
libnm: cleanup redundant code for direct properties of NMSetting 2022-01-18 16:22:32 +01:00