Provide a failsafe version of the path_info() function that doesn't
authorreyk <reyk@openbsd.org>
Wed, 13 Aug 2014 16:04:28 +0000 (16:04 +0000)
committerreyk <reyk@openbsd.org>
Wed, 13 Aug 2014 16:04:28 +0000 (16:04 +0000)
need a temporary path variable.  Based on an initial diff from
chrisz@.

"Commit any failsafe version and I'm ok with it" chrisz@

usr.sbin/httpd/httpd.c
usr.sbin/httpd/httpd.h
usr.sbin/httpd/server_fcgi.c

index d5ca6e4..4b631ec 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: httpd.c,v 1.18 2014/08/13 08:08:55 chrisz Exp $       */
+/*     $OpenBSD: httpd.c,v 1.19 2014/08/13 16:04:28 reyk Exp $ */
 
 /*
  * Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
@@ -580,28 +580,33 @@ canonicalize_path(const char *input, char *path, size_t len)
        return (path);
 }
 
-ssize_t
-path_info(char *name)
+size_t
+path_info(char *path)
 {
-       char            *p, *start, *end;
-       char             path[MAXPATHLEN];
+       char            *p, *start, *end, ch;
        struct stat      st;
-
-       if (strlcpy(path, name, sizeof(path)) >= sizeof(path))
-               return (-1);
+       int              ret;
 
        start = path;
        end = start + strlen(path);
 
-       for (p = end; p >= start; p--) {
-               if (*p != '/')
+       for (p = end; p > start; p--) {
+               /* Scan every path component from the end and at each '/' */
+               if (p < end && *p != '/')
                        continue;
-               if (stat(path, &st) == 0)
-                       break;
+
+               /* Temporarily cut the path component out */
+               ch = *p;
                *p = '\0';
+               ret = stat(path, &st);
+               *p = ch;
+
+               /* Break if the initial path component was found */
+               if (ret == 0)
+                       break;
        }
 
-       return (strlen(path));
+       return (p - start);
 }
 
 void
index 1a80428..371dd1c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: httpd.h,v 1.52 2014/08/08 18:29:42 reyk Exp $ */
+/*     $OpenBSD: httpd.h,v 1.53 2014/08/13 16:04:28 reyk Exp $ */
 
 /*
  * Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -537,7 +537,7 @@ void                 event_again(struct event *, int, short,
                    struct timeval *, struct timeval *, void *);
 const char     *canonicalize_host(const char *, char *, size_t);
 const char     *canonicalize_path(const char *, char *, size_t);
-ssize_t                 path_info(char *);
+size_t          path_info(char *);
 void            imsg_event_add(struct imsgev *);
 int             imsg_compose_event(struct imsgev *, u_int16_t, u_int32_t,
                    pid_t, int, void *, u_int16_t);
index e740883..d191ef2 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: server_fcgi.c,v 1.31 2014/08/11 15:26:33 deraadt Exp $        */
+/*     $OpenBSD: server_fcgi.c,v 1.32 2014/08/13 16:04:28 reyk Exp $   */
 
 /*
  * Copyright (c) 2014 Florian Obser <florian@openbsd.org>
@@ -100,7 +100,7 @@ server_fcgi(struct httpd *env, struct client *clt)
        struct fcgi_record_header       *h;
        struct fcgi_begin_request_body  *begin;
        char                             hbuf[MAXHOSTNAMELEN];
-       ssize_t                          scriptlen;
+       ssize_t                          scriptlen, pathlen;
        int                              fd = -1, ret;
        const char                      *errstr = NULL;
        char                            *str, *p, *script = NULL;
@@ -191,15 +191,14 @@ server_fcgi(struct httpd *env, struct client *clt)
        h->type = FCGI_PARAMS;
        h->content_len = param.total_len = 0;
 
-       if (asprintf(&script, "%s%s", srv_conf->root,
+       if ((pathlen = (ssize_t)asprintf(&script, "%s%s", srv_conf->root,
            desc->http_path_alias != NULL ?
-           desc->http_path_alias : desc->http_path) == -1 ||
-           (scriptlen = path_info(script)) == -1) {
+           desc->http_path_alias : desc->http_path)) == -1) {
                errstr = "failed to get script name";
                goto fail;
        }
 
-       if (scriptlen) {
+       if ((scriptlen = path_info(script)) < pathlen) {
                if (fcgi_add_param(&param, "PATH_INFO",
                    script + scriptlen, clt) == -1) {
                        errstr = "failed to encode param";