connect.c 31.7 KB
Newer Older
Jason Riedy's avatar
Jason Riedy committed
1
#include "git-compat-util.h"
2
#include "cache.h"
3
#include "config.h"
4
#include "pkt-line.h"
5
#include "quote.h"
6
#include "refs.h"
7
#include "run-command.h"
8
#include "remote.h"
9
#include "connect.h"
10
#include "url.h"
11
#include "string-list.h"
12
#include "sha1-array.h"
13
#include "transport.h"
14
#include "strbuf.h"
15
#include "version.h"
16
#include "protocol.h"
17
#include "alias.h"
18

19 20
static char *server_capabilities_v1;
static struct argv_array server_capabilities_v2 = ARGV_ARRAY_INIT;
21
static const char *parse_feature_value(const char *, const char *, int *);
22

23
static int check_ref(const char *name, unsigned int flags)
Linus Torvalds's avatar
Linus Torvalds committed
24 25 26 27
{
	if (!flags)
		return 1;

28
	if (!skip_prefix(name, "refs/", &name))
Linus Torvalds's avatar
Linus Torvalds committed
29 30 31
		return 0;

	/* REF_NORMAL means that we don't want the magic fake tag refs */
32
	if ((flags & REF_NORMAL) && check_refname_format(name, 0))
Linus Torvalds's avatar
Linus Torvalds committed
33 34 35
		return 0;

	/* REF_HEADS means that we want regular branch heads */
36
	if ((flags & REF_HEADS) && starts_with(name, "heads/"))
Linus Torvalds's avatar
Linus Torvalds committed
37 38 39
		return 1;

	/* REF_TAGS means that we want tags */
40
	if ((flags & REF_TAGS) && starts_with(name, "tags/"))
Linus Torvalds's avatar
Linus Torvalds committed
41 42 43 44 45 46
		return 1;

	/* All type bits clear means that we are ok with anything */
	return !(flags & ~REF_NORMAL);
}

47 48
int check_ref_type(const struct ref *ref, int flags)
{
49
	return check_ref(ref->name, flags);
50 51
}

52
static NORETURN void die_initial_contact(int unexpected)
53
{
54 55 56 57 58 59
	/*
	 * A hang-up after seeing some response from the other end
	 * means that it is unexpected, as we know the other end is
	 * willing to talk to us.  A hang-up before seeing any
	 * response does not necessarily mean an ACL problem, though.
	 */
60
	if (unexpected)
61
		die(_("The remote end hung up upon initial contact"));
62
	else
63 64 65
		die(_("Could not read from remote repository.\n\n"
		      "Please make sure you have the correct access rights\n"
		      "and the repository exists."));
66 67
}

68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
/* Checks if the server supports the capability 'c' */
int server_supports_v2(const char *c, int die_on_error)
{
	int i;

	for (i = 0; i < server_capabilities_v2.argc; i++) {
		const char *out;
		if (skip_prefix(server_capabilities_v2.argv[i], c, &out) &&
		    (!*out || *out == '='))
			return 1;
	}

	if (die_on_error)
		die("server doesn't support '%s'", c);

	return 0;
}

86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
int server_supports_feature(const char *c, const char *feature,
			    int die_on_error)
{
	int i;

	for (i = 0; i < server_capabilities_v2.argc; i++) {
		const char *out;
		if (skip_prefix(server_capabilities_v2.argv[i], c, &out) &&
		    (!*out || *(out++) == '=')) {
			if (parse_feature_request(out, feature))
				return 1;
			else
				break;
		}
	}

	if (die_on_error)
		die("server doesn't support feature '%s'", feature);

	return 0;
}

108 109 110 111 112 113 114 115 116
static void process_capabilities_v2(struct packet_reader *reader)
{
	while (packet_reader_read(reader) == PACKET_READ_NORMAL)
		argv_array_push(&server_capabilities_v2, reader->line);

	if (reader->status != PACKET_READ_FLUSH)
		die("expected flush after capabilities");
}

117
enum protocol_version discover_version(struct packet_reader *reader)
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
{
	enum protocol_version version = protocol_unknown_version;

	/*
	 * Peek the first line of the server's response to
	 * determine the protocol version the server is speaking.
	 */
	switch (packet_reader_peek(reader)) {
	case PACKET_READ_EOF:
		die_initial_contact(0);
	case PACKET_READ_FLUSH:
	case PACKET_READ_DELIM:
		version = protocol_v0;
		break;
	case PACKET_READ_NORMAL:
		version = determine_protocol_version_client(reader->line);
		break;
	}

	switch (version) {
138
	case protocol_v2:
139
		process_capabilities_v2(reader);
140
		break;
141 142 143 144 145 146 147 148 149 150 151 152 153
	case protocol_v1:
		/* Read the peeked version line */
		packet_reader_read(reader);
		break;
	case protocol_v0:
		break;
	case protocol_unknown_version:
		BUG("unknown protocol version");
	}

	return version;
}

154 155 156 157 158 159 160 161
static void parse_one_symref_info(struct string_list *symref, const char *val, int len)
{
	char *sym, *target;
	struct string_list_item *item;

	if (!len)
		return; /* just "symref" */
	/* e.g. "symref=HEAD:refs/heads/master" */
162
	sym = xmemdupz(val, len);
163 164 165 166 167 168 169 170 171
	target = strchr(sym, ':');
	if (!target)
		/* just "symref=something" */
		goto reject;
	*(target++) = '\0';
	if (check_refname_format(sym, REFNAME_ALLOW_ONELEVEL) ||
	    check_refname_format(target, REFNAME_ALLOW_ONELEVEL))
		/* "symref=bogus:pair */
		goto reject;
172
	item = string_list_append_nodup(symref, sym);
173 174 175 176 177 178 179 180 181 182
	item->util = target;
	return;
reject:
	free(sym);
	return;
}

