daemon.c 24.5 KB
Newer Older
1
#include "cache.h"
2
#include "pkt-line.h"
3
#include "exec_cmd.h"
P
Petr Baudis 已提交
4

5 6
#include <syslog.h>

7 8 9 10
#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 256
#endif

11 12 13 14
#ifndef NI_MAXSERV
#define NI_MAXSERV 32
#endif

15
static int log_syslog;
P
Petr Baudis 已提交
16
static int verbose;
17
static int reuseaddr;
P
Petr Baudis 已提交
18

19
static const char daemon_usage[] =
S
Stephan Beyer 已提交
20
"git daemon [--verbose] [--syslog] [--export-all]\n"
21 22
"           [--timeout=n] [--init-timeout=n] [--max-connections=n]\n"
"           [--strict-paths] [--base-path=path] [--base-path-relaxed]\n"
J
Jens Axboe 已提交
23
"           [--user-path | --user-path=path]\n"
24
"           [--interpolated-path=path]\n"
25
"           [--reuseaddr] [--detach] [--pid-file=file]\n"
26
"           [--[enable|disable|allow-override|forbid-override]=service]\n"
27 28 29
"           [--inetd | [--listen=host_or_ipaddr] [--port=n]\n"
"                      [--user=user [--group=group]]\n"
"           [directory...]";
30 31

/* List of acceptable pathname prefixes */
32 33
static char **ok_paths;
static int strict_paths;
34 35

/* If this is set, git-daemon-export-ok is not required */
36
static int export_all_trees;
P
Petr Baudis 已提交
37

P
Petr Baudis 已提交
38
/* Take all paths relative to this one if non-NULL */
39
static char *base_path;
40
static char *interpolated_path;
J
Jens Axboe 已提交
41
static int base_path_relaxed;
42 43 44

/* Flag indicating client sent extra args. */
static int saw_extended_args;
P
Petr Baudis 已提交
45

46 47 48 49
/* 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.
 */
50
static const char *user_path;
51

52
/* Timeout, and initial timeout */
53 54
static unsigned int timeout;
static unsigned int init_timeout;
P
Petr Baudis 已提交
55

56 57 58 59
static char *hostname;
static char *canon_hostname;
static char *ip_address;
static char *tcp_port;
60

61
static void logreport(int priority, const char *err, va_list params)
P
Petr Baudis 已提交
62
{
63
	if (log_syslog) {
64 65
		char buf[1024];
		vsnprintf(buf, sizeof(buf), err, params);
66
		syslog(priority, "%s", buf);
J
Junio C Hamano 已提交
67 68 69
	} else {
		/*
		 * Since stderr is set to linebuffered mode, the
70 71
		 * logging of different processes will not overlap
		 */
72
		fprintf(stderr, "[%"PRIuMAX"] ", (uintmax_t)getpid());
73 74 75
		vfprintf(stderr, err, params);
		fputc('\n', stderr);
	}
P
Petr Baudis 已提交
76 77
}

78
static void logerror(const char *err, ...)
P
Petr Baudis 已提交
79 80 81
{
	va_list params;
	va_start(params, err);
82
	logreport(LOG_ERR, err, params);
P
Petr Baudis 已提交
83 84 85
	va_end(params);
}

86
static void loginfo(const char *err, ...)
P
Petr Baudis 已提交
87 88 89 90 91
{
	va_list params;
	if (!verbose)
		return;
	va_start(params, err);
92
	logreport(LOG_INFO, err, params);
P
Petr Baudis 已提交
93 94
	va_end(params);
}
95

96 97 98 99 100 101
static void NORETURN daemon_die(const char *err, va_list params)
{
	logreport(LOG_ERR, err, params);
	exit(1);
}

102 103 104 105
static int avoid_alias(char *p)
{
	int sl, ndot;

J
Junio C Hamano 已提交
106
	/*
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
	 * This resurrects the belts and suspenders paranoia check by HPA
	 * done in <435560F7.4080006@zytor.com> thread, now enter_repo()
	 * does not do getcwd() based path canonicalizations.
	 *
	 * sl becomes true immediately after seeing '/' and continues to
	 * be true as long as dots continue after that without intervening
	 * non-dot character.
	 */
	if (!p || (*p != '/' && *p != '~'))
		return -1;
	sl = 1; ndot = 0;
	p++;

	while (1) {
		char ch = *p++;
		if (sl) {
			if (ch == '.')
				ndot++;
			else if (ch == '/') {
				if (ndot < 3)
					/* reject //, /./ and /../ */
					return -1;
				ndot = 0;
			}
			else if (ch == 0) {
				if (0 < ndot && ndot < 3)
					/* reject /.$ and /..$ */
					return -1;
				return 0;
			}
			else
				sl = ndot = 0;
		}
		else if (ch == 0)
			return 0;
		else if (ch == '/') {
			sl = 1;
			ndot = 0;
		}
	}
}

