summaryrefslogtreecommitdiffhomepage
path: root/src/config.c
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2017-03-28 11:55:27 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2017-03-28 11:55:27 +0200
commitb0520f85366095675ff59c112f2060ad9ce7df80 (patch)
treee1493a8bb6c71b11bca868fc7e0cc122407370f8 /src/config.c
parentdf3c824b8ef2f824771d921a0aa10429f8c2b064 (diff)
config: do not allow peers with public keys the same as the interface
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'src/config.c')
-rw-r--r--src/config.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/src/config.c b/src/config.c
index 963f9e1..c420f7c 100644
--- a/src/config.c
+++ b/src/config.c
@@ -61,6 +61,16 @@ static int set_peer(struct wireguard_device *wg, void __user *user_peer, size_t
if (!peer) { /* Peer doesn't exist yet. Add a new one. */
if (in_peer.flags & WGPEER_REMOVE_ME)
return -ENODEV; /* Tried to remove a non existing peer. */
+
+ down_read(&wg->static_identity.lock);
+ if (wg->static_identity.has_identity && !memcmp(in_peer.public_key, wg->static_identity.static_public, NOISE_PUBLIC_KEY_LEN)) {
+ /* We silently ignore peers that have the same public key as the device. The reason we do it silently
+ * is that we'd like for people to be able to reuse the same set of API calls across peers. */
+ up_read(&wg->static_identity.lock);
+ goto out;
+ }
+ up_read(&wg->static_identity.lock);
+
peer = peer_rcu_get(peer_create(wg, in_peer.public_key));
if (!peer)
return -ENOMEM;
@@ -146,6 +156,16 @@ int config_set_device(struct wireguard_device *wg, void __user *user_device)
noise_set_static_identity_private_key(&wg->static_identity, NULL);
modified_static_identity = true;
} else if (memcmp(zeros, in_device.private_key, WG_KEY_LEN)) {
+ u8 public_key[NOISE_PUBLIC_KEY_LEN] = { 0 };
+ struct wireguard_peer *peer;
+ /* We remove before setting, to prevent race, which means doing two 25519-genpub ops. */
+ curve25519_generate_public(public_key, in_device.private_key);
+ peer = pubkey_hashtable_lookup(&wg->peer_hashtable, public_key);
+ if (peer) {
+ peer_put(peer);
+ peer_remove(peer);
+ }
+
noise_set_static_identity_private_key(&wg->static_identity, in_device.private_key);
modified_static_identity = true;
}