commit 10148c62cc2a85237ae1b21eba67787e3bd05bbc
Author: Benjamin Cohen <bencoh@notk.org>
Date:   Fri Feb 4 12:54:41 2011 +0100

    Drop privs.

diff --git a/hts.c b/hts.c
index c318fba..35aef82 100644
--- a/hts.c
+++ b/hts.c
@@ -13,6 +13,29 @@ two-way data path tunneled in HTTP requests.
 #include <signal.h>
 #include <sys/poll_.h>
 #include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <pwd.h>
+
+int changepriv(const char *user) {
+	struct passwd *pw;
+	int rv;
+
+	pw = getpwnam(user);
+	if (!pw)
+		return -1;
+
+	rv = setgid(pw->pw_gid);
+	if (rv == -1)
+		return -2;
+
+	rv = setuid(pw->pw_uid);
+	if (rv == -1)
+		return -3;
+
+	return 0;
+}
+
 
 #include "common.h"
 
@@ -31,6 +54,7 @@ typedef struct
   int strict_content_length;
   int keep_alive;
   int max_connection_age;
+  char *user;
 } Arguments;
 
 int debug_level = 0;
@@ -67,6 +91,7 @@ usage (FILE *f, const char *me)
 "  -V, --version                  output version information and exit\n"
 "  -w, --no-daemon                don't fork into the background\n"
 "  -p, --pid-file LOCATION        write a PID file to LOCATION\n"
+"  -u, --user USER                write a PID file to LOCATION\n"
 "\n"
 "Report bugs to %s.\n",
 	   me, DEFAULT_HOST_PORT, DEFAULT_KEEP_ALIVE,
@@ -93,6 +118,7 @@ parse_arguments (int argc, char **argv, Arguments *arg)
   arg->strict_content_length = FALSE;
   arg->keep_alive = DEFAULT_KEEP_ALIVE;
   arg->max_connection_age = DEFAULT_CONNECTION_MAX_TIME;
+  arg->user = NULL;
   
   for (;;)
     {
@@ -108,6 +134,7 @@ parse_arguments (int argc, char **argv, Arguments *arg)
 	{ "debug", optional_argument, 0, 'D' },
 	{ "logfile", required_argument, 0, 'l' },
 #endif
+	{ "user", optional_argument, 0, 'u' },
 	{ "device", required_argument, 0, 'd' },
 	{ "pid-file", required_argument, 0, 'p' },
 	{ "keep-alive", required_argument, 0, 'k' },
@@ -117,7 +144,7 @@ parse_arguments (int argc, char **argv, Arguments *arg)
 	{ 0, 0, 0, 0 }
       };
 
-      static const char *short_options = "c:d:F:hk:M:p:sSVw"
+      static const char *short_options = "c:d:F:hk:M:p:u:sSVw"
 #ifdef DEBUG_MODE
 	"D:l:"
 #endif
@@ -210,6 +237,9 @@ parse_arguments (int argc, char **argv, Arguments *arg)
 
 	case '?':
 	  break;
+	case 'u':
+	  arg->user = optarg;
+	  break;
 
 	default:
 	  fprintf (stderr, "?? getopt returned character code 0%o ??\n", c);
@@ -353,6 +383,16 @@ main (int argc, char **argv)
          }
      }
 
+  if (arg.user != NULL)
+  {
+    if ( changepriv(arg.user) < 0 )
+	{
+		log_error(stderr, "Error dropping privilege to %s\n", arg.user);
+		log_exit(1);
+	}
+  }
+  
+
   for (;;)
     {
       time_t last_tunnel_write;