static void annotate_refs_with_symref_info(struct ref *ref)
{
	struct string_list symref = STRING_LIST_INIT_DUP;
183
	const char *feature_list = server_capabilities_v1;
184 185 186 187 188 189 190 191 192 193 194

	while (feature_list) {
		int len;
		const char *val;

		val = parse_feature_value(feature_list, "symref", &len);
		if (!val)
			break;
		parse_one_symref_info(&symref, val, len);
		feature_list = val + 1;
	}
195
	string_list_sort(&symref);
196 197 198 199 200 201 202 203 204 205 206

	for (; ref; ref = ref->next) {
		struct string_list_item *item;
		item = string_list_lookup(&symref, ref->name);
		if (!item)
			continue;
		ref->symref = xstrdup((char *)item->util);
	}
	string_list_clear(&symref, 0);
}

207
static void process_capabilities(const char *line, int *len)
208
{
209
	int nul_location = strlen(line);
210 211
	if (nul_location == *len)
		return;
212
	server_capabilities_v1 = xstrdup(line + nul_location + 1);
213 214 215
	*len = nul_location;
}

216
static int process_dummy_ref(const char *line)
217 218 219 220
{
	struct object_id oid;
	const char *name;

221
	if (parse_oid_hex(line, &oid, &name))
222 223 224 225 226 227 228 229
		return 0;
	if (*name != ' ')
		return 0;
	name++;

	return !oidcmp(&null_oid, &oid) && !strcmp(name, "capabilities^{}");
}

230
static void check_no_capabilities(const char *line, int len)
231
{
232
	if (strlen(line) != len)
233
		warning("Ignoring capabilities after first line '%s'",
234
			line + strlen(line));
235 236
}

237 238
static int process_ref(const char *line, int len, struct ref ***list,
		       unsigned int flags, struct oid_array *extra_have)
239 240 241 242
{
	struct object_id old_oid;
	const char *name;

243
	if (parse_oid_hex(line, &old_oid, &name))
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
		return 0;
	if (*name != ' ')
		return 0;
	name++;

	if (extra_have && !strcmp(name, ".have")) {
		oid_array_append(extra_have, &old_oid);
	} else if (!strcmp(name, "capabilities^{}")) {
		die("protocol error: unexpected capabilities^{}");
	} else if (check_ref(name, flags)) {
		struct ref *ref = alloc_ref(name);
		oidcpy(&ref->old_oid, &old_oid);
		**list = ref;
		*list = &ref->next;
	}
259
	check_no_capabilities(line, len);
260 261 262
	return 1;
}

263 264
static int process_shallow(const char *line, int len,
			   struct oid_array *shallow_points)
265 266 267 268
{
	const char *arg;
	struct object_id old_oid;

269
	if (!skip_prefix(line, "shallow ", &arg))
270 271 272 273 274 275 276
		return 0;

	if (get_oid_hex(arg, &old_oid))
		die("protocol error: expected shallow sha-1, got '%s'", arg);
	if (!shallow_points)
		die("repository on the other end cannot be shallow");
	oid_array_append(shallow_points, &old_oid);
277
	check_no_capabilities(line, len);
278 279 280
	return 1;
}

281 282 283 284 285 286 287
enum get_remote_heads_state {
	EXPECTING_FIRST_REF = 0,
	EXPECTING_REF,
	EXPECTING_SHALLOW,
	EXPECTING_DONE,
};

288 289 290
/*
 * Read all the refs from the other end
 */
291
struct ref **get_remote_heads(struct packet_reader *reader,
292
			      struct ref **list, unsigned int flags,
293 294
			      struct oid_array *extra_have,
			      struct oid_array *shallow_points)
295
{
296
	struct ref **orig_list = list;
297 298 299
	int len = 0;
	enum get_remote_heads_state state = EXPECTING_FIRST_REF;
	const char *arg;
300

301
	*list = NULL;
302

303
	while (state != EXPECTING_DONE) {
304
		switch (packet_reader_read(reader)) {
305 306 307
		case PACKET_READ_EOF:
			die_initial_contact(1);
		case PACKET_READ_NORMAL:
308 309
			len = reader->pktlen;
			if (len > 4 && skip_prefix(reader->line, "ERR ", &arg))
310 311 312 313 314 315 316 317 318
				die("remote error: %s", arg);
			break;
		case PACKET_READ_FLUSH:
			state = EXPECTING_DONE;
			break;
		case PACKET_READ_DELIM:
			die("invalid packet");
		}

319 320
		switch (state) {
		case EXPECTING_FIRST_REF:
321 322
			process_capabilities(reader->line, &len);
			if (process_dummy_ref(reader->line)) {
323 324 325 326 327 328
				state = EXPECTING_SHALLOW;
				break;
			}
			state = EXPECTING_REF;
			/* fallthrough */
		case EXPECTING_REF:
329
			if (process_ref(reader->line, len, &list, flags, extra_have))
330 331 332 333
				break;
			state = EXPECTING_SHALLOW;
			/* fallthrough */
		case EXPECTING_SHALLOW:
334
			if (process_shallow(reader->line, len, shallow_points))
335
				break;
336
			die("protocol error: unexpected '%s'", reader->line);
337 338
		case EXPECTING_DONE:
			break;
339
		}
340
	}
341 342 343

	annotate_refs_with_symref_info(*orig_list);

344 345 346
	return list;
}