149
static char *path_ok(char *directory)
150
{
151
	static char rpath[PATH_MAX];
152
	static char interp_path[PATH_MAX];
153
	char *path;
154 155
	char *dir;

156
	dir = directory;
157 158 159 160 161 162

	if (avoid_alias(dir)) {
		logerror("'%s': aliased", dir);
		return NULL;
	}

163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
	if (*dir == '~') {
		if (!user_path) {
			logerror("'%s': User-path not allowed", dir);
			return NULL;
		}
		if (*user_path) {
			/* Got either "~alice" or "~alice/foo";
			 * rewrite them to "~alice/%s" or
			 * "~alice/%s/foo".
			 */
			int namlen, restlen = strlen(dir);
			char *slash = strchr(dir, '/');
			if (!slash)
				slash = dir + restlen;
			namlen = slash - dir;
			restlen -= namlen;
			loginfo("userpath <%s>, request <%s>, namlen %d, restlen %d, slash <%s>", user_path, dir, namlen, restlen, slash);
			snprintf(rpath, PATH_MAX, "%.*s/%s%.*s",
				 namlen, dir, user_path, restlen, slash);
			dir = rpath;
		}
	}
185
	else if (interpolated_path && saw_extended_args) {
186 187 188 189 190 191 192 193 194 195 196
		struct strbuf expanded_path = STRBUF_INIT;
		struct strbuf_expand_dict_entry dict[] = {
			{ "H", hostname },
			{ "CH", canon_hostname },
			{ "IP", ip_address },
			{ "P", tcp_port },
			{ "D", directory },
			{ "%", "%" },
			{ NULL }
		};

197 198 199 200 201 202
		if (*dir != '/') {
			/* Allow only absolute */
			logerror("'%s': Non-absolute path denied (interpolated-path active)", dir);
			return NULL;
		}

203 204 205 206
		strbuf_expand(&expanded_path, interpolated_path,
				strbuf_expand_dict_cb, &dict);
		strlcpy(interp_path, expanded_path.buf, PATH_MAX);
		strbuf_release(&expanded_path);
207 208 209 210
		loginfo("Interpolated dir '%s'", interp_path);

		dir = interp_path;
	}
211 212 213
	else if (base_path) {
		if (*dir != '/') {
			/* Allow only absolute */
214
			logerror("'%s': Non-absolute path denied (base-path active)", dir);
P
Petr Baudis 已提交
215 216
			return NULL;
		}
217 218
		snprintf(rpath, PATH_MAX, "%s%s", base_path, dir);
		dir = rpath;
P
Petr Baudis 已提交
219 220
	}

221 222
	path = enter_repo(dir, strict_paths);
	if (!path && base_path && base_path_relaxed) {
J
Jens Axboe 已提交
223 224 225 226
		/*
		 * if we fail and base_path_relaxed is enabled, try without
		 * prefixing the base path
		 */
227 228 229
		dir = directory;
		path = enter_repo(dir, strict_paths);
	}
230

231 232 233
	if (!path) {
		logerror("'%s': unable to chdir or not a git archive", dir);
		return NULL;
234 235 236
	}

	if ( ok_paths && *ok_paths ) {
J
Junio C Hamano 已提交
237
		char **pp;
238
		int pathlen = strlen(path);
239

J
Junio C Hamano 已提交
240
		/* The validation is done on the paths after enter_repo
J
Junio C Hamano 已提交
241
		 * appends optional {.git,.git/.git} and friends, but
242 243 244 245
		 * it does not use getcwd().  So if your /pub is
		 * a symlink to /mnt/pub, you can whitelist /pub and
		 * do not have to say /mnt/pub.
		 * Do not say /pub/.
J
Junio C Hamano 已提交
246
		 */
247 248
		for ( pp = ok_paths ; *pp ; pp++ ) {
			int len = strlen(*pp);
J
Junio C Hamano 已提交
249 250 251 252 253
			if (len <= pathlen &&
			    !memcmp(*pp, path, len) &&
			    (path[len] == '\0' ||
			     (!strict_paths && path[len] == '/')))
				return path;
254
		}
255 256 257 258 259
	}
	else {
		/* be backwards compatible */
		if (!strict_paths)
			return path;
260 261
	}

262 263
	logerror("'%s': not in whitelist", path);
	return NULL;		/* Fallthrough. Deny by default */
264
}
265

266 267 268 269 270 271 272 273 274 275 276 277
typedef int (*daemon_service_fn)(void);
struct daemon_service {
	const char *name;
	const char *config_name;
	daemon_service_fn fn;
	int enabled;
	int overridable;
};

