[PATCH] httpd: Pass custom HTTP headers to CGI scripts

Alexander Vickberg wickbergster at gmail.com
Thu Mar 28 17:04:10 UTC 2019


This patch creates a list of unmatched HTTP headers and sets up environment
variables before running the CGI script. The variables will be named
HTTP_<filtered name> where the filtered name is the header name capitalized
and all characters not matching [a-z] | [A-Z] | [0-9] replaced with '_'.

Bloatcheck
function                                             old     new   delta
handle_incoming_and_exit                            2859    3116    +257
send_cgi_and_exit                                   1016    1086     +70
static.last                                            -       8      +8
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 2/0 up/down: 335/0)             Total: 335
bytes
   text    data     bss     dec     hex filename
1017044   17695    1888 1036627   fd153 busybox_old
1017371   17695    1896 1036962   fd2a2 busybox_unstripped

diff --git a/networking/httpd.c b/networking/httpd.c
index b52526a78..f29c0a6a0 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -305,6 +305,12 @@ typedef struct Htaccess_Proxy {
  char *url_to;
 } Htaccess_Proxy;

+typedef struct HTTP_Header {
+    struct HTTP_Header *next;
+    char *name;
+    char *value;
+} HTTP_Header;
+
 enum {
  HTTP_OK = 200,
  HTTP_PARTIAL_CONTENT = 206,
@@ -417,6 +423,7 @@ struct globals {
  IF_FEATURE_HTTPD_CGI(char *host;)
  IF_FEATURE_HTTPD_CGI(char *http_accept;)
  IF_FEATURE_HTTPD_CGI(char *http_accept_language;)
+ IF_FEATURE_HTTPD_CGI(HTTP_Header *hdr_list;)

  off_t file_size;        /* -1 - unknown */
 #if ENABLE_FEATURE_HTTPD_RANGES
@@ -527,6 +534,13 @@ static ALWAYS_INLINE void
free_Htaccess_IP_list(Htaccess_IP **pptr)
  free_llist((has_next_ptr**)pptr);
 }

+#if ENABLE_FEATURE_HTTPD_CGI
+static ALWAYS_INLINE void free_HTTP_Header_list(HTTP_Header **pptr)
+{
+ free_llist((has_next_ptr**)pptr);
+}
+#endif
+
 /* Returns presumed mask width in bits or < 0 on error.
  * Updates strp, stores IP at provided pointer */
 static int scan_ip(const char **strp, unsigned *ipp, unsigned char endc)
@@ -1554,6 +1568,18 @@ static void send_cgi_and_exit(
  /* setenv1("SERVER_NAME", safe_gethostname()); - don't do this,
  * just run "env SERVER_NAME=xyz httpd ..." instead */

+ if (G.hdr_list) {
+ HTTP_Header *cur = G.hdr_list;
+ do {
+ setenv1(cur->name, cur->value);
+ //bb_error_msg("test: '%s = %s'", cur->name, cur->value);
+ free(cur->name);
+ free(cur->value);
+ cur = cur->next;
+ } while (cur != G.hdr_list);
+ free_HTTP_Header_list(&G.hdr_list);
+ }
+
  xpiped_pair(fromCgi);
  xpiped_pair(toCgi);

@@ -2326,6 +2352,9 @@ static void handle_incoming_and_exit(const
len_and_sockaddr *fromAddr)
  }
 #endif
 #if ENABLE_FEATURE_HTTPD_BASIC_AUTH
+#if ENABLE_FEATURE_HTTPD_CGI || ENABLE_FEATURE_HTTPD_PROXY
+ else
+#endif
  if (STRNCASECMP(iobuf, "Authorization:") == 0) {
  /* We only allow Basic credentials.
  * It shows up as "Authorization: Basic <user>:<passwd>" where
@@ -2341,6 +2370,9 @@ static void handle_incoming_and_exit(const
len_and_sockaddr *fromAddr)
  }
 #endif
 #if ENABLE_FEATURE_HTTPD_RANGES
+#if ENABLE_FEATURE_HTTPD_CGI || ENABLE_FEATURE_HTTPD_PROXY ||
ENABLE_FEATURE_HTTPD_BASIC_AUTH
+ else
+#endif
  if (STRNCASECMP(iobuf, "Range:") == 0) {
  /* We know only bytes=NNN-[MMM] */
  char *s = skip_whitespace(iobuf + sizeof("Range:")-1);
@@ -2358,6 +2390,9 @@ static void handle_incoming_and_exit(const
len_and_sockaddr *fromAddr)
  }
 #endif
 #if ENABLE_FEATURE_HTTPD_GZIP
+#if ENABLE_FEATURE_HTTPD_CGI || ENABLE_FEATURE_HTTPD_PROXY ||
ENABLE_FEATURE_HTTPD_BASIC_AUTH || ENABLE_FEATURE_HTTPD_GZIP
+ else
+#endif
  if (STRNCASECMP(iobuf, "Accept-Encoding:") == 0) {
  /* Note: we do not support "gzip;q=0"
  * method of _disabling_ gzip
@@ -2373,6 +2408,43 @@ static void handle_incoming_and_exit(const
len_and_sockaddr *fromAddr)
  //}
  }
  }
+#endif
+#if ENABLE_FEATURE_HTTPD_CGI
+ else {
+ static HTTP_Header *last;
+ HTTP_Header *cur = xzalloc(sizeof(HTTP_Header));
+ char *after_colon = strchr(iobuf, ':');
+ char *ch = iobuf;
+
+ if (!after_colon)
+     continue;
+
+ *after_colon++ = '\0';
+
+ while (*ch) {
+ if (isalpha(*ch))
+ *ch &= ~0x20;
+ else if (!isdigit(*ch))
+     *ch = '_';
+ ch++;
+ }
+
+ cur->name = xmalloc(sizeof("HTTP_")+strlen(iobuf));
+ memcpy(cur->name, "HTTP_", sizeof("HTTP_")-1);
+ strcpy(cur->name + sizeof("HTTP_")-1, iobuf);
+ cur->value = xstrdup(skip_whitespace(after_colon));
+
+ /* Insert new header into header list */
+ if (!G.hdr_list) {
+ G.hdr_list = cur;
+ cur->next = G.hdr_list;
+ last = cur;
+ } else {
+ cur->next = G.hdr_list;
+ last->next = cur;
+ last = cur;
+ }
+ }
 #endif
  } /* while extra header reading */
  }
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.busybox.net/pipermail/busybox/attachments/20190328/bf067774/attachment.html>


More information about the busybox mailing list