[BACK]Return to bozohttpd.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/bozohttpd.c between version 1.56.2.8 and 1.56.2.8.2.3

version 1.56.2.8, 2017/02/12 22:07:17 version 1.56.2.8.2.3, 2019/06/15 15:56:21
Line 3 
Line 3 
 /*      $eterna: bozohttpd.c,v 1.178 2011/11/18 09:21:15 mrg Exp $      */  /*      $eterna: bozohttpd.c,v 1.178 2011/11/18 09:21:15 mrg Exp $      */
   
 /*  /*
  * Copyright (c) 1997-2017 Matthew R. Green   * Copyright (c) 1997-2019 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 109 
Line 109 
 #define INDEX_HTML              "index.html"  #define INDEX_HTML              "index.html"
 #endif  #endif
 #ifndef SERVER_SOFTWARE  #ifndef SERVER_SOFTWARE
 #define SERVER_SOFTWARE         "bozohttpd/20170201"  #define SERVER_SOFTWARE         "bozohttpd/20190228"
 #endif  
 #ifndef DIRECT_ACCESS_FILE  
 #define DIRECT_ACCESS_FILE      ".bzdirect"  
 #endif  
 #ifndef REDIRECT_FILE  
 #define REDIRECT_FILE           ".bzredirect"  
 #endif  
 #ifndef ABSREDIRECT_FILE  
 #define ABSREDIRECT_FILE        ".bzabsredirect"  
 #endif  #endif
 #ifndef PUBLIC_HTML  #ifndef PUBLIC_HTML
 #define PUBLIC_HTML             "public_html"  #define PUBLIC_HTML             "public_html"
Line 146 
Line 137 
 #include <netdb.h>  #include <netdb.h>
 #include <pwd.h>  #include <pwd.h>
 #include <grp.h>  #include <grp.h>
 #include <signal.h>  
 #include <stdarg.h>  #include <stdarg.h>
 #include <stdlib.h>  #include <stdlib.h>
   #include <strings.h>
 #include <string.h>  #include <string.h>
 #include <syslog.h>  #include <syslog.h>
 #include <time.h>  #include <time.h>
Line 156 
Line 147 
   
 #include "bozohttpd.h"  #include "bozohttpd.h"
   
 #ifndef MAX_WAIT_TIME  #ifndef SSL_TIMEOUT
 #define MAX_WAIT_TIME   60      /* hang around for 60 seconds max */  #define SSL_TIMEOUT             "30"    /* wait for 30 seconds for ssl handshake  */
   #endif
   #ifndef INITIAL_TIMEOUT
   #define INITIAL_TIMEOUT         "30"    /* wait for 30 seconds initially */
   #endif
   #ifndef HEADER_WAIT_TIME
   #define HEADER_WAIT_TIME        "10"    /* need more headers every 10 seconds */
   #endif
   #ifndef TOTAL_MAX_REQ_TIME
   #define TOTAL_MAX_REQ_TIME      "600"   /* must have total request in 600 */
   #endif                                  /* seconds */
   
   /* if monotonic time is not available try real time. */
   #ifndef CLOCK_MONOTONIC
   #define CLOCK_MONOTONIC CLOCK_REALTIME
 #endif  #endif
   
 /* variables and functions */  /* variables and functions */
Line 165 
Line 170 
 #define LOG_FTP LOG_DAEMON  #define LOG_FTP LOG_DAEMON
 #endif  #endif
   
 volatile sig_atomic_t   alarmhit;  /*
    * List of special file that we should never serve.
    */
   struct {
           const char *file;
           const char *name;
   } specials[] = {
           { DIRECT_ACCESS_FILE, "rejected direct access request" },
           { REDIRECT_FILE,      "rejected redirect request" },
           { ABSREDIRECT_FILE,   "rejected absredirect request" },
           { REMAP_FILE,         "rejected remap request" },
           { AUTH_FILE,          "rejected authfile request" },
           { NULL,               NULL },
   };
   
   volatile sig_atomic_t   bozo_timeout_hit;
   
 /*  /*
  * check there's enough space in the prefs and names arrays.   * check there's enough space in the prefs and names arrays.
  */   */
 static int  static int
 size_arrays(bozoprefs_t *bozoprefs, size_t needed)  size_arrays(bozohttpd_t *httpd, bozoprefs_t *bozoprefs, size_t needed)
 {  {
         char    **temp;          size_t  len = sizeof(char *) * needed;
   
         if (bozoprefs->size == 0) {          if (bozoprefs->size == 0) {
                 /* only get here first time around */                  /* only get here first time around */
                 bozoprefs->name = calloc(sizeof(char *), needed);                  bozoprefs->name = bozomalloc(httpd, len);
                 if (bozoprefs->name == NULL)                  bozoprefs->value = bozomalloc(httpd, len);
                         return 0;  
                 bozoprefs->value = calloc(sizeof(char *), needed);  
                 if (bozoprefs->value == NULL) {  
                         free(bozoprefs->name);  
                         return 0;  
                 }  
                 bozoprefs->size = needed;  
         } else if (bozoprefs->count == bozoprefs->size) {          } else if (bozoprefs->count == bozoprefs->size) {
                 /* only uses 'needed' when filled array */                  /* only uses 'needed' when filled array */
                 temp = realloc(bozoprefs->name, sizeof(char *) * needed);                  bozoprefs->name = bozorealloc(httpd, bozoprefs->name, len);
                 if (temp == NULL)                  bozoprefs->value = bozorealloc(httpd, bozoprefs->value, len);
                         return 0;  
                 bozoprefs->name = temp;  
                 temp = realloc(bozoprefs->value, sizeof(char *) * needed);  
                 if (temp == NULL)  
                         return 0;  
                 bozoprefs->value = temp;  
                 bozoprefs->size += needed;  
         }          }
   
           bozoprefs->size = needed;
         return 1;          return 1;
 }  }
   
