Skip to content

Commit 780182e

Browse files
committed
syncconf: account for psks removed from config file
Otherwise removing a psk from a config file wouldn't reflect on the runtime state. Note that this could have been implemented more simply, by just setting WGPEER_HAS_PRESHARED_KEY on all of the file's peers, since the psk slot is zeroed by calloc in config.c, and this way ones with no set key will be cleared. The downside is that this means every peer update will take the handshake lock in the kernel, creating more work and possibly contention: if (preshared_key) { down_write(&peer->handshake.lock); memcpy(&peer->handshake.preshared_key, preshared_key, NOISE_SYMMETRIC_KEY_LEN); up_write(&peer->handshake.lock); } Avoid this by only setting it if there's a mismatch between the runtime and the file. Computationally this shouldn't make much of a difference because we can do it in the same iteration as the peer removal detection. Reported-by: Patrick Havelange <[email protected]> Signed-off-by: Jason A. Donenfeld <[email protected]>
1 parent 5150cd6 commit 780182e

File tree

1 file changed

+24
-19
lines changed

1 file changed

+24
-19
lines changed

src/setconf.c

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@
1313
#include "ipc.h"
1414
#include "subcommands.h"
1515

16-
struct pubkey_origin {
17-
uint8_t *pubkey;
16+
struct peer_origin {
17+
struct wgpeer *peer;
1818
bool from_file;
1919
};
2020

21-
static int pubkey_cmp(const void *first, const void *second)
21+
static int peer_cmp(const void *first, const void *second)
2222
{
23-
const struct pubkey_origin *a = first, *b = second;
24-
int ret = memcmp(a->pubkey, b->pubkey, WG_KEY_LEN);
23+
const struct peer_origin *a = first, *b = second;
24+
int ret = memcmp(a->peer->public_key, b->peer->public_key, WG_KEY_LEN);
2525
if (ret)
2626
return ret;
2727
return a->from_file - b->from_file;
@@ -31,7 +31,7 @@ static bool sync_conf(struct wgdevice *file)
3131
{
3232
struct wgdevice *runtime;
3333
struct wgpeer *peer;
34-
struct pubkey_origin *pubkeys;
34+
struct peer_origin *peers;
3535
size_t peer_count = 0, i = 0;
3636

3737
if (!file->first_peer)
@@ -55,46 +55,51 @@ static bool sync_conf(struct wgdevice *file)
5555
for_each_wgpeer(runtime, peer)
5656
++peer_count;
5757

58-
pubkeys = calloc(peer_count, sizeof(*pubkeys));
59-
if (!pubkeys) {
58+
peers = calloc(peer_count, sizeof(*peers));
59+
if (!peers) {
6060
free_wgdevice(runtime);
61-
perror("Public key allocation");
61+
perror("Peer list allocation");
6262
return false;
6363
}
6464

6565
for_each_wgpeer(file, peer) {
66-
pubkeys[i].pubkey = peer->public_key;
67-
pubkeys[i].from_file = true;
66+
peers[i].peer = peer;
67+
peers[i].from_file = true;
6868
++i;
6969
}
7070
for_each_wgpeer(runtime, peer) {
71-
pubkeys[i].pubkey = peer->public_key;
72-
pubkeys[i].from_file = false;
71+
peers[i].peer = peer;
72+
peers[i].from_file = false;
7373
++i;
7474
}
75-
qsort(pubkeys, peer_count, sizeof(*pubkeys), pubkey_cmp);
75+
qsort(peers, peer_count, sizeof(*peers), peer_cmp);
7676

7777
for (i = 0; i < peer_count; ++i) {
78-
if (pubkeys[i].from_file)
78+
if (peers[i].from_file)
7979
continue;
80-
if (i == peer_count - 1 || !pubkeys[i + 1].from_file || memcmp(pubkeys[i].pubkey, pubkeys[i + 1].pubkey, WG_KEY_LEN)) {
80+
if (i == peer_count - 1 || !peers[i + 1].from_file || memcmp(peers[i].peer->public_key, peers[i + 1].peer->public_key, WG_KEY_LEN)) {
8181
peer = calloc(1, sizeof(struct wgpeer));
8282
if (!peer) {
8383
free_wgdevice(runtime);
84-
free(pubkeys);
84+
free(peers);
8585
perror("Peer allocation");
8686
return false;
8787
}
8888
peer->flags = WGPEER_REMOVE_ME;
89-
memcpy(peer->public_key, pubkeys[i].pubkey, WG_KEY_LEN);
89+
memcpy(peer->public_key, peers[i].peer->public_key, WG_KEY_LEN);
9090
peer->next_peer = file->first_peer;
9191
file->first_peer = peer;
9292
if (!file->last_peer)
9393
file->last_peer = peer;
94+
} else if (i < peer_count - 1 && peers[i + 1].from_file &&
95+
(peers[i].peer->flags & WGPEER_HAS_PRESHARED_KEY) && !(peers[i + 1].peer->flags & WGPEER_HAS_PRESHARED_KEY) &&
96+
!memcmp(peers[i].peer->public_key, peers[i + 1].peer->public_key, WG_KEY_LEN)) {
97+
memset(peers[i + 1].peer->preshared_key, 0, WG_KEY_LEN);
98+
peers[i + 1].peer->flags |= WGPEER_HAS_PRESHARED_KEY;
9499
}
95100
}
96101
free_wgdevice(runtime);
97-
free(pubkeys);
102+
free(peers);
98103
return true;
99104
}
100105

0 commit comments

Comments
 (0)