static struct daemon_service *service_looking_at;
static int service_enabled;

278
static int git_daemon_config(const char *var, const char *value, void *cb)
279
{
280
	if (!prefixcmp(var, "daemon.") &&
281 282 283 284 285 286 287 288 289
	    !strcmp(var + 7, service_looking_at->config_name)) {
		service_enabled = git_config_bool(var, value);
		return 0;
	}

	/* we are not interested in parsing any other configuration here */
	return 0;
}

290
static int run_service(char *dir, struct daemon_service *service)
291
{
292
	const char *path;
293 294
	int enabled = service->enabled;

295
	loginfo("Request %s for '%s'", service->name, dir);
296

297 298 299 300 301
	if (!enabled && !service->overridable) {
		logerror("'%s': service not enabled.", service->name);
		errno = EACCES;
		return -1;
	}
302

303
	if (!(path = path_ok(dir)))
304
		return -1;
H
H. Peter Anvin 已提交
305

306 307 308
	/*
	 * Security on the cheap.
	 *
309
	 * We want a readable HEAD, usable "objects" directory, and
310 311
	 * a "git-daemon-export-ok" flag that says that the other side
	 * is ok with us doing this.
312 313 314
	 *
	 * path_ok() uses enter_repo() and does whitelist checking.
	 * We only need to make sure the repository is exported.
315
	 */
316

317
	if (!export_all_trees && access("git-daemon-export-ok", F_OK)) {
318
		logerror("'%s': repository not exported.", path);
319 320 321 322
		errno = EACCES;
		return -1;
	}

323 324 325
	if (service->overridable) {
		service_looking_at = service;
		service_enabled = -1;
326
		git_config(git_daemon_config, NULL);
327 328 329 330 331 332 333 334 335 336
		if (0 <= service_enabled)
			enabled = service_enabled;
	}
	if (!enabled) {
		logerror("'%s': service not enabled for '%s'",
			 service->name, path);
		errno = EACCES;
		return -1;
	}

337 338 339 340 341 342
	/*
	 * We'll ignore SIGTERM from now on, we have a
	 * good client.
	 */
	signal(SIGTERM, SIG_IGN);

343 344 345 346 347 348 349 350
	return service->fn();
}

static int upload_pack(void)
{
	/* Timeout as string */
	char timeout_buf[64];

351 352
	snprintf(timeout_buf, sizeof timeout_buf, "--timeout=%u", timeout);

353
	/* git-upload-pack only ever reads stuff, so this is safe */
354
	execl_git_cmd("upload-pack", "--strict", timeout_buf, ".", NULL);
355 356 357
	return -1;
}

F
Franck Bui-Huu 已提交
358 359 360 361 362 363
static int upload_archive(void)
{
	execl_git_cmd("upload-archive", ".", NULL);
	return -1;
}

L
Linus Torvalds 已提交
364 365 366 367 368 369
static int receive_pack(void)
{
	execl_git_cmd("receive-pack", ".", NULL);
	return -1;
}

370
static struct daemon_service daemon_service[] = {
F
Franck Bui-Huu 已提交
371
	{ "upload-archive", "uploadarch", upload_archive, 0, 1 },
372
	{ "upload-pack", "uploadpack", upload_pack, 1, 1 },
L
Linus Torvalds 已提交
373
	{ "receive-pack", "receivepack", receive_pack, 0, 1 },
374 375
};

376 377
static void enable_service(const char *name, int ena)
{
378 379 380 381 382 383 384 385 386 387
	int i;
	for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
		if (!strcmp(daemon_service[i].name, name)) {
			daemon_service[i].enabled = ena;
			return;
		}
	}
	die("No such service %s", name);
}

388 389
static void make_service_overridable(const char *name, int ena)
{
390 391 392 393 394 395 396 397 398 399
	int i;
	for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
		if (!strcmp(daemon_service[i].name, name)) {
			daemon_service[i].overridable = ena;
			return;
		}
	}
	die("No such service %s", name);
}

400 401 402 403 404 405 406 407
static char *xstrdup_tolower(const char *str)
{
	char *p, *dup = xstrdup(str);
	for (p = dup; *p; p++)
		*p = tolower(*p);
	return dup;
}

408 409 410
/*
 * Separate the "extra args" information as supplied by the client connection.
 */
411
static void parse_extra_args(char *extra_args, int buflen)
412 413 414 415 416 417 418 419 420 421 422
{
	char *val;
	int vallen;
	char *end = extra_args + buflen;

	while (extra_args < end && *extra_args) {
		saw_extended_args = 1;
		if (strncasecmp("host=", extra_args, 5) == 0) {
			val = extra_args + 5;
			vallen = strlen(val) + 1;
			if (*val) {
423 424 425
				/* Split <host>:<port> at colon. */
				char *host = val;
				char *port = strrchr(host, ':');
426 427 428
				if (port) {
					*port = 0;
					port++;
429 430
					free(tcp_port);
					tcp_port = xstrdup(port);
431
				}
432
				free(hostname);
433
				hostname = xstrdup_tolower(host);
434
			}
435

436 437 438 439
			/* On to the next one */
			extra_args = val + vallen;
		}
	}
440 441 442 443

	/*
	 * Locate canonical hostname and its IP address.
	 */
444
	if (hostname) {
445 446 447 448 449 450 451 452 453
#ifndef NO_IPV6
		struct addrinfo hints;
		struct addrinfo *ai, *ai0;
		int gai;
		static char addrbuf[HOST_NAME_MAX + 1];

		memset(&hints, 0, sizeof(hints));
		hints.ai_flags = AI_CANONNAME;

454
		gai = getaddrinfo(hostname, 0, &hints, &ai0);
455 456 457 458 459 460
		if (!gai) {
			for (ai = ai0; ai; ai = ai->ai_next) {
				struct sockaddr_in *sin_addr = (void *)ai->ai_addr;

				inet_ntop(AF_INET, &sin_addr->sin_addr,
					  addrbuf, sizeof(addrbuf));
461 462 463 464
				free(canon_hostname);
				canon_hostname = xstrdup(ai->ai_canonname);
				free(ip_address);
				ip_address = xstrdup(addrbuf);
465 466 467 468 469 470 471 472 473 474
				break;
			}
			freeaddrinfo(ai0);
		}
#else
		struct hostent *hent;
		struct sockaddr_in sa;
		char **ap;
		static char addrbuf[HOST_NAME_MAX + 1];

475
		hent = gethostbyname(hostname);
476 477 478 479 480 481 482 483 484

		ap = hent->h_addr_list;
		memset(&sa, 0, sizeof sa);
		sa.sin_family = hent->h_addrtype;
		sa.sin_port = htons(0);
		memcpy(&sa.sin_addr, *ap, hent->h_length);

		inet_ntop(hent->h_addrtype, &sa.sin_addr,
			  addrbuf, sizeof(addrbuf));
485

486 487 488 489
		free(canon_hostname);
		canon_hostname = xstrdup(hent->h_name);
		free(ip_address);
		ip_address = xstrdup(addrbuf);
490
#endif
491
	}
492 493 494
}


495
static int execute(struct sockaddr *addr)
496
{
497
	static char line[1000];
498
	int pktlen, len, i;
499

500 501 502 503 504 505 506
	if (addr) {
		char addrbuf[256] = "";
		int port = -1;

		if (addr->sa_family == AF_INET) {
			struct sockaddr_in *sin_addr = (void *) addr;
			inet_ntop(addr->sa_family, &sin_addr->sin_addr, addrbuf, sizeof(addrbuf));
507
			port = ntohs(sin_addr->sin_port);
508 509 510 511 512 513 514 515 516
#ifndef NO_IPV6
		} else if (addr && addr->sa_family == AF_INET6) {
			struct sockaddr_in6 *sin6_addr = (void *) addr;

			char *buf = addrbuf;
			*buf++ = '['; *buf = '\0'; /* stpcpy() is cool */
			inet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf, sizeof(addrbuf) - 1);
			strcat(buf, "]");

517
			port = ntohs(sin6_addr->sin6_port);
518 519 520
#endif
		}
		loginfo("Connection from %s:%d", addrbuf, port);
521 522 523 524
		setenv("REMOTE_ADDR", addrbuf, 1);
	}
	else {
		unsetenv("REMOTE_ADDR");
525 526
	}

527
	alarm(init_timeout ? init_timeout : timeout);
528
	pktlen = packet_read_line(0, line, sizeof(line));
529
	alarm(0);
530

531 532 533 534 535
	len = strlen(line);
	if (pktlen != len)
		loginfo("Extended attributes (%d bytes) exist <%.*s>",
			(int) pktlen - len,
			(int) pktlen - len, line + len + 1);
536
	if (len && line[len-1] == '\n') {
537
		line[--len] = 0;
538 539
		pktlen--;
	}
540

541 542 543 544
	free(hostname);
	free(canon_hostname);
	free(ip_address);
	free(tcp_port);
545
	hostname = canon_hostname = ip_address = tcp_port = NULL;
546

547
	if (len != pktlen)
548
		parse_extra_args(line + len + 1, pktlen - len - 1);
549

550 551 552
	for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
		struct daemon_service *s = &(daemon_service[i]);
		int namelen = strlen(s->name);
553
		if (!prefixcmp(line, "git-") &&
554
		    !strncmp(s->name, line + 4, namelen) &&
555
		    line[namelen + 4] == ' ') {
556 557 558 559
			/*
			 * Note: The directory here is probably context sensitive,
			 * and might depend on the actual service being performed.
			 */
560
			return run_service(line + namelen + 5, s);
561
		}
562
	}
563

P
Petr Baudis 已提交
564
	logerror("Protocol error: '%s'", line);
565 566 567
	return -1;
}

568
static int max_connections = 32;
569

570
static unsigned int live_children;
571

L
Linus Torvalds 已提交
572
static struct child {
573
	struct child *next;
574
	pid_t pid;
575
	struct sockaddr_storage address;
576
} *firstborn;
577

578
static void add_child(pid_t pid, struct sockaddr *addr, int addrlen)
579
{
J
Junio C Hamano 已提交
580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
	struct child *newborn, **cradle;

	/*
	 * This must be xcalloc() -- we'll compare the whole sockaddr_storage
	 * but individual address may be shorter.
	 */
	newborn = xcalloc(1, sizeof(*newborn));
	live_children++;
	newborn->pid = pid;
	memcpy(&newborn->address, addr, addrlen);
	for (cradle = &firstborn; *cradle; cradle = &(*cradle)->next)
		if (!memcmp(&(*cradle)->address, &newborn->address,
			    sizeof(newborn->address)))
			break;
	newborn->next = *cradle;
	*cradle = newborn;
596 597
}

598
static void remove_child(pid_t pid)
599
{
600
	struct child **cradle, *blanket;
601

602 603 604 605 606 607 608
	for (cradle = &firstborn; (blanket = *cradle); cradle = &blanket->next)
		if (blanket->pid == pid) {
			*cradle = blanket->next;
			live_children--;
			free(blanket);
			break;
		}
609 610 611 612 613 614
}

/*
 * This gets called if the number of connections grows
 * past "max_connections".
 *
615
 * We kill the newest connection from a duplicate IP.
616
 */
617
static void kill_some_child(void)
618
{
J
Junio C Hamano 已提交
619
	const struct child *blanket, *next;
620

J
Junio C Hamano 已提交
621 622
	if (!(blanket = firstborn))
		return;
623

J
Junio C Hamano 已提交
624 625 626 627 628 629
	for (; (next = blanket->next); blanket = next)
		if (!memcmp(&blanket->address, &next->address,
			    sizeof(next->address))) {
			kill(blanket->pid, SIGTERM);
			break;
		}
630 631
}

632
static void check_dead_children(void)
633
{
634 635
	int status;
	pid_t pid;
636

J
Junio C Hamano 已提交
637
	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
638 639
		const char *dead = "";
		remove_child(pid);
J
Junio C Hamano 已提交
640
		if (!WIFEXITED(status) || (WEXITSTATUS(status) > 0))
641
			dead = " (with error)";
642
		loginfo("[%"PRIuMAX"] Disconnected%s", (uintmax_t)pid, dead);
643 644 645
	}
}

J
Junio C Hamano 已提交
646
static void handle(int incoming, struct sockaddr *addr, int addrlen)
647
{
648
	pid_t pid;
649

650 651
	if (max_connections && live_children >= max_connections) {
		kill_some_child();
J
Junio C Hamano 已提交
652
		sleep(1);  /* give it some time to die */
653 654 655 656 657 658 659
		check_dead_children();
		if (live_children >= max_connections) {
			close(incoming);
			logerror("Too many children, dropping connection");
			return;
		}
	}
660

661
	if ((pid = fork())) {
662
		close(incoming);
663 664
		if (pid < 0) {
			logerror("Couldn't fork %s", strerror(errno));
665
			return;
666
		}
667

668
		add_child(pid, addr, addrlen);
669 670 671 672 673 674
		return;
	}

	dup2(incoming, 0);
	dup2(incoming, 1);
	close(incoming);
P
Petr Baudis 已提交
675

676
	exit(execute(addr));
677 678
}

679 680
static void child_handler(int signo)
{
J
Junio C Hamano 已提交
681 682
	/*
	 * Otherwise empty handler because systemcalls will get interrupted
683 684 685
	 * upon signal receipt
	 * SysV needs the handler to be rearmed
	 */
686
	signal(SIGCHLD, child_handler);
687 688
}

689 690 691 692 693 694 695 696 697 698
static int set_reuse_addr(int sockfd)
{
	int on = 1;

	if (!reuseaddr)
		return 0;
	return setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
			  &on, sizeof(on));
}

P
Peter Anvin 已提交
699 700
#ifndef NO_IPV6

