daemon.c 25.3 KB
Newer Older
1
#include "cache.h"
2
#include "pkt-line.h"
3
#include "exec_cmd.h"
4 5
#include "run-command.h"
#include "strbuf.h"
P
Petr Baudis 已提交
6

7 8
#include <syslog.h>

9 10 11 12
#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 256
#endif

13 14 15 16
#ifndef NI_MAXSERV
#define NI_MAXSERV 32
#endif

17
static int log_syslog;
P
Petr Baudis 已提交
18
static int verbose;
19
static int reuseaddr;
P
Petr Baudis 已提交
20

21
static const char daemon_usage[] =
S
Stephan Beyer 已提交
22
"git daemon [--verbose] [--syslog] [--export-all]\n"
23 24
"           [--timeout=n] [--init-timeout=n] [--max-connections=n]\n"
"           [--strict-paths] [--base-path=path] [--base-path-relaxed]\n"
J
Jens Axboe 已提交
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 30 31
"           [--inetd | [--listen=host_or_ipaddr] [--port=n]\n"
"                      [--user=user [--group=group]]\n"
"           [directory...]";
32 33

/* List of acceptable pathname prefixes */
34 35
static char **ok_paths;
static int strict_paths;
36 37

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

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

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

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

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

58 59 60 61
static char *hostname;
static char *canon_hostname;
static char *ip_address;
static char *tcp_port;
62

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

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

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

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

104 105 106 107
static int avoid_alias(char *p)
{
	int sl, ndot;

J
Junio C Hamano 已提交
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 149 150
	 * 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;
		}
	}
}

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

158
	dir = directory;
159 160 161 162 163 164

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

165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
	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;
		}
	}
187
	else if (interpolated_path && saw_extended_args) {
188 189 190 191 192 193 194 195 196 197 198
		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 }
		};

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

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

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

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

233
	if (!path) {
234
		logerror("'%s' does not appear to be a git repository", dir);
235
		return NULL;
236 237 238
	}

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

J
Junio C Hamano 已提交
242
		/* The validation is done on the paths after enter_repo
J
Junio C Hamano 已提交
243
		 * appends optional {.git,.git/.git} and friends, but
244 245 246 247
		 * 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 已提交
248
		 */
249 250
		for ( pp = ok_paths ; *pp ; pp++ ) {
			int len = strlen(*pp);
J
Junio C Hamano 已提交
251 252 253 254 255
			if (len <= pathlen &&
			    !memcmp(*pp, path, len) &&
			    (path[len] == '\0' ||
			     (!strict_paths && path[len] == '/')))
				return path;
256
		}
257 258 259 260 261
	}
	else {
		/* be backwards compatible */
		if (!strict_paths)
			return path;
262 263
	}

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

268 269 270 271 272 273 274 275 276 277 278 279
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;

280
static int git_daemon_config(const char *var, const char *value, void *cb)
281
{
282
	if (!prefixcmp(var, "daemon.") &&
283 284 285 286 287 288 289 290 291
	    !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;
}

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

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

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

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

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

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

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

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

345 346 347
	return service->fn();
}

348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
static void copy_to_log(int fd)
{
	struct strbuf line = STRBUF_INIT;
	FILE *fp;

	fp = fdopen(fd, "r");
	if (fp == NULL) {
		logerror("fdopen of error channel failed");
		close(fd);
		return;
	}

	while (strbuf_getline(&line, fp, '\n') != EOF) {
		logerror("%s", line.buf);
		strbuf_setlen(&line, 0);
	}

	strbuf_release(&line);
	fclose(fp);
}

static int run_service_command(const char **argv)
{
	struct child_process cld;

	memset(&cld, 0, sizeof(cld));
	cld.argv = argv;
	cld.git_cmd = 1;
	cld.err = -1;
	if (start_command(&cld))
		return -1;

	close(0);
	close(1);

	copy_to_log(cld.err);

	return finish_command(&cld);
}

388 389 390 391
static int upload_pack(void)
{
	/* Timeout as string */
	char timeout_buf[64];
392
	const char *argv[] = { "upload-pack", "--strict", timeout_buf, ".", NULL };
393

394
	snprintf(timeout_buf, sizeof timeout_buf, "--timeout=%u", timeout);
395
	return run_service_command(argv);
396 397
}