Line 220  bozo_set_pref(bozohttpd_t *httpd, bozopr
Line 228  bozo_set_pref(bozohttpd_t *httpd, bozopr
   
         if ((i = findvar(bozoprefs, name)) < 0) {          if ((i = findvar(bozoprefs, name)) < 0) {
                 /* add the element to the array */                  /* add the element to the array */
                 if (!size_arrays(bozoprefs, bozoprefs->size + 15))                  if (!size_arrays(httpd, bozoprefs, bozoprefs->size + 15))
                         return 0;                          return 0;
                 i = bozoprefs->count++;                  i = bozoprefs->count++;
                 bozoprefs->name[i] = bozostrdup(httpd, NULL, name);                  bozoprefs->name[i] = bozostrdup(httpd, NULL, name);
         } else {          } else {
                 /* replace the element in the array */                  /* replace the element in the array */
                 if (bozoprefs->value[i]) {                  free(bozoprefs->value[i]);
                         free(bozoprefs->value[i]);  
                         bozoprefs->value[i] = NULL;  
                 }  
         }          }
         bozoprefs->value[i] = bozostrdup(httpd, NULL, value);          bozoprefs->value[i] = bozostrdup(httpd, NULL, value);
         return 1;          return 1;
Line 278  parse_request(bozohttpd_t *httpd, char *
Line 283  parse_request(bozohttpd_t *httpd, char *
   
         len = (ssize_t)strlen(in);          len = (ssize_t)strlen(in);
         val = bozostrnsep(&in, " \t\n\r", &len);          val = bozostrnsep(&in, " \t\n\r", &len);
         if (len < 1 || val == NULL)          if (len < 1 || val == NULL || in == NULL)
                 return;                  return;
         *method = val;          *method = val;
   
Line 368  bozo_clean_request(bozo_httpreq_t *reque
Line 373  bozo_clean_request(bozo_httpreq_t *reque
 static void  static void
 alarmer(int sig)  alarmer(int sig)
 {  {
         alarmhit = 1;          bozo_timeout_hit = 1;
   }
   
   
   /*
    * set a timeout for "ssl", "initial", "header", or "request".
    */
   int
   bozo_set_timeout(bozohttpd_t *httpd, bozoprefs_t *prefs,
                    const char *target, const char *val)
   {
           const char **cur, *timeouts[] = {
                   "ssl timeout",
                   "initial timeout",
                   "header timeout",
                   "request timeout",
                   NULL,
           };
           /* adjust minlen if more timeouts appear with conflicting names */
           const size_t minlen = 1;
           size_t len = strlen(target);
   
           for (cur = timeouts; len >= minlen && *cur; cur++) {
                   if (strncmp(target, *cur, len) == 0) {
                           bozo_set_pref(httpd, prefs, *cur, val);
                           return 0;
                   }
           }
           return 1;
 }  }
   
 /*  /*
Line 536  process_method(bozo_httpreq_t *request, 
Line 569  process_method(bozo_httpreq_t *request, 
         return bozo_http_error(httpd, 404, request, "unknown method");          return bozo_http_error(httpd, 404, request, "unknown method");
 }  }
   
   /* check header byte count */
   static int
   bozo_got_header_length(bozo_httpreq_t *request, size_t len)
   {
   
           if (len > BOZO_HEADERS_MAX_SIZE - request->hr_header_bytes)
                   return bozo_http_error(request->hr_httpd, 413, request,
                           "too many headers");
   
           request->hr_header_bytes += len;
   
           return 0;
   }
   
 /*  /*
  * This function reads a http request from stdin, returning a pointer to a   * This function reads a http request from stdin, returning a pointer to a
  * bozo_httpreq_t structure, describing the request.   * bozo_httpreq_t structure, describing the request.
Line 553  bozo_read_request(bozohttpd_t *httpd)
Line 600  bozo_read_request(bozohttpd_t *httpd)
         int     line = 0;          int     line = 0;
         socklen_t slen;          socklen_t slen;
         bozo_httpreq_t *request;          bozo_httpreq_t *request;
           struct timespec ots, ts;
   
         /*          /*
          * if we're in daemon mode, bozo_daemon_fork() will return here twice           * if we're in daemon mode, bozo_daemon_fork() will return here twice
          * for each call.  once in the child, returning 0, and once in the           * for each call.  once in the child, returning 0, and once in the
          * parent, returning 1.  for each child, then we can setup SSL, and           * parent, returning 1 for each child.
          * the parent can signal the caller there was no request to process  
          * and it will wait for another.  
          */           */
         if (bozo_daemon_fork(httpd))          if (bozo_daemon_fork(httpd))
                 return NULL;                  return NULL;
         if (bozo_ssl_accept(httpd))  
                 return NULL;  
   
         request = bozomalloc(httpd, sizeof(*request));          request = bozomalloc(httpd, sizeof(*request));
         memset(request, 0, sizeof(*request));          memset(request, 0, sizeof(*request));
Line 635  bozo_read_request(bozohttpd_t *httpd)
Line 679  bozo_read_request(bozohttpd_t *httpd)
         sa.sa_flags = 0;          sa.sa_flags = 0;
         sigaction(SIGALRM, &sa, NULL);          sigaction(SIGALRM, &sa, NULL);
   
         alarm(MAX_WAIT_TIME);          if (clock_gettime(CLOCK_MONOTONIC, &ots) != 0) {
                   bozo_http_error(httpd, 500, NULL, "clock_gettime failed");
                   goto cleanup;
           }
   
           /*
            * now to try to setup SSL, and upon failure parent can signal the
            * caller there was no request to process and it will wait for
            * another.
            */
           if (bozo_ssl_accept(httpd))
                   return NULL;
   
           alarm(httpd->initial_timeout);
         while ((str = bozodgetln(httpd, STDIN_FILENO, &len, bozo_read)) != NULL) {          while ((str = bozodgetln(httpd, STDIN_FILENO, &len, bozo_read)) != NULL) {
                 alarm(0);                  alarm(0);
                 if (alarmhit) {  
                         (void)bozo_http_error(httpd, 408, NULL,                  if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
                                         "request timed out");                          bozo_http_error(httpd, 500, NULL, "clock_gettime failed");
                           goto cleanup;
                   }
                   /*
                    * don't timeout if old tv_sec is not more than current
                    * tv_sec, or if current tv_sec is less than the request
                    * timeout (these shouldn't happen, but the first could
                    * if monotonic time is not available.)
                    *
                    * the other timeout and header size checks should ensure
                    * that even if time it set backwards or forwards a very
                    * long way, timeout will eventually happen, even if this
                    * one fails.
                    */
                   if (ts.tv_sec > ots.tv_sec &&
                       ts.tv_sec > httpd->request_timeout &&
                       ts.tv_sec - httpd->request_timeout > ots.tv_sec)
                           bozo_timeout_hit = 1;
   
                   if (bozo_timeout_hit) {
                           bozo_http_error(httpd, 408, NULL, "request timed out");
                         goto cleanup;                          goto cleanup;
                 }                  }
                 line++;                  line++;
   
                 if (line == 1) {                  if (line == 1) {
   
                         if (len < 1) {                          if (len < 1) {
                                 (void)bozo_http_error(httpd, 404, NULL,                                  bozo_http_error(httpd, 404, NULL, "null method");
                                                 "null method");  
                                 goto cleanup;                                  goto cleanup;
                         }                          }
                         bozowarn(httpd,                          bozowarn(httpd,
Line 663  bozo_read_request(bozohttpd_t *httpd)
Line 738  bozo_read_request(bozohttpd_t *httpd)
                         request->hr_file = file;                          request->hr_file = file;
                         request->hr_query = query;                          request->hr_query = query;
                         if (method == NULL) {                          if (method == NULL) {
                                 (void)bozo_http_error(httpd, 404, NULL,                                  bozo_http_error(httpd, 404, NULL, "null method");
                                                 "null method");  
                                 goto cleanup;                                  goto cleanup;
                         }                          }
                         if (file == NULL) {                          if (file == NULL) {
                                 (void)bozo_http_error(httpd, 404, NULL,                                  bozo_http_error(httpd, 404, NULL, "null file");
                                                 "null file");  
                                 goto cleanup;                                  goto cleanup;
                         }                          }
   
Line 697  bozo_read_request(bozohttpd_t *httpd)
Line 770  bozo_read_request(bozohttpd_t *httpd)
                                 break;                                  break;
   
                         val = bozostrnsep(&str, ":", &len);                          val = bozostrnsep(&str, ":", &len);
                         debug((httpd, DEBUG_EXPLODING,                          debug((httpd, DEBUG_EXPLODING, "read_req2: after "
                             "read_req2: after bozostrnsep: str ``%s'' val ``%s''",                              "bozostrnsep: str `%s' val `%s'", str, val));
                             str, val));  
                         if (val == NULL || len == -1) {                          if (val == NULL || len == -1) {
                                 (void)bozo_http_error(httpd, 404, request,                                  bozo_http_error(httpd, 404, request, "no header");
                                                 "no header");  
                                 goto cleanup;                                  goto cleanup;
                         }                          }
                         while (*str == ' ' || *str == '\t')                          while (*str == ' ' || *str == '\t')
Line 710  bozo_read_request(bozohttpd_t *httpd)
Line 781  bozo_read_request(bozohttpd_t *httpd)
                         while (*val == ' ' || *val == '\t')                          while (*val == ' ' || *val == '\t')
                                 val++;                                  val++;
   
                           if (bozo_got_header_length(request, len))
                                   goto cleanup;
   
                         if (bozo_auth_check_headers(request, val, str, len))                          if (bozo_auth_check_headers(request, val, str, len))
                                 goto next_header;                                  goto next_header;
   
Line 719  bozo_read_request(bozohttpd_t *httpd)
Line 793  bozo_read_request(bozohttpd_t *httpd)
                                 request->hr_content_type = hdr->h_value;                                  request->hr_content_type = hdr->h_value;
                         else if (strcasecmp(hdr->h_header, "content-length") == 0)                          else if (strcasecmp(hdr->h_header, "content-length") == 0)
                                 request->hr_content_length = hdr->h_value;                                  request->hr_content_length = hdr->h_value;
                         else if (strcasecmp(hdr->h_header, "host") == 0)                          else if (strcasecmp(hdr->h_header, "host") == 0) {
                                   if (request->hr_host) {
                                           /* RFC 7230 (HTTP/1.1): 5.4 */
                                           bozo_http_error(httpd, 400, request,
                                                   "Only allow one Host: header");
                                           goto cleanup;
                                   }
                                 request->hr_host = bozostrdup(httpd, request,                                  request->hr_host = bozostrdup(httpd, request,
                                                               hdr->h_value);                                                                hdr->h_value);
                           }
                         /* RFC 2616 (HTTP/1.1): 14.20 */                          /* RFC 2616 (HTTP/1.1): 14.20 */
                         else if (strcasecmp(hdr->h_header, "expect") == 0) {                          else if (strcasecmp(hdr->h_header, "expect") == 0) {
                                 (void)bozo_http_error(httpd, 417, request,                                  bozo_http_error(httpd, 417, request,
                                                 "we don't support Expect:");                                                  "we don't support Expect:");
                                 goto cleanup;                                  goto cleanup;
                         }                          }
Line 744  bozo_read_request(bozohttpd_t *httpd)
Line 825  bozo_read_request(bozohttpd_t *httpd)
                             hdr->h_header, hdr->h_value));                              hdr->h_header, hdr->h_value));
                 }                  }
 next_header:  next_header:
                 alarm(MAX_WAIT_TIME);                  alarm(httpd->header_timeout);
         }          }
   
         /* now, clear it all out */          /* now, clear it all out */
Line 754  next_header:
Line 835  next_header:
         /* RFC1945, 8.3 */          /* RFC1945, 8.3 */
         if (request->hr_method == HTTP_POST &&          if (request->hr_method == HTTP_POST &&
             request->hr_content_length == NULL) {              request->hr_content_length == NULL) {
                 (void)bozo_http_error(httpd, 400, request,                  bozo_http_error(httpd, 400, request, "missing content length");
                                 "missing content length");  
                 goto cleanup;                  goto cleanup;
         }          }
   
Line 763  next_header:
Line 843  next_header:
         if (request->hr_proto == httpd->consts.http_11 &&          if (request->hr_proto == httpd->consts.http_11 &&
             /*(strncasecmp(request->hr_file, "http://", 7) != 0) &&*/              /*(strncasecmp(request->hr_file, "http://", 7) != 0) &&*/
             request->hr_host == NULL) {              request->hr_host == NULL) {
                 (void)bozo_http_error(httpd, 400, request,                  bozo_http_error(httpd, 400, request, "missing Host header");
                                 "missing Host header");  
                 goto cleanup;                  goto cleanup;
         }          }
   
Line 908  bozo_escape_rfc3986(bozohttpd_t *httpd, 
Line 987  bozo_escape_rfc3986(bozohttpd_t *httpd, 
                 buf = bozorealloc(httpd, buf, buflen);                  buf = bozorealloc(httpd, buf, buflen);
         }          }
   
         for (len = 0, s = url, d = buf; *s;) {          for (s = url, d = buf; *s;) {
                 if (*s & 0x80)                  if (*s & 0x80)
                         goto encode_it;                          goto encode_it;
                 switch (*s) {                  switch (*s) {
Line 933  bozo_escape_rfc3986(bozohttpd_t *httpd, 
Line 1012  bozo_escape_rfc3986(bozohttpd_t *httpd, 
                 case '"':                  case '"':
                         if (absolute)                          if (absolute)
                                 goto leave_it;                                  goto leave_it;
                           /*FALLTHROUGH*/
                 case '\n':                  case '\n':
                 case '\r':                  case '\r':
                 case ' ':                  case ' ':
                 encode_it:                  encode_it:
                         snprintf(d, 4, "%%%02X", *s++);                          snprintf(d, 4, "%%%02X", (unsigned char)*s++);
                         d += 3;                          d += 3;
                         len += 3;  
                         break;                          break;
                 leave_it:  
                 default:                  default:
                   leave_it:
                         *d++ = *s++;                          *d++ = *s++;
                         len++;  
                         break;                          break;
                 }                  }
         }          }
         buf[len] = 0;          *d = 0;
   
         return buf;          return buf;
 }  }
Line 1069  head:
Line 1147  head:
 }  }
   
 /*  /*
    * Like strncmp(), but s_esc may contain characters escaped by \.
    * The len argument does not include the backslashes used for escaping,
    * that is: it gives the raw len, after unescaping the string.
    */
   static int
   esccmp(const char *s_plain, const char *s_esc, size_t len)
   {
           bool esc = false;
   
           while (len) {
                   if (!esc && *s_esc == '\\') {
                           esc = true;
                           s_esc++;
                           continue;
                   }
                   esc = false;
                   if (*s_plain == 0 || *s_esc == 0 || *s_plain != *s_esc)
                           return *s_esc - *s_plain;
                   s_esc++;
                   s_plain++;
                   len--;
           }
           return 0;
   }
   
   /*
    * Check if the request refers to a uri that is mapped via a .bzremap.
    * We have  /requested/path:/re/mapped/to/this.html lines in there,
    * and the : separator may be use in the left hand side escaped with
    * \ to encode a path containig a : character.
    */
   static void
   check_remap(bozo_httpreq_t *request)
   {
           bozohttpd_t *httpd = request->hr_httpd;
           char *file = request->hr_file, *newfile;
           void *fmap;
           const char *replace = NULL, *map_to = NULL, *p;
           struct stat st;
           int mapfile;
           size_t avail, len, rlen, reqlen, num_esc = 0;
           bool escaped = false;
   
           mapfile = open(REMAP_FILE, O_RDONLY, 0);
           if (mapfile == -1)
                   return;
           debug((httpd, DEBUG_FAT, "remap file found"));
           if (fstat(mapfile, &st) == -1) {
                   bozowarn(httpd, "could not stat " REMAP_FILE ", errno: %d",
                       errno);
                   goto out;
           }
   
           fmap = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, mapfile, 0);
           if (fmap == NULL) {
                   bozowarn(httpd, "could not mmap " REMAP_FILE ", error %d",
                       errno);
                   goto out;
           }
           reqlen = strlen(file);
           for (p = fmap, avail = st.st_size; avail; ) {
                   /*
                    * We have lines like:
                    *   /this/url:/replacement/that/url
                    * If we find a matching left hand side, replace will point
                    * to it and len will be its length. map_to will point to
                    * the right hand side and rlen wil be its length.
                    * If we have no match, both pointers will be NULL.
                    */
   
                   /* skip empty lines */
                   while ((*p == '\r' || *p == '\n') && avail) {
                           p++;
                           avail--;
                   }
                   replace = p;
                   escaped = false;
                   while (avail) {
                           if (*p == '\r' || *p == '\n')
                                   break;
                           if (!escaped && *p == ':')
                                   break;
                           if (escaped) {
                                   escaped = false;
                                   num_esc++;
                           } else if (*p == '\\') {
                                   escaped = true;
                           }
                           p++;
                           avail--;
                   }
                   if (!avail || *p != ':') {
                           replace = NULL;
                           map_to = NULL;
                           break;
                   }
                   len = p - replace - num_esc;
                   /*
                    * reqlen < len: the left hand side is too long, can't be a
                    *   match
                    * reqlen == len: full string has to match
                    * reqlen > len: make sure there is a path separator at 'len'
                    * avail < 2: we are at eof, missing right hand side
                    */
                   if (avail < 2 || reqlen < len ||
                       (reqlen == len && esccmp(file, replace, len) != 0) ||
                       (reqlen > len && (file[len] != '/' ||
                                           esccmp(file, replace, len) != 0))) {
   
                           /* non-match, skip to end of line and continue */
                           while (*p != '\r' && *p != '\n' && avail) {
                                   p++;
                                   avail--;
                           }
                           replace = NULL;
                           map_to = NULL;
                           continue;
                   }
                   p++;
                   avail--;
   
                   /* found a match, parse the target */
                   map_to = p;
                   while (*p != '\r' && *p != '\n' && avail) {
                           p++;
                           avail--;
                   }
                   rlen = p - map_to;
                   break;
           }
   
           if (replace && map_to) {
                   newfile = bozomalloc(httpd, strlen(file) + rlen - len + 1);
                   memcpy(newfile, map_to, rlen);
                   strcpy(newfile+rlen, file + len);
                   debug((httpd, DEBUG_NORMAL, "remapping found '%s'",
                       newfile));
                   free(request->hr_file);
                   request->hr_file = newfile;
           }
   
           munmap(fmap, st.st_size);
   out:
           close(mapfile);
   }
   
   /*
  * deal with virtual host names; we do this:   * deal with virtual host names; we do this:
  *      if we have a virtual path root (httpd->virtbase), and we are given a   *      if we have a virtual path root (httpd->virtbase), and we are given a
  *      virtual host spec (Host: ho.st or http://ho.st/), see if this   *      virtual host spec (Host: ho.st or http://ho.st/), see if this
Line 1085  check_virtual(bozo_httpreq_t *request)
Line 1310  check_virtual(bozo_httpreq_t *request)
         /*          /*
          * convert http://virtual.host/ to request->hr_host           * convert http://virtual.host/ to request->hr_host
          */           */
         debug((httpd, DEBUG_OBESE, "checking for http:// virtual host in ``%s''",          debug((httpd, DEBUG_OBESE,
                         file));                 "checking for http:// virtual host in '%s'", file));
         if (strncasecmp(file, "http://", 7) == 0) {          if (strncasecmp(file, "http://", 7) == 0) {
                   /* bozostrdup() might access it. */
                   char *old_file = request->hr_file;
   
                 /* we would do virtual hosting here? */                  /* we would do virtual hosting here? */
                 file += 7;                  file += 7;
                 /* RFC 2616 (HTTP/1.1), 5.2: URI takes precedence over Host: */                  /* RFC 2616 (HTTP/1.1), 5.2: URI takes precedence over Host: */
Line 1096  check_virtual(bozo_httpreq_t *request)
Line 1324  check_virtual(bozo_httpreq_t *request)
                 if ((s = strchr(request->hr_host, '/')) != NULL)                  if ((s = strchr(request->hr_host, '/')) != NULL)
                         *s = '\0';                          *s = '\0';
                 s = strchr(file, '/');                  s = strchr(file, '/');
                 free(request->hr_file);  
                 request->hr_file = bozostrdup(httpd, request, s ? s : "/");                  request->hr_file = bozostrdup(httpd, request, s ? s : "/");
                 debug((httpd, DEBUG_OBESE, "got host ``%s'' file is now ``%s''",                  free(old_file);
                   debug((httpd, DEBUG_OBESE, "got host '%s' file is now '%s'",
                     request->hr_host, request->hr_file));                      request->hr_host, request->hr_file));
         } else if (!request->hr_host)          } else if (!request->hr_host)
                 goto use_slashdir;                  goto use_slashdir;