347 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 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
/* Returns 1 when a valid ref has been added to `list`, 0 otherwise */
static int process_ref_v2(const char *line, struct ref ***list)
{
	int ret = 1;
	int i = 0;
	struct object_id old_oid;
	struct ref *ref;
	struct string_list line_sections = STRING_LIST_INIT_DUP;
	const char *end;

	/*
	 * Ref lines have a number of fields which are space deliminated.  The
	 * first field is the OID of the ref.  The second field is the ref
	 * name.  Subsequent fields (symref-target and peeled) are optional and
	 * don't have a particular order.
	 */
	if (string_list_split(&line_sections, line, ' ', -1) < 2) {
		ret = 0;
		goto out;
	}

	if (parse_oid_hex(line_sections.items[i++].string, &old_oid, &end) ||
	    *end) {
		ret = 0;
		goto out;
	}

	ref = alloc_ref(line_sections.items[i++].string);

	oidcpy(&ref->old_oid, &old_oid);
	**list = ref;
	*list = &ref->next;

	for (; i < line_sections.nr; i++) {
		const char *arg = line_sections.items[i].string;
		if (skip_prefix(arg, "symref-target:", &arg))
			ref->symref = xstrdup(arg);

		if (skip_prefix(arg, "peeled:", &arg)) {
			struct object_id peeled_oid;
			char *peeled_name;
			struct ref *peeled;
			if (parse_oid_hex(arg, &peeled_oid, &end) || *end) {
				ret = 0;
				goto out;
			}

			peeled_name = xstrfmt("%s^{}", ref->name);
			peeled = alloc_ref(peeled_name);

			oidcpy(&peeled->old_oid, &peeled_oid);
			**list = peeled;
			*list = &peeled->next;

			free(peeled_name);
		}
	}

out:
	string_list_clear(&line_sections, 0);
	return ret;
}

struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
			     struct ref **list, int for_push,
412 413
			     const struct argv_array *ref_prefixes,
			     const struct string_list *server_options)
414 415 416 417 418 419 420 421 422 423
{
	int i;
	*list = NULL;

	if (server_supports_v2("ls-refs", 1))
		packet_write_fmt(fd_out, "command=ls-refs\n");

	if (server_supports_v2("agent", 0))
		packet_write_fmt(fd_out, "agent=%s", git_user_agent_sanitized());

424 425 426 427 428 429
	if (server_options && server_options->nr &&
	    server_supports_v2("server-option", 1))
		for (i = 0; i < server_options->nr; i++)
			packet_write_fmt(fd_out, "server-option=%s",
					 server_options->items[i].string);

430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
	packet_delim(fd_out);
	/* When pushing we don't want to request the peeled tags */
	if (!for_push)
		packet_write_fmt(fd_out, "peel\n");
	packet_write_fmt(fd_out, "symrefs\n");
	for (i = 0; ref_prefixes && i < ref_prefixes->argc; i++) {
		packet_write_fmt(fd_out, "ref-prefix %s\n",
				 ref_prefixes->argv[i]);
	}
	packet_flush(fd_out);

	/* Process response from server */
	while (packet_reader_read(reader) == PACKET_READ_NORMAL) {
		if (!process_ref_v2(reader->line, &list))
			die("invalid ls-refs response: %s", reader->line);
	}

	if (reader->status != PACKET_READ_FLUSH)
		die("expected flush after ref listing");

	return list;
}

453
static const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp)
454 455 456 457 458 459 460 461 462 463 464
{
	int len;

	if (!feature_list)
		return NULL;

	len = strlen(feature);
	while (*feature_list) {
		const char *found = strstr(feature_list, feature);
		if (!found)
			return NULL;
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
		if (feature_list == found || isspace(found[-1])) {
			const char *value = found + len;
			/* feature with no value (e.g., "thin-pack") */
			if (!*value || isspace(*value)) {
				if (lenp)
					*lenp = 0;
				return value;
			}
			/* feature with a value (e.g., "agent=git/1.2.3") */
			else if (*value == '=') {
				value++;
				if (lenp)
					*lenp = strcspn(value, " \t\n");
				return value;
			}
			/*
			 * otherwise we matched a substring of another feature;
			 * keep looking
			 */
		}
485 486 487
		feature_list = found + 1;
	}
	return NULL;
488 489
}

490 491 492 493 494 495 496
int parse_feature_request(const char *feature_list, const char *feature)
{
	return !!parse_feature_value(feature_list, feature, NULL);
}

const char *server_feature_value(const char *feature, int *len)
{
497
	return parse_feature_value(server_capabilities_v1, feature, len);
498 499 500 501 502 503 504
}

int server_supports(const char *feature)
{
	return !!server_feature_value(feature, NULL);
}

505 506
enum protocol {
	PROTO_LOCAL = 1,
507
	PROTO_FILE,
508
	PROTO_SSH,
509
	PROTO_GIT
510 511
};

512 513 514 515 516 517 518 519
int url_is_local_not_ssh(const char *url)
{
	const char *colon = strchr(url, ':');
	const char *slash = strchr(url, '/');
	return !colon || (slash && slash < colon) ||
		has_dos_drive_prefix(url);
}

520 521 522 523
static const char *prot_name(enum protocol protocol)
{
	switch (protocol) {
		case PROTO_LOCAL:
524
		case PROTO_FILE:
525 526 527 528 529 530
			return "file";
		case PROTO_SSH:
			return "ssh";
		case PROTO_GIT:
			return "git";
		default:
531
			return "unknown protocol";
532 533 534
	}
}

535 536 537 538 539 540
static enum protocol get_protocol(const char *name)
{
	if (!strcmp(name, "ssh"))
		return PROTO_SSH;
	if (!strcmp(name, "git"))
		return PROTO_GIT;
Carlos's avatar
Carlos committed
541
	if (!strcmp(name, "git+ssh")) /* deprecated - do not use */
542
		return PROTO_SSH;
Carlos's avatar
Carlos committed
543
	if (!strcmp(name, "ssh+git")) /* deprecated - do not use */
544
		return PROTO_SSH;
545
	if (!strcmp(name, "file"))
546
		return PROTO_FILE;
547 548 549
	die("I don't handle protocol '%s'", name);
}