F
Franck Bui-Huu 已提交
398 399
static int upload_archive(void)
{
400 401
	static const char *argv[] = { "upload-archive", ".", NULL };
	return run_service_command(argv);
F
Franck Bui-Huu 已提交
402 403
}

L
Linus Torvalds 已提交
404 405
static int receive_pack(void)
{
406 407
	static const char *argv[] = { "receive-pack", ".", NULL };
	return run_service_command(argv);
L
Linus Torvalds 已提交
408 409
}

410
static struct daemon_service daemon_service[] = {
F
Franck Bui-Huu 已提交
411
	{ "upload-archive", "uploadarch", upload_archive, 0, 1 },
412
	{ "upload-pack", "uploadpack", upload_pack, 1, 1 },
L
Linus Torvalds 已提交
413
	{ "receive-pack", "receivepack", receive_pack, 0, 1 },
414 415
};

416 417
static void enable_service(const char *name, int ena)
{
418 419 420 421 422 423 424 425 426 427
	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);
}

428 429
static void make_service_overridable(const char *name, int ena)
{
430 431 432 433 434 435 436 437 438 439
	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);
}

440 441 442 443 444 445 446 447
static char *xstrdup_tolower(const char *str)
{
	char *p, *dup = xstrdup(str);
	for (p = dup; *p; p++)
		*p = tolower(*p);
	return dup;
}

448
/*
449
 * Read the host as supplied by the client connection.
450
 */
451
static void parse_host_arg(char *extra_args, int buflen)
452 453 454 455 456
{
	char *val;
	int vallen;
	char *end = extra_args + buflen;

457
	if (extra_args < end && *extra_args) {
458 459 460 461 462
		saw_extended_args = 1;
		if (strncasecmp("host=", extra_args, 5) == 0) {
			val = extra_args + 5;
			vallen = strlen(val) + 1;
			if (*val) {
463 464 465
				/* Split <host>:<port> at colon. */
				char *host = val;
				char *port = strrchr(host, ':');
466 467 468
				if (port) {
					*port = 0;
					port++;
469 470
					free(tcp_port);
					tcp_port = xstrdup(port);
471
				}
472
				free(hostname);
473
				hostname = xstrdup_tolower(host);
474
			}
475

476 477 478
			/* On to the next one */
			extra_args = val + vallen;
		}
479 480
		if (extra_args < end && *extra_args)
			die("Invalid request");
481
	}
482 483 484 485

	/*
	 * Locate canonical hostname and its IP address.
	 */
486
	if (hostname) {
487 488
#ifndef NO_IPV6
		struct addrinfo hints;
B
Benjamin Kramer 已提交
489
		struct addrinfo *ai;
490 491 492 493 494 495
		int gai;
		static char addrbuf[HOST_NAME_MAX + 1];

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

496
		gai = getaddrinfo(hostname, NULL, &hints, &ai);
497
		if (!gai) {
B
Benjamin Kramer 已提交
498 499 500 501 502 503 504 505 506 507 508 509
			struct sockaddr_in *sin_addr = (void *)ai->ai_addr;

			inet_ntop(AF_INET, &sin_addr->sin_addr,
				  addrbuf, sizeof(addrbuf));
			free(ip_address);
			ip_address = xstrdup(addrbuf);

			free(canon_hostname);
			canon_hostname = xstrdup(ai->ai_canonname ?
						 ai->ai_canonname : ip_address);

			freeaddrinfo(ai);
510 511 512 513 514 515 516
		}
#else
		struct hostent *hent;
		struct sockaddr_in sa;
		char **ap;
		static char addrbuf[HOST_NAME_MAX + 1];

517
		hent = gethostbyname(hostname);
518 519 520 521 522 523 524 525 526

		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));
527

528 529 530 531
		free(canon_hostname);
		canon_hostname = xstrdup(hent->h_name);
		free(ip_address);
		ip_address = xstrdup(addrbuf);
532
#endif
533
	}
534 535 536
}


537
static int execute(struct sockaddr *addr)
538
{
539
	static char line[1000];
540
	int pktlen, len, i;
541

542 543 544 545 546 547 548
	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));
549
			port = ntohs(sin_addr->sin_port);
