Support for legacy clients

This commit is contained in:
Iurii Egorov 2024-08-16 10:22:39 +03:00 committed by Iurii Egorov
parent e42813caac
commit dafa38e4b0
8 changed files with 91 additions and 4 deletions

View file

@ -62,7 +62,8 @@ enum wgdevice_attribute {
enum wgpeer_flag {
WGPEER_F_REMOVE_ME = 1U << 0,
WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1
WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1,
WGPEER_F_HAS_ADVANCED_SECURITY = 1U << 3
};
enum wgpeer_attribute {
WGPEER_A_UNSPEC,
@ -76,6 +77,7 @@ enum wgpeer_attribute {
WGPEER_A_TX_BYTES,
WGPEER_A_ALLOWEDIPS,
WGPEER_A_PROTOCOL_VERSION,
WGPEER_A_ADVANCED_SECURITY,
__WGPEER_A_LAST
};

View file

@ -447,6 +447,41 @@ static inline bool parse_uint32(uint32_t *device_value, const char *name, const
return true;
}
static inline bool parse_bool(bool *device_value, const char *name, const char *value) {
if (!strlen(value)) {
fprintf(stderr, "Unable to parse empty string\n");
return false;
}
if (!strcasecmp(value, "off")) {
*device_value = false;
return true;
}
if (!strcasecmp(value, "on")) {
*device_value = true;
return true;
}
if (!char_is_digit(value[0]))
goto err;
char *end;
uint32_t ret;
ret = strtoul(value, &end, 10);
if (*end) {
fprintf(stderr, "Unable to parse %s: `%s'\n", name, value);
exit(1);
}
*device_value = ret != 0;
return true;
err:
fprintf(stderr, "Boolean value is neither on/off nor 0/1: `%s'\n", value);
return false;
}
static bool process_line(struct config_ctx *ctx, const char *line)
{
const char *value;
@ -540,6 +575,10 @@ static bool process_line(struct config_ctx *ctx, const char *line)
ret = parse_key(ctx->last_peer->preshared_key, value);
if (ret)
ctx->last_peer->flags |= WGPEER_HAS_PRESHARED_KEY;
} else if (key_match("AdvancedSecurity")) {
ret = parse_bool(&ctx->last_peer->advanced_security, "AdvancedSecurity", value);
if (ret)
ctx->last_peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
} else
goto error;
} else
@ -774,6 +813,12 @@ struct wgdevice *config_read_cmd(const char *argv[], int argc)
peer->flags |= WGPEER_HAS_PRESHARED_KEY;
argv += 2;
argc -= 2;
} else if (!strcmp(argv[0], "advanced-security") && argc >= 2 && peer) {
if (!parse_bool(&peer->advanced_security, "AdvancedSecurity", argv[1]))
goto error;
peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
argv += 2;
argc -= 2;
} else {
fprintf(stderr, "Invalid argument: %s\n", argv[0]);
goto error;

View file

@ -7,6 +7,7 @@
#define CONTAINERS_H
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
#include <sys/socket.h>
@ -43,7 +44,8 @@ enum {
WGPEER_REPLACE_ALLOWEDIPS = 1U << 1,
WGPEER_HAS_PUBLIC_KEY = 1U << 2,
WGPEER_HAS_PRESHARED_KEY = 1U << 3,
WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL = 1U << 4
WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL = 1U << 4,
WGPEER_HAS_ADVANCED_SECURITY = 1U << 5
};
struct wgpeer {
@ -62,6 +64,8 @@ struct wgpeer {
uint64_t rx_bytes, tx_bytes;
uint16_t persistent_keepalive_interval;
bool advanced_security;
struct wgallowedip *first_allowedip, *last_allowedip;
struct wgpeer *next_peer;
};
@ -96,7 +100,7 @@ struct wgdevice {
uint16_t listen_port;
struct wgpeer *first_peer, *last_peer;
uint16_t junk_packet_count;
uint16_t junk_packet_min_size;
uint16_t junk_packet_max_size;

View file

@ -221,6 +221,11 @@ again:
goto toobig_peers;
}
}
if (peer->flags & WGPEER_HAS_ADVANCED_SECURITY) {
if (peer->advanced_security)
mnl_attr_put_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_ADVANCED_SECURITY, 0, NULL);
flags |= WGPEER_F_HAS_ADVANCED_SECURITY;
}
if (flags) {
if (!mnl_attr_put_u32_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_FLAGS, flags))
goto toobig_peers;
@ -389,6 +394,25 @@ static int parse_peer(const struct nlattr *attr, void *data)
if (!mnl_attr_validate(attr, MNL_TYPE_U64))
peer->tx_bytes = mnl_attr_get_u64(attr);
break;
case WGPEER_A_FLAGS:
if (!mnl_attr_validate(attr, MNL_TYPE_U32)) {
uint32_t flags = mnl_attr_get_u32(attr);
if (flags & WGPEER_F_HAS_ADVANCED_SECURITY && !(peer->flags & WGPEER_HAS_ADVANCED_SECURITY)) {
peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
peer->advanced_security = false;
}
}
break;
case WGPEER_A_ADVANCED_SECURITY:
if (!mnl_attr_validate(attr, MNL_TYPE_FLAG)) {
peer->advanced_security = true;
if (!(peer->flags & WGPEER_HAS_ADVANCED_SECURITY)) {
peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
}
}
break;
case WGPEER_A_ALLOWEDIPS:
return mnl_attr_parse_nested(attr, parse_allowedips, peer);
}

