]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network/wireguard: introduce [WireGuardPeer] PublicKeyFile=
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 16 Aug 2024 13:13:23 +0000 (22:13 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 16 Aug 2024 16:58:02 +0000 (01:58 +0900)
Similar to PresharedKeyFile=, but for public key.

Closes #34012.

man/systemd.netdev.xml
src/network/netdev/netdev-gperf.gperf
src/network/netdev/wireguard.c
src/network/netdev/wireguard.h
test/test-network/conf/25-wireguard-public-key.txt [new file with mode: 0644]
test/test-network/conf/25-wireguard.netdev.d/peer.conf
test/test-network/systemd-networkd-tests.py

index a9ebd153b89550fb24bd5c0196aa7e8de74304f8..b0058c11c8744df0796ec6be19b4d5fb41c2a689 100644 (file)
         <xi:include href="version-info.xml" xpointer="v237"/>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><varname>PublicKeyFile=</varname></term>
+        <listitem>
+          <para>Takes an absolute path to a file which contains the Base64 encoded public key for the peer.
+          When this option is specified, then <varname>PublicKey=</varname> will be ignored. Note that the
+          file must be readable by the user <literal>systemd-network</literal>, so it should be, e.g., owned
+          by <literal>root:systemd-network</literal> with a <literal>0640</literal> file mode. If the path
+          refers to an <constant>AF_UNIX</constant> stream socket in the file system a connection is made to
+          it and the key read from it.</para>
+
+          <xi:include href="version-info.xml" xpointer="v257"/>
+        </listitem>
+      </varlistentry>
       <varlistentry>
         <term><varname>PresharedKey=</varname></term>
         <listitem>
index 2ac92e061fc9a3ddaf04981f61b9c0460e3c41c9..03a4791ee48ac790cee9a99e64e5aac5dc2967ae 100644 (file)
@@ -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
index fed1be8d1104613d37408b18e8f186b0df44f0b4..ba013e3ba54141e4e5444e55566fe9bc6a5fd3f0 100644 (file)
@@ -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. "
index 09dca88bbf0803bf29ccfed5fd57b931b6ceac59..8e5b3b58f56f26d03becbe875215803290a37b19 100644 (file)
@@ -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 (file)
index 0000000..0267479
--- /dev/null
@@ -0,0 +1 @@
+lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=
index f559ea68f6c45a17836f4f2f5ae3fa68af878655..9f8770de5941d72099e1835e8785bdf83deeffa9 100644 (file)
@@ -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
index 0b95bfff143763011282f5e0922c6875a157ecc6..3a30c8bfd19639a0fbbbada5a49d4f47a6235122 100755 (executable)
@@ -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')