550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
static char *host_end(char **hoststart, int removebrackets)
{
	char *host = *hoststart;
	char *end;
	char *start = strstr(host, "@[");
	if (start)
		start++; /* Jump over '@' */
	else
		start = host;
	if (start[0] == '[') {
		end = strchr(start + 1, ']');
		if (end) {
			if (removebrackets) {
				*end = 0;
				memmove(start, start + 1, end - start);
				end++;
			}
		} else
			end = host;
	} else
		end = host;
	return end;
}

574 575
#define STR_(s)	# s
#define STR(s)	STR_(s)
576

577 578 579
static void get_host_and_port(char **host, const char **port)
{
	char *colon, *end;
580
	end = host_end(host, 1);
581 582
	colon = strchr(end, ':');
	if (colon) {
583 584 585 586
		long portnr = strtol(colon + 1, &end, 10);
		if (end != colon + 1 && *end == '\0' && 0 <= portnr && portnr < 65536) {
			*colon = 0;
			*port = colon + 1;
587 588
		} else if (!colon[1]) {
			*colon = 0;
589
		}
590 591 592
	}
}

593 594 595 596 597 598 599 600 601
static void enable_keepalive(int sockfd)
{
	int ka = 1;

	if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &ka, sizeof(ka)) < 0)
		fprintf(stderr, "unable to set SO_KEEPALIVE on socket: %s\n",
			strerror(errno));
}

602
#ifndef NO_IPV6
603

604 605
static const char *ai_name(const struct addrinfo *ai)
{
606 607 608
	static char addr[NI_MAXHOST];
	if (getnameinfo(ai->ai_addr, ai->ai_addrlen, addr, sizeof(addr), NULL, 0,
			NI_NUMERICHOST) != 0)
609
		xsnprintf(addr, sizeof(addr), "(unknown)");
610

611 612 613
	return addr;
}

614 615 616
/*
 * Returns a connected socket() fd, or else die()s.
 */
617
static int git_tcp_connect_sock(char *host, int flags)
618
{
619 620
	struct strbuf error_message = STRBUF_INIT;
	int sockfd = -1;
Timo Hirvonen's avatar
Timo Hirvonen committed
621
	const char *port = STR(DEFAULT_GIT_PORT);
622 623
	struct addrinfo hints, *ai0, *ai;
	int gai;
624
	int cnt = 0;
625

626 627 628
	get_host_and_port(&host, &port);
	if (!*port)
		port = "<none>";
629 630

	memset(&hints, 0, sizeof(hints));
631 632 633 634
	if (flags & CONNECT_IPV4)
		hints.ai_family = AF_INET;
	else if (flags & CONNECT_IPV6)
		hints.ai_family = AF_INET6;
635 636 637
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

638 639 640
	if (flags & CONNECT_VERBOSE)
		fprintf(stderr, "Looking up %s ... ", host);

641 642
	gai = getaddrinfo(host, port, &hints, &ai);
	if (gai)
643
		die("Unable to look up %s (port %s) (%s)", host, port, gai_strerror(gai));
644

645 646 647
	if (flags & CONNECT_VERBOSE)
		fprintf(stderr, "done.\nConnecting to %s (port %s) ... ", host, port);

648
	for (ai0 = ai; ai; ai = ai->ai_next, cnt++) {
649 650
		sockfd = socket(ai->ai_family,
				ai->ai_socktype, ai->ai_protocol);
651 652 653 654 655 656
		if ((sockfd < 0) ||
		    (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0)) {
			strbuf_addf(&error_message, "%s[%d: %s]: errno=%s\n",
				    host, cnt, ai_name(ai), strerror(errno));
			if (0 <= sockfd)
				close(sockfd);
657 658
			sockfd = -1;
			continue;
659
		}
660 661
		if (flags & CONNECT_VERBOSE)
			fprintf(stderr, "%s ", ai_name(ai));
662
		break;
663 664
	}

665
	freeaddrinfo(ai0);
666 667

	if (sockfd < 0)
668
		die("unable to connect to %s:\n%s", host, error_message.buf);
669

670 671
	enable_keepalive(sockfd);

672 673 674
	if (flags & CONNECT_VERBOSE)
		fprintf(stderr, "done.\n");

675 676
	strbuf_release(&error_message);

677
	return sockfd;
678 679
}

680
#else /* NO_IPV6 */
681

682 683 684
/*
 * Returns a connected socket() fd, or else die()s.
 */
