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