Line 1113  check_virtual(bozo_httpreq_t *request)
Line 1341  check_virtual(bozo_httpreq_t *request)
         }          }
   
         if (!httpd->virtbase) {          if (!httpd->virtbase) {
   
                 /*                  /*
                  * if we don't use vhost support, then set virthostname if                   * if we don't use vhost support, then set virthostname if
                  * user supplied Host header. It will be used for possible                   * user supplied Host header. It will be used for possible
                  * redirections                   * redirections
                  */                   */
   
                 if (request->hr_host) {                  if (request->hr_host) {
                         s = strrchr(request->hr_host, ':');                          s = strrchr(request->hr_host, ':');
                         if (s != NULL)                          if (s != NULL)
                                 /* truncate Host: as we want to copy it without port part */                                  /*
                                    * truncate Host: as we want to copy it
                                    * without port part
                                    */
                                 *s = '\0';                                  *s = '\0';
                         request->hr_virthostname = bozostrdup(httpd, request,                          request->hr_virthostname = bozostrdup(httpd, request,
                           request->hr_host);                            request->hr_host);
Line 1131  check_virtual(bozo_httpreq_t *request)
Line 1360  check_virtual(bozo_httpreq_t *request)
                                 /* fix Host: again, if we truncated it */                                  /* fix Host: again, if we truncated it */
                                 *s = ':';                                  *s = ':';
                 }                  }
   
                 goto use_slashdir;                  goto use_slashdir;
         }          }
   
