diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml index 10397402a46..1836b5fe00e 100644 --- a/man/systemd.netdev.xml +++ b/man/systemd.netdev.xml @@ -1241,7 +1241,7 @@ PrivateKeyFile= - Takes a absolute path to a file which contains the Base64 encoded private key for the interface. + Takes an absolute path to a file which contains the Base64 encoded private key for the interface. When this option is specified, then PrivateKey= is 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 @@ -1296,6 +1296,16 @@ with a 0640 file mode. + + PresharedKeyFile= + + Takes an absolute path to a file which contains the Base64 encoded preshared key for the + peer. When this option is specified, then PresharedKey= is 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. + + AllowedIPs= diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf index fcd2ec2097b..1a3d6caeb9f 100644 --- a/src/network/netdev/netdev-gperf.gperf +++ b/src/network/netdev/netdev-gperf.gperf @@ -187,4 +187,5 @@ WireGuardPeer.AllowedIPs, config_parse_wireguard_allowed_ips, 0, WireGuardPeer.Endpoint, config_parse_wireguard_endpoint, 0, 0 WireGuardPeer.PublicKey, config_parse_wireguard_public_key, 0, 0 WireGuardPeer.PresharedKey, config_parse_wireguard_preshared_key, 0, 0 +WireGuardPeer.PresharedKeyFile, config_parse_wireguard_preshared_key_file, 0, 0 WireGuardPeer.PersistentKeepalive, config_parse_wireguard_keepalive, 0, 0 diff --git a/src/network/netdev/wireguard.c b/src/network/netdev/wireguard.c index d897090f722..0b618962015 100644 --- a/src/network/netdev/wireguard.c +++ b/src/network/netdev/wireguard.c @@ -53,6 +53,7 @@ static void wireguard_peer_free(WireguardPeer *peer) { free(peer->endpoint_host); free(peer->endpoint_port); + free(peer->preshared_key_file); explicit_bzero_safe(peer->preshared_key, WG_KEY_LEN); free(peer); @@ -602,6 +603,49 @@ int config_parse_wireguard_preshared_key( return 0; } +int config_parse_wireguard_preshared_key_file( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(wireguard_peer_free_or_set_invalidp) WireguardPeer *peer = NULL; + _cleanup_free_ char *path = NULL; + Wireguard *w; + int r; + + assert(data); + w = WIREGUARD(data); + assert(w); + + r = wireguard_peer_new_static(w, filename, section_line, &peer); + if (r < 0) + return r; + + if (isempty(rvalue)) { + peer->preshared_key_file = mfree(peer->preshared_key_file); + TAKE_PTR(peer); + return 0; + } + + path = strdup(rvalue); + if (!path) + return log_oom(); + + if (path_simplify_and_warn(path, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue) < 0) + return 0; + + free_and_replace(peer->preshared_key_file, path); + TAKE_PTR(peer); + return 0; +} + int config_parse_wireguard_public_key( const char *unit, const char *filename, @@ -879,6 +923,7 @@ finalize: static int wireguard_peer_verify(WireguardPeer *peer) { NetDev *netdev = NETDEV(peer->wireguard); + int r; if (section_is_invalid(peer->section)) return -EINVAL; @@ -889,6 +934,14 @@ static int wireguard_peer_verify(WireguardPeer *peer) { "Ignoring [WireGuardPeer] section from line %u.", peer->section->filename, peer->section->line); + r = wireguard_read_key_file(peer->preshared_key_file, peer->preshared_key); + if (r < 0) + return log_netdev_error_errno(netdev, r, + "%s: Failed to read preshared key from '%s'. " + "Ignoring [WireGuardPeer] section from line %u.", + peer->section->filename, peer->preshared_key_file, + peer->section->line); + return 0; } diff --git a/src/network/netdev/wireguard.h b/src/network/netdev/wireguard.h index 6cf6eec14db..4ae520c52ba 100644 --- a/src/network/netdev/wireguard.h +++ b/src/network/netdev/wireguard.h @@ -21,6 +21,7 @@ typedef struct WireguardPeer { uint8_t public_key[WG_KEY_LEN]; uint8_t preshared_key[WG_KEY_LEN]; + char *preshared_key_file; uint32_t flags; uint16_t persistent_keepalive_interval; @@ -63,4 +64,5 @@ CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_public_key); 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); +CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_preshared_key_file); CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_keepalive); diff --git a/test/fuzz/fuzz-netdev-parser/directives.netdev b/test/fuzz/fuzz-netdev-parser/directives.netdev index e0756dc7554..7da3955af6b 100644 --- a/test/fuzz/fuzz-netdev-parser/directives.netdev +++ b/test/fuzz/fuzz-netdev-parser/directives.netdev @@ -52,6 +52,7 @@ Name= [WireGuardPeer] Endpoint= PresharedKey= +PresharedKeyFile= PersistentKeepalive= PublicKey= AllowedIPs=