685
static int git_tcp_connect_sock(char *host, int flags)
686
{
687 688
	struct strbuf error_message = STRBUF_INIT;
	int sockfd = -1;
689 690
	const char *port = STR(DEFAULT_GIT_PORT);
	char *ep;
691 692 693 694
	struct hostent *he;
	struct sockaddr_in sa;
	char **ap;
	unsigned int nport;
695
	int cnt;
696

697
	get_host_and_port(&host, &port);
698

699 700 701
	if (flags & CONNECT_VERBOSE)
		fprintf(stderr, "Looking up %s ... ", host);

702 703 704 705 706 707 708 709
	he = gethostbyname(host);
	if (!he)
		die("Unable to look up %s (%s)", host, hstrerror(h_errno));
	nport = strtoul(port, &ep, 10);
	if ( ep == port || *ep ) {
		/* Not numeric */
		struct servent *se = getservbyname(port,"tcp");
		if ( !se )
710
			die("Unknown port %s", port);
711 712 713
		nport = se->s_port;
	}

714 715 716
	if (flags & CONNECT_VERBOSE)
		fprintf(stderr, "done.\nConnecting to %s (port %s) ... ", host, port);

717
	for (cnt = 0, ap = he->h_addr_list; *ap; ap++, cnt++) {
718 719
		memset(&sa, 0, sizeof sa);
		sa.sin_family = he->h_addrtype;
720
		sa.sin_port = htons(nport);
721
		memcpy(&sa.sin_addr, *ap, he->h_length);
722

723 724 725 726
		sockfd = socket(he->h_addrtype, SOCK_STREAM, 0);
		if ((sockfd < 0) ||
		    connect(sockfd, (struct sockaddr *)&sa, sizeof sa) < 0) {
			strbuf_addf(&error_message, "%s[%d: %s]: errno=%s\n",
727 728 729
				host,
				cnt,
				inet_ntoa(*(struct in_addr *)&sa.sin_addr),
730 731 732
				strerror(errno));
			if (0 <= sockfd)
				close(sockfd);
733 734 735
			sockfd = -1;
			continue;
		}
736 737 738
		if (flags & CONNECT_VERBOSE)
			fprintf(stderr, "%s ",
				inet_ntoa(*(struct in_addr *)&sa.sin_addr));
739 740 741 742
		break;
	}

	if (sockfd < 0)
743
		die("unable to connect to %s:\n%s", host, error_message.buf);
744

745 746
	enable_keepalive(sockfd);

747 748 749
	if (flags & CONNECT_VERBOSE)
		fprintf(stderr, "done.\n");

750 751 752 753 754 755
	return sockfd;
}

#endif /* NO_IPV6 */


756 757 758 759 760 761 762 763 764 765 766 767
/*
 * Dummy child_process returned by git_connect() if the transport protocol
 * does not need fork(2).
 */
static struct child_process no_fork = CHILD_PROCESS_INIT;

int git_connection_is_socket(struct child_process *conn)
{
	return conn == &no_fork;
}

static struct child_process *git_tcp_connect(int fd[2], char *host, int flags)
768
{
769
	int sockfd = git_tcp_connect_sock(host, flags);
770

771
	fd[0] = sockfd;
772
	fd[1] = dup(sockfd);
773 774

	return &no_fork;
775 776 777
}


778
static char *git_proxy_command;
779

780 781
static int git_proxy_command_options(const char *var, const char *value,
		void *cb)
782
{
Junio C Hamano's avatar
Junio C Hamano committed
783
	if (!strcmp(var, "core.gitproxy")) {
784 785 786
		const char *for_pos;
		int matchlen = -1;
		int hostlen;
787 788
		const char *rhost_name = cb;
		int rhost_len = strlen(rhost_name);
789

Junio C Hamano's avatar
Junio C Hamano committed
790
		if (git_proxy_command)
791
			return 0;
792 793
		if (!value)
			return config_error_nonbool(var);
Junio C Hamano's avatar
Junio C Hamano committed
794 795 796 797 798 799
		/* [core]
		 * ;# matches www.kernel.org as well
		 * gitproxy = netcatter-1 for kernel.org
		 * gitproxy = netcatter-2 for sample.xz
		 * gitproxy = netcatter-default
		 */
800
		for_pos = strstr(value, " for ");
Junio C Hamano's avatar
Junio C Hamano committed
801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818
		if (!for_pos)
			/* matches everybody */
			matchlen = strlen(value);
		else {
			hostlen = strlen(for_pos + 5);
			if (rhost_len < hostlen)
				matchlen = -1;
			else if (!strncmp(for_pos + 5,
					  rhost_name + rhost_len - hostlen,
					  hostlen) &&
				 ((rhost_len == hostlen) ||
				  rhost_name[rhost_len - hostlen -1] == '.'))
				matchlen = for_pos - value;
			else
				matchlen = -1;
		}
		if (0 <= matchlen) {
			/* core.gitproxy = none for kernel.org */
Junio C Hamano's avatar
Junio C Hamano committed
819
			if (matchlen == 4 &&
Junio C Hamano's avatar
Junio C Hamano committed
820 821
			    !memcmp(value, "none", 4))
				matchlen = 0;
822
			git_proxy_command = xmemdupz(value, matchlen);
823
		}
Junio C Hamano's avatar
Junio C Hamano committed
824
		return 0;
825 826
	}

827
	return git_default_config(var, value, cb);
828 829
}

Junio C Hamano's avatar
Junio C Hamano committed
830
static int git_use_proxy(const char *host)
831 832
{
	git_proxy_command = getenv("GIT_PROXY_COMMAND");
833
	git_config(git_proxy_command_options, (void*)host);
Junio C Hamano's avatar
Junio C Hamano committed
834
	return (git_proxy_command && *git_proxy_command);
835 836
}

837
static struct child_process *git_proxy_connect(int fd[2], char *host)
838
{
Timo Hirvonen's avatar
Timo Hirvonen committed
839
	const char *port = STR(DEFAULT_GIT_PORT);
840
	struct child_process *proxy;
841

842
	get_host_and_port(&host, &port);
843

844 845 846 847 848
	if (looks_like_command_line_option(host))
		die("strange hostname '%s' blocked", host);
	if (looks_like_command_line_option(port))
		die("strange port '%s' blocked", port);

849 850
	proxy = xmalloc(sizeof(*proxy));
	child_process_init(proxy);
Jeff King's avatar
Jeff King committed
851 852 853
	argv_array_push(&proxy->args, git_proxy_command);
	argv_array_push(&proxy->args, host);
	argv_array_push(&proxy->args, port);
854 855 856
	proxy->in = -1;
	proxy->out = -1;
	if (start_command(proxy))
Jeff King's avatar
Jeff King committed
857
		die("cannot start proxy %s", git_proxy_command);
858 859 860
	fd[0] = proxy->out; /* read from proxy stdout */
	fd[1] = proxy->in;  /* write to proxy stdin */
	return proxy;
861 862
}

