mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-10 18:20:37 +01:00
wireguard: merge branch 'th/wireguard-pt3'
https://github.com/NetworkManager/NetworkManager/pull/295
This commit is contained in:
commit
4aaa0ed482
30 changed files with 5274 additions and 31 deletions
|
|
@ -670,6 +670,7 @@ libnm_core_lib_h_pub_real = \
|
|||
libnm-core/nm-setting-wifi-p2p.h \
|
||||
libnm-core/nm-setting-wimax.h \
|
||||
libnm-core/nm-setting-wired.h \
|
||||
libnm-core/nm-setting-wireguard.h \
|
||||
libnm-core/nm-setting-wireless-security.h \
|
||||
libnm-core/nm-setting-wireless.h \
|
||||
libnm-core/nm-setting-wpan.h \
|
||||
|
|
@ -739,6 +740,7 @@ libnm_core_lib_c_settings_real = \
|
|||
libnm-core/nm-setting-wifi-p2p.c \
|
||||
libnm-core/nm-setting-wimax.c \
|
||||
libnm-core/nm-setting-wired.c \
|
||||
libnm-core/nm-setting-wireguard.c \
|
||||
libnm-core/nm-setting-wireless-security.c \
|
||||
libnm-core/nm-setting-wireless.c \
|
||||
libnm-core/nm-setting-wpan.c
|
||||
|
|
|
|||
|
|
@ -177,6 +177,7 @@ EXTRA_DIST += \
|
|||
examples/python/gi/get_ips.py \
|
||||
examples/python/gi/list-connections.py \
|
||||
examples/python/gi/nm-connection-update-stable-id.py \
|
||||
examples/python/gi/nm-wg-set \
|
||||
examples/python/gi/setting-user-data.py \
|
||||
examples/python/gi/show-wifi-networks.py \
|
||||
examples/python/gi/update-ip4-method.py \
|
||||
|
|
|
|||
3
NEWS
3
NEWS
|
|
@ -14,6 +14,9 @@ USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE!
|
|||
* Use a new type of secret-keys that combines the secret value with /etc/machine-id.
|
||||
This way when cloning a VM it suffices to change machine-id to generate different
|
||||
addresses.
|
||||
* Add support for WireGuard VPN tunnels to NetworkManager. D-Bus API and libnm
|
||||
support all options. nmcli supports creating and managing WireGuard profiles,
|
||||
with the exception of configuring and showing peers.
|
||||
|
||||
The following changes were backported to 1.14.x releases between 1.14.0
|
||||
and 1.14.2 are also present in NetworkManager-1.14:
|
||||
|
|
|
|||
|
|
@ -822,6 +822,7 @@ const NmcMetaGenericInfo *const metagen_con_active_vpn[_NMC_GENERIC_INFO_TYPE_CO
|
|||
NM_SETTING_VXLAN_SETTING_NAME"," \
|
||||
NM_SETTING_WPAN_SETTING_NAME","\
|
||||
NM_SETTING_6LOWPAN_SETTING_NAME","\
|
||||
NM_SETTING_WIREGUARD_SETTING_NAME","\
|
||||
NM_SETTING_PROXY_SETTING_NAME"," \
|
||||
NM_SETTING_TC_CONFIG_SETTING_NAME"," \
|
||||
NM_SETTING_SRIOV_SETTING_NAME"," \
|
||||
|
|
|
|||
|
|
@ -7504,6 +7504,28 @@ static const NMMetaPropertyInfo *const property_infos_WIRED[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
#undef _CURRENT_NM_META_SETTING_TYPE
|
||||
#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_WIREGUARD
|
||||
static const NMMetaPropertyInfo *const property_infos_WIREGUARD[] = {
|
||||
PROPERTY_INFO_WITH_DESC (NM_SETTING_WIREGUARD_PRIVATE_KEY,
|
||||
.is_secret = TRUE,
|
||||
.property_type = &_pt_gobject_string,
|
||||
),
|
||||
PROPERTY_INFO_WITH_DESC (NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS,
|
||||
.property_type = &_pt_gobject_secret_flags,
|
||||
),
|
||||
PROPERTY_INFO_WITH_DESC (NM_SETTING_WIREGUARD_LISTEN_PORT,
|
||||
.property_type = &_pt_gobject_int,
|
||||
),
|
||||
PROPERTY_INFO_WITH_DESC (NM_SETTING_WIREGUARD_FWMARK,
|
||||
.property_type = &_pt_gobject_int,
|
||||
.property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, \
|
||||
.base = 16,
|
||||
),
|
||||
),
|
||||
NULL
|
||||
};
|
||||
|
||||
#undef _CURRENT_NM_META_SETTING_TYPE
|
||||
#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_WIRELESS
|
||||
static const NMMetaPropertyInfo *const property_infos_WIRELESS[] = {
|
||||
|
|
@ -8001,6 +8023,7 @@ _setting_init_fcn_wireless (ARGS_SETTING_INIT_FCN)
|
|||
#define SETTING_PRETTY_NAME_WIFI_P2P N_("Wi-Fi P2P connection")
|
||||
#define SETTING_PRETTY_NAME_WIMAX N_("WiMAX connection")
|
||||
#define SETTING_PRETTY_NAME_WIRED N_("Wired Ethernet")
|
||||
#define SETTING_PRETTY_NAME_WIREGUARD N_("WireGuard VPN settings")
|
||||
#define SETTING_PRETTY_NAME_WIRELESS N_("Wi-Fi connection")
|
||||
#define SETTING_PRETTY_NAME_WIRELESS_SECURITY N_("Wi-Fi security settings")
|
||||
#define SETTING_PRETTY_NAME_WPAN N_("WPAN settings")
|
||||
|
|
@ -8264,6 +8287,12 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = {
|
|||
NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE),
|
||||
),
|
||||
),
|
||||
SETTING_INFO (WIREGUARD,
|
||||
.valid_parts = NM_META_SETTING_VALID_PARTS (
|
||||
NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE),
|
||||
NM_META_SETTING_VALID_PART_ITEM (WIREGUARD, TRUE),
|
||||
),
|
||||
),
|
||||
SETTING_INFO (WIRELESS,
|
||||
.alias = "wifi",
|
||||
.valid_parts = NM_META_SETTING_VALID_PARTS (
|
||||
|
|
|
|||
|
|
@ -214,6 +214,32 @@ _secret_real_new_vpn_secret (const char *pretty_name,
|
|||
return &real->base;
|
||||
}
|
||||
|
||||
static NMSecretAgentSimpleSecret *
|
||||
_secret_real_new_wireguard_peer_psk (NMSettingWireGuard *s_wg,
|
||||
const char *public_key,
|
||||
const char *preshared_key)
|
||||
{
|
||||
SecretReal *real;
|
||||
|
||||
nm_assert (NM_IS_SETTING_WIREGUARD (s_wg));
|
||||
nm_assert (public_key);
|
||||
|
||||
real = g_slice_new (SecretReal);
|
||||
*real = (SecretReal) {
|
||||
.base.secret_type = NM_SECRET_AGENT_SECRET_TYPE_WIREGUARD_PEER_PSK,
|
||||
.base.pretty_name = g_strdup_printf (_("Preshared-key for %s"),
|
||||
public_key),
|
||||
.base.entry_id = g_strdup_printf (NM_SETTING_WIREGUARD_SETTING_NAME"."NM_SETTING_WIREGUARD_PEERS".%s."NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY,
|
||||
public_key),
|
||||
.base.value = g_strdup (preshared_key),
|
||||
.base.is_secret = TRUE,
|
||||
.base.no_prompt_entry_id = TRUE,
|
||||
.setting = NM_SETTING (g_object_ref (s_wg)),
|
||||
.property = g_strdup (public_key),
|
||||
};
|
||||
return &real->base;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
|
|
@ -405,8 +431,8 @@ add_vpn_secret_helper (GPtrArray *secrets, NMSettingVpn *s_vpn, const char *name
|
|||
|
||||
static gboolean
|
||||
add_vpn_secrets (RequestData *request,
|
||||
GPtrArray *secrets,
|
||||
char **msg)
|
||||
GPtrArray *secrets,
|
||||
char **msg)
|
||||
{
|
||||
NMSettingVpn *s_vpn = nm_connection_get_setting_vpn (request->connection);
|
||||
const VpnPasswordName *secret_names, *p;
|
||||
|
|
@ -435,6 +461,74 @@ add_vpn_secrets (RequestData *request,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
add_wireguard_secrets (RequestData *request,
|
||||
GPtrArray *secrets,
|
||||
char **msg,
|
||||
GError **error)
|
||||
{
|
||||
NMSettingWireGuard *s_wg;
|
||||
NMSecretAgentSimpleSecret *secret;
|
||||
guint i;
|
||||
|
||||
s_wg = NM_SETTING_WIREGUARD (nm_connection_get_setting (request->connection, NM_TYPE_SETTING_WIREGUARD));
|
||||
if (!s_wg) {
|
||||
g_set_error (error, NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_FAILED,
|
||||
"Cannot service a WireGuard secrets request %s for a connection without WireGuard settings",
|
||||
request->request_id);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( !request->hints
|
||||
|| !request->hints[0]
|
||||
|| g_strv_contains (NM_CAST_STRV_CC (request->hints), NM_SETTING_WIREGUARD_PRIVATE_KEY)) {
|
||||
secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
|
||||
_("WireGuard private-key"),
|
||||
NM_SETTING (s_wg),
|
||||
NM_SETTING_WIREGUARD_PRIVATE_KEY);
|
||||
g_ptr_array_add (secrets, secret);
|
||||
}
|
||||
|
||||
if (request->hints) {
|
||||
|
||||
for (i = 0; request->hints[i]; i++) {
|
||||
NMWireGuardPeer *peer;
|
||||
const char *name = request->hints[i];
|
||||
gs_free char *public_key = NULL;
|
||||
|
||||
if (nm_streq (name, NM_SETTING_WIREGUARD_PRIVATE_KEY))
|
||||
continue;
|
||||
|
||||
if (NM_STR_HAS_PREFIX (name, NM_SETTING_WIREGUARD_PEERS".")) {
|
||||
const char *tmp;
|
||||
|
||||
tmp = &name[NM_STRLEN (NM_SETTING_WIREGUARD_PEERS".")];
|
||||
if (NM_STR_HAS_SUFFIX (tmp, "."NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY)) {
|
||||
public_key = g_strndup (tmp,
|
||||
strlen (tmp) - NM_STRLEN ("."NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY));
|
||||
}
|
||||
}
|
||||
|
||||
if (!public_key)
|
||||
continue;
|
||||
|
||||
peer = nm_setting_wireguard_get_peer_by_public_key (s_wg, public_key, NULL);
|
||||
|
||||
g_ptr_array_add (secrets, _secret_real_new_wireguard_peer_psk (s_wg,
|
||||
( peer
|
||||
? nm_wireguard_peer_get_public_key (peer)
|
||||
: public_key),
|
||||
( peer
|
||||
? nm_wireguard_peer_get_preshared_key (peer)
|
||||
: NULL)));
|
||||
}
|
||||
}
|
||||
|
||||
*msg = g_strdup_printf (_("Secrets are required to connect WireGuard VPN '%s'"),
|
||||
nm_connection_get_id (request->connection));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
GPid auth_dialog_pid;
|
||||
GString *auth_dialog_response;
|
||||
|
|
@ -820,6 +914,10 @@ request_secrets_from_ui (RequestData *request)
|
|||
if (!add_8021x_secrets (request, secrets))
|
||||
goto out_fail;
|
||||
}
|
||||
} else if (nm_connection_is_type (request->connection, NM_SETTING_WIREGUARD_SETTING_NAME)) {
|
||||
title = _("WireGuard VPN secret");
|
||||
if (!add_wireguard_secrets (request, secrets, &msg, &error))
|
||||
goto out_fail_error;
|
||||
} else if (nm_connection_is_type (request->connection, NM_SETTING_CDMA_SETTING_NAME)) {
|
||||
NMSettingCdma *s_cdma = nm_connection_get_setting_cdma (request->connection);
|
||||
|
||||
|
|
@ -980,10 +1078,13 @@ nm_secret_agent_simple_response (NMSecretAgentSimple *self,
|
|||
if (secrets) {
|
||||
GVariantBuilder conn_builder, *setting_builder;
|
||||
GVariantBuilder vpn_secrets_builder;
|
||||
GVariantBuilder wg_secrets_builder;
|
||||
GVariantBuilder wg_peer_builder;
|
||||
GHashTable *settings;
|
||||
GHashTableIter iter;
|
||||
const char *name;
|
||||
gboolean has_vpn = FALSE;
|
||||
gboolean has_wg = FALSE;
|
||||
|
||||
settings = g_hash_table_new (nm_str_hash, g_str_equal);
|
||||
for (i = 0; i < secrets->len; i++) {
|
||||
|
|
@ -1011,6 +1112,19 @@ nm_secret_agent_simple_response (NMSecretAgentSimple *self,
|
|||
g_variant_builder_add (&vpn_secrets_builder, "{ss}",
|
||||
secret->property, secret->base.value);
|
||||
break;
|
||||
case NM_SECRET_AGENT_SECRET_TYPE_WIREGUARD_PEER_PSK:
|
||||
if (!has_wg) {
|
||||
g_variant_builder_init (&wg_secrets_builder, G_VARIANT_TYPE ("aa{sv}"));
|
||||
has_wg = TRUE;
|
||||
}
|
||||
g_variant_builder_init (&wg_peer_builder, G_VARIANT_TYPE ("a{sv}"));
|
||||
g_variant_builder_add (&wg_peer_builder, "{sv}",
|
||||
NM_WIREGUARD_PEER_ATTR_PUBLIC_KEY, g_variant_new_string (secret->property));
|
||||
g_variant_builder_add (&wg_peer_builder, "{sv}",
|
||||
NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY, g_variant_new_string (secret->base.value));
|
||||
g_variant_builder_add (&wg_secrets_builder, "a{sv}",
|
||||
&wg_peer_builder);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1020,6 +1134,12 @@ nm_secret_agent_simple_response (NMSecretAgentSimple *self,
|
|||
g_variant_builder_end (&vpn_secrets_builder));
|
||||
}
|
||||
|
||||
if (has_wg) {
|
||||
g_variant_builder_add (setting_builder, "{sv}",
|
||||
NM_SETTING_WIREGUARD_PEERS,
|
||||
g_variant_builder_end (&wg_secrets_builder));
|
||||
}
|
||||
|
||||
g_variant_builder_init (&conn_builder, NM_VARIANT_TYPE_CONNECTION);
|
||||
g_hash_table_iter_init (&iter, settings);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &setting_builder))
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ typedef enum {
|
|||
NM_SECRET_AGENT_SECRET_TYPE_PROPERTY,
|
||||
NM_SECRET_AGENT_SECRET_TYPE_SECRET,
|
||||
NM_SECRET_AGENT_SECRET_TYPE_VPN_SECRET,
|
||||
NM_SECRET_AGENT_SECRET_TYPE_WIREGUARD_PEER_PSK,
|
||||
} NMSecretAgentSecretType;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
|||
|
|
@ -362,6 +362,10 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_WIFI_P2P_WPS_METHOD N_("Flags indicating which mode of WPS is to be used. There's little point in changing the default setting as NetworkManager will automatically determine the best method to use.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIMAX_MAC_ADDRESS N_("If specified, this connection will only apply to the WiMAX device whose MAC address matches. This property does not change the MAC address of the device (known as MAC spoofing). Deprecated: 1")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIMAX_NETWORK_NAME N_("Network Service Provider (NSP) name of the WiMAX network this connection should use. Deprecated: 1")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_FWMARK N_("The use of fwmark is optional and is by default off. Setting it to 0 disables it. Otherwise it is a 32-bit fwmark for outgoing packets.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_LISTEN_PORT N_("The listen-port. If listen-port is not specified, the port will be chosen randomly when the interface comes up.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_PRIVATE_KEY N_("The 256 bit private-key in base64 encoding.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS N_("Flags indicating how to handle the \"private-key\" property.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WPAN_CHANNEL N_("IEEE 802.15.4 channel. A positive integer or -1, meaning \"do not set, use whatever the device is already set to\".")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WPAN_MAC_ADDRESS N_("If specified, this connection will only apply to the IEEE 802.15.4 (WPAN) MAC layer device whose permanent MAC address matches.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WPAN_PAGE N_("IEEE 802.15.4 channel page. A positive integer or -1, meaning \"do not set, use whatever the device is already set to\".")
|
||||
|
|
|
|||
|
|
@ -234,6 +234,7 @@ print ("NetworkManager version " + client.get_version())]]></programlisting></in
|
|||
<xi:include href="xml/nm-setting-wifi-p2p.xml"/>
|
||||
<xi:include href="xml/nm-setting-wimax.xml"/>
|
||||
<xi:include href="xml/nm-setting-wired.xml"/>
|
||||
<xi:include href="xml/nm-setting-wireguard.xml"/>
|
||||
<xi:include href="xml/nm-setting-wireless-security.xml"/>
|
||||
<xi:include href="xml/nm-setting-wireless.xml"/>
|
||||
<xi:include href="xml/nm-setting-wpan.xml"/>
|
||||
|
|
|
|||
423
examples/python/gi/nm-wg-set
Executable file
423
examples/python/gi/nm-wg-set
Executable file
|
|
@ -0,0 +1,423 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Copyright 2018 - 2019 Red Hat, Inc.
|
||||
|
||||
# nm-wg-set: modify an existing WireGuard connection profile.
|
||||
#
|
||||
# $ nm-wg-set [id|uuid|interface] ID [wg-args...]
|
||||
#
|
||||
# The arguments to set the parameters are like the set parameters from `man 8 wg`.
|
||||
# For example:
|
||||
#
|
||||
# $ nm-wg-set wg0 peer wN8G5HpphoXOGkiXTgBPyr9BhrRm2z9JEI6BiH6fB0g= preshared-key <(wg genpsk)
|
||||
#
|
||||
# extra, script specific arguments:
|
||||
# - private-key-flags
|
||||
# - preshared-key-flags
|
||||
#
|
||||
# Note that the arguments have some simliarities to `wg set` command. But this
|
||||
# script only modify the connection profile in NetworkManager. They don't (re)activate
|
||||
# the profile and thus the changes only result in the configuration of the kernel interface
|
||||
# after activating the profile. Use `nmcli connection up` for that.
|
||||
#
|
||||
# The example script does not support creating or deleting the WireGuard profile itself. It also
|
||||
# does not support modifying other settings of the connection profile, like the IP address configuation.
|
||||
# For that also use nmcli. For example:
|
||||
#
|
||||
# PROFILE=wg0
|
||||
#
|
||||
# # create the WireGuard profile with nmcli
|
||||
# PRIVKEY_FILE=/tmp/wg.key
|
||||
# (umask 077; rm -f "$PRIVKEY_FILE"; wg genkey > "$PRIVKEY_FILE")
|
||||
# IFNAME=wg0
|
||||
# PUBKEY=$(wg pubkey < "$PRIVKEY_FILE")
|
||||
# IP4ADDR=192.168.99.5/24
|
||||
# IP4GW=192.168.99.1
|
||||
# nmcli connection delete id "$PROFILE"
|
||||
# nmcli connection add \
|
||||
# type wireguard \
|
||||
# con-name "$PROFILE" \
|
||||
# ifname "$IFNAME" \
|
||||
# connection.stable-id "$PROFILE-$PUBKEY" \
|
||||
# ipv4.method manual \
|
||||
# ipv4.addresses "$IP4ADDR" \
|
||||
# ipv4.gateway "$IP4GW" \
|
||||
# ipv4.never-default yes \
|
||||
# ipv6.method link-local \
|
||||
# wireguard.listen-port 0 \
|
||||
# wireguard.fwmark 0 \
|
||||
# wireguard.private-key '' \
|
||||
# wireguard.private-key-flags 0
|
||||
# nmcli connection up \
|
||||
# id "$PROFILE" \
|
||||
# passwd-file <(echo "wireguard.private-key:$(cat "$PRIVKEY_FILE")")
|
||||
#
|
||||
# # modify the WireGuard profile with the script
|
||||
# nm-wg-set id "$PROFILE" $WG_ARGS
|
||||
|
||||
import sys
|
||||
import re
|
||||
|
||||
import gi
|
||||
gi.require_version('NM', '1.0')
|
||||
from gi.repository import NM
|
||||
|
||||
class MyError(Exception):
|
||||
pass
|
||||
|
||||
def pr(v):
|
||||
import pprint
|
||||
pprint.pprint(v, indent=4, depth=5, width=60)
|
||||
|
||||
###############################################################################
|
||||
|
||||
def connection_is_wireguard(conn):
|
||||
s_con = conn.get_setting(NM.SettingConnection)
|
||||
return s_con \
|
||||
and s_con.get_connection_type() == NM.SETTING_WIREGUARD_SETTING_NAME \
|
||||
and conn.get_setting(NM.SettingWireGuard)
|
||||
|
||||
def connection_to_str(conn):
|
||||
if connection_is_wireguard(conn):
|
||||
iface = conn.get_setting(NM.SettingConnection).get_interface_name()
|
||||
if iface:
|
||||
extra = ', interface: "%s"' % (iface)
|
||||
else:
|
||||
extra = ''
|
||||
else:
|
||||
extra = ', type: %s' % (conn.get_setting(NM.SettingConnection).get_connection_type())
|
||||
|
||||
return '"%s" (%s%s)' % (conn.get_id(), conn.get_uuid(), extra)
|
||||
|
||||
def connections_find(connections, con_spec, con_id):
|
||||
connections = list(sorted(connections, key=connection_to_str))
|
||||
l = []
|
||||
if con_spec in [None, 'id']:
|
||||
for c in connections:
|
||||
if con_id == c.get_id():
|
||||
if c not in l:
|
||||
l.append(c)
|
||||
if con_spec in [None, 'interface']:
|
||||
for c in connections:
|
||||
s_con = c.get_setting(NM.SettingConnection)
|
||||
if s_con \
|
||||
and con_id == s_con.get_interface_name():
|
||||
if c not in l:
|
||||
l.append(c)
|
||||
if con_spec in [None, 'uuid']:
|
||||
for c in connections:
|
||||
if con_id == c.get_uuid():
|
||||
if c not in l:
|
||||
l.append(c)
|
||||
return l
|
||||
|
||||
###############################################################################
|
||||
|
||||
def argv_get_one(argv, idx, type_ctor=None, topic=None):
|
||||
|
||||
if topic is not None:
|
||||
try:
|
||||
v = argv_get_one(argv, idx, type_ctor, None)
|
||||
except MyError as e:
|
||||
if isinstance(topic, (int, long)):
|
||||
topic = argv[topic]
|
||||
raise MyError('error for "%s": %s' % (topic, e.message))
|
||||
return v
|
||||
|
||||
v = None
|
||||
try:
|
||||
v = argv[idx]
|
||||
except:
|
||||
raise MyError('missing argument')
|
||||
if type_ctor is not None:
|
||||
try:
|
||||
v = type_ctor(v)
|
||||
except Exception as e:
|
||||
raise MyError('invalid argument "%s" (%s)' % (v, e.message))
|
||||
return v
|
||||
|
||||
###############################################################################
|
||||
|
||||
def arg_parse_secret_flags(arg):
|
||||
try:
|
||||
f = arg.strip()
|
||||
n = {
|
||||
'none': NM.SettingSecretFlags.NONE,
|
||||
'not-saved': NM.SettingSecretFlags.NOT_SAVED,
|
||||
'not-required': NM.SettingSecretFlags.NOT_REQUIRED,
|
||||
'agent-owned': NM.SettingSecretFlags.AGENT_OWNED,
|
||||
}.get(f)
|
||||
if n is not None:
|
||||
return n
|
||||
return NM.SettingSecretFlags(int(f))
|
||||
except Exception as e:
|
||||
raise MyError('invalid secret flags "%s"' % (arg))
|
||||
|
||||
def _arg_parse_int(arg, vmin, vmax, key, base = 0):
|
||||
try:
|
||||
v = int(arg, base)
|
||||
if v >= vmin and vmax <= 0xFFFFFFFF:
|
||||
return v
|
||||
except:
|
||||
raise MyError('invalid %s "%s"' % (key, arg))
|
||||
raise MyError("%s out of range" % (key))
|
||||
|
||||
def arg_parse_listen_port(arg):
|
||||
return _arg_parse_int(arg, 0, 0xFFFF, "listen-port")
|
||||
|
||||
def arg_parse_fwmark(arg):
|
||||
return _arg_parse_int(arg, 0, 0xFFFFFFFF, "fwmark", base = 0)
|
||||
|
||||
def arg_parse_persistent_keep_alive(arg):
|
||||
return _arg_parse_int(arg, 0, 0xFFFFFFFF, "persistent-keepalive")
|
||||
|
||||
def arg_parse_allowed_ips(arg):
|
||||
l = [s.strip() for s in arg.strip().split(',')]
|
||||
l = [s for s in l if s != '']
|
||||
l = list(l)
|
||||
# use a peer to parse and validate the allowed-ips.
|
||||
peer = NM.WireGuardPeer()
|
||||
for aip in l:
|
||||
if not peer.append_allowed_ip(aip, False):
|
||||
raise MyError('invalid allowed-ip "%s"' % (aip))
|
||||
return l
|
||||
|
||||
###############################################################################
|
||||
|
||||
def secret_flags_to_string(flags):
|
||||
nick = {
|
||||
NM.SettingSecretFlags.NONE: 'none',
|
||||
NM.SettingSecretFlags.NOT_SAVED: 'not-saved',
|
||||
NM.SettingSecretFlags.NOT_REQUIRED: 'not-required',
|
||||
NM.SettingSecretFlags.AGENT_OWNED: 'agent-owned',
|
||||
}.get(flags)
|
||||
num = str(int(flags))
|
||||
if nick is None:
|
||||
return num
|
||||
return '%s (%s)' % (num, nick)
|
||||
|
||||
###############################################################################
|
||||
|
||||
def wg_read_private_key(privkey_file):
|
||||
import base64
|
||||
try:
|
||||
with open(privkey_file, "r") as f:
|
||||
data = f.read()
|
||||
bdata = base64.decodestring(data)
|
||||
if len(bdata) != 32:
|
||||
raise Exception("not 32 bytes base64 encoded")
|
||||
return base64.encodestring(bdata).strip()
|
||||
except Exception as e:
|
||||
raise MyError('failed to read private key "%s": %s' % (privkey_file, e.message))
|
||||
|
||||
def wg_peer_is_valid(peer, msg = None):
|
||||
try:
|
||||
peer.is_valid(True, True)
|
||||
except gi.repository.GLib.Error as e:
|
||||
if msg is None:
|
||||
raise MyError('%s' % (e.message))
|
||||
else:
|
||||
raise MyError('%s' % (msg))
|
||||
|
||||
###############################################################################
|
||||
|
||||
def do_get(nm_client, connection):
|
||||
s_con = conn.get_setting(NM.SettingConnection)
|
||||
s_wg = conn.get_setting(NM.SettingWireGuard)
|
||||
|
||||
# Fetching secrets is not implemented. For now show them all as
|
||||
# <hidden>.
|
||||
|
||||
print('interface: %s' % (s_con.get_interface_name()))
|
||||
print('uuid: %s' % (conn.get_uuid()))
|
||||
print('id: %s' % (conn.get_id()))
|
||||
print('private-key: %s' % ('<hidden>'))
|
||||
print('private-key-flags: %s' % (secret_flags_to_string(s_wg.get_private_key_flags())))
|
||||
print('listen-port: %s' % (s_wg.get_listen_port()))
|
||||
print('fwmark: 0x%x' % (s_wg.get_fwmark()))
|
||||
for i in range(s_wg.get_peers_len()):
|
||||
peer = s_wg.get_peer(i)
|
||||
print('peer[%d].public-key: %s' % (i, peer.get_public_key()))
|
||||
print('peer[%d].preshared-key: %s' % (i, '<hidden>' if peer.get_preshared_key_flags() != NM.SettingSecretFlags.NOT_REQUIRED else ''))
|
||||
print('peer[%d].preshared-key-flags: %s' % (i, secret_flags_to_string(peer.get_preshared_key_flags())))
|
||||
print('peer[%d].endpoint: %s' % (i, peer.get_endpoint() if peer.get_endpoint() else ''))
|
||||
print('peer[%d].persistent-keepalive: %s' % (i, peer.get_persistent_keepalive()))
|
||||
print('peer[%d].allowed-ips: %s' % (i, ','.join([peer.get_allowed_ip(j) for j in range(peer.get_allowed_ips_len())])))
|
||||
|
||||
def do_set(nm_client, conn, argv):
|
||||
s_wg = conn.get_setting(NM.SettingWireGuard)
|
||||
peer = None
|
||||
peer_remove = False
|
||||
peer_idx = None
|
||||
peer_secret_flags = None
|
||||
|
||||
try:
|
||||
idx = 0
|
||||
while True:
|
||||
if peer \
|
||||
and ( idx >= len(argv) \
|
||||
or argv[idx] == 'peer'):
|
||||
if peer_remove:
|
||||
pp_peer, pp_idx = s_wg.get_peer_by_public_key(peer.get_public_key())
|
||||
if pp_peer:
|
||||
s_wg.remove_peer(pp_idx)
|
||||
else:
|
||||
if peer_secret_flags is not None:
|
||||
peer.set_preshared_key_flags(peer_secret_flags)
|
||||
wg_peer_is_valid(peer)
|
||||
if peer_idx is None:
|
||||
s_wg.append_peer(peer)
|
||||
else:
|
||||
s_wg.set_peer(peer, peer_idx)
|
||||
peer = None
|
||||
peer_remove = False
|
||||
peer_idx = None
|
||||
peer_secret_flags = None
|
||||
|
||||
if idx >= len(argv):
|
||||
break;
|
||||
|
||||
if not peer and argv[idx] == 'private-key':
|
||||
key = argv_get_one(argv, idx + 1, None, idx)
|
||||
if key == '':
|
||||
s_wg.set_property(NM.SETTING_WIREGUARD_PRIVATE_KEY, None)
|
||||
else:
|
||||
s_wg.set_property(NM.SETTING_WIREGUARD_PRIVATE_KEY, wg_read_private_key(key))
|
||||
idx += 2
|
||||
continue
|
||||
if not peer and argv[idx] == 'private-key-flags':
|
||||
s_wg.set_property(NM.SETTING_WIREGUARD_PRIVATE_KEY_FLAGS, argv_get_one(argv, idx + 1, arg_parse_secret_flags, idx))
|
||||
idx += 2
|
||||
continue
|
||||
if not peer and argv[idx] == 'listen-port':
|
||||
s_wg.set_property(NM.SETTING_WIREGUARD_LISTEN_PORT, argv_get_one(argv, idx + 1, arg_parse_listen_port, idx))
|
||||
idx += 2
|
||||
continue
|
||||
if not peer and argv[idx] == 'fwmark':
|
||||
s_wg.set_property(NM.SETTING_WIREGUARD_FWMARK, argv_get_one(argv, idx + 1, arg_parse_fwmark, idx))
|
||||
idx += 2
|
||||
continue
|
||||
if argv[idx] == 'peer':
|
||||
public_key = argv_get_one(argv, idx + 1, None, idx)
|
||||
peer, peer_idx = s_wg.get_peer_by_public_key(public_key)
|
||||
if peer:
|
||||
peer = peer.new_clone(True)
|
||||
else:
|
||||
peer_idx = None
|
||||
peer = NM.WireGuardPeer()
|
||||
peer.set_public_key(public_key)
|
||||
wg_peer_is_valid(peer, 'public key "%s" is invalid' % (public_key))
|
||||
peer_remove = False
|
||||
idx += 2
|
||||
continue
|
||||
if peer and argv[idx] == 'remove':
|
||||
peer_remove = True
|
||||
idx += 1
|
||||
continue
|
||||
if peer and argv[idx] == 'preshared-key':
|
||||
psk = argv_get_one(argv, idx + 1, None, idx)
|
||||
if psk == '':
|
||||
peer.set_preshared_key(None)
|
||||
if peer_secret_flags is not None:
|
||||
peer_secret_flags = NM.SettingSecretFlags.NOT_REQUIRED
|
||||
else:
|
||||
peer.set_preshared_key(wg_read_private_key(psk))
|
||||
if peer_secret_flags is not None:
|
||||
peer_secret_flags = NM.SettingSecretFlags.NONE
|
||||
idx += 2
|
||||
continue
|
||||
if peer and argv[idx] == 'preshared-key-flags':
|
||||
peer_secret_flags = argv_get_one(argv, idx + 1, arg_parse_secret_flags, idx)
|
||||
idx += 2
|
||||
continue
|
||||
if peer and argv[idx] == 'endpoint':
|
||||
peer.set_endpoint(argv_get_one(argv, idx + 1, None, idx))
|
||||
idx += 2
|
||||
continue
|
||||
if peer and argv[idx] == 'persistent-keepalive':
|
||||
peer.set_persistent_keepalive(argv_get_one(argv, idx + 1, arg_parse_persistent_keep_alive, idx))
|
||||
idx += 2
|
||||
continue
|
||||
if peer and argv[idx] == 'allowed-ips':
|
||||
allowed_ips = list(argv_get_one(argv, idx + 1, arg_parse_allowed_ips, idx))
|
||||
peer.clear_allowed_ips()
|
||||
for aip in allowed_ips:
|
||||
peer.append_allowed_ip(aip, False)
|
||||
del allowed_ips
|
||||
idx += 2
|
||||
continue
|
||||
|
||||
raise MyError('invalid argument "%s"' % (argv[idx]))
|
||||
except MyError as e:
|
||||
print('Error: %s' % (e.message))
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
conn.commit_changes(True, None)
|
||||
except Exception as e:
|
||||
print('failure to commit connection: %s' % (e))
|
||||
sys.exit(1)
|
||||
|
||||
print('Success')
|
||||
sys.exit(0)
|
||||
|
||||
###############################################################################
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
argv = sys.argv
|
||||
del argv[0]
|
||||
|
||||
con_spec = None
|
||||
if len(argv) >= 1:
|
||||
if argv[0] in [ 'id', 'uuid', 'interface' ]:
|
||||
con_spec = argv[0]
|
||||
del argv[0]
|
||||
if len(argv) < 1:
|
||||
print('Requires an existing NetworkManager connection profile as first argument')
|
||||
print('Select it based on the connection ID, UUID, or interface-name (optionally qualify the selection with [id|uuid|interface])')
|
||||
print('Maybe you want to create one first with')
|
||||
print(' nmcli connection add type wireguard ifname wg0 $MORE_ARGS')
|
||||
sys.exit(1)
|
||||
con_id = argv[0]
|
||||
del argv[0]
|
||||
|
||||
nm_client = NM.Client.new(None)
|
||||
|
||||
connections = connections_find(nm_client.get_connections(), con_spec, con_id)
|
||||
if len(connections) == 0:
|
||||
print('No matching connection %s\"%s\" found.' % ((con_spec+' ' if con_spec else ''), con_id))
|
||||
print('Maybe you want to create one first with')
|
||||
print(' nmcli connection add type wireguard ifname wg0 $MORE_ARGS')
|
||||
sys.exit(1)
|
||||
if len(connections) > 1:
|
||||
print("Connection %s\"%s\" is not unique (%s)" % ((con_spec+' ' if con_spec else ''), con_id, ', '.join(['['+connection_to_str(c)+']' for c in connections])))
|
||||
if not con_spec:
|
||||
print('Maybe qualify the name with [id|uuid|interface]?')
|
||||
sys.exit(1)
|
||||
|
||||
conn = connections[0]
|
||||
if not connection_is_wireguard(conn):
|
||||
print('Connection %s is not a WireGuard profile' % (connection_to_str(conn)))
|
||||
print('See available profiles with `nmcli connection show`')
|
||||
sys.exit(1)
|
||||
|
||||
if not argv:
|
||||
do_get(nm_client, conn)
|
||||
else:
|
||||
do_set(nm_client, conn, argv)
|
||||
|
||||
|
|
@ -48,6 +48,7 @@ libnm_core_headers = files(
|
|||
'nm-setting-wifi-p2p.h',
|
||||
'nm-setting-wimax.h',
|
||||
'nm-setting-wired.h',
|
||||
'nm-setting-wireguard.h',
|
||||
'nm-setting-wireless-security.h',
|
||||
'nm-setting-wireless.h',
|
||||
'nm-setting-wpan.h',
|
||||
|
|
@ -104,6 +105,7 @@ libnm_core_settings_sources = files(
|
|||
'nm-setting-wifi-p2p.c',
|
||||
'nm-setting-wimax.c',
|
||||
'nm-setting-wired.c',
|
||||
'nm-setting-wireguard.c',
|
||||
'nm-setting-wireless-security.c',
|
||||
'nm-setting-wireless.c',
|
||||
'nm-setting-wpan.c',
|
||||
|
|
|
|||
|
|
@ -905,25 +905,24 @@ _supports_addr_family (NMConnection *self, int family)
|
|||
static gboolean
|
||||
_normalize_ip_config (NMConnection *self, GHashTable *parameters)
|
||||
{
|
||||
const char *default_ip4_method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
|
||||
const char *default_ip6_method = NULL;
|
||||
NMSettingIPConfig *s_ip4, *s_ip6;
|
||||
NMSettingProxy *s_proxy;
|
||||
NMSetting *setting;
|
||||
gboolean changed = FALSE;
|
||||
guint num, i;
|
||||
|
||||
if (parameters)
|
||||
default_ip6_method = g_hash_table_lookup (parameters, NM_CONNECTION_NORMALIZE_PARAM_IP6_CONFIG_METHOD);
|
||||
if (!default_ip6_method)
|
||||
default_ip6_method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
|
||||
|
||||
s_ip4 = nm_connection_get_setting_ip4_config (self);
|
||||
s_ip6 = nm_connection_get_setting_ip6_config (self);
|
||||
s_proxy = nm_connection_get_setting_proxy (self);
|
||||
|
||||
if (_supports_addr_family (self, AF_INET)) {
|
||||
|
||||
if (!s_ip4) {
|
||||
const char *default_ip4_method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
|
||||
|
||||
if (nm_connection_is_type (self, NM_SETTING_WIREGUARD_SETTING_NAME))
|
||||
default_ip4_method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
|
||||
|
||||
/* But if no IP4 setting was specified, assume the caller was just
|
||||
* being lazy and use the default method.
|
||||
*/
|
||||
|
|
@ -966,6 +965,17 @@ _normalize_ip_config (NMConnection *self, GHashTable *parameters)
|
|||
|
||||
if (_supports_addr_family (self, AF_INET6)) {
|
||||
if (!s_ip6) {
|
||||
const char *default_ip6_method = NULL;
|
||||
|
||||
if (parameters)
|
||||
default_ip6_method = g_hash_table_lookup (parameters, NM_CONNECTION_NORMALIZE_PARAM_IP6_CONFIG_METHOD);
|
||||
if (!default_ip6_method) {
|
||||
if (nm_connection_is_type (self, NM_SETTING_WIREGUARD_SETTING_NAME))
|
||||
default_ip6_method = NM_SETTING_IP6_CONFIG_METHOD_IGNORE;
|
||||
else
|
||||
default_ip6_method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
|
||||
}
|
||||
|
||||
/* If no IP6 setting was specified, then assume that means IP6 config is
|
||||
* allowed to fail.
|
||||
*/
|
||||
|
|
@ -2419,7 +2429,8 @@ nm_connection_is_virtual (NMConnection *connection)
|
|||
NM_SETTING_TEAM_SETTING_NAME,
|
||||
NM_SETTING_TUN_SETTING_NAME,
|
||||
NM_SETTING_VLAN_SETTING_NAME,
|
||||
NM_SETTING_VXLAN_SETTING_NAME))
|
||||
NM_SETTING_VXLAN_SETTING_NAME,
|
||||
NM_SETTING_WIREGUARD_SETTING_NAME))
|
||||
return TRUE;
|
||||
|
||||
if (nm_streq (type, NM_SETTING_INFINIBAND_SETTING_NAME)) {
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
#include "nm-setting-wifi-p2p.h"
|
||||
#include "nm-setting-wimax.h"
|
||||
#include "nm-setting-wired.h"
|
||||
#include "nm-setting-wireguard.h"
|
||||
#include "nm-setting-wireless-security.h"
|
||||
#include "nm-setting-wireless.h"
|
||||
#include "nm-setting-wpan.h"
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@
|
|||
#include "nm-setting-wifi-p2p.h"
|
||||
#include "nm-setting-wimax.h"
|
||||
#include "nm-setting-wired.h"
|
||||
#include "nm-setting-wireguard.h"
|
||||
#include "nm-setting-wireless-security.h"
|
||||
#include "nm-setting-wireless.h"
|
||||
#include "nm-setting-wpan.h"
|
||||
|
|
@ -633,6 +634,15 @@ NM_AUTO_DEFINE_FCN_VOID0 (NMSockAddrEndpoint *, _nm_auto_unref_sockaddrendpoint,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMSockAddrEndpoint *_nm_wireguard_peer_get_endpoint (const NMWireGuardPeer *self);
|
||||
void _nm_wireguard_peer_set_endpoint (NMWireGuardPeer *self,
|
||||
NMSockAddrEndpoint *endpoint);
|
||||
|
||||
void _nm_wireguard_peer_set_public_key_bin (NMWireGuardPeer *self,
|
||||
const guint8 public_key[static NM_WIREGUARD_PUBLIC_KEY_LEN]);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct _NMSettInfoSetting NMSettInfoSetting;
|
||||
typedef struct _NMSettInfoProperty NMSettInfoProperty;
|
||||
|
||||
|
|
@ -768,4 +778,17 @@ gboolean _nm_connection_find_secret (NMConnection *self,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define nm_auto_unref_wgpeer nm_auto(_nm_auto_unref_wgpeer)
|
||||
NM_AUTO_DEFINE_FCN_VOID0 (NMWireGuardPeer *, _nm_auto_unref_wgpeer, nm_wireguard_peer_unref)
|
||||
|
||||
gboolean _nm_utils_wireguard_decode_key (const char *base64_key,
|
||||
gsize required_key_len,
|
||||
guint8 *out_key);
|
||||
|
||||
gboolean _nm_utils_wireguard_normalize_key (const char *base64_key,
|
||||
gsize required_key_len,
|
||||
char **out_base64_key_norm);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ typedef struct _NMSettingVxlan NMSettingVxlan;
|
|||
typedef struct _NMSettingWifiP2P NMSettingWifiP2P;
|
||||
typedef struct _NMSettingWimax NMSettingWimax;
|
||||
typedef struct _NMSettingWired NMSettingWired;
|
||||
typedef struct _NMSettingWireGuard NMSettingWireGuard;
|
||||
typedef struct _NMSettingWireless NMSettingWireless;
|
||||
typedef struct _NMSettingWirelessSecurity NMSettingWirelessSecurity;
|
||||
typedef struct _NMSettingWpan NMSettingWpan;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@
|
|||
#error Cannot use this header.
|
||||
#endif
|
||||
|
||||
#define NM_KEYFILE_GROUP_VPN_SECRETS "vpn-secrets"
|
||||
#define NM_KEYFILE_GROUP_VPN_SECRETS "vpn-secrets"
|
||||
#define NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER "wireguard-peer."
|
||||
|
||||
const char *nm_keyfile_plugin_get_alias_for_setting_name (const char *setting_name);
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include <linux/pkt_sched.h>
|
||||
|
||||
#include "nm-utils/nm-secret-utils.h"
|
||||
#include "systemd/nm-sd-utils-shared.h"
|
||||
#include "nm-common-macros.h"
|
||||
#include "nm-core-internal.h"
|
||||
#include "nm-keyfile-utils.h"
|
||||
|
|
@ -2901,6 +2902,137 @@ out:
|
|||
nm_connection_add_setting (info->connection, g_steal_pointer (&setting));
|
||||
}
|
||||
|
||||
static void
|
||||
_read_setting_wireguard_peer (KeyfileReaderInfo *info)
|
||||
{
|
||||
gs_unref_object NMSettingWireGuard *s_wg_new = NULL;
|
||||
nm_auto_unref_wgpeer NMWireGuardPeer *peer = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
NMSettingWireGuard *s_wg;
|
||||
gs_free char *str = NULL;
|
||||
const char *cstr = NULL;
|
||||
const char *key;
|
||||
gint64 i64;
|
||||
gs_strfreev char **sa = NULL;
|
||||
gsize n_sa;
|
||||
|
||||
peer = nm_wireguard_peer_new ();
|
||||
|
||||
nm_assert (g_str_has_prefix (info->group, NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER));
|
||||
cstr = &info->group[NM_STRLEN (NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER)];
|
||||
if ( !_nm_utils_wireguard_normalize_key (cstr, NM_WIREGUARD_PUBLIC_KEY_LEN, &str)
|
||||
|| !nm_streq0 (str, cstr)) {
|
||||
/* the group name must be identical to the normalized(!) key, so that it
|
||||
* is uniquely identified. */
|
||||
handle_warn (info, NULL, NM_KEYFILE_WARN_SEVERITY_WARN,
|
||||
_("invalid peer public key in section '%s'"),
|
||||
info->group);
|
||||
return;
|
||||
}
|
||||
nm_wireguard_peer_set_public_key (peer, cstr);
|
||||
nm_clear_g_free (&str);
|
||||
|
||||
key = NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY;
|
||||
str = nm_keyfile_plugin_kf_get_string (info->keyfile, info->group, key, NULL);
|
||||
if (str) {
|
||||
if (!_nm_utils_wireguard_decode_key (str, NM_WIREGUARD_SYMMETRIC_KEY_LEN, NULL)) {
|
||||
if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
|
||||
_("key '%s.%s' is not not a valid 256 bit key in base64 encoding"),
|
||||
info->group, key))
|
||||
return;
|
||||
} else
|
||||
nm_wireguard_peer_set_preshared_key (peer, str);
|
||||
nm_clear_g_free (&str);
|
||||
}
|
||||
|
||||
key = NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY_FLAGS;
|
||||
i64 = nm_keyfile_plugin_kf_get_int64 (info->keyfile, info->group, key, 0, 0, NM_SETTING_SECRET_FLAG_ALL, -1, NULL);
|
||||
if (errno != ENODATA) {
|
||||
if ( i64 == -1
|
||||
|| !_nm_setting_secret_flags_valid (i64)) {
|
||||
if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
|
||||
_("key '%s.%s' is not not a valid secret flag"),
|
||||
info->group, key))
|
||||
return;
|
||||
} else
|
||||
nm_wireguard_peer_set_preshared_key_flags (peer, i64);
|
||||
}
|
||||
|
||||
key = NM_WIREGUARD_PEER_ATTR_PERSISTENT_KEEPALIVE;
|
||||
i64 = nm_keyfile_plugin_kf_get_int64 (info->keyfile, info->group, key, 0, 0, G_MAXUINT32, -1, NULL);
|
||||
if (errno != ENODATA) {
|
||||
if (i64 == -1) {
|
||||
if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
|
||||
_("key '%s.%s' is not not a integer in range 0 to 2^32"),
|
||||
info->group, key))
|
||||
return;
|
||||
} else
|
||||
nm_wireguard_peer_set_persistent_keepalive (peer, i64);
|
||||
}
|
||||
|
||||
key = NM_WIREGUARD_PEER_ATTR_ENDPOINT;
|
||||
str = nm_keyfile_plugin_kf_get_string (info->keyfile, info->group, key, NULL);
|
||||
if (str && str[0]) {
|
||||
nm_auto_unref_sockaddrendpoint NMSockAddrEndpoint *ep = NULL;
|
||||
|
||||
ep = nm_sock_addr_endpoint_new (str);
|
||||
if (!nm_sock_addr_endpoint_get_host (ep)) {
|
||||
if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
|
||||
_("key '%s.%s' is not not a valid endpoint"),
|
||||
info->group, key))
|
||||
return;
|
||||
} else
|
||||
_nm_wireguard_peer_set_endpoint (peer, ep);
|
||||
}
|
||||
nm_clear_g_free (&str);
|
||||
|
||||
key = NM_WIREGUARD_PEER_ATTR_ALLOWED_IPS;
|
||||
sa = nm_keyfile_plugin_kf_get_string_list (info->keyfile, info->group, key, &n_sa, NULL);
|
||||
if (n_sa > 0) {
|
||||
gboolean has_error = FALSE;
|
||||
gsize i;
|
||||
|
||||
for (i = 0; i < n_sa; i++) {
|
||||
if (!nm_utils_parse_inaddr_prefix_bin (AF_UNSPEC, sa[i], NULL, NULL, NULL)) {
|
||||
has_error = TRUE;
|
||||
continue;
|
||||
}
|
||||
nm_wireguard_peer_append_allowed_ip (peer, sa[i], TRUE);
|
||||
}
|
||||
if (has_error) {
|
||||
if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
|
||||
_("key '%s.%s' has invalid allowed-ips"),
|
||||
info->group, key))
|
||||
return;
|
||||
}
|
||||
}
|
||||
nm_clear_pointer (&sa, g_strfreev);
|
||||
|
||||
if (info->error)
|
||||
return;
|
||||
|
||||
if (!nm_wireguard_peer_is_valid (peer, TRUE, TRUE, &error)) {
|
||||
if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
|
||||
_("peer '%s' is invalid: %s"),
|
||||
info->group, error->message))
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
s_wg = NM_SETTING_WIREGUARD (nm_connection_get_setting (info->connection, NM_TYPE_SETTING_WIREGUARD));
|
||||
if (!s_wg) {
|
||||
s_wg_new = NM_SETTING_WIREGUARD (nm_setting_wireguard_new ());
|
||||
s_wg = s_wg_new;
|
||||
}
|
||||
|
||||
nm_setting_wireguard_append_peer (s_wg, peer);
|
||||
|
||||
if (s_wg_new) {
|
||||
nm_connection_add_setting (info->connection,
|
||||
NM_SETTING (g_steal_pointer (&s_wg_new)));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_read_setting_vpn_secrets (KeyfileReaderInfo *info)
|
||||
{
|
||||
|
|
@ -3021,7 +3153,9 @@ nm_keyfile_read (GKeyFile *keyfile,
|
|||
if (nm_streq (groups[i], NM_KEYFILE_GROUP_VPN_SECRETS)) {
|
||||
/* Only read out secrets when needed */
|
||||
vpn_secrets = TRUE;
|
||||
} else
|
||||
} else if (NM_STR_HAS_PREFIX (groups[i], NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER))
|
||||
_read_setting_wireguard_peer (&info);
|
||||
else
|
||||
_read_setting (&info);
|
||||
|
||||
info.group = NULL;
|
||||
|
|
@ -3198,6 +3332,92 @@ out_unset_value:
|
|||
g_value_unset (&value);
|
||||
}
|
||||
|
||||
static void
|
||||
_write_setting_wireguard (NMSetting *setting, KeyfileWriterInfo *info)
|
||||
{
|
||||
NMSettingWireGuard *s_wg;
|
||||
guint i_peer, n_peers;
|
||||
|
||||
s_wg = NM_SETTING_WIREGUARD (setting);
|
||||
|
||||
n_peers = nm_setting_wireguard_get_peers_len (s_wg);
|
||||
for (i_peer = 0; i_peer < n_peers; i_peer++) {
|
||||
NMWireGuardPeer *peer = nm_setting_wireguard_get_peer (s_wg, i_peer);
|
||||
const char *public_key;
|
||||
char group[NM_STRLEN (NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER) + 200];
|
||||
NMSettingSecretFlags secret_flags;
|
||||
gboolean any_key = FALSE;
|
||||
guint i_aip, n_aip;
|
||||
const char *cstr;
|
||||
guint32 u32;
|
||||
|
||||
public_key = nm_wireguard_peer_get_public_key (peer);
|
||||
if ( !public_key
|
||||
|| !public_key[0]
|
||||
|| !NM_STRCHAR_ALL (public_key, ch, nm_sd_utils_unbase64char (ch, TRUE) >= 0)) {
|
||||
/* invalid peer. Skip it */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (g_snprintf (group,
|
||||
sizeof (group),
|
||||
"%s%s",
|
||||
NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER,
|
||||
nm_wireguard_peer_get_public_key (peer)) >= sizeof (group)) {
|
||||
/* Too long. Not a valid public key. Skip the peer. */
|
||||
continue;
|
||||
}
|
||||
|
||||
cstr = nm_wireguard_peer_get_endpoint (peer);
|
||||
if (cstr) {
|
||||
g_key_file_set_string (info->keyfile, group, NM_WIREGUARD_PEER_ATTR_ENDPOINT, cstr);
|
||||
any_key = TRUE;
|
||||
}
|
||||
|
||||
secret_flags = nm_wireguard_peer_get_preshared_key_flags (peer);
|
||||
if (_secret_flags_persist_secret (secret_flags)) {
|
||||
cstr = nm_wireguard_peer_get_preshared_key (peer);
|
||||
if (cstr) {
|
||||
g_key_file_set_string (info->keyfile, group, NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY, cstr);
|
||||
any_key = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* usually, we don't persist the secret-flags 0 (because they are the default).
|
||||
* For WireGuard peers, the default secret-flags for preshared-key are 4 (not-required).
|
||||
* So, in this case behave differently: a missing preshared-key-flag setting means
|
||||
* "not-required". */
|
||||
if (secret_flags != NM_SETTING_SECRET_FLAG_NOT_REQUIRED) {
|
||||
g_key_file_set_int64 (info->keyfile, group, NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY_FLAGS, secret_flags);
|
||||
any_key = TRUE;
|
||||
}
|
||||
|
||||
u32 = nm_wireguard_peer_get_persistent_keepalive (peer);
|
||||
if (u32) {
|
||||
g_key_file_set_uint64 (info->keyfile, group, NM_WIREGUARD_PEER_ATTR_PERSISTENT_KEEPALIVE, u32);
|
||||
any_key = TRUE;
|
||||
}
|
||||
|
||||
n_aip = nm_wireguard_peer_get_allowed_ips_len (peer);
|
||||
if (n_aip > 0) {
|
||||
gs_free const char **strv = NULL;
|
||||
|
||||
strv = g_new (const char *, ((gsize) n_aip) + 1);
|
||||
for (i_aip = 0; i_aip < n_aip; i_aip++)
|
||||
strv[i_aip] = nm_wireguard_peer_get_allowed_ip (peer, i_aip, NULL);
|
||||
strv[n_aip] = NULL;
|
||||
g_key_file_set_string_list (info->keyfile, group, NM_WIREGUARD_PEER_ATTR_ALLOWED_IPS,
|
||||
strv, n_aip);
|
||||
any_key = TRUE;
|
||||
}
|
||||
|
||||
if (!any_key) {
|
||||
/* we cannot omit all keys. At an empty endpoint. */
|
||||
g_key_file_set_string (info->keyfile, group, NM_WIREGUARD_PEER_ATTR_ENDPOINT, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GKeyFile *
|
||||
nm_keyfile_write (NMConnection *connection,
|
||||
NMKeyfileWriteHandler handler,
|
||||
|
|
@ -3275,6 +3495,12 @@ nm_keyfile_write (NMConnection *connection,
|
|||
goto out_with_info_error;
|
||||
}
|
||||
|
||||
if (NM_IS_SETTING_WIREGUARD (setting)) {
|
||||
_write_setting_wireguard (setting, &info);
|
||||
if (info.error)
|
||||
goto out_with_info_error;
|
||||
}
|
||||
|
||||
nm_assert (!info.error);
|
||||
}
|
||||
|
||||
|
|
|
|||
2356
libnm-core/nm-setting-wireguard.c
Normal file
2356
libnm-core/nm-setting-wireguard.c
Normal file
File diff suppressed because it is too large
Load diff
201
libnm-core/nm-setting-wireguard.h
Normal file
201
libnm-core/nm-setting-wireguard.h
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright 2018 - 2019 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __NM_SETTING_WIREGUARD_H__
|
||||
#define __NM_SETTING_WIREGUARD_H__
|
||||
|
||||
#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
|
||||
#error "Only <NetworkManager.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "nm-setting.h"
|
||||
#include "nm-utils.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define NM_WIREGUARD_PUBLIC_KEY_LEN 32
|
||||
#define NM_WIREGUARD_SYMMETRIC_KEY_LEN 32
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct _NMWireGuardPeer NMWireGuardPeer;
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
GType nm_wireguard_peer_get_type (void);
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
NMWireGuardPeer *nm_wireguard_peer_new (void);
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
NMWireGuardPeer *nm_wireguard_peer_new_clone (const NMWireGuardPeer *self,
|
||||
gboolean with_secrets);
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
NMWireGuardPeer *nm_wireguard_peer_ref (NMWireGuardPeer *self);
|
||||
NM_AVAILABLE_IN_1_16
|
||||
void nm_wireguard_peer_unref (NMWireGuardPeer *self);
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
void nm_wireguard_peer_seal (NMWireGuardPeer *self);
|
||||
NM_AVAILABLE_IN_1_16
|
||||
gboolean nm_wireguard_peer_is_sealed (const NMWireGuardPeer *self);
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
const char *nm_wireguard_peer_get_public_key (const NMWireGuardPeer *self);
|
||||
NM_AVAILABLE_IN_1_16
|
||||
void nm_wireguard_peer_set_public_key (NMWireGuardPeer *self,
|
||||
const char *public_key);
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
const char *nm_wireguard_peer_get_preshared_key (const NMWireGuardPeer *self);
|
||||
NM_AVAILABLE_IN_1_16
|
||||
void nm_wireguard_peer_set_preshared_key (NMWireGuardPeer *self,
|
||||
const char *preshared_key);
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
NMSettingSecretFlags nm_wireguard_peer_get_preshared_key_flags (const NMWireGuardPeer *self);
|
||||
NM_AVAILABLE_IN_1_16
|
||||
void nm_wireguard_peer_set_preshared_key_flags (NMWireGuardPeer *self,
|
||||
NMSettingSecretFlags preshared_key_flags);
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
guint16 nm_wireguard_peer_get_persistent_keepalive (const NMWireGuardPeer *self);
|
||||
NM_AVAILABLE_IN_1_16
|
||||
void nm_wireguard_peer_set_persistent_keepalive (NMWireGuardPeer *self,
|
||||
guint16 persistent_keepalive);
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
const char *nm_wireguard_peer_get_endpoint (const NMWireGuardPeer *self);
|
||||
NM_AVAILABLE_IN_1_16
|
||||
void nm_wireguard_peer_set_endpoint (NMWireGuardPeer *self,
|
||||
const char *endpoint);
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
guint nm_wireguard_peer_get_allowed_ips_len (const NMWireGuardPeer *self);
|
||||
NM_AVAILABLE_IN_1_16
|
||||
const char *nm_wireguard_peer_get_allowed_ip (const NMWireGuardPeer *self,
|
||||
guint idx,
|
||||
gboolean *out_is_valid);
|
||||
NM_AVAILABLE_IN_1_16
|
||||
void nm_wireguard_peer_clear_allowed_ips (NMWireGuardPeer *self);
|
||||
NM_AVAILABLE_IN_1_16
|
||||
gboolean nm_wireguard_peer_append_allowed_ip (NMWireGuardPeer *self,
|
||||
const char *allowed_ip,
|
||||
gboolean accept_invalid);
|
||||
NM_AVAILABLE_IN_1_16
|
||||
gboolean nm_wireguard_peer_remove_allowed_ip (NMWireGuardPeer *self,
|
||||
guint idx);
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
gboolean nm_wireguard_peer_is_valid (const NMWireGuardPeer *self,
|
||||
gboolean check_non_secrets,
|
||||
gboolean check_secrets,
|
||||
GError **error);
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
int nm_wireguard_peer_cmp (const NMWireGuardPeer *a,
|
||||
const NMWireGuardPeer *b,
|
||||
NMSettingCompareFlags compare_flags);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define NM_TYPE_SETTING_WIREGUARD (nm_setting_wireguard_get_type ())
|
||||
#define NM_SETTING_WIREGUARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_WIREGUARD, NMSettingWireGuard))
|
||||
#define NM_SETTING_WIREGUARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_WIREGUARD, NMSettingWireGuardClass))
|
||||
#define NM_IS_SETTING_WIREGUARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_WIREGUARD))
|
||||
#define NM_IS_SETTING_WIREGUARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_WIREGUARD))
|
||||
#define NM_SETTING_WIREGUARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_WIREGUARD, NMSettingWireGuardClass))
|
||||
|
||||
#define NM_SETTING_WIREGUARD_SETTING_NAME "wireguard"
|
||||
|
||||
#define NM_SETTING_WIREGUARD_PRIVATE_KEY "private-key"
|
||||
#define NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS "private-key-flags"
|
||||
#define NM_SETTING_WIREGUARD_LISTEN_PORT "listen-port"
|
||||
#define NM_SETTING_WIREGUARD_FWMARK "fwmark"
|
||||
|
||||
#define NM_SETTING_WIREGUARD_PEERS "peers"
|
||||
|
||||
#define NM_WIREGUARD_PEER_ATTR_PUBLIC_KEY "public-key"
|
||||
#define NM_WIREGUARD_PEER_ATTR_ENDPOINT "endpoint"
|
||||
#define NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY "preshared-key"
|
||||
#define NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY_FLAGS "preshared-key-flags"
|
||||
#define NM_WIREGUARD_PEER_ATTR_ALLOWED_IPS "allowed-ips"
|
||||
#define NM_WIREGUARD_PEER_ATTR_PERSISTENT_KEEPALIVE "persistent-keepalive"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct _NMSettingWireGuardClass NMSettingWireGuardClass;
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
GType nm_setting_wireguard_get_type (void);
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
NMSetting *nm_setting_wireguard_new (void);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
const char *nm_setting_wireguard_get_private_key (NMSettingWireGuard *self);
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
NMSettingSecretFlags nm_setting_wireguard_get_private_key_flags (NMSettingWireGuard *self);
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
guint16 nm_setting_wireguard_get_listen_port (NMSettingWireGuard *self);
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
guint32 nm_setting_wireguard_get_fwmark (NMSettingWireGuard *self);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
guint nm_setting_wireguard_get_peers_len (NMSettingWireGuard *self);
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
NMWireGuardPeer *nm_setting_wireguard_get_peer (NMSettingWireGuard *self,
|
||||
guint idx);
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
NMWireGuardPeer *nm_setting_wireguard_get_peer_by_public_key (NMSettingWireGuard *self,
|
||||
const char *public_key,
|
||||
guint *out_idx);
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
void nm_setting_wireguard_set_peer (NMSettingWireGuard *self,
|
||||
NMWireGuardPeer *peer,
|
||||
guint idx);
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
void nm_setting_wireguard_append_peer (NMSettingWireGuard *self,
|
||||
NMWireGuardPeer *peer);
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
gboolean nm_setting_wireguard_remove_peer (NMSettingWireGuard *self,
|
||||
guint idx);
|
||||
|
||||
NM_AVAILABLE_IN_1_16
|
||||
guint nm_setting_wireguard_clear_peers (NMSettingWireGuard *self);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __NM_SETTING_WIREGUARD_H__ */
|
||||
|
|
@ -2067,7 +2067,7 @@ _nm_setting_update_secrets (NMSetting *setting, GVariant *secrets, GError **erro
|
|||
int success;
|
||||
|
||||
success = NM_SETTING_GET_CLASS (setting)->update_one_secret (setting, secret_key, secret_value, &tmp_error);
|
||||
g_assert (!((success == NM_SETTING_UPDATE_SECRET_ERROR) ^ (!!tmp_error)));
|
||||
nm_assert (!((success == NM_SETTING_UPDATE_SECRET_ERROR) ^ (!!tmp_error)));
|
||||
|
||||
g_variant_unref (secret_value);
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@
|
|||
#endif
|
||||
|
||||
#include "nm-utils/nm-enum-utils.h"
|
||||
#include "nm-utils/nm-secret-utils.h"
|
||||
#include "systemd/nm-sd-utils-shared.h"
|
||||
#include "nm-common-macros.h"
|
||||
#include "nm-utils-private.h"
|
||||
#include "nm-setting-private.h"
|
||||
|
|
@ -6809,3 +6811,76 @@ nm_utils_version (void)
|
|||
return NM_VERSION;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
* _nm_utils_wireguard_decode_key:
|
||||
* @base64_key: the (possibly invalid) base64 encode key.
|
||||
* @required_key_len: the expected (binary) length of the key after
|
||||
* decoding. If the length does not match, the validation fails.
|
||||
* @out_key: (allow-none): an optional output buffer for the binary
|
||||
* key. If given, it will be filled with exactly @required_key_len
|
||||
* bytes.
|
||||
*
|
||||
* Returns: %TRUE if the input key is a valid base64 encoded key
|
||||
* with @required_key_len bytes.
|
||||
*/
|
||||
gboolean
|
||||
_nm_utils_wireguard_decode_key (const char *base64_key,
|
||||
gsize required_key_len,
|
||||
guint8 *out_key)
|
||||
{
|
||||
gs_free guint8 *bin_arr = NULL;
|
||||
gsize base64_key_len;
|
||||
gsize bin_len;
|
||||
int r;
|
||||
|
||||
if (!base64_key)
|
||||
return FALSE;
|
||||
|
||||
base64_key_len = strlen (base64_key);
|
||||
|
||||
r = nm_sd_utils_unbase64mem (base64_key, base64_key_len, &bin_arr, &bin_len);
|
||||
if (r < 0)
|
||||
return FALSE;
|
||||
if (bin_len != required_key_len) {
|
||||
nm_explicit_bzero (bin_arr, bin_len);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (nm_utils_memeqzero (bin_arr, required_key_len)) {
|
||||
/* an all zero key is not valid either. That is used to represet an unset key */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (out_key)
|
||||
memcpy (out_key, bin_arr, required_key_len);
|
||||
|
||||
nm_explicit_bzero (bin_arr, bin_len);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_utils_wireguard_normalize_key (const char *base64_key,
|
||||
gsize required_key_len,
|
||||
char **out_base64_key_norm)
|
||||
{
|
||||
gs_free guint8 *buf_free = NULL;
|
||||
guint8 buf_static[200];
|
||||
guint8 *buf;
|
||||
|
||||
if (required_key_len > sizeof (buf_static)) {
|
||||
buf_free = g_new (guint8, required_key_len);
|
||||
buf = buf_free;
|
||||
} else
|
||||
buf = buf_static;
|
||||
|
||||
if (!_nm_utils_wireguard_decode_key (base64_key, required_key_len, buf)) {
|
||||
NM_SET_OUT (out_base64_key_norm, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
NM_SET_OUT (out_base64_key_norm, g_base64_encode (buf, required_key_len));
|
||||
nm_explicit_bzero (buf, required_key_len);
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,6 +115,30 @@ _connection_new_from_dbus_strict (GVariant *dict,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static char *
|
||||
_create_random_ipaddr (int addr_family, gboolean as_service)
|
||||
{
|
||||
char delimiter = as_service ? ':' : '/';
|
||||
int num;
|
||||
|
||||
if (addr_family == AF_UNSPEC)
|
||||
addr_family = nmtst_rand_select (AF_INET, AF_INET6);
|
||||
|
||||
g_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6));
|
||||
|
||||
if (as_service)
|
||||
num = (nmtst_get_rand_int () % 1000) + 30000;
|
||||
else
|
||||
num = addr_family == AF_INET ? 32 : 128;
|
||||
|
||||
if (addr_family == AF_INET)
|
||||
return g_strdup_printf ("192.168.%u.%u%c%d", nmtst_get_rand_int () % 256, nmtst_get_rand_int () % 256, delimiter, num);
|
||||
else
|
||||
return g_strdup_printf ("a:b:c::%02x:%02x%c%d", nmtst_get_rand_int () % 256, nmtst_get_rand_int () % 256, delimiter, num);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
compare_blob_data (const char *test,
|
||||
const char *key_path,
|
||||
|
|
@ -2013,6 +2037,235 @@ test_tc_config_dbus (void)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static GPtrArray *
|
||||
_rndt_wg_peers_create (void)
|
||||
{
|
||||
GPtrArray *wg_peers;
|
||||
guint i, n;
|
||||
|
||||
wg_peers = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_wireguard_peer_unref);
|
||||
|
||||
n = nmtst_get_rand_int () % 10;
|
||||
for (i = 0; i < n; i++) {
|
||||
NMWireGuardPeer *peer;
|
||||
guint8 public_key_buf[NM_WIREGUARD_PUBLIC_KEY_LEN];
|
||||
guint8 preshared_key_buf[NM_WIREGUARD_SYMMETRIC_KEY_LEN];
|
||||
gs_free char *public_key = NULL;
|
||||
gs_free char *preshared_key = NULL;
|
||||
gs_free char *s_endpoint = NULL;
|
||||
guint i_aip, n_aip;
|
||||
|
||||
/* we don't bother to create a valid curve25519 public key. Of course, libnm cannot
|
||||
* check whether the public key is bogus or not. Hence, for our purpose a random
|
||||
* bogus key is good enough. */
|
||||
public_key = g_base64_encode (nmtst_rand_buf (NULL, public_key_buf, sizeof (public_key_buf)), sizeof (public_key_buf));
|
||||
|
||||
preshared_key = g_base64_encode (nmtst_rand_buf (NULL, preshared_key_buf, sizeof (preshared_key_buf)), sizeof (preshared_key_buf));
|
||||
|
||||
s_endpoint = _create_random_ipaddr (AF_UNSPEC, TRUE);
|
||||
|
||||
peer = nm_wireguard_peer_new ();
|
||||
nm_wireguard_peer_set_public_key (peer, public_key);
|
||||
|
||||
nm_wireguard_peer_set_preshared_key (peer, nmtst_rand_select (NULL, preshared_key));
|
||||
|
||||
nm_wireguard_peer_set_preshared_key_flags (peer, nmtst_rand_select (NM_SETTING_SECRET_FLAG_NONE,
|
||||
NM_SETTING_SECRET_FLAG_NOT_SAVED,
|
||||
NM_SETTING_SECRET_FLAG_AGENT_OWNED));
|
||||
|
||||
nm_wireguard_peer_set_persistent_keepalive (peer,
|
||||
nmtst_rand_select ((guint32) 0, nmtst_get_rand_int ()));
|
||||
|
||||
nm_wireguard_peer_set_endpoint (peer, nmtst_rand_select (s_endpoint, NULL));
|
||||
|
||||
n_aip = nmtst_rand_select (0, nmtst_get_rand_int () % 10);
|
||||
for (i_aip = 0; i_aip < n_aip; i_aip++) {
|
||||
gs_free char *aip = NULL;
|
||||
|
||||
aip = _create_random_ipaddr (AF_UNSPEC, FALSE);
|
||||
if (!nm_wireguard_peer_append_allowed_ip (peer, aip, FALSE))
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
g_assert (nm_wireguard_peer_is_valid (peer, TRUE, TRUE, NULL));
|
||||
|
||||
nm_wireguard_peer_seal (peer);
|
||||
g_ptr_array_add (wg_peers, peer);
|
||||
}
|
||||
|
||||
return wg_peers;
|
||||
}
|
||||
|
||||
static const char *
|
||||
_rndt_wg_peers_to_keyfile (GPtrArray *wg_peers,
|
||||
gboolean strict,
|
||||
char **out_str)
|
||||
{
|
||||
nm_auto_free_gstring GString *gstr = NULL;
|
||||
nm_auto_free_gstring GString *gstr_aip = NULL;
|
||||
guint i, j;
|
||||
|
||||
g_assert (wg_peers);
|
||||
g_assert (out_str && !*out_str);
|
||||
|
||||
nm_gstring_prepare (&gstr);
|
||||
for (i = 0; i < wg_peers->len; i++) {
|
||||
const NMWireGuardPeer *peer = wg_peers->pdata[i];
|
||||
gs_free char *s_endpoint = NULL;
|
||||
gs_free char *s_preshared_key = NULL;
|
||||
gs_free char *s_preshared_key_flags = NULL;
|
||||
gs_free char *s_persistent_keepalive = NULL;
|
||||
gs_free char *s_allowed_ips = NULL;
|
||||
|
||||
if (nm_wireguard_peer_get_endpoint (peer))
|
||||
s_endpoint = g_strdup_printf ("endpoint=%s\n", nm_wireguard_peer_get_endpoint (peer));
|
||||
else if (!strict)
|
||||
s_endpoint = g_strdup_printf ("endpoint=\n");
|
||||
|
||||
if ( nm_wireguard_peer_get_preshared_key (peer)
|
||||
|| !strict) {
|
||||
if (nm_wireguard_peer_get_preshared_key_flags (peer) == NM_SETTING_SECRET_FLAG_NONE)
|
||||
s_preshared_key = g_strdup_printf ("preshared-key=%s\n", nm_wireguard_peer_get_preshared_key (peer) ?: "");
|
||||
}
|
||||
|
||||
if ( nm_wireguard_peer_get_preshared_key_flags (peer) != NM_SETTING_SECRET_FLAG_NOT_REQUIRED
|
||||
|| !strict)
|
||||
s_preshared_key_flags = g_strdup_printf ("preshared-key-flags=%d\n", (int) nm_wireguard_peer_get_preshared_key_flags (peer));
|
||||
|
||||
if ( nm_wireguard_peer_get_persistent_keepalive (peer) != 0
|
||||
|| !strict)
|
||||
s_persistent_keepalive = g_strdup_printf ("persistent-keepalive=%u\n", nm_wireguard_peer_get_persistent_keepalive (peer));
|
||||
|
||||
if ( nm_wireguard_peer_get_allowed_ips_len (peer) > 0
|
||||
|| !strict) {
|
||||
nm_gstring_prepare (&gstr_aip);
|
||||
for (j = 0; j < nm_wireguard_peer_get_allowed_ips_len (peer); j++)
|
||||
g_string_append_printf (gstr_aip, "%s;", nm_wireguard_peer_get_allowed_ip (peer, j, NULL));
|
||||
s_allowed_ips = g_strdup_printf ("allowed-ips=%s\n", gstr_aip->str);
|
||||
}
|
||||
|
||||
if ( !s_endpoint
|
||||
&& !s_preshared_key
|
||||
&& !s_preshared_key_flags
|
||||
&& !s_persistent_keepalive
|
||||
&& !s_allowed_ips)
|
||||
s_endpoint = g_strdup_printf ("endpoint=\n");
|
||||
|
||||
g_string_append_printf (gstr,
|
||||
"\n"
|
||||
"[wireguard-peer.%s]\n"
|
||||
"%s" /* endpoint */
|
||||
"%s" /* preshared-key */
|
||||
"%s" /* preshared-key-flags */
|
||||
"%s" /* persistent-keepalive */
|
||||
"%s" /* allowed-ips */
|
||||
"",
|
||||
nm_wireguard_peer_get_public_key (peer),
|
||||
s_endpoint ?: "",
|
||||
s_preshared_key ?: "",
|
||||
s_preshared_key_flags ?: "",
|
||||
s_persistent_keepalive ?: "",
|
||||
s_allowed_ips ?: "");
|
||||
}
|
||||
|
||||
return (*out_str = g_string_free (g_steal_pointer (&gstr), FALSE));
|
||||
}
|
||||
|
||||
static void
|
||||
_rndt_wg_peers_assert_equal (NMSettingWireGuard *s_wg,
|
||||
GPtrArray *peers,
|
||||
gboolean consider_persistent_secrets,
|
||||
gboolean consider_all_secrets,
|
||||
gboolean expect_no_secrets)
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_assert (NM_IS_SETTING_WIREGUARD (s_wg));
|
||||
g_assert (peers);
|
||||
|
||||
g_assert_cmpint (peers->len, ==, nm_setting_wireguard_get_peers_len (s_wg));
|
||||
|
||||
for (i = 0; i < peers->len; i++) {
|
||||
const NMWireGuardPeer *a = peers->pdata[i];
|
||||
const NMWireGuardPeer *b = nm_setting_wireguard_get_peer (s_wg, i);
|
||||
gboolean consider_secrets;
|
||||
|
||||
g_assert (a);
|
||||
g_assert (b);
|
||||
|
||||
g_assert_cmpint (nm_wireguard_peer_cmp (a, b, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS), ==, 0);
|
||||
|
||||
if ( consider_all_secrets
|
||||
|| !nm_wireguard_peer_get_preshared_key (a))
|
||||
consider_secrets = TRUE;
|
||||
else if (nm_wireguard_peer_get_preshared_key (b))
|
||||
consider_secrets = TRUE;
|
||||
else if ( consider_persistent_secrets
|
||||
&& nm_wireguard_peer_get_preshared_key_flags (b) == NM_SETTING_SECRET_FLAG_NONE)
|
||||
consider_secrets = TRUE;
|
||||
else
|
||||
consider_secrets = FALSE;
|
||||
|
||||
if (consider_secrets) {
|
||||
g_assert_cmpstr (nm_wireguard_peer_get_preshared_key (a), ==, nm_wireguard_peer_get_preshared_key (b));
|
||||
g_assert_cmpint (nm_wireguard_peer_cmp (a, b, NM_SETTING_COMPARE_FLAG_EXACT), ==, 0);
|
||||
}
|
||||
|
||||
if (expect_no_secrets)
|
||||
g_assert_cmpstr (nm_wireguard_peer_get_preshared_key (b), ==, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_rndt_wg_peers_fix_secrets (NMSettingWireGuard *s_wg,
|
||||
GPtrArray *peers)
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_assert (NM_IS_SETTING_WIREGUARD (s_wg));
|
||||
g_assert (peers);
|
||||
|
||||
g_assert_cmpint (peers->len, ==, nm_setting_wireguard_get_peers_len (s_wg));
|
||||
|
||||
for (i = 0; i < peers->len; i++) {
|
||||
const NMWireGuardPeer *a = peers->pdata[i];
|
||||
const NMWireGuardPeer *b = nm_setting_wireguard_get_peer (s_wg, i);
|
||||
nm_auto_unref_wgpeer NMWireGuardPeer *b_clone = NULL;
|
||||
|
||||
g_assert (a);
|
||||
g_assert (b);
|
||||
|
||||
g_assert_cmpint (nm_wireguard_peer_get_preshared_key_flags (a), ==, nm_wireguard_peer_get_preshared_key_flags (b));
|
||||
g_assert_cmpint (nm_wireguard_peer_cmp (a, b, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS), ==, 0);
|
||||
|
||||
if (!nm_streq0 (nm_wireguard_peer_get_preshared_key (a),
|
||||
nm_wireguard_peer_get_preshared_key (b))) {
|
||||
g_assert_cmpstr (nm_wireguard_peer_get_preshared_key (a), !=, NULL);
|
||||
g_assert_cmpstr (nm_wireguard_peer_get_preshared_key (b), ==, NULL);
|
||||
g_assert (NM_IN_SET (nm_wireguard_peer_get_preshared_key_flags (a), NM_SETTING_SECRET_FLAG_AGENT_OWNED,
|
||||
NM_SETTING_SECRET_FLAG_NOT_SAVED));
|
||||
b_clone = nm_wireguard_peer_new_clone (b, TRUE);
|
||||
nm_wireguard_peer_set_preshared_key (b_clone, nm_wireguard_peer_get_preshared_key (a));
|
||||
nm_setting_wireguard_set_peer (s_wg, b_clone, i);
|
||||
b = nm_setting_wireguard_get_peer (s_wg, i);
|
||||
g_assert (b == b_clone);
|
||||
} else {
|
||||
if (nm_wireguard_peer_get_preshared_key (a)) {
|
||||
g_assert (NM_IN_SET (nm_wireguard_peer_get_preshared_key_flags (a), NM_SETTING_SECRET_FLAG_NONE,
|
||||
NM_SETTING_SECRET_FLAG_NOT_REQUIRED));
|
||||
} else {
|
||||
g_assert (NM_IN_SET (nm_wireguard_peer_get_preshared_key_flags (a), NM_SETTING_SECRET_FLAG_AGENT_OWNED,
|
||||
NM_SETTING_SECRET_FLAG_NONE,
|
||||
NM_SETTING_SECRET_FLAG_NOT_SAVED,
|
||||
NM_SETTING_SECRET_FLAG_NOT_REQUIRED));
|
||||
}
|
||||
}
|
||||
|
||||
g_assert_cmpstr (nm_wireguard_peer_get_preshared_key (a), ==, nm_wireguard_peer_get_preshared_key (b));
|
||||
g_assert_cmpint (nm_wireguard_peer_cmp (a, b, NM_SETTING_COMPARE_FLAG_EXACT), ==, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_roundtrip_conversion (gconstpointer test_data)
|
||||
{
|
||||
|
|
@ -2022,7 +2275,18 @@ test_roundtrip_conversion (gconstpointer test_data)
|
|||
const char *INTERFACE_NAME = nm_sprintf_bufa (100, "ifname%d", MODE);
|
||||
guint32 ETH_MTU = nmtst_rand_select ((guint32) 0u,
|
||||
nmtst_get_rand_int ());
|
||||
const char *WG_PRIVATE_KEY = nmtst_get_rand_bool ()
|
||||
? "yGXGK+5bVnxSJUejH4vbpXbq+ZtaG4NB8IHRK/aVtE0="
|
||||
: NULL;
|
||||
const NMSettingSecretFlags WG_PRIVATE_KEY_FLAGS = nmtst_rand_select (NM_SETTING_SECRET_FLAG_NONE,
|
||||
NM_SETTING_SECRET_FLAG_NOT_SAVED,
|
||||
NM_SETTING_SECRET_FLAG_AGENT_OWNED);
|
||||
const guint WG_LISTEN_PORT = nmtst_rand_select (0u,
|
||||
nmtst_get_rand_int () % 0x10000);
|
||||
const guint WG_FWMARK = nmtst_rand_select (0u,
|
||||
nmtst_get_rand_int ());
|
||||
gs_unref_ptrarray GPtrArray *kf_data_arr = g_ptr_array_new_with_free_func (g_free);
|
||||
gs_unref_ptrarray GPtrArray *wg_peers = NULL;
|
||||
const NMConnectionSerializationFlags dbus_serialization_flags[] = {
|
||||
NM_CONNECTION_SERIALIZE_ALL,
|
||||
NM_CONNECTION_SERIALIZE_NO_SECRETS,
|
||||
|
|
@ -2031,9 +2295,12 @@ test_roundtrip_conversion (gconstpointer test_data)
|
|||
guint dbus_serialization_flags_idx;
|
||||
gs_unref_object NMConnection *con = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
gs_free char *tmp_str = NULL;
|
||||
guint kf_data_idx;
|
||||
NMSettingConnection *s_con = NULL;
|
||||
NMSettingWired *s_eth = NULL;
|
||||
NMSettingWireGuard *s_wg = NULL;
|
||||
guint i;
|
||||
|
||||
switch (MODE) {
|
||||
case 0:
|
||||
|
|
@ -2110,6 +2377,116 @@ test_roundtrip_conversion (gconstpointer test_data)
|
|||
|
||||
break;
|
||||
|
||||
case 1:
|
||||
con = nmtst_create_minimal_connection (ID, UUID, "wireguard", &s_con);
|
||||
g_object_set (s_con,
|
||||
NM_SETTING_CONNECTION_INTERFACE_NAME,
|
||||
INTERFACE_NAME,
|
||||
NULL);
|
||||
nmtst_connection_normalize (con);
|
||||
|
||||
s_wg = NM_SETTING_WIREGUARD (nm_connection_get_setting (con, NM_TYPE_SETTING_WIREGUARD));
|
||||
|
||||
g_ptr_array_add (kf_data_arr,
|
||||
g_strdup_printf ("[connection]\n"
|
||||
"id=%s\n"
|
||||
"uuid=%s\n"
|
||||
"type=wireguard\n"
|
||||
"interface-name=%s\n"
|
||||
"permissions=\n"
|
||||
"\n"
|
||||
"[ipv4]\n"
|
||||
"dns-search=\n"
|
||||
"method=disabled\n"
|
||||
"\n"
|
||||
"[ipv6]\n"
|
||||
"addr-gen-mode=stable-privacy\n"
|
||||
"dns-search=\n"
|
||||
"method=ignore\n"
|
||||
"",
|
||||
ID,
|
||||
UUID,
|
||||
INTERFACE_NAME));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
con = nmtst_create_minimal_connection (ID, UUID, "wireguard", &s_con);
|
||||
g_object_set (s_con,
|
||||
NM_SETTING_CONNECTION_INTERFACE_NAME,
|
||||
INTERFACE_NAME,
|
||||
NULL);
|
||||
nmtst_connection_normalize (con);
|
||||
|
||||
s_wg = NM_SETTING_WIREGUARD (nm_connection_get_setting (con, NM_TYPE_SETTING_WIREGUARD));
|
||||
g_object_set (s_wg,
|
||||
NM_SETTING_WIREGUARD_PRIVATE_KEY,
|
||||
WG_PRIVATE_KEY,
|
||||
NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS,
|
||||
WG_PRIVATE_KEY_FLAGS,
|
||||
NM_SETTING_WIREGUARD_LISTEN_PORT,
|
||||
WG_LISTEN_PORT,
|
||||
NM_SETTING_WIREGUARD_FWMARK,
|
||||
WG_FWMARK,
|
||||
NULL);
|
||||
|
||||
wg_peers = _rndt_wg_peers_create ();
|
||||
|
||||
for (i = 0; i < wg_peers->len; i++)
|
||||
nm_setting_wireguard_append_peer (s_wg, wg_peers->pdata[i]);
|
||||
|
||||
nm_clear_g_free (&tmp_str);
|
||||
|
||||
g_ptr_array_add (kf_data_arr,
|
||||
g_strdup_printf ("[connection]\n"
|
||||
"id=%s\n"
|
||||
"uuid=%s\n"
|
||||
"type=wireguard\n"
|
||||
"interface-name=%s\n"
|
||||
"permissions=\n"
|
||||
"%s" /* [wireguard] */
|
||||
"%s" /* fwmark */
|
||||
"%s" /* listen-port */
|
||||
"%s" /* private-key-flags */
|
||||
"%s" /* private-key */
|
||||
"%s" /* [wireguard-peers*] */
|
||||
"\n"
|
||||
"[ipv4]\n"
|
||||
"dns-search=\n"
|
||||
"method=disabled\n"
|
||||
"\n"
|
||||
"[ipv6]\n"
|
||||
"addr-gen-mode=stable-privacy\n"
|
||||
"dns-search=\n"
|
||||
"method=ignore\n"
|
||||
"",
|
||||
ID,
|
||||
UUID,
|
||||
INTERFACE_NAME,
|
||||
( ( (WG_FWMARK != 0)
|
||||
|| (WG_LISTEN_PORT != 0)
|
||||
|| (WG_PRIVATE_KEY_FLAGS != NM_SETTING_SECRET_FLAG_NONE)
|
||||
|| ( WG_PRIVATE_KEY
|
||||
&& WG_PRIVATE_KEY_FLAGS == NM_SETTING_SECRET_FLAG_NONE))
|
||||
? "\n[wireguard]\n"
|
||||
: ""),
|
||||
( (WG_FWMARK != 0)
|
||||
? nm_sprintf_bufa (100, "fwmark=%u\n", WG_FWMARK)
|
||||
: ""),
|
||||
( (WG_LISTEN_PORT != 0)
|
||||
? nm_sprintf_bufa (100, "listen-port=%u\n", WG_LISTEN_PORT)
|
||||
: ""),
|
||||
( (WG_PRIVATE_KEY_FLAGS != NM_SETTING_SECRET_FLAG_NONE)
|
||||
? nm_sprintf_bufa (100, "private-key-flags=%u\n", (guint) WG_PRIVATE_KEY_FLAGS)
|
||||
: ""),
|
||||
( ( WG_PRIVATE_KEY
|
||||
&& WG_PRIVATE_KEY_FLAGS == NM_SETTING_SECRET_FLAG_NONE)
|
||||
? nm_sprintf_bufa (100, "private-key=%s\n", WG_PRIVATE_KEY)
|
||||
: ""),
|
||||
_rndt_wg_peers_to_keyfile (wg_peers, TRUE, &tmp_str)));
|
||||
|
||||
_rndt_wg_peers_assert_equal (s_wg, wg_peers, TRUE, TRUE, FALSE);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
|
@ -2131,6 +2508,7 @@ test_roundtrip_conversion (gconstpointer test_data)
|
|||
/* check that reading any of kf_data_arr yields the same result that we expect. */
|
||||
for (kf_data_idx = 0; kf_data_idx < kf_data_arr->len; kf_data_idx++) {
|
||||
gs_unref_object NMConnection *con2 = NULL;
|
||||
NMSettingWireGuard *s_wg2 = NULL;
|
||||
NMSettingWired *s_eth2 = NULL;
|
||||
|
||||
con2 = nmtst_create_connection_from_keyfile (kf_data_arr->pdata[kf_data_idx], "/no/where/file.nmconnection");
|
||||
|
|
@ -2159,6 +2537,35 @@ test_roundtrip_conversion (gconstpointer test_data)
|
|||
g_assert_cmpint (nm_setting_wired_get_mtu (s_eth), ==, ETH_MTU);
|
||||
g_assert_cmpint (nm_setting_wired_get_mtu (s_eth2), ==, ETH_MTU);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
s_wg2 = NM_SETTING_WIREGUARD (nm_connection_get_setting (con2, NM_TYPE_SETTING_WIREGUARD));
|
||||
g_assert (NM_IS_SETTING_WIREGUARD (s_wg2));
|
||||
|
||||
g_assert_cmpstr (nm_setting_wireguard_get_private_key (s_wg), ==, NULL);
|
||||
g_assert_cmpstr (nm_setting_wireguard_get_private_key (s_wg2), ==, NULL);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
s_wg2 = NM_SETTING_WIREGUARD (nm_connection_get_setting (con2, NM_TYPE_SETTING_WIREGUARD));
|
||||
g_assert (NM_IS_SETTING_WIREGUARD (s_wg2));
|
||||
|
||||
/* the private key was lost due to the secret-flags. Patch it. */
|
||||
if (WG_PRIVATE_KEY_FLAGS != NM_SETTING_SECRET_FLAG_NONE) {
|
||||
g_assert_cmpstr (nm_setting_wireguard_get_private_key (s_wg2), ==, NULL);
|
||||
g_object_set (s_wg2,
|
||||
NM_SETTING_WIREGUARD_PRIVATE_KEY,
|
||||
WG_PRIVATE_KEY,
|
||||
NULL);
|
||||
}
|
||||
|
||||
g_assert_cmpstr (nm_setting_wireguard_get_private_key (s_wg), ==, WG_PRIVATE_KEY);
|
||||
g_assert_cmpstr (nm_setting_wireguard_get_private_key (s_wg2), ==, WG_PRIVATE_KEY);
|
||||
|
||||
_rndt_wg_peers_assert_equal (s_wg2, wg_peers, TRUE, FALSE, FALSE);
|
||||
_rndt_wg_peers_fix_secrets (s_wg2, wg_peers);
|
||||
_rndt_wg_peers_assert_equal (s_wg2, wg_peers, TRUE, TRUE, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
nmtst_assert_connection_equals (con, nmtst_get_rand_bool (), con2, nmtst_get_rand_bool ());
|
||||
|
|
@ -2168,6 +2575,7 @@ test_roundtrip_conversion (gconstpointer test_data)
|
|||
NMConnectionSerializationFlags flag = dbus_serialization_flags[dbus_serialization_flags_idx];
|
||||
gs_unref_variant GVariant *con_var = NULL;
|
||||
gs_unref_object NMConnection *con2 = NULL;
|
||||
NMSettingWireGuard *s_wg2 = NULL;
|
||||
|
||||
con_var = nm_connection_to_dbus (con, flag);
|
||||
g_assert (g_variant_is_of_type (con_var, NM_VARIANT_TYPE_CONNECTION));
|
||||
|
|
@ -2186,6 +2594,21 @@ test_roundtrip_conversion (gconstpointer test_data)
|
|||
nmtst_keyfile_assert_data (kf, kf_data_arr->pdata[0], -1);
|
||||
}
|
||||
}
|
||||
|
||||
switch (MODE) {
|
||||
case 2:
|
||||
if (flag == NM_CONNECTION_SERIALIZE_ALL) {
|
||||
s_wg2 = NM_SETTING_WIREGUARD (nm_connection_get_setting (con2, NM_TYPE_SETTING_WIREGUARD));
|
||||
|
||||
if (flag == NM_CONNECTION_SERIALIZE_ALL)
|
||||
_rndt_wg_peers_assert_equal (s_wg2, wg_peers, TRUE, TRUE, FALSE);
|
||||
else if (flag == NM_CONNECTION_SERIALIZE_NO_SECRETS)
|
||||
_rndt_wg_peers_assert_equal (s_wg2, wg_peers, FALSE, FALSE, TRUE);
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2268,6 +2691,8 @@ main (int argc, char **argv)
|
|||
#endif
|
||||
|
||||
g_test_add_data_func ("/libnm/settings/roundtrip-conversion/general/0", GINT_TO_POINTER (0), test_roundtrip_conversion);
|
||||
g_test_add_data_func ("/libnm/settings/roundtrip-conversion/wireguard/1", GINT_TO_POINTER (1), test_roundtrip_conversion);
|
||||
g_test_add_data_func ("/libnm/settings/roundtrip-conversion/wireguard/2", GINT_TO_POINTER (2), test_roundtrip_conversion);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@
|
|||
#include "nm-setting-vxlan.h"
|
||||
#include "nm-setting-wimax.h"
|
||||
#include "nm-setting-wired.h"
|
||||
#include "nm-setting-wireguard.h"
|
||||
#include "nm-setting-wireless.h"
|
||||
#include "nm-setting-wireless-security.h"
|
||||
#include "nm-setting-wpan.h"
|
||||
|
|
|
|||
|
|
@ -1462,6 +1462,19 @@ global:
|
|||
nm_setting_wifi_p2p_get_wfd_ies;
|
||||
nm_setting_wifi_p2p_get_wps_method;
|
||||
nm_setting_wifi_p2p_new;
|
||||
nm_setting_wireguard_append_peer;
|
||||
nm_setting_wireguard_clear_peers;
|
||||
nm_setting_wireguard_get_fwmark;
|
||||
nm_setting_wireguard_get_listen_port;
|
||||
nm_setting_wireguard_get_peer;
|
||||
nm_setting_wireguard_get_peer_by_public_key;
|
||||
nm_setting_wireguard_get_peers_len;
|
||||
nm_setting_wireguard_get_private_key;
|
||||
nm_setting_wireguard_get_private_key_flags;
|
||||
nm_setting_wireguard_get_type;
|
||||
nm_setting_wireguard_new;
|
||||
nm_setting_wireguard_remove_peer;
|
||||
nm_setting_wireguard_set_peer;
|
||||
nm_team_link_watcher_get_vlanid;
|
||||
nm_team_link_watcher_new_arp_ping2;
|
||||
nm_wifi_p2p_peer_connection_valid;
|
||||
|
|
@ -1477,4 +1490,28 @@ global:
|
|||
nm_wifi_p2p_peer_get_strength;
|
||||
nm_wifi_p2p_peer_get_type;
|
||||
nm_wifi_p2p_peer_get_wfd_ies;
|
||||
nm_wireguard_peer_append_allowed_ip;
|
||||
nm_wireguard_peer_clear_allowed_ips;
|
||||
nm_wireguard_peer_cmp;
|
||||
nm_wireguard_peer_get_allowed_ip;
|
||||
nm_wireguard_peer_get_allowed_ips_len;
|
||||
nm_wireguard_peer_get_endpoint;
|
||||
nm_wireguard_peer_get_persistent_keepalive;
|
||||
nm_wireguard_peer_get_preshared_key;
|
||||
nm_wireguard_peer_get_preshared_key_flags;
|
||||
nm_wireguard_peer_get_public_key;
|
||||
nm_wireguard_peer_get_type;
|
||||
nm_wireguard_peer_is_sealed;
|
||||
nm_wireguard_peer_is_valid;
|
||||
nm_wireguard_peer_new;
|
||||
nm_wireguard_peer_new_clone;
|
||||
nm_wireguard_peer_ref;
|
||||
nm_wireguard_peer_remove_allowed_ip;
|
||||
nm_wireguard_peer_seal;
|
||||
nm_wireguard_peer_set_endpoint;
|
||||
nm_wireguard_peer_set_persistent_keepalive;
|
||||
nm_wireguard_peer_set_preshared_key;
|
||||
nm_wireguard_peer_set_preshared_key_flags;
|
||||
nm_wireguard_peer_set_public_key;
|
||||
nm_wireguard_peer_unref;
|
||||
} libnm_1_14_0;
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingVxlan, g_object_unref)
|
|||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingWifiP2P, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingWimax, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingWired, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingWireGuard, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingWireless, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingWirelessSecurity, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingWpan, g_object_unref)
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ libnm-core/nm-setting-vxlan.c
|
|||
libnm-core/nm-setting-wifi-p2p.c
|
||||
libnm-core/nm-setting-wimax.c
|
||||
libnm-core/nm-setting-wired.c
|
||||
libnm-core/nm-setting-wireguard.c
|
||||
libnm-core/nm-setting-wireless-security.c
|
||||
libnm-core/nm-setting-wireless.c
|
||||
libnm-core/nm-setting-wpan.c
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@
|
|||
#include "nm-setting-wifi-p2p.h"
|
||||
#include "nm-setting-wimax.h"
|
||||
#include "nm-setting-wired.h"
|
||||
#include "nm-setting-wireguard.h"
|
||||
#include "nm-setting-wireless-security.h"
|
||||
#include "nm-setting-wireless.h"
|
||||
#include "nm-setting-wpan.h"
|
||||
|
|
@ -402,6 +403,12 @@ const NMMetaSettingInfo nm_meta_setting_infos[] = {
|
|||
.setting_name = NM_SETTING_WIRED_SETTING_NAME,
|
||||
.get_setting_gtype = nm_setting_wired_get_type,
|
||||
},
|
||||
[NM_META_SETTING_TYPE_WIREGUARD] = {
|
||||
.meta_type = NM_META_SETTING_TYPE_WIREGUARD,
|
||||
.setting_priority = NM_SETTING_PRIORITY_HW_BASE,
|
||||
.setting_name = NM_SETTING_WIREGUARD_SETTING_NAME,
|
||||
.get_setting_gtype = nm_setting_wireguard_get_type,
|
||||
},
|
||||
[NM_META_SETTING_TYPE_WIRELESS] = {
|
||||
.meta_type = NM_META_SETTING_TYPE_WIRELESS,
|
||||
.setting_priority = NM_SETTING_PRIORITY_HW_BASE,
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@ typedef enum {
|
|||
NM_META_SETTING_TYPE_VXLAN,
|
||||
NM_META_SETTING_TYPE_WIFI_P2P,
|
||||
NM_META_SETTING_TYPE_WIMAX,
|
||||
NM_META_SETTING_TYPE_WIREGUARD,
|
||||
NM_META_SETTING_TYPE_WPAN,
|
||||
|
||||
NM_META_SETTING_TYPE_UNKNOWN,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -4363,8 +4363,7 @@ realize_start_setup (NMDevice *self,
|
|||
* NetworkManager might down the interface or remove the 127.0.0.1 address. */
|
||||
nm_device_set_unmanaged_flags (self,
|
||||
NM_UNMANAGED_BY_TYPE,
|
||||
is_loopback (self)
|
||||
|| NM_IS_DEVICE_WIREGUARD (self));
|
||||
is_loopback (self));
|
||||
|
||||
nm_device_set_unmanaged_by_user_udev (self);
|
||||
nm_device_set_unmanaged_by_user_conf (self);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue