daemon.con commit pull: Fix parsing of -X<option> (14e5d40)
   1#include "cache.h"
   2#include "pkt-line.h"
   3#include "exec_cmd.h"
   4#include "run-command.h"
   5#include "strbuf.h"
   6
   7#include <syslog.h>
   8
   9#ifndef HOST_NAME_MAX
  10#define HOST_NAME_MAX 256
  11#endif
  12
  13#ifndef NI_MAXSERV
  14#define NI_MAXSERV 32
  15#endif
  16
  17static int log_syslog;
  18static int verbose;
  19static int reuseaddr;
  20
  21static const char daemon_usage[] =
  22"git daemon [--verbose] [--syslog] [--export-all]\n"
  23"           [--timeout=n] [--init-timeout=n] [--max-connections=n]\n"
  24"           [--strict-paths] [--base-path=path] [--base-path-relaxed]\n"
  25"           [--user-path | --user-path=path]\n"
  26"           [--interpolated-path=path]\n"
  27"           [--reuseaddr] [--detach] [--pid-file=file]\n"
  28"           [--[enable|disable|allow-override|forbid-override]=service]\n"
  29"           [--inetd | [--listen=host_or_ipaddr] [--port=n]\n"
  30"                      [--user=user [--group=group]]\n"
  31"           [directory...]";
  32
  33/* List of acceptable pathname prefixes */
  34static char **ok_paths;
  35static int strict_paths;
  36
  37/* If this is set, git-daemon-export-ok is not required */
  38static int export_all_trees;
  39
  40/* Take all paths relative to this one if non-NULL */
  41static char *base_path;
  42static char *interpolated_path;
  43static int base_path_relaxed;
  44
  45/* Flag indicating client sent extra args. */
  46static int saw_extended_args;
  47
  48/* If defined, ~user notation is allowed and the string is inserted
  49 * after ~user/.  E.g. a request to git://host/~alice/frotz would
  50 * go to /home/alice/pub_git/frotz with --user-path=pub_git.
  51 */
  52static const char *user_path;
  53
  54/* Timeout, and initial timeout */
  55static unsigned int timeout;
  56static unsigned int init_timeout;
  57
  58static char *hostname;
  59static char *canon_hostname;
  60static char *ip_address;
  61static char *tcp_port;
  62
  63static void logreport(int priority, const char *err, va_list params)
  64{
  65        if (log_syslog) {
  66                char buf[1024];
  67                vsnprintf(buf, sizeof(buf), err, params);
  68                syslog(priority, "%s", buf);
  69        } else {
  70                /*
  71                 * Since stderr is set to linebuffered mode, the
  72                 * logging of different processes will not overlap
  73                 */
  74                fprintf(stderr, "[%"PRIuMAX"] ", (uintmax_t)getpid());
  75                vfprintf(stderr, err, params);
  76                fputc('\n', stderr);
  77        }
  78}
  79
  80__attribute__((format (printf, 1, 2)))
  81static void logerror(const char *err, ...)
  82{
  83        va_list params;
  84        va_start(params, err);
  85        logreport(LOG_ERR, err, params);
  86        va_end(params);
  87}
  88
  89__attribute__((format (printf, 1, 2)))
  90static void loginfo(const char *err, ...)
  91{
  92        va_list params;
  93        if (!verbose)
  94                return;
  95        va_start(params, err);
  96        logreport(LOG_INFO, err, params);
  97        va_end(params);
  98}
  99
 100static void NORETURN daemon_die(const char *err, va_list params)
 101{
 102        logreport(LOG_ERR, err, params);
 103        exit(1);
 104}
 105
 106static char *path_ok(char *directory)
 107{
 108        static char rpath[PATH_MAX];
 109        static char interp_path[PATH_MAX];
 110        char *path;
 111        char *dir;
 112
 113        dir = directory;
 114
 115        if (daemon_avoid_alias(dir)) {
 116                logerror("'%s': aliased", dir);
 117                return NULL;
 118        }
 119
 120        if (*dir == '~') {
 121                if (!user_path) {
 122                        logerror("'%s': User-path not allowed", dir);
 123                        return NULL;
 124                }
 125                if (*user_path) {
 126                        /* Got either "~alice" or "~alice/foo";
 127                         * rewrite them to "~alice/%s" or
 128                         * "~alice/%s/foo".
 129                         */
 130                        int namlen, restlen = strlen(dir);
 131                        char *slash = strchr(dir, '/');
 132                        if (!slash)
 133                                slash = dir + restlen;
 134                        namlen = slash - dir;
 135                        restlen -= namlen;
 136                        loginfo("userpath <%s>, request <%s>, namlen %d, restlen %d, slash <%s>", user_path, dir, namlen, restlen, slash);
 137                        snprintf(rpath, PATH_MAX, "%.*s/%s%.*s",
 138                                 namlen, dir, user_path, restlen, slash);
 139                        dir = rpath;
 140                }
 141        }
 142        else if (interpolated_path && saw_extended_args) {
 143                struct strbuf expanded_path = STRBUF_INIT;
 144                struct strbuf_expand_dict_entry dict[] = {
 145                        { "H", hostname },
 146                        { "CH", canon_hostname },
 147                        { "IP", ip_address },
 148                        { "P", tcp_port },
 149                        { "D", directory },
 150                        { "%", "%" },
 151                        { NULL }
 152                };
 153
 154                if (*dir != '/') {
 155                        /* Allow only absolute */
 156                        logerror("'%s': Non-absolute path denied (interpolated-path active)", dir);
 157                        return NULL;
 158                }
 159
 160                strbuf_expand(&expanded_path, interpolated_path,
 161                                strbuf_expand_dict_cb, &dict);
 162                strlcpy(interp_path, expanded_path.buf, PATH_MAX);
 163                strbuf_release(&expanded_path);
 164                loginfo("Interpolated dir '%s'", interp_path);
 165
 166                dir = interp_path;
 167        }
 168        else if (base_path) {
 169                if (*dir != '/') {
 170                        /* Allow only absolute */
 171                        logerror("'%s': Non-absolute path denied (base-path active)", dir);
 172                        return NULL;
 173                }
 174                snprintf(rpath, PATH_MAX, "%s%s", base_path, dir);
 175                dir = rpath;
 176        }
 177
 178        path = enter_repo(dir, strict_paths);
 179        if (!path && base_path && base_path_relaxed) {
 180                /*
 181                 * if we fail and base_path_relaxed is enabled, try without
 182                 * prefixing the base path
 183                 */
 184                dir = directory;
 185                path = enter_repo(dir, strict_paths);
 186        }
 187
 188        if (!path) {
 189                logerror("'%s' does not appear to be a git repository", dir);
 190                return NULL;
 191        }
 192
 193        if ( ok_paths && *ok_paths ) {
 194                char **pp;
 195                int pathlen = strlen(path);
 196
 197                /* The validation is done on the paths after enter_repo
 198                 * appends optional {.git,.git/.git} and friends, but
 199                 * it does not use getcwd().  So if your /pub is
 200                 * a symlink to /mnt/pub, you can whitelist /pub and
 201                 * do not have to say /mnt/pub.
 202                 * Do not say /pub/.
 203                 */
 204                for ( pp = ok_paths ; *pp ; pp++ ) {
 205                        int len = strlen(*pp);
 206                        if (len <= pathlen &&
 207                            !memcmp(*pp, path, len) &&
 208                            (path[len] == '\0' ||
 209                             (!strict_paths && path[len] == '/')))
 210                                return path;
 211                }
 212        }
 213        else {
 214                /* be backwards compatible */
 215                if (!strict_paths)
 216                        return path;
 217        }
 218
 219        logerror("'%s': not in whitelist", path);
 220        return NULL;            /* Fallthrough. Deny by default */
 221}
 222
 223typedef int (*daemon_service_fn)(void);
 224struct daemon_service {
 225        const char *name;
 226        const char *config_name;
 227        daemon_service_fn fn;
 228        int enabled;
 229        int overridable;
 230};
 231
 232static struct daemon_service *service_looking_at;
 233static int service_enabled;
 234
 235static int git_daemon_config(const char *var, const char *value, void *cb)
 236{
 237        if (!prefixcmp(var, "daemon.") &&
 238            !strcmp(var + 7, service_looking_at->config_name)) {
 239                service_enabled = git_config_bool(var, value);
 240                return 0;
 241        }
 242
 243        /* we are not interested in parsing any other configuration here */
 244        return 0;
 245}
 246
 247static int run_service(char *dir, struct daemon_service *service)
 248{
 249        const char *path;
 250        int enabled = service->enabled;
 251
 252        loginfo("Request %s for '%s'", service->name, dir);
 253
 254        if (!enabled && !service->overridable) {
 255                logerror("'%s': service not enabled.", service->name);
 256                errno = EACCES;
 257                return -1;
 258        }
 259
 260        if (!(path = path_ok(dir)))
 261                return -1;
 262
 263        /*
 264         * Security on the cheap.
 265         *
 266         * We want a readable HEAD, usable "objects" directory, and
 267         * a "git-daemon-export-ok" flag that says that the other side
 268         * is ok with us doing this.
 269         *
 270         * path_ok() uses enter_repo() and does whitelist checking.
 271         * We only need to make sure the repository is exported.
 272         */
 273
 274        if (!export_all_trees && access("git-daemon-export-ok", F_OK)) {
 275                logerror("'%s': repository not exported.", path);
 276                errno = EACCES;
 277                return -1;
 278        }
 279
 280        if (service->overridable) {
 281                service_looking_at = service;
 282                service_enabled = -1;
 283                git_config(git_daemon_config, NULL);
 284                if (0 <= service_enabled)
 285                        enabled = service_enabled;
 286        }
 287        if (!enabled) {
 288                logerror("'%s': service not enabled for '%s'",
 289                         service->name, path);
 290                errno = EACCES;
 291                return -1;
 292        }
 293
 294        /*
 295         * We'll ignore SIGTERM from now on, we have a
 296         * good client.
 297         */
 298        signal(SIGTERM, SIG_IGN);
 299
 300        return service->fn();
 301}
 302
 303static void copy_to_log(int fd)
 304{
 305        struct strbuf line = STRBUF_INIT;
 306        FILE *fp;
 307
 308        fp = fdopen(fd, "r");
 309        if (fp == NULL) {
 310                logerror("fdopen of error channel failed");
 311                close(fd);
 312                return;
 313        }
 314
 315        while (strbuf_getline(&line, fp, '\n') != EOF) {
 316                logerror("%s", line.buf);
 317                strbuf_setlen(&line, 0);
 318        }
 319
 320        strbuf_release(&line);
 321        fclose(fp);
 322}
 323
 324static int run_service_command(const char **argv)
 325{
 326        struct child_process cld;
 327
 328        memset(&cld, 0, sizeof(cld));
 329        cld.argv = argv;
 330        cld.git_cmd = 1;
 331        cld.err = -1;
 332        if (start_command(&cld))
 333                return -1;
 334
 335        close(0);
 336        close(1);
 337
 338        copy_to_log(cld.err);
 339
 340        return finish_command(&cld);
 341}
 342
 343static int upload_pack(void)
 344{
 345        /* Timeout as string */
 346        char timeout_buf[64];
 347        const char *argv[] = { "upload-pack", "--strict", timeout_buf, ".", NULL };
 348
 349        snprintf(timeout_buf, sizeof timeout_buf, "--timeout=%u", timeout);
 350        return run_service_command(argv);
 351}
 352
 353static int upload_archive(void)
 354{
 355        static const char *argv[] = { "upload-archive", ".", NULL };
 356        return run_service_command(argv);
 357}
 358
 359static int receive_pack(void)
 360{
 361        static const char *argv[] = { "receive-pack", ".", NULL };
 362        return run_service_command(argv);
 363}
 364
 365static struct daemon_service daemon_service[] = {
 366        { "upload-archive", "uploadarch", upload_archive, 0, 1 },
 367        { "upload-pack", "uploadpack", upload_pack, 1, 1 },
 368        { "receive-pack", "receivepack", receive_pack, 0, 1 },
 369};
 370
 371static void enable_service(const char *name, int ena)
 372{
 373        int i;
 374        for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
 375                if (!strcmp(daemon_service[i].name, name)) {
 376                        daemon_service[i].enabled = ena;
 377                        return;
 378                }
 379        }
 380        die("No such service %s", name);
 381}
 382
 383static void make_service_overridable(const char *name, int ena)
 384{
 385        int i;
 386        for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
 387                if (!strcmp(daemon_service[i].name, name)) {
 388                        daemon_service[i].overridable = ena;
 389                        return;
 390                }
 391        }
 392        die("No such service %s", name);
 393}
 394
 395static char *xstrdup_tolower(const char *str)
 396{
 397        char *p, *dup = xstrdup(str);
 398        for (p = dup; *p; p++)
 399                *p = tolower(*p);
 400        return dup;
 401}
 402
 403/*
 404 * Read the host as supplied by the client connection.
 405 */
 406static void parse_host_arg(char *extra_args, int buflen)
 407{
 408        char *val;
 409        int vallen;
 410        char *end = extra_args + buflen;
 411
 412        if (extra_args < end && *extra_args) {
 413                saw_extended_args = 1;
 414                if (strncasecmp("host=", extra_args, 5) == 0) {
 415                        val = extra_args + 5;
 416                        vallen = strlen(val) + 1;
 417                        if (*val) {
 418                                /* Split <host>:<port> at colon. */
 419                                char *host = val;
 420                                char *port = strrchr(host, ':');
 421                                if (port) {
 422                                        *port = 0;
 423                                        port++;
 424                                        free(tcp_port);
 425                                        tcp_port = xstrdup(port);
 426                                }
 427                                free(hostname);
 428                                hostname = xstrdup_tolower(host);
 429                        }
 430
 431                        /* On to the next one */
 432                        extra_args = val + vallen;
 433                }
 434                if (extra_args < end && *extra_args)
 435                        die("Invalid request");
 436        }
 437
 438        /*
 439         * Locate canonical hostname and its IP address.
 440         */
 441        if (hostname) {
 442#ifndef NO_IPV6
 443                struct addrinfo hints;
 444                struct addrinfo *ai;
 445                int gai;
 446                static char addrbuf[HOST_NAME_MAX + 1];
 447
 448                memset(&hints, 0, sizeof(hints));
 449                hints.ai_flags = AI_CANONNAME;
 450
 451                gai = getaddrinfo(hostname, NULL, &hints, &ai);
 452                if (!gai) {
 453                        struct sockaddr_in *sin_addr = (void *)ai->ai_addr;
 454
 455                        inet_ntop(AF_INET, &sin_addr->sin_addr,
 456                                  addrbuf, sizeof(addrbuf));
 457                        free(ip_address);
 458                        ip_address = xstrdup(addrbuf);
 459
 460                        free(canon_hostname);
 461                        canon_hostname = xstrdup(ai->ai_canonname ?
 462                                                 ai->ai_canonname : ip_address);
 463
 464                        freeaddrinfo(ai);
 465                }
 466#else
 467                struct hostent *hent;
 468                struct sockaddr_in sa;
 469                char **ap;
 470                static char addrbuf[HOST_NAME_MAX + 1];
 471
 472                hent = gethostbyname(hostname);
 473
 474                ap = hent->h_addr_list;
 475                memset(&sa, 0, sizeof sa);
 476                sa.sin_family = hent->h_addrtype;
 477                sa.sin_port = htons(0);
 478                memcpy(&sa.sin_addr, *ap, hent->h_length);
 479
 480                inet_ntop(hent->h_addrtype, &sa.sin_addr,
 481                          addrbuf, sizeof(addrbuf));
 482
 483                free(canon_hostname);
 484                canon_hostname = xstrdup(hent->h_name);
 485                free(ip_address);
 486                ip_address = xstrdup(addrbuf);
 487#endif
 488        }
 489}
 490
 491
 492static int execute(struct sockaddr *addr)
 493{
 494        static char line[1000];
 495        int pktlen, len, i;
 496
 497        if (addr) {
 498                char addrbuf[256] = "";
 499                int port = -1;
 500
 501                if (addr->sa_family == AF_INET) {
 502                        struct sockaddr_in *sin_addr = (void *) addr;
 503                        inet_ntop(addr->sa_family, &sin_addr->sin_addr, addrbuf, sizeof(addrbuf));
 504                        port = ntohs(sin_addr->sin_port);
 505#ifndef NO_IPV6
 506                } else if (addr && addr->sa_family == AF_INET6) {
 507                        struct sockaddr_in6 *sin6_addr = (void *) addr;
 508
 509                        char *buf = addrbuf;
 510                        *buf++ = '['; *buf = '\0'; /* stpcpy() is cool */
 511                        inet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf, sizeof(addrbuf) - 1);
 512                        strcat(buf, "]");
 513
 514                        port = ntohs(sin6_addr->sin6_port);
 515#endif
 516                }
 517                loginfo("Connection from %s:%d", addrbuf, port);
 518                setenv("REMOTE_ADDR", addrbuf, 1);
 519        }
 520        else {
 521                unsetenv("REMOTE_ADDR");
 522        }
 523
 524        alarm(init_timeout ? init_timeout : timeout);
 525        pktlen = packet_read_line(0, line, sizeof(line));
 526        alarm(0);
 527
 528        len = strlen(line);
 529        if (pktlen != len)
 530                loginfo("Extended attributes (%d bytes) exist <%.*s>",
 531                        (int) pktlen - len,
 532                        (int) pktlen - len, line + len + 1);
 533        if (len && line[len-1] == '\n') {
 534                line[--len] = 0;
 535                pktlen--;
 536        }
 537
 538        free(hostname);
 539        free(canon_hostname);
 540        free(ip_address);
 541        free(tcp_port);
 542        hostname = canon_hostname = ip_address = tcp_port = NULL;
 543
 544        if (len != pktlen)
 545                parse_host_arg(line + len + 1, pktlen - len - 1);
 546
 547        for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
 548                struct daemon_service *s = &(daemon_service[i]);
 549                int namelen = strlen(s->name);
 550                if (!prefixcmp(line, "git-") &&
 551                    !strncmp(s->name, line + 4, namelen) &&
 552                    line[namelen + 4] == ' ') {
 553                        /*
 554                         * Note: The directory here is probably context sensitive,
 555                         * and might depend on the actual service being performed.
 556                         */
 557                        return run_service(line + namelen + 5, s);
 558                }
 559        }
 560
 561        logerror("Protocol error: '%s'", line);
 562        return -1;
 563}
 564
 565static int max_connections = 32;
 566
 567static unsigned int live_children;
 568
 569static struct child {
 570        struct child *next;
 571        pid_t pid;
 572        struct sockaddr_storage address;
 573} *firstborn;
 574
 575static void add_child(pid_t pid, struct sockaddr *addr, int addrlen)
 576{
 577        struct child *newborn, **cradle;
 578
 579        /*
 580         * This must be xcalloc() -- we'll compare the whole sockaddr_storage
 581         * but individual address may be shorter.
 582         */
 583        newborn = xcalloc(1, sizeof(*newborn));
 584        live_children++;
 585        newborn->pid = pid;
 586        memcpy(&newborn->address, addr, addrlen);
 587        for (cradle = &firstborn; *cradle; cradle = &(*cradle)->next)
 588                if (!memcmp(&(*cradle)->address, &newborn->address,
 589                            sizeof(newborn->address)))
 590                        break;
 591        newborn->next = *cradle;
 592        *cradle = newborn;
 593}
 594
 595static void remove_child(pid_t pid)
 596{
 597        struct child **cradle, *blanket;
 598
 599        for (cradle = &firstborn; (blanket = *cradle); cradle = &blanket->next)
 600                if (blanket->pid == pid) {
 601                        *cradle = blanket->next;
 602                        live_children--;
 603                        free(blanket);
 604                        break;
 605                }
 606}
 607
 608/*
 609 * This gets called if the number of connections grows
 610 * past "max_connections".
 611 *
 612 * We kill the newest connection from a duplicate IP.
 613 */
 614static void kill_some_child(void)
 615{
 616        const struct child *blanket, *next;
 617
 618        if (!(blanket = firstborn))
 619                return;
 620
 621        for (; (next = blanket->next); blanket = next)
 622                if (!memcmp(&blanket->address, &next->address,
 623                            sizeof(next->address))) {
 624                        kill(blanket->pid, SIGTERM);
 625                        break;
 626                }
 627}
 628
 629static void check_dead_children(void)
 630{
 631        int status;
 632        pid_t pid;
 633
 634        while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
 635                const char *dead = "";
 636                remove_child(pid);
 637                if (!WIFEXITED(status) || (WEXITSTATUS(status) > 0))
 638                        dead = " (with error)";
 639                loginfo("[%"PRIuMAX"] Disconnected%s", (uintmax_t)pid, dead);
 640        }
 641}
 642
 643static void handle(int incoming, struct sockaddr *addr, int addrlen)
 644{
 645        pid_t pid;
 646
 647        if (max_connections && live_children >= max_connections) {
 648                kill_some_child();
 649                sleep(1);  /* give it some time to die */
 650                check_dead_children();
 651                if (live_children >= max_connections) {
 652                        close(incoming);
 653                        logerror("Too many children, dropping connection");
 654                        return;
 655                }
 656        }
 657
 658        if ((pid = fork())) {
 659                close(incoming);
 660                if (pid < 0) {
 661                        logerror("Couldn't fork %s", strerror(errno));
 662                        return;
 663                }
 664
 665                add_child(pid, addr, addrlen);
 666                return;
 667        }
 668
 669        dup2(incoming, 0);
 670        dup2(incoming, 1);
 671        close(incoming);
 672
 673        exit(execute(addr));
 674}
 675
 676static void child_handler(int signo)
 677{
 678        /*
 679         * Otherwise empty handler because systemcalls will get interrupted
 680         * upon signal receipt
 681         * SysV needs the handler to be rearmed
 682         */
 683        signal(SIGCHLD, child_handler);
 684}
 685
 686static int set_reuse_addr(int sockfd)
 687{
 688        int on = 1;
 689
 690        if (!reuseaddr)
 691                return 0;
 692        return setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
 693                          &on, sizeof(on));
 694}
 695
 696#ifndef NO_IPV6
 697
 698static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
 699{
 700        int socknum = 0, *socklist = NULL;
 701        int maxfd = -1;
 702        char pbuf[NI_MAXSERV];
 703        struct addrinfo hints, *ai0, *ai;
 704        int gai;
 705        long flags;
 706
 707        sprintf(pbuf, "%d", listen_port);
 708        memset(&hints, 0, sizeof(hints));
 709        hints.ai_family = AF_UNSPEC;
 710        hints.ai_socktype = SOCK_STREAM;
 711        hints.ai_protocol = IPPROTO_TCP;
 712        hints.ai_flags = AI_PASSIVE;
 713
 714        gai = getaddrinfo(listen_addr, pbuf, &hints, &ai0);
 715        if (gai)
 716                die("getaddrinfo() failed: %s", gai_strerror(gai));
 717
 718        for (ai = ai0; ai; ai = ai->ai_next) {
 719                int sockfd;
 720
 721                sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
 722                if (sockfd < 0)
 723                        continue;
 724                if (sockfd >= FD_SETSIZE) {
 725                        logerror("Socket descriptor too large");
 726                        close(sockfd);
 727                        continue;
 728                }
 729
 730#ifdef IPV6_V6ONLY
 731                if (ai->ai_family == AF_INET6) {
 732                        int on = 1;
 733                        setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
 734                                   &on, sizeof(on));
 735                        /* Note: error is not fatal */
 736                }
 737#endif
 738
 739                if (set_reuse_addr(sockfd)) {
 740                        close(sockfd);
 741                        continue;
 742                }
 743
 744                if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
 745                        close(sockfd);
 746                        continue;       /* not fatal */
 747                }
 748                if (listen(sockfd, 5) < 0) {
 749                        close(sockfd);
 750                        continue;       /* not fatal */
 751                }
 752
 753                flags = fcntl(sockfd, F_GETFD, 0);
 754                if (flags >= 0)
 755                        fcntl(sockfd, F_SETFD, flags | FD_CLOEXEC);
 756
 757                socklist = xrealloc(socklist, sizeof(int) * (socknum + 1));
 758                socklist[socknum++] = sockfd;
 759
 760                if (maxfd < sockfd)
 761                        maxfd = sockfd;
 762        }
 763
 764        freeaddrinfo(ai0);
 765
 766        *socklist_p = socklist;
 767        return socknum;
 768}
 769
 770#else /* NO_IPV6 */
 771
 772static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
 773{
 774        struct sockaddr_in sin;
 775        int sockfd;
 776        long flags;
 777
 778        memset(&sin, 0, sizeof sin);
 779        sin.sin_family = AF_INET;
 780        sin.sin_port = htons(listen_port);
 781
 782        if (listen_addr) {
 783                /* Well, host better be an IP address here. */
 784                if (inet_pton(AF_INET, listen_addr, &sin.sin_addr.s_addr) <= 0)
 785                        return 0;
 786        } else {
 787                sin.sin_addr.s_addr = htonl(INADDR_ANY);
 788        }
 789
 790        sockfd = socket(AF_INET, SOCK_STREAM, 0);
 791        if (sockfd < 0)
 792                return 0;
 793
 794        if (set_reuse_addr(sockfd)) {
 795                close(sockfd);
 796                return 0;
 797        }
 798
 799        if ( bind(sockfd, (struct sockaddr *)&sin, sizeof sin) < 0 ) {
 800                close(sockfd);
 801                return 0;
 802        }
 803
 804        if (listen(sockfd, 5) < 0) {
 805                close(sockfd);
 806                return 0;
 807        }
 808
 809        flags = fcntl(sockfd, F_GETFD, 0);
 810        if (flags >= 0)
 811                fcntl(sockfd, F_SETFD, flags | FD_CLOEXEC);
 812
 813        *socklist_p = xmalloc(sizeof(int));
 814        **socklist_p = sockfd;
 815        return 1;
 816}
 817
 818#endif
 819
 820static int service_loop(int socknum, int *socklist)
 821{
 822        struct pollfd *pfd;
 823        int i;
 824
 825        pfd = xcalloc(socknum, sizeof(struct pollfd));
 826
 827        for (i = 0; i < socknum; i++) {
 828                pfd[i].fd = socklist[i];
 829                pfd[i].events = POLLIN;
 830        }
 831
 832        signal(SIGCHLD, child_handler);
 833
 834        for (;;) {
 835                int i;
 836
 837                check_dead_children();
 838
 839                if (poll(pfd, socknum, -1) < 0) {
 840                        if (errno != EINTR) {
 841                                logerror("Poll failed, resuming: %s",
 842                                      strerror(errno));
 843                                sleep(1);
 844                        }
 845                        continue;
 846                }
 847
 848                for (i = 0; i < socknum; i++) {
 849                        if (pfd[i].revents & POLLIN) {
 850                                struct sockaddr_storage ss;
 851                                unsigned int sslen = sizeof(ss);
 852                                int incoming = accept(pfd[i].fd, (struct sockaddr *)&ss, &sslen);
 853                                if (incoming < 0) {
 854                                        switch (errno) {
 855                                        case EAGAIN:
 856                                        case EINTR:
 857                                        case ECONNABORTED:
 858                                                continue;
 859                                        default:
 860                                                die_errno("accept returned");
 861                                        }
 862                                }
 863                                handle(incoming, (struct sockaddr *)&ss, sslen);
 864                        }
 865                }
 866        }
 867}
 868
 869/* if any standard file descriptor is missing open it to /dev/null */
 870static void sanitize_stdfds(void)
 871{
 872        int fd = open("/dev/null", O_RDWR, 0);
 873        while (fd != -1 && fd < 2)
 874                fd = dup(fd);
 875        if (fd == -1)
 876                die_errno("open /dev/null or dup failed");
 877        if (fd > 2)
 878                close(fd);
 879}
 880
 881static void daemonize(void)
 882{
 883        switch (fork()) {
 884                case 0:
 885                        break;
 886                case -1:
 887                        die_errno("fork failed");
 888                default:
 889                        exit(0);
 890        }
 891        if (setsid() == -1)
 892                die_errno("setsid failed");
 893        close(0);
 894        close(1);
 895        close(2);
 896        sanitize_stdfds();
 897}
 898
 899static void store_pid(const char *path)
 900{
 901        FILE *f = fopen(path, "w");
 902        if (!f)
 903                die_errno("cannot open pid file '%s'", path);
 904        if (fprintf(f, "%"PRIuMAX"\n", (uintmax_t) getpid()) < 0 || fclose(f) != 0)
 905                die_errno("failed to write pid file '%s'", path);
 906}
 907
 908static int serve(char *listen_addr, int listen_port, struct passwd *pass, gid_t gid)
 909{
 910        int socknum, *socklist;
 911
 912        socknum = socksetup(listen_addr, listen_port, &socklist);
 913        if (socknum == 0)
 914                die("unable to allocate any listen sockets on host %s port %u",
 915                    listen_addr, listen_port);
 916
 917        if (pass && gid &&
 918            (initgroups(pass->pw_name, gid) || setgid (gid) ||
 919             setuid(pass->pw_uid)))
 920                die("cannot drop privileges");
 921
 922        return service_loop(socknum, socklist);
 923}
 924
 925int main(int argc, char **argv)
 926{
 927        int listen_port = 0;
 928        char *listen_addr = NULL;
 929        int inetd_mode = 0;
 930        const char *pid_file = NULL, *user_name = NULL, *group_name = NULL;
 931        int detach = 0;
 932        struct passwd *pass = NULL;
 933        struct group *group;
 934        gid_t gid = 0;
 935        int i;
 936
 937        git_extract_argv0_path(argv[0]);
 938
 939        for (i = 1; i < argc; i++) {
 940                char *arg = argv[i];
 941
 942                if (!prefixcmp(arg, "--listen=")) {
 943                        listen_addr = xstrdup_tolower(arg + 9);
 944                        continue;
 945                }
 946                if (!prefixcmp(arg, "--port=")) {
 947                        char *end;
 948                        unsigned long n;
 949                        n = strtoul(arg+7, &end, 0);
 950                        if (arg[7] && !*end) {
 951                                listen_port = n;
 952                                continue;
 953                        }
 954                }
 955                if (!strcmp(arg, "--inetd")) {
 956                        inetd_mode = 1;
 957                        log_syslog = 1;
 958                        continue;
 959                }
 960                if (!strcmp(arg, "--verbose")) {
 961                        verbose = 1;
 962                        continue;
 963                }
 964                if (!strcmp(arg, "--syslog")) {
 965                        log_syslog = 1;
 966                        continue;
 967                }
 968                if (!strcmp(arg, "--export-all")) {
 969                        export_all_trees = 1;
 970                        continue;
 971                }
 972                if (!prefixcmp(arg, "--timeout=")) {
 973                        timeout = atoi(arg+10);
 974                        continue;
 975                }
 976                if (!prefixcmp(arg, "--init-timeout=")) {
 977                        init_timeout = atoi(arg+15);
 978                        continue;
 979                }
 980                if (!prefixcmp(arg, "--max-connections=")) {
 981                        max_connections = atoi(arg+18);
 982                        if (max_connections < 0)
 983                                max_connections = 0;            /* unlimited */
 984                        continue;
 985                }
 986                if (!strcmp(arg, "--strict-paths")) {
 987                        strict_paths = 1;
 988                        continue;
 989                }
 990                if (!prefixcmp(arg, "--base-path=")) {
 991                        base_path = arg+12;
 992                        continue;
 993                }
 994                if (!strcmp(arg, "--base-path-relaxed")) {
 995                        base_path_relaxed = 1;
 996                        continue;
 997                }
 998                if (!prefixcmp(arg, "--interpolated-path=")) {
 999                        interpolated_path = arg+20;
1000                        continue;
1001                }
1002                if (!strcmp(arg, "--reuseaddr")) {
1003                        reuseaddr = 1;
1004                        continue;
1005                }
1006                if (!strcmp(arg, "--user-path")) {
1007                        user_path = "";
1008                        continue;
1009                }
1010                if (!prefixcmp(arg, "--user-path=")) {
1011                        user_path = arg + 12;
1012                        continue;
1013                }
1014                if (!prefixcmp(arg, "--pid-file=")) {
1015                        pid_file = arg + 11;
1016                        continue;
1017                }
1018                if (!strcmp(arg, "--detach")) {
1019                        detach = 1;
1020                        log_syslog = 1;
1021                        continue;
1022                }
1023                if (!prefixcmp(arg, "--user=")) {
1024                        user_name = arg + 7;
1025                        continue;
1026                }
1027                if (!prefixcmp(arg, "--group=")) {
1028                        group_name = arg + 8;
1029                        continue;
1030                }
1031                if (!prefixcmp(arg, "--enable=")) {
1032                        enable_service(arg + 9, 1);
1033                        continue;
1034                }
1035                if (!prefixcmp(arg, "--disable=")) {
1036                        enable_service(arg + 10, 0);
1037                        continue;
1038                }
1039                if (!prefixcmp(arg, "--allow-override=")) {
1040                        make_service_overridable(arg + 17, 1);
1041                        continue;
1042                }
1043                if (!prefixcmp(arg, "--forbid-override=")) {
1044                        make_service_overridable(arg + 18, 0);
1045                        continue;
1046                }
1047                if (!strcmp(arg, "--")) {
1048                        ok_paths = &argv[i+1];
1049                        break;
1050                } else if (arg[0] != '-') {
1051                        ok_paths = &argv[i];
1052                        break;
1053                }
1054
1055                usage(daemon_usage);
1056        }
1057
1058        if (log_syslog) {
1059                openlog("git-daemon", LOG_PID, LOG_DAEMON);
1060                set_die_routine(daemon_die);
1061        } else
1062                /* avoid splitting a message in the middle */
1063                setvbuf(stderr, NULL, _IOLBF, 0);
1064
1065        if (inetd_mode && (group_name || user_name))
1066                die("--user and --group are incompatible with --inetd");
1067
1068        if (inetd_mode && (listen_port || listen_addr))
1069                die("--listen= and --port= are incompatible with --inetd");
1070        else if (listen_port == 0)
1071                listen_port = DEFAULT_GIT_PORT;
1072
1073        if (group_name && !user_name)
1074                die("--group supplied without --user");
1075
1076        if (user_name) {
1077                pass = getpwnam(user_name);
1078                if (!pass)
1079                        die("user not found - %s", user_name);
1080
1081                if (!group_name)
1082                        gid = pass->pw_gid;
1083                else {
1084                        group = getgrnam(group_name);
1085                        if (!group)
1086                                die("group not found - %s", group_name);
1087
1088                        gid = group->gr_gid;
1089                }
1090        }
1091
1092        if (strict_paths && (!ok_paths || !*ok_paths))
1093                die("option --strict-paths requires a whitelist");
1094
1095        if (base_path && !is_directory(base_path))
1096                die("base-path '%s' does not exist or is not a directory",
1097                    base_path);
1098
1099        if (inetd_mode) {
1100                struct sockaddr_storage ss;
1101                struct sockaddr *peer = (struct sockaddr *)&ss;
1102                socklen_t slen = sizeof(ss);
1103
1104                if (!freopen("/dev/null", "w", stderr))
1105                        die_errno("failed to redirect stderr to /dev/null");
1106
1107                if (getpeername(0, peer, &slen))
1108                        peer = NULL;
1109
1110                return execute(peer);
1111        }
1112
1113        if (detach) {
1114                daemonize();
1115                loginfo("Ready to rumble");
1116        }
1117        else
1118                sanitize_stdfds();
1119
1120        if (pid_file)
1121                store_pid(pid_file);
1122
1123        return serve(listen_addr, listen_port, pass, gid);
1124}