863
static char *get_port(char *host)
864 865
{
	char *end;
866 867
	char *p = strchr(host, ':');

868
	if (p) {
869 870
		long port = strtol(p + 1, &end, 10);
		if (end != p + 1 && *end == '\0' && 0 <= port && port < 65536) {
871 872
			*p = '\0';
			return p+1;
873 874 875 876 877 878
		}
	}

	return NULL;
}

879
/*
880 881
 * Extract protocol and relevant parts from the specified connection URL.
 * The caller must free() the returned strings.
882
 */
883
static enum protocol parse_connect_url(const char *url_orig, char **ret_host,
884
				       char **ret_path)
885
{
886
	char *url;
887
	char *host, *path;
888
	char *end;
889
	int separator = '/';
890
	enum protocol protocol = PROTO_LOCAL;
891

892 893 894 895 896
	if (is_url(url_orig))
		url = url_decode(url_orig);
	else
		url = xstrdup(url_orig);

897
	host = strstr(url, "://");
898
	if (host) {
899 900 901
		*host = '\0';
		protocol = get_protocol(url);
		host += 3;
902
	} else {
903
		host = url;
904 905 906 907
		if (!url_is_local_not_ssh(url)) {
			protocol = PROTO_SSH;
			separator = ':';
		}
908 909
	}

910
	/*
911 912
	 * Don't do destructive transforms as protocol code does
	 * '[]' unwrapping in get_host_and_port()
913
	 */
914
	end = host_end(&host, 0);
915

916
	if (protocol == PROTO_LOCAL)
917
		path = end;
918 919 920 921
	else if (protocol == PROTO_FILE && has_dos_drive_prefix(end))
		path = end; /* "file://$(pwd)" may be "file://C:/projects/repo" */
	else
		path = strchr(end, separator);
922

923 924 925 926 927 928 929
	if (!path || !*path)
		die("No path specified. See 'man git-pull' for valid url syntax");

	/*
	 * null-terminate hostname and point path to ~ for URL's like this:
	 *    ssh://host.xz/~user/repo
	 */
930 931 932 933 934

	end = path; /* Need to \0 terminate host here */
	if (separator == ':')
		path++; /* path starts after ':' */
	if (protocol == PROTO_GIT || protocol == PROTO_SSH) {
935 936 937 938
		if (path[1] == '~')
			path++;
	}

939 940 941
	path = xstrdup(path);
	*end = '\0';

942
	*ret_host = xstrdup(host);
943
	*ret_path = path;
944 945 946 947
	free(url);
	return protocol;
}

948 949 950 951 952 953 954 955 956 957 958 959 960
static const char *get_ssh_command(void)
{
	const char *ssh;

	if ((ssh = getenv("GIT_SSH_COMMAND")))
		return ssh;

	if (!git_config_get_string_const("core.sshcommand", &ssh))
		return ssh;

	return NULL;
}

961
enum ssh_variant {
962
	VARIANT_AUTO,
963 964 965 966 967 968 969
	VARIANT_SIMPLE,
	VARIANT_SSH,
	VARIANT_PLINK,
	VARIANT_PUTTY,
	VARIANT_TORTOISEPLINK,
};

970
static void override_ssh_variant(enum ssh_variant *ssh_variant)
971
{
972
	const char *variant = getenv("GIT_SSH_VARIANT");
973

974
	if (!variant && git_config_get_string_const("ssh.variant", &variant))
975
		return;
976

977 978 979
	if (!strcmp(variant, "auto"))
		*ssh_variant = VARIANT_AUTO;
	else if (!strcmp(variant, "plink"))
980 981 982 983 984 985 986 987 988
		*ssh_variant = VARIANT_PLINK;
	else if (!strcmp(variant, "putty"))
		*ssh_variant = VARIANT_PUTTY;
	else if (!strcmp(variant, "tortoiseplink"))
		*ssh_variant = VARIANT_TORTOISEPLINK;
	else if (!strcmp(variant, "simple"))
		*ssh_variant = VARIANT_SIMPLE;
	else
		*ssh_variant = VARIANT_SSH;
989 990
}

991 992
static enum ssh_variant determine_ssh_variant(const char *ssh_command,
					      int is_cmdline)
993
{
994
	enum ssh_variant ssh_variant = VARIANT_AUTO;
995
	const char *variant;
996 997
	char *p = NULL;

998 999 1000
	override_ssh_variant(&ssh_variant);

	if (ssh_variant != VARIANT_AUTO)
1001
		return ssh_variant;
1002 1003

	if (!is_cmdline) {
1004 1005 1006 1007 1008 1009
		p = xstrdup(ssh_command);
		variant = basename(p);
	} else {
		const char **ssh_argv;

		p = xstrdup(ssh_command);
1010
		if (split_cmdline(p, &ssh_argv) > 0) {
1011 1012 1013 1014 1015 1016 1017
			variant = basename((char *)ssh_argv[0]);
			/*
			 * At this point, variant points into the buffer
			 * referenced by p, hence we do not need ssh_argv
			 * any longer.
			 */
			free(ssh_argv);
1018 1019
		} else {
			free(p);
1020
			return ssh_variant;
1021
		}
1022 1023
	}

1024 1025 1026 1027 1028 1029
	if (!strcasecmp(variant, "ssh") ||
	    !strcasecmp(variant, "ssh.exe"))
		ssh_variant = VARIANT_SSH;
	else if (!strcasecmp(variant, "plink") ||
		 !strcasecmp(variant, "plink.exe"))
		ssh_variant = VARIANT_PLINK;
1030
	else if (!strcasecmp(variant, "tortoiseplink") ||
1031 1032 1033
		 !strcasecmp(variant, "tortoiseplink.exe"))
		ssh_variant = VARIANT_TORTOISEPLINK;

1034
	free(p);
1035
	return ssh_variant;
1036 1037
}

