diff options
author | June McEnroe <june@causal.agency> | 2022-04-20 18:29:28 -0400 |
---|---|---|
committer | June McEnroe <june@causal.agency> | 2022-04-20 18:29:28 -0400 |
commit | 1b8be724bc5f3cc18da770e01174719ec4890791 (patch) | |
tree | 79cbb0ba57f3bf265c587089aca902f786e73639 | |
parent | Add screenshot to README (diff) | |
download | catgirl-1b8be724bc5f3cc18da770e01174719ec4890791.tar.gz catgirl-1b8be724bc5f3cc18da770e01174719ec4890791.zip |
Sanitize leading dots from log path components
Prevent directory traversal by sanitizing leading dots as well as slashes from log path components, which can be controlled by the server. Side effect of preventing hidden dotfiles is a bonus, I think. Also check that the full path actually fits in the buffer. Reported-by: Samanta Navarro <ferivoz@riseup.net>
Diffstat (limited to '')
-rw-r--r-- | log.c | 30 |
1 files changed, 19 insertions, 11 deletions
diff --git a/log.c b/log.c index 32d771f..d2f937f 100644 --- a/log.c +++ b/log.c @@ -73,6 +73,15 @@ static void logMkdir(const char *path) { if (error && errno != EEXIST) err(EX_CANTCREAT, "log/%s", path); } +static void sanitize(char *ptr, char *end) { + for (char *ch = ptr; ch < end && *ch == '.'; ++ch) { + *ch = '_'; + } + for (char *ch = ptr; ch < end; ++ch) { + if (*ch == '/') *ch = '_'; + } +} + static struct { int year; int month; @@ -97,22 +106,21 @@ static FILE *logFile(uint id, const struct tm *tm) { logs[id].month = tm->tm_mon; logs[id].day = tm->tm_mday; - size_t len = 0; char path[PATH_MAX]; - for (const char *ch = network.name; *ch; ++ch) { - path[len++] = (*ch == '/' ? '_' : *ch); - } - path[len] = '\0'; + char *ptr = path, *end = &path[sizeof(path)]; + + ptr = seprintf(ptr, end, "%s", network.name); + sanitize(path, ptr); logMkdir(path); - path[len++] = '/'; - for (const char *ch = idNames[id]; *ch; ++ch) { - path[len++] = (*ch == '/' ? '_' : *ch); - } - path[len] = '\0'; + char *name = ptr; + ptr = seprintf(ptr, end, "/%s", idNames[id]); + sanitize(&name[1], ptr); logMkdir(path); - strftime(&path[len], sizeof(path) - len, "/%F.log", tm); + size_t len = strftime(ptr, end - ptr, "/%F.log", tm); + if (!len) errx(EX_CANTCREAT, "log path too long"); + int fd = openat( logDir, path, O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC, |