daemon.con commit pack-objects: further work on internal rev-list logic. (8d1d8f8)
   1#include <signal.h>
   2#include <sys/wait.h>
   3#include <sys/socket.h>
   4#include <sys/time.h>
   5#include <sys/poll.h>
   6#include <netdb.h>
   7#include <netinet/in.h>
   8#include <arpa/inet.h>
   9#include <syslog.h>
  10#include <pwd.h>
  11#include <grp.h>
  12#include "pkt-line.h"
  13#include "cache.h"
  14#include "exec_cmd.h"
  15
  16static int log_syslog;
  17static int verbose;
  18static int reuseaddr;
  19
  20static const char daemon_usage[] =
  21"git-daemon [--verbose] [--syslog] [--inetd | --port=n] [--export-all]\n"
  22"           [--timeout=n] [--init-timeout=n] [--strict-paths]\n"
  23"           [--base-path=path] [--user-path | --user-path=path]\n"
  24"           [--reuseaddr] [--detach] [--pid-file=file]\n"
  25"           [--[enable|disable|allow-override|forbid-override]=service]\n"
  26"           [--user=user [[--group=group]] [directory...]";
  27
  28/* List of acceptable pathname prefixes */
  29static char **ok_paths;
  30static int strict_paths;
  31
  32/* If this is set, git-daemon-export-ok is not required */
  33static int export_all_trees;
  34
  35/* Take all paths relative to this one if non-NULL */
  36static char *base_path;
  37
  38/* If defined, ~user notation is allowed and the string is inserted
  39 * after ~user/.  E.g. a request to git://host/~alice/frotz would
  40 * go to /home/alice/pub_git/frotz with --user-path=pub_git.
  41 */
  42static const char *user_path;
  43
  44/* Timeout, and initial timeout */
  45static unsigned int timeout;
  46static unsigned int init_timeout;
  47
  48static void logreport(int priority, const char *err, va_list params)
  49{
  50        /* We should do a single write so that it is atomic and output
  51         * of several processes do not get intermingled. */
  52        char buf[1024];
  53        int buflen;
  54        int maxlen, msglen;
  55
  56        /* sizeof(buf) should be big enough for "[pid] \n" */
  57        buflen = snprintf(buf, sizeof(buf), "[%ld] ", (long) getpid());
  58
  59        maxlen = sizeof(buf) - buflen - 1; /* -1 for our own LF */
  60        msglen = vsnprintf(buf + buflen, maxlen, err, params);
  61
  62        if (log_syslog) {
  63                syslog(priority, "%s", buf);
  64                return;
  65        }
  66
  67        /* maxlen counted our own LF but also counts space given to
  68         * vsnprintf for the terminating NUL.  We want to make sure that
  69         * we have space for our own LF and NUL after the "meat" of the
  70         * message, so truncate it at maxlen - 1.
  71         */
  72        if (msglen > maxlen - 1)
  73                msglen = maxlen - 1;
  74        else if (msglen < 0)
  75                msglen = 0; /* Protect against weird return values. */
  76        buflen += msglen;
  77
  78        buf[buflen++] = '\n';
  79        buf[buflen] = '\0';
  80
  81        write(2, buf, buflen);
  82}
  83
  84static void logerror(const char *err, ...)
  85{
  86        va_list params;
  87        va_start(params, err);
  88        logreport(LOG_ERR, err, params);
  89        va_end(params);
  90}
  91
  92static void loginfo(const char *err, ...)
  93{
  94        va_list params;
  95        if (!verbose)
  96                return;
  97        va_start(params, err);
  98        logreport(LOG_INFO, err, params);
  99        va_end(params);
 100}
 101
 102static void NORETURN daemon_die(const char *err, va_list params)
 103{
 104        logreport(LOG_ERR, err, params);
 105        exit(1);
 106}
 107
 108static int avoid_alias(char *p)
 109{
 110        int sl, ndot;
 111
 112        /* 
 113         * This resurrects the belts and suspenders paranoia check by HPA
 114         * done in <435560F7.4080006@zytor.com> thread, now enter_repo()
 115         * does not do getcwd() based path canonicalizations.
 116         *
 117         * sl becomes true immediately after seeing '/' and continues to
 118         * be true as long as dots continue after that without intervening
 119         * non-dot character.
 120         */
 121        if (!p || (*p != '/' && *p != '~'))
 122                return -1;
 123        sl = 1; ndot = 0;
 124        p++;
 125
 126        while (1) {
 127                char ch = *p++;
 128                if (sl) {
 129                        if (ch == '.')
 130                                ndot++;
 131                        else if (ch == '/') {
 132                                if (ndot < 3)
 133                                        /* reject //, /./ and /../ */
 134                                        return -1;
 135                                ndot = 0;
 136                        }
 137                        else if (ch == 0) {
 138                                if (0 < ndot && ndot < 3)
 139                                        /* reject /.$ and /..$ */
 140                                        return -1;
 141                                return 0;
 142                        }
 143                        else
 144                                sl = ndot = 0;
 145                }
 146                else if (ch == 0)
 147                        return 0;
 148                else if (ch == '/') {
 149                        sl = 1;
 150                        ndot = 0;
 151                }
 152        }
 153}
 154
 155static char *path_ok(char *dir)
 156{
 157        static char rpath[PATH_MAX];
 158        char *path;
 159
 160        if (avoid_alias(dir)) {
 161                logerror("'%s': aliased", dir);
 162                return NULL;
 163        }
 164
 165        if (*dir == '~') {
 166                if (!user_path) {
 167                        logerror("'%s': User-path not allowed", dir);
 168                        return NULL;
 169                }
 170                if (*user_path) {
 171                        /* Got either "~alice" or "~alice/foo";
 172                         * rewrite them to "~alice/%s" or
 173                         * "~alice/%s/foo".
 174                         */
 175                        int namlen, restlen = strlen(dir);
 176                        char *slash = strchr(dir, '/');
 177                        if (!slash)
 178                                slash = dir + restlen;
 179                        namlen = slash - dir;
 180                        restlen -= namlen;
 181                        loginfo("userpath <%s>, request <%s>, namlen %d, restlen %d, slash <%s>", user_path, dir, namlen, restlen, slash);
 182                        snprintf(rpath, PATH_MAX, "%.*s/%s%.*s",
 183                                 namlen, dir, user_path, restlen, slash);
 184                        dir = rpath;
 185                }
 186        }
 187        else if (base_path) {
 188                if (*dir != '/') {
 189                        /* Allow only absolute */
 190                        logerror("'%s': Non-absolute path denied (base-path active)", dir);
 191                        return NULL;
 192                }
 193                else {
 194                        snprintf(rpath, PATH_MAX, "%s%s", base_path, dir);
 195                        dir = rpath;
 196                }
 197        }
 198
 199        path = enter_repo(dir, strict_paths);
 200
 201        if (!path) {
 202                logerror("'%s': unable to chdir or not a git archive", dir);
 203                return NULL;
 204        }
 205
 206        if ( ok_paths && *ok_paths ) {
 207                char **pp;
 208                int pathlen = strlen(path);
 209
 210                /* The validation is done on the paths after enter_repo
 211                 * appends optional {.git,.git/.git} and friends, but 
 212                 * it does not use getcwd().  So if your /pub is
 213                 * a symlink to /mnt/pub, you can whitelist /pub and
 214                 * do not have to say /mnt/pub.
 215                 * Do not say /pub/.
 216                 */
 217                for ( pp = ok_paths ; *pp ; pp++ ) {
 218                        int len = strlen(*pp);
 219                        if (len <= pathlen &&
 220                            !memcmp(*pp, path, len) &&
 221                            (path[len] == '\0' ||
 222                             (!strict_paths && path[len] == '/')))
 223                                return path;
 224                }
 225        }
 226        else {
 227                /* be backwards compatible */
 228                if (!strict_paths)
 229                        return path;
 230        }
 231
 232        logerror("'%s': not in whitelist", path);
 233        return NULL;            /* Fallthrough. Deny by default */
 234}
 235
 236typedef int (*daemon_service_fn)(void);
 237struct daemon_service {
 238        const char *name;
 239        const char *config_name;
 240        daemon_service_fn fn;
 241        int enabled;
 242        int overridable;
 243};
 244
 245static struct daemon_service *service_looking_at;
 246static int service_enabled;
 247
 248static int git_daemon_config(const char *var, const char *value)
 249{
 250        if (!strncmp(var, "daemon.", 7) &&
 251            !strcmp(var + 7, service_looking_at->config_name)) {
 252                service_enabled = git_config_bool(var, value);
 253                return 0;
 254        }
 255
 256        /* we are not interested in parsing any other configuration here */
 257        return 0;
 258}
 259
 260static int run_service(char *dir, struct daemon_service *service)
 261{
 262        const char *path;
 263        int enabled = service->enabled;
 264
 265        loginfo("Request %s for '%s'", service->name, dir);
 266
 267        if (!enabled && !service->overridable) {
 268                logerror("'%s': service not enabled.", service->name);
 269                errno = EACCES;
 270                return -1;
 271        }
 272
 273        if (!(path = path_ok(dir)))
 274                return -1;
 275
 276        /*
 277         * Security on the cheap.
 278         *
 279         * We want a readable HEAD, usable "objects" directory, and
 280         * a "git-daemon-export-ok" flag that says that the other side
 281         * is ok with us doing this.
 282         *
 283         * path_ok() uses enter_repo() and does whitelist checking.
 284         * We only need to make sure the repository is exported.
 285         */
 286
 287        if (!export_all_trees && access("git-daemon-export-ok", F_OK)) {
 288                logerror("'%s': repository not exported.", path);
 289                errno = EACCES;
 290                return -1;
 291        }
 292
 293        if (service->overridable) {
 294                service_looking_at = service;
 295                service_enabled = -1;
 296                git_config(git_daemon_config);
 297                if (0 <= service_enabled)
 298                        enabled = service_enabled;
 299        }
 300        if (!enabled) {
 301                logerror("'%s': service not enabled for '%s'",
 302                         service->name, path);
 303                errno = EACCES;
 304                return -1;
 305        }
 306
 307        /*
 308         * We'll ignore SIGTERM from now on, we have a
 309         * good client.
 310         */
 311        signal(SIGTERM, SIG_IGN);
 312
 313        return service->fn();
 314}
 315
 316static int upload_pack(void)
 317{
 318        /* Timeout as string */
 319        char timeout_buf[64];
 320
 321        snprintf(timeout_buf, sizeof timeout_buf, "--timeout=%u", timeout);
 322
 323        /* git-upload-pack only ever reads stuff, so this is safe */
 324        execl_git_cmd("upload-pack", "--strict", timeout_buf, ".", NULL);
 325        return -1;
 326}
 327
 328static struct daemon_service daemon_service[] = {
 329        { "upload-pack", "uploadpack", upload_pack, 1, 1 },
 330};
 331
 332static void enable_service(const char *name, int ena) {
 333        int i;
 334        for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
 335                if (!strcmp(daemon_service[i].name, name)) {
 336                        daemon_service[i].enabled = ena;
 337                        return;
 338                }
 339        }
 340        die("No such service %s", name);
 341}
 342
 343static void make_service_overridable(const char *name, int ena) {
 344        int i;
 345        for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
 346                if (!strcmp(daemon_service[i].name, name)) {
 347                        daemon_service[i].overridable = ena;
 348                        return;
 349                }
 350        }
 351        die("No such service %s", name);
 352}
 353
 354static int execute(struct sockaddr *addr)
 355{
 356        static char line[1000];
 357        int pktlen, len, i;
 358
 359        if (addr) {
 360                char addrbuf[256] = "";
 361                int port = -1;
 362
 363                if (addr->sa_family == AF_INET) {
 364                        struct sockaddr_in *sin_addr = (void *) addr;
 365                        inet_ntop(addr->sa_family, &sin_addr->sin_addr, addrbuf, sizeof(addrbuf));
 366                        port = sin_addr->sin_port;
 367#ifndef NO_IPV6
 368                } else if (addr && addr->sa_family == AF_INET6) {
 369                        struct sockaddr_in6 *sin6_addr = (void *) addr;
 370
 371                        char *buf = addrbuf;
 372                        *buf++ = '['; *buf = '\0'; /* stpcpy() is cool */
 373                        inet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf, sizeof(addrbuf) - 1);
 374                        strcat(buf, "]");
 375
 376                        port = sin6_addr->sin6_port;
 377#endif
 378                }
 379                loginfo("Connection from %s:%d", addrbuf, port);
 380        }
 381
 382        alarm(init_timeout ? init_timeout : timeout);
 383        pktlen = packet_read_line(0, line, sizeof(line));
 384        alarm(0);
 385
 386        len = strlen(line);
 387        if (pktlen != len)
 388                loginfo("Extended attributes (%d bytes) exist <%.*s>",
 389                        (int) pktlen - len,
 390                        (int) pktlen - len, line + len + 1);
 391        if (len && line[len-1] == '\n')
 392                line[--len] = 0;
 393
 394        for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
 395                struct daemon_service *s = &(daemon_service[i]);
 396                int namelen = strlen(s->name);
 397                if (!strncmp("git-", line, 4) &&
 398                    !strncmp(s->name, line + 4, namelen) &&
 399                    line[namelen + 4] == ' ')
 400                        return run_service(line + namelen + 5, s);
 401        }
 402
 403        logerror("Protocol error: '%s'", line);
 404        return -1;
 405}
 406
 407
 408/*
 409 * We count spawned/reaped separately, just to avoid any
 410 * races when updating them from signals. The SIGCHLD handler
 411 * will only update children_reaped, and the fork logic will
 412 * only update children_spawned.
 413 *
 414 * MAX_CHILDREN should be a power-of-two to make the modulus
 415 * operation cheap. It should also be at least twice
 416 * the maximum number of connections we will ever allow.
 417 */
 418#define MAX_CHILDREN 128
 419
 420static int max_connections = 25;
 421
 422/* These are updated by the signal handler */
 423static volatile unsigned int children_reaped;
 424static pid_t dead_child[MAX_CHILDREN];
 425
 426/* These are updated by the main loop */
 427static unsigned int children_spawned;
 428static unsigned int children_deleted;
 429
 430static struct child {
 431        pid_t pid;
 432        int addrlen;
 433        struct sockaddr_storage address;
 434} live_child[MAX_CHILDREN];
 435
 436static void add_child(int idx, pid_t pid, struct sockaddr *addr, int addrlen)
 437{
 438        live_child[idx].pid = pid;
 439        live_child[idx].addrlen = addrlen;
 440        memcpy(&live_child[idx].address, addr, addrlen);
 441}
 442
 443/*
 444 * Walk from "deleted" to "spawned", and remove child "pid".
 445 *
 446 * We move everything up by one, since the new "deleted" will
 447 * be one higher.
 448 */
 449static void remove_child(pid_t pid, unsigned deleted, unsigned spawned)
 450{
 451        struct child n;
 452
 453        deleted %= MAX_CHILDREN;
 454        spawned %= MAX_CHILDREN;
 455        if (live_child[deleted].pid == pid) {
 456                live_child[deleted].pid = -1;
 457                return;
 458        }
 459        n = live_child[deleted];
 460        for (;;) {
 461                struct child m;
 462                deleted = (deleted + 1) % MAX_CHILDREN;
 463                if (deleted == spawned)
 464                        die("could not find dead child %d\n", pid);
 465                m = live_child[deleted];
 466                live_child[deleted] = n;
 467                if (m.pid == pid)
 468                        return;
 469                n = m;
 470        }
 471}
 472
 473/*
 474 * This gets called if the number of connections grows
 475 * past "max_connections".
 476 *
 477 * We _should_ start off by searching for connections
 478 * from the same IP, and if there is some address wth
 479 * multiple connections, we should kill that first.
 480 *
 481 * As it is, we just "randomly" kill 25% of the connections,
 482 * and our pseudo-random generator sucks too. I have no
 483 * shame.
 484 *
 485 * Really, this is just a place-holder for a _real_ algorithm.
 486 */
 487static void kill_some_children(int signo, unsigned start, unsigned stop)
 488{
 489        start %= MAX_CHILDREN;
 490        stop %= MAX_CHILDREN;
 491        while (start != stop) {
 492                if (!(start & 3))
 493                        kill(live_child[start].pid, signo);
 494                start = (start + 1) % MAX_CHILDREN;
 495        }
 496}
 497
 498static void check_max_connections(void)
 499{
 500        for (;;) {
 501                int active;
 502                unsigned spawned, reaped, deleted;
 503
 504                spawned = children_spawned;
 505                reaped = children_reaped;
 506                deleted = children_deleted;
 507
 508                while (deleted < reaped) {
 509                        pid_t pid = dead_child[deleted % MAX_CHILDREN];
 510                        remove_child(pid, deleted, spawned);
 511                        deleted++;
 512                }
 513                children_deleted = deleted;
 514
 515                active = spawned - deleted;
 516                if (active <= max_connections)
 517                        break;
 518
 519                /* Kill some unstarted connections with SIGTERM */
 520                kill_some_children(SIGTERM, deleted, spawned);
 521                if (active <= max_connections << 1)
 522                        break;
 523
 524                /* If the SIGTERM thing isn't helping use SIGKILL */
 525                kill_some_children(SIGKILL, deleted, spawned);
 526                sleep(1);
 527        }
 528}
 529
 530static void handle(int incoming, struct sockaddr *addr, int addrlen)
 531{
 532        pid_t pid = fork();
 533
 534        if (pid) {
 535                unsigned idx;
 536
 537                close(incoming);
 538                if (pid < 0)
 539                        return;
 540
 541                idx = children_spawned % MAX_CHILDREN;
 542                children_spawned++;
 543                add_child(idx, pid, addr, addrlen);
 544
 545                check_max_connections();
 546                return;
 547        }
 548
 549        dup2(incoming, 0);
 550        dup2(incoming, 1);
 551        close(incoming);
 552
 553        exit(execute(addr));
 554}
 555
 556static void child_handler(int signo)
 557{
 558        for (;;) {
 559                int status;
 560                pid_t pid = waitpid(-1, &status, WNOHANG);
 561
 562                if (pid > 0) {
 563                        unsigned reaped = children_reaped;
 564                        dead_child[reaped % MAX_CHILDREN] = pid;
 565                        children_reaped = reaped + 1;
 566                        /* XXX: Custom logging, since we don't wanna getpid() */
 567                        if (verbose) {
 568                                const char *dead = "";
 569                                if (!WIFEXITED(status) || WEXITSTATUS(status) > 0)
 570                                        dead = " (with error)";
 571                                if (log_syslog)
 572                                        syslog(LOG_INFO, "[%d] Disconnected%s", pid, dead);
 573                                else
 574                                        fprintf(stderr, "[%d] Disconnected%s\n", pid, dead);
 575                        }
 576                        continue;
 577                }
 578                break;
 579        }
 580}
 581
 582static int set_reuse_addr(int sockfd)
 583{
 584        int on = 1;
 585
 586        if (!reuseaddr)
 587                return 0;
 588        return setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
 589                          &on, sizeof(on));
 590}
 591
 592#ifndef NO_IPV6
 593
 594static int socksetup(int port, int **socklist_p)
 595{
 596        int socknum = 0, *socklist = NULL;
 597        int maxfd = -1;
 598        char pbuf[NI_MAXSERV];
 599
 600        struct addrinfo hints, *ai0, *ai;
 601        int gai;
 602
 603        sprintf(pbuf, "%d", port);
 604        memset(&hints, 0, sizeof(hints));
 605        hints.ai_family = AF_UNSPEC;
 606        hints.ai_socktype = SOCK_STREAM;
 607        hints.ai_protocol = IPPROTO_TCP;
 608        hints.ai_flags = AI_PASSIVE;
 609
 610        gai = getaddrinfo(NULL, pbuf, &hints, &ai0);
 611        if (gai)
 612                die("getaddrinfo() failed: %s\n", gai_strerror(gai));
 613
 614        for (ai = ai0; ai; ai = ai->ai_next) {
 615                int sockfd;
 616
 617                sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
 618                if (sockfd < 0)
 619                        continue;
 620                if (sockfd >= FD_SETSIZE) {
 621                        error("too large socket descriptor.");
 622                        close(sockfd);
 623                        continue;
 624                }
 625
 626#ifdef IPV6_V6ONLY
 627                if (ai->ai_family == AF_INET6) {
 628                        int on = 1;
 629                        setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
 630                                   &on, sizeof(on));
 631                        /* Note: error is not fatal */
 632                }
 633#endif
 634
 635                if (set_reuse_addr(sockfd)) {
 636                        close(sockfd);
 637                        continue;
 638                }
 639
 640                if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
 641                        close(sockfd);
 642                        continue;       /* not fatal */
 643                }
 644                if (listen(sockfd, 5) < 0) {
 645                        close(sockfd);
 646                        continue;       /* not fatal */
 647                }
 648
 649                socklist = xrealloc(socklist, sizeof(int) * (socknum + 1));
 650                socklist[socknum++] = sockfd;
 651
 652                if (maxfd < sockfd)
 653                        maxfd = sockfd;
 654        }
 655
 656        freeaddrinfo(ai0);
 657
 658        *socklist_p = socklist;
 659        return socknum;
 660}
 661
 662#else /* NO_IPV6 */
 663
 664static int socksetup(int port, int **socklist_p)
 665{
 666        struct sockaddr_in sin;
 667        int sockfd;
 668
 669        sockfd = socket(AF_INET, SOCK_STREAM, 0);
 670        if (sockfd < 0)
 671                return 0;
 672
 673        memset(&sin, 0, sizeof sin);
 674        sin.sin_family = AF_INET;
 675        sin.sin_addr.s_addr = htonl(INADDR_ANY);
 676        sin.sin_port = htons(port);
 677
 678        if (set_reuse_addr(sockfd)) {
 679                close(sockfd);
 680                return 0;
 681        }
 682
 683        if ( bind(sockfd, (struct sockaddr *)&sin, sizeof sin) < 0 ) {
 684                close(sockfd);
 685                return 0;
 686        }
 687
 688        if (listen(sockfd, 5) < 0) {
 689                close(sockfd);
 690                return 0;
 691        }
 692
 693        *socklist_p = xmalloc(sizeof(int));
 694        **socklist_p = sockfd;
 695        return 1;
 696}
 697
 698#endif
 699
 700static int service_loop(int socknum, int *socklist)
 701{
 702        struct pollfd *pfd;
 703        int i;
 704
 705        pfd = xcalloc(socknum, sizeof(struct pollfd));
 706
 707        for (i = 0; i < socknum; i++) {
 708                pfd[i].fd = socklist[i];
 709                pfd[i].events = POLLIN;
 710        }
 711
 712        signal(SIGCHLD, child_handler);
 713
 714        for (;;) {
 715                int i;
 716
 717                if (poll(pfd, socknum, -1) < 0) {
 718                        if (errno != EINTR) {
 719                                error("poll failed, resuming: %s",
 720                                      strerror(errno));
 721                                sleep(1);
 722                        }
 723                        continue;
 724                }
 725
 726                for (i = 0; i < socknum; i++) {
 727                        if (pfd[i].revents & POLLIN) {
 728                                struct sockaddr_storage ss;
 729                                unsigned int sslen = sizeof(ss);
 730                                int incoming = accept(pfd[i].fd, (struct sockaddr *)&ss, &sslen);
 731                                if (incoming < 0) {
 732                                        switch (errno) {
 733                                        case EAGAIN:
 734                                        case EINTR:
 735                                        case ECONNABORTED:
 736                                                continue;
 737                                        default:
 738                                                die("accept returned %s", strerror(errno));
 739                                        }
 740                                }
 741                                handle(incoming, (struct sockaddr *)&ss, sslen);
 742                        }
 743                }
 744        }
 745}
 746
 747/* if any standard file descriptor is missing open it to /dev/null */
 748static void sanitize_stdfds(void)
 749{
 750        int fd = open("/dev/null", O_RDWR, 0);
 751        while (fd != -1 && fd < 2)
 752                fd = dup(fd);
 753        if (fd == -1)
 754                die("open /dev/null or dup failed: %s", strerror(errno));
 755        if (fd > 2)
 756                close(fd);
 757}
 758
 759static void daemonize(void)
 760{
 761        switch (fork()) {
 762                case 0:
 763                        break;
 764                case -1:
 765                        die("fork failed: %s", strerror(errno));
 766                default:
 767                        exit(0);
 768        }
 769        if (setsid() == -1)
 770                die("setsid failed: %s", strerror(errno));
 771        close(0);
 772        close(1);
 773        close(2);
 774        sanitize_stdfds();
 775}
 776
 777static void store_pid(const char *path)
 778{
 779        FILE *f = fopen(path, "w");
 780        if (!f)
 781                die("cannot open pid file %s: %s", path, strerror(errno));
 782        fprintf(f, "%d\n", getpid());
 783        fclose(f);
 784}
 785
 786static int serve(int port, struct passwd *pass, gid_t gid)
 787{
 788        int socknum, *socklist;
 789
 790        socknum = socksetup(port, &socklist);
 791        if (socknum == 0)
 792                die("unable to allocate any listen sockets on port %u", port);
 793
 794        if (pass && gid &&
 795            (initgroups(pass->pw_name, gid) || setgid (gid) ||
 796             setuid(pass->pw_uid)))
 797                die("cannot drop privileges");
 798
 799        return service_loop(socknum, socklist);
 800}
 801
 802int main(int argc, char **argv)
 803{
 804        int port = DEFAULT_GIT_PORT;
 805        int inetd_mode = 0;
 806        const char *pid_file = NULL, *user_name = NULL, *group_name = NULL;
 807        int detach = 0;
 808        struct passwd *pass = NULL;
 809        struct group *group;
 810        gid_t gid = 0;
 811        int i;
 812
 813        /* Without this we cannot rely on waitpid() to tell
 814         * what happened to our children.
 815         */
 816        signal(SIGCHLD, SIG_DFL);
 817
 818        for (i = 1; i < argc; i++) {
 819                char *arg = argv[i];
 820
 821                if (!strncmp(arg, "--port=", 7)) {
 822                        char *end;
 823                        unsigned long n;
 824                        n = strtoul(arg+7, &end, 0);
 825                        if (arg[7] && !*end) {
 826                                port = n;
 827                                continue;
 828                        }
 829                }
 830                if (!strcmp(arg, "--inetd")) {
 831                        inetd_mode = 1;
 832                        log_syslog = 1;
 833                        continue;
 834                }
 835                if (!strcmp(arg, "--verbose")) {
 836                        verbose = 1;
 837                        continue;
 838                }
 839                if (!strcmp(arg, "--syslog")) {
 840                        log_syslog = 1;
 841                        continue;
 842                }
 843                if (!strcmp(arg, "--export-all")) {
 844                        export_all_trees = 1;
 845                        continue;
 846                }
 847                if (!strncmp(arg, "--timeout=", 10)) {
 848                        timeout = atoi(arg+10);
 849                        continue;
 850                }
 851                if (!strncmp(arg, "--init-timeout=", 15)) {
 852                        init_timeout = atoi(arg+15);
 853                        continue;
 854                }
 855                if (!strcmp(arg, "--strict-paths")) {
 856                        strict_paths = 1;
 857                        continue;
 858                }
 859                if (!strncmp(arg, "--base-path=", 12)) {
 860                        base_path = arg+12;
 861                        continue;
 862                }
 863                if (!strcmp(arg, "--reuseaddr")) {
 864                        reuseaddr = 1;
 865                        continue;
 866                }
 867                if (!strcmp(arg, "--user-path")) {
 868                        user_path = "";
 869                        continue;
 870                }
 871                if (!strncmp(arg, "--user-path=", 12)) {
 872                        user_path = arg + 12;
 873                        continue;
 874                }
 875                if (!strncmp(arg, "--pid-file=", 11)) {
 876                        pid_file = arg + 11;
 877                        continue;
 878                }
 879                if (!strcmp(arg, "--detach")) {
 880                        detach = 1;
 881                        log_syslog = 1;
 882                        continue;
 883                }
 884                if (!strncmp(arg, "--user=", 7)) {
 885                        user_name = arg + 7;
 886                        continue;
 887                }
 888                if (!strncmp(arg, "--group=", 8)) {
 889                        group_name = arg + 8;
 890                        continue;
 891                }
 892                if (!strncmp(arg, "--enable=", 9)) {
 893                        enable_service(arg + 9, 1);
 894                        continue;
 895                }
 896                if (!strncmp(arg, "--disable=", 10)) {
 897                        enable_service(arg + 10, 0);
 898                        continue;
 899                }
 900                if (!strncmp(arg, "--allow-override=", 17)) {
 901                        make_service_overridable(arg + 17, 1);
 902                        continue;
 903                }
 904                if (!strncmp(arg, "--forbid-override=", 18)) {
 905                        make_service_overridable(arg + 18, 0);
 906                        continue;
 907                }
 908                if (!strcmp(arg, "--")) {
 909                        ok_paths = &argv[i+1];
 910                        break;
 911                } else if (arg[0] != '-') {
 912                        ok_paths = &argv[i];
 913                        break;
 914                }
 915
 916                usage(daemon_usage);
 917        }
 918
 919        if (inetd_mode && (group_name || user_name))
 920                die("--user and --group are incompatible with --inetd");
 921
 922        if (group_name && !user_name)
 923                die("--group supplied without --user");
 924
 925        if (user_name) {
 926                pass = getpwnam(user_name);
 927                if (!pass)
 928                        die("user not found - %s", user_name);
 929
 930                if (!group_name)
 931                        gid = pass->pw_gid;
 932                else {
 933                        group = getgrnam(group_name);
 934                        if (!group)
 935                                die("group not found - %s", group_name);
 936
 937                        gid = group->gr_gid;
 938                }
 939        }
 940
 941        if (log_syslog) {
 942                openlog("git-daemon", 0, LOG_DAEMON);
 943                set_die_routine(daemon_die);
 944        }
 945
 946        if (strict_paths && (!ok_paths || !*ok_paths))
 947                die("option --strict-paths requires a whitelist");
 948
 949        if (inetd_mode) {
 950                struct sockaddr_storage ss;
 951                struct sockaddr *peer = (struct sockaddr *)&ss;
 952                socklen_t slen = sizeof(ss);
 953
 954                freopen("/dev/null", "w", stderr);
 955
 956                if (getpeername(0, peer, &slen))
 957                        peer = NULL;
 958
 959                return execute(peer);
 960        }
 961
 962        if (detach)
 963                daemonize();
 964        else
 965                sanitize_stdfds();
 966
 967        if (pid_file)
 968                store_pid(pid_file);
 969
 970        return serve(port, pass, gid);
 971}