Line 1146  check_virtual(bozo_httpreq_t *request)
Line 1374  check_virtual(bozo_httpreq_t *request)
             "for file `%s'",              "for file `%s'",
             request->hr_host, httpd->virtbase, request->hr_file));              request->hr_host, httpd->virtbase, request->hr_file));
         if (strncasecmp(httpd->virthostname, request->hr_host, len) != 0) {          if (strncasecmp(httpd->virthostname, request->hr_host, len) != 0) {
                 s = 0;                  s = NULL;
                 DIR *dirp;                  DIR *dirp;
                 struct dirent *d;                  struct dirent *d;
   
Line 1156  check_virtual(bozo_httpreq_t *request)
Line 1384  check_virtual(bozo_httpreq_t *request)
                                     strcmp(d->d_name, "..") == 0) {                                      strcmp(d->d_name, "..") == 0) {
                                         continue;                                          continue;
                                 }                                  }
                                 debug((httpd, DEBUG_OBESE, "looking at dir``%s''",                                  debug((httpd, DEBUG_OBESE, "looking at dir '%s'",
                                    d->d_name));                                     d->d_name));
                                 if (strcmp(d->d_name, request->hr_host) == 0) {                                  if (strcmp(d->d_name, request->hr_host) == 0) {
                                         /* found it, punch it */                                          /* found it, punch it */
Line 1191  use_slashdir:
Line 1419  use_slashdir:
         if (chdir(s) < 0)          if (chdir(s) < 0)
                 return bozo_http_error(httpd, 404, request,                  return bozo_http_error(httpd, 404, request,
                                         "can't chdir to slashdir");                                          "can't chdir to slashdir");
   
           /*
            * is there a mapping for this request?
            */
           check_remap(request);
   
         return 0;          return 0;
 }  }
   
