diff options
author | Tyson Andre <tysonandre775@hotmail.com> | 2021-07-22 10:17:17 -0400 |
---|---|---|
committer | dormando <dormando@rydia.net> | 2021-07-25 14:54:42 -0700 |
commit | ddee3e27a031be22f5f28c160be18fd3cb9bc63d (patch) | |
tree | c58b9b22603b1e4b4ab19644ac8956bd2914201d /authfile.c | |
parent | 56a0ba62baab4f9acb8606a8754815a4cacf24b7 (diff) | |
download | memcached-ddee3e27a031be22f5f28c160be18fd3cb9bc63d.tar.gz |
Fix minor severity heap buffer overflow reading `--auth-file`1.6.10
Fixes #805
Allocate an extra byte for reading the last entry when there is no `\n` at
the end of the file.
Also, check if the user contains null bytes when reading the last entry.
Unrelatedly, add handling in case the auth file size changes while it is being read.
Diffstat (limited to 'authfile.c')
-rw-r--r-- | authfile.c | 22 |
1 files changed, 14 insertions, 8 deletions
@@ -41,23 +41,29 @@ enum authfile_ret authfile_load(const char *file) { return AUTHFILE_STATFAIL; } - auth_data = calloc(1, sb.st_size); + auth_data = calloc(1, sb.st_size + 1); char *auth_cur = auth_data; + char *auth_end = auth_data + sb.st_size; auth_t *entry_cur = auth_entries; int used = 0; - while ((fgets(auth_cur, MAX_ENTRY_LEN, pwfile)) != NULL) { + while ((fgets(auth_cur, auth_end - auth_cur < MAX_ENTRY_LEN ? auth_end - auth_cur : MAX_ENTRY_LEN, pwfile)) != NULL) { int x; int found = 0; for (x = 0; x < MAX_ENTRY_LEN; x++) { - if (!found && auth_cur[x] == ':') { - entry_cur->user = auth_cur; - entry_cur->ulen = x; - entry_cur->pass = &auth_cur[x+1]; - found = 1; - } else if (found) { + if (!found) { + if (auth_cur[x] == '\0') { + // The username is malformed - this is either the end of the file or a null byte. + break; + } else if (auth_cur[x] == ':') { + entry_cur->user = auth_cur; + entry_cur->ulen = x; + entry_cur->pass = &auth_cur[x+1]; + found = 1; + } + } else { // Find end of password. if (auth_cur[x] == '\n' || auth_cur[x] == '\r' || |