View file

@ -73,6 +73,10 @@ static int userspace_set_device(struct wgdevice *dev)
for_each_wgpeer(dev, peer) {
key_to_hex(hex, peer->public_key);
fprintf(f, "public_key=%s\n", hex);
if (peer->flags & WGPEER_HAS_ADVANCED_SECURITY) {
ret = -EINVAL;
goto out;
}
if (peer->flags & WGPEER_REMOVE_ME) {
fprintf(f, "remove=true\n");
continue;

View file

@ -18,7 +18,7 @@ int set_main(int argc, const char *argv[])
int ret = 1;
if (argc < 3) {
fprintf(stderr, "Usage: %s %s <interface> [listen-port <port>] [fwmark <mark>] [private-key <file path>] [peer <base64 public key> [remove] [preshared-key <file path>] [endpoint <ip>:<port>] [persistent-keepalive <interval seconds>] [allowed-ips <ip1>/<cidr1>[,<ip2>/<cidr2>]...] ]...\n", PROG_NAME, argv[0]);
fprintf(stderr, "Usage: %s %s <interface> [listen-port <port>] [fwmark <mark>] [private-key <file path>] [peer <base64 public key> [remove] [preshared-key <file path>] [endpoint <ip>:<port>] [persistent-keepalive <interval seconds>] [allowed-ips <ip1>/<cidr1>[,<ip2>/<cidr2>] [advanced-security <on|off>]...] ]...\n", PROG_NAME, argv[0]);
return 1;
}

View file

@ -73,6 +73,9 @@ int showconf_main(int argc, const char *argv[])
key_to_base64(base64, peer->preshared_key);
printf("PresharedKey = %s\n", base64);
}
if (peer->flags & WGPEER_HAS_ADVANCED_SECURITY) {
printf("AdvancedSecurity = %s\n", peer->advanced_security ? "on" : "off");
}
if (peer->first_allowedip)
printf("AllowedIPs = ");
for_each_wgallowedip(peer, allowedip) {

View file

@ -111,6 +111,9 @@
* most recent protocol will be used when
* this is unset. Otherwise, must be set
* to 1.
* WGPEER_A_ADVANCED_SECURITY: flag indicating that advanced security
* techniques provided by AmneziaWG should
* be used.
* 0: NLA_NESTED
* ...
* ...
@ -174,6 +177,7 @@ enum wgpeer_flag {
WGPEER_F_REMOVE_ME = 1U << 0,
WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1,
WGPEER_F_UPDATE_ONLY = 1U << 2,
WGPEER_F_HAS_ADVANCED_SECURITY = 1U << 3,
__WGPEER_F_ALL = WGPEER_F_REMOVE_ME | WGPEER_F_REPLACE_ALLOWEDIPS |
WGPEER_F_UPDATE_ONLY
};
@ -189,6 +193,7 @@ enum wgpeer_attribute {
WGPEER_A_TX_BYTES,
WGPEER_A_ALLOWEDIPS,
WGPEER_A_PROTOCOL_VERSION,
WGPEER_A_ADVANCED_SECURITY,
__WGPEER_A_LAST
};
#define WGPEER_A_MAX (__WGPEER_A_LAST - 1)