550 551 552 553 554 555 556 557 558
#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, "]");

559
			port = ntohs(sin6_addr->sin6_port);
560 561 562
#endif
		}
		loginfo("Connection from %s:%d", addrbuf, port);
563 564 565 566
		setenv("REMOTE_ADDR", addrbuf, 1);
	}
	else {
		unsetenv("REMOTE_ADDR");
567 568
	}

569
	alarm(init_timeout ? init_timeout : timeout);
570
	pktlen = packet_read_line(0, line, sizeof(line));
571
	alarm(0);
572

573 574 575 576 577
	len = strlen(line);
	if (pktlen != len)
		loginfo("Extended attributes (%d bytes) exist <%.*s>",
			(int) pktlen - len,
			(int) pktlen - len, line + len + 1);
578
	if (len && line[len-1] == '\n') {
579
		line[--len] = 0;
580 581
		pktlen--;
	}
582

583 584 585 586
	free(hostname);
	free(canon_hostname);
	free(ip_address);
	free(tcp_port);
587
	hostname = canon_hostname = ip_address = tcp_port = NULL;
588

589
	if (len != pktlen)
590
		parse_host_arg(line + len + 1, pktlen - len - 1);
591

592 593 594
	for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
		struct daemon_service *s = &(daemon_service[i]);
		int namelen = strlen(s->name);
595
		if (!prefixcmp(line, "git-") &&
596
		    !strncmp(s->name, line + 4, namelen) &&
597
		    line[namelen + 4] == ' ') {
598 599 600 601
			/*
			 * Note: The directory here is probably context sensitive,
			 * and might depend on the actual service being performed.
			 */
602
			return run_service(line + namelen + 5, s);
603
		}
604
	}
605

P
Petr Baudis 已提交
606
	logerror("Protocol error: '%s'", line);
607 608 609
	return -1;
}

610
static int max_connections = 32;
611

612
static unsigned int live_children;
613

L
Linus Torvalds 已提交
614
static struct child {
615
	struct child *next;
616
	pid_t pid;
617
	struct sockaddr_storage address;
618
} *firstborn;
619

620
static void add_child(pid_t pid, struct sockaddr *addr, int addrlen)
621
{
J
Junio C Hamano 已提交
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
	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;
638 639
}

640
static void remove_child(pid_t pid)
641
{
642
	struct child **cradle, *blanket;
643

644 645 646 647 648 649 650
	for (cradle = &firstborn; (blanket = *cradle); cradle = &blanket->next)
		if (blanket->pid == pid) {
			*cradle = blanket->next;
			live_children--;
			free(blanket);
			break;
		}
651 652 653 654 655 656
}

/*
 * This gets called if the number of connections grows
 * past "max_connections".
 *
657
 * We kill the newest connection from a duplicate IP.
658
 */
659
static void kill_some_child(void)
660
{
J
Junio C Hamano 已提交
661
	const struct child *blanket, *next;
662

J
Junio C Hamano 已提交
663 664
	if (!(blanket = firstborn))
		return;
665

J
Junio C Hamano 已提交
666 667 668 669 670 671
	for (; (next = blanket->next); blanket = next)
		if (!memcmp(&blanket->address, &next->address,
			    sizeof(next->address))) {
			kill(blanket->pid, SIGTERM);
			break;
		}
672 673
}

674
static void check_dead_children(void)
675
{
676 677
	int status;
	pid_t pid;
678

J
Junio C Hamano 已提交
679
	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
680 681
		const char *dead = "";
		remove_child(pid);
J
Junio C Hamano 已提交
682
		if (!WIFEXITED(status) || (WEXITSTATUS(status) > 0))
683
			dead = " (with error)";
684
		loginfo("[%"PRIuMAX"] Disconnected%s", (uintmax_t)pid, dead);
685 686 687
	}
}

