[BACK]Return to cgi-bozo.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / libexec / httpd

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/libexec/httpd/cgi-bozo.c between version 1.20.2.4 and 1.21

version 1.20.2.4, 2017/03/07 07:25:18 version 1.21, 2013/06/27 10:01:31
Line 3 
Line 3 
 /*      $eterna: cgi-bozo.c,v 1.40 2011/11/18 09:21:15 mrg Exp $        */  /*      $eterna: cgi-bozo.c,v 1.40 2011/11/18 09:21:15 mrg Exp $        */
   
 /*  /*
  * Copyright (c) 1997-2017 Matthew R. Green   * Copyright (c) 1997-2011 Matthew R. Green
  * All rights reserved.   * All rights reserved.
  *   *
  * Redistribution and use in source and binary forms, with or without   * Redistribution and use in source and binary forms, with or without
Line 75  content_cgihandler(bozohttpd_t *httpd, b
Line 75  content_cgihandler(bozohttpd_t *httpd, b
 }  }
   
 static int  static int
 parse_header(bozo_httpreq_t *request, const char *str, ssize_t len,  parse_header(bozohttpd_t *httpd, const char *str, ssize_t len, char **hdr_str,
              char **hdr_str, char **hdr_val)                  char **hdr_val)
 {  {
         struct  bozohttpd_t *httpd = request->hr_httpd;  
         char    *name, *value;          char    *name, *value;
   
         /* if the string passed is zero-length bail out */          /* if the string passed is zero-length bail out */
         if (*str == '\0')          if (*str == '\0')
                 return -1;                  return -1;
   
         value = bozostrdup(httpd, request, str);          value = bozostrdup(httpd, str);
   
         /* locate the ':' separator in the header/value */          /* locate the ':' separator in the header/value */
         name = bozostrnsep(&value, ":", &len);          name = bozostrnsep(&value, ":", &len);
   
         if (NULL == name || -1 == len) {          if (NULL == name || -1 == len) {
                 free(value);                  free(name);
                 return -1;                  return -1;
         }          }
   
