From b5b4c4b14babd84964e2f5af1b047ff427ef5230 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 1 Aug 2022 17:57:46 +0200 Subject: [PATCH] add support for loading signed network files Signed-off-by: Felix Fietkau --- examples/net0.bin | Bin 0 -> 909 bytes examples/net0.key | 1 + examples/net0.pub | 1 + examples/test-net0.sh | 7 +++-- main.c | 6 +++- network.c | 65 +++++++++++++++++++++++++++++++++++++++--- network.h | 6 ++++ unetd.h | 3 ++ 8 files changed, 82 insertions(+), 7 deletions(-) create mode 100644 examples/net0.bin create mode 100644 examples/net0.key create mode 100644 examples/net0.pub diff --git a/examples/net0.bin b/examples/net0.bin new file mode 100644 index 0000000000000000000000000000000000000000..4249d8517f6d56ea9ab1d7c7307bc2d6b5f37c5c GIT binary patch literal 909 zcmXT*OD$mlg1qOsjCwx%Q(Fob2#GJ=c=LX@L3wl3Yl&Xd7dzr+NLDBdO=$ai@k@^J z)Oo_(X8eUm|FKHHe6`7ysZOZx%mzOekQqtuxA2^QaFhM2N^JbDZ}Ku_FNJFM1eY9b zE{Hccwc}Of+F-dSAa&JToJz_0d1;yHN>&O$4yRHk{T@JJ(vA_^04+;plOLHp%11k#3GxKs>Dk=?<3QWyRl8j6w&!mPm?I zi^?*SQ{m|($4IxNG%qhT2kx1Y$^uZjQYx#+Nz8*rGfHBGL>i}3Zfb5)Y7sQRq3KOW cLCFCe_V92j1*Su!govUEp%mymu39bz01c7!asU7T literal 0 HcmV?d00001 diff --git a/examples/net0.key b/examples/net0.key new file mode 100644 index 0000000..745d15e --- /dev/null +++ b/examples/net0.key @@ -0,0 +1 @@ +EHCvNDZW7v+WjAeFT6EYXhIHm8exRdjnlz35hxefgWg= diff --git a/examples/net0.pub b/examples/net0.pub new file mode 100644 index 0000000..e458fbe --- /dev/null +++ b/examples/net0.pub @@ -0,0 +1 @@ +z+DZB9UkXV+69h8cdukSfLxTdMWDcF8wyrjqWa1THuQ= \ No newline at end of file diff --git a/examples/test-net0.sh b/examples/test-net0.sh index 06de301..1c5159d 100755 --- a/examples/test-net0.sh +++ b/examples/test-net0.sh @@ -4,9 +4,12 @@ host="${2:-ap1}" ip link add dev $ifname type wireguard > /dev/null 2>&1 -../unetd -d -h $PWD/hosts -N '{ +[ "$ifname" != "net0" ] && ln -sf net0.bin "${ifname}.bin" + +../unetd -D $PWD -d -h $PWD/hosts -N '{ "name": "'"$ifname"'", - "type": "file", + "type": "dynamic", + "auth_key": "'"$(cat ./net0.pub)"'", "key": "'"$(cat ./net0-${host}.key)"'", "file": "'"$PWD/net0.json"'", "tunnels": { diff --git a/main.c b/main.c index cd39843..6e1d765 100644 --- a/main.c +++ b/main.c @@ -17,6 +17,7 @@ struct cmdline_network { static struct cmdline_network *cmd_nets; static const char *hosts_file; const char *mssfix_path = UNETD_MSS_BPF_PATH; +const char *data_dir = UNETD_DATA_DIR; bool debug; static void @@ -97,8 +98,11 @@ int main(int argc, char **argv) struct cmdline_network *net; int ch; - while ((ch = getopt(argc, argv, "dh:M:N:")) != -1) { + while ((ch = getopt(argc, argv, "D:dh:M:N:")) != -1) { switch (ch) { + case 'D': + data_dir = optarg; + break; case 'd': debug = true; break; diff --git a/network.c b/network.c index e422954..3f598fa 100644 --- a/network.c +++ b/network.c @@ -44,6 +44,7 @@ static const struct blobmsg_policy netconf_policy[__NETCONF_ATTR_MAX] = { const struct blobmsg_policy network_policy[__NETWORK_ATTR_MAX] = { [NETWORK_ATTR_NAME] = { "name", BLOBMSG_TYPE_STRING }, [NETWORK_ATTR_TYPE] = { "type", BLOBMSG_TYPE_STRING }, + [NETWORK_ATTR_AUTH_KEY] = { "auth_key", BLOBMSG_TYPE_STRING }, [NETWORK_ATTR_KEY] = { "key", BLOBMSG_TYPE_STRING }, [NETWORK_ATTR_FILE] = { "file", BLOBMSG_TYPE_STRING }, [NETWORK_ATTR_DATA] = { "data", BLOBMSG_TYPE_TABLE }, @@ -117,6 +118,50 @@ static int network_load_file(struct network *net) return network_load_data(net, b.head); } +static int network_load_dynamic(struct network *net) +{ + const char *json = NULL; + char *fname = NULL; + struct stat st; + FILE *f = NULL; + int ret = -1; + + asprintf(&fname, "%s/%s.bin", data_dir, network_name(net)); + f = fopen(fname, "r"); + free(fname); + + if (!f) { + D_NET(net, "failed to open %s/%s.bin\n", data_dir, network_name(net)); + return -1; + } + + if (fstat(fileno(f), &st) < 0) + goto out; + + net->net_data_len = st.st_size; + net->net_data = realloc(net->net_data, net->net_data_len + 1); + memset(net->net_data + net->net_data_len, 0, 1); + if (fread(net->net_data, 1, net->net_data_len, f) != net->net_data_len || + unet_auth_data_validate(net->config.auth_key, net->net_data, + net->net_data_len, &json)) { + net->net_data_len = 0; + goto out; + } + + fclose(f); + blob_buf_init(&b, 0); + if (!blobmsg_add_json_from_string(&b, json)) { + net->net_data_len = 0; + return -1; + } + + return network_load_data(net, b.head); + +out: + fclose(f); + return ret; +} + static void network_fill_ip(struct blob_buf *buf, int af, union network_addr *addr, int mask) { @@ -309,6 +354,9 @@ static int network_reload(struct network *net) case NETWORK_TYPE_INLINE: ret = network_load_data(net, net->config.net_data); break; + case NETWORK_TYPE_DYNAMIC: + ret = network_load_dynamic(net); + break; } network_services_update_done(net); @@ -354,6 +402,7 @@ network_destroy(struct network *net) { network_teardown(net); avl_delete(&networks, &net->node); + free(net->net_data); free(net->config.data); free(net); } @@ -377,10 +426,10 @@ network_set_config(struct network *net, struct blob_attr *config) blobmsg_data(net->config.data), blobmsg_len(net->config.data)); - if ((cur = tb[NETWORK_ATTR_TYPE]) == NULL) - goto invalid; - - if (!strcmp(blobmsg_get_string(cur), "file")) + if ((cur = tb[NETWORK_ATTR_TYPE]) == NULL || + !strcmp(blobmsg_get_string(cur), "dynamic")) + net->config.type = NETWORK_TYPE_DYNAMIC; + else if (!strcmp(blobmsg_get_string(cur), "file")) net->config.type = NETWORK_TYPE_FILE; else if (!strcmp(blobmsg_get_string(cur), "inline")) net->config.type = NETWORK_TYPE_INLINE; @@ -404,6 +453,14 @@ network_set_config(struct network *net, struct blob_attr *config) if (!net->config.net_data) goto invalid; break; + case NETWORK_TYPE_DYNAMIC: + if ((cur = tb[NETWORK_ATTR_AUTH_KEY]) == NULL) + goto invalid; + + if (b64_decode(blobmsg_get_string(cur), net->config.auth_key, + sizeof(net->config.auth_key)) != sizeof(net->config.auth_key)) + goto invalid; + break; } if ((cur = tb[NETWORK_ATTR_INTERFACE]) != NULL) diff --git a/network.h b/network.h index ea52be3..81fe892 100644 --- a/network.h +++ b/network.h @@ -12,6 +12,7 @@ enum network_type { NETWORK_TYPE_FILE, NETWORK_TYPE_INLINE, + NETWORK_TYPE_DYNAMIC, }; struct wg_ops; @@ -29,6 +30,7 @@ struct network { int keepalive; uint8_t key[CURVE25519_KEY_SIZE]; uint8_t pubkey[CURVE25519_KEY_SIZE]; + uint8_t auth_key[CURVE25519_KEY_SIZE]; const char *file; const char *interface; const char *update_cmd; @@ -46,6 +48,9 @@ struct network { bool local_host_changed; } net_config; + void *net_data; + size_t net_data_len; + int ifindex; struct network_host *prev_local_host; struct avl_tree hosts; @@ -63,6 +68,7 @@ enum { NETWORK_ATTR_NAME, NETWORK_ATTR_TYPE, NETWORK_ATTR_KEY, + NETWORK_ATTR_AUTH_KEY, NETWORK_ATTR_FILE, NETWORK_ATTR_DATA, NETWORK_ATTR_INTERFACE, diff --git a/unetd.h b/unetd.h index 56d88c4..d4a816b 100644 --- a/unetd.h +++ b/unetd.h @@ -18,8 +18,10 @@ #include "host.h" #include "service.h" #include "ubus.h" +#include "auth-data.h" extern const char *mssfix_path; +extern const char *data_dir; extern bool debug; #define D(format, ...) \ @@ -34,6 +36,7 @@ extern bool debug; #define D_PEER(net, peer, format, ...) D_NET(net, "host %s " format, network_peer_name(peer), ##__VA_ARGS__) #define D_SERVICE(net, service, format, ...) D_NET(net, "service %s " format, network_service_name(service), ##__VA_ARGS__) +#define UNETD_DATA_DIR "/etc/unetd" #define UNETD_MSS_BPF_PATH "/lib/bpf/mss.o" #define UNETD_MSS_PRIO_BASE 0x130 -- 2.30.2