[BusyBox] httpd setgid support and CGI SERVER_ADDR var

John McCarthy jgmcc at magma.ca
Tue Oct 21 20:42:18 UTC 2003


Hi Vladimir,

On Mon, 2003-10-20 at 09:05, Vladimir N. Oleynik wrote:
> John,
> 
> > httpd supports setting the uid but not the gid after performing
> > privileged operations.  I've added a -g switch to do this as it is
> > needed by my CGI application.  It is also missing usage text for the -h
> > option which I've added as part of the same patch.
> 
>  >  #define OPT_SETUID      (1<<(5+OPT_INC_1+OPT_INC_2))
>  > +#define OPT_SETGID      (1<<(5+OPT_INC_1+OPT_INC_2))
> 
> This part have small mistake, must change 5 to 6.

Oops, my bad.  Fixed.

> > httpd does not set the SERVER_ADDR or SERVER_NAME env vars for CGI
> > programs.  This breaks a CGI engine I'm using that requires this to
> > generate HTTP redirect requests.  With BOA I'm getting both sent as the
> > IP addr of the server, but the name is specified in a config. file so
> > this should probably be a command line arg. in httpd.  For now I just
> > set both to the string representation of the server IP addr from the
> > server socket. Oops, that reminds me, I need to do the same in the
> > inetd_server_only side as well--that will be in the next patch.
> 
> Hmm. Best method: call httpd with setted and exported this environs,
> and patch httpd to don`t unset this vars, see saving PATH code.

Sounds good.  I've done that and included a default of gethostname() as
well.  So SERVER_NAME gets set to:
	   SERVER_NAME env var
	or gethostname()
	or calculated SERVER_ADDR value
which ever is found first.  Does that sound ok?

Where should this SERVER_NAME env variable feature be documented?

I've updated my patch (including the missing setup for the INETD_ONLY
case).  The usage.h patch is unchanged but I've included it for
completeness. I've only verified that this compiles at this point as my
test machine is tied up at the moment.  Thought I'd pass along what I
have at this point in any case.


Cheers,
John McCarthy.
-------------- next part --------------
--- ../../busybox-1.00-cvs/busybox/networking/httpd.c	2003-10-06 13:36:22.000000000 -0400
+++ httpd.c	2003-10-21 15:44:18.000000000 -0400
@@ -106,6 +106,7 @@
 #include <time.h>
 #include <unistd.h>        /* for close             */
 #include <signal.h>
+#include <sys/param.h>     /* for MAXHOSTNAMELEN    */
 #include <sys/types.h>
 #include <sys/socket.h>    /* for connect and socket*/
 #include <netinet/in.h>    /* for sockaddr_in       */
@@ -182,7 +183,7 @@
 void bb_show_usage(void)
 {
   fprintf(stderr, "Usage: %s [-p <port>] [-c configFile] [-d/-e <string>] "
-		  "[-r realm] [-u user] [-h homedir]\n", bb_applet_name);
+		  "[-r realm] [-u user] [-g group] [-h homedir]\n", bb_applet_name);
   exit(1);
 }
 #endif
@@ -231,6 +232,11 @@
   unsigned port;           /* server initial port and for
 			      set env REMOTE_PORT */
 
+#if defined(CONFIG_FEATURE_HTTPD_CGI) || defined(DEBUG)
+  unsigned int loc_ip;
+  char loc_ip_str[16];     /* for set env SERVER_ADDR */
+#endif
+
   const char *found_mime_type;
   off_t ContentLength;          /* -1 - unknown */
   time_t last_mod;
@@ -1059,6 +1065,7 @@
   int inFd;
   int outFd;
   int firstLine = 1;
+  char *server_name = NULL;
 
   do {
     if (pipe(fromCgi) != 0) {
@@ -1131,6 +1138,25 @@
       /* set SCRIPT_NAME as full path: /cgi-bin/dirs/script.cgi */
       addEnv("SCRIPT_NAME",    "",         purl);
       addEnv("QUERY_STRING",   "",         urlArgs);
+
+      addEnv("SERVER",         "ADDR",     config->loc_ip_str);
+      server_name = getenv("SERVER_NAME");
+      if(server_name && server_name[0])
+              /* Use SERVER_NAME env variable if available */
+	      addEnv("SERVER",         "NAME",     server_name);
+      else {
+              char hname[MAXHOSTNAMELEN+1];
+
+	      gethostname(hname, MAXHOSTNAMELEN);
+              hname[MAXHOSTNAMELEN] = '\0';
+	      if(hname[0])
+		      /* or use the hostname() */
+		      addEnv("SERVER",         "NAME",     hname);
+	      else
+		      /* as a last resort, use the ipaddr as a string */
+		      addEnv("SERVER",         "NAME",     config->loc_ip_str);
+      }
+
       addEnv("SERVER",         "SOFTWARE", httpdVersion);
       addEnv("SERVER",         "PROTOCOL", "HTTP/1.0");
       addEnv("GATEWAY_INTERFACE", "",      "CGI/1.1");
@@ -1747,14 +1773,17 @@
       if (FD_ISSET(server, &readfd)) {
 	int on;
 	struct sockaddr_in fromAddr;
+        struct sockaddr_in myAddr;
 
 	socklen_t fromAddrLen = sizeof(fromAddr);
+        socklen_t myAddrLen = sizeof(myAddr);
 	int s = accept(server,
 		       (struct sockaddr *)&fromAddr, &fromAddrLen);
 
 	if (s < 0) {
 	    continue;
 	}
+
 	config->accepted_socket = s;
 	config->rmt_ip = ntohl(fromAddr.sin_addr.s_addr);
 #if defined(CONFIG_FEATURE_HTTPD_CGI) || defined(DEBUG)
@@ -1764,6 +1793,16 @@
 		(unsigned char)(config->rmt_ip >> 8),
 				config->rmt_ip & 0xff);
 	config->port = ntohs(fromAddr.sin_port);
+
+        memset(&myAddr, 0, myAddrLen);
+        getsockname(s, (struct sockaddr *)&myAddr, &myAddrLen);
+
+	config->loc_ip = ntohl(myAddr.sin_addr.s_addr);
+	sprintf(config->loc_ip_str, "%u.%u.%u.%u",
+		(unsigned char)(config->loc_ip >> 24),
+		(unsigned char)(config->loc_ip >> 16),
+		(unsigned char)(config->loc_ip >> 8),
+				config->loc_ip & 0xff);
 #ifdef DEBUG
 	if (config->debugHttpd) {
 	    bb_error_msg("connection from IP=%s, port %u\n",
@@ -1799,7 +1838,9 @@
 static int miniHttpd(void)
 {
   struct sockaddr_in fromAddrLen;
+  struct sockaddr_in myAddr;
   socklen_t sinlen = sizeof (struct sockaddr_in);
+  socklen_t myAddrLen = sizeof(myAddr);
 
   getpeername (0, (struct sockaddr *)&fromAddrLen, &sinlen);
   config->rmt_ip = ntohl(fromAddrLen.sin_addr.s_addr);
@@ -1809,6 +1850,15 @@
 		(unsigned char)(config->rmt_ip >> 16),
 		(unsigned char)(config->rmt_ip >> 8),
 				config->rmt_ip & 0xff);
+
+  memset(&myAddr, 0, myAddrLen);
+  getsockname(0, (struct sockaddr *)&myAddr, &myAddrLen);
+
+  config->loc_ip = ntohl(myAddr.sin_addr.s_addr);
+  sprintf(config->loc_ip_str, "%u.%u.%u.%u",
+	(unsigned char)(config->loc_ip >> 24),
+	(unsigned char)(config->loc_ip >> 16),
+	(unsigned char)(config->loc_ip >> 8),
 #endif
   config->port = ntohs(fromAddrLen.sin_port);
   handleIncoming();
@@ -1853,7 +1903,7 @@
 #ifndef CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY
 				"p:v"
 #ifdef CONFIG_FEATURE_HTTPD_SETUID
-				"u:"
+				"u:g:"
 #endif
 #endif /* CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY */
 					;
@@ -1867,6 +1917,7 @@
 #define OPT_PORT        (1<<(3+OPT_INC_1+OPT_INC_2))
 #define OPT_DEBUG       (1<<(4+OPT_INC_1+OPT_INC_2))
 #define OPT_SETUID      (1<<(5+OPT_INC_1+OPT_INC_2))
+#define OPT_SETGID      (1<<(6+OPT_INC_1+OPT_INC_2))
 
 
 #ifdef HTTPD_STANDALONE
@@ -1891,7 +1942,9 @@
 
 #ifdef CONFIG_FEATURE_HTTPD_SETUID
   const char *s_uid;
+  const char *s_gid;
   long uid = -1;
+  long gid = -1;
 #endif
 
 #ifdef CONFIG_FEATURE_HTTPD_AUTH_MD5
@@ -1924,6 +1977,7 @@
 			, &s_port
 #ifdef CONFIG_FEATURE_HTTPD_SETUID
 			, &s_uid
+			, &s_gid
 #endif
 #endif
     );
@@ -1958,6 +2012,14 @@
 		uid = my_getpwnam(s_uid);
 	}
       }
+    if(opt & OPT_SETGID) {
+	char *e;
+	gid = strtol(s_gid, &e, 0);
+	if(*e != '\0') {
+		/* not integer */
+		gid = my_getpwnamegid(s_gid);
+	}
+      }
 #endif
 #endif
 
@@ -1968,6 +2030,8 @@
   server = openServer();
 # ifdef CONFIG_FEATURE_HTTPD_SETUID
   /* drop privilegies */
+  if(gid > 0)
+	setgid(gid);
   if(uid > 0)
 	setuid(uid);
 # endif
@@ -1976,12 +2040,18 @@
 #ifdef CONFIG_FEATURE_HTTPD_CGI
    {
 	char *p = getenv("PATH");
+	char *s = getenv("SERVER_NAME");
 	if(p) {
 		p = bb_xstrdup(p);
 	}
+	if(s) {
+		s = bb_xstrdup(s);
+	}
 	clearenv();
 	if(p)
 		setenv("PATH", p, 1);
+	if(s)
+		setenv("SERVER_NAME", s, 1);
 # ifndef CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY
 	addEnvPort("SERVER");
 # endif
-------------- next part --------------
--- busybox-1.00-pre3/include/usage.h	2003-08-29 10:18:26.000000000 -0400
+++ busybox-1.00-pre3-s1/include/usage.h	2003-10-17 14:48:52.000000000 -0400
@@ -959,25 +959,30 @@
   #define USAGE_HTTPD_STANDALONE(a) a
   #ifdef CONFIG_FEATURE_HTTPD_SETUID
     #define USAGE_HTTPD_SETUID(a) a
+    #define USAGE_HTTPD_SETGID(a) a
   #else
     #define USAGE_HTTPD_SETUID(a)
+    #define USAGE_HTTPD_SETGID(a)
   #endif
 #endif
 #define httpd_trivial_usage \
 	"[-c <conf file>]" \
 	USAGE_HTTPD_STANDALONE(" [-p <port>]") \
 	USAGE_HTTPD_SETUID(" [-u user]") \
+	USAGE_HTTPD_SETGID(" [-g group]") \
 	USAGE_HTTPD_BASIC_AUTH(" [-r <realm>]") \
 	USAGE_HTTPD_AUTH_MD5(" [-m pass]") \
-	" [-d/-e <string>]"
+	" [-h dir] [-d/-e <string>]"
 #define httpd_full_usage \
        "Listens for incoming http server requests.\n"\
        "Options:\n" \
        "\t-c FILE\tSpecifies configuration file. (default httpd.conf)\n" \
        USAGE_HTTPD_STANDALONE("\t-p PORT\tServer port (default 80)\n") \
        USAGE_HTTPD_SETUID("\t-u USER\tSet uid to USER after listening privilegies port\n") \
+       USAGE_HTTPD_SETGID("\t-g GROUP\tSet gid to GROUP after listening privilegies port\n") \
        USAGE_HTTPD_BASIC_AUTH("\t-r REALM\tAuthentication Realm for Basic Authentication\n") \
        USAGE_HTTPD_AUTH_MD5("\t-m PASS\tCrypt PASS with md5 algorithm\n") \
+       "\t-h DIR\tSet document root for web content to DIR\n" \
        "\t-e STRING\tHtml encode STRING\n" \
        "\t-d STRING\tURL decode STRING"
 


More information about the busybox mailing list