gitweb: Remove forgotten call to git_to_hash
[gitweb.git] / daemon.c
index e4ec676301c965e0b0ec81995f4e1fb77363c373..66ec830b7cab775e16c3fe06539e698edd6b7aff 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -7,6 +7,8 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <syslog.h>
+#include <pwd.h>
+#include <grp.h>
 #include "pkt-line.h"
 #include "cache.h"
 #include "exec_cmd.h"
@@ -19,27 +21,28 @@ static const char daemon_usage[] =
 "git-daemon [--verbose] [--syslog] [--inetd | --port=n] [--export-all]\n"
 "           [--timeout=n] [--init-timeout=n] [--strict-paths]\n"
 "           [--base-path=path] [--user-path | --user-path=path]\n"
-"           [--reuseaddr] [directory...]";
+"           [--reuseaddr] [--detach] [--pid-file=file]\n"
+"           [--user=user [[--group=group]] [directory...]";
 
 /* List of acceptable pathname prefixes */
-static char **ok_paths = NULL;
-static int strict_paths = 0;
+static char **ok_paths;
+static int strict_paths;
 
 /* If this is set, git-daemon-export-ok is not required */
-static int export_all_trees = 0;
+static int export_all_trees;
 
 /* Take all paths relative to this one if non-NULL */
-static char *base_path = NULL;
+static char *base_path;
 
 /* If defined, ~user notation is allowed and the string is inserted
  * after ~user/.  E.g. a request to git://host/~alice/frotz would
  * go to /home/alice/pub_git/frotz with --user-path=pub_git.
  */
-static const char *user_path = NULL;
+static const char *user_path;
 
 /* Timeout, and initial timeout */
-static unsigned int timeout = 0;
-static unsigned int init_timeout = 0;
+static unsigned int timeout;
+static unsigned int init_timeout;
 
 static void logreport(int priority, const char *err, va_list params)
 {
@@ -333,12 +336,12 @@ static int execute(struct sockaddr *addr)
 static int max_connections = 25;
 
 /* These are updated by the signal handler */
-static volatile unsigned int children_reaped = 0;
+static volatile unsigned int children_reaped;
 static pid_t dead_child[MAX_CHILDREN];
 
 /* These are updated by the main loop */
-static unsigned int children_spawned = 0;
-static unsigned int children_deleted = 0;
+static unsigned int children_spawned;
+static unsigned int children_deleted;
 
 static struct child {
        pid_t pid;
@@ -526,7 +529,6 @@ static int socksetup(int port, int **socklist_p)
 
        for (ai = ai0; ai; ai = ai->ai_next) {
                int sockfd;
-               int *newlist;
 
                sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
                if (sockfd < 0)
@@ -560,11 +562,7 @@ static int socksetup(int port, int **socklist_p)
                        continue;       /* not fatal */
                }
 
-               newlist = realloc(socklist, sizeof(int) * (socknum + 1));
-               if (!newlist)
-                       die("memory allocation failed: %s", strerror(errno));
-
-               socklist = newlist;
+               socklist = xrealloc(socklist, sizeof(int) * (socknum + 1));
                socklist[socknum++] = sockfd;
 
                if (maxfd < sockfd)
@@ -701,7 +699,7 @@ static void store_pid(const char *path)
        fclose(f);
 }
 
-static int serve(int port)
+static int serve(int port, struct passwd *pass, gid_t gid)
 {
        int socknum, *socklist;
 
@@ -709,6 +707,11 @@ static int serve(int port)
        if (socknum == 0)
                die("unable to allocate any listen sockets on port %u", port);
 
+       if (pass && gid &&
+           (initgroups(pass->pw_name, gid) || setgid (gid) ||
+            setuid(pass->pw_uid)))
+               die("cannot drop privileges");
+
        return service_loop(socknum, socklist);
 }
 
@@ -716,8 +719,11 @@ int main(int argc, char **argv)
 {
        int port = DEFAULT_GIT_PORT;
        int inetd_mode = 0;
-       const char *pid_file = NULL;
+       const char *pid_file = NULL, *user_name = NULL, *group_name = NULL;
        int detach = 0;
+       struct passwd *pass = NULL;
+       struct group *group;
+       gid_t gid = 0;
        int i;
 
        /* Without this we cannot rely on waitpid() to tell
@@ -791,6 +797,14 @@ int main(int argc, char **argv)
                        log_syslog = 1;
                        continue;
                }
+               if (!strncmp(arg, "--user=", 7)) {
+                       user_name = arg + 7;
+                       continue;
+               }
+               if (!strncmp(arg, "--group=", 8)) {
+                       group_name = arg + 8;
+                       continue;
+               }
                if (!strcmp(arg, "--")) {
                        ok_paths = &argv[i+1];
                        break;
@@ -802,6 +816,28 @@ int main(int argc, char **argv)
                usage(daemon_usage);
        }
 
+       if (inetd_mode && (group_name || user_name))
+               die("--user and --group are incompatible with --inetd");
+
+       if (group_name && !user_name)
+               die("--group supplied without --user");
+
+       if (user_name) {
+               pass = getpwnam(user_name);
+               if (!pass)
+                       die("user not found - %s", user_name);
+
+               if (!group_name)
+                       gid = pass->pw_gid;
+               else {
+                       group = getgrnam(group_name);
+                       if (!group)
+                               die("group not found - %s", group_name);
+
+                       gid = group->gr_gid;
+               }
+       }
+
        if (log_syslog) {
                openlog("git-daemon", 0, LOG_DAEMON);
                set_die_routine(daemon_die);
@@ -831,5 +867,5 @@ int main(int argc, char **argv)
        if (pid_file)
                store_pid(pid_file);
 
-       return serve(port);
+       return serve(port, pass, gid);
 }