J
Junio C Hamano 已提交
688
static void handle(int incoming, struct sockaddr *addr, int addrlen)
689
{
690
	pid_t pid;
691

692 693
	if (max_connections && live_children >= max_connections) {
		kill_some_child();
J
Junio C Hamano 已提交
694
		sleep(1);  /* give it some time to die */
695 696 697 698 699 700 701
		check_dead_children();
		if (live_children >= max_connections) {
			close(incoming);
			logerror("Too many children, dropping connection");
			return;
		}
	}
702

703
	if ((pid = fork())) {
704
		close(incoming);
705 706
		if (pid < 0) {
			logerror("Couldn't fork %s", strerror(errno));
707
			return;
708
		}
709

710
		add_child(pid, addr, addrlen);
711 712 713 714 715 716
		return;
	}

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

718
	exit(execute(addr));
719 720
}

721 722
static void child_handler(int signo)
{
J
Junio C Hamano 已提交
723 724
	/*
	 * Otherwise empty handler because systemcalls will get interrupted
725 726 727
	 * upon signal receipt
	 * SysV needs the handler to be rearmed
	 */
728
	signal(SIGCHLD, child_handler);
729 730
}

731 732 733 734 735 736 737 738 739 740
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 已提交
741 742
#ifndef NO_IPV6

743
static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
744
{
745 746 747
	int socknum = 0, *socklist = NULL;
	int maxfd = -1;
	char pbuf[NI_MAXSERV];
P
Peter Anvin 已提交
748 749
	struct addrinfo hints, *ai0, *ai;
	int gai;
750
	long flags;
751

752
	sprintf(pbuf, "%d", listen_port);
753 754 755 756 757 758
	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;

759
	gai = getaddrinfo(listen_addr, pbuf, &hints, &ai0);
760
	if (gai)
761
		die("getaddrinfo() failed: %s", gai_strerror(gai));
762 763 764 765 766 767 768 769

	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) {
770
			logerror("Socket descriptor too large");
771 772 773 774 775 776 777 778 779 780 781 782 783
			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

784 785
		if (set_reuse_addr(sockfd)) {
			close(sockfd);
786
			continue;
787 788
		}

789 790 791 792 793 794 795 796 797
		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 */
		}

798 799 800 801
		flags = fcntl(sockfd, F_GETFD, 0);
		if (flags >= 0)
			fcntl(sockfd, F_SETFD, flags | FD_CLOEXEC);

J
Jonas Fonseca 已提交
802
		socklist = xrealloc(socklist, sizeof(int) * (socknum + 1));
803 804 805 806 807 808 809 810
		socklist[socknum++] = sockfd;

		if (maxfd < sockfd)
			maxfd = sockfd;
	}

	freeaddrinfo(ai0);

P
Peter Anvin 已提交
811 812 813 814 815 816
	*socklist_p = socklist;
	return socknum;
}

#else /* NO_IPV6 */

817
static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
P
Peter Anvin 已提交
818 819 820
{
	struct sockaddr_in sin;
	int sockfd;
821
	long flags;
P
Peter Anvin 已提交
822

823 824 825 826 827 828 829 830 831 832 833 834
	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 已提交
835 836 837 838
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if (sockfd < 0)
		return 0;

839 840 841 842 843
	if (set_reuse_addr(sockfd)) {
		close(sockfd);
		return 0;
	}

P
Peter Anvin 已提交
844 845 846 847
	if ( bind(sockfd, (struct sockaddr *)&sin, sizeof sin) < 0 ) {
		close(sockfd);
		return 0;
	}
848

849 850 851 852 853
	if (listen(sockfd, 5) < 0) {
		close(sockfd);
		return 0;
	}

854 855 856 857
	flags = fcntl(sockfd, F_GETFD, 0);
	if (flags >= 0)
		fcntl(sockfd, F_SETFD, flags | FD_CLOEXEC);

H
H. Peter Anvin 已提交
858
	*socklist_p = xmalloc(sizeof(int));
P
Peter Anvin 已提交
859
	**socklist_p = sockfd;
860
	return 1;
P
Peter Anvin 已提交
861 862 863 864 865 866 867 868 869
}

#endif

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

870
	pfd = xcalloc(socknum, sizeof(struct pollfd));
P
Peter Anvin 已提交
871 872 873 874 875

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

	signal(SIGCHLD, child_handler);