1038 1039 1040 1041 1042 1043 1044 1045
/*
 * Open a connection using Git's native protocol.
 *
 * The caller is responsible for freeing hostandport, but this function may
 * modify it (for example, to truncate it to remove the port part).
 */
static struct child_process *git_connect_git(int fd[2], char *hostandport,
					     const char *path, const char *prog,
1046
					     enum protocol_version version,
1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063
					     int flags)
{
	struct child_process *conn;
	struct strbuf request = STRBUF_INIT;
	/*
	 * Set up virtual host information based on where we will
	 * connect, unless the user has overridden us in
	 * the environment.
	 */
	char *target_host = getenv("GIT_OVERRIDE_VIRTUAL_HOST");
	if (target_host)
		target_host = xstrdup(target_host);
	else
		target_host = xstrdup(hostandport);

	transport_check_allowed("git");

1064 1065
	/*
	 * These underlying connection commands die() if they
1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084
	 * cannot connect.
	 */
	if (git_use_proxy(hostandport))
		conn = git_proxy_connect(fd, hostandport);
	else
		conn = git_tcp_connect(fd, hostandport, flags);
	/*
	 * Separate original protocol components prog and path
	 * from extended host header with a NUL byte.
	 *
	 * Note: Do not add any other headers here!  Doing so
	 * will cause older git-daemon servers to crash.
	 */
	strbuf_addf(&request,
		    "%s %s%chost=%s%c",
		    prog, path, 0,
		    target_host, 0);

	/* If using a new version put that stuff here after a second null byte */
1085
	if (version > 0) {
1086 1087
		strbuf_addch(&request, '\0');
		strbuf_addf(&request, "version=%d%c",
1088
			    version, '\0');
1089 1090 1091 1092 1093 1094 1095 1096 1097
	}

	packet_write(fd[1], request.buf, request.len);

	free(target_host);
	strbuf_release(&request);
	return conn;
}

1098 1099 1100 1101 1102 1103
/*
 * Append the appropriate environment variables to `env` and options to
 * `args` for running ssh in Git's SSH-tunneled transport.
 */
static void push_ssh_options(struct argv_array *args, struct argv_array *env,
			     enum ssh_variant variant, const char *port,
1104
			     enum protocol_version version, int flags)
1105 1106
{
	if (variant == VARIANT_SSH &&
1107
	    version > 0) {
1108 1109 1110
		argv_array_push(args, "-o");
		argv_array_push(args, "SendEnv=" GIT_PROTOCOL_ENVIRONMENT);
		argv_array_pushf(env, GIT_PROTOCOL_ENVIRONMENT "=version=%d",
1111
				 version);
1112 1113
	}

1114 1115 1116 1117 1118 1119 1120 1121 1122 1123
	if (flags & CONNECT_IPV4) {
		switch (variant) {
		case VARIANT_AUTO:
			BUG("VARIANT_AUTO passed to push_ssh_options");
		case VARIANT_SIMPLE:
			die("ssh variant 'simple' does not support -4");
		case VARIANT_SSH:
		case VARIANT_PLINK:
		case VARIANT_PUTTY:
		case VARIANT_TORTOISEPLINK:
1124
			argv_array_push(args, "-4");
1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135
		}
	} else if (flags & CONNECT_IPV6) {
		switch (variant) {
		case VARIANT_AUTO:
			BUG("VARIANT_AUTO passed to push_ssh_options");
		case VARIANT_SIMPLE:
			die("ssh variant 'simple' does not support -6");
		case VARIANT_SSH:
		case VARIANT_PLINK:
		case VARIANT_PUTTY:
		case VARIANT_TORTOISEPLINK:
1136
			argv_array_push(args, "-6");
1137
		}
1138 1139 1140 1141 1142
	}

	if (variant == VARIANT_TORTOISEPLINK)
		argv_array_push(args, "-batch");

1143 1144 1145 1146 1147 1148 1149
	if (port) {
		switch (variant) {
		case VARIANT_AUTO:
			BUG("VARIANT_AUTO passed to push_ssh_options");
		case VARIANT_SIMPLE:
			die("ssh variant 'simple' does not support setting port");
		case VARIANT_SSH:
1150
			argv_array_push(args, "-p");
1151 1152 1153 1154
			break;
		case VARIANT_PLINK:
		case VARIANT_PUTTY:
		case VARIANT_TORTOISEPLINK:
1155
			argv_array_push(args, "-P");
1156
		}
1157 1158 1159 1160 1161

		argv_array_push(args, port);
	}
}

1162 1163
/* Prepare a child_process for use by Git's SSH-tunneled transport. */
static void fill_ssh_args(struct child_process *conn, const char *ssh_host,
1164 1165
			  const char *port, enum protocol_version version,
			  int flags)
