From: Junio C Hamano Date: Wed, 6 Jul 2016 20:38:06 +0000 (-0700) Subject: Merge branch 'ep/http-curl-trace' X-Git-Tag: v2.10.0-rc0~169 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/2f84df2ca0f7a5174d2eb5f4ee52324ce8f807b9?ds=inline;hp=-c Merge branch 'ep/http-curl-trace' HTTP transport gained an option to produce more detailed debugging trace. * ep/http-curl-trace: imap-send.c: introduce the GIT_TRACE_CURL enviroment variable http.c: implement the GIT_TRACE_CURL environment variable --- 2f84df2ca0f7a5174d2eb5f4ee52324ce8f807b9 diff --combined Documentation/git.txt index b0611eaab4,958db0fc65..ca611c9f86 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@@ -43,18 -43,10 +43,18 @@@ unreleased) version of Git, that is ava branch of the `git.git` repository. Documentation for older releases are available here: -* link:v2.8.1/git.html[documentation for release 2.8.1] +* link:v2.9.0/git.html[documentation for release 2.9] * release notes for - link:RelNotes/2.8.1.txt[2.8.1]. + link:RelNotes/2.9.0.txt[2.9]. + +* link:v2.8.4/git.html[documentation for release 2.8.4] + +* release notes for + link:RelNotes/2.8.4.txt[2.8.4], + link:RelNotes/2.8.3.txt[2.8.3], + link:RelNotes/2.8.2.txt[2.8.2], + link:RelNotes/2.8.1.txt[2.8.1], link:RelNotes/2.8.0.txt[2.8]. * link:v2.7.3/git.html[documentation for release 2.7.3] @@@ -577,7 -569,7 +577,7 @@@ foo.bar= ...`) sets `foo.bar` to the em --git-dir=:: Set the path to the repository. This can also be controlled by - setting the GIT_DIR environment variable. It can be an absolute + setting the `GIT_DIR` environment variable. It can be an absolute path or relative path to current working directory. --work-tree=:: @@@ -827,46 -819,46 +827,46 @@@ These environment variables apply to 'a is worth noting that they may be used/overridden by SCMS sitting above Git so take care if using a foreign front-end. -'GIT_INDEX_FILE':: +`GIT_INDEX_FILE`:: This environment allows the specification of an alternate index file. If not specified, the default of `$GIT_DIR/index` is used. -'GIT_INDEX_VERSION':: +`GIT_INDEX_VERSION`:: This environment variable allows the specification of an index version for new repositories. It won't affect existing index files. By default index file version 2 or 3 is used. See linkgit:git-update-index[1] for more information. -'GIT_OBJECT_DIRECTORY':: +`GIT_OBJECT_DIRECTORY`:: If the object storage directory is specified via this environment variable then the sha1 directories are created underneath - otherwise the default `$GIT_DIR/objects` directory is used. -'GIT_ALTERNATE_OBJECT_DIRECTORIES':: +`GIT_ALTERNATE_OBJECT_DIRECTORIES`:: Due to the immutable nature of Git objects, old objects can be archived into shared, read-only directories. This variable specifies a ":" separated (on Windows ";" separated) list of Git object directories which can be used to search for Git objects. New objects will not be written to these directories. -'GIT_DIR':: - If the 'GIT_DIR' environment variable is set then it +`GIT_DIR`:: + If the `GIT_DIR` environment variable is set then it specifies a path to use instead of the default `.git` for the base of the repository. The '--git-dir' command-line option also sets this value. -'GIT_WORK_TREE':: +`GIT_WORK_TREE`:: Set the path to the root of the working tree. This can also be controlled by the '--work-tree' command-line option and the core.worktree configuration variable. -'GIT_NAMESPACE':: +`GIT_NAMESPACE`:: Set the Git namespace; see linkgit:gitnamespaces[7] for details. The '--namespace' command-line option also sets this value. -'GIT_CEILING_DIRECTORIES':: +`GIT_CEILING_DIRECTORIES`:: This should be a colon-separated list of absolute paths. If set, it is a list of directories that Git should not chdir up into while looking for a repository directory (useful for @@@ -879,19 -871,19 +879,19 @@@ can add an empty entry to the list to tell Git that the subsequent entries are not symlinks and needn't be resolved; e.g., - 'GIT_CEILING_DIRECTORIES=/maybe/symlink::/very/slow/non/symlink'. + `GIT_CEILING_DIRECTORIES=/maybe/symlink::/very/slow/non/symlink`. -'GIT_DISCOVERY_ACROSS_FILESYSTEM':: +`GIT_DISCOVERY_ACROSS_FILESYSTEM`:: When run in a directory that does not have ".git" repository directory, Git tries to find such a directory in the parent directories to find the top of the working tree, but by default it does not cross filesystem boundaries. This environment variable can be set to true to tell Git not to stop at filesystem - boundaries. Like 'GIT_CEILING_DIRECTORIES', this will not affect - an explicit repository directory set via 'GIT_DIR' or on the + boundaries. Like `GIT_CEILING_DIRECTORIES`, this will not affect + an explicit repository directory set via `GIT_DIR` or on the command line. -'GIT_COMMON_DIR':: +`GIT_COMMON_DIR`:: If this variable is set to a path, non-worktree files that are normally in $GIT_DIR will be taken from this path instead. Worktree-specific files such as HEAD or index are @@@ -902,28 -894,28 +902,28 @@@ Git Commits ~~~~~~~~~~~ -'GIT_AUTHOR_NAME':: -'GIT_AUTHOR_EMAIL':: -'GIT_AUTHOR_DATE':: -'GIT_COMMITTER_NAME':: -'GIT_COMMITTER_EMAIL':: -'GIT_COMMITTER_DATE':: +`GIT_AUTHOR_NAME`:: +`GIT_AUTHOR_EMAIL`:: +`GIT_AUTHOR_DATE`:: +`GIT_COMMITTER_NAME`:: +`GIT_COMMITTER_EMAIL`:: +`GIT_COMMITTER_DATE`:: 'EMAIL':: see linkgit:git-commit-tree[1] Git Diffs ~~~~~~~~~ -'GIT_DIFF_OPTS':: +`GIT_DIFF_OPTS`:: Only valid setting is "--unified=??" or "-u??" to set the number of context lines shown when a unified diff is created. This takes precedence over any "-U" or "--unified" option value passed on the Git diff command line. -'GIT_EXTERNAL_DIFF':: - When the environment variable 'GIT_EXTERNAL_DIFF' is set, the +`GIT_EXTERNAL_DIFF`:: + When the environment variable `GIT_EXTERNAL_DIFF` is set, the program named by it is called, instead of the diff invocation described above. For a path that is added, removed, or modified, - 'GIT_EXTERNAL_DIFF' is called with 7 parameters: + `GIT_EXTERNAL_DIFF` is called with 7 parameters: path old-file old-hex old-mode new-file new-hex new-mode + @@@ -937,42 -929,42 +937,42 @@@ where The file parameters can point at the user's working file (e.g. `new-file` in "git-diff-files"), `/dev/null` (e.g. `old-file` when a new file is added), or a temporary file (e.g. `old-file` in the -index). 'GIT_EXTERNAL_DIFF' should not worry about unlinking the -temporary file --- it is removed when 'GIT_EXTERNAL_DIFF' exits. +index). `GIT_EXTERNAL_DIFF` should not worry about unlinking the +temporary file --- it is removed when `GIT_EXTERNAL_DIFF` exits. + -For a path that is unmerged, 'GIT_EXTERNAL_DIFF' is called with 1 +For a path that is unmerged, `GIT_EXTERNAL_DIFF` is called with 1 parameter, . + -For each path 'GIT_EXTERNAL_DIFF' is called, two environment variables, -'GIT_DIFF_PATH_COUNTER' and 'GIT_DIFF_PATH_TOTAL' are set. +For each path `GIT_EXTERNAL_DIFF` is called, two environment variables, +`GIT_DIFF_PATH_COUNTER` and `GIT_DIFF_PATH_TOTAL` are set. -'GIT_DIFF_PATH_COUNTER':: +`GIT_DIFF_PATH_COUNTER`:: A 1-based counter incremented by one for every path. -'GIT_DIFF_PATH_TOTAL':: +`GIT_DIFF_PATH_TOTAL`:: The total number of paths. other ~~~~~ -'GIT_MERGE_VERBOSITY':: +`GIT_MERGE_VERBOSITY`:: A number controlling the amount of output shown by the recursive merge strategy. Overrides merge.verbosity. See linkgit:git-merge[1] -'GIT_PAGER':: +`GIT_PAGER`:: This environment variable overrides `$PAGER`. If it is set to an empty string or to the value "cat", Git will not launch a pager. See also the `core.pager` option in linkgit:git-config[1]. -'GIT_EDITOR':: +`GIT_EDITOR`:: This environment variable overrides `$EDITOR` and `$VISUAL`. It is used by several Git commands when, on interactive mode, an editor is to be launched. See also linkgit:git-var[1] and the `core.editor` option in linkgit:git-config[1]. -'GIT_SSH':: -'GIT_SSH_COMMAND':: +`GIT_SSH`:: +`GIT_SSH_COMMAND`:: If either of these environment variables is set then 'git fetch' and 'git push' will use the specified command instead of 'ssh' when they need to connect to a remote system. @@@ -992,18 -984,18 +992,18 @@@ Usually it is easier to configure any d personal `.ssh/config` file. Please consult your ssh documentation for further details. -'GIT_ASKPASS':: +`GIT_ASKPASS`:: If this environment variable is set, then Git commands which need to acquire passwords or passphrases (e.g. for HTTP or IMAP authentication) will call this program with a suitable prompt as command-line argument - and read the password from its STDOUT. See also the 'core.askPass' + and read the password from its STDOUT. See also the `core.askPass` option in linkgit:git-config[1]. -'GIT_TERMINAL_PROMPT':: +`GIT_TERMINAL_PROMPT`:: If this environment variable is set to `0`, git will not prompt on the terminal (e.g., when asking for HTTP authentication). -'GIT_CONFIG_NOSYSTEM':: +`GIT_CONFIG_NOSYSTEM`:: Whether to skip reading settings from the system-wide `$(prefix)/etc/gitconfig` file. This environment variable can be used along with `$HOME` and `$XDG_CONFIG_HOME` to create a @@@ -1011,7 -1003,7 +1011,7 @@@ temporarily to avoid using a buggy `/etc/gitconfig` file while waiting for someone with sufficient permissions to fix it. -'GIT_FLUSH':: +`GIT_FLUSH`:: If this environment variable is set to "1", then commands such as 'git blame' (in incremental mode), 'git rev-list', 'git log', 'git check-attr' and 'git check-ignore' will @@@ -1022,7 -1014,7 +1022,7 @@@ not set, Git will choose buffered or record-oriented flushing based on whether stdout appears to be redirected to a file or not. -'GIT_TRACE':: +`GIT_TRACE`:: Enables general trace messages, e.g. alias expansion, built-in command execution and external command execution. + @@@ -1043,21 -1035,21 +1043,21 @@@ into it Unsetting the variable, or setting it to empty, "0" or "false" (case insensitive) disables trace messages. -'GIT_TRACE_PACK_ACCESS':: +`GIT_TRACE_PACK_ACCESS`:: Enables trace messages for all accesses to any packs. For each access, the pack file name and an offset in the pack is recorded. This may be helpful for troubleshooting some pack-related performance problems. - See 'GIT_TRACE' for available trace output options. + See `GIT_TRACE` for available trace output options. -'GIT_TRACE_PACKET':: +`GIT_TRACE_PACKET`:: Enables trace messages for all packets coming in or out of a given program. This can help with debugging object negotiation or other protocol issues. Tracing is turned off at a packet - starting with "PACK" (but see 'GIT_TRACE_PACKFILE' below). - See 'GIT_TRACE' for available trace output options. + starting with "PACK" (but see `GIT_TRACE_PACKFILE` below). + See `GIT_TRACE` for available trace output options. -'GIT_TRACE_PACKFILE':: +`GIT_TRACE_PACKFILE`:: Enables tracing of packfiles sent or received by a given program. Unlike other trace output, this trace is verbatim: no headers, and no quoting of binary data. You almost @@@ -1068,22 -1060,30 +1068,30 @@@ Note that this is currently only implemented for the client side of clones and fetches. -'GIT_TRACE_PERFORMANCE':: +`GIT_TRACE_PERFORMANCE`:: Enables performance related trace messages, e.g. total execution time of each Git command. - See 'GIT_TRACE' for available trace output options. + See `GIT_TRACE` for available trace output options. -'GIT_TRACE_SETUP':: +`GIT_TRACE_SETUP`:: Enables trace messages printing the .git, working tree and current working directory after Git has completed its setup phase. - See 'GIT_TRACE' for available trace output options. + See `GIT_TRACE` for available trace output options. -'GIT_TRACE_SHALLOW':: +`GIT_TRACE_SHALLOW`:: Enables trace messages that can help debugging fetching / cloning of shallow repositories. - See 'GIT_TRACE' for available trace output options. + See `GIT_TRACE` for available trace output options. -'GIT_TRACE_CURL':: ++`GIT_TRACE_CURL`:: + Enables a curl full trace dump of all incoming and outgoing data, + including descriptive information, of the git transport protocol. - This is similar to doing curl --trace-ascii on the command line. - This option overrides setting the GIT_CURL_VERBOSE environment ++ This is similar to doing curl `--trace-ascii` on the command line. ++ This option overrides setting the `GIT_CURL_VERBOSE` environment + variable. - See 'GIT_TRACE' for available trace output options. ++ See `GIT_TRACE` for available trace output options. + -'GIT_LITERAL_PATHSPECS':: +`GIT_LITERAL_PATHSPECS`:: Setting this variable to `1` will cause Git to treat all pathspecs literally, rather than as glob patterns. For example, running `GIT_LITERAL_PATHSPECS=1 git log -- '*.c'` will search @@@ -1092,19 -1092,19 +1100,19 @@@ literal paths to Git (e.g., paths previously given to you by `git ls-tree`, `--raw` diff output, etc). -'GIT_GLOB_PATHSPECS':: +`GIT_GLOB_PATHSPECS`:: Setting this variable to `1` will cause Git to treat all pathspecs as glob patterns (aka "glob" magic). -'GIT_NOGLOB_PATHSPECS':: +`GIT_NOGLOB_PATHSPECS`:: Setting this variable to `1` will cause Git to treat all pathspecs as literal (aka "literal" magic). -'GIT_ICASE_PATHSPECS':: +`GIT_ICASE_PATHSPECS`:: Setting this variable to `1` will cause Git to treat all pathspecs as case-insensitive. -'GIT_REFLOG_ACTION':: +`GIT_REFLOG_ACTION`:: When a ref is updated, reflog entries are created to keep track of the reason why the ref was updated (which is typically the name of the high-level command that updated @@@ -1114,7 -1114,7 +1122,7 @@@ variable when it is invoked as the top level command by the end user, to be recorded in the body of the reflog. -'GIT_REF_PARANOIA':: +`GIT_REF_PARANOIA`:: If set to `1`, include broken or badly named refs when iterating over lists of refs. In a normal, non-corrupted repository, this does nothing. However, enabling it may help git to detect and @@@ -1125,7 -1125,7 +1133,7 @@@ an operation has touched every ref (e.g., because you are cloning a repository to make a backup). -'GIT_ALLOW_PROTOCOL':: +`GIT_ALLOW_PROTOCOL`:: If set, provide a colon-separated list of protocols which are allowed to be used with fetch/push/clone. This is useful to restrict recursive submodule initialization from an untrusted diff --combined http.c index df6dd01594,deaf65522f..d8b2bec861 --- a/http.c +++ b/http.c @@@ -11,6 -11,7 +11,7 @@@ #include "gettext.h" #include "transport.h" + static struct trace_key trace_curl = TRACE_KEY_INIT(CURL); #if LIBCURL_VERSION_NUM >= 0x070a08 long int git_curl_ipresolve = CURL_IPRESOLVE_WHATEVER; #else @@@ -114,7 -115,6 +115,7 @@@ static unsigned long http_auth_methods static struct curl_slist *pragma_header; static struct curl_slist *no_pragma_header; +static struct curl_slist *extra_http_headers; static struct active_request_slot *active_queue_head; @@@ -294,7 -294,7 +295,7 @@@ static int http_options(const char *var return git_config_string(&http_proxy_authmethod, var, value); if (!strcmp("http.cookiefile", var)) - return git_config_string(&curl_cookie_file, var, value); + return git_config_pathname(&curl_cookie_file, var, value); if (!strcmp("http.savecookies", var)) { curl_save_cookies = git_config_bool(var, value); return 0; @@@ -324,19 -324,6 +325,19 @@@ #endif } + if (!strcmp("http.extraheader", var)) { + if (!value) { + return config_error_nonbool(var); + } else if (!*value) { + curl_slist_free_all(extra_http_headers); + extra_http_headers = NULL; + } else { + extra_http_headers = + curl_slist_append(extra_http_headers, value); + } + return 0; + } + /* Fall back on the default ones */ return git_default_config(var, value, cb); } @@@ -460,7 -447,8 +461,7 @@@ static int sockopt_callback(void *clien rc = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&ka, len); if (rc < 0) - warning("unable to set SO_KEEPALIVE on socket %s", - strerror(errno)); + warning_errno("unable to set SO_KEEPALIVE on socket"); return 0; /* CURL_SOCKOPT_OK only exists since curl 7.21.5 */ } @@@ -477,6 -465,125 +478,125 @@@ static void set_curl_keepalive(CURL *c } #endif + static void redact_sensitive_header(struct strbuf *header) + { + const char *sensitive_header; + + if (skip_prefix(header->buf, "Authorization:", &sensitive_header) || + skip_prefix(header->buf, "Proxy-Authorization:", &sensitive_header)) { + /* The first token is the type, which is OK to log */ + while (isspace(*sensitive_header)) + sensitive_header++; + while (*sensitive_header && !isspace(*sensitive_header)) + sensitive_header++; + /* Everything else is opaque and possibly sensitive */ + strbuf_setlen(header, sensitive_header - header->buf); + strbuf_addstr(header, " "); + } + } + + static void curl_dump_header(const char *text, unsigned char *ptr, size_t size, int hide_sensitive_header) + { + struct strbuf out = STRBUF_INIT; + struct strbuf **headers, **header; + + strbuf_addf(&out, "%s, %10.10ld bytes (0x%8.8lx)\n", + text, (long)size, (long)size); + trace_strbuf(&trace_curl, &out); + strbuf_reset(&out); + strbuf_add(&out, ptr, size); + headers = strbuf_split_max(&out, '\n', 0); + + for (header = headers; *header; header++) { + if (hide_sensitive_header) + redact_sensitive_header(*header); + strbuf_insert((*header), 0, text, strlen(text)); + strbuf_insert((*header), strlen(text), ": ", 2); + strbuf_rtrim((*header)); + strbuf_addch((*header), '\n'); + trace_strbuf(&trace_curl, (*header)); + } + strbuf_list_free(headers); + strbuf_release(&out); + } + + static void curl_dump_data(const char *text, unsigned char *ptr, size_t size) + { + size_t i; + struct strbuf out = STRBUF_INIT; + unsigned int width = 60; + + strbuf_addf(&out, "%s, %10.10ld bytes (0x%8.8lx)\n", + text, (long)size, (long)size); + trace_strbuf(&trace_curl, &out); + + for (i = 0; i < size; i += width) { + size_t w; + + strbuf_reset(&out); + strbuf_addf(&out, "%s: ", text); + for (w = 0; (w < width) && (i + w < size); w++) { + unsigned char ch = ptr[i + w]; + + strbuf_addch(&out, + (ch >= 0x20) && (ch < 0x80) + ? ch : '.'); + } + strbuf_addch(&out, '\n'); + trace_strbuf(&trace_curl, &out); + } + strbuf_release(&out); + } + + static int curl_trace(CURL *handle, curl_infotype type, char *data, size_t size, void *userp) + { + const char *text; + enum { NO_FILTER = 0, DO_FILTER = 1 }; + + switch (type) { + case CURLINFO_TEXT: + trace_printf_key(&trace_curl, "== Info: %s", data); + default: /* we ignore unknown types by default */ + return 0; + + case CURLINFO_HEADER_OUT: + text = "=> Send header"; + curl_dump_header(text, (unsigned char *)data, size, DO_FILTER); + break; + case CURLINFO_DATA_OUT: + text = "=> Send data"; + curl_dump_data(text, (unsigned char *)data, size); + break; + case CURLINFO_SSL_DATA_OUT: + text = "=> Send SSL data"; + curl_dump_data(text, (unsigned char *)data, size); + break; + case CURLINFO_HEADER_IN: + text = "<= Recv header"; + curl_dump_header(text, (unsigned char *)data, size, NO_FILTER); + break; + case CURLINFO_DATA_IN: + text = "<= Recv data"; + curl_dump_data(text, (unsigned char *)data, size); + break; + case CURLINFO_SSL_DATA_IN: + text = "<= Recv SSL data"; + curl_dump_data(text, (unsigned char *)data, size); + break; + } + return 0; + } + + void setup_curl_trace(CURL *handle) + { + if (!trace_want(&trace_curl)) + return; + curl_easy_setopt(handle, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(handle, CURLOPT_DEBUGFUNCTION, curl_trace); + curl_easy_setopt(handle, CURLOPT_DEBUGDATA, NULL); + } + + static CURL *get_curl_handle(void) { CURL *result = curl_easy_init(); @@@ -575,9 -682,9 +695,9 @@@ warning("protocol restrictions not applied to curl redirects because\n" "your curl version is too old (>= 7.19.4)"); #endif - if (getenv("GIT_CURL_VERBOSE")) - curl_easy_setopt(result, CURLOPT_VERBOSE, 1); + curl_easy_setopt(result, CURLOPT_VERBOSE, 1L); + setup_curl_trace(result); curl_easy_setopt(result, CURLOPT_USERAGENT, user_agent ? user_agent : git_user_agent()); @@@ -618,10 -725,7 +738,10 @@@ if (curl_http_proxy) { curl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy); #if LIBCURL_VERSION_NUM >= 0x071800 - if (starts_with(curl_http_proxy, "socks5")) + if (starts_with(curl_http_proxy, "socks5h")) + curl_easy_setopt(result, + CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5_HOSTNAME); + else if (starts_with(curl_http_proxy, "socks5")) curl_easy_setopt(result, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); else if (starts_with(curl_http_proxy, "socks4a")) @@@ -691,10 -795,8 +811,10 @@@ void http_init(struct remote *remote, c if (remote) var_override(&http_proxy_authmethod, remote->http_proxy_authmethod); - pragma_header = curl_slist_append(pragma_header, "Pragma: no-cache"); - no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:"); + pragma_header = curl_slist_append(http_copy_default_headers(), + "Pragma: no-cache"); + no_pragma_header = curl_slist_append(http_copy_default_headers(), + "Pragma:"); #ifdef USE_CURL_MULTI { @@@ -780,9 -882,6 +900,9 @@@ void http_cleanup(void #endif curl_global_cleanup(); + curl_slist_free_all(extra_http_headers); + extra_http_headers = NULL; + curl_slist_free_all(pragma_header); pragma_header = NULL; @@@ -1181,16 -1280,6 +1301,16 @@@ int run_one_slot(struct active_request_ return handle_curl_result(results); } +struct curl_slist *http_copy_default_headers(void) +{ + struct curl_slist *headers = NULL, *h; + + for (h = extra_http_headers; h; h = h->next) + headers = curl_slist_append(headers, h->data); + + return headers; +} + static CURLcode curlinfo_strbuf(CURL *curl, CURLINFO info, struct strbuf *buf) { char *ptr; @@@ -1408,7 -1497,7 +1528,7 @@@ static int http_request(const char *url { struct active_request_slot *slot; struct slot_results results; - struct curl_slist *headers = NULL; + struct curl_slist *headers = http_copy_default_headers(); struct strbuf buf = STRBUF_INIT; const char *accept_language; int ret; @@@ -1922,7 -2011,8 +2042,7 @@@ struct http_object_request *new_http_ob } if (freq->localfile < 0) { - error("Couldn't create temporary file %s: %s", - freq->tmpfile, strerror(errno)); + error_errno("Couldn't create temporary file %s", freq->tmpfile); goto abort; } @@@ -1967,8 -2057,8 +2087,8 @@@ prev_posn = 0; lseek(freq->localfile, 0, SEEK_SET); if (ftruncate(freq->localfile, 0) < 0) { - error("Couldn't truncate temporary file %s: %s", - freq->tmpfile, strerror(errno)); + error_errno("Couldn't truncate temporary file %s", + freq->tmpfile); goto abort; } } diff --combined http.h index 36f558bfb3,2fb56d0743..5ab9d9c329 --- a/http.h +++ b/http.h @@@ -106,7 -106,6 +106,7 @@@ extern void step_active_slots(void) extern void http_init(struct remote *remote, const char *url, int proactive_auth); extern void http_cleanup(void); +extern struct curl_slist *http_copy_default_headers(void); extern long int git_curl_ipresolve; extern int active_requests; @@@ -225,4 -224,6 +225,6 @@@ extern int finish_http_object_request(s extern void abort_http_object_request(struct http_object_request *freq); extern void release_http_object_request(struct http_object_request *freq); + /* setup routine for curl_easy_setopt CURLOPT_DEBUGFUNCTION */ + void setup_curl_trace(CURL *handle); #endif /* HTTP_H */ diff --combined imap-send.c index 938c691585,8ad80674da..50377c5b88 --- a/imap-send.c +++ b/imap-send.c @@@ -287,20 -287,17 +287,20 @@@ static int ssl_socket_connect(struct im SSL_library_init(); SSL_load_error_strings(); - if (use_tls_only) - meth = TLSv1_method(); - else - meth = SSLv23_method(); - + meth = SSLv23_method(); if (!meth) { ssl_socket_perror("SSLv23_method"); return -1; } ctx = SSL_CTX_new(meth); + if (!ctx) { + ssl_socket_perror("SSL_CTX_new"); + return -1; + } + + if (use_tls_only) + SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); if (verify) SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); @@@ -865,6 -862,7 +865,6 @@@ static char hexchar(unsigned int b static char *cram(const char *challenge_64, const char *user, const char *pass) { int i, resp_len, encoded_len, decoded_len; - HMAC_CTX hmac; unsigned char hash[16]; char hex[33]; char *response, *response_64, *challenge; @@@ -879,8 -877,10 +879,8 @@@ (unsigned char *)challenge_64, encoded_len); if (decoded_len < 0) die("invalid challenge %s", challenge_64); - HMAC_Init(&hmac, (unsigned char *)pass, strlen(pass), EVP_md5()); - HMAC_Update(&hmac, (unsigned char *)challenge, decoded_len); - HMAC_Final(&hmac, hash, NULL); - HMAC_CTX_cleanup(&hmac); + if (!HMAC(EVP_md5(), pass, strlen(pass), (unsigned char *)challenge, decoded_len, hash, NULL)) + die("HMAC error"); hex[32] = 0; for (i = 0; i < 16; i++) { @@@ -890,7 -890,7 +890,7 @@@ /* response: " " */ response = xstrfmt("%s %s", user, hex); - resp_len = strlen(response) + 1; + resp_len = strlen(response); response_64 = xmallocz(ENCODED_SIZE(resp_len)); encoded_len = EVP_EncodeBlock((unsigned char *)response_64, @@@ -1095,6 -1095,11 +1095,6 @@@ static struct imap_store *imap_open_sto srvc->pass = xstrdup(cred.password); } - if (CAP(NOLOGIN)) { - fprintf(stderr, "Skipping account %s@%s, server forbids LOGIN\n", srvc->user, srvc->host); - goto bail; - } - if (srvc->auth_method) { struct imap_cmd_cb cb; @@@ -1118,11 -1123,6 +1118,11 @@@ goto bail; } } else { + if (CAP(NOLOGIN)) { + fprintf(stderr, "Skipping account %s@%s, server forbids LOGIN\n", + srvc->user, srvc->host); + goto bail; + } if (!imap->buf.sock.ssl) imap_warn("*** IMAP Warning *** Password is being " "sent in the clear\n"); @@@ -1443,6 -1443,7 +1443,7 @@@ static CURL *setup_curl(struct imap_ser if (0 < verbosity || getenv("GIT_CURL_VERBOSE")) curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); + setup_curl_trace(curl); return curl; }