Line 128  finish_cgi_output(bozohttpd_t *httpd, bo
Line 127  finish_cgi_output(bozohttpd_t *httpd, bo
                 (str = bozodgetln(httpd, in, &len, bozo_read)) != NULL) {                  (str = bozodgetln(httpd, in, &len, bozo_read)) != NULL) {
                 char    *hdr_name, *hdr_value;                  char    *hdr_name, *hdr_value;
   
                 if (parse_header(request, str, len, &hdr_name, &hdr_value))                  if (parse_header(httpd, str, len, &hdr_name, &hdr_value))
                         break;                          break;
   
                 /*                  /*
Line 195  finish_cgi_output(bozohttpd_t *httpd, bo
Line 194  finish_cgi_output(bozohttpd_t *httpd, bo
                                 rbytes -= wbytes;                                  rbytes -= wbytes;
                                 bp += wbytes;                                  bp += wbytes;
                         } else                          } else
                                 bozoerr(httpd, 1,                                  bozo_err(httpd, 1,
                                         "cgi output write failed: %s",                                          "cgi output write failed: %s",
                                         strerror(errno));                                          strerror(errno));
                 }                  }
Line 212  append_index_html(bozohttpd_t *httpd, ch
Line 211  append_index_html(bozohttpd_t *httpd, ch
                 "append_index_html: url adjusted to `%s'", *url));                  "append_index_html: url adjusted to `%s'", *url));
 }  }
   
 /* This function parse search-string according to section 4.4 of RFC3875 */  
 static char **  
 parse_search_string(bozo_httpreq_t *request, const char *query, size_t *args_len)  
 {  
         struct  bozohttpd_t *httpd = request->hr_httpd;  
         size_t i;  
         char *s, *str, **args;  
   
         *args_len = 0;  
   
         /* URI MUST not contain any unencoded '=' - RFC3875, section 4.4 */  
         if (strchr(query, '=')) {  
                 return NULL;  
         }  
   
         str = bozostrdup(httpd, request, query);  
   
         /*  
          * there's no more arguments than '+' chars in the query string as it's  
          * the separator  
          */  
         *args_len = 1;  
         /* count '+' in str */  
         for (s = str; (s = strchr(s, '+')); (*args_len)++)  
                 s++;  
   
         args = bozomalloc(httpd, sizeof(*args) * (*args_len + 1));  
   
         args[0] = str;  
         args[*args_len] = NULL;  
         for (s = str, i = 0; (s = strchr(s, '+'));) {  
                 *s = '\0';  
                 s++;  
                 args[i++] = s;  
         }  
   
         /*  
          * check if search-strings are valid:  
          *  
          * RFC3875, section 4.4:  
          *  
          * search-string = search-word *( "+" search-word )  
          * search-word   = 1*schar  
          * schar                 = unreserved | escaped | xreserved  
          * xreserved     = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "," |  
          *                 "$"  
          *  
          * section 2.3:  
          *  
          * hex        = digit | "A" | "B" | "C" | "D" | "E" | "F" | "a" |  
          *              "b" | "c" | "d" | "e" | "f"  
          * escaped    = "%" hex hex  
          * unreserved = alpha | digit | mark  
          * mark       = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"  
          *  
          * section 2.2:  
          *  
          * alpha        = lowalpha | hialpha  
          * lowalpha     = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" |  
          *                "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" |  
          *                "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" |  
          *                "y" | "z"  
          * hialpha      = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" |  
          *                "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" |  
          *                "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" |  
          *                "Y" | "Z"  
          * digit        = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |  
          *                "8" | "9"  
          */  
 #define UNRESERVED_CHAR "-_.!~*'()"  
 #define XRESERVED_CHAR  ";/?:@&=,$"  
   
         for (i = 0; i < *args_len; i++) {  
                 s = args[i];  
                 /* search-word MUST have at least one schar */  
                 if (*s == '\0')  
                         goto parse_err;  
                 while(*s) {  
                         /* check if it's unreserved */  
                         if (isalpha((int)*s) || isdigit((int)*s) ||  
                             strchr(UNRESERVED_CHAR, *s)) {  
                                 s++;  
                                 continue;  
                         }  
   
                         /* check if it's escaped */  
                         if (*s == '%') {  
                                 if (s[1] == '\0' || s[2] == '\0')  
                                         goto parse_err;  
                                 if (!isxdigit((int)s[1]) ||  
                                     !isxdigit((int)s[2]))  
                                         goto parse_err;  
                                 s += 3;  
                                 continue;  
                         }  
   
                         /* check if it's xreserved */  
   
                         if (strchr(XRESERVED_CHAR, *s)) {  
                                 s++;  
                                 continue;  
                         }  
   
                         goto parse_err;  
                 }  
         }  
   
         /* decode percent encoding */  
         for (i = 0; i < *args_len; i++) {  
                 if (bozo_decode_url_percent(request, args[i]))  
                         goto parse_err;  
         }  
   
         /* allocate each arg separately */  
         for (i = 0; i < *args_len; i++)  
                 args[i] = bozostrdup(httpd, request, args[i]);  
         free(str);  
   
         return args;  
   
 parse_err:  
   
         free (str);  
         free (*args);  
         free(args);  
         *args_len = 0;  
   
         return NULL;  
   
 }  
   
 void  void
 bozo_cgi_setbin(bozohttpd_t *httpd, const char *path)  bozo_cgi_setbin(bozohttpd_t *httpd, const char *path)
 {  {
         httpd->cgibin = bozostrdup(httpd, NULL, path);          httpd->cgibin = strdup(path);
         debug((httpd, DEBUG_OBESE, "cgibin (cgi-bin directory) is %s",          debug((httpd, DEBUG_OBESE, "cgibin (cgi-bin directory) is %s",
                 httpd->cgibin));                  httpd->cgibin));
 }  }
Line 380  bozo_process_cgi(bozo_httpreq_t *request
Line 248  bozo_process_cgi(bozo_httpreq_t *request
         bozoheaders_t *headp;          bozoheaders_t *headp;
         const char *type, *clen, *info, *cgihandler;          const char *type, *clen, *info, *cgihandler;
         char    *query, *s, *t, *path, *env, *command, *file, *url;          char    *query, *s, *t, *path, *env, *command, *file, *url;
         char    **envp, **curenvp, **argv, **search_string_argv = NULL;          char    **envp, **curenvp, *argv[4];
         char    *uri;          char    *uri;
         size_t  i, len, search_string_argc = 0;          size_t  len;
         ssize_t rbytes;          ssize_t rbytes;
         pid_t   pid;          pid_t   pid;
         int     envpsize, ix, nph;          int     envpsize, ix, nph;
Line 391  bozo_process_cgi(bozo_httpreq_t *request
Line 259  bozo_process_cgi(bozo_httpreq_t *request
         if (!httpd->cgibin && !httpd->process_cgi)          if (!httpd->cgibin && !httpd->process_cgi)
                 return 0;                  return 0;
   
 #ifndef NO_USER_SUPPORT          uri = request->hr_oldfile ? request->hr_oldfile : request->hr_file;
         if (request->hr_user && !httpd->enable_cgi_users)  
                 return 0;  
 #endif /* !NO_USER_SUPPORT */  
   
         if (request->hr_oldfile && strcmp(request->hr_oldfile, "/") != 0)  
                 uri = request->hr_oldfile;  
         else  
                 uri = request->hr_file;  
   
         if (uri[0] == '/')          if (uri[0] == '/')
                 file = bozostrdup(httpd, request, uri);                  file = bozostrdup(httpd, uri);
         else          else
                 bozoasprintf(httpd, &file, "/%s", uri);                  asprintf(&file, "/%s", uri);
           if (file == NULL)
                   return 0;
   
         if (request->hr_query && strlen(request->hr_query))          if (request->hr_query && strlen(request->hr_query))
                 query = bozostrdup(httpd, request, request->hr_query);                  query = bozostrdup(httpd, request->hr_query);
         else          else
                 query = NULL;                  query = NULL;
   
         bozoasprintf(httpd, &url, "%s%s%s",          asprintf(&url, "%s%s%s", file, query ? "?" : "", query ? query : "");
                      file,          if (url == NULL)
                      query ? "?" : "",                  goto out;
                      query ? query : "");  
         debug((httpd, DEBUG_NORMAL, "bozo_process_cgi: url `%s'", url));          debug((httpd, DEBUG_NORMAL, "bozo_process_cgi: url `%s'", url));
   
         path = NULL;          path = NULL;
Line 443  bozo_process_cgi(bozo_httpreq_t *request
Line 303  bozo_process_cgi(bozo_httpreq_t *request
         } else if (len - 1 == CGIBIN_PREFIX_LEN)        /* url is "/cgi-bin/" */          } else if (len - 1 == CGIBIN_PREFIX_LEN)        /* url is "/cgi-bin/" */
                 append_index_html(httpd, &file);                  append_index_html(httpd, &file);
   
         /* RFC3875  sect. 4.4. - search-string support */  
         if (query != NULL) {  
                 search_string_argv = parse_search_string(request, query,  
                     &search_string_argc);  
         }  
   
         debug((httpd, DEBUG_NORMAL, "parse_search_string args no: %zu",  
             search_string_argc));  
         for (i = 0; i < search_string_argc; i++) {  
                 debug((httpd, DEBUG_FAT,  
                     "search_string[%zu]: `%s'", i, search_string_argv[i]));  
         }  
   
         argv = bozomalloc(httpd, sizeof(*argv) * (3 + search_string_argc));  
   
         ix = 0;          ix = 0;
         if (cgihandler) {          if (cgihandler) {
                 command = file + 1;                  command = file + 1;
                 path = bozostrdup(httpd, request, cgihandler);                  path = bozostrdup(httpd, cgihandler);
                   argv[ix++] = path;
                           /* argv[] = [ path, command, query, NULL ] */
         } else {          } else {
                 command = file + CGIBIN_PREFIX_LEN + 1;                  command = file + CGIBIN_PREFIX_LEN + 1;
                 if ((s = strchr(command, '/')) != NULL) {                  if ((s = strchr(command, '/')) != NULL) {
                         info = bozostrdup(httpd, request, s);                          info = bozostrdup(httpd, s);
                         *s = '\0';                          *s = '\0';
                 }                  }
                 path = bozomalloc(httpd,                  path = bozomalloc(httpd,
Line 473  bozo_process_cgi(bozo_httpreq_t *request
Line 320  bozo_process_cgi(bozo_httpreq_t *request
                 strcpy(path, httpd->cgibin);                  strcpy(path, httpd->cgibin);
                 strcat(path, "/");                  strcat(path, "/");
                 strcat(path, command);                  strcat(path, command);
                           /* argv[] = [ command, query, NULL ] */
         }          }
           argv[ix++] = command;
         argv[ix++] = path;          argv[ix++] = query;
   
         /* copy search-string args */  
         for (i = 0; i < search_string_argc; i++)  
                 argv[ix++] = search_string_argv[i];  
   
         argv[ix++] = NULL;          argv[ix++] = NULL;
   
         nph = strncmp(command, "nph-", 4) == 0;          nph = strncmp(command, "nph-", 4) == 0;
   
         type = request->hr_content_type;          type = request->hr_content_type;
Line 547  bozo_process_cgi(bozo_httpreq_t *request
Line 391  bozo_process_cgi(bozo_httpreq_t *request
         bozo_setenv(httpd, "REQUEST_URI", uri, curenvp++);          bozo_setenv(httpd, "REQUEST_URI", uri, curenvp++);
         bozo_setenv(httpd, "DATE_GMT", bozo_http_date(date, sizeof(date)),          bozo_setenv(httpd, "DATE_GMT", bozo_http_date(date, sizeof(date)),
                         curenvp++);                          curenvp++);
         /* RFC3875 section 4.1.7 says that QUERY_STRING MUST be defined. */  
         if (query && *query)          if (query && *query)
                 bozo_setenv(httpd, "QUERY_STRING", query, curenvp++);                  bozo_setenv(httpd, "QUERY_STRING", query, curenvp++);
         else  
                 bozo_setenv(httpd, "QUERY_STRING", "", curenvp++);  
         if (info && *info)          if (info && *info)
                 bozo_setenv(httpd, "PATH_INFO", info, curenvp++);                  bozo_setenv(httpd, "PATH_INFO", info, curenvp++);
         if (type && *type)          if (type && *type)
Line 568  bozo_process_cgi(bozo_httpreq_t *request
Line 409  bozo_process_cgi(bozo_httpreq_t *request
                 bozo_setenv(httpd, "REMOTE_ADDR", request->hr_remoteaddr,                  bozo_setenv(httpd, "REMOTE_ADDR", request->hr_remoteaddr,
                                 curenvp++);                                  curenvp++);
         /*          /*
          * Apache does this when invoking content handlers, and PHP           * XXX Apache does this when invoking content handlers, and PHP
          * 5.3 requires it as a "security" measure.           * XXX 5.3 requires it as a "security" measure.
          */           */
         if (cgihandler)          if (cgihandler)
                 bozo_setenv(httpd, "REDIRECT_STATUS", "200", curenvp++);                  bozo_setenv(httpd, "REDIRECT_STATUS", "200", curenvp++);
         bozo_auth_cgi_setenv(request, &curenvp);          bozo_auth_cgi_setenv(request, &curenvp);
   
         debug((httpd, DEBUG_FAT, "bozo_process_cgi: going exec %s with args:",          free(file);
             path));          free(url);
   
         for (i = 0; argv[i] != NULL; i++) {          debug((httpd, DEBUG_FAT, "bozo_process_cgi: going exec %s, %s %s %s",
                 debug((httpd, DEBUG_FAT, "bozo_process_cgi: argv[%zu] = `%s'",              path, argv[0], strornull(argv[1]), strornull(argv[2])));
                     i, argv[i]));  
         }  
   
         if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sv) == -1)          if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sv) == -1)
                 bozoerr(httpd, 1, "child socketpair failed: %s",                  bozo_err(httpd, 1, "child socketpair failed: %s",
                                 strerror(errno));                                  strerror(errno));
   
         /*          /*
Line 595  bozo_process_cgi(bozo_httpreq_t *request
Line 434  bozo_process_cgi(bozo_httpreq_t *request
          */           */
         switch (fork()) {          switch (fork()) {
         case -1: /* eep, failure */          case -1: /* eep, failure */
                 bozoerr(httpd, 1, "child fork failed: %s", strerror(errno));                  bozo_err(httpd, 1, "child fork failed: %s", strerror(errno));
                 /*NOTREACHED*/                  /*NOTREACHED*/
         case 0:          case 0:
                 close(sv[0]);                  close(sv[0]);
Line 607  bozo_process_cgi(bozo_httpreq_t *request
Line 446  bozo_process_cgi(bozo_httpreq_t *request
                 bozo_daemon_closefds(httpd);                  bozo_daemon_closefds(httpd);
   
                 if (-1 == execve(path, argv, envp))                  if (-1 == execve(path, argv, envp))
                         bozoerr(httpd, 1, "child exec failed: %s: %s",                          bozo_err(httpd, 1, "child exec failed: %s: %s",
                               path, strerror(errno));                                path, strerror(errno));
                 /* NOT REACHED */                  /* NOT REACHED */
                 bozoerr(httpd, 1, "child execve returned?!");                  bozo_err(httpd, 1, "child execve returned?!");
         }          }
   
         free(query);  
         free(file);  
         free(url);  
         for (i = 0; i < search_string_argc; i++)  
                 free(search_string_argv[i]);  
         free(search_string_argv);  
   
         close(sv[1]);          close(sv[1]);
   
         /* parent: read from stdin (bozo_read()) write to sv[0] */          /* parent: read from stdin (bozo_read()) write to sv[0] */
         /* child: read from sv[0] (bozo_write()) write to stdout */          /* child: read from sv[0] (bozo_write()) write to stdout */
         pid = fork();          pid = fork();
         if (pid == -1)          if (pid == -1)
                 bozoerr(httpd, 1, "io child fork failed: %s", strerror(errno));                  bozo_err(httpd, 1, "io child fork failed: %s", strerror(errno));
         else if (pid == 0) {          else if (pid == 0) {
                 /* child reader/writer */                  /* child reader/writer */
                 close(STDIN_FILENO);                  close(STDIN_FILENO);
Line 650  bozo_process_cgi(bozo_httpreq_t *request
Line 482  bozo_process_cgi(bozo_httpreq_t *request
                                 rbytes -= wbytes;                                  rbytes -= wbytes;
                                 bp += wbytes;                                  bp += wbytes;
                         } else                          } else
                                 bozoerr(httpd, 1, "write failed: %s",                                  bozo_err(httpd, 1, "write failed: %s",
                                         strerror(errno));                                          strerror(errno));
                 }                  }
         }          }
Line 658  bozo_process_cgi(bozo_httpreq_t *request
Line 490  bozo_process_cgi(bozo_httpreq_t *request
         exit(0);          exit(0);
   
  out:   out:
           if (query)
         for (i = 0; i < search_string_argc; i++)                  free(query);
                 free(search_string_argv[i]);          if (file)
         free(search_string_argv);                  free(file);
         free(query);          if (url)
         free(file);                  free(url);
         free(url);  
         return 0;          return 0;
 }  }
   
 #ifndef NO_DYNAMIC_CONTENT  #ifndef NO_DYNAMIC_CONTENT
 /* cgi maps are simple ".postfix /path/to/prog" */  /* cgi maps are simple ".postfix /path/to/prog" */
 void  void
 bozo_add_content_map_cgi(bozohttpd_t *httpd, const char *arg,  bozo_add_content_map_cgi(bozohttpd_t *httpd, const char *arg, const char *cgihandler)
                          const char *cgihandler)  
 {  {
         bozo_content_map_t *map;          bozo_content_map_t *map;
   
Line 683  bozo_add_content_map_cgi(bozohttpd_t *ht
Line 513  bozo_add_content_map_cgi(bozohttpd_t *ht
   
         map = bozo_get_content_map(httpd, arg);          map = bozo_get_content_map(httpd, arg);
         map->name = arg;          map->name = arg;
           map->namelen = strlen(map->name);
         map->type = map->encoding = map->encoding11 = NULL;          map->type = map->encoding = map->encoding11 = NULL;
         map->cgihandler = cgihandler;          map->cgihandler = cgihandler;
 }  }

Legend:
Removed from v.1.20.2.4  
changed lines
  Added in v.1.21

CVSweb <webmaster@jp.NetBSD.org>