878 879

	for (;;) {
880
		int i;
P
Peter Anvin 已提交
881

882 883 884
		check_dead_children();

		if (poll(pfd, socknum, -1) < 0) {
885
			if (errno != EINTR) {
886
				logerror("Poll failed, resuming: %s",
887 888 889
				      strerror(errno));
				sleep(1);
			}
890 891 892 893
			continue;
		}

		for (i = 0; i < socknum; i++) {
P
Peter Anvin 已提交
894
			if (pfd[i].revents & POLLIN) {
895
				struct sockaddr_storage ss;
896
				unsigned int sslen = sizeof(ss);
P
Peter Anvin 已提交
897
				int incoming = accept(pfd[i].fd, (struct sockaddr *)&ss, &sslen);
898 899 900 901 902 903 904 905 906 907 908
				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);
909 910 911 912 913
			}
		}
	}
}

914 915 916 917 918 919 920 921 922 923 924 925
/* 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);
}

926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943
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();
}

944 945 946 947 948
static void store_pid(const char *path)
{
	FILE *f = fopen(path, "w");
	if (!f)
		die("cannot open pid file %s: %s", path, strerror(errno));
949
	if (fprintf(f, "%"PRIuMAX"\n", (uintmax_t) getpid()) < 0 || fclose(f) != 0)
950
		die("failed to write pid file %s: %s", path, strerror(errno));
951 952
}

953
static int serve(char *listen_addr, int listen_port, struct passwd *pass, gid_t gid)
P
Peter Anvin 已提交
954 955
{
	int socknum, *socklist;
J
Junio C Hamano 已提交
956

957
	socknum = socksetup(listen_addr, listen_port, &socklist);
P
Peter Anvin 已提交
958
	if (socknum == 0)
959 960
		die("unable to allocate any listen sockets on host %s port %u",
		    listen_addr, listen_port);
J
Junio C Hamano 已提交
961

962 963 964 965 966
	if (pass && gid &&
	    (initgroups(pass->pw_name, gid) || setgid (gid) ||
	     setuid(pass->pw_uid)))
		die("cannot drop privileges");

P
Peter Anvin 已提交
967
	return service_loop(socknum, socklist);
J
Junio C Hamano 已提交
968
}
P
Peter Anvin 已提交
969

970 971
int main(int argc, char **argv)
{
972 973
	int listen_port = 0;
	char *listen_addr = NULL;
974
	int inetd_mode = 0;
975
	const char *pid_file = NULL, *user_name = NULL, *group_name = NULL;
976
	int detach = 0;
977 978 979
	struct passwd *pass = NULL;
	struct group *group;
	gid_t gid = 0;
980 981
	int i;

982 983
	git_extract_argv0_path(argv[0]);

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

987
		if (!prefixcmp(arg, "--listen=")) {
988 989
			listen_addr = xstrdup_tolower(arg + 9);
			continue;
990
		}
991
		if (!prefixcmp(arg, "--port=")) {
992 993 994 995
			char *end;
			unsigned long n;
			n = strtoul(arg+7, &end, 0);
			if (arg[7] && !*end) {
996
				listen_port = n;
997 998 999
				continue;
			}
		}
1000 1001
		if (!strcmp(arg, "--inetd")) {
			inetd_mode = 1;
A
Andreas Ericsson 已提交
1002
			log_syslog = 1;
1003 1004
			continue;
		}
P
Petr Baudis 已提交
1005 1006 1007 1008
		if (!strcmp(arg, "--verbose")) {
			verbose = 1;
			continue;
		}
1009 1010 1011 1012
		if (!strcmp(arg, "--syslog")) {
			log_syslog = 1;
			continue;
		}
1013 1014 1015 1016
		if (!strcmp(arg, "--export-all")) {
			export_all_trees = 1;
			continue;
		}
1017
		if (!prefixcmp(arg, "--timeout=")) {
1018
			timeout = atoi(arg+10);
A
Andreas Ericsson 已提交
1019
			continue;
1020
		}
1021
		if (!prefixcmp(arg, "--init-timeout=")) {
1022
			init_timeout = atoi(arg+15);
A
Andreas Ericsson 已提交
1023
			continue;
1024
		}
1025 1026 1027 1028 1029 1030
		if (!prefixcmp(arg, "--max-connections=")) {
			max_connections = atoi(arg+18);
			if (max_connections < 0)
				max_connections = 0;	        /* unlimited */
			continue;
		}
1031 1032 1033 1034
		if (!strcmp(arg, "--strict-paths")) {
			strict_paths = 1;
			continue;
		}
