[BusyBox] httpd patches

Vladimir N. Oleynik dzo at simtreas.ru
Mon Apr 7 04:41:22 UTC 2003


Glenn,

> > I found restore old algorithms for addEnvCgi(), base64ToBin[] and many
> > others :(
> 
> addEnvCgi() I didn't change unless it was formatting.

What for you add non-standard features?
Your code easily turns out inside the CGI script.

CGI_ARGLIST_=`env | sed "{
s/^CGI_\(..*\)=.*/\1/
t ok
/.*/d
: ok
}

> base64ToBin() was broken for certain combinations of input.  

I found problem. I ignored '=' padding, but require set as '\0';

> Rather than
> debug the new version I put in the old one.  The old one was smaller code
> size 

Only 3 bytes.
New version base64ToBin() have size:

  text    data     bss     dec     hex filename
    172       0       0     172      ac b64_vodz.o
    189       0       0     189      bd b64_glen.o

with my old algorithm without your ascii comparing:
if ((newch < '+') || (newch > 'z'))
 
> >
> > You removed my sorting and my not trivial logic from conf_parse :(
> >
> 
> The sorting is still there and should behave the same as your version.  

Example:

global conf (administrative) have:
A:10.
D:*

subdir conf (users) have:
A:10.
A:172.20.
D:*

My result:
A:10.
D:*

Your result:
A:10.
A:172.20 # open by user!
x:*


--w
vodz
-------------- next part --------------
diff -ru busybox.orig/networking/httpd.c busybox/networking/httpd.c
--- busybox.orig/networking/httpd.c	Wed Mar 19 12:12:37 2003
+++ busybox/networking/httpd.c	Mon Apr  7 08:31:56 2003
@@ -42,7 +42,7 @@
  * The server can also be invoked as a url arg decoder and html text encoder
  * as follows:
  *  foo=`httpd -d $foo`             # decode "Hello%20World" as "Hello World"
- *  bar=`httpd -e "<Hello World>"`  # encode as "%3CHello%20World%3E"
+ *  bar=`httpd -e "<Hello World>"`  # encode as "&#60Hello&#32World&#62"
  *
  * httpd.conf has the following format:
 
@@ -120,30 +120,29 @@
 #include "busybox.h"
 
 
-static const char httpdVersion[] = "busybox httpd/1.20 31-Jan-2003";
-static const char default_patch_httpd_conf[] = "/etc";
+static const char httpdVersion[] = "busybox httpd/1.22 05-Apr-2003";
+static const char default_path_httpd_conf[] = "/etc";
 static const char httpd_conf[] = "httpd.conf";
 static const char home[] = "/www";
 
-// Note: xfuncs are not used because we want the server to keep running
+// Note: bussybox xfuncs are not used because we want the server to keep running
 //       if something bad happens due to a malformed user request.
 //       As a result, all memory allocation after daemonize
 //       is checked rigorously
 
 //#define DEBUG 1
 
-/* Configure options, disabled by default as nonstandart httpd feature */
+/* Configure options, disabled by default as custom httpd feature */
+
+/* disabled as optional features */
 //#define CONFIG_FEATURE_HTTPD_SET_CGI_VARS_TO_ENV
 //#define CONFIG_FEATURE_HTTPD_ENCODE_URL_STR
-//#define CONFIG_FEATURE_HTTPD_DECODE_URL_STR
-
-/* disabled as not necessary feature */
 //#define CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV
 //#define CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
 //#define CONFIG_FEATURE_HTTPD_SETUID
 //#define CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
 
-/* If seted this you can use this server from internet superserver only */
+/* If set, use this server from internet superserver only */
 //#define CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY
 
 /* You can use this server as standalone, require libbb.a for linking */
@@ -160,7 +159,6 @@
 #undef CONFIG_FEATURE_HTTPD_BASIC_AUTH
 #undef CONFIG_FEATURE_HTTPD_SET_CGI_VARS_TO_ENV
 #undef CONFIG_FEATURE_HTTPD_ENCODE_URL_STR
-#undef CONFIG_FEATURE_HTTPD_DECODE_URL_STR
 #undef CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV
 #undef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
 #undef CONFIG_FEATURE_HTTPD_CGI
@@ -170,7 +168,6 @@
 #define CONFIG_FEATURE_HTTPD_BASIC_AUTH
 #define CONFIG_FEATURE_HTTPD_SET_CGI_VARS_TO_ENV
 #define CONFIG_FEATURE_HTTPD_ENCODE_URL_STR
-#define CONFIG_FEATURE_HTTPD_DECODE_URL_STR
 #define CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV
 #define CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
 #define CONFIG_FEATURE_HTTPD_CGI
@@ -183,7 +180,7 @@
 void bb_show_usage(void)
 {
   fprintf(stderr, "Usage: %s [-p <port>] [-c configFile] [-d/-e <string>] "
-		  "[-r realm] [-u user]\n", bb_applet_name);
+		  "[-r realm] [-u user] [-h homedir ]\n", bb_applet_name);
   exit(1);
 }
 #endif
@@ -423,7 +420,7 @@
 	cf = p0 = alloca(strlen(path) + sizeof(httpd_conf) + 2);
 	if(p0 == NULL) {
 	    if(flag == FIRST_PARSE)
-		bb_error_msg_and_die(bb_msg_memory_exhausted);
+		bb_error_msg_and_die(bb_memory_exhausted);
 	    return;
 	}
 	sprintf(p0, "%s/%s", path, httpd_conf);
@@ -432,7 +429,7 @@
     while((f = fopen(cf, "r")) == NULL) {
 	if(flag != FIRST_PARSE)
 	    return;                 /* subdir config not found */
-	if(p0 == NULL)              /* if -c option gived */
+	if(p0 == NULL)              /* if -c option given */
 		bb_perror_msg_and_die("%s", cf);
 	p0 = NULL;
 	cf = httpd_conf;            /* set -c ./httpd_conf */
@@ -459,7 +456,7 @@
 	}
     }
 
-	/* This could stand some work */
+    /* This could stand some work */
     while ( (p0 = fgets(buf, 80, f)) != NULL) {
 	char *p;
 	char *colon;
@@ -543,7 +540,7 @@
 	pcur = alloca((n + 1) * sizeof(Htaccess *));
 	if(pcur == NULL) {
 	    if(flag == FIRST_PARSE)
-		bb_error_msg_and_die(bb_msg_memory_exhausted);
+		bb_error_msg_and_die(bb_memory_exhausted);
 	    return;
 	}
 	n = 0;
@@ -602,7 +599,6 @@
 }
 #endif          /* CONFIG_FEATURE_HTTPD_ENCODE_URL_STR */
 
-#ifdef CONFIG_FEATURE_HTTPD_DECODE_URL_STR
 /****************************************************************************
  *
  > $Function: decodeString()
@@ -615,20 +611,21 @@
  *
  * $Parameters:
  *      (char *) string . . . The first string to decode.
+ *      (int)    flag   . . . 1 if require decode '+' as ' ' for CGI
  *
  * $Return: (char *)  . . . . A pointer to the decoded string (same as input).
  *
  * $Errors: None
  *
  ****************************************************************************/
-static char *decodeString(char *string)
+static char *decodeString(char *string, int flag_plus_to_space)
 {
   /* note that decoded string is always shorter than original */
   char *orig = string;
   char *ptr = string;
   while (*ptr)
   {
-    if (*ptr == '+')    { *string++ = ' '; ptr++; }
+    if (*ptr == '+' && flag_plus_to_space)    { *string++ = ' '; ptr++; }
     else if (*ptr != '%') *string++ = *ptr++;
     else  {
       unsigned int value;
@@ -640,7 +637,6 @@
   *string = '\0';
   return orig;
 }
-#endif          /* CONFIG_FEATURE_HTTPD_DECODE_URL_STR */
 
 
 #ifdef CONFIG_FEATURE_HTTPD_CGI
@@ -730,7 +726,7 @@
     args = strchr(value, '&');
     if (args)
 	*args++ = 0;
-    addEnv("CGI", name, decodeString(value));
+    addEnv("CGI", name, decodeString(value, 1));
   }
   free(memargs);
 }
@@ -758,33 +754,28 @@
  ****************************************************************************/
 static void decodeBase64(char *Data)
 {
-  int i = 0;
   static const char base64ToBin[] =
-    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
 
   const unsigned char *in = Data;
   // The decoded size will be at most 3/4 the size of the encoded
   unsigned long ch = 0;
+  int i = 0;
 
   while (*in) {
-    unsigned char conv = 0;
-
-    while (*in) {
-      const char *p64;
+    const char *p64 = strchr(base64ToBin, *in++);
 
-      p64 = strchr(base64ToBin, *in++);
-      if(p64 == NULL)
-	continue;
-      conv = (p64 - base64ToBin);
-      break;
-    }
-    ch = (ch << 6) | conv;
-    i++;
-    if (i== 4) {
-      *Data++ = (char) (ch >> 16);
-      *Data++ = (char) (ch >> 8);
-      *Data++ = (char) ch;
-      i = 0;
+    if(p64) {
+	if(*p64 == '=')         /* padding, set 0 */
+	    p64 = base64ToBin;
+	ch = (ch << 6) | (p64 - base64ToBin);
+	i++;
+	if (i == 4) {
+	    *Data++ = (char) (ch >> 16);
+	    *Data++ = (char) (ch >> 8);
+	    *Data++ = (char) ch;
+	    i = 0;
+	}
     }
   }
   *Data = 0;
@@ -882,12 +873,10 @@
 	"Date: %s\r\nConnection: close\r\n",
 	  responseNum, responseString, config->found_mime_type, timeStr);
 
-#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
   if (responseNum == HTTP_UNAUTHORIZED) {
     len += sprintf(buf+len, "WWW-Authenticate: Basic realm=\"%s\"\r\n",
 							    config->realm);
   }
-#endif
   if (config->ContentLength != -1) {    /* file */
     strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&config->last_mod));
     len += sprintf(buf+len, "Last-Modified: %s\r\n%s %ld\r\n",
@@ -1382,6 +1371,7 @@
     *purl = ' ';
     count = sscanf(purl, " %[^ ] HTTP/%d.%*d", buf, &blank);
 
+    decodeString(buf, 0);
     if (count < 1 || buf[0] != '/') {
       /* Garbled request/URL */
       goto BAD_REQUEST;
@@ -1394,10 +1384,8 @@
     strcpy(url, buf);
     /* extract url args if present */
     urlArgs = strchr(url, '?');
-    if (urlArgs) {
-      *urlArgs++ = 0;   /* next code can set '/' to this pointer,
-			   but CGI script can`t be a directory */
-    }
+    if (urlArgs)
+      *urlArgs++ = 0;
 
     /* algorithm stolen from libbb bb_simplify_path(),
        but don`t strdup and reducing trailing slash */