701
static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
702
{
703 704 705
	int socknum = 0, *socklist = NULL;
	int maxfd = -1;
	char pbuf[NI_MAXSERV];
P
Peter Anvin 已提交
706 707
	struct addrinfo hints, *ai0, *ai;
	int gai;
708
	long flags;
709

710
	sprintf(pbuf, "%d", listen_port);
711 712 713 714 715 716
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;
	hints.ai_flags = AI_PASSIVE;

717
	gai = getaddrinfo(listen_addr, pbuf, &hints, &ai0);
718
	if (gai)
719
		die("getaddrinfo() failed: %s", gai_strerror(gai));
720 721 722 723 724 725 726 727

	for (ai = ai0; ai; ai = ai->ai_next) {
		int sockfd;

		sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
		if (sockfd < 0)
			continue;
		if (sockfd >= FD_SETSIZE) {
728
			logerror("Socket descriptor too large");
729 730 731 732 733 734 735 736 737 738 739 740 741
			close(sockfd);
			continue;
		}

#ifdef IPV6_V6ONLY
		if (ai->ai_family == AF_INET6) {
			int on = 1;
			setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
				   &on, sizeof(on));
			/* Note: error is not fatal */
		}
#endif

742 743
		if (set_reuse_addr(sockfd)) {
			close(sockfd);
744
			continue;
745 746
		}

747 748 749 750 751 752 753 754 755
		if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
			close(sockfd);
			continue;	/* not fatal */
		}
		if (listen(sockfd, 5) < 0) {
			close(sockfd);
			continue;	/* not fatal */
		}

756 757 758 759
		flags = fcntl(sockfd, F_GETFD, 0);
		if (flags >= 0)
			fcntl(sockfd, F_SETFD, flags | FD_CLOEXEC);

J
Jonas Fonseca 已提交
760
		socklist = xrealloc(socklist, sizeof(int) * (socknum + 1));
761 762 763 764 765 766 767 768
		socklist[socknum++] = sockfd;

		if (maxfd < sockfd)
			maxfd = sockfd;
	}

	freeaddrinfo(ai0);

P
Peter Anvin 已提交
769 770 771 772 773 774
	*socklist_p = socklist;
	return socknum;
}

#else /* NO_IPV6 */

775
static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
P
Peter Anvin 已提交
776 777 778
{
	struct sockaddr_in sin;
	int sockfd;
779
	long flags;
P
Peter Anvin 已提交
780

781 782 783 784 785 786 787 788 789 790 791 792
	memset(&sin, 0, sizeof sin);
	sin.sin_family = AF_INET;
	sin.sin_port = htons(listen_port);

	if (listen_addr) {
		/* Well, host better be an IP address here. */
		if (inet_pton(AF_INET, listen_addr, &sin.sin_addr.s_addr) <= 0)
			return 0;
	} else {
		sin.sin_addr.s_addr = htonl(INADDR_ANY);
	}

P
Peter Anvin 已提交
793 794 795 796
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if (sockfd < 0)
		return 0;

797 798 799 800 801
	if (set_reuse_addr(sockfd)) {
		close(sockfd);
		return 0;
	}

P
Peter Anvin 已提交
802 803 804 805
	if ( bind(sockfd, (struct sockaddr *)&sin, sizeof sin) < 0 ) {
		close(sockfd);
		return 0;
	}
806

807 808 809 810 811
	if (listen(sockfd, 5) < 0) {
		close(sockfd);
		return 0;
	}

812 813 814 815
	flags = fcntl(sockfd, F_GETFD, 0);
	if (flags >= 0)
		fcntl(sockfd, F_SETFD, flags | FD_CLOEXEC);

H
H. Peter Anvin 已提交
816
	*socklist_p = xmalloc(sizeof(int));
P
Peter Anvin 已提交
817
	**socklist_p = sockfd;
818
	return 1;
P
Peter Anvin 已提交
819 820 821 822 823 824 825 826 827
}

#endif

static int service_loop(int socknum, int *socklist)
{
	struct pollfd *pfd;
	int i;

828
	pfd = xcalloc(socknum, sizeof(struct pollfd));
P
Peter Anvin 已提交
829 830 831 832 833

	for (i = 0; i < socknum; i++) {
		pfd[i].fd = socklist[i];
		pfd[i].events = POLLIN;
	}
834 835

	signal(SIGCHLD, child_handler);
836 837

	for (;;) {
838
		int i;
P
Peter Anvin 已提交
839

840 841 842
		check_dead_children();

		if (poll(pfd, socknum, -1) < 0) {
843
			if (errno != EINTR) {
844
				logerror("Poll failed, resuming: %s",
845 846 847
				      strerror(errno));
				sleep(1);
			}
848 849 850 851
			continue;
		}

		for (i = 0; i < socknum; i++) {
P
Peter Anvin 已提交
852
			if (pfd[i].revents & POLLIN) {
853
				struct sockaddr_storage ss;
854
				unsigned int sslen = sizeof(ss);
P
Peter Anvin 已提交
855
				int incoming = accept(pfd[i].fd, (struct sockaddr *)&ss, &sslen);
856 857 858 859 860 861 862 863 864 865 866
				if (incoming < 0) {
					switch (errno) {
					case EAGAIN:
					case EINTR:
					case ECONNABORTED:
						continue;
					default:
						die("accept returned %s", strerror(errno));
					}
				}
				handle(incoming, (struct sockaddr *)&ss, sslen);
867 868 869 870 871
			}
		}
	}
}