1035
		if (!prefixcmp(arg, "--base-path=")) {
P
Petr Baudis 已提交
1036 1037 1038
			base_path = arg+12;
			continue;
		}
J
Jens Axboe 已提交
1039 1040 1041 1042
		if (!strcmp(arg, "--base-path-relaxed")) {
			base_path_relaxed = 1;
			continue;
		}
1043
		if (!prefixcmp(arg, "--interpolated-path=")) {
1044 1045 1046
			interpolated_path = arg+20;
			continue;
		}
1047 1048 1049 1050
		if (!strcmp(arg, "--reuseaddr")) {
			reuseaddr = 1;
			continue;
		}
1051 1052 1053 1054
		if (!strcmp(arg, "--user-path")) {
			user_path = "";
			continue;
		}
1055
		if (!prefixcmp(arg, "--user-path=")) {
1056 1057 1058
			user_path = arg + 12;
			continue;
		}
1059
		if (!prefixcmp(arg, "--pid-file=")) {
1060 1061 1062
			pid_file = arg + 11;
			continue;
		}
1063 1064 1065 1066 1067
		if (!strcmp(arg, "--detach")) {
			detach = 1;
			log_syslog = 1;
			continue;
		}
1068
		if (!prefixcmp(arg, "--user=")) {
1069 1070 1071
			user_name = arg + 7;
			continue;
		}
1072
		if (!prefixcmp(arg, "--group=")) {
1073 1074 1075
			group_name = arg + 8;
			continue;
		}
1076
		if (!prefixcmp(arg, "--enable=")) {
1077 1078 1079
			enable_service(arg + 9, 1);
			continue;
		}
1080
		if (!prefixcmp(arg, "--disable=")) {
1081 1082 1083
			enable_service(arg + 10, 0);
			continue;
		}
1084
		if (!prefixcmp(arg, "--allow-override=")) {
J
Junio C Hamano 已提交
1085
			make_service_overridable(arg + 17, 1);
1086 1087
			continue;
		}
1088
		if (!prefixcmp(arg, "--forbid-override=")) {
J
Junio C Hamano 已提交
1089
			make_service_overridable(arg + 18, 0);
1090 1091
			continue;
		}
1092 1093 1094 1095 1096 1097 1098
		if (!strcmp(arg, "--")) {
			ok_paths = &argv[i+1];
			break;
		} else if (arg[0] != '-') {
			ok_paths = &argv[i];
			break;
		}
1099

1100 1101 1102
		usage(daemon_usage);
	}

1103
	if (log_syslog) {
1104
		openlog("git-daemon", LOG_PID, LOG_DAEMON);
1105
		set_die_routine(daemon_die);
J
Junio C Hamano 已提交
1106
	} else
J
Junio C Hamano 已提交
1107 1108
		/* avoid splitting a message in the middle */
		setvbuf(stderr, NULL, _IOLBF, 0);
1109

1110 1111 1112
	if (inetd_mode && (group_name || user_name))
		die("--user and --group are incompatible with --inetd");

1113 1114 1115 1116 1117
	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;

1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136
	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;
		}
	}

1137 1138 1139
	if (strict_paths && (!ok_paths || !*ok_paths))
		die("option --strict-paths requires a whitelist");

1140 1141 1142
	if (base_path && !is_directory(base_path))
		die("base-path '%s' does not exist or is not a directory",
		    base_path);
1143

1144
	if (inetd_mode) {
1145 1146 1147 1148
		struct sockaddr_storage ss;
		struct sockaddr *peer = (struct sockaddr *)&ss;
		socklen_t slen = sizeof(ss);

R
René Scharfe 已提交
1149 1150 1151
		if (!freopen("/dev/null", "w", stderr))
			die("failed to redirect stderr to /dev/null: %s",
			    strerror(errno));
1152 1153 1154 1155 1156

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

		return execute(peer);
1157
	}
1158

1159
	if (detach) {
1160
		daemonize();
1161 1162
		loginfo("Ready to rumble");
	}
1163 1164
	else
		sanitize_stdfds();
1165

1166 1167 1168
	if (pid_file)
		store_pid(pid_file);

1169
	return serve(listen_addr, listen_port, pass, gid);
1170
}