On Wed, Nov 29, 2017 at 10:28:32PM -0500, Jeff King wrote: > 2. Setting GIT_TRACE_CURL=1 may dump more verbose information. But one > caveat: if you get as far as authenticating, then the trace will > contain your password. We redact HTTP auth from the trace output, > but not imap ones. I tried my hand at a patch, but it ended up a lot more complicated than I would have liked. Thoughts? diff --git a/http.c b/http.c index 713525f38e..fcc9001af6 100644 --- a/http.c +++ b/http.c @@ -560,7 +560,7 @@ static void set_curl_keepalive(CURL *c) } #endif -static void redact_sensitive_header(struct strbuf *header) +static void redact_http_header(struct strbuf *header) { const char *sensitive_header; @@ -577,7 +577,60 @@ static void redact_sensitive_header(struct strbuf *header) } } -static void curl_dump_header(const char *text, unsigned char *ptr, size_t size, int hide_sensitive_header) +static void redact_imap_header(struct strbuf *header) +{ + const char *p; + + /* skip past the command tag */ + p = strchr(header->buf, ' '); + if (!p) + return; /* no tag */ + p++; + + if (skip_prefix(p, "AUTHENTICATE ", &p)) { + /* the first token is the auth type, which is OK to log */ + while (*p && !isspace(*p)) + p++; + /* the rest is an opaque blob; fall through to redact */ + } else if (skip_prefix(p, "LOGIN ", &p)) { + /* fall through to redact both login and password */ + } else { + /* not a sensitive header */ + return; + } + + strbuf_setlen(header, p - header->buf); + strbuf_addstr(header, " <redacted>"); +} + +static void redact_sensitive_header(CURL *handle, struct strbuf *header) +{ + const char *url; + int ret; + + ret = curl_easy_getinfo(handle, CURLINFO_EFFECTIVE_URL, &url); + if (!ret && url) { + if (starts_with(url, "http")) { + redact_http_header(header); + return; + } + if (starts_with(url, "imap")) { + redact_imap_header(header); + return; + } + } + + /* + * We weren't able to figure out the protocol. Err on the side of + * redacting too much. + */ + redact_http_header(header); + redact_imap_header(header); +} + +static void curl_dump_header(CURL *handle, const char *text, + unsigned char *ptr, size_t size, + int hide_sensitive_header) { struct strbuf out = STRBUF_INIT; struct strbuf **headers, **header; @@ -591,7 +644,7 @@ static void curl_dump_header(const char *text, unsigned char *ptr, size_t size, for (header = headers; *header; header++) { if (hide_sensitive_header) - redact_sensitive_header(*header); + redact_sensitive_header(handle, *header); strbuf_insert((*header), 0, text, strlen(text)); strbuf_insert((*header), strlen(text), ": ", 2); strbuf_rtrim((*header)); @@ -641,7 +694,7 @@ static int curl_trace(CURL *handle, curl_infotype type, char *data, size_t size, break; case CURLINFO_HEADER_OUT: text = "=> Send header"; - curl_dump_header(text, (unsigned char *)data, size, DO_FILTER); + curl_dump_header(handle, text, (unsigned char *)data, size, DO_FILTER); break; case CURLINFO_DATA_OUT: text = "=> Send data"; @@ -653,7 +706,7 @@ static int curl_trace(CURL *handle, curl_infotype type, char *data, size_t size, break; case CURLINFO_HEADER_IN: text = "<= Recv header"; - curl_dump_header(text, (unsigned char *)data, size, NO_FILTER); + curl_dump_header(handle, text, (unsigned char *)data, size, NO_FILTER); break; case CURLINFO_DATA_IN: text = "<= Recv data";