connect.con commit t1400: add tests around adding/deleting pseudorefs (65eb8fc)
   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
  18static char *server_capabilities_v1;
  19static struct argv_array server_capabilities_v2 = ARGV_ARRAY_INIT;
  20static const char *parse_feature_value(const char *, const char *, int *);
  21
  22static int check_ref(const char *name, unsigned int flags)
  23{
  24        if (!flags)
  25                return 1;
  26
  27        if (!skip_prefix(name, "refs/", &name))
  28                return 0;
  29
  30        /* REF_NORMAL means that we don't want the magic fake tag refs */
  31        if ((flags & REF_NORMAL) && check_refname_format(name, 0))
  32                return 0;
  33
  34        /* REF_HEADS means that we want regular branch heads */
  35        if ((flags & REF_HEADS) && starts_with(name, "heads/"))
  36                return 1;
  37
  38        /* REF_TAGS means that we want tags */
  39        if ((flags & REF_TAGS) && starts_with(name, "tags/"))
  40                return 1;
  41
  42        /* All type bits clear means that we are ok with anything */
  43        return !(flags & ~REF_NORMAL);
  44}
  45
  46int check_ref_type(const struct ref *ref, int flags)
  47{
  48        return check_ref(ref->name, flags);
  49}
  50
  51static NORETURN void die_initial_contact(int unexpected)
  52{
  53        /*
  54         * A hang-up after seeing some response from the other end
  55         * means that it is unexpected, as we know the other end is
  56         * willing to talk to us.  A hang-up before seeing any
  57         * response does not necessarily mean an ACL problem, though.
  58         */
  59        if (unexpected)
  60                die(_("The remote end hung up upon initial contact"));
  61        else
  62                die(_("Could not read from remote repository.\n\n"
  63                      "Please make sure you have the correct access rights\n"
  64                      "and the repository exists."));
  65}
  66
  67/* Checks if the server supports the capability 'c' */
  68int server_supports_v2(const char *c, int die_on_error)
  69{
  70        int i;
  71
  72        for (i = 0; i < server_capabilities_v2.argc; i++) {
  73                const char *out;
  74                if (skip_prefix(server_capabilities_v2.argv[i], c, &out) &&
  75                    (!*out || *out == '='))
  76                        return 1;
  77        }
  78
  79        if (die_on_error)
  80                die("server doesn't support '%s'", c);
  81
  82        return 0;
  83}
  84
  85int server_supports_feature(const char *c, const char *feature,
  86                            int die_on_error)
  87{
  88        int i;
  89
  90        for (i = 0; i < server_capabilities_v2.argc; i++) {
  91                const char *out;
  92                if (skip_prefix(server_capabilities_v2.argv[i], c, &out) &&
  93                    (!*out || *(out++) == '=')) {
  94                        if (parse_feature_request(out, feature))
  95                                return 1;
  96                        else
  97                                break;
  98                }
  99        }
 100
 101        if (die_on_error)
 102                die("server doesn't support feature '%s'", feature);
 103
 104        return 0;
 105}
 106
 107static void process_capabilities_v2(struct packet_reader *reader)
 108{
 109        while (packet_reader_read(reader) == PACKET_READ_NORMAL)
 110                argv_array_push(&server_capabilities_v2, reader->line);
 111
 112        if (reader->status != PACKET_READ_FLUSH)
 113                die("expected flush after capabilities");
 114}
 115
 116enum protocol_version discover_version(struct packet_reader *reader)
 117{
 118        enum protocol_version version = protocol_unknown_version;
 119
 120        /*
 121         * Peek the first line of the server's response to
 122         * determine the protocol version the server is speaking.
 123         */
 124        switch (packet_reader_peek(reader)) {
 125        case PACKET_READ_EOF:
 126                die_initial_contact(0);
 127        case PACKET_READ_FLUSH:
 128        case PACKET_READ_DELIM:
 129                version = protocol_v0;
 130                break;
 131        case PACKET_READ_NORMAL:
 132                version = determine_protocol_version_client(reader->line);
 133                break;
 134        }
 135
 136        switch (version) {
 137        case protocol_v2:
 138                process_capabilities_v2(reader);
 139                break;
 140        case protocol_v1:
 141                /* Read the peeked version line */
 142                packet_reader_read(reader);
 143                break;
 144        case protocol_v0:
 145                break;
 146        case protocol_unknown_version:
 147                BUG("unknown protocol version");
 148        }
 149
 150        return version;
 151}
 152
 153static void parse_one_symref_info(struct string_list *symref, const char *val, int len)
 154{
 155        char *sym, *target;
 156        struct string_list_item *item;
 157
 158        if (!len)
 159                return; /* just "symref" */
 160        /* e.g. "symref=HEAD:refs/heads/master" */
 161        sym = xmemdupz(val, len);
 162        target = strchr(sym, ':');
 163        if (!target)
 164                /* just "symref=something" */
 165                goto reject;
 166        *(target++) = '\0';
 167        if (check_refname_format(sym, REFNAME_ALLOW_ONELEVEL) ||
 168            check_refname_format(target, REFNAME_ALLOW_ONELEVEL))
 169                /* "symref=bogus:pair */
 170                goto reject;
 171        item = string_list_append_nodup(symref, sym);
 172        item->util = target;
 173        return;
 174reject:
 175        free(sym);
 176        return;
 177}
 178
 179static void annotate_refs_with_symref_info(struct ref *ref)
 180{
 181        struct string_list symref = STRING_LIST_INIT_DUP;
 182        const char *feature_list = server_capabilities_v1;
 183
 184        while (feature_list) {
 185                int len;
 186                const char *val;
 187
 188                val = parse_feature_value(feature_list, "symref", &len);
 189                if (!val)
 190                        break;
 191                parse_one_symref_info(&symref, val, len);
 192                feature_list = val + 1;
 193        }
 194        string_list_sort(&symref);
 195
 196        for (; ref; ref = ref->next) {
 197                struct string_list_item *item;
 198                item = string_list_lookup(&symref, ref->name);
 199                if (!item)
 200                        continue;
 201                ref->symref = xstrdup((char *)item->util);
 202        }
 203        string_list_clear(&symref, 0);
 204}
 205
 206static void process_capabilities(const char *line, int *len)
 207{
 208        int nul_location = strlen(line);
 209        if (nul_location == *len)
 210                return;
 211        server_capabilities_v1 = xstrdup(line + nul_location + 1);
 212        *len = nul_location;
 213}
 214
 215static int process_dummy_ref(const char *line)
 216{
 217        struct object_id oid;
 218        const char *name;
 219
 220        if (parse_oid_hex(line, &oid, &name))
 221                return 0;
 222        if (*name != ' ')
 223                return 0;
 224        name++;
 225
 226        return !oidcmp(&null_oid, &oid) && !strcmp(name, "capabilities^{}");
 227}
 228
 229static void check_no_capabilities(const char *line, int len)
 230{
 231        if (strlen(line) != len)
 232                warning("Ignoring capabilities after first line '%s'",
 233                        line + strlen(line));
 234}
 235
 236static int process_ref(const char *line, int len, struct ref ***list,
 237                       unsigned int flags, struct oid_array *extra_have)
 238{
 239        struct object_id old_oid;
 240        const char *name;
 241
 242        if (parse_oid_hex(line, &old_oid, &name))
 243                return 0;
 244        if (*name != ' ')
 245                return 0;
 246        name++;
 247
 248        if (extra_have && !strcmp(name, ".have")) {
 249                oid_array_append(extra_have, &old_oid);
 250        } else if (!strcmp(name, "capabilities^{}")) {
 251                die("protocol error: unexpected capabilities^{}");
 252        } else if (check_ref(name, flags)) {
 253                struct ref *ref = alloc_ref(name);
 254                oidcpy(&ref->old_oid, &old_oid);
 255                **list = ref;
 256                *list = &ref->next;
 257        }
 258        check_no_capabilities(line, len);
 259        return 1;
 260}
 261
 262static int process_shallow(const char *line, int len,
 263                           struct oid_array *shallow_points)
 264{
 265        const char *arg;
 266        struct object_id old_oid;
 267
 268        if (!skip_prefix(line, "shallow ", &arg))
 269                return 0;
 270
 271        if (get_oid_hex(arg, &old_oid))
 272                die("protocol error: expected shallow sha-1, got '%s'", arg);
 273        if (!shallow_points)
 274                die("repository on the other end cannot be shallow");
 275        oid_array_append(shallow_points, &old_oid);
 276        check_no_capabilities(line, len);
 277        return 1;
 278}
 279
 280enum get_remote_heads_state {
 281        EXPECTING_FIRST_REF = 0,
 282        EXPECTING_REF,
 283        EXPECTING_SHALLOW,
 284        EXPECTING_DONE,
 285};
 286
 287/*
 288 * Read all the refs from the other end
 289 */
 290struct ref **get_remote_heads(struct packet_reader *reader,
 291                              struct ref **list, unsigned int flags,
 292                              struct oid_array *extra_have,
 293                              struct oid_array *shallow_points)
 294{
 295        struct ref **orig_list = list;
 296        int len = 0;
 297        enum get_remote_heads_state state = EXPECTING_FIRST_REF;
 298        const char *arg;
 299
 300        *list = NULL;
 301
 302        while (state != EXPECTING_DONE) {
 303                switch (packet_reader_read(reader)) {
 304                case PACKET_READ_EOF:
 305                        die_initial_contact(1);
 306                case PACKET_READ_NORMAL:
 307                        len = reader->pktlen;
 308                        if (len > 4 && skip_prefix(reader->line, "ERR ", &arg))
 309                                die("remote error: %s", arg);
 310                        break;
 311                case PACKET_READ_FLUSH:
 312                        state = EXPECTING_DONE;
 313                        break;
 314                case PACKET_READ_DELIM:
 315                        die("invalid packet");
 316                }
 317
 318                switch (state) {
 319                case EXPECTING_FIRST_REF:
 320                        process_capabilities(reader->line, &len);
 321                        if (process_dummy_ref(reader->line)) {
 322                                state = EXPECTING_SHALLOW;
 323                                break;
 324                        }
 325                        state = EXPECTING_REF;
 326                        /* fallthrough */
 327                case EXPECTING_REF:
 328                        if (process_ref(reader->line, len, &list, flags, extra_have))
 329                                break;
 330                        state = EXPECTING_SHALLOW;
 331                        /* fallthrough */
 332                case EXPECTING_SHALLOW:
 333                        if (process_shallow(reader->line, len, shallow_points))
 334                                break;
 335                        die("protocol error: unexpected '%s'", reader->line);
 336                case EXPECTING_DONE:
 337                        break;
 338                }
 339        }
 340
 341        annotate_refs_with_symref_info(*orig_list);
 342
 343        return list;
 344}
 345
 346/* Returns 1 when a valid ref has been added to `list`, 0 otherwise */
 347static int process_ref_v2(const char *line, struct ref ***list)
 348{
 349        int ret = 1;
 350        int i = 0;
 351        struct object_id old_oid;
 352        struct ref *ref;
 353        struct string_list line_sections = STRING_LIST_INIT_DUP;
 354        const char *end;
 355
 356        /*
 357         * Ref lines have a number of fields which are space deliminated.  The
 358         * first field is the OID of the ref.  The second field is the ref
 359         * name.  Subsequent fields (symref-target and peeled) are optional and
 360         * don't have a particular order.
 361         */
 362        if (string_list_split(&line_sections, line, ' ', -1) < 2) {
 363                ret = 0;
 364                goto out;
 365        }
 366
 367        if (parse_oid_hex(line_sections.items[i++].string, &old_oid, &end) ||
 368            *end) {
 369                ret = 0;
 370                goto out;
 371        }
 372
 373        ref = alloc_ref(line_sections.items[i++].string);
 374
 375        oidcpy(&ref->old_oid, &old_oid);
 376        **list = ref;
 377        *list = &ref->next;
 378
 379        for (; i < line_sections.nr; i++) {
 380                const char *arg = line_sections.items[i].string;
 381                if (skip_prefix(arg, "symref-target:", &arg))
 382                        ref->symref = xstrdup(arg);
 383
 384                if (skip_prefix(arg, "peeled:", &arg)) {
 385                        struct object_id peeled_oid;
 386                        char *peeled_name;
 387                        struct ref *peeled;
 388                        if (parse_oid_hex(arg, &peeled_oid, &end) || *end) {
 389                                ret = 0;
 390                                goto out;
 391                        }
 392
 393                        peeled_name = xstrfmt("%s^{}", ref->name);
 394                        peeled = alloc_ref(peeled_name);
 395
 396                        oidcpy(&peeled->old_oid, &peeled_oid);
 397                        **list = peeled;
 398                        *list = &peeled->next;
 399
 400                        free(peeled_name);
 401                }
 402        }
 403
 404out:
 405        string_list_clear(&line_sections, 0);
 406        return ret;
 407}
 408
 409struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
 410                             struct ref **list, int for_push,
 411                             const struct argv_array *ref_prefixes)
 412{
 413        int i;
 414        *list = NULL;
 415
 416        if (server_supports_v2("ls-refs", 1))
 417                packet_write_fmt(fd_out, "command=ls-refs\n");
 418
 419        if (server_supports_v2("agent", 0))
 420                packet_write_fmt(fd_out, "agent=%s", git_user_agent_sanitized());
 421
 422        packet_delim(fd_out);
 423        /* When pushing we don't want to request the peeled tags */
 424        if (!for_push)
 425                packet_write_fmt(fd_out, "peel\n");
 426        packet_write_fmt(fd_out, "symrefs\n");
 427        for (i = 0; ref_prefixes && i < ref_prefixes->argc; i++) {
 428                packet_write_fmt(fd_out, "ref-prefix %s\n",
 429                                 ref_prefixes->argv[i]);
 430        }
 431        packet_flush(fd_out);
 432
 433        /* Process response from server */
 434        while (packet_reader_read(reader) == PACKET_READ_NORMAL) {
 435                if (!process_ref_v2(reader->line, &list))
 436                        die("invalid ls-refs response: %s", reader->line);
 437        }
 438
 439        if (reader->status != PACKET_READ_FLUSH)
 440                die("expected flush after ref listing");
 441
 442        return list;
 443}
 444
 445static const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp)
 446{
 447        int len;
 448
 449        if (!feature_list)
 450                return NULL;
 451
 452        len = strlen(feature);
 453        while (*feature_list) {
 454                const char *found = strstr(feature_list, feature);
 455                if (!found)
 456                        return NULL;
 457                if (feature_list == found || isspace(found[-1])) {
 458                        const char *value = found + len;
 459                        /* feature with no value (e.g., "thin-pack") */
 460                        if (!*value || isspace(*value)) {
 461                                if (lenp)
 462                                        *lenp = 0;
 463                                return value;
 464                        }
 465                        /* feature with a value (e.g., "agent=git/1.2.3") */
 466                        else if (*value == '=') {
 467                                value++;
 468                                if (lenp)
 469                                        *lenp = strcspn(value, " \t\n");
 470                                return value;
 471                        }
 472                        /*
 473                         * otherwise we matched a substring of another feature;
 474                         * keep looking
 475                         */
 476                }
 477                feature_list = found + 1;
 478        }
 479        return NULL;
 480}
 481
 482int parse_feature_request(const char *feature_list, const char *feature)
 483{
 484        return !!parse_feature_value(feature_list, feature, NULL);
 485}
 486
 487const char *server_feature_value(const char *feature, int *len)
 488{
 489        return parse_feature_value(server_capabilities_v1, feature, len);
 490}
 491
 492int server_supports(const char *feature)
 493{
 494        return !!server_feature_value(feature, NULL);
 495}
 496
 497enum protocol {
 498        PROTO_LOCAL = 1,
 499        PROTO_FILE,
 500        PROTO_SSH,
 501        PROTO_GIT
 502};
 503
 504int url_is_local_not_ssh(const char *url)
 505{
 506        const char *colon = strchr(url, ':');
 507        const char *slash = strchr(url, '/');
 508        return !colon || (slash && slash < colon) ||
 509                has_dos_drive_prefix(url);
 510}
 511
 512static const char *prot_name(enum protocol protocol)
 513{
 514        switch (protocol) {
 515                case PROTO_LOCAL:
 516                case PROTO_FILE:
 517                        return "file";
 518                case PROTO_SSH:
 519                        return "ssh";
 520                case PROTO_GIT:
 521                        return "git";
 522                default:
 523                        return "unknown protocol";
 524        }
 525}
 526
 527static enum protocol get_protocol(const char *name)
 528{
 529        if (!strcmp(name, "ssh"))
 530                return PROTO_SSH;
 531        if (!strcmp(name, "git"))
 532                return PROTO_GIT;
 533        if (!strcmp(name, "git+ssh")) /* deprecated - do not use */
 534                return PROTO_SSH;
 535        if (!strcmp(name, "ssh+git")) /* deprecated - do not use */
 536                return PROTO_SSH;
 537        if (!strcmp(name, "file"))
 538                return PROTO_FILE;
 539        die("I don't handle protocol '%s'", name);
 540}
 541
 542static char *host_end(char **hoststart, int removebrackets)
 543{
 544        char *host = *hoststart;
 545        char *end;
 546        char *start = strstr(host, "@[");
 547        if (start)
 548                start++; /* Jump over '@' */
 549        else
 550                start = host;
 551        if (start[0] == '[') {
 552                end = strchr(start + 1, ']');
 553                if (end) {
 554                        if (removebrackets) {
 555                                *end = 0;
 556                                memmove(start, start + 1, end - start);
 557                                end++;
 558                        }
 559                } else
 560                        end = host;
 561        } else
 562                end = host;
 563        return end;
 564}
 565
 566#define STR_(s) # s
 567#define STR(s)  STR_(s)
 568
 569static void get_host_and_port(char **host, const char **port)
 570{
 571        char *colon, *end;
 572        end = host_end(host, 1);
 573        colon = strchr(end, ':');
 574        if (colon) {
 575                long portnr = strtol(colon + 1, &end, 10);
 576                if (end != colon + 1 && *end == '\0' && 0 <= portnr && portnr < 65536) {
 577                        *colon = 0;
 578                        *port = colon + 1;
 579                } else if (!colon[1]) {
 580                        *colon = 0;
 581                }
 582        }
 583}
 584
 585static void enable_keepalive(int sockfd)
 586{
 587        int ka = 1;
 588
 589        if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &ka, sizeof(ka)) < 0)
 590                fprintf(stderr, "unable to set SO_KEEPALIVE on socket: %s\n",
 591                        strerror(errno));
 592}
 593
 594#ifndef NO_IPV6
 595
 596static const char *ai_name(const struct addrinfo *ai)
 597{
 598        static char addr[NI_MAXHOST];
 599        if (getnameinfo(ai->ai_addr, ai->ai_addrlen, addr, sizeof(addr), NULL, 0,
 600                        NI_NUMERICHOST) != 0)
 601                xsnprintf(addr, sizeof(addr), "(unknown)");
 602
 603        return addr;
 604}
 605
 606/*
 607 * Returns a connected socket() fd, or else die()s.
 608 */
 609static int git_tcp_connect_sock(char *host, int flags)
 610{
 611        struct strbuf error_message = STRBUF_INIT;
 612        int sockfd = -1;
 613        const char *port = STR(DEFAULT_GIT_PORT);
 614        struct addrinfo hints, *ai0, *ai;
 615        int gai;
 616        int cnt = 0;
 617
 618        get_host_and_port(&host, &port);
 619        if (!*port)
 620                port = "<none>";
 621
 622        memset(&hints, 0, sizeof(hints));
 623        if (flags & CONNECT_IPV4)
 624                hints.ai_family = AF_INET;
 625        else if (flags & CONNECT_IPV6)
 626                hints.ai_family = AF_INET6;
 627        hints.ai_socktype = SOCK_STREAM;
 628        hints.ai_protocol = IPPROTO_TCP;
 629
 630        if (flags & CONNECT_VERBOSE)
 631                fprintf(stderr, "Looking up %s ... ", host);
 632
 633        gai = getaddrinfo(host, port, &hints, &ai);
 634        if (gai)
 635                die("Unable to look up %s (port %s) (%s)", host, port, gai_strerror(gai));
 636
 637        if (flags & CONNECT_VERBOSE)
 638                fprintf(stderr, "done.\nConnecting to %s (port %s) ... ", host, port);
 639
 640        for (ai0 = ai; ai; ai = ai->ai_next, cnt++) {
 641                sockfd = socket(ai->ai_family,
 642                                ai->ai_socktype, ai->ai_protocol);
 643                if ((sockfd < 0) ||
 644                    (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0)) {
 645                        strbuf_addf(&error_message, "%s[%d: %s]: errno=%s\n",
 646                                    host, cnt, ai_name(ai), strerror(errno));
 647                        if (0 <= sockfd)
 648                                close(sockfd);
 649                        sockfd = -1;
 650                        continue;
 651                }
 652                if (flags & CONNECT_VERBOSE)
 653                        fprintf(stderr, "%s ", ai_name(ai));
 654                break;
 655        }
 656
 657        freeaddrinfo(ai0);
 658
 659        if (sockfd < 0)
 660                die("unable to connect to %s:\n%s", host, error_message.buf);
 661
 662        enable_keepalive(sockfd);
 663
 664        if (flags & CONNECT_VERBOSE)
 665                fprintf(stderr, "done.\n");
 666
 667        strbuf_release(&error_message);
 668
 669        return sockfd;
 670}
 671
 672#else /* NO_IPV6 */
 673
 674/*
 675 * Returns a connected socket() fd, or else die()s.
 676 */
 677static int git_tcp_connect_sock(char *host, int flags)
 678{
 679        struct strbuf error_message = STRBUF_INIT;
 680        int sockfd = -1;
 681        const char *port = STR(DEFAULT_GIT_PORT);
 682        char *ep;
 683        struct hostent *he;
 684        struct sockaddr_in sa;
 685        char **ap;
 686        unsigned int nport;
 687        int cnt;
 688
 689        get_host_and_port(&host, &port);
 690
 691        if (flags & CONNECT_VERBOSE)
 692                fprintf(stderr, "Looking up %s ... ", host);
 693
 694        he = gethostbyname(host);
 695        if (!he)
 696                die("Unable to look up %s (%s)", host, hstrerror(h_errno));
 697        nport = strtoul(port, &ep, 10);
 698        if ( ep == port || *ep ) {
 699                /* Not numeric */
 700                struct servent *se = getservbyname(port,"tcp");
 701                if ( !se )
 702                        die("Unknown port %s", port);
 703                nport = se->s_port;
 704        }
 705
 706        if (flags & CONNECT_VERBOSE)
 707                fprintf(stderr, "done.\nConnecting to %s (port %s) ... ", host, port);
 708
 709        for (cnt = 0, ap = he->h_addr_list; *ap; ap++, cnt++) {
 710                memset(&sa, 0, sizeof sa);
 711                sa.sin_family = he->h_addrtype;
 712                sa.sin_port = htons(nport);
 713                memcpy(&sa.sin_addr, *ap, he->h_length);
 714
 715                sockfd = socket(he->h_addrtype, SOCK_STREAM, 0);
 716                if ((sockfd < 0) ||
 717                    connect(sockfd, (struct sockaddr *)&sa, sizeof sa) < 0) {
 718                        strbuf_addf(&error_message, "%s[%d: %s]: errno=%s\n",
 719                                host,
 720                                cnt,
 721                                inet_ntoa(*(struct in_addr *)&sa.sin_addr),
 722                                strerror(errno));
 723                        if (0 <= sockfd)
 724                                close(sockfd);
 725                        sockfd = -1;
 726                        continue;
 727                }
 728                if (flags & CONNECT_VERBOSE)
 729                        fprintf(stderr, "%s ",
 730                                inet_ntoa(*(struct in_addr *)&sa.sin_addr));
 731                break;
 732        }
 733
 734        if (sockfd < 0)
 735                die("unable to connect to %s:\n%s", host, error_message.buf);
 736
 737        enable_keepalive(sockfd);
 738
 739        if (flags & CONNECT_VERBOSE)
 740                fprintf(stderr, "done.\n");
 741
 742        return sockfd;
 743}
 744
 745#endif /* NO_IPV6 */
 746
 747
 748/*
 749 * Dummy child_process returned by git_connect() if the transport protocol
 750 * does not need fork(2).
 751 */
 752static struct child_process no_fork = CHILD_PROCESS_INIT;
 753
 754int git_connection_is_socket(struct child_process *conn)
 755{
 756        return conn == &no_fork;
 757}
 758
 759static struct child_process *git_tcp_connect(int fd[2], char *host, int flags)
 760{
 761        int sockfd = git_tcp_connect_sock(host, flags);
 762
 763        fd[0] = sockfd;
 764        fd[1] = dup(sockfd);
 765
 766        return &no_fork;
 767}
 768
 769
 770static char *git_proxy_command;
 771
 772static int git_proxy_command_options(const char *var, const char *value,
 773                void *cb)
 774{
 775        if (!strcmp(var, "core.gitproxy")) {
 776                const char *for_pos;
 777                int matchlen = -1;
 778                int hostlen;
 779                const char *rhost_name = cb;
 780                int rhost_len = strlen(rhost_name);
 781
 782                if (git_proxy_command)
 783                        return 0;
 784                if (!value)
 785                        return config_error_nonbool(var);
 786                /* [core]
 787                 * ;# matches www.kernel.org as well
 788                 * gitproxy = netcatter-1 for kernel.org
 789                 * gitproxy = netcatter-2 for sample.xz
 790                 * gitproxy = netcatter-default
 791                 */
 792                for_pos = strstr(value, " for ");
 793                if (!for_pos)
 794                        /* matches everybody */
 795                        matchlen = strlen(value);
 796                else {
 797                        hostlen = strlen(for_pos + 5);
 798                        if (rhost_len < hostlen)
 799                                matchlen = -1;
 800                        else if (!strncmp(for_pos + 5,
 801                                          rhost_name + rhost_len - hostlen,
 802                                          hostlen) &&
 803                                 ((rhost_len == hostlen) ||
 804                                  rhost_name[rhost_len - hostlen -1] == '.'))
 805                                matchlen = for_pos - value;
 806                        else
 807                                matchlen = -1;
 808                }
 809                if (0 <= matchlen) {
 810                        /* core.gitproxy = none for kernel.org */
 811                        if (matchlen == 4 &&
 812                            !memcmp(value, "none", 4))
 813                                matchlen = 0;
 814                        git_proxy_command = xmemdupz(value, matchlen);
 815                }
 816                return 0;
 817        }
 818
 819        return git_default_config(var, value, cb);
 820}
 821
 822static int git_use_proxy(const char *host)
 823{
 824        git_proxy_command = getenv("GIT_PROXY_COMMAND");
 825        git_config(git_proxy_command_options, (void*)host);
 826        return (git_proxy_command && *git_proxy_command);
 827}
 828
 829static struct child_process *git_proxy_connect(int fd[2], char *host)
 830{
 831        const char *port = STR(DEFAULT_GIT_PORT);
 832        struct child_process *proxy;
 833
 834        get_host_and_port(&host, &port);
 835
 836        if (looks_like_command_line_option(host))
 837                die("strange hostname '%s' blocked", host);
 838        if (looks_like_command_line_option(port))
 839                die("strange port '%s' blocked", port);
 840
 841        proxy = xmalloc(sizeof(*proxy));
 842        child_process_init(proxy);
 843        argv_array_push(&proxy->args, git_proxy_command);
 844        argv_array_push(&proxy->args, host);
 845        argv_array_push(&proxy->args, port);
 846        proxy->in = -1;
 847        proxy->out = -1;
 848        if (start_command(proxy))
 849                die("cannot start proxy %s", git_proxy_command);
 850        fd[0] = proxy->out; /* read from proxy stdout */
 851        fd[1] = proxy->in;  /* write to proxy stdin */
 852        return proxy;
 853}
 854
 855static char *get_port(char *host)
 856{
 857        char *end;
 858        char *p = strchr(host, ':');
 859
 860        if (p) {
 861                long port = strtol(p + 1, &end, 10);
 862                if (end != p + 1 && *end == '\0' && 0 <= port && port < 65536) {
 863                        *p = '\0';
 864                        return p+1;
 865                }
 866        }
 867
 868        return NULL;
 869}
 870
 871/*
 872 * Extract protocol and relevant parts from the specified connection URL.
 873 * The caller must free() the returned strings.
 874 */
 875static enum protocol parse_connect_url(const char *url_orig, char **ret_host,
 876                                       char **ret_path)
 877{
 878        char *url;
 879        char *host, *path;
 880        char *end;
 881        int separator = '/';
 882        enum protocol protocol = PROTO_LOCAL;
 883
 884        if (is_url(url_orig))
 885                url = url_decode(url_orig);
 886        else
 887                url = xstrdup(url_orig);
 888
 889        host = strstr(url, "://");
 890        if (host) {
 891                *host = '\0';
 892                protocol = get_protocol(url);
 893                host += 3;
 894        } else {
 895                host = url;
 896                if (!url_is_local_not_ssh(url)) {
 897                        protocol = PROTO_SSH;
 898                        separator = ':';
 899                }
 900        }
 901
 902        /*
 903         * Don't do destructive transforms as protocol code does
 904         * '[]' unwrapping in get_host_and_port()
 905         */
 906        end = host_end(&host, 0);
 907
 908        if (protocol == PROTO_LOCAL)
 909                path = end;
 910        else if (protocol == PROTO_FILE && has_dos_drive_prefix(end))
 911                path = end; /* "file://$(pwd)" may be "file://C:/projects/repo" */
 912        else
 913                path = strchr(end, separator);
 914
 915        if (!path || !*path)
 916                die("No path specified. See 'man git-pull' for valid url syntax");
 917
 918        /*
 919         * null-terminate hostname and point path to ~ for URL's like this:
 920         *    ssh://host.xz/~user/repo
 921         */
 922
 923        end = path; /* Need to \0 terminate host here */
 924        if (separator == ':')
 925                path++; /* path starts after ':' */
 926        if (protocol == PROTO_GIT || protocol == PROTO_SSH) {
 927                if (path[1] == '~')
 928                        path++;
 929        }
 930
 931        path = xstrdup(path);
 932        *end = '\0';
 933
 934        *ret_host = xstrdup(host);
 935        *ret_path = path;
 936        free(url);
 937        return protocol;
 938}
 939
 940static const char *get_ssh_command(void)
 941{
 942        const char *ssh;
 943
 944        if ((ssh = getenv("GIT_SSH_COMMAND")))
 945                return ssh;
 946
 947        if (!git_config_get_string_const("core.sshcommand", &ssh))
 948                return ssh;
 949
 950        return NULL;
 951}
 952
 953enum ssh_variant {
 954        VARIANT_AUTO,
 955        VARIANT_SIMPLE,
 956        VARIANT_SSH,
 957        VARIANT_PLINK,
 958        VARIANT_PUTTY,
 959        VARIANT_TORTOISEPLINK,
 960};
 961
 962static void override_ssh_variant(enum ssh_variant *ssh_variant)
 963{
 964        const char *variant = getenv("GIT_SSH_VARIANT");
 965
 966        if (!variant && git_config_get_string_const("ssh.variant", &variant))
 967                return;
 968
 969        if (!strcmp(variant, "auto"))
 970                *ssh_variant = VARIANT_AUTO;
 971        else if (!strcmp(variant, "plink"))
 972                *ssh_variant = VARIANT_PLINK;
 973        else if (!strcmp(variant, "putty"))
 974                *ssh_variant = VARIANT_PUTTY;
 975        else if (!strcmp(variant, "tortoiseplink"))
 976                *ssh_variant = VARIANT_TORTOISEPLINK;
 977        else if (!strcmp(variant, "simple"))
 978                *ssh_variant = VARIANT_SIMPLE;
 979        else
 980                *ssh_variant = VARIANT_SSH;
 981}
 982
 983static enum ssh_variant determine_ssh_variant(const char *ssh_command,
 984                                              int is_cmdline)
 985{
 986        enum ssh_variant ssh_variant = VARIANT_AUTO;
 987        const char *variant;
 988        char *p = NULL;
 989
 990        override_ssh_variant(&ssh_variant);
 991
 992        if (ssh_variant != VARIANT_AUTO)
 993                return ssh_variant;
 994
 995        if (!is_cmdline) {
 996                p = xstrdup(ssh_command);
 997                variant = basename(p);
 998        } else {
 999                const char **ssh_argv;
1000
1001                p = xstrdup(ssh_command);
1002                if (split_cmdline(p, &ssh_argv) > 0) {
1003                        variant = basename((char *)ssh_argv[0]);
1004                        /*
1005                         * At this point, variant points into the buffer
1006                         * referenced by p, hence we do not need ssh_argv
1007                         * any longer.
1008                         */
1009                        free(ssh_argv);
1010                } else {
1011                        free(p);
1012                        return ssh_variant;
1013                }
1014        }
1015
1016        if (!strcasecmp(variant, "ssh") ||
1017            !strcasecmp(variant, "ssh.exe"))
1018                ssh_variant = VARIANT_SSH;
1019        else if (!strcasecmp(variant, "plink") ||
1020                 !strcasecmp(variant, "plink.exe"))
1021                ssh_variant = VARIANT_PLINK;
1022        else if (!strcasecmp(variant, "tortoiseplink") ||
1023                 !strcasecmp(variant, "tortoiseplink.exe"))
1024                ssh_variant = VARIANT_TORTOISEPLINK;
1025
1026        free(p);
1027        return ssh_variant;
1028}
1029
1030/*
1031 * Open a connection using Git's native protocol.
1032 *
1033 * The caller is responsible for freeing hostandport, but this function may
1034 * modify it (for example, to truncate it to remove the port part).
1035 */
1036static struct child_process *git_connect_git(int fd[2], char *hostandport,
1037                                             const char *path, const char *prog,
1038                                             enum protocol_version version,
1039                                             int flags)
1040{
1041        struct child_process *conn;
1042        struct strbuf request = STRBUF_INIT;
1043        /*
1044         * Set up virtual host information based on where we will
1045         * connect, unless the user has overridden us in
1046         * the environment.
1047         */
1048        char *target_host = getenv("GIT_OVERRIDE_VIRTUAL_HOST");
1049        if (target_host)
1050                target_host = xstrdup(target_host);
1051        else
1052                target_host = xstrdup(hostandport);
1053
1054        transport_check_allowed("git");
1055
1056        /*
1057         * These underlying connection commands die() if they
1058         * cannot connect.
1059         */
1060        if (git_use_proxy(hostandport))
1061                conn = git_proxy_connect(fd, hostandport);
1062        else
1063                conn = git_tcp_connect(fd, hostandport, flags);
1064        /*
1065         * Separate original protocol components prog and path
1066         * from extended host header with a NUL byte.
1067         *
1068         * Note: Do not add any other headers here!  Doing so
1069         * will cause older git-daemon servers to crash.
1070         */
1071        strbuf_addf(&request,
1072                    "%s %s%chost=%s%c",
1073                    prog, path, 0,
1074                    target_host, 0);
1075
1076        /* If using a new version put that stuff here after a second null byte */
1077        if (version > 0) {
1078                strbuf_addch(&request, '\0');
1079                strbuf_addf(&request, "version=%d%c",
1080                            version, '\0');
1081        }
1082
1083        packet_write(fd[1], request.buf, request.len);
1084
1085        free(target_host);
1086        strbuf_release(&request);
1087        return conn;
1088}
1089
1090/*
1091 * Append the appropriate environment variables to `env` and options to
1092 * `args` for running ssh in Git's SSH-tunneled transport.
1093 */
1094static void push_ssh_options(struct argv_array *args, struct argv_array *env,
1095                             enum ssh_variant variant, const char *port,
1096                             enum protocol_version version, int flags)
1097{
1098        if (variant == VARIANT_SSH &&
1099            version > 0) {
1100                argv_array_push(args, "-o");
1101                argv_array_push(args, "SendEnv=" GIT_PROTOCOL_ENVIRONMENT);
1102                argv_array_pushf(env, GIT_PROTOCOL_ENVIRONMENT "=version=%d",
1103                                 version);
1104        }
1105
1106        if (flags & CONNECT_IPV4) {
1107                switch (variant) {
1108                case VARIANT_AUTO:
1109                        BUG("VARIANT_AUTO passed to push_ssh_options");
1110                case VARIANT_SIMPLE:
1111                        die("ssh variant 'simple' does not support -4");
1112                case VARIANT_SSH:
1113                case VARIANT_PLINK:
1114                case VARIANT_PUTTY:
1115                case VARIANT_TORTOISEPLINK:
1116                        argv_array_push(args, "-4");
1117                }
1118        } else if (flags & CONNECT_IPV6) {
1119                switch (variant) {
1120                case VARIANT_AUTO:
1121                        BUG("VARIANT_AUTO passed to push_ssh_options");
1122                case VARIANT_SIMPLE:
1123                        die("ssh variant 'simple' does not support -6");
1124                case VARIANT_SSH:
1125                case VARIANT_PLINK:
1126                case VARIANT_PUTTY:
1127                case VARIANT_TORTOISEPLINK:
1128                        argv_array_push(args, "-6");
1129                }
1130        }
1131
1132        if (variant == VARIANT_TORTOISEPLINK)
1133                argv_array_push(args, "-batch");
1134
1135        if (port) {
1136                switch (variant) {
1137                case VARIANT_AUTO:
1138                        BUG("VARIANT_AUTO passed to push_ssh_options");
1139                case VARIANT_SIMPLE:
1140                        die("ssh variant 'simple' does not support setting port");
1141                case VARIANT_SSH:
1142                        argv_array_push(args, "-p");
1143                        break;
1144                case VARIANT_PLINK:
1145                case VARIANT_PUTTY:
1146                case VARIANT_TORTOISEPLINK:
1147                        argv_array_push(args, "-P");
1148                }
1149
1150                argv_array_push(args, port);
1151        }
1152}
1153
1154/* Prepare a child_process for use by Git's SSH-tunneled transport. */
1155static void fill_ssh_args(struct child_process *conn, const char *ssh_host,
1156                          const char *port, enum protocol_version version,
1157                          int flags)
1158{
1159        const char *ssh;
1160        enum ssh_variant variant;
1161
1162        if (looks_like_command_line_option(ssh_host))
1163                die("strange hostname '%s' blocked", ssh_host);
1164
1165        ssh = get_ssh_command();
1166        if (ssh) {
1167                variant = determine_ssh_variant(ssh, 1);
1168        } else {
1169                /*
1170                 * GIT_SSH is the no-shell version of
1171                 * GIT_SSH_COMMAND (and must remain so for
1172                 * historical compatibility).
1173                 */
1174                conn->use_shell = 0;
1175
1176                ssh = getenv("GIT_SSH");
1177                if (!ssh)
1178                        ssh = "ssh";
1179                variant = determine_ssh_variant(ssh, 0);
1180        }
1181
1182        if (variant == VARIANT_AUTO) {
1183                struct child_process detect = CHILD_PROCESS_INIT;
1184
1185                detect.use_shell = conn->use_shell;
1186                detect.no_stdin = detect.no_stdout = detect.no_stderr = 1;
1187
1188                argv_array_push(&detect.args, ssh);
1189                argv_array_push(&detect.args, "-G");
1190                push_ssh_options(&detect.args, &detect.env_array,
1191                                 VARIANT_SSH, port, version, flags);
1192                argv_array_push(&detect.args, ssh_host);
1193
1194                variant = run_command(&detect) ? VARIANT_SIMPLE : VARIANT_SSH;
1195        }
1196
1197        argv_array_push(&conn->args, ssh);
1198        push_ssh_options(&conn->args, &conn->env_array, variant, port, version, flags);
1199        argv_array_push(&conn->args, ssh_host);
1200}
1201
1202/*
1203 * This returns the dummy child_process `no_fork` if the transport protocol
1204 * does not need fork(2), or a struct child_process object if it does.  Once
1205 * done, finish the connection with finish_connect() with the value returned
1206 * from this function (it is safe to call finish_connect() with NULL to
1207 * support the former case).
1208 *
1209 * If it returns, the connect is successful; it just dies on errors (this
1210 * will hopefully be changed in a libification effort, to return NULL when
1211 * the connection failed).
1212 */
1213struct child_process *git_connect(int fd[2], const char *url,
1214                                  const char *prog, int flags)
1215{
1216        char *hostandport, *path;
1217        struct child_process *conn;
1218        enum protocol protocol;
1219        enum protocol_version version = get_protocol_version_config();
1220
1221        /*
1222         * NEEDSWORK: If we are trying to use protocol v2 and we are planning
1223         * to perform a push, then fallback to v0 since the client doesn't know
1224         * how to push yet using v2.
1225         */
1226        if (version == protocol_v2 && !strcmp("git-receive-pack", prog))
1227                version = protocol_v0;
1228
1229        /* Without this we cannot rely on waitpid() to tell
1230         * what happened to our children.
1231         */
1232        signal(SIGCHLD, SIG_DFL);
1233
1234        protocol = parse_connect_url(url, &hostandport, &path);
1235        if ((flags & CONNECT_DIAG_URL) && (protocol != PROTO_SSH)) {
1236                printf("Diag: url=%s\n", url ? url : "NULL");
1237                printf("Diag: protocol=%s\n", prot_name(protocol));
1238                printf("Diag: hostandport=%s\n", hostandport ? hostandport : "NULL");
1239                printf("Diag: path=%s\n", path ? path : "NULL");
1240                conn = NULL;
1241        } else if (protocol == PROTO_GIT) {
1242                conn = git_connect_git(fd, hostandport, path, prog, version, flags);
1243        } else {
1244                struct strbuf cmd = STRBUF_INIT;
1245                const char *const *var;
1246
1247                conn = xmalloc(sizeof(*conn));
1248                child_process_init(conn);
1249
1250                if (looks_like_command_line_option(path))
1251                        die("strange pathname '%s' blocked", path);
1252
1253                strbuf_addstr(&cmd, prog);
1254                strbuf_addch(&cmd, ' ');
1255                sq_quote_buf(&cmd, path);
1256
1257                /* remove repo-local variables from the environment */
1258                for (var = local_repo_env; *var; var++)
1259                        argv_array_push(&conn->env_array, *var);
1260
1261                conn->use_shell = 1;
1262                conn->in = conn->out = -1;
1263                if (protocol == PROTO_SSH) {
1264                        char *ssh_host = hostandport;
1265                        const char *port = NULL;
1266                        transport_check_allowed("ssh");
1267                        get_host_and_port(&ssh_host, &port);
1268
1269                        if (!port)
1270                                port = get_port(ssh_host);
1271
1272                        if (flags & CONNECT_DIAG_URL) {
1273                                printf("Diag: url=%s\n", url ? url : "NULL");
1274                                printf("Diag: protocol=%s\n", prot_name(protocol));
1275                                printf("Diag: userandhost=%s\n", ssh_host ? ssh_host : "NULL");
1276                                printf("Diag: port=%s\n", port ? port : "NONE");
1277                                printf("Diag: path=%s\n", path ? path : "NULL");
1278
1279                                free(hostandport);
1280                                free(path);
1281                                free(conn);
1282                                strbuf_release(&cmd);
1283                                return NULL;
1284                        }
1285                        fill_ssh_args(conn, ssh_host, port, version, flags);
1286                } else {
1287                        transport_check_allowed("file");
1288                        if (version > 0) {
1289                                argv_array_pushf(&conn->env_array, GIT_PROTOCOL_ENVIRONMENT "=version=%d",
1290                                                 version);
1291                        }
1292                }
1293                argv_array_push(&conn->args, cmd.buf);
1294
1295                if (start_command(conn))
1296                        die("unable to fork");
1297
1298                fd[0] = conn->out; /* read from child's stdout */
1299                fd[1] = conn->in;  /* write to child's stdin */
1300                strbuf_release(&cmd);
1301        }
1302        free(hostandport);
1303        free(path);
1304        return conn;
1305}
1306
1307int finish_connect(struct child_process *conn)
1308{
1309        int code;
1310        if (!conn || git_connection_is_socket(conn))
1311                return 0;
1312
1313        code = finish_command(conn);
1314        free(conn);
1315        return code;
1316}