1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189
{
	const char *ssh;
	enum ssh_variant variant;

	if (looks_like_command_line_option(ssh_host))
		die("strange hostname '%s' blocked", ssh_host);

	ssh = get_ssh_command();
	if (ssh) {
		variant = determine_ssh_variant(ssh, 1);
	} else {
		/*
		 * GIT_SSH is the no-shell version of
		 * GIT_SSH_COMMAND (and must remain so for
		 * historical compatibility).
		 */
		conn->use_shell = 0;

		ssh = getenv("GIT_SSH");
		if (!ssh)
			ssh = "ssh";
		variant = determine_ssh_variant(ssh, 0);
	}

1190 1191 1192 1193 1194 1195 1196 1197 1198
	if (variant == VARIANT_AUTO) {
		struct child_process detect = CHILD_PROCESS_INIT;

		detect.use_shell = conn->use_shell;
		detect.no_stdin = detect.no_stdout = detect.no_stderr = 1;

		argv_array_push(&detect.args, ssh);
		argv_array_push(&detect.args, "-G");
		push_ssh_options(&detect.args, &detect.env_array,
1199
				 VARIANT_SSH, port, version, flags);
1200 1201 1202 1203 1204
		argv_array_push(&detect.args, ssh_host);

		variant = run_command(&detect) ? VARIANT_SIMPLE : VARIANT_SSH;
	}

1205
	argv_array_push(&conn->args, ssh);
1206
	push_ssh_options(&conn->args, &conn->env_array, variant, port, version, flags);
1207 1208 1209
	argv_array_push(&conn->args, ssh_host);
}

1210
/*
1211 1212 1213 1214 1215
 * This returns the dummy child_process `no_fork` if the transport protocol
 * does not need fork(2), or a struct child_process object if it does.  Once
 * done, finish the connection with finish_connect() with the value returned
 * from this function (it is safe to call finish_connect() with NULL to
 * support the former case).
1216 1217 1218 1219 1220 1221 1222 1223
 *
 * If it returns, the connect is successful; it just dies on errors (this
 * will hopefully be changed in a libification effort, to return NULL when
 * the connection failed).
 */
struct child_process *git_connect(int fd[2], const char *url,
				  const char *prog, int flags)
{
1224
	char *hostandport, *path;
1225
	struct child_process *conn;
1226
	enum protocol protocol;
1227
	enum protocol_version version = get_protocol_version_config();
1228

1229 1230 1231 1232 1233 1234 1235 1236
	/*
	 * NEEDSWORK: If we are trying to use protocol v2 and we are planning
	 * to perform a push, then fallback to v0 since the client doesn't know
	 * how to push yet using v2.
	 */
	if (version == protocol_v2 && !strcmp("git-receive-pack", prog))
		version = protocol_v0;

1237 1238
	/* Without this we cannot rely on waitpid() to tell
	 * what happened to our children.
1239
	 */
1240
	signal(SIGCHLD, SIG_DFL);
1241

1242
	protocol = parse_connect_url(url, &hostandport, &path);
1243
	if ((flags & CONNECT_DIAG_URL) && (protocol != PROTO_SSH)) {
1244 1245
		printf("Diag: url=%s\n", url ? url : "NULL");
		printf("Diag: protocol=%s\n", prot_name(protocol));
1246
		printf("Diag: hostandport=%s\n", hostandport ? hostandport : "NULL");
1247
		printf("Diag: path=%s\n", path ? path : "NULL");
1248 1249
		conn = NULL;
	} else if (protocol == PROTO_GIT) {
1250
		conn = git_connect_git(fd, hostandport, path, prog, version, flags);
1251
	} else {
1252
		struct strbuf cmd = STRBUF_INIT;
1253
		const char *const *var;
1254

1255 1256
		conn = xmalloc(sizeof(*conn));
		child_process_init(conn);
1257

1258 1259 1260
		if (looks_like_command_line_option(path))
			die("strange pathname '%s' blocked", path);

1261 1262 1263 1264
		strbuf_addstr(&cmd, prog);
		strbuf_addch(&cmd, ' ');
		sq_quote_buf(&cmd, path);

1265
		/* remove repo-local variables from the environment */
1266 1267 1268
		for (var = local_repo_env; *var; var++)
			argv_array_push(&conn->env_array, *var);

1269
		conn->use_shell = 1;
1270 1271 1272 1273
		conn->in = conn->out = -1;
		if (protocol == PROTO_SSH) {
			char *ssh_host = hostandport;
			const char *port = NULL;
1274
			transport_check_allowed("ssh");
1275 1276
			get_host_and_port(&ssh_host, &port);

1277 1278
			if (!port)
				port = get_port(ssh_host);
1279

1280 1281 1282 1283 1284 1285
			if (flags & CONNECT_DIAG_URL) {
				printf("Diag: url=%s\n", url ? url : "NULL");
				printf("Diag: protocol=%s\n", prot_name(protocol));
				printf("Diag: userandhost=%s\n", ssh_host ? ssh_host : "NULL");
				printf("Diag: port=%s\n", port ? port : "NONE");
				printf("Diag: path=%s\n", path ? path : "NULL");
1286

1287 1288
				free(hostandport);
				free(path);
1289
				free(conn);
1290
				strbuf_release(&cmd);
1291
				return NULL;
1292
			}
1293
			fill_ssh_args(conn, ssh_host, port, version, flags);
1294
		} else {
1295
			transport_check_allowed("file");
1296
			if (version > 0) {
1297
				argv_array_pushf(&conn->env_array, GIT_PROTOCOL_ENVIRONMENT "=version=%d",
1298
						 version);
1299
			}
1300
		}
Jeff King's avatar
Jeff King committed
1301
		argv_array_push(&conn->args, cmd.buf);
1302

1303 1304
		if (start_command(conn))
			die("unable to fork");
1305

1306 1307 1308 1309 1310
		fd[0] = conn->out; /* read from child's stdout */
		fd[1] = conn->in;  /* write to child's stdin */
		strbuf_release(&cmd);
	}
	free(hostandport);
1311
	free(path);
1312
	return conn;
1313 1314
}

1315
int finish_connect(struct child_process *conn)
1316
{
1317
	int code;
1318
	if (!conn || git_connection_is_socket(conn))
1319 1320
		return 0;

1321
	code = finish_command(conn);
1322
	free(conn);
1323
	return code;
1324
}