Coverage Report

Created: 2023-11-30 07:19

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