872 873 874 875 876 877 878 879 880 881 882 883
/* if any standard file descriptor is missing open it to /dev/null */
static void sanitize_stdfds(void)
{
	int fd = open("/dev/null", O_RDWR, 0);
	while (fd != -1 && fd < 2)
		fd = dup(fd);
	if (fd == -1)
		die("open /dev/null or dup failed: %s", strerror(errno));
	if (fd > 2)
		close(fd);
}

884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901
static void daemonize(void)
{
	switch (fork()) {
		case 0:
			break;
		case -1:
			die("fork failed: %s", strerror(errno));
		default:
			exit(0);
	}
	if (setsid() == -1)
		die("setsid failed: %s", strerror(errno));
	close(0);
	close(1);
	close(2);
	sanitize_stdfds();
}

902 903 904 905 906
static void store_pid(const char *path)
{
	FILE *f = fopen(path, "w");
	if (!f)
		die("cannot open pid file %s: %s", path, strerror(errno));
907
	if (fprintf(f, "%"PRIuMAX"\n", (uintmax_t) getpid()) < 0 || fclose(f) != 0)
908
		die("failed to write pid file %s: %s", path, strerror(errno));
909 910
}

911
static int serve(char *listen_addr, int listen_port, struct passwd *pass, gid_t gid)
P
Peter Anvin 已提交
912 913
{
	int socknum, *socklist;
J
Junio C Hamano 已提交
914

915
	socknum = socksetup(listen_addr, listen_port, &socklist);
P
Peter Anvin 已提交
916
	if (socknum == 0)
917 918
		die("unable to allocate any listen sockets on host %s port %u",
		    listen_addr, listen_port);
J
Junio C Hamano 已提交
919

920 921 922 923 924
	if (pass && gid &&
	    (initgroups(pass->pw_name, gid) || setgid (gid) ||
	     setuid(pass->pw_uid)))
		die("cannot drop privileges");

P
Peter Anvin 已提交
925
	return service_loop(socknum, socklist);
J
Junio C Hamano 已提交
926
}
P
Peter Anvin 已提交
927

