http.con commit http: add support for selecting SSL backends at runtime (21084e8)
   1#include "git-compat-util.h"
   2#include "http.h"
   3#include "config.h"
   4#include "pack.h"
   5#include "sideband.h"
   6#include "run-command.h"
   7#include "url.h"
   8#include "urlmatch.h"
   9#include "credential.h"
  10#include "version.h"
  11#include "pkt-line.h"
  12#include "gettext.h"
  13#include "transport.h"
  14#include "packfile.h"
  15#include "protocol.h"
  16#include "string-list.h"
  17#include "object-store.h"
  18
  19static struct trace_key trace_curl = TRACE_KEY_INIT(CURL);
  20static int trace_curl_data = 1;
  21static struct string_list cookies_to_redact = STRING_LIST_INIT_DUP;
  22#if LIBCURL_VERSION_NUM >= 0x070a08
  23long int git_curl_ipresolve = CURL_IPRESOLVE_WHATEVER;
  24#else
  25long int git_curl_ipresolve;
  26#endif
  27int active_requests;
  28int http_is_verbose;
  29ssize_t http_post_buffer = 16 * LARGE_PACKET_MAX;
  30
  31#if LIBCURL_VERSION_NUM >= 0x070a06
  32#define LIBCURL_CAN_HANDLE_AUTH_ANY
  33#endif
  34
  35static int min_curl_sessions = 1;
  36static int curl_session_count;
  37#ifdef USE_CURL_MULTI
  38static int max_requests = -1;
  39static CURLM *curlm;
  40#endif
  41#ifndef NO_CURL_EASY_DUPHANDLE
  42static CURL *curl_default;
  43#endif
  44
  45#define PREV_BUF_SIZE 4096
  46
  47char curl_errorstr[CURL_ERROR_SIZE];
  48
  49static int curl_ssl_verify = -1;
  50static int curl_ssl_try;
  51static const char *ssl_cert;
  52static const char *ssl_cipherlist;
  53static const char *ssl_version;
  54static struct {
  55        const char *name;
  56        long ssl_version;
  57} sslversions[] = {
  58        { "sslv2", CURL_SSLVERSION_SSLv2 },
  59        { "sslv3", CURL_SSLVERSION_SSLv3 },
  60        { "tlsv1", CURL_SSLVERSION_TLSv1 },
  61#if LIBCURL_VERSION_NUM >= 0x072200
  62        { "tlsv1.0", CURL_SSLVERSION_TLSv1_0 },
  63        { "tlsv1.1", CURL_SSLVERSION_TLSv1_1 },
  64        { "tlsv1.2", CURL_SSLVERSION_TLSv1_2 },
  65#endif
  66#if LIBCURL_VERSION_NUM >= 0x073400
  67        { "tlsv1.3", CURL_SSLVERSION_TLSv1_3 },
  68#endif
  69};
  70#if LIBCURL_VERSION_NUM >= 0x070903
  71static const char *ssl_key;
  72#endif
  73#if LIBCURL_VERSION_NUM >= 0x070908
  74static const char *ssl_capath;
  75#endif
  76#if LIBCURL_VERSION_NUM >= 0x071304
  77static const char *curl_no_proxy;
  78#endif
  79#if LIBCURL_VERSION_NUM >= 0x072c00
  80static const char *ssl_pinnedkey;
  81#endif
  82static const char *ssl_cainfo;
  83static long curl_low_speed_limit = -1;
  84static long curl_low_speed_time = -1;
  85static int curl_ftp_no_epsv;
  86static const char *curl_http_proxy;
  87static const char *http_proxy_authmethod;
  88static struct {
  89        const char *name;
  90        long curlauth_param;
  91} proxy_authmethods[] = {
  92        { "basic", CURLAUTH_BASIC },
  93        { "digest", CURLAUTH_DIGEST },
  94        { "negotiate", CURLAUTH_GSSNEGOTIATE },
  95        { "ntlm", CURLAUTH_NTLM },
  96#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
  97        { "anyauth", CURLAUTH_ANY },
  98#endif
  99        /*
 100         * CURLAUTH_DIGEST_IE has no corresponding command-line option in
 101         * curl(1) and is not included in CURLAUTH_ANY, so we leave it out
 102         * here, too
 103         */
 104};
 105#ifdef CURLGSSAPI_DELEGATION_FLAG
 106static const char *curl_deleg;
 107static struct {
 108        const char *name;
 109        long curl_deleg_param;
 110} curl_deleg_levels[] = {
 111        { "none", CURLGSSAPI_DELEGATION_NONE },
 112        { "policy", CURLGSSAPI_DELEGATION_POLICY_FLAG },
 113        { "always", CURLGSSAPI_DELEGATION_FLAG },
 114};
 115#endif
 116
 117static struct credential proxy_auth = CREDENTIAL_INIT;
 118static const char *curl_proxyuserpwd;
 119static const char *curl_cookie_file;
 120static int curl_save_cookies;
 121struct credential http_auth = CREDENTIAL_INIT;
 122static int http_proactive_auth;
 123static const char *user_agent;
 124static int curl_empty_auth = -1;
 125
 126enum http_follow_config http_follow_config = HTTP_FOLLOW_INITIAL;
 127
 128#if LIBCURL_VERSION_NUM >= 0x071700
 129/* Use CURLOPT_KEYPASSWD as is */
 130#elif LIBCURL_VERSION_NUM >= 0x070903
 131#define CURLOPT_KEYPASSWD CURLOPT_SSLKEYPASSWD
 132#else
 133#define CURLOPT_KEYPASSWD CURLOPT_SSLCERTPASSWD
 134#endif
 135
 136static struct credential cert_auth = CREDENTIAL_INIT;
 137static int ssl_cert_password_required;
 138#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
 139static unsigned long http_auth_methods = CURLAUTH_ANY;
 140static int http_auth_methods_restricted;
 141/* Modes for which empty_auth cannot actually help us. */
 142static unsigned long empty_auth_useless =
 143        CURLAUTH_BASIC
 144#ifdef CURLAUTH_DIGEST_IE
 145        | CURLAUTH_DIGEST_IE
 146#endif
 147        | CURLAUTH_DIGEST;
 148#endif
 149
 150static struct curl_slist *pragma_header;
 151static struct curl_slist *no_pragma_header;
 152static struct curl_slist *extra_http_headers;
 153
 154static struct active_request_slot *active_queue_head;
 155
 156static char *cached_accept_language;
 157
 158static char *http_ssl_backend;
 159
 160size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_)
 161{
 162        size_t size = eltsize * nmemb;
 163        struct buffer *buffer = buffer_;
 164
 165        if (size > buffer->buf.len - buffer->posn)
 166                size = buffer->buf.len - buffer->posn;
 167        memcpy(ptr, buffer->buf.buf + buffer->posn, size);
 168        buffer->posn += size;
 169
 170        return size;
 171}
 172
 173#ifndef NO_CURL_IOCTL
 174curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp)
 175{
 176        struct buffer *buffer = clientp;
 177
 178        switch (cmd) {
 179        case CURLIOCMD_NOP:
 180                return CURLIOE_OK;
 181
 182        case CURLIOCMD_RESTARTREAD:
 183                buffer->posn = 0;
 184                return CURLIOE_OK;
 185
 186        default:
 187                return CURLIOE_UNKNOWNCMD;
 188        }
 189}
 190#endif
 191
 192size_t fwrite_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_)
 193{
 194        size_t size = eltsize * nmemb;
 195        struct strbuf *buffer = buffer_;
 196
 197        strbuf_add(buffer, ptr, size);
 198        return size;
 199}
 200
 201size_t fwrite_null(char *ptr, size_t eltsize, size_t nmemb, void *strbuf)
 202{
 203        return eltsize * nmemb;
 204}
 205
 206static void closedown_active_slot(struct active_request_slot *slot)
 207{
 208        active_requests--;
 209        slot->in_use = 0;
 210}
 211
 212static void finish_active_slot(struct active_request_slot *slot)
 213{
 214        closedown_active_slot(slot);
 215        curl_easy_getinfo(slot->curl, CURLINFO_HTTP_CODE, &slot->http_code);
 216
 217        if (slot->finished != NULL)
 218                (*slot->finished) = 1;
 219
 220        /* Store slot results so they can be read after the slot is reused */
 221        if (slot->results != NULL) {
 222                slot->results->curl_result = slot->curl_result;
 223                slot->results->http_code = slot->http_code;
 224#if LIBCURL_VERSION_NUM >= 0x070a08
 225                curl_easy_getinfo(slot->curl, CURLINFO_HTTPAUTH_AVAIL,
 226                                  &slot->results->auth_avail);
 227#else
 228                slot->results->auth_avail = 0;
 229#endif
 230
 231                curl_easy_getinfo(slot->curl, CURLINFO_HTTP_CONNECTCODE,
 232                        &slot->results->http_connectcode);
 233        }
 234
 235        /* Run callback if appropriate */
 236        if (slot->callback_func != NULL)
 237                slot->callback_func(slot->callback_data);
 238}
 239
 240static void xmulti_remove_handle(struct active_request_slot *slot)
 241{
 242#ifdef USE_CURL_MULTI
 243        curl_multi_remove_handle(curlm, slot->curl);
 244#endif
 245}
 246
 247#ifdef USE_CURL_MULTI
 248static void process_curl_messages(void)
 249{
 250        int num_messages;
 251        struct active_request_slot *slot;
 252        CURLMsg *curl_message = curl_multi_info_read(curlm, &num_messages);
 253
 254        while (curl_message != NULL) {
 255                if (curl_message->msg == CURLMSG_DONE) {
 256                        int curl_result = curl_message->data.result;
 257                        slot = active_queue_head;
 258                        while (slot != NULL &&
 259                               slot->curl != curl_message->easy_handle)
 260                                slot = slot->next;
 261                        if (slot != NULL) {
 262                                xmulti_remove_handle(slot);
 263                                slot->curl_result = curl_result;
 264                                finish_active_slot(slot);
 265                        } else {
 266                                fprintf(stderr, "Received DONE message for unknown request!\n");
 267                        }
 268                } else {
 269                        fprintf(stderr, "Unknown CURL message received: %d\n",
 270                                (int)curl_message->msg);
 271                }
 272                curl_message = curl_multi_info_read(curlm, &num_messages);
 273        }
 274}
 275#endif
 276
 277static int http_options(const char *var, const char *value, void *cb)
 278{
 279        if (!strcmp("http.sslverify", var)) {
 280                curl_ssl_verify = git_config_bool(var, value);
 281                return 0;
 282        }
 283        if (!strcmp("http.sslcipherlist", var))
 284                return git_config_string(&ssl_cipherlist, var, value);
 285        if (!strcmp("http.sslversion", var))
 286                return git_config_string(&ssl_version, var, value);
 287        if (!strcmp("http.sslcert", var))
 288                return git_config_pathname(&ssl_cert, var, value);
 289#if LIBCURL_VERSION_NUM >= 0x070903
 290        if (!strcmp("http.sslkey", var))
 291                return git_config_pathname(&ssl_key, var, value);
 292#endif
 293#if LIBCURL_VERSION_NUM >= 0x070908
 294        if (!strcmp("http.sslcapath", var))
 295                return git_config_pathname(&ssl_capath, var, value);
 296#endif
 297        if (!strcmp("http.sslcainfo", var))
 298                return git_config_pathname(&ssl_cainfo, var, value);
 299        if (!strcmp("http.sslcertpasswordprotected", var)) {
 300                ssl_cert_password_required = git_config_bool(var, value);
 301                return 0;
 302        }
 303        if (!strcmp("http.ssltry", var)) {
 304                curl_ssl_try = git_config_bool(var, value);
 305                return 0;
 306        }
 307        if (!strcmp("http.sslbackend", var)) {
 308                free(http_ssl_backend);
 309                http_ssl_backend = xstrdup_or_null(value);
 310                return 0;
 311        }
 312
 313        if (!strcmp("http.minsessions", var)) {
 314                min_curl_sessions = git_config_int(var, value);
 315#ifndef USE_CURL_MULTI
 316                if (min_curl_sessions > 1)
 317                        min_curl_sessions = 1;
 318#endif
 319                return 0;
 320        }
 321#ifdef USE_CURL_MULTI
 322        if (!strcmp("http.maxrequests", var)) {
 323                max_requests = git_config_int(var, value);
 324                return 0;
 325        }
 326#endif
 327        if (!strcmp("http.lowspeedlimit", var)) {
 328                curl_low_speed_limit = (long)git_config_int(var, value);
 329                return 0;
 330        }
 331        if (!strcmp("http.lowspeedtime", var)) {
 332                curl_low_speed_time = (long)git_config_int(var, value);
 333                return 0;
 334        }
 335
 336        if (!strcmp("http.noepsv", var)) {
 337                curl_ftp_no_epsv = git_config_bool(var, value);
 338                return 0;
 339        }
 340        if (!strcmp("http.proxy", var))
 341                return git_config_string(&curl_http_proxy, var, value);
 342
 343        if (!strcmp("http.proxyauthmethod", var))
 344                return git_config_string(&http_proxy_authmethod, var, value);
 345
 346        if (!strcmp("http.cookiefile", var))
 347                return git_config_pathname(&curl_cookie_file, var, value);
 348        if (!strcmp("http.savecookies", var)) {
 349                curl_save_cookies = git_config_bool(var, value);
 350                return 0;
 351        }
 352
 353        if (!strcmp("http.postbuffer", var)) {
 354                http_post_buffer = git_config_ssize_t(var, value);
 355                if (http_post_buffer < 0)
 356                        warning(_("negative value for http.postbuffer; defaulting to %d"), LARGE_PACKET_MAX);
 357                if (http_post_buffer < LARGE_PACKET_MAX)
 358                        http_post_buffer = LARGE_PACKET_MAX;
 359                return 0;
 360        }
 361
 362        if (!strcmp("http.useragent", var))
 363                return git_config_string(&user_agent, var, value);
 364
 365        if (!strcmp("http.emptyauth", var)) {
 366                if (value && !strcmp("auto", value))
 367                        curl_empty_auth = -1;
 368                else
 369                        curl_empty_auth = git_config_bool(var, value);
 370                return 0;
 371        }
 372
 373        if (!strcmp("http.delegation", var)) {
 374#ifdef CURLGSSAPI_DELEGATION_FLAG
 375                return git_config_string(&curl_deleg, var, value);
 376#else
 377                warning(_("Delegation control is not supported with cURL < 7.22.0"));
 378                return 0;
 379#endif
 380        }
 381
 382        if (!strcmp("http.pinnedpubkey", var)) {
 383#if LIBCURL_VERSION_NUM >= 0x072c00
 384                return git_config_pathname(&ssl_pinnedkey, var, value);
 385#else
 386                warning(_("Public key pinning not supported with cURL < 7.44.0"));
 387                return 0;
 388#endif
 389        }
 390
 391        if (!strcmp("http.extraheader", var)) {
 392                if (!value) {
 393                        return config_error_nonbool(var);
 394                } else if (!*value) {
 395                        curl_slist_free_all(extra_http_headers);
 396                        extra_http_headers = NULL;
 397                } else {
 398                        extra_http_headers =
 399                                curl_slist_append(extra_http_headers, value);
 400                }
 401                return 0;
 402        }
 403
 404        if (!strcmp("http.followredirects", var)) {
 405                if (value && !strcmp(value, "initial"))
 406                        http_follow_config = HTTP_FOLLOW_INITIAL;
 407                else if (git_config_bool(var, value))
 408                        http_follow_config = HTTP_FOLLOW_ALWAYS;
 409                else
 410                        http_follow_config = HTTP_FOLLOW_NONE;
 411                return 0;
 412        }
 413
 414        /* Fall back on the default ones */
 415        return git_default_config(var, value, cb);
 416}
 417
 418static int curl_empty_auth_enabled(void)
 419{
 420        if (curl_empty_auth >= 0)
 421                return curl_empty_auth;
 422
 423#ifndef LIBCURL_CAN_HANDLE_AUTH_ANY
 424        /*
 425         * Our libcurl is too old to do AUTH_ANY in the first place;
 426         * just default to turning the feature off.
 427         */
 428#else
 429        /*
 430         * In the automatic case, kick in the empty-auth
 431         * hack as long as we would potentially try some
 432         * method more exotic than "Basic" or "Digest".
 433         *
 434         * But only do this when this is our second or
 435         * subsequent request, as by then we know what
 436         * methods are available.
 437         */
 438        if (http_auth_methods_restricted &&
 439            (http_auth_methods & ~empty_auth_useless))
 440                return 1;
 441#endif
 442        return 0;
 443}
 444
 445static void init_curl_http_auth(CURL *result)
 446{
 447        if (!http_auth.username || !*http_auth.username) {
 448                if (curl_empty_auth_enabled())
 449                        curl_easy_setopt(result, CURLOPT_USERPWD, ":");
 450                return;
 451        }
 452
 453        credential_fill(&http_auth);
 454
 455#if LIBCURL_VERSION_NUM >= 0x071301
 456        curl_easy_setopt(result, CURLOPT_USERNAME, http_auth.username);
 457        curl_easy_setopt(result, CURLOPT_PASSWORD, http_auth.password);
 458#else
 459        {
 460                static struct strbuf up = STRBUF_INIT;
 461                /*
 462                 * Note that we assume we only ever have a single set of
 463                 * credentials in a given program run, so we do not have
 464                 * to worry about updating this buffer, only setting its
 465                 * initial value.
 466                 */
 467                if (!up.len)
 468                        strbuf_addf(&up, "%s:%s",
 469                                http_auth.username, http_auth.password);
 470                curl_easy_setopt(result, CURLOPT_USERPWD, up.buf);
 471        }
 472#endif
 473}
 474
 475/* *var must be free-able */
 476static void var_override(const char **var, char *value)
 477{
 478        if (value) {
 479                free((void *)*var);
 480                *var = xstrdup(value);
 481        }
 482}
 483
 484static void set_proxyauth_name_password(CURL *result)
 485{
 486#if LIBCURL_VERSION_NUM >= 0x071301
 487                curl_easy_setopt(result, CURLOPT_PROXYUSERNAME,
 488                        proxy_auth.username);
 489                curl_easy_setopt(result, CURLOPT_PROXYPASSWORD,
 490                        proxy_auth.password);
 491#else
 492                struct strbuf s = STRBUF_INIT;
 493
 494                strbuf_addstr_urlencode(&s, proxy_auth.username, 1);
 495                strbuf_addch(&s, ':');
 496                strbuf_addstr_urlencode(&s, proxy_auth.password, 1);
 497                curl_proxyuserpwd = strbuf_detach(&s, NULL);
 498                curl_easy_setopt(result, CURLOPT_PROXYUSERPWD, curl_proxyuserpwd);
 499#endif
 500}
 501
 502static void init_curl_proxy_auth(CURL *result)
 503{
 504        if (proxy_auth.username) {
 505                if (!proxy_auth.password)
 506                        credential_fill(&proxy_auth);
 507                set_proxyauth_name_password(result);
 508        }
 509
 510        var_override(&http_proxy_authmethod, getenv("GIT_HTTP_PROXY_AUTHMETHOD"));
 511
 512#if LIBCURL_VERSION_NUM >= 0x070a07 /* CURLOPT_PROXYAUTH and CURLAUTH_ANY */
 513        if (http_proxy_authmethod) {
 514                int i;
 515                for (i = 0; i < ARRAY_SIZE(proxy_authmethods); i++) {
 516                        if (!strcmp(http_proxy_authmethod, proxy_authmethods[i].name)) {
 517                                curl_easy_setopt(result, CURLOPT_PROXYAUTH,
 518                                                proxy_authmethods[i].curlauth_param);
 519                                break;
 520                        }
 521                }
 522                if (i == ARRAY_SIZE(proxy_authmethods)) {
 523                        warning("unsupported proxy authentication method %s: using anyauth",
 524                                        http_proxy_authmethod);
 525                        curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
 526                }
 527        }
 528        else
 529                curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
 530#endif
 531}
 532
 533static int has_cert_password(void)
 534{
 535        if (ssl_cert == NULL || ssl_cert_password_required != 1)
 536                return 0;
 537        if (!cert_auth.password) {
 538                cert_auth.protocol = xstrdup("cert");
 539                cert_auth.username = xstrdup("");
 540                cert_auth.path = xstrdup(ssl_cert);
 541                credential_fill(&cert_auth);
 542        }
 543        return 1;
 544}
 545
 546#if LIBCURL_VERSION_NUM >= 0x071900
 547static void set_curl_keepalive(CURL *c)
 548{
 549        curl_easy_setopt(c, CURLOPT_TCP_KEEPALIVE, 1);
 550}
 551
 552#elif LIBCURL_VERSION_NUM >= 0x071000
 553static int sockopt_callback(void *client, curl_socket_t fd, curlsocktype type)
 554{
 555        int ka = 1;
 556        int rc;
 557        socklen_t len = (socklen_t)sizeof(ka);
 558
 559        if (type != CURLSOCKTYPE_IPCXN)
 560                return 0;
 561
 562        rc = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&ka, len);
 563        if (rc < 0)
 564                warning_errno("unable to set SO_KEEPALIVE on socket");
 565
 566        return 0; /* CURL_SOCKOPT_OK only exists since curl 7.21.5 */
 567}
 568
 569static void set_curl_keepalive(CURL *c)
 570{
 571        curl_easy_setopt(c, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
 572}
 573
 574#else
 575static void set_curl_keepalive(CURL *c)
 576{
 577        /* not supported on older curl versions */
 578}
 579#endif
 580
 581static void redact_sensitive_header(struct strbuf *header)
 582{
 583        const char *sensitive_header;
 584
 585        if (skip_prefix(header->buf, "Authorization:", &sensitive_header) ||
 586            skip_prefix(header->buf, "Proxy-Authorization:", &sensitive_header)) {
 587                /* The first token is the type, which is OK to log */
 588                while (isspace(*sensitive_header))
 589                        sensitive_header++;
 590                while (*sensitive_header && !isspace(*sensitive_header))
 591                        sensitive_header++;
 592                /* Everything else is opaque and possibly sensitive */
 593                strbuf_setlen(header,  sensitive_header - header->buf);
 594                strbuf_addstr(header, " <redacted>");
 595        } else if (cookies_to_redact.nr &&
 596                   skip_prefix(header->buf, "Cookie:", &sensitive_header)) {
 597                struct strbuf redacted_header = STRBUF_INIT;
 598                char *cookie;
 599
 600                while (isspace(*sensitive_header))
 601                        sensitive_header++;
 602
 603                /*
 604                 * The contents of header starting from sensitive_header will
 605                 * subsequently be overridden, so it is fine to mutate this
 606                 * string (hence the assignment to "char *").
 607                 */
 608                cookie = (char *) sensitive_header;
 609
 610                while (cookie) {
 611                        char *equals;
 612                        char *semicolon = strstr(cookie, "; ");
 613                        if (semicolon)
 614                                *semicolon = 0;
 615                        equals = strchrnul(cookie, '=');
 616                        if (!equals) {
 617                                /* invalid cookie, just append and continue */
 618                                strbuf_addstr(&redacted_header, cookie);
 619                                continue;
 620                        }
 621                        *equals = 0; /* temporarily set to NUL for lookup */
 622                        if (string_list_lookup(&cookies_to_redact, cookie)) {
 623                                strbuf_addstr(&redacted_header, cookie);
 624                                strbuf_addstr(&redacted_header, "=<redacted>");
 625                        } else {
 626                                *equals = '=';
 627                                strbuf_addstr(&redacted_header, cookie);
 628                        }
 629                        if (semicolon) {
 630                                /*
 631                                 * There are more cookies. (Or, for some
 632                                 * reason, the input string ends in "; ".)
 633                                 */
 634                                strbuf_addstr(&redacted_header, "; ");
 635                                cookie = semicolon + strlen("; ");
 636                        } else {
 637                                cookie = NULL;
 638                        }
 639                }
 640
 641                strbuf_setlen(header, sensitive_header - header->buf);
 642                strbuf_addbuf(header, &redacted_header);
 643        }
 644}
 645
 646static void curl_dump_header(const char *text, unsigned char *ptr, size_t size, int hide_sensitive_header)
 647{
 648        struct strbuf out = STRBUF_INIT;
 649        struct strbuf **headers, **header;
 650
 651        strbuf_addf(&out, "%s, %10.10ld bytes (0x%8.8lx)\n",
 652                text, (long)size, (long)size);
 653        trace_strbuf(&trace_curl, &out);
 654        strbuf_reset(&out);
 655        strbuf_add(&out, ptr, size);
 656        headers = strbuf_split_max(&out, '\n', 0);
 657
 658        for (header = headers; *header; header++) {
 659                if (hide_sensitive_header)
 660                        redact_sensitive_header(*header);
 661                strbuf_insert((*header), 0, text, strlen(text));
 662                strbuf_insert((*header), strlen(text), ": ", 2);
 663                strbuf_rtrim((*header));
 664                strbuf_addch((*header), '\n');
 665                trace_strbuf(&trace_curl, (*header));
 666        }
 667        strbuf_list_free(headers);
 668        strbuf_release(&out);
 669}
 670
 671static void curl_dump_data(const char *text, unsigned char *ptr, size_t size)
 672{
 673        size_t i;
 674        struct strbuf out = STRBUF_INIT;
 675        unsigned int width = 60;
 676
 677        strbuf_addf(&out, "%s, %10.10ld bytes (0x%8.8lx)\n",
 678                text, (long)size, (long)size);
 679        trace_strbuf(&trace_curl, &out);
 680
 681        for (i = 0; i < size; i += width) {
 682                size_t w;
 683
 684                strbuf_reset(&out);
 685                strbuf_addf(&out, "%s: ", text);
 686                for (w = 0; (w < width) && (i + w < size); w++) {
 687                        unsigned char ch = ptr[i + w];
 688
 689                        strbuf_addch(&out,
 690                                       (ch >= 0x20) && (ch < 0x80)
 691                                       ? ch : '.');
 692                }
 693                strbuf_addch(&out, '\n');
 694                trace_strbuf(&trace_curl, &out);
 695        }
 696        strbuf_release(&out);
 697}
 698
 699static int curl_trace(CURL *handle, curl_infotype type, char *data, size_t size, void *userp)
 700{
 701        const char *text;
 702        enum { NO_FILTER = 0, DO_FILTER = 1 };
 703
 704        switch (type) {
 705        case CURLINFO_TEXT:
 706                trace_printf_key(&trace_curl, "== Info: %s", data);
 707                break;
 708        case CURLINFO_HEADER_OUT:
 709                text = "=> Send header";
 710                curl_dump_header(text, (unsigned char *)data, size, DO_FILTER);
 711                break;
 712        case CURLINFO_DATA_OUT:
 713                if (trace_curl_data) {
 714                        text = "=> Send data";
 715                        curl_dump_data(text, (unsigned char *)data, size);
 716                }
 717                break;
 718        case CURLINFO_SSL_DATA_OUT:
 719                if (trace_curl_data) {
 720                        text = "=> Send SSL data";
 721                        curl_dump_data(text, (unsigned char *)data, size);
 722                }
 723                break;
 724        case CURLINFO_HEADER_IN:
 725                text = "<= Recv header";
 726                curl_dump_header(text, (unsigned char *)data, size, NO_FILTER);
 727                break;
 728        case CURLINFO_DATA_IN:
 729                if (trace_curl_data) {
 730                        text = "<= Recv data";
 731                        curl_dump_data(text, (unsigned char *)data, size);
 732                }
 733                break;
 734        case CURLINFO_SSL_DATA_IN:
 735                if (trace_curl_data) {
 736                        text = "<= Recv SSL data";
 737                        curl_dump_data(text, (unsigned char *)data, size);
 738                }
 739                break;
 740
 741        default:                /* we ignore unknown types by default */
 742                return 0;
 743        }
 744        return 0;
 745}
 746
 747void setup_curl_trace(CURL *handle)
 748{
 749        if (!trace_want(&trace_curl))
 750                return;
 751        curl_easy_setopt(handle, CURLOPT_VERBOSE, 1L);
 752        curl_easy_setopt(handle, CURLOPT_DEBUGFUNCTION, curl_trace);
 753        curl_easy_setopt(handle, CURLOPT_DEBUGDATA, NULL);
 754}
 755
 756#ifdef CURLPROTO_HTTP
 757static long get_curl_allowed_protocols(int from_user)
 758{
 759        long allowed_protocols = 0;
 760
 761        if (is_transport_allowed("http", from_user))
 762                allowed_protocols |= CURLPROTO_HTTP;
 763        if (is_transport_allowed("https", from_user))
 764                allowed_protocols |= CURLPROTO_HTTPS;
 765        if (is_transport_allowed("ftp", from_user))
 766                allowed_protocols |= CURLPROTO_FTP;
 767        if (is_transport_allowed("ftps", from_user))
 768                allowed_protocols |= CURLPROTO_FTPS;
 769
 770        return allowed_protocols;
 771}
 772#endif
 773
 774static CURL *get_curl_handle(void)
 775{
 776        CURL *result = curl_easy_init();
 777
 778        if (!result)
 779                die("curl_easy_init failed");
 780
 781        if (!curl_ssl_verify) {
 782                curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 0);
 783                curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 0);
 784        } else {
 785                /* Verify authenticity of the peer's certificate */
 786                curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 1);
 787                /* The name in the cert must match whom we tried to connect */
 788                curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 2);
 789        }
 790
 791#if LIBCURL_VERSION_NUM >= 0x070907
 792        curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
 793#endif
 794#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
 795        curl_easy_setopt(result, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
 796#endif
 797
 798#ifdef CURLGSSAPI_DELEGATION_FLAG
 799        if (curl_deleg) {
 800                int i;
 801                for (i = 0; i < ARRAY_SIZE(curl_deleg_levels); i++) {
 802                        if (!strcmp(curl_deleg, curl_deleg_levels[i].name)) {
 803                                curl_easy_setopt(result, CURLOPT_GSSAPI_DELEGATION,
 804                                                curl_deleg_levels[i].curl_deleg_param);
 805                                break;
 806                        }
 807                }
 808                if (i == ARRAY_SIZE(curl_deleg_levels))
 809                        warning("Unknown delegation method '%s': using default",
 810                                curl_deleg);
 811        }
 812#endif
 813
 814        if (http_proactive_auth)
 815                init_curl_http_auth(result);
 816
 817        if (getenv("GIT_SSL_VERSION"))
 818                ssl_version = getenv("GIT_SSL_VERSION");
 819        if (ssl_version && *ssl_version) {
 820                int i;
 821                for (i = 0; i < ARRAY_SIZE(sslversions); i++) {
 822                        if (!strcmp(ssl_version, sslversions[i].name)) {
 823                                curl_easy_setopt(result, CURLOPT_SSLVERSION,
 824                                                 sslversions[i].ssl_version);
 825                                break;
 826                        }
 827                }
 828                if (i == ARRAY_SIZE(sslversions))
 829                        warning("unsupported ssl version %s: using default",
 830                                ssl_version);
 831        }
 832
 833        if (getenv("GIT_SSL_CIPHER_LIST"))
 834                ssl_cipherlist = getenv("GIT_SSL_CIPHER_LIST");
 835        if (ssl_cipherlist != NULL && *ssl_cipherlist)
 836                curl_easy_setopt(result, CURLOPT_SSL_CIPHER_LIST,
 837                                ssl_cipherlist);
 838
 839        if (ssl_cert != NULL)
 840                curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert);
 841        if (has_cert_password())
 842                curl_easy_setopt(result, CURLOPT_KEYPASSWD, cert_auth.password);
 843#if LIBCURL_VERSION_NUM >= 0x070903
 844        if (ssl_key != NULL)
 845                curl_easy_setopt(result, CURLOPT_SSLKEY, ssl_key);
 846#endif
 847#if LIBCURL_VERSION_NUM >= 0x070908
 848        if (ssl_capath != NULL)
 849                curl_easy_setopt(result, CURLOPT_CAPATH, ssl_capath);
 850#endif
 851#if LIBCURL_VERSION_NUM >= 0x072c00
 852        if (ssl_pinnedkey != NULL)
 853                curl_easy_setopt(result, CURLOPT_PINNEDPUBLICKEY, ssl_pinnedkey);
 854#endif
 855        if (ssl_cainfo != NULL)
 856                curl_easy_setopt(result, CURLOPT_CAINFO, ssl_cainfo);
 857
 858        if (curl_low_speed_limit > 0 && curl_low_speed_time > 0) {
 859                curl_easy_setopt(result, CURLOPT_LOW_SPEED_LIMIT,
 860                                 curl_low_speed_limit);
 861                curl_easy_setopt(result, CURLOPT_LOW_SPEED_TIME,
 862                                 curl_low_speed_time);
 863        }
 864
 865        curl_easy_setopt(result, CURLOPT_MAXREDIRS, 20);
 866#if LIBCURL_VERSION_NUM >= 0x071301
 867        curl_easy_setopt(result, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL);
 868#elif LIBCURL_VERSION_NUM >= 0x071101
 869        curl_easy_setopt(result, CURLOPT_POST301, 1);
 870#endif
 871#ifdef CURLPROTO_HTTP
 872        curl_easy_setopt(result, CURLOPT_REDIR_PROTOCOLS,
 873                         get_curl_allowed_protocols(0));
 874        curl_easy_setopt(result, CURLOPT_PROTOCOLS,
 875                         get_curl_allowed_protocols(-1));
 876#else
 877        warning("protocol restrictions not applied to curl redirects because\n"
 878                "your curl version is too old (>= 7.19.4)");
 879#endif
 880        if (getenv("GIT_CURL_VERBOSE"))
 881                curl_easy_setopt(result, CURLOPT_VERBOSE, 1L);
 882        setup_curl_trace(result);
 883        if (getenv("GIT_TRACE_CURL_NO_DATA"))
 884                trace_curl_data = 0;
 885        if (getenv("GIT_REDACT_COOKIES")) {
 886                string_list_split(&cookies_to_redact,
 887                                  getenv("GIT_REDACT_COOKIES"), ',', -1);
 888                string_list_sort(&cookies_to_redact);
 889        }
 890
 891        curl_easy_setopt(result, CURLOPT_USERAGENT,
 892                user_agent ? user_agent : git_user_agent());
 893
 894        if (curl_ftp_no_epsv)
 895                curl_easy_setopt(result, CURLOPT_FTP_USE_EPSV, 0);
 896
 897#ifdef CURLOPT_USE_SSL
 898        if (curl_ssl_try)
 899                curl_easy_setopt(result, CURLOPT_USE_SSL, CURLUSESSL_TRY);
 900#endif
 901
 902        /*
 903         * CURL also examines these variables as a fallback; but we need to query
 904         * them here in order to decide whether to prompt for missing password (cf.
 905         * init_curl_proxy_auth()).
 906         *
 907         * Unlike many other common environment variables, these are historically
 908         * lowercase only. It appears that CURL did not know this and implemented
 909         * only uppercase variants, which was later corrected to take both - with
 910         * the exception of http_proxy, which is lowercase only also in CURL. As
 911         * the lowercase versions are the historical quasi-standard, they take
 912         * precedence here, as in CURL.
 913         */
 914        if (!curl_http_proxy) {
 915                if (http_auth.protocol && !strcmp(http_auth.protocol, "https")) {
 916                        var_override(&curl_http_proxy, getenv("HTTPS_PROXY"));
 917                        var_override(&curl_http_proxy, getenv("https_proxy"));
 918                } else {
 919                        var_override(&curl_http_proxy, getenv("http_proxy"));
 920                }
 921                if (!curl_http_proxy) {
 922                        var_override(&curl_http_proxy, getenv("ALL_PROXY"));
 923                        var_override(&curl_http_proxy, getenv("all_proxy"));
 924                }
 925        }
 926
 927        if (curl_http_proxy && curl_http_proxy[0] == '\0') {
 928                /*
 929                 * Handle case with the empty http.proxy value here to keep
 930                 * common code clean.
 931                 * NB: empty option disables proxying at all.
 932                 */
 933                curl_easy_setopt(result, CURLOPT_PROXY, "");
 934        } else if (curl_http_proxy) {
 935#if LIBCURL_VERSION_NUM >= 0x071800
 936                if (starts_with(curl_http_proxy, "socks5h"))
 937                        curl_easy_setopt(result,
 938                                CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5_HOSTNAME);
 939                else if (starts_with(curl_http_proxy, "socks5"))
 940                        curl_easy_setopt(result,
 941                                CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
 942                else if (starts_with(curl_http_proxy, "socks4a"))
 943                        curl_easy_setopt(result,
 944                                CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4A);
 945                else if (starts_with(curl_http_proxy, "socks"))
 946                        curl_easy_setopt(result,
 947                                CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
 948#endif
 949#if LIBCURL_VERSION_NUM >= 0x073400
 950                else if (starts_with(curl_http_proxy, "https"))
 951                        curl_easy_setopt(result,
 952                                CURLOPT_PROXYTYPE, CURLPROXY_HTTPS);
 953#endif
 954                if (strstr(curl_http_proxy, "://"))
 955                        credential_from_url(&proxy_auth, curl_http_proxy);
 956                else {
 957                        struct strbuf url = STRBUF_INIT;
 958                        strbuf_addf(&url, "http://%s", curl_http_proxy);
 959                        credential_from_url(&proxy_auth, url.buf);
 960                        strbuf_release(&url);
 961                }
 962
 963                if (!proxy_auth.host)
 964                        die("Invalid proxy URL '%s'", curl_http_proxy);
 965
 966                curl_easy_setopt(result, CURLOPT_PROXY, proxy_auth.host);
 967#if LIBCURL_VERSION_NUM >= 0x071304
 968                var_override(&curl_no_proxy, getenv("NO_PROXY"));
 969                var_override(&curl_no_proxy, getenv("no_proxy"));
 970                curl_easy_setopt(result, CURLOPT_NOPROXY, curl_no_proxy);
 971#endif
 972        }
 973        init_curl_proxy_auth(result);
 974
 975        set_curl_keepalive(result);
 976
 977        return result;
 978}
 979
 980static void set_from_env(const char **var, const char *envname)
 981{
 982        const char *val = getenv(envname);
 983        if (val)
 984                *var = val;
 985}
 986
 987void http_init(struct remote *remote, const char *url, int proactive_auth)
 988{
 989        char *low_speed_limit;
 990        char *low_speed_time;
 991        char *normalized_url;
 992        struct urlmatch_config config = { STRING_LIST_INIT_DUP };
 993
 994        config.section = "http";
 995        config.key = NULL;
 996        config.collect_fn = http_options;
 997        config.cascade_fn = git_default_config;
 998        config.cb = NULL;
 999
1000        http_is_verbose = 0;
1001        normalized_url = url_normalize(url, &config.url);
1002
1003        git_config(urlmatch_config_entry, &config);
1004        free(normalized_url);
1005
1006#if LIBCURL_VERSION_NUM >= 0x073800
1007        if (http_ssl_backend) {
1008                const curl_ssl_backend **backends;
1009                struct strbuf buf = STRBUF_INIT;
1010                int i;
1011
1012                switch (curl_global_sslset(-1, http_ssl_backend, &backends)) {
1013                case CURLSSLSET_UNKNOWN_BACKEND:
1014                        strbuf_addf(&buf, _("Unsupported SSL backend '%s'. "
1015                                            "Supported SSL backends:"),
1016                                            http_ssl_backend);
1017                        for (i = 0; backends[i]; i++)
1018                                strbuf_addf(&buf, "\n\t%s", backends[i]->name);
1019                        die("%s", buf.buf);
1020                case CURLSSLSET_NO_BACKENDS:
1021                        die(_("Could not set SSL backend to '%s': "
1022                              "cURL was built without SSL backends"),
1023                            http_ssl_backend);
1024                case CURLSSLSET_TOO_LATE:
1025                        die(_("Could not set SSL backend to '%s': already set"),
1026                            http_ssl_backend);
1027                case CURLSSLSET_OK:
1028                        break; /* Okay! */
1029                }
1030        }
1031#endif
1032
1033        if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK)
1034                die("curl_global_init failed");
1035
1036        http_proactive_auth = proactive_auth;
1037
1038        if (remote && remote->http_proxy)
1039                curl_http_proxy = xstrdup(remote->http_proxy);
1040
1041        if (remote)
1042                var_override(&http_proxy_authmethod, remote->http_proxy_authmethod);
1043
1044        pragma_header = curl_slist_append(http_copy_default_headers(),
1045                "Pragma: no-cache");
1046        no_pragma_header = curl_slist_append(http_copy_default_headers(),
1047                "Pragma:");
1048
1049#ifdef USE_CURL_MULTI
1050        {
1051                char *http_max_requests = getenv("GIT_HTTP_MAX_REQUESTS");
1052                if (http_max_requests != NULL)
1053                        max_requests = atoi(http_max_requests);
1054        }
1055
1056        curlm = curl_multi_init();
1057        if (!curlm)
1058                die("curl_multi_init failed");
1059#endif
1060
1061        if (getenv("GIT_SSL_NO_VERIFY"))
1062                curl_ssl_verify = 0;
1063
1064        set_from_env(&ssl_cert, "GIT_SSL_CERT");
1065#if LIBCURL_VERSION_NUM >= 0x070903
1066        set_from_env(&ssl_key, "GIT_SSL_KEY");
1067#endif
1068#if LIBCURL_VERSION_NUM >= 0x070908
1069        set_from_env(&ssl_capath, "GIT_SSL_CAPATH");
1070#endif
1071        set_from_env(&ssl_cainfo, "GIT_SSL_CAINFO");
1072
1073        set_from_env(&user_agent, "GIT_HTTP_USER_AGENT");
1074
1075        low_speed_limit = getenv("GIT_HTTP_LOW_SPEED_LIMIT");
1076        if (low_speed_limit != NULL)
1077                curl_low_speed_limit = strtol(low_speed_limit, NULL, 10);
1078        low_speed_time = getenv("GIT_HTTP_LOW_SPEED_TIME");
1079        if (low_speed_time != NULL)
1080                curl_low_speed_time = strtol(low_speed_time, NULL, 10);
1081
1082        if (curl_ssl_verify == -1)
1083                curl_ssl_verify = 1;
1084
1085        curl_session_count = 0;
1086#ifdef USE_CURL_MULTI
1087        if (max_requests < 1)
1088                max_requests = DEFAULT_MAX_REQUESTS;
1089#endif
1090
1091        if (getenv("GIT_CURL_FTP_NO_EPSV"))
1092                curl_ftp_no_epsv = 1;
1093
1094        if (url) {
1095                credential_from_url(&http_auth, url);
1096                if (!ssl_cert_password_required &&
1097                    getenv("GIT_SSL_CERT_PASSWORD_PROTECTED") &&
1098                    starts_with(url, "https://"))
1099                        ssl_cert_password_required = 1;
1100        }
1101
1102#ifndef NO_CURL_EASY_DUPHANDLE
1103        curl_default = get_curl_handle();
1104#endif
1105}
1106
1107void http_cleanup(void)
1108{
1109        struct active_request_slot *slot = active_queue_head;
1110
1111        while (slot != NULL) {
1112                struct active_request_slot *next = slot->next;
1113                if (slot->curl != NULL) {
1114                        xmulti_remove_handle(slot);
1115                        curl_easy_cleanup(slot->curl);
1116                }
1117                free(slot);
1118                slot = next;
1119        }
1120        active_queue_head = NULL;
1121
1122#ifndef NO_CURL_EASY_DUPHANDLE
1123        curl_easy_cleanup(curl_default);
1124#endif
1125
1126#ifdef USE_CURL_MULTI
1127        curl_multi_cleanup(curlm);
1128#endif
1129        curl_global_cleanup();
1130
1131        curl_slist_free_all(extra_http_headers);
1132        extra_http_headers = NULL;
1133
1134        curl_slist_free_all(pragma_header);
1135        pragma_header = NULL;
1136
1137        curl_slist_free_all(no_pragma_header);
1138        no_pragma_header = NULL;
1139
1140        if (curl_http_proxy) {
1141                free((void *)curl_http_proxy);
1142                curl_http_proxy = NULL;
1143        }
1144
1145        if (proxy_auth.password) {
1146                memset(proxy_auth.password, 0, strlen(proxy_auth.password));
1147                FREE_AND_NULL(proxy_auth.password);
1148        }
1149
1150        free((void *)curl_proxyuserpwd);
1151        curl_proxyuserpwd = NULL;
1152
1153        free((void *)http_proxy_authmethod);
1154        http_proxy_authmethod = NULL;
1155
1156        if (cert_auth.password != NULL) {
1157                memset(cert_auth.password, 0, strlen(cert_auth.password));
1158                FREE_AND_NULL(cert_auth.password);
1159        }
1160        ssl_cert_password_required = 0;
1161
1162        FREE_AND_NULL(cached_accept_language);
1163}
1164
1165struct active_request_slot *get_active_slot(void)
1166{
1167        struct active_request_slot *slot = active_queue_head;
1168        struct active_request_slot *newslot;
1169
1170#ifdef USE_CURL_MULTI
1171        int num_transfers;
1172
1173        /* Wait for a slot to open up if the queue is full */
1174        while (active_requests >= max_requests) {
1175                curl_multi_perform(curlm, &num_transfers);
1176                if (num_transfers < active_requests)
1177                        process_curl_messages();
1178        }
1179#endif
1180
1181        while (slot != NULL && slot->in_use)
1182                slot = slot->next;
1183
1184        if (slot == NULL) {
1185                newslot = xmalloc(sizeof(*newslot));
1186                newslot->curl = NULL;
1187                newslot->in_use = 0;
1188                newslot->next = NULL;
1189
1190                slot = active_queue_head;
1191                if (slot == NULL) {
1192                        active_queue_head = newslot;
1193                } else {
1194                        while (slot->next != NULL)
1195                                slot = slot->next;
1196                        slot->next = newslot;
1197                }
1198                slot = newslot;
1199        }
1200
1201        if (slot->curl == NULL) {
1202#ifdef NO_CURL_EASY_DUPHANDLE
1203                slot->curl = get_curl_handle();
1204#else
1205                slot->curl = curl_easy_duphandle(curl_default);
1206#endif
1207                curl_session_count++;
1208        }
1209
1210        active_requests++;
1211        slot->in_use = 1;
1212        slot->results = NULL;
1213        slot->finished = NULL;
1214        slot->callback_data = NULL;
1215        slot->callback_func = NULL;
1216        curl_easy_setopt(slot->curl, CURLOPT_COOKIEFILE, curl_cookie_file);
1217        if (curl_save_cookies)
1218                curl_easy_setopt(slot->curl, CURLOPT_COOKIEJAR, curl_cookie_file);
1219        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, pragma_header);
1220        curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, curl_errorstr);
1221        curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, NULL);
1222        curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, NULL);
1223        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, NULL);
1224        curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, NULL);
1225        curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 0);
1226        curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
1227        curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 1);
1228        curl_easy_setopt(slot->curl, CURLOPT_RANGE, NULL);
1229
1230        /*
1231         * Default following to off unless "ALWAYS" is configured; this gives
1232         * callers a sane starting point, and they can tweak for individual
1233         * HTTP_FOLLOW_* cases themselves.
1234         */
1235        if (http_follow_config == HTTP_FOLLOW_ALWAYS)
1236                curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 1);
1237        else
1238                curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 0);
1239
1240#if LIBCURL_VERSION_NUM >= 0x070a08
1241        curl_easy_setopt(slot->curl, CURLOPT_IPRESOLVE, git_curl_ipresolve);
1242#endif
1243#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
1244        curl_easy_setopt(slot->curl, CURLOPT_HTTPAUTH, http_auth_methods);
1245#endif
1246        if (http_auth.password || curl_empty_auth_enabled())
1247                init_curl_http_auth(slot->curl);
1248
1249        return slot;
1250}
1251
1252int start_active_slot(struct active_request_slot *slot)
1253{
1254#ifdef USE_CURL_MULTI
1255        CURLMcode curlm_result = curl_multi_add_handle(curlm, slot->curl);
1256        int num_transfers;
1257
1258        if (curlm_result != CURLM_OK &&
1259            curlm_result != CURLM_CALL_MULTI_PERFORM) {
1260                warning("curl_multi_add_handle failed: %s",
1261                        curl_multi_strerror(curlm_result));
1262                active_requests--;
1263                slot->in_use = 0;
1264                return 0;
1265        }
1266
1267        /*
1268         * We know there must be something to do, since we just added
1269         * something.
1270         */
1271        curl_multi_perform(curlm, &num_transfers);
1272#endif
1273        return 1;
1274}
1275
1276#ifdef USE_CURL_MULTI
1277struct fill_chain {
1278        void *data;
1279        int (*fill)(void *);
1280        struct fill_chain *next;
1281};
1282
1283static struct fill_chain *fill_cfg;
1284
1285void add_fill_function(void *data, int (*fill)(void *))
1286{
1287        struct fill_chain *new_fill = xmalloc(sizeof(*new_fill));
1288        struct fill_chain **linkp = &fill_cfg;
1289        new_fill->data = data;
1290        new_fill->fill = fill;
1291        new_fill->next = NULL;
1292        while (*linkp)
1293                linkp = &(*linkp)->next;
1294        *linkp = new_fill;
1295}
1296
1297void fill_active_slots(void)
1298{
1299        struct active_request_slot *slot = active_queue_head;
1300
1301        while (active_requests < max_requests) {
1302                struct fill_chain *fill;
1303                for (fill = fill_cfg; fill; fill = fill->next)
1304                        if (fill->fill(fill->data))
1305                                break;
1306
1307                if (!fill)
1308                        break;
1309        }
1310
1311        while (slot != NULL) {
1312                if (!slot->in_use && slot->curl != NULL
1313                        && curl_session_count > min_curl_sessions) {
1314                        curl_easy_cleanup(slot->curl);
1315                        slot->curl = NULL;
1316                        curl_session_count--;
1317                }
1318                slot = slot->next;
1319        }
1320}
1321
1322void step_active_slots(void)
1323{
1324        int num_transfers;
1325        CURLMcode curlm_result;
1326
1327        do {
1328                curlm_result = curl_multi_perform(curlm, &num_transfers);
1329        } while (curlm_result == CURLM_CALL_MULTI_PERFORM);
1330        if (num_transfers < active_requests) {
1331                process_curl_messages();
1332                fill_active_slots();
1333        }
1334}
1335#endif
1336
1337void run_active_slot(struct active_request_slot *slot)
1338{
1339#ifdef USE_CURL_MULTI
1340        fd_set readfds;
1341        fd_set writefds;
1342        fd_set excfds;
1343        int max_fd;
1344        struct timeval select_timeout;
1345        int finished = 0;
1346
1347        slot->finished = &finished;
1348        while (!finished) {
1349                step_active_slots();
1350
1351                if (slot->in_use) {
1352#if LIBCURL_VERSION_NUM >= 0x070f04
1353                        long curl_timeout;
1354                        curl_multi_timeout(curlm, &curl_timeout);
1355                        if (curl_timeout == 0) {
1356                                continue;
1357                        } else if (curl_timeout == -1) {
1358                                select_timeout.tv_sec  = 0;
1359                                select_timeout.tv_usec = 50000;
1360                        } else {
1361                                select_timeout.tv_sec  =  curl_timeout / 1000;
1362                                select_timeout.tv_usec = (curl_timeout % 1000) * 1000;
1363                        }
1364#else
1365                        select_timeout.tv_sec  = 0;
1366                        select_timeout.tv_usec = 50000;
1367#endif
1368
1369                        max_fd = -1;
1370                        FD_ZERO(&readfds);
1371                        FD_ZERO(&writefds);
1372                        FD_ZERO(&excfds);
1373                        curl_multi_fdset(curlm, &readfds, &writefds, &excfds, &max_fd);
1374
1375                        /*
1376                         * It can happen that curl_multi_timeout returns a pathologically
1377                         * long timeout when curl_multi_fdset returns no file descriptors
1378                         * to read.  See commit message for more details.
1379                         */
1380                        if (max_fd < 0 &&
1381                            (select_timeout.tv_sec > 0 ||
1382                             select_timeout.tv_usec > 50000)) {
1383                                select_timeout.tv_sec  = 0;
1384                                select_timeout.tv_usec = 50000;
1385                        }
1386
1387                        select(max_fd+1, &readfds, &writefds, &excfds, &select_timeout);
1388                }
1389        }
1390#else
1391        while (slot->in_use) {
1392                slot->curl_result = curl_easy_perform(slot->curl);
1393                finish_active_slot(slot);
1394        }
1395#endif
1396}
1397
1398static void release_active_slot(struct active_request_slot *slot)
1399{
1400        closedown_active_slot(slot);
1401        if (slot->curl) {
1402                xmulti_remove_handle(slot);
1403                if (curl_session_count > min_curl_sessions) {
1404                        curl_easy_cleanup(slot->curl);
1405                        slot->curl = NULL;
1406                        curl_session_count--;
1407                }
1408        }
1409#ifdef USE_CURL_MULTI
1410        fill_active_slots();
1411#endif
1412}
1413
1414void finish_all_active_slots(void)
1415{
1416        struct active_request_slot *slot = active_queue_head;
1417
1418        while (slot != NULL)
1419                if (slot->in_use) {
1420                        run_active_slot(slot);
1421                        slot = active_queue_head;
1422                } else {
1423                        slot = slot->next;
1424                }
1425}
1426
1427/* Helpers for modifying and creating URLs */
1428static inline int needs_quote(int ch)
1429{
1430        if (((ch >= 'A') && (ch <= 'Z'))
1431                        || ((ch >= 'a') && (ch <= 'z'))
1432                        || ((ch >= '0') && (ch <= '9'))
1433                        || (ch == '/')
1434                        || (ch == '-')
1435                        || (ch == '.'))
1436                return 0;
1437        return 1;
1438}
1439
1440static char *quote_ref_url(const char *base, const char *ref)
1441{
1442        struct strbuf buf = STRBUF_INIT;
1443        const char *cp;
1444        int ch;
1445
1446        end_url_with_slash(&buf, base);
1447
1448        for (cp = ref; (ch = *cp) != 0; cp++)
1449                if (needs_quote(ch))
1450                        strbuf_addf(&buf, "%%%02x", ch);
1451                else
1452                        strbuf_addch(&buf, *cp);
1453
1454        return strbuf_detach(&buf, NULL);
1455}
1456
1457void append_remote_object_url(struct strbuf *buf, const char *url,
1458                              const char *hex,
1459                              int only_two_digit_prefix)
1460{
1461        end_url_with_slash(buf, url);
1462
1463        strbuf_addf(buf, "objects/%.*s/", 2, hex);
1464        if (!only_two_digit_prefix)
1465                strbuf_addstr(buf, hex + 2);
1466}
1467
1468char *get_remote_object_url(const char *url, const char *hex,
1469                            int only_two_digit_prefix)
1470{
1471        struct strbuf buf = STRBUF_INIT;
1472        append_remote_object_url(&buf, url, hex, only_two_digit_prefix);
1473        return strbuf_detach(&buf, NULL);
1474}
1475
1476static int handle_curl_result(struct slot_results *results)
1477{
1478        /*
1479         * If we see a failing http code with CURLE_OK, we have turned off
1480         * FAILONERROR (to keep the server's custom error response), and should
1481         * translate the code into failure here.
1482         *
1483         * Likewise, if we see a redirect (30x code), that means we turned off
1484         * redirect-following, and we should treat the result as an error.
1485         */
1486        if (results->curl_result == CURLE_OK &&
1487            results->http_code >= 300) {
1488                results->curl_result = CURLE_HTTP_RETURNED_ERROR;
1489                /*
1490                 * Normally curl will already have put the "reason phrase"
1491                 * from the server into curl_errorstr; unfortunately without
1492                 * FAILONERROR it is lost, so we can give only the numeric
1493                 * status code.
1494                 */
1495                xsnprintf(curl_errorstr, sizeof(curl_errorstr),
1496                          "The requested URL returned error: %ld",
1497                          results->http_code);
1498        }
1499
1500        if (results->curl_result == CURLE_OK) {
1501                credential_approve(&http_auth);
1502                if (proxy_auth.password)
1503                        credential_approve(&proxy_auth);
1504                return HTTP_OK;
1505        } else if (missing_target(results))
1506                return HTTP_MISSING_TARGET;
1507        else if (results->http_code == 401) {
1508                if (http_auth.username && http_auth.password) {
1509                        credential_reject(&http_auth);
1510                        return HTTP_NOAUTH;
1511                } else {
1512#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
1513                        http_auth_methods &= ~CURLAUTH_GSSNEGOTIATE;
1514                        if (results->auth_avail) {
1515                                http_auth_methods &= results->auth_avail;
1516                                http_auth_methods_restricted = 1;
1517                        }
1518#endif
1519                        return HTTP_REAUTH;
1520                }
1521        } else {
1522                if (results->http_connectcode == 407)
1523                        credential_reject(&proxy_auth);
1524#if LIBCURL_VERSION_NUM >= 0x070c00
1525                if (!curl_errorstr[0])
1526                        strlcpy(curl_errorstr,
1527                                curl_easy_strerror(results->curl_result),
1528                                sizeof(curl_errorstr));
1529#endif
1530                return HTTP_ERROR;
1531        }
1532}
1533
1534int run_one_slot(struct active_request_slot *slot,
1535                 struct slot_results *results)
1536{
1537        slot->results = results;
1538        if (!start_active_slot(slot)) {
1539                xsnprintf(curl_errorstr, sizeof(curl_errorstr),
1540                          "failed to start HTTP request");
1541                return HTTP_START_FAILED;
1542        }
1543
1544        run_active_slot(slot);
1545        return handle_curl_result(results);
1546}
1547
1548struct curl_slist *http_copy_default_headers(void)
1549{
1550        struct curl_slist *headers = NULL, *h;
1551
1552        for (h = extra_http_headers; h; h = h->next)
1553                headers = curl_slist_append(headers, h->data);
1554
1555        return headers;
1556}
1557
1558static CURLcode curlinfo_strbuf(CURL *curl, CURLINFO info, struct strbuf *buf)
1559{
1560        char *ptr;
1561        CURLcode ret;
1562
1563        strbuf_reset(buf);
1564        ret = curl_easy_getinfo(curl, info, &ptr);
1565        if (!ret && ptr)
1566                strbuf_addstr(buf, ptr);
1567        return ret;
1568}
1569
1570/*
1571 * Check for and extract a content-type parameter. "raw"
1572 * should be positioned at the start of the potential
1573 * parameter, with any whitespace already removed.
1574 *
1575 * "name" is the name of the parameter. The value is appended
1576 * to "out".
1577 */
1578static int extract_param(const char *raw, const char *name,
1579                         struct strbuf *out)
1580{
1581        size_t len = strlen(name);
1582
1583        if (strncasecmp(raw, name, len))
1584                return -1;
1585        raw += len;
1586
1587        if (*raw != '=')
1588                return -1;
1589        raw++;
1590
1591        while (*raw && !isspace(*raw) && *raw != ';')
1592                strbuf_addch(out, *raw++);
1593        return 0;
1594}
1595
1596/*
1597 * Extract a normalized version of the content type, with any
1598 * spaces suppressed, all letters lowercased, and no trailing ";"
1599 * or parameters.
1600 *
1601 * Note that we will silently remove even invalid whitespace. For
1602 * example, "text / plain" is specifically forbidden by RFC 2616,
1603 * but "text/plain" is the only reasonable output, and this keeps
1604 * our code simple.
1605 *
1606 * If the "charset" argument is not NULL, store the value of any
1607 * charset parameter there.
1608 *
1609 * Example:
1610 *   "TEXT/PLAIN; charset=utf-8" -> "text/plain", "utf-8"
1611 *   "text / plain" -> "text/plain"
1612 */
1613static void extract_content_type(struct strbuf *raw, struct strbuf *type,
1614                                 struct strbuf *charset)
1615{
1616        const char *p;
1617
1618        strbuf_reset(type);
1619        strbuf_grow(type, raw->len);
1620        for (p = raw->buf; *p; p++) {
1621                if (isspace(*p))
1622                        continue;
1623                if (*p == ';') {
1624                        p++;
1625                        break;
1626                }
1627                strbuf_addch(type, tolower(*p));
1628        }
1629
1630        if (!charset)
1631                return;
1632
1633        strbuf_reset(charset);
1634        while (*p) {
1635                while (isspace(*p) || *p == ';')
1636                        p++;
1637                if (!extract_param(p, "charset", charset))
1638                        return;
1639                while (*p && !isspace(*p))
1640                        p++;
1641        }
1642
1643        if (!charset->len && starts_with(type->buf, "text/"))
1644                strbuf_addstr(charset, "ISO-8859-1");
1645}
1646
1647static void write_accept_language(struct strbuf *buf)
1648{
1649        /*
1650         * MAX_DECIMAL_PLACES must not be larger than 3. If it is larger than
1651         * that, q-value will be smaller than 0.001, the minimum q-value the
1652         * HTTP specification allows. See
1653         * http://tools.ietf.org/html/rfc7231#section-5.3.1 for q-value.
1654         */
1655        const int MAX_DECIMAL_PLACES = 3;
1656        const int MAX_LANGUAGE_TAGS = 1000;
1657        const int MAX_ACCEPT_LANGUAGE_HEADER_SIZE = 4000;
1658        char **language_tags = NULL;
1659        int num_langs = 0;
1660        const char *s = get_preferred_languages();
1661        int i;
1662        struct strbuf tag = STRBUF_INIT;
1663
1664        /* Don't add Accept-Language header if no language is preferred. */
1665        if (!s)
1666                return;
1667
1668        /*
1669         * Split the colon-separated string of preferred languages into
1670         * language_tags array.
1671         */
1672        do {
1673                /* collect language tag */
1674                for (; *s && (isalnum(*s) || *s == '_'); s++)
1675                        strbuf_addch(&tag, *s == '_' ? '-' : *s);
1676
1677                /* skip .codeset, @modifier and any other unnecessary parts */
1678                while (*s && *s != ':')
1679                        s++;
1680
1681                if (tag.len) {
1682                        num_langs++;
1683                        REALLOC_ARRAY(language_tags, num_langs);
1684                        language_tags[num_langs - 1] = strbuf_detach(&tag, NULL);
1685                        if (num_langs >= MAX_LANGUAGE_TAGS - 1) /* -1 for '*' */
1686                                break;
1687                }
1688        } while (*s++);
1689
1690        /* write Accept-Language header into buf */
1691        if (num_langs) {
1692                int last_buf_len = 0;
1693                int max_q;
1694                int decimal_places;
1695                char q_format[32];
1696
1697                /* add '*' */
1698                REALLOC_ARRAY(language_tags, num_langs + 1);
1699                language_tags[num_langs++] = "*"; /* it's OK; this won't be freed */
1700
1701                /* compute decimal_places */
1702                for (max_q = 1, decimal_places = 0;
1703                     max_q < num_langs && decimal_places <= MAX_DECIMAL_PLACES;
1704                     decimal_places++, max_q *= 10)
1705                        ;
1706
1707                xsnprintf(q_format, sizeof(q_format), ";q=0.%%0%dd", decimal_places);
1708
1709                strbuf_addstr(buf, "Accept-Language: ");
1710
1711                for (i = 0; i < num_langs; i++) {
1712                        if (i > 0)
1713                                strbuf_addstr(buf, ", ");
1714
1715                        strbuf_addstr(buf, language_tags[i]);
1716
1717                        if (i > 0)
1718                                strbuf_addf(buf, q_format, max_q - i);
1719
1720                        if (buf->len > MAX_ACCEPT_LANGUAGE_HEADER_SIZE) {
1721                                strbuf_remove(buf, last_buf_len, buf->len - last_buf_len);
1722                                break;
1723                        }
1724
1725                        last_buf_len = buf->len;
1726                }
1727        }
1728
1729        /* free language tags -- last one is a static '*' */
1730        for (i = 0; i < num_langs - 1; i++)
1731                free(language_tags[i]);
1732        free(language_tags);
1733}
1734
1735/*
1736 * Get an Accept-Language header which indicates user's preferred languages.
1737 *
1738 * Examples:
1739 *   LANGUAGE= -> ""
1740 *   LANGUAGE=ko:en -> "Accept-Language: ko, en; q=0.9, *; q=0.1"
1741 *   LANGUAGE=ko_KR.UTF-8:sr@latin -> "Accept-Language: ko-KR, sr; q=0.9, *; q=0.1"
1742 *   LANGUAGE=ko LANG=en_US.UTF-8 -> "Accept-Language: ko, *; q=0.1"
1743 *   LANGUAGE= LANG=en_US.UTF-8 -> "Accept-Language: en-US, *; q=0.1"
1744 *   LANGUAGE= LANG=C -> ""
1745 */
1746static const char *get_accept_language(void)
1747{
1748        if (!cached_accept_language) {
1749                struct strbuf buf = STRBUF_INIT;
1750                write_accept_language(&buf);
1751                if (buf.len > 0)
1752                        cached_accept_language = strbuf_detach(&buf, NULL);
1753        }
1754
1755        return cached_accept_language;
1756}
1757
1758static void http_opt_request_remainder(CURL *curl, off_t pos)
1759{
1760        char buf[128];
1761        xsnprintf(buf, sizeof(buf), "%"PRIuMAX"-", (uintmax_t)pos);
1762        curl_easy_setopt(curl, CURLOPT_RANGE, buf);
1763}
1764
1765/* http_request() targets */
1766#define HTTP_REQUEST_STRBUF     0
1767#define HTTP_REQUEST_FILE       1
1768
1769static int http_request(const char *url,
1770                        void *result, int target,
1771                        const struct http_get_options *options)
1772{
1773        struct active_request_slot *slot;
1774        struct slot_results results;
1775        struct curl_slist *headers = http_copy_default_headers();
1776        struct strbuf buf = STRBUF_INIT;
1777        const char *accept_language;
1778        int ret;
1779
1780        slot = get_active_slot();
1781        curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
1782
1783        if (result == NULL) {
1784                curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1);
1785        } else {
1786                curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
1787                curl_easy_setopt(slot->curl, CURLOPT_FILE, result);
1788
1789                if (target == HTTP_REQUEST_FILE) {
1790                        off_t posn = ftello(result);
1791                        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
1792                                         fwrite);
1793                        if (posn > 0)
1794                                http_opt_request_remainder(slot->curl, posn);
1795                } else
1796                        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
1797                                         fwrite_buffer);
1798        }
1799
1800        accept_language = get_accept_language();
1801
1802        if (accept_language)
1803                headers = curl_slist_append(headers, accept_language);
1804
1805        strbuf_addstr(&buf, "Pragma:");
1806        if (options && options->no_cache)
1807                strbuf_addstr(&buf, " no-cache");
1808        if (options && options->keep_error)
1809                curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0);
1810        if (options && options->initial_request &&
1811            http_follow_config == HTTP_FOLLOW_INITIAL)
1812                curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 1);
1813
1814        headers = curl_slist_append(headers, buf.buf);
1815
1816        /* Add additional headers here */
1817        if (options && options->extra_headers) {
1818                const struct string_list_item *item;
1819                for_each_string_list_item(item, options->extra_headers) {
1820                        headers = curl_slist_append(headers, item->string);
1821                }
1822        }
1823
1824        curl_easy_setopt(slot->curl, CURLOPT_URL, url);
1825        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
1826        curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "");
1827
1828        ret = run_one_slot(slot, &results);
1829
1830        if (options && options->content_type) {
1831                struct strbuf raw = STRBUF_INIT;
1832                curlinfo_strbuf(slot->curl, CURLINFO_CONTENT_TYPE, &raw);
1833                extract_content_type(&raw, options->content_type,
1834                                     options->charset);
1835                strbuf_release(&raw);
1836        }
1837
1838        if (options && options->effective_url)
1839                curlinfo_strbuf(slot->curl, CURLINFO_EFFECTIVE_URL,
1840                                options->effective_url);
1841
1842        curl_slist_free_all(headers);
1843        strbuf_release(&buf);
1844
1845        return ret;
1846}
1847
1848/*
1849 * Update the "base" url to a more appropriate value, as deduced by
1850 * redirects seen when requesting a URL starting with "url".
1851 *
1852 * The "asked" parameter is a URL that we asked curl to access, and must begin
1853 * with "base".
1854 *
1855 * The "got" parameter is the URL that curl reported to us as where we ended
1856 * up.
1857 *
1858 * Returns 1 if we updated the base url, 0 otherwise.
1859 *
1860 * Our basic strategy is to compare "base" and "asked" to find the bits
1861 * specific to our request. We then strip those bits off of "got" to yield the
1862 * new base. So for example, if our base is "http://example.com/foo.git",
1863 * and we ask for "http://example.com/foo.git/info/refs", we might end up
1864 * with "https://other.example.com/foo.git/info/refs". We would want the
1865 * new URL to become "https://other.example.com/foo.git".
1866 *
1867 * Note that this assumes a sane redirect scheme. It's entirely possible
1868 * in the example above to end up at a URL that does not even end in
1869 * "info/refs".  In such a case we die. There's not much we can do, such a
1870 * scheme is unlikely to represent a real git repository, and failing to
1871 * rewrite the base opens options for malicious redirects to do funny things.
1872 */
1873static int update_url_from_redirect(struct strbuf *base,
1874                                    const char *asked,
1875                                    const struct strbuf *got)
1876{
1877        const char *tail;
1878        size_t new_len;
1879
1880        if (!strcmp(asked, got->buf))
1881                return 0;
1882
1883        if (!skip_prefix(asked, base->buf, &tail))
1884                BUG("update_url_from_redirect: %s is not a superset of %s",
1885                    asked, base->buf);
1886
1887        new_len = got->len;
1888        if (!strip_suffix_mem(got->buf, &new_len, tail))
1889                die(_("unable to update url base from redirection:\n"
1890                      "  asked for: %s\n"
1891                      "   redirect: %s"),
1892                    asked, got->buf);
1893
1894        strbuf_reset(base);
1895        strbuf_add(base, got->buf, new_len);
1896
1897        return 1;
1898}
1899
1900static int http_request_reauth(const char *url,
1901                               void *result, int target,
1902                               struct http_get_options *options)
1903{
1904        int ret = http_request(url, result, target, options);
1905
1906        if (ret != HTTP_OK && ret != HTTP_REAUTH)
1907                return ret;
1908
1909        if (options && options->effective_url && options->base_url) {
1910                if (update_url_from_redirect(options->base_url,
1911                                             url, options->effective_url)) {
1912                        credential_from_url(&http_auth, options->base_url->buf);
1913                        url = options->effective_url->buf;
1914                }
1915        }
1916
1917        if (ret != HTTP_REAUTH)
1918                return ret;
1919
1920        /*
1921         * If we are using KEEP_ERROR, the previous request may have
1922         * put cruft into our output stream; we should clear it out before
1923         * making our next request. We only know how to do this for
1924         * the strbuf case, but that is enough to satisfy current callers.
1925         */
1926        if (options && options->keep_error) {
1927                switch (target) {
1928                case HTTP_REQUEST_STRBUF:
1929                        strbuf_reset(result);
1930                        break;
1931                default:
1932                        BUG("HTTP_KEEP_ERROR is only supported with strbufs");
1933                }
1934        }
1935
1936        credential_fill(&http_auth);
1937
1938        return http_request(url, result, target, options);
1939}
1940
1941int http_get_strbuf(const char *url,
1942                    struct strbuf *result,
1943                    struct http_get_options *options)
1944{
1945        return http_request_reauth(url, result, HTTP_REQUEST_STRBUF, options);
1946}
1947
1948/*
1949 * Downloads a URL and stores the result in the given file.
1950 *
1951 * If a previous interrupted download is detected (i.e. a previous temporary
1952 * file is still around) the download is resumed.
1953 */
1954static int http_get_file(const char *url, const char *filename,
1955                         struct http_get_options *options)
1956{
1957        int ret;
1958        struct strbuf tmpfile = STRBUF_INIT;
1959        FILE *result;
1960
1961        strbuf_addf(&tmpfile, "%s.temp", filename);
1962        result = fopen(tmpfile.buf, "a");
1963        if (!result) {
1964                error("Unable to open local file %s", tmpfile.buf);
1965                ret = HTTP_ERROR;
1966                goto cleanup;
1967        }
1968
1969        ret = http_request_reauth(url, result, HTTP_REQUEST_FILE, options);
1970        fclose(result);
1971
1972        if (ret == HTTP_OK && finalize_object_file(tmpfile.buf, filename))
1973                ret = HTTP_ERROR;
1974cleanup:
1975        strbuf_release(&tmpfile);
1976        return ret;
1977}
1978
1979int http_fetch_ref(const char *base, struct ref *ref)
1980{
1981        struct http_get_options options = {0};
1982        char *url;
1983        struct strbuf buffer = STRBUF_INIT;
1984        int ret = -1;
1985
1986        options.no_cache = 1;
1987
1988        url = quote_ref_url(base, ref->name);
1989        if (http_get_strbuf(url, &buffer, &options) == HTTP_OK) {
1990                strbuf_rtrim(&buffer);
1991                if (buffer.len == 40)
1992                        ret = get_oid_hex(buffer.buf, &ref->old_oid);
1993                else if (starts_with(buffer.buf, "ref: ")) {
1994                        ref->symref = xstrdup(buffer.buf + 5);
1995                        ret = 0;
1996                }
1997        }
1998
1999        strbuf_release(&buffer);
2000        free(url);
2001        return ret;
2002}
2003
2004/* Helpers for fetching packs */
2005static char *fetch_pack_index(unsigned char *sha1, const char *base_url)
2006{
2007        char *url, *tmp;
2008        struct strbuf buf = STRBUF_INIT;
2009
2010        if (http_is_verbose)
2011                fprintf(stderr, "Getting index for pack %s\n", sha1_to_hex(sha1));
2012
2013        end_url_with_slash(&buf, base_url);
2014        strbuf_addf(&buf, "objects/pack/pack-%s.idx", sha1_to_hex(sha1));
2015        url = strbuf_detach(&buf, NULL);
2016
2017        strbuf_addf(&buf, "%s.temp", sha1_pack_index_name(sha1));
2018        tmp = strbuf_detach(&buf, NULL);
2019
2020        if (http_get_file(url, tmp, NULL) != HTTP_OK) {
2021                error("Unable to get pack index %s", url);
2022                FREE_AND_NULL(tmp);
2023        }
2024
2025        free(url);
2026        return tmp;
2027}
2028
2029static int fetch_and_setup_pack_index(struct packed_git **packs_head,
2030        unsigned char *sha1, const char *base_url)
2031{
2032        struct packed_git *new_pack;
2033        char *tmp_idx = NULL;
2034        int ret;
2035
2036        if (has_pack_index(sha1)) {
2037                new_pack = parse_pack_index(sha1, sha1_pack_index_name(sha1));
2038                if (!new_pack)
2039                        return -1; /* parse_pack_index() already issued error message */
2040                goto add_pack;
2041        }
2042
2043        tmp_idx = fetch_pack_index(sha1, base_url);
2044        if (!tmp_idx)
2045                return -1;
2046
2047        new_pack = parse_pack_index(sha1, tmp_idx);
2048        if (!new_pack) {
2049                unlink(tmp_idx);
2050                free(tmp_idx);
2051
2052                return -1; /* parse_pack_index() already issued error message */
2053        }
2054
2055        ret = verify_pack_index(new_pack);
2056        if (!ret) {
2057                close_pack_index(new_pack);
2058                ret = finalize_object_file(tmp_idx, sha1_pack_index_name(sha1));
2059        }
2060        free(tmp_idx);
2061        if (ret)
2062                return -1;
2063
2064add_pack:
2065        new_pack->next = *packs_head;
2066        *packs_head = new_pack;
2067        return 0;
2068}
2069
2070int http_get_info_packs(const char *base_url, struct packed_git **packs_head)
2071{
2072        struct http_get_options options = {0};
2073        int ret = 0, i = 0;
2074        char *url, *data;
2075        struct strbuf buf = STRBUF_INIT;
2076        unsigned char hash[GIT_MAX_RAWSZ];
2077        const unsigned hexsz = the_hash_algo->hexsz;
2078
2079        end_url_with_slash(&buf, base_url);
2080        strbuf_addstr(&buf, "objects/info/packs");
2081        url = strbuf_detach(&buf, NULL);
2082
2083        options.no_cache = 1;
2084        ret = http_get_strbuf(url, &buf, &options);
2085        if (ret != HTTP_OK)
2086                goto cleanup;
2087
2088        data = buf.buf;
2089        while (i < buf.len) {
2090                switch (data[i]) {
2091                case 'P':
2092                        i++;
2093                        if (i + hexsz + 12 <= buf.len &&
2094                            starts_with(data + i, " pack-") &&
2095                            starts_with(data + i + hexsz + 6, ".pack\n")) {
2096                                get_sha1_hex(data + i + 6, hash);
2097                                fetch_and_setup_pack_index(packs_head, hash,
2098                                                      base_url);
2099                                i += hexsz + 11;
2100                                break;
2101                        }
2102                default:
2103                        while (i < buf.len && data[i] != '\n')
2104                                i++;
2105                }
2106                i++;
2107        }
2108
2109cleanup:
2110        free(url);
2111        return ret;
2112}
2113
2114void release_http_pack_request(struct http_pack_request *preq)
2115{
2116        if (preq->packfile != NULL) {
2117                fclose(preq->packfile);
2118                preq->packfile = NULL;
2119        }
2120        preq->slot = NULL;
2121        strbuf_release(&preq->tmpfile);
2122        free(preq->url);
2123        free(preq);
2124}
2125
2126int finish_http_pack_request(struct http_pack_request *preq)
2127{
2128        struct packed_git **lst;
2129        struct packed_git *p = preq->target;
2130        char *tmp_idx;
2131        size_t len;
2132        struct child_process ip = CHILD_PROCESS_INIT;
2133
2134        close_pack_index(p);
2135
2136        fclose(preq->packfile);
2137        preq->packfile = NULL;
2138
2139        lst = preq->lst;
2140        while (*lst != p)
2141                lst = &((*lst)->next);
2142        *lst = (*lst)->next;
2143
2144        if (!strip_suffix(preq->tmpfile.buf, ".pack.temp", &len))
2145                BUG("pack tmpfile does not end in .pack.temp?");
2146        tmp_idx = xstrfmt("%.*s.idx.temp", (int)len, preq->tmpfile.buf);
2147
2148        argv_array_push(&ip.args, "index-pack");
2149        argv_array_pushl(&ip.args, "-o", tmp_idx, NULL);
2150        argv_array_push(&ip.args, preq->tmpfile.buf);
2151        ip.git_cmd = 1;
2152        ip.no_stdin = 1;
2153        ip.no_stdout = 1;
2154
2155        if (run_command(&ip)) {
2156                unlink(preq->tmpfile.buf);
2157                unlink(tmp_idx);
2158                free(tmp_idx);
2159                return -1;
2160        }
2161
2162        unlink(sha1_pack_index_name(p->sha1));
2163
2164        if (finalize_object_file(preq->tmpfile.buf, sha1_pack_name(p->sha1))
2165         || finalize_object_file(tmp_idx, sha1_pack_index_name(p->sha1))) {
2166                free(tmp_idx);
2167                return -1;
2168        }
2169
2170        install_packed_git(the_repository, p);
2171        free(tmp_idx);
2172        return 0;
2173}
2174
2175struct http_pack_request *new_http_pack_request(
2176        struct packed_git *target, const char *base_url)
2177{
2178        off_t prev_posn = 0;
2179        struct strbuf buf = STRBUF_INIT;
2180        struct http_pack_request *preq;
2181
2182        preq = xcalloc(1, sizeof(*preq));
2183        strbuf_init(&preq->tmpfile, 0);
2184        preq->target = target;
2185
2186        end_url_with_slash(&buf, base_url);
2187        strbuf_addf(&buf, "objects/pack/pack-%s.pack",
2188                sha1_to_hex(target->sha1));
2189        preq->url = strbuf_detach(&buf, NULL);
2190
2191        strbuf_addf(&preq->tmpfile, "%s.temp", sha1_pack_name(target->sha1));
2192        preq->packfile = fopen(preq->tmpfile.buf, "a");
2193        if (!preq->packfile) {
2194                error("Unable to open local file %s for pack",
2195                      preq->tmpfile.buf);
2196                goto abort;
2197        }
2198
2199        preq->slot = get_active_slot();
2200        curl_easy_setopt(preq->slot->curl, CURLOPT_FILE, preq->packfile);
2201        curl_easy_setopt(preq->slot->curl, CURLOPT_WRITEFUNCTION, fwrite);
2202        curl_easy_setopt(preq->slot->curl, CURLOPT_URL, preq->url);
2203        curl_easy_setopt(preq->slot->curl, CURLOPT_HTTPHEADER,
2204                no_pragma_header);
2205
2206        /*
2207         * If there is data present from a previous transfer attempt,
2208         * resume where it left off
2209         */
2210        prev_posn = ftello(preq->packfile);
2211        if (prev_posn>0) {
2212                if (http_is_verbose)
2213                        fprintf(stderr,
2214                                "Resuming fetch of pack %s at byte %"PRIuMAX"\n",
2215                                sha1_to_hex(target->sha1), (uintmax_t)prev_posn);
2216                http_opt_request_remainder(preq->slot->curl, prev_posn);
2217        }
2218
2219        return preq;
2220
2221abort:
2222        strbuf_release(&preq->tmpfile);
2223        free(preq->url);
2224        free(preq);
2225        return NULL;
2226}
2227
2228/* Helpers for fetching objects (loose) */
2229static size_t fwrite_sha1_file(char *ptr, size_t eltsize, size_t nmemb,
2230                               void *data)
2231{
2232        unsigned char expn[4096];
2233        size_t size = eltsize * nmemb;
2234        int posn = 0;
2235        struct http_object_request *freq = data;
2236        struct active_request_slot *slot = freq->slot;
2237
2238        if (slot) {
2239                CURLcode c = curl_easy_getinfo(slot->curl, CURLINFO_HTTP_CODE,
2240                                                &slot->http_code);
2241                if (c != CURLE_OK)
2242                        BUG("curl_easy_getinfo for HTTP code failed: %s",
2243                                curl_easy_strerror(c));
2244                if (slot->http_code >= 300)
2245                        return size;
2246        }
2247
2248        do {
2249                ssize_t retval = xwrite(freq->localfile,
2250                                        (char *) ptr + posn, size - posn);
2251                if (retval < 0)
2252                        return posn;
2253                posn += retval;
2254        } while (posn < size);
2255
2256        freq->stream.avail_in = size;
2257        freq->stream.next_in = (void *)ptr;
2258        do {
2259                freq->stream.next_out = expn;
2260                freq->stream.avail_out = sizeof(expn);
2261                freq->zret = git_inflate(&freq->stream, Z_SYNC_FLUSH);
2262                git_SHA1_Update(&freq->c, expn,
2263                                sizeof(expn) - freq->stream.avail_out);
2264        } while (freq->stream.avail_in && freq->zret == Z_OK);
2265        return size;
2266}
2267
2268struct http_object_request *new_http_object_request(const char *base_url,
2269        unsigned char *sha1)
2270{
2271        char *hex = sha1_to_hex(sha1);
2272        struct strbuf filename = STRBUF_INIT;
2273        struct strbuf prevfile = STRBUF_INIT;
2274        int prevlocal;
2275        char prev_buf[PREV_BUF_SIZE];
2276        ssize_t prev_read = 0;
2277        off_t prev_posn = 0;
2278        struct http_object_request *freq;
2279
2280        freq = xcalloc(1, sizeof(*freq));
2281        strbuf_init(&freq->tmpfile, 0);
2282        hashcpy(freq->sha1, sha1);
2283        freq->localfile = -1;
2284
2285        sha1_file_name(the_repository, &filename, sha1);
2286        strbuf_addf(&freq->tmpfile, "%s.temp", filename.buf);
2287
2288        strbuf_addf(&prevfile, "%s.prev", filename.buf);
2289        unlink_or_warn(prevfile.buf);
2290        rename(freq->tmpfile.buf, prevfile.buf);
2291        unlink_or_warn(freq->tmpfile.buf);
2292        strbuf_release(&filename);
2293
2294        if (freq->localfile != -1)
2295                error("fd leakage in start: %d", freq->localfile);
2296        freq->localfile = open(freq->tmpfile.buf,
2297                               O_WRONLY | O_CREAT | O_EXCL, 0666);
2298        /*
2299         * This could have failed due to the "lazy directory creation";
2300         * try to mkdir the last path component.
2301         */
2302        if (freq->localfile < 0 && errno == ENOENT) {
2303                char *dir = strrchr(freq->tmpfile.buf, '/');
2304                if (dir) {
2305                        *dir = 0;
2306                        mkdir(freq->tmpfile.buf, 0777);
2307                        *dir = '/';
2308                }
2309                freq->localfile = open(freq->tmpfile.buf,
2310                                       O_WRONLY | O_CREAT | O_EXCL, 0666);
2311        }
2312
2313        if (freq->localfile < 0) {
2314                error_errno("Couldn't create temporary file %s",
2315                            freq->tmpfile.buf);
2316                goto abort;
2317        }
2318
2319        git_inflate_init(&freq->stream);
2320
2321        git_SHA1_Init(&freq->c);
2322
2323        freq->url = get_remote_object_url(base_url, hex, 0);
2324
2325        /*
2326         * If a previous temp file is present, process what was already
2327         * fetched.
2328         */
2329        prevlocal = open(prevfile.buf, O_RDONLY);
2330        if (prevlocal != -1) {
2331                do {
2332                        prev_read = xread(prevlocal, prev_buf, PREV_BUF_SIZE);
2333                        if (prev_read>0) {
2334                                if (fwrite_sha1_file(prev_buf,
2335                                                     1,
2336                                                     prev_read,
2337                                                     freq) == prev_read) {
2338                                        prev_posn += prev_read;
2339                                } else {
2340                                        prev_read = -1;
2341                                }
2342                        }
2343                } while (prev_read > 0);
2344                close(prevlocal);
2345        }
2346        unlink_or_warn(prevfile.buf);
2347        strbuf_release(&prevfile);
2348
2349        /*
2350         * Reset inflate/SHA1 if there was an error reading the previous temp
2351         * file; also rewind to the beginning of the local file.
2352         */
2353        if (prev_read == -1) {
2354                memset(&freq->stream, 0, sizeof(freq->stream));
2355                git_inflate_init(&freq->stream);
2356                git_SHA1_Init(&freq->c);
2357                if (prev_posn>0) {
2358                        prev_posn = 0;
2359                        lseek(freq->localfile, 0, SEEK_SET);
2360                        if (ftruncate(freq->localfile, 0) < 0) {
2361                                error_errno("Couldn't truncate temporary file %s",
2362                                            freq->tmpfile.buf);
2363                                goto abort;
2364                        }
2365                }
2366        }
2367
2368        freq->slot = get_active_slot();
2369
2370        curl_easy_setopt(freq->slot->curl, CURLOPT_FILE, freq);
2371        curl_easy_setopt(freq->slot->curl, CURLOPT_FAILONERROR, 0);
2372        curl_easy_setopt(freq->slot->curl, CURLOPT_WRITEFUNCTION, fwrite_sha1_file);
2373        curl_easy_setopt(freq->slot->curl, CURLOPT_ERRORBUFFER, freq->errorstr);
2374        curl_easy_setopt(freq->slot->curl, CURLOPT_URL, freq->url);
2375        curl_easy_setopt(freq->slot->curl, CURLOPT_HTTPHEADER, no_pragma_header);
2376
2377        /*
2378         * If we have successfully processed data from a previous fetch
2379         * attempt, only fetch the data we don't already have.
2380         */
2381        if (prev_posn>0) {
2382                if (http_is_verbose)
2383                        fprintf(stderr,
2384                                "Resuming fetch of object %s at byte %"PRIuMAX"\n",
2385                                hex, (uintmax_t)prev_posn);
2386                http_opt_request_remainder(freq->slot->curl, prev_posn);
2387        }
2388
2389        return freq;
2390
2391abort:
2392        strbuf_release(&prevfile);
2393        free(freq->url);
2394        free(freq);
2395        return NULL;
2396}
2397
2398void process_http_object_request(struct http_object_request *freq)
2399{
2400        if (freq->slot == NULL)
2401                return;
2402        freq->curl_result = freq->slot->curl_result;
2403        freq->http_code = freq->slot->http_code;
2404        freq->slot = NULL;
2405}
2406
2407int finish_http_object_request(struct http_object_request *freq)
2408{
2409        struct stat st;
2410        struct strbuf filename = STRBUF_INIT;
2411
2412        close(freq->localfile);
2413        freq->localfile = -1;
2414
2415        process_http_object_request(freq);
2416
2417        if (freq->http_code == 416) {
2418                warning("requested range invalid; we may already have all the data.");
2419        } else if (freq->curl_result != CURLE_OK) {
2420                if (stat(freq->tmpfile.buf, &st) == 0)
2421                        if (st.st_size == 0)
2422                                unlink_or_warn(freq->tmpfile.buf);
2423                return -1;
2424        }
2425
2426        git_inflate_end(&freq->stream);
2427        git_SHA1_Final(freq->real_sha1, &freq->c);
2428        if (freq->zret != Z_STREAM_END) {
2429                unlink_or_warn(freq->tmpfile.buf);
2430                return -1;
2431        }
2432        if (hashcmp(freq->sha1, freq->real_sha1)) {
2433                unlink_or_warn(freq->tmpfile.buf);
2434                return -1;
2435        }
2436        sha1_file_name(the_repository, &filename, freq->sha1);
2437        freq->rename = finalize_object_file(freq->tmpfile.buf, filename.buf);
2438        strbuf_release(&filename);
2439
2440        return freq->rename;
2441}
2442
2443void abort_http_object_request(struct http_object_request *freq)
2444{
2445        unlink_or_warn(freq->tmpfile.buf);
2446
2447        release_http_object_request(freq);
2448}
2449
2450void release_http_object_request(struct http_object_request *freq)
2451{
2452        if (freq->localfile != -1) {
2453                close(freq->localfile);
2454                freq->localfile = -1;
2455        }
2456        FREE_AND_NULL(freq->url);
2457        if (freq->slot != NULL) {
2458                freq->slot->callback_func = NULL;
2459                freq->slot->callback_data = NULL;
2460                release_active_slot(freq->slot);
2461                freq->slot = NULL;
2462        }
2463        strbuf_release(&freq->tmpfile);
2464}