wg: stricter key file reading

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2017-05-12 15:03:38 +02:00
parent fabb6eca2b
commit 067ebe2cb9

View file

@ -424,32 +424,48 @@ err:
return false; return false;
} }
static int read_line(char **dst, const char *path) static int read_keyfile(char dst[WG_KEY_LEN_BASE64], const char *path)
{ {
FILE *f; FILE *f;
size_t n = 0; int ret = -1, c;
*dst = NULL;
f = fopen(path, "r"); f = fopen(path, "r");
if (!f) { if (!f) {
perror("fopen"); perror("fopen");
return -1; return -1;
} }
if (getline(dst, &n, f) < 0 && errno) {
perror("getline"); if (fread(dst, WG_KEY_LEN_BASE64 - 1, 1, f) != 1) {
fclose(f); if (errno) {
return -1; perror("fread");
goto out;
} }
fclose(f); /* If we're at the end and we didn't read anything, we're /dev/null. */
n = strlen(*dst); if (!ferror(f) && feof(f) && !ftell(f)) {
if (!n) ret = 1;
return 1; goto out;
while (--n) {
if (isspace((*dst)[n]))
(*dst)[n] = '\0';
} }
return 0;
fprintf(stderr, "Invalid length key in key file\n");
goto out;
}
dst[WG_KEY_LEN_BASE64 - 1] = '\0';
while ((c = getc(f)) != EOF) {
if (!isspace(c)) {
fprintf(stderr, "Found trailing character in key file: `%c`\n", c);
goto out;
}
}
if (ferror(f) && errno) {
perror("getc");
goto out;
}
ret = 0;
out:
fclose(f);
return ret;
} }
static char *strip_spaces(const char *in) static char *strip_spaces(const char *in)
@ -492,14 +508,11 @@ bool config_read_cmd(struct wgdevice **device, char *argv[], int argc)
argv += 2; argv += 2;
argc -= 2; argc -= 2;
} else if (!strcmp(argv[0], "private-key") && argc >= 2 && !buf.dev->num_peers) { } else if (!strcmp(argv[0], "private-key") && argc >= 2 && !buf.dev->num_peers) {
char *line; char key_line[WG_KEY_LEN_BASE64];
int ret = read_line(&line, argv[1]); int ret = read_keyfile(key_line, argv[1]);
if (ret == 0) { if (ret == 0) {
if (!parse_key(buf.dev->private_key, line)) { if (!parse_key(buf.dev->private_key, key_line))
free(line);
goto error; goto error;
}
free(line);
} else if (ret == 1) } else if (ret == 1)
buf.dev->flags |= WGDEVICE_REMOVE_PRIVATE_KEY; buf.dev->flags |= WGDEVICE_REMOVE_PRIVATE_KEY;
else else
@ -544,18 +557,14 @@ bool config_read_cmd(struct wgdevice **device, char *argv[], int argc)
argv += 2; argv += 2;
argc -= 2; argc -= 2;
} else if (!strcmp(argv[0], "preshared-key") && argc >= 2 && buf.dev->num_peers) { } else if (!strcmp(argv[0], "preshared-key") && argc >= 2 && buf.dev->num_peers) {
char *line; char key_line[WG_KEY_LEN_BASE64];
int ret = read_line(&line, argv[1]); int ret = read_keyfile(key_line, argv[1]);
if (ret == 0) { if (ret == 0) {
if (!parse_key(peer_from_offset(buf.dev, peer_offset)->preshared_key, line)) { if (!parse_key(peer_from_offset(buf.dev, peer_offset)->preshared_key, key_line))
free(line);
goto error; goto error;
} } else if (ret == 1)
free(line);
} else if (ret == 1) {
free(line);
buf.dev->flags |= WGPEER_REMOVE_PRESHARED_KEY; buf.dev->flags |= WGPEER_REMOVE_PRESHARED_KEY;
} else else
goto error; goto error;
argv += 2; argv += 2;
argc -= 2; argc -= 2;