From 4bdc9a6325c8113ca11d107ef875371ad8363ade Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Mon, 22 Sep 2014 15:20:01 +0200 Subject: Fix possible buffer overruns in path handling * Implement safe uh_realpath() wrapper * Fix possible buffer overrun in canonpath() * Fix possible buffer overrun in uh_path_lookup() Signed-off-by: Jo-Philipp Wich --- uhttpd-utils.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) (limited to 'uhttpd-utils.c') diff --git a/uhttpd-utils.c b/uhttpd-utils.c index ad8813e..e4ac26c 100644 --- a/uhttpd-utils.c +++ b/uhttpd-utils.c @@ -483,13 +483,12 @@ static char * canonpath(const char *path, char *path_resolved) /* relative -> absolute */ if (*path != '/') { - getcwd(path_copy, PATH_MAX); - strncat(path_copy, "/", PATH_MAX - strlen(path_copy)); - strncat(path_copy, path, PATH_MAX - strlen(path_copy)); + getcwd(path_copy, sizeof(path_copy)); + snprintf(path_copy, sizeof(path_copy) - strlen(path_copy), "/%s", path); } else { - strncpy(path_copy, path, PATH_MAX); + strncpy(path_copy, path, sizeof(path_copy) - 1); } /* normalize */ @@ -545,6 +544,28 @@ static char * canonpath(const char *path, char *path_resolved) return NULL; } +char * uh_realpath(const char *path, char *resolved_path) +{ + char *res = realpath(path, NULL); + + if (res && strlen(res) >= PATH_MAX) + { + free(res); + errno = ENAMETOOLONG; + + return NULL; + } + else if (res) + { + strncpy(resolved_path, res, PATH_MAX - 1); + free(res); + + return resolved_path; + } + + return NULL; +} + struct index_file *uh_index_files = NULL; @@ -632,7 +653,7 @@ struct path_info * uh_path_lookup(struct client *cl, const char *url) memset(path_info, 0, sizeof(path_info)); memcpy(path_info, buffer, min(i + 1, sizeof(path_info) - 1)); - if (no_sym ? realpath(path_info, path_phys) + if (no_sym ? uh_realpath(path_info, path_phys) : canonpath(path_info, path_phys)) { memset(path_info, 0, sizeof(path_info)); @@ -673,7 +694,7 @@ struct path_info * uh_path_lookup(struct client *cl, const char *url) /* try to locate index file */ memset(buffer, 0, sizeof(buffer)); - memcpy(buffer, path_phys, sizeof(buffer)); + memcpy(buffer, path_phys, sizeof(buffer) - 1); pathptr = &buffer[strlen(buffer)]; /* if requested url resolves to a directory and a trailing slash @@ -696,7 +717,7 @@ struct path_info * uh_path_lookup(struct client *cl, const char *url) { for (idx = uh_index_files; idx; idx = idx->next) { - strncat(buffer, idx->name, sizeof(buffer)); + strncpy(pathptr, idx->name, sizeof(buffer) - (pathptr - buffer) - 1); if (!stat(buffer, &s) && (s.st_mode & S_IFREG)) { -- cgit v1.2.1