@@ -1644,6 +1632,9 @@
 		exit(0);
 	}
 	close(s);
+#ifdef TEST
+       return 0;  // exit after processing one request
+#endif
       }
     }
   } // while (1)
@@ -1682,7 +1673,7 @@
 	sigemptyset(&sa.sa_mask);
 	sa.sa_flags = SA_RESTART;
 	sigaction(SIGHUP, &sa, NULL);
-	parse_conf(default_patch_httpd_conf,
+	parse_conf(default_path_httpd_conf,
 		    sig == SIGHUP ? SIGNALED_PARSE : FIRST_PARSE);
 }
 #endif
@@ -1694,6 +1685,10 @@
 #endif
 {
   const char *home_httpd = home;
+#ifdef TEST
+  const char *testArg1 = 0;
+  const char *testArg2 = 0;
+#endif
 
 #ifndef CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY
   int server;
@@ -1716,22 +1711,22 @@
 
   /* check if user supplied a port number */
   for (;;) {
-    int c = getopt( argc, argv, "c:h:"
+    int c = getopt( argc, argv, "c:d:h:"
 #ifndef CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY
 				"p:v"
 #endif
 #ifdef CONFIG_FEATURE_HTTPD_ENCODE_URL_STR
 		"e:"
 #endif
-#ifdef CONFIG_FEATURE_HTTPD_DECODE_URL_STR
-		"d:"
-#endif
 #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
 		"r:"
 #endif
 #ifdef CONFIG_FEATURE_HTTPD_SETUID
 		"u:"
 #endif
+#ifdef TEST
+		"t:"
+#endif
     );
     if (c == EOF) break;
     switch (c) {
@@ -1751,11 +1746,9 @@
 	bb_error_msg_and_die("invalid %s for -p", optarg);
       break;
 #endif
-#ifdef CONFIG_FEATURE_HTTPD_DECODE_URL_STR
     case 'd':
-      printf("%s", decodeString(optarg));
+      printf("%s", decodeString(optarg, 1));
       return 0;
-#endif
 #ifdef CONFIG_FEATURE_HTTPD_ENCODE_URL_STR
     case 'e':
       printf("%s", encodeString(optarg));
@@ -1779,6 +1772,12 @@
       }
       break;
 #endif
+#ifdef TEST
+    case 't':
+      if (testArg1 == 0) testArg1 = optarg;
+      else testArg2 = optarg;
+      break;
+#endif
     default:
       bb_error_msg("%s", httpdVersion);
       bb_show_usage();
@@ -1803,8 +1802,16 @@
 #ifdef CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
   sighup_handler(0);
 #else
-  parse_conf(default_patch_httpd_conf, FIRST_PARSE);
+  parse_conf(default_path_httpd_conf, FIRST_PARSE);
 #endif
+
+#ifdef TEST
+  if (testArg1) {
+	 if (strcmp(testArg1,"ip") == 0)
+		    testArg1 = 0;
+	 return printf("%d\n", checkPerm(testArg1, testArg2));
+  }
+ #endif
 
 #ifndef CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY
   if (!config->debugHttpd) {


More information about the busybox mailing list