diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml
index a9ebd153b8..b0058c11c8 100644
--- a/man/systemd.netdev.xml
+++ b/man/systemd.netdev.xml
@@ -2026,6 +2026,19 @@
+
+ PublicKeyFile=
+
+ Takes an absolute path to a file which contains the Base64 encoded public key for the peer.
+ When this option is specified, then PublicKey= will be ignored. Note that the
+ file must be readable by the user systemd-network, so it should be, e.g., owned
+ by root:systemd-network with a 0640 file mode. If the path
+ refers to an AF_UNIX stream socket in the file system a connection is made to
+ it and the key read from it.
+
+
+
+
PresharedKey=
diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf
index 2ac92e061f..03a4791ee4 100644
--- a/src/network/netdev/netdev-gperf.gperf
+++ b/src/network/netdev/netdev-gperf.gperf
@@ -250,8 +250,9 @@ WireGuard.RouteMetric, config_parse_wireguard_route_priority,
WireGuardPeer.AllowedIPs, config_parse_wireguard_allowed_ips, 0, 0
WireGuardPeer.Endpoint, config_parse_wireguard_endpoint, 0, 0
WireGuardPeer.PublicKey, config_parse_wireguard_peer_key, 0, 0
+WireGuardPeer.PublicKeyFile, config_parse_wireguard_peer_key_file, 0, 0
WireGuardPeer.PresharedKey, config_parse_wireguard_peer_key, 0, 0
-WireGuardPeer.PresharedKeyFile, config_parse_wireguard_preshared_key_file, 0, 0
+WireGuardPeer.PresharedKeyFile, config_parse_wireguard_peer_key_file, 0, 0
WireGuardPeer.PersistentKeepalive, config_parse_wireguard_keepalive, 0, 0
WireGuardPeer.RouteTable, config_parse_wireguard_peer_route_table, 0, 0
WireGuardPeer.RouteMetric, config_parse_wireguard_peer_route_priority,0, 0
diff --git a/src/network/netdev/wireguard.c b/src/network/netdev/wireguard.c
index fed1be8d11..ba013e3ba5 100644
--- a/src/network/netdev/wireguard.c
+++ b/src/network/netdev/wireguard.c
@@ -60,6 +60,7 @@ static WireguardPeer* wireguard_peer_free(WireguardPeer *peer) {
free(peer->endpoint_host);
free(peer->endpoint_port);
+ free(peer->public_key_file);
free(peer->preshared_key_file);
explicit_bzero_safe(peer->preshared_key, WG_KEY_LEN);
@@ -609,7 +610,7 @@ int config_parse_wireguard_peer_key(
return 0;
}
-int config_parse_wireguard_preshared_key_file(
+int config_parse_wireguard_peer_key_file(
const char *unit,
const char *filename,
unsigned line,
@@ -624,14 +625,25 @@ int config_parse_wireguard_preshared_key_file(
Wireguard *w = WIREGUARD(data);
_cleanup_(wireguard_peer_free_or_set_invalidp) WireguardPeer *peer = NULL;
_cleanup_free_ char *path = NULL;
+ char **key_file;
int r;
+ assert(filename);
+ assert(lvalue);
+
r = wireguard_peer_new_static(w, filename, section_line, &peer);
if (r < 0)
return log_oom();
+ if (streq(lvalue, "PublicKeyFile"))
+ key_file = &peer->public_key_file;
+ else if (streq(lvalue, "PresharedKeyFile"))
+ key_file = &peer->preshared_key_file;
+ else
+ assert_not_reached();
+
if (isempty(rvalue)) {
- peer->preshared_key_file = mfree(peer->preshared_key_file);
+ *key_file = mfree(*key_file);
TAKE_PTR(peer);
return 0;
}
@@ -643,7 +655,7 @@ int config_parse_wireguard_preshared_key_file(
if (path_simplify_and_warn(path, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue) < 0)
return 0;
- free_and_replace(peer->preshared_key_file, path);
+ free_and_replace(*key_file, path);
TAKE_PTR(peer);
return 0;
}
@@ -1099,6 +1111,14 @@ static int wireguard_peer_verify(WireguardPeer *peer) {
if (section_is_invalid(peer->section))
return -EINVAL;
+ r = wireguard_read_key_file(peer->public_key_file, peer->public_key);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r,
+ "%s: Failed to read public key from '%s'. "
+ "Ignoring [WireGuardPeer] section from line %u.",
+ peer->section->filename, peer->public_key_file,
+ peer->section->line);
+
if (eqzero(peer->public_key))
return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
"%s: WireGuardPeer section without PublicKey= configured. "
diff --git a/src/network/netdev/wireguard.h b/src/network/netdev/wireguard.h
index 09dca88bbf..8e5b3b58f5 100644
--- a/src/network/netdev/wireguard.h
+++ b/src/network/netdev/wireguard.h
@@ -28,6 +28,7 @@ typedef struct WireguardPeer {
uint8_t public_key[WG_KEY_LEN];
uint8_t preshared_key[WG_KEY_LEN];
+ char *public_key_file;
char *preshared_key_file;
uint32_t flags;
uint16_t persistent_keepalive_interval;
@@ -74,9 +75,9 @@ CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_allowed_ips);
CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_endpoint);
CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_listen_port);
CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_peer_key);
+CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_peer_key_file);
CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_private_key);
CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_private_key_file);
-CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_preshared_key_file);
CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_keepalive);
CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_route_table);
CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_peer_route_table);
diff --git a/test/test-network/conf/25-wireguard-public-key.txt b/test/test-network/conf/25-wireguard-public-key.txt
new file mode 100644
index 0000000000..0267479682
--- /dev/null
+++ b/test/test-network/conf/25-wireguard-public-key.txt
@@ -0,0 +1 @@
+lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=
diff --git a/test/test-network/conf/25-wireguard.netdev.d/peer.conf b/test/test-network/conf/25-wireguard.netdev.d/peer.conf
index f559ea68f6..9f8770de59 100644
--- a/test/test-network/conf/25-wireguard.netdev.d/peer.conf
+++ b/test/test-network/conf/25-wireguard.netdev.d/peer.conf
@@ -1,5 +1,5 @@
[WireGuardPeer]
-PublicKey=lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=
+PublicKeyFile=/run/systemd/network/25-wireguard-public-key.txt
AllowedIPs=fdbc:bae2:7871:0500:e1fe:0793:8636:dad1/128
AllowedIPs=fdbc:bae2:7871:e1fe:0793:8636::/96
PresharedKeyFile=/run/systemd/network/25-wireguard-preshared-key.txt
diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py
index 0b95bfff14..3a30c8bfd1 100755
--- a/test/test-network/systemd-networkd-tests.py
+++ b/test/test-network/systemd-networkd-tests.py
@@ -1940,7 +1940,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
copy_network_unit('25-wireguard.netdev', '25-wireguard.network',
'25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network',
- '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt',
+ '25-wireguard-public-key.txt', '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt',
'25-wireguard-no-peer.netdev', '25-wireguard-no-peer.network')
start_networkd()
self.wait_online('wg99:routable', 'wg98:routable', 'wg97:carrier')