Line 1205  check_bzredirect(bozo_httpreq_t *request
Line 1439  check_bzredirect(bozo_httpreq_t *request
         bozohttpd_t *httpd = request->hr_httpd;          bozohttpd_t *httpd = request->hr_httpd;
         struct stat sb;          struct stat sb;
         char dir[MAXPATHLEN], redir[MAXPATHLEN], redirpath[MAXPATHLEN + 1],          char dir[MAXPATHLEN], redir[MAXPATHLEN], redirpath[MAXPATHLEN + 1],
             path[MAXPATHLEN];              path[MAXPATHLEN + 1];
         char *basename, *finalredir;          char *basename, *finalredir;
         int rv, absolute;          int rv, absolute;
   
Line 1213  check_bzredirect(bozo_httpreq_t *request
Line 1447  check_bzredirect(bozo_httpreq_t *request
          * if this pathname is really a directory, but doesn't end in /,           * if this pathname is really a directory, but doesn't end in /,
          * use it as the directory to look for the redir file.           * use it as the directory to look for the redir file.
          */           */
         if((size_t)snprintf(dir, sizeof(dir), "%s", request->hr_file + 1) >=          if ((size_t)snprintf(dir, sizeof(dir), "%s", request->hr_file + 1) >=
           sizeof(dir)) {              sizeof(dir)) {
                 bozo_http_error(httpd, 404, request,                  bozo_http_error(httpd, 404, request, "file path too long");
                   "file path too long");  
                 return -1;                  return -1;
         }          }
         debug((httpd, DEBUG_FAT, "check_bzredirect: dir %s", dir));          debug((httpd, DEBUG_FAT, "check_bzredirect: dir %s", dir));
Line 1225  check_bzredirect(bozo_httpreq_t *request
Line 1458  check_bzredirect(bozo_httpreq_t *request
         if ((!basename || basename[1] != '\0') &&          if ((!basename || basename[1] != '\0') &&
             lstat(dir, &sb) == 0 && S_ISDIR(sb.st_mode)) {              lstat(dir, &sb) == 0 && S_ISDIR(sb.st_mode)) {
                 strcpy(path, dir);                  strcpy(path, dir);
                   basename = dir;
         } else if (basename == NULL) {          } else if (basename == NULL) {
                 strcpy(path, ".");                  strcpy(path, ".");
                 strcpy(dir, "");                  strcpy(dir, "");
                   basename = request->hr_file + 1;
         } else {          } else {
                 *basename++ = '\0';                  *basename++ = '\0';
                 bozo_check_special_files(request, basename);  
                 strcpy(path, dir);                  strcpy(path, dir);
         }          }
           if (bozo_check_special_files(request, basename, true))
                   return -1;
   
         debug((httpd, DEBUG_FAT, "check_bzredirect: path %s", path));          debug((httpd, DEBUG_FAT, "check_bzredirect: path %s", path));
   
         if ((size_t)snprintf(redir, sizeof(redir), "%s/%s", path,          if ((size_t)snprintf(redir, sizeof(redir), "%s/%s", path,
           REDIRECT_FILE) >= sizeof(redir)) {                               REDIRECT_FILE) >= sizeof(redir)) {
                 bozo_http_error(httpd, 404, request,                  return bozo_http_error(httpd, 404, request,
                     "redirectfile path too long");                      "redirectfile path too long");
                 return -1;  
         }          }
         if (lstat(redir, &sb) == 0) {          if (lstat(redir, &sb) == 0) {
                 if (!S_ISLNK(sb.st_mode))                  if (!S_ISLNK(sb.st_mode))
                         return 0;                          return 0;
                 absolute = 0;                  absolute = 0;
         } else {          } else {
                 if((size_t)snprintf(redir, sizeof(redir), "%s/%s", path,                  if ((size_t)snprintf(redir, sizeof(redir), "%s/%s", path,
                   ABSREDIRECT_FILE) >= sizeof(redir)) {                                       ABSREDIRECT_FILE) >= sizeof(redir)) {
                         bozo_http_error(httpd, 404, request,                          bozo_http_error(httpd, 404, request,
                           "redirectfile path too long");                                          "redirectfile path too long");
                         return -1;                          return -1;
                 }                  }
                 if (lstat(redir, &sb) < 0 || !S_ISLNK(sb.st_mode))                  if (lstat(redir, &sb) < 0 || !S_ISLNK(sb.st_mode))
Line 1276  check_bzredirect(bozo_httpreq_t *request
Line 1511  check_bzredirect(bozo_httpreq_t *request
                 if ((size_t)snprintf(finalredir = redir, sizeof(redir), "%s%s/%s",                  if ((size_t)snprintf(finalredir = redir, sizeof(redir), "%s%s/%s",
                   (strlen(dir) > 0 ? "/" : ""), dir, redirpath) >= sizeof(redir)) {                    (strlen(dir) > 0 ? "/" : ""), dir, redirpath) >= sizeof(redir)) {
                         bozo_http_error(httpd, 404, request,                          bozo_http_error(httpd, 404, request,
                           "redirect path too long");                                          "redirect path too long");
                         return -1;                          return -1;
                 }                  }
         } else          } else
Line 1313  bozo_decode_url_percent(bozo_httpreq_t *
Line 1548  bozo_decode_url_percent(bozo_httpreq_t *
                 debug((httpd, DEBUG_EXPLODING,                  debug((httpd, DEBUG_EXPLODING,
                         "fu_%%: got s == %%, s[1]s[2] == %c%c",                          "fu_%%: got s == %%, s[1]s[2] == %c%c",
                         s[1], s[2]));                          s[1], s[2]));
                 if (s[1] == '\0' || s[2] == '\0') {                  if (s[1] == '\0' || s[2] == '\0')
                         (void)bozo_http_error(httpd, 400, request,                          return bozo_http_error(httpd, 400, request,
                             "percent hack missing two chars afterwards");                              "percent hack missing two chars afterwards");
                         return 1;                  if (s[1] == '0' && s[2] == '0')
                 }                          return bozo_http_error(httpd, 404, request,
                 if (s[1] == '0' && s[2] == '0') {                              "percent hack was %00");
                         (void)bozo_http_error(httpd, 404, request,                  if (s[1] == '2' && s[2] == 'f')
                                         "percent hack was %00");                          return bozo_http_error(httpd, 404, request,
                         return 1;                              "percent hack was %2f (/)");
                 }  
                 if (s[1] == '2' && s[2] == 'f') {  
                         (void)bozo_http_error(httpd, 404, request,  
                                         "percent hack was %2f (/)");  
                         return 1;  
                 }  
   
                 buf[0] = *++s;                  buf[0] = *++s;
                 buf[1] = *++s;                  buf[1] = *++s;
Line 1336  bozo_decode_url_percent(bozo_httpreq_t *
Line 1565  bozo_decode_url_percent(bozo_httpreq_t *
                 *t = (char)strtol(buf, NULL, 16);                  *t = (char)strtol(buf, NULL, 16);
                 debug((httpd, DEBUG_EXPLODING,                  debug((httpd, DEBUG_EXPLODING,
                                 "fu_%%: strtol put '%02x' into *t", *t));                                  "fu_%%: strtol put '%02x' into *t", *t));
                 if (*t++ == '\0') {                  if (*t++ == '\0')
                         (void)bozo_http_error(httpd, 400, request,                          return bozo_http_error(httpd, 400, request,
                                         "percent hack got a 0 back");                              "percent hack got a 0 back");
                         return 1;  
                 }  
   
                 while (*s && *s != '%') {                  while (*s && *s != '%') {
                         if (end && s >= end)                          if (end && s >= end)
Line 1381  transform_request(bozo_httpreq_t *reques
Line 1608  transform_request(bozo_httpreq_t *reques
         file = NULL;          file = NULL;
         *isindex = 0;          *isindex = 0;
         debug((httpd, DEBUG_FAT, "tf_req: file %s", request->hr_file));          debug((httpd, DEBUG_FAT, "tf_req: file %s", request->hr_file));
         if (bozo_decode_url_percent(request, request->hr_file)) {  
                 goto bad_done;          if (bozo_decode_url_percent(request, request->hr_file) ||
         }              check_virtual(request))
         if (check_virtual(request)) {  
                 goto bad_done;                  goto bad_done;
         }  
         file = request->hr_file;          file = request->hr_file;
   
         if (file[0] != '/') {          if (file[0] != '/') {
                 (void)bozo_http_error(httpd, 404, request, "unknown URL");                  bozo_http_error(httpd, 404, request, "unknown URL");
                 goto bad_done;                  goto bad_done;
         }          }
   
Line 1407  transform_request(bozo_httpreq_t *reques
Line 1633  transform_request(bozo_httpreq_t *reques
         /* first of all expand user path */          /* first of all expand user path */
         if (len > 1 && httpd->enable_users && file[1] == '~') {          if (len > 1 && httpd->enable_users && file[1] == '~') {
                 if (file[2] == '\0') {                  if (file[2] == '\0') {
                         (void)bozo_http_error(httpd, 404, request,                          bozo_http_error(httpd, 404, request,
                                                 "missing username");                                          "missing username");
                         goto bad_done;                          goto bad_done;
                 }                  }
                 if (strchr(file + 2, '/') == NULL) {                  if (strchr(file + 2, '/') == NULL) {
                         char *userredirecturl;                          char *userredirecturl;
   
                         bozoasprintf(httpd, &userredirecturl, "%s/", file);                          bozoasprintf(httpd, &userredirecturl, "%s/", file);
                         handle_redirect(request, userredirecturl, 0);                          handle_redirect(request, userredirecturl, 0);
                         free(userredirecturl);                          free(userredirecturl);
Line 1432  transform_request(bozo_httpreq_t *reques
Line 1659  transform_request(bozo_httpreq_t *reques
         switch (check_bzredirect(request)) {          switch (check_bzredirect(request)) {
         case -1:          case -1:
                 goto bad_done;                  goto bad_done;
         case 1:          case 0:
                   break;
           default:
                 return 0;                  return 0;
         }          }
   
Line 1452  transform_request(bozo_httpreq_t *reques
Line 1681  transform_request(bozo_httpreq_t *reques
                 newfile = bozostrdup(httpd, request, httpd->index_html);                  newfile = bozostrdup(httpd, request, httpd->index_html);
                 *isindex = 1;                  *isindex = 1;
         } else {        /* len == 0 ? */          } else {        /* len == 0 ? */
                 (void)bozo_http_error(httpd, 500, request,                  bozo_http_error(httpd, 500, request, "request->hr_file is nul");
                                         "request->hr_file is nul?");  
                 goto bad_done;                  goto bad_done;
         }          }
   
         if (newfile == NULL) {          if (newfile == NULL) {
                 (void)bozo_http_error(httpd, 500, request, "internal failure");                  bozo_http_error(httpd, 500, request, "internal failure");
                 goto bad_done;                  goto bad_done;
         }          }
   
Line 1473  transform_request(bozo_httpreq_t *reques
Line 1701  transform_request(bozo_httpreq_t *reques
   
         if (*newfile == '/' || strcmp(newfile, "..") == 0 ||          if (*newfile == '/' || strcmp(newfile, "..") == 0 ||
             strstr(newfile, "/..") || strstr(newfile, "../")) {              strstr(newfile, "/..") || strstr(newfile, "../")) {
                 (void)bozo_http_error(httpd, 403, request, "illegal request");                  bozo_http_error(httpd, 403, request, "illegal request");
                 goto bad_done;                  goto bad_done;
         }          }
   
Line 1485  transform_request(bozo_httpreq_t *reques
Line 1713  transform_request(bozo_httpreq_t *reques
                 request->hr_file = newfile;                  request->hr_file = newfile;
         }          }
   
         if (bozo_process_cgi(request))          if (bozo_process_cgi(request) ||
                 return 0;              bozo_process_lua(request))
   
         if (bozo_process_lua(request))  
                 return 0;                  return 0;
   
         debug((httpd, DEBUG_FAT, "transform_request set: %s", newfile));          debug((httpd, DEBUG_FAT, "transform_request set: %s", newfile));
         return 1;          return 1;
   
 bad_done:  bad_done:
         debug((httpd, DEBUG_FAT, "transform_request returning: 0"));          debug((httpd, DEBUG_FAT, "transform_request returning: 0"));
         free(newfile);          free(newfile);
Line 1591  bozo_process_request(bozo_httpreq_t *req
Line 1818  bozo_process_request(bozo_httpreq_t *req
                 switch (errno) {                  switch (errno) {
                 case EPERM:                  case EPERM:
                 case EACCES:                  case EACCES:
                         (void)bozo_http_error(httpd, 403, request,                          bozo_http_error(httpd, 403, request,
                                                 "no permission to open file");                                          "no permission to open file");
                         break;                          break;
                 case ENAMETOOLONG:                  case ENAMETOOLONG:
                         /*FALLTHROUGH*/                          /*FALLTHROUGH*/
                 case ENOENT:                  case ENOENT:
                         if (!bozo_dir_index(request, file, isindex))                          if (!bozo_dir_index(request, file, isindex))
                                 (void)bozo_http_error(httpd, 404, request,                                  bozo_http_error(httpd, 404, request, "no file");
                                                         "no file");  
                         break;                          break;
                 default:                  default:
                         (void)bozo_http_error(httpd, 500, request, "open file");                          bozo_http_error(httpd, 500, request, "open file");
                 }                  }
                 goto cleanup_nofd;                  goto cleanup_nofd;
         }          }
         if (fstat(fd, &sb) < 0) {          if (fstat(fd, &sb) < 0) {
                 (void)bozo_http_error(httpd, 500, request, "can't fstat");                  bozo_http_error(httpd, 500, request, "can't fstat");
                 goto cleanup;                  goto cleanup;
         }          }
         if (S_ISDIR(sb.st_mode)) {          if (S_ISDIR(sb.st_mode)) {
Line 1693  bozo_process_request(bozo_httpreq_t *req
Line 1919  bozo_process_request(bozo_httpreq_t *req
   
 /* make sure we're not trying to access special files */  /* make sure we're not trying to access special files */
 int  int
 bozo_check_special_files(bozo_httpreq_t *request, const char *name)  bozo_check_special_files(bozo_httpreq_t *request, const char *name, bool doerror)
 {  {
         bozohttpd_t *httpd = request->hr_httpd;          bozohttpd_t *httpd = request->hr_httpd;
           size_t i;
           int error = 0;
   
           for (i = 0; specials[i].file; i++) {
                   if (strcmp(name, specials[i].file) == 0) {
                           if (doerror) {
                                   error = bozo_http_error(httpd, 403, request,
                                                  specials[i].name);
                           } else {
                                   error = -1;
                           }
                   }
           }
   
         /* ensure basename(name) != special files */          return error;
         if (strcmp(name, DIRECT_ACCESS_FILE) == 0)  
                 return bozo_http_error(httpd, 403, request,  
                     "no permission to open direct access file");  
         if (strcmp(name, REDIRECT_FILE) == 0)  
                 return bozo_http_error(httpd, 403, request,  
                     "no permission to open redirect file");  
         if (strcmp(name, ABSREDIRECT_FILE) == 0)  
                 return bozo_http_error(httpd, 403, request,  
                     "no permission to open redirect file");  
         return bozo_auth_check_special_files(request, name);  
 }  }
   
 /* generic header printing routine */  /* generic header printing routine */
Line 1852  bozo_escape_html(bozohttpd_t *httpd, con
Line 2081  bozo_escape_html(bozohttpd_t *httpd, con
                 case '&':                  case '&':
                         j += 5;                          j += 5;
                         break;                          break;
                   case '"':
                           j += 6;
                           break;
                 }                  }
         }          }
   
Line 1882  bozo_escape_html(bozohttpd_t *httpd, con
Line 2114  bozo_escape_html(bozohttpd_t *httpd, con
                         memcpy(tmp + j, "&amp;", 5);                          memcpy(tmp + j, "&amp;", 5);
                         j += 5;                          j += 5;
                         break;                          break;
                   case '"':
                           memcpy(tmp + j, "&quot;", 6);
                           j += 6;
                           break;
                 default:                  default:
                         tmp[j++] = url[i];                          tmp[j++] = url[i];
                 }                  }
Line 1902  static struct errors_map {
Line 2138  static struct errors_map {
         { 403,  "403 Forbidden",        "Access to this item has been denied",},          { 403,  "403 Forbidden",        "Access to this item has been denied",},
         { 404,  "404 Not Found",        "This item has not been found", },          { 404,  "404 Not Found",        "This item has not been found", },
         { 408,  "408 Request Timeout",  "This request took too long", },          { 408,  "408 Request Timeout",  "This request took too long", },
           { 413,  "413 Payload Too Large", "Use smaller requests", },
         { 417,  "417 Expectation Failed","Expectations not available", },          { 417,  "417 Expectation Failed","Expectations not available", },
         { 420,  "420 Enhance Your Calm","Chill, Winston", },          { 420,  "420 Enhance Your Calm","Chill, Winston", },
         { 500,  "500 Internal Error",   "An error occured on the server", },          { 500,  "500 Internal Error",   "An error occured on the server", },
Line 1963  bozo_http_error(bozohttpd_t *httpd, int 
Line 2200  bozo_http_error(bozohttpd_t *httpd, int 
                 portbuf[0] = '\0';                  portbuf[0] = '\0';
   
         if (request && request->hr_file) {          if (request && request->hr_file) {
                 char *file = NULL, *user = NULL, *user_escaped = NULL;                  char *file = NULL, *user = NULL;
                 int file_alloc = 0;                  int file_alloc = 0;
                 const char *hostname = BOZOHOST(httpd, request);                  const char *hostname = BOZOHOST(httpd, request);
   
Line 1976  bozo_http_error(bozohttpd_t *httpd, int 
Line 2213  bozo_http_error(bozohttpd_t *httpd, int 
   
 #ifndef NO_USER_SUPPORT  #ifndef NO_USER_SUPPORT
                 if (request->hr_user != NULL) {                  if (request->hr_user != NULL) {
                           char *user_escaped;
   
                         user_escaped = bozo_escape_html(NULL, request->hr_user);                          user_escaped = bozo_escape_html(NULL, request->hr_user);
                         if (user_escaped == NULL)                          if (user_escaped == NULL)
                                 user_escaped = request->hr_user;                                  user_escaped = request->hr_user;
Line 1990  bozo_http_error(bozohttpd_t *httpd, int 
Line 2229  bozo_http_error(bozohttpd_t *httpd, int 
                     "<html><head><title>%s</title></head>\n"                      "<html><head><title>%s</title></head>\n"
                     "<body><h1>%s</h1>\n"                      "<body><h1>%s</h1>\n"
                     "%s%s: <pre>%s</pre>\n"                      "%s%s: <pre>%s</pre>\n"
                     "<hr><address><a href=\"http://%s%s/\">%s%s</a></address>\n"                      "<hr><address><a href=\"//%s%s/\">%s%s</a></address>\n"
                     "</body></html>\n",                      "</body></html>\n",
                     header, header,                      header, header,
                     user ? user : "", file,                      user ? user : "", file,
Line 2022  bozo_http_error(bozohttpd_t *httpd, int 
Line 2261  bozo_http_error(bozohttpd_t *httpd, int 
         bozo_printf(httpd, "Server: %s\r\n", httpd->server_software);          bozo_printf(httpd, "Server: %s\r\n", httpd->server_software);
         if (request && request->hr_allow)          if (request && request->hr_allow)
                 bozo_printf(httpd, "Allow: %s\r\n", request->hr_allow);                  bozo_printf(httpd, "Allow: %s\r\n", request->hr_allow);
           /* RFC 7231 (HTTP/1.1) 6.5.7 */
           if (code == 408 && request &&
               request->hr_proto == httpd->consts.http_11)
                   bozo_printf(httpd, "Connection: close\r\n");
         bozo_printf(httpd, "\r\n");          bozo_printf(httpd, "\r\n");
         /* According to the RFC 2616 sec. 9.4 HEAD method MUST NOT return a          /* According to the RFC 2616 sec. 9.4 HEAD method MUST NOT return a
          * message-body in the response */           * message-body in the response */
Line 2136  bozodgetln(bozohttpd_t *httpd, int fd, s
Line 2379  bozodgetln(bozohttpd_t *httpd, int fd, s
   
         }          }
         httpd->getln_buffer[len] = '\0';          httpd->getln_buffer[len] = '\0';
         debug((httpd, DEBUG_OBESE, "bozodgetln returns: ``%s'' with len %zd",          debug((httpd, DEBUG_OBESE, "bozodgetln returns: '%s' with len %zd",
                httpd->getln_buffer, len));                 httpd->getln_buffer, len));
         *lenp = len;          *lenp = len;
         return httpd->getln_buffer;          return httpd->getln_buffer;
Line 2151  bozorealloc(bozohttpd_t *httpd, void *pt
Line 2394  bozorealloc(bozohttpd_t *httpd, void *pt
         if (p)          if (p)
                 return p;                  return p;
   
         (void)bozo_http_error(httpd, 500, NULL, "memory allocation failure");          bozo_http_error(httpd, 500, NULL, "memory allocation failure");
         exit(EXIT_FAILURE);          exit(EXIT_FAILURE);
 }  }
   
Line 2164  bozomalloc(bozohttpd_t *httpd, size_t si
Line 2407  bozomalloc(bozohttpd_t *httpd, size_t si
         if (p)          if (p)
                 return p;                  return p;
   
         (void)bozo_http_error(httpd, 500, NULL, "memory allocation failure");          bozo_http_error(httpd, 500, NULL, "memory allocation failure");
         exit(EXIT_FAILURE);          exit(EXIT_FAILURE);
 }  }
   
Line 2180  bozostrdup(bozohttpd_t *httpd, bozo_http
Line 2423  bozostrdup(bozohttpd_t *httpd, bozo_http
         if (!request)          if (!request)
                 bozoerr(httpd, EXIT_FAILURE, "strdup");                  bozoerr(httpd, EXIT_FAILURE, "strdup");
   
         (void)bozo_http_error(httpd, 500, request, "memory allocation failure");          bozo_http_error(httpd, 500, request, "memory allocation failure");
         exit(EXIT_FAILURE);          exit(EXIT_FAILURE);
 }  }
   
Line 2202  bozo_init_httpd(bozohttpd_t *httpd)
Line 2445  bozo_init_httpd(bozohttpd_t *httpd)
   
         /* error buffer for bozo_http_error() */          /* error buffer for bozo_http_error() */
         if ((httpd->errorbuf = malloc(BUFSIZ)) == NULL) {          if ((httpd->errorbuf = malloc(BUFSIZ)) == NULL) {
                 (void) fprintf(stderr,                  fprintf(stderr,
                         "bozohttpd: memory_allocation failure\n");                          "bozohttpd: memory_allocation failure\n");
                 return 0;                  return 0;
         }          }
Line 2216  bozo_init_httpd(bozohttpd_t *httpd)
Line 2459  bozo_init_httpd(bozohttpd_t *httpd)
 int  int
 bozo_init_prefs(bozohttpd_t *httpd, bozoprefs_t *prefs)  bozo_init_prefs(bozohttpd_t *httpd, bozoprefs_t *prefs)
 {  {
           int rv = 0;
   
         /* make sure everything is clean */          /* make sure everything is clean */
         (void) memset(prefs, 0x0, sizeof(*prefs));          (void) memset(prefs, 0x0, sizeof(*prefs));
   
         /* set up default values */          /* set up default values */
         if (!bozo_set_pref(httpd, prefs, "server software", SERVER_SOFTWARE) ||          if (!bozo_set_pref(httpd, prefs, "server software", SERVER_SOFTWARE))
             !bozo_set_pref(httpd, prefs, "index.html", INDEX_HTML) ||                  rv = 1;
             !bozo_set_pref(httpd, prefs, "public_html", PUBLIC_HTML))          if (!bozo_set_pref(httpd, prefs, "index.html", INDEX_HTML))
                 return 0;                  rv = 1;
           if (!bozo_set_pref(httpd, prefs, "public_html", PUBLIC_HTML))
                   rv = 1;
           if (!bozo_set_pref(httpd, prefs, "ssl timeout", SSL_TIMEOUT))
                   rv = 1;
           if (!bozo_set_pref(httpd, prefs, "initial timeout", INITIAL_TIMEOUT))
                   rv = 1;
           if (!bozo_set_pref(httpd, prefs, "header timeout", HEADER_WAIT_TIME))
                   rv = 1;
           if (!bozo_set_pref(httpd, prefs, "request timeout", TOTAL_MAX_REQ_TIME))
                   rv = 1;
   
         return 1;          return rv;
 }  }
   
 /* set default values */  /* set default values */
Line 2318  bozo_setup(bozohttpd_t *httpd, bozoprefs
Line 2573  bozo_setup(bozohttpd_t *httpd, bozoprefs
         if ((cp = bozo_get_pref(prefs, "public_html")) != NULL) {          if ((cp = bozo_get_pref(prefs, "public_html")) != NULL) {
                 httpd->public_html = bozostrdup(httpd, NULL, cp);                  httpd->public_html = bozostrdup(httpd, NULL, cp);
         }          }
           if ((cp = bozo_get_pref(prefs, "ssl timeout")) != NULL) {
                   httpd->ssl_timeout = atoi(cp);
           }
           if ((cp = bozo_get_pref(prefs, "initial timeout")) != NULL) {
                   httpd->initial_timeout = atoi(cp);
           }
           if ((cp = bozo_get_pref(prefs, "header timeout")) != NULL) {
                   httpd->header_timeout = atoi(cp);
           }
           if ((cp = bozo_get_pref(prefs, "request timeout")) != NULL) {
                   httpd->request_timeout = atoi(cp);
           }
         httpd->server_software =          httpd->server_software =
             bozostrdup(httpd, NULL, bozo_get_pref(prefs, "server software"));              bozostrdup(httpd, NULL, bozo_get_pref(prefs, "server software"));
         httpd->index_html =          httpd->index_html =

Legend:
Removed from v.1.56.2.8  
changed lines
  Added in v.1.56.2.8.2.3

CVSweb <webmaster@jp.NetBSD.org>