928 929
int main(int argc, char **argv)
{
930 931
	int listen_port = 0;
	char *listen_addr = NULL;
932
	int inetd_mode = 0;
933
	const char *pid_file = NULL, *user_name = NULL, *group_name = NULL;
934
	int detach = 0;
935 936 937
	struct passwd *pass = NULL;
	struct group *group;
	gid_t gid = 0;
938 939 940 941 942
	int i;

	for (i = 1; i < argc; i++) {
		char *arg = argv[i];

943
		if (!prefixcmp(arg, "--listen=")) {
944 945
			listen_addr = xstrdup_tolower(arg + 9);
			continue;
946
		}
947
		if (!prefixcmp(arg, "--port=")) {
948 949 950 951
			char *end;
			unsigned long n;
			n = strtoul(arg+7, &end, 0);
			if (arg[7] && !*end) {
952
				listen_port = n;
953 954 955
				continue;
			}
		}
956 957
		if (!strcmp(arg, "--inetd")) {
			inetd_mode = 1;
A
Andreas Ericsson 已提交
958
			log_syslog = 1;
959 960
			continue;
		}
P
Petr Baudis 已提交
961 962 963 964
		if (!strcmp(arg, "--verbose")) {
			verbose = 1;
			continue;
		}
965 966 967 968
		if (!strcmp(arg, "--syslog")) {
			log_syslog = 1;
			continue;
		}
969 970 971 972
		if (!strcmp(arg, "--export-all")) {
			export_all_trees = 1;
			continue;
		}
973
		if (!prefixcmp(arg, "--timeout=")) {
974
			timeout = atoi(arg+10);
A
Andreas Ericsson 已提交
975
			continue;
976
		}
977
		if (!prefixcmp(arg, "--init-timeout=")) {
978
			init_timeout = atoi(arg+15);
A
Andreas Ericsson 已提交
979
			continue;
980
		}
981 982 983 984 985 986
		if (!prefixcmp(arg, "--max-connections=")) {
			max_connections = atoi(arg+18);
			if (max_connections < 0)
				max_connections = 0;	        /* unlimited */
			continue;
		}
987 988 989 990
		if (!strcmp(arg, "--strict-paths")) {
			strict_paths = 1;
			continue;
		}
991
		if (!prefixcmp(arg, "--base-path=")) {
P
Petr Baudis 已提交
992 993 994
			base_path = arg+12;
			continue;
		}
J
Jens Axboe 已提交
995 996 997 998
		if (!strcmp(arg, "--base-path-relaxed")) {
			base_path_relaxed = 1;
			continue;
		}
999
		if (!prefixcmp(arg, "--interpolated-path=")) {
1000 1001 1002
			interpolated_path = arg+20;
			continue;
		}
1003 1004 1005 1006
		if (!strcmp(arg, "--reuseaddr")) {
			reuseaddr = 1;
			continue;
		}
1007 1008 1009 1010
		if (!strcmp(arg, "--user-path")) {
			user_path = "";
			continue;
		}
1011
		if (!prefixcmp(arg, "--user-path=")) {
1012 1013 1014
			user_path = arg + 12;
			continue;
		}
1015
		if (!prefixcmp(arg, "--pid-file=")) {
1016 1017 1018
			pid_file = arg + 11;
			continue;
		}
1019 1020 1021 1022 1023
		if (!strcmp(arg, "--detach")) {
			detach = 1;
			log_syslog = 1;
			continue;
		}
1024
		if (!prefixcmp(arg, "--user=")) {
1025 1026 1027
			user_name = arg + 7;
			continue;
		}
1028
		if (!prefixcmp(arg, "--group=")) {
1029 1030 1031
			group_name = arg + 8;
			continue;
		}
1032
		if (!prefixcmp(arg, "--enable=")) {
1033 1034 1035
			enable_service(arg + 9, 1);
			continue;
		}
1036
		if (!prefixcmp(arg, "--disable=")) {
1037 1038 1039
			enable_service(arg + 10, 0);
			continue;
		}
1040
		if (!prefixcmp(arg, "--allow-override=")) {
J
Junio C Hamano 已提交
1041
			make_service_overridable(arg + 17, 1);
1042 1043
			continue;
		}
1044
		if (!prefixcmp(arg, "--forbid-override=")) {
J
Junio C Hamano 已提交
1045
			make_service_overridable(arg + 18, 0);
1046 1047
			continue;
		}
1048 1049 1050 1051 1052 1053 1054
		if (!strcmp(arg, "--")) {
			ok_paths = &argv[i+1];
			break;
		} else if (arg[0] != '-') {
			ok_paths = &argv[i];
			break;
		}
1055

1056 1057 1058
		usage(daemon_usage);
	}

1059
	if (log_syslog) {
1060
		openlog("git-daemon", LOG_PID, LOG_DAEMON);
1061
		set_die_routine(daemon_die);
J
Junio C Hamano 已提交
1062
	} else
J
Junio C Hamano 已提交
1063 1064
		/* avoid splitting a message in the middle */
		setvbuf(stderr, NULL, _IOLBF, 0);
1065

1066 1067 1068
	if (inetd_mode && (group_name || user_name))
		die("--user and --group are incompatible with --inetd");

1069 1070 1071 1072 1073
	if (inetd_mode && (listen_port || listen_addr))
		die("--listen= and --port= are incompatible with --inetd");
	else if (listen_port == 0)
		listen_port = DEFAULT_GIT_PORT;

1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092
	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;
		}
	}

1093 1094 1095
	if (strict_paths && (!ok_paths || !*ok_paths))
		die("option --strict-paths requires a whitelist");

1096 1097 1098
	if (base_path && !is_directory(base_path))
		die("base-path '%s' does not exist or is not a directory",
		    base_path);
1099

1100
	if (inetd_mode) {
1101 1102 1103 1104
		struct sockaddr_storage ss;
		struct sockaddr *peer = (struct sockaddr *)&ss;
		socklen_t slen = sizeof(ss);

R
René Scharfe 已提交
1105 1106 1107
		if (!freopen("/dev/null", "w", stderr))
			die("failed to redirect stderr to /dev/null: %s",
			    strerror(errno));
1108 1109 1110 1111 1112

		if (getpeername(0, peer, &slen))
			peer = NULL;

		return execute(peer);
1113
	}
1114

1115
	if (detach) {
1116
		daemonize();
1117 1118
		loginfo("Ready to rumble");
	}
1119 1120
	else
		sanitize_stdfds();
1121

1122 1123 1124
	if (pid_file)
		store_pid(pid_file);

1125
	return serve(listen_addr, listen_port, pass, gid);
1126
}