mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
Merge pull request #12223 from yuwata/network-wireguard-preshared-key-file
network: add PresharedKeyFile= setting and make reading key file failure fatal
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "missing.h"
|
||||
@@ -264,26 +265,29 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int read_full_stream(
|
||||
int read_full_stream_full(
|
||||
FILE *f,
|
||||
const char *filename,
|
||||
ReadFullFileFlags flags,
|
||||
char **ret_contents,
|
||||
size_t *ret_size) {
|
||||
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
struct stat st;
|
||||
size_t n, l;
|
||||
int fd;
|
||||
size_t n, n_next, l;
|
||||
int fd, r;
|
||||
|
||||
assert(f);
|
||||
assert(ret_contents);
|
||||
assert(!(flags & READ_FULL_FILE_UNBASE64) || ret_size);
|
||||
|
||||
n = LINE_MAX; /* Start size */
|
||||
n_next = LINE_MAX; /* Start size */
|
||||
|
||||
fd = fileno(f);
|
||||
if (fd >= 0) { /* If the FILE* object is backed by an fd (as opposed to memory or such, see fmemopen(), let's
|
||||
* optimize our buffering) */
|
||||
|
||||
if (fstat(fileno(f), &st) < 0)
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (S_ISREG(st.st_mode)) {
|
||||
@@ -296,27 +300,44 @@ int read_full_stream(
|
||||
* size of 0. Note that we increase the size to read here by one, so that the first read attempt
|
||||
* already makes us notice the EOF. */
|
||||
if (st.st_size > 0)
|
||||
n = st.st_size + 1;
|
||||
n_next = st.st_size + 1;
|
||||
|
||||
if (flags & READ_FULL_FILE_SECURE)
|
||||
(void) warn_file_is_world_accessible(filename, &st, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
l = 0;
|
||||
n = l = 0;
|
||||
for (;;) {
|
||||
char *t;
|
||||
size_t k;
|
||||
|
||||
t = realloc(buf, n + 1);
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
if (flags & READ_FULL_FILE_SECURE) {
|
||||
t = malloc(n_next + 1);
|
||||
if (!t) {
|
||||
r = -ENOMEM;
|
||||
goto finalize;
|
||||
}
|
||||
memcpy_safe(t, buf, n);
|
||||
explicit_bzero_safe(buf, n);
|
||||
} else {
|
||||
t = realloc(buf, n_next + 1);
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
buf = t;
|
||||
n = n_next;
|
||||
|
||||
errno = 0;
|
||||
k = fread(buf + l, 1, n - l, f);
|
||||
if (k > 0)
|
||||
l += k;
|
||||
|
||||
if (ferror(f))
|
||||
return errno > 0 ? -errno : -EIO;
|
||||
if (ferror(f)) {
|
||||
r = errno > 0 ? -errno : -EIO;
|
||||
goto finalize;
|
||||
}
|
||||
|
||||
if (feof(f))
|
||||
break;
|
||||
@@ -327,10 +348,18 @@ int read_full_stream(
|
||||
assert(l == n);
|
||||
|
||||
/* Safety check */
|
||||
if (n >= READ_FULL_BYTES_MAX)
|
||||
return -E2BIG;
|
||||
if (n >= READ_FULL_BYTES_MAX) {
|
||||
r = -E2BIG;
|
||||
goto finalize;
|
||||
}
|
||||
|
||||
n = MIN(n * 2, READ_FULL_BYTES_MAX);
|
||||
n_next = MIN(n * 2, READ_FULL_BYTES_MAX);
|
||||
}
|
||||
|
||||
if (flags & READ_FULL_FILE_UNBASE64) {
|
||||
buf[l++] = 0;
|
||||
r = unbase64mem_full(buf, l, flags & READ_FULL_FILE_SECURE, (void **) ret_contents, ret_size);
|
||||
goto finalize;
|
||||
}
|
||||
|
||||
if (!ret_size) {
|
||||
@@ -338,8 +367,10 @@ int read_full_stream(
|
||||
* trailing NUL byte. But if there's an embedded NUL byte, then we should refuse operation as otherwise
|
||||
* there'd be ambiguity about what we just read. */
|
||||
|
||||
if (memchr(buf, 0, l))
|
||||
return -EBADMSG;
|
||||
if (memchr(buf, 0, l)) {
|
||||
r = -EBADMSG;
|
||||
goto finalize;
|
||||
}
|
||||
}
|
||||
|
||||
buf[l] = 0;
|
||||
@@ -349,21 +380,27 @@ int read_full_stream(
|
||||
*ret_size = l;
|
||||
|
||||
return 0;
|
||||
|
||||
finalize:
|
||||
if (flags & READ_FULL_FILE_SECURE)
|
||||
explicit_bzero_safe(buf, n);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int read_full_file(const char *fn, char **contents, size_t *size) {
|
||||
int read_full_file_full(const char *filename, ReadFullFileFlags flags, char **contents, size_t *size) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
|
||||
assert(fn);
|
||||
assert(filename);
|
||||
assert(contents);
|
||||
|
||||
f = fopen(fn, "re");
|
||||
f = fopen(filename, "re");
|
||||
if (!f)
|
||||
return -errno;
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
|
||||
return read_full_stream(f, contents, size);
|
||||
return read_full_stream_full(f, filename, flags, contents, size);
|
||||
}
|
||||
|
||||
int executable_is_script(const char *path, char **interpreter) {
|
||||
@@ -818,3 +855,28 @@ int safe_fgetc(FILE *f, char *ret) {
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int warn_file_is_world_accessible(const char *filename, struct stat *st, const char *unit, unsigned line) {
|
||||
struct stat _st;
|
||||
|
||||
if (!filename)
|
||||
return 0;
|
||||
|
||||
if (!st) {
|
||||
if (stat(filename, &_st) < 0)
|
||||
return -errno;
|
||||
st = &_st;
|
||||
}
|
||||
|
||||
if ((st->st_mode & S_IRWXO) == 0)
|
||||
return 0;
|
||||
|
||||
if (unit)
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"%s has %04o mode that is too permissive, please adjust the access mode.",
|
||||
filename, st->st_mode & 07777);
|
||||
else
|
||||
log_warning("%s has %04o mode that is too permissive, please adjust the access mode.",
|
||||
filename, st->st_mode & 07777);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "macro.h"
|
||||
@@ -27,6 +28,11 @@ typedef enum {
|
||||
|
||||
} WriteStringFileFlags;
|
||||
|
||||
typedef enum {
|
||||
READ_FULL_FILE_SECURE = 1 << 0,
|
||||
READ_FULL_FILE_UNBASE64 = 1 << 1,
|
||||
} ReadFullFileFlags;
|
||||
|
||||
int write_string_stream_ts(FILE *f, const char *line, WriteStringFileFlags flags, struct timespec *ts);
|
||||
static inline int write_string_stream(FILE *f, const char *line, WriteStringFileFlags flags) {
|
||||
return write_string_stream_ts(f, line, flags, NULL);
|
||||
@@ -38,9 +44,15 @@ static inline int write_string_file(const char *fn, const char *line, WriteStrin
|
||||
|
||||
int write_string_filef(const char *fn, WriteStringFileFlags flags, const char *format, ...) _printf_(3, 4);
|
||||
|
||||
int read_one_line_file(const char *fn, char **line);
|
||||
int read_full_file(const char *fn, char **contents, size_t *size);
|
||||
int read_full_stream(FILE *f, char **contents, size_t *size);
|
||||
int read_one_line_file(const char *filename, char **line);
|
||||
int read_full_file_full(const char *filename, ReadFullFileFlags flags, char **contents, size_t *size);
|
||||
static inline int read_full_file(const char *filename, char **contents, size_t *size) {
|
||||
return read_full_file_full(filename, 0, contents, size);
|
||||
}
|
||||
int read_full_stream_full(FILE *f, const char *filename, ReadFullFileFlags flags, char **contents, size_t *size);
|
||||
static inline int read_full_stream(FILE *f, char **contents, size_t *size) {
|
||||
return read_full_stream_full(f, NULL, 0, contents, size);
|
||||
}
|
||||
|
||||
int verify_file(const char *fn, const char *blob, bool accept_extra_nl);
|
||||
|
||||
@@ -76,3 +88,5 @@ static inline int read_nul_string(FILE *f, size_t limit, char **ret) {
|
||||
}
|
||||
|
||||
int safe_fgetc(FILE *f, char *ret);
|
||||
|
||||
int warn_file_is_world_accessible(const char *filename, struct stat *st, const char *unit, unsigned line);
|
||||
|
||||
@@ -685,11 +685,12 @@ static int unbase64_next(const char **p, size_t *l) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) {
|
||||
int unbase64mem_full(const char *p, size_t l, bool secure, void **ret, size_t *ret_size) {
|
||||
_cleanup_free_ uint8_t *buf = NULL;
|
||||
const char *x;
|
||||
uint8_t *z;
|
||||
size_t len;
|
||||
int r;
|
||||
|
||||
assert(p || l == 0);
|
||||
assert(ret);
|
||||
@@ -712,36 +713,54 @@ int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) {
|
||||
a = unbase64_next(&x, &l);
|
||||
if (a == -EPIPE) /* End of string */
|
||||
break;
|
||||
if (a < 0)
|
||||
return a;
|
||||
if (a == INT_MAX) /* Padding is not allowed at the beginning of a 4ch block */
|
||||
return -EINVAL;
|
||||
if (a < 0) {
|
||||
r = a;
|
||||
goto on_failure;
|
||||
}
|
||||
if (a == INT_MAX) { /* Padding is not allowed at the beginning of a 4ch block */
|
||||
r = -EINVAL;
|
||||
goto on_failure;
|
||||
}
|
||||
|
||||
b = unbase64_next(&x, &l);
|
||||
if (b < 0)
|
||||
return b;
|
||||
if (b == INT_MAX) /* Padding is not allowed at the second character of a 4ch block either */
|
||||
return -EINVAL;
|
||||
if (b < 0) {
|
||||
r = b;
|
||||
goto on_failure;
|
||||
}
|
||||
if (b == INT_MAX) { /* Padding is not allowed at the second character of a 4ch block either */
|
||||
r = -EINVAL;
|
||||
goto on_failure;
|
||||
}
|
||||
|
||||
c = unbase64_next(&x, &l);
|
||||
if (c < 0)
|
||||
return c;
|
||||
if (c < 0) {
|
||||
r = c;
|
||||
goto on_failure;
|
||||
}
|
||||
|
||||
d = unbase64_next(&x, &l);
|
||||
if (d < 0)
|
||||
return d;
|
||||
if (d < 0) {
|
||||
r = d;
|
||||
goto on_failure;
|
||||
}
|
||||
|
||||
if (c == INT_MAX) { /* Padding at the third character */
|
||||
|
||||
if (d != INT_MAX) /* If the third character is padding, the fourth must be too */
|
||||
return -EINVAL;
|
||||
if (d != INT_MAX) { /* If the third character is padding, the fourth must be too */
|
||||
r = -EINVAL;
|
||||
goto on_failure;
|
||||
}
|
||||
|
||||
/* b == 00YY0000 */
|
||||
if (b & 15)
|
||||
return -EINVAL;
|
||||
if (b & 15) {
|
||||
r = -EINVAL;
|
||||
goto on_failure;
|
||||
}
|
||||
|
||||
if (l > 0) /* Trailing rubbish? */
|
||||
return -ENAMETOOLONG;
|
||||
if (l > 0) { /* Trailing rubbish? */
|
||||
r = -ENAMETOOLONG;
|
||||
goto on_failure;
|
||||
}
|
||||
|
||||
*(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */
|
||||
break;
|
||||
@@ -749,11 +768,15 @@ int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) {
|
||||
|
||||
if (d == INT_MAX) {
|
||||
/* c == 00ZZZZ00 */
|
||||
if (c & 3)
|
||||
return -EINVAL;
|
||||
if (c & 3) {
|
||||
r = -EINVAL;
|
||||
goto on_failure;
|
||||
}
|
||||
|
||||
if (l > 0) /* Trailing rubbish? */
|
||||
return -ENAMETOOLONG;
|
||||
if (l > 0) { /* Trailing rubbish? */
|
||||
r = -ENAMETOOLONG;
|
||||
goto on_failure;
|
||||
}
|
||||
|
||||
*(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
|
||||
*(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
|
||||
@@ -771,6 +794,12 @@ int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) {
|
||||
*ret = TAKE_PTR(buf);
|
||||
|
||||
return 0;
|
||||
|
||||
on_failure:
|
||||
if (secure)
|
||||
explicit_bzero_safe(buf, len);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void hexdump(FILE *f, const void *p, size_t s) {
|
||||
|
||||
@@ -33,6 +33,9 @@ ssize_t base64mem(const void *p, size_t l, char **out);
|
||||
int base64_append(char **prefix, int plen,
|
||||
const void *p, size_t l,
|
||||
int margin, int width);
|
||||
int unbase64mem(const char *p, size_t l, void **mem, size_t *len);
|
||||
int unbase64mem_full(const char *p, size_t l, bool secure, void **mem, size_t *len);
|
||||
static inline int unbase64mem(const char *p, size_t l, void **mem, size_t *len) {
|
||||
return unbase64mem_full(p, l, false, mem, len);
|
||||
}
|
||||
|
||||
void hexdump(FILE *f, const void *p, size_t s);
|
||||
|
||||
Reference in New Issue
Block a user