Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/libexec/httpd avoid truncating a directory path when using s...



details:   https://anonhg.NetBSD.org/src/rev/0a4bba5da08d
branches:  trunk
changeset: 330426:0a4bba5da08d
user:      mrg <mrg%NetBSD.org@localhost>
date:      Tue Jul 08 14:01:21 2014 +0000

description:
avoid truncating a directory path when using snprintf(), but instead
detect and return an error.

found and fixed by shm@netbsd.

diffstat:

 libexec/httpd/CHANGES     |   2 +
 libexec/httpd/auth-bozo.c |   8 +++++-
 libexec/httpd/bozohttpd.c |  49 +++++++++++++++++++++++++++++++++++++---------
 3 files changed, 47 insertions(+), 12 deletions(-)

diffs (138 lines):

diff -r d16f96ae0828 -r 0a4bba5da08d libexec/httpd/CHANGES
--- a/libexec/httpd/CHANGES     Tue Jul 08 13:59:39 2014 +0000
+++ b/libexec/httpd/CHANGES     Tue Jul 08 14:01:21 2014 +0000
@@ -3,6 +3,8 @@
 changes in bozohttpd 20140201:
        o  support .svg files
        o  fix a core dump when requests timeout
+       o  fix a security issue in basic HTTP authentication which would allow
+          authentication to be bypassed, from shm%netbsd.org@localhost
 
 changes in bozohttpd 20140102:
        o  update a few content types
diff -r d16f96ae0828 -r 0a4bba5da08d libexec/httpd/auth-bozo.c
--- a/libexec/httpd/auth-bozo.c Tue Jul 08 13:59:39 2014 +0000
+++ b/libexec/httpd/auth-bozo.c Tue Jul 08 14:01:21 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: auth-bozo.c,v 1.12 2014/01/02 08:21:38 mrg Exp $       */
+/*     $NetBSD: auth-bozo.c,v 1.13 2014/07/08 14:01:21 mrg Exp $       */
 
 /*     $eterna: auth-bozo.c,v 1.17 2011/11/18 09:21:15 mrg Exp $       */
 
@@ -74,7 +74,11 @@
        }
        request->hr_authrealm = bozostrdup(httpd, dir);
 
-       snprintf(authfile, sizeof(authfile), "%s/%s", dir, AUTH_FILE);
+       if ((size_t)snprintf(authfile, sizeof(authfile), "%s/%s", dir, AUTH_FILE) >= 
+         sizeof(authfile)) {
+               return bozo_http_error(httpd, 404, request,
+                       "authfile path too long");
+       }
        if (stat(authfile, &sb) < 0) {
                debug((httpd, DEBUG_NORMAL,
                    "bozo_auth_check realm `%s' dir `%s' authfile `%s' missing",
diff -r d16f96ae0828 -r 0a4bba5da08d libexec/httpd/bozohttpd.c
--- a/libexec/httpd/bozohttpd.c Tue Jul 08 13:59:39 2014 +0000
+++ b/libexec/httpd/bozohttpd.c Tue Jul 08 14:01:21 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bozohttpd.c,v 1.52 2014/07/02 13:58:09 shm Exp $       */
+/*     $NetBSD: bozohttpd.c,v 1.53 2014/07/08 14:01:21 mrg Exp $       */
 
 /*     $eterna: bozohttpd.c,v 1.178 2011/11/18 09:21:15 mrg Exp $      */
 
@@ -935,7 +935,12 @@
                bozo_check_special_files(request, basename);
        }
 
-       snprintf(dirfile, sizeof(dirfile), "%s/%s", dir, DIRECT_ACCESS_FILE);
+       if ((size_t)snprintf(dirfile, sizeof(dirfile), "%s/%s", dir,
+         DIRECT_ACCESS_FILE) >= sizeof(dirfile)) {
+               bozo_http_error(request->hr_httpd, 404, request,
+                 "directfile path too long");
+               return 0;
+       }
        if (stat(dirfile, &sb) < 0 ||
            (fp = fopen(dirfile, "r")) == NULL)
                return 0;
@@ -1127,7 +1132,7 @@
 /*
  * checks to see if this request has a valid .bzredirect file.  returns
  * 0 when no redirection happend, or 1 when handle_redirect() has been
- * called.
+ * called, -1 on error.
  */
 static int
 check_bzredirect(bozo_httpreq_t *request)
@@ -1142,7 +1147,12 @@
         * if this pathname is really a directory, but doesn't end in /,
         * use it as the directory to look for the redir file.
         */
-       snprintf(dir, sizeof(dir), "%s", request->hr_file + 1);
+       if((size_t)snprintf(dir, sizeof(dir), "%s", request->hr_file + 1) >=
+         sizeof(dir)) {
+               bozo_http_error(request->hr_httpd, 404, request,
+                 "file path too long");
+               return -1;
+       }
        debug((request->hr_httpd, DEBUG_FAT, "check_bzredirect: dir %s", dir));
        basename = strrchr(dir, '/');
 
@@ -1156,13 +1166,23 @@
                bozo_check_special_files(request, basename);
        }
 
-       snprintf(redir, sizeof(redir), "%s/%s", dir, REDIRECT_FILE);
+       if ((size_t)snprintf(redir, sizeof(redir), "%s/%s", dir,
+         REDIRECT_FILE) >= sizeof(redir)) {
+               bozo_http_error(request->hr_httpd, 404, request,
+                 "redirectfile path too long");
+               return -1;
+       }
        if (lstat(redir, &sb) == 0) {
                if (!S_ISLNK(sb.st_mode))
                        return 0;
                absolute = 0;
        } else {
-               snprintf(redir, sizeof(redir), "%s/%s", dir, ABSREDIRECT_FILE);
+               if((size_t)snprintf(redir, sizeof(redir), "%s/%s", dir,
+                 ABSREDIRECT_FILE) >= sizeof(redir)) {
+                       bozo_http_error(request->hr_httpd, 404, request,
+                         "redirectfile path too long");
+                       return -1;
+               }
                if (lstat(redir, &sb) < 0 || !S_ISLNK(sb.st_mode))
                        return 0;
                absolute = 1;
@@ -1186,9 +1206,14 @@
        /* now we have the link pointer, redirect to the real place */
        if (absolute)
                finalredir = redirpath;
-       else
-               snprintf(finalredir = redir, sizeof(redir), "/%s/%s", dir,
-                        redirpath);
+       else {
+               if ((size_t)snprintf(finalredir = redir, sizeof(redir), "/%s/%s",
+                 dir, redirpath) >= sizeof(redir)) {
+                       bozo_http_error(request->hr_httpd, 404, request,
+                         "redirect path too long");
+                       return -1;
+               }
+       }
 
        debug((request->hr_httpd, DEBUG_FAT,
               "check_bzredirect: new redir %s", finalredir));
@@ -1307,8 +1332,12 @@
                goto bad_done;
        }
 
-       if (check_bzredirect(request))
+       switch(check_bzredirect(request)) {
+       case -1:
+               goto bad_done;
+       case 1:
                return 0;
+       }
 
        if (httpd->untrustedref) {
                int to_indexhtml = 0;



Home | Main Index | Thread Index | Old Index