Merge branch 'bw/transport-protocol-policy'
authorJunio C Hamano <gitster@pobox.com>
Tue, 27 Dec 2016 08:11:41 +0000 (00:11 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 27 Dec 2016 08:11:41 +0000 (00:11 -0800)
Finer-grained control of what protocols are allowed for transports
during clone/fetch/push have been enabled via a new configuration
mechanism.

* bw/transport-protocol-policy:
http: respect protocol.*.allow=user for http-alternates
transport: add from_user parameter to is_transport_allowed
http: create function to get curl allowed protocols
transport: add protocol policy config option
http: always warn if libcurl version is too old
lib-proto-disable: variable name fix

1  2 
Documentation/config.txt
Documentation/git.txt
git-submodule.sh
http.c
t/t5550-http-fetch-dumb.sh
transport.c
transport.h
Simple merge
Simple merge
Simple merge
diff --cc http.c
index 051fe6e5ab77a5dc6e53dce7011d0fc445f15ab0,2208269b33ae11c8b6371309d961b065e9fe5e05..90a1c0f1131c4a5fcbc50d6cc81c1be9cef3cd71
--- 1/http.c
--- 2/http.c
+++ b/http.c
@@@ -518,124 -489,21 +518,139 @@@ 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, " <redacted>");
 +      }
 +}
 +
 +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 long get_curl_allowed_protocols(int from_user)
+ {
+       long allowed_protocols = 0;
+       if (is_transport_allowed("http", from_user))
+               allowed_protocols |= CURLPROTO_HTTP;
+       if (is_transport_allowed("https", from_user))
+               allowed_protocols |= CURLPROTO_HTTPS;
+       if (is_transport_allowed("ftp", from_user))
+               allowed_protocols |= CURLPROTO_FTP;
+       if (is_transport_allowed("ftps", from_user))
+               allowed_protocols |= CURLPROTO_FTPS;
+       return allowed_protocols;
+ }
  
  static CURL *get_curl_handle(void)
  {
        curl_easy_setopt(result, CURLOPT_POST301, 1);
  #endif
  #if LIBCURL_VERSION_NUM >= 0x071304
-       if (is_transport_allowed("http"))
-               allowed_protocols |= CURLPROTO_HTTP;
-       if (is_transport_allowed("https"))
-               allowed_protocols |= CURLPROTO_HTTPS;
-       if (is_transport_allowed("ftp"))
-               allowed_protocols |= CURLPROTO_FTP;
-       if (is_transport_allowed("ftps"))
-               allowed_protocols |= CURLPROTO_FTPS;
-       curl_easy_setopt(result, CURLOPT_REDIR_PROTOCOLS, allowed_protocols);
-       curl_easy_setopt(result, CURLOPT_PROTOCOLS, allowed_protocols);
+       curl_easy_setopt(result, CURLOPT_REDIR_PROTOCOLS,
+                        get_curl_allowed_protocols(0));
+       curl_easy_setopt(result, CURLOPT_PROTOCOLS,
+                        get_curl_allowed_protocols(-1));
  #else
-       if (transport_restrict_protocols())
-               warning("protocol restrictions not applied to curl redirects because\n"
-                       "your curl version is too old (>= 7.19.4)");
+       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());
Simple merge
diff --cc transport.c
Simple merge
diff --cc transport.h
Simple merge