blob: 44dcd1e33d7936c9bdf1ade7459522dd066b6fdb [file] [log] [blame]
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001Backport of:
2
3From f4113cac0c88b4f36ee6f3abf3218034440a68e3 Mon Sep 17 00:00:00 2001
4From: Blake Burkhart <bburky@bburky.com>
5Date: Tue, 22 Sep 2015 18:06:04 -0400
6Subject: [PATCH] http: limit redirection to protocol-whitelist
7
8Previously, libcurl would follow redirection to any protocol
9it was compiled for support with. This is desirable to allow
10redirection from HTTP to HTTPS. However, it would even
11successfully allow redirection from HTTP to SFTP, a protocol
12that git does not otherwise support at all. Furthermore
13git's new protocol-whitelisting could be bypassed by
14following a redirect within the remote helper, as it was
15only enforced at transport selection time.
16
17This patch limits redirects within libcurl to HTTP, HTTPS,
18FTP and FTPS. If there is a protocol-whitelist present, this
19list is limited to those also allowed by the whitelist. As
20redirection happens from within libcurl, it is impossible
21for an HTTP redirect to a protocol implemented within
22another remote helper.
23
24When the curl version git was compiled with is too old to
25support restrictions on protocol redirection, we warn the
26user if GIT_ALLOW_PROTOCOL restrictions were requested. This
27is a little inaccurate, as even without that variable in the
28environment, we would still restrict SFTP, etc, and we do
29not warn in that case. But anything else means we would
30literally warn every time git accesses an http remote.
31
32This commit includes a test, but it is not as robust as we
33would hope. It redirects an http request to ftp, and checks
34that curl complained about the protocol, which means that we
35are relying on curl's specific error message to know what
36happened. Ideally we would redirect to a working ftp server
37and confirm that we can clone without protocol restrictions,
38and not with them. But we do not have a portable way of
39providing an ftp server, nor any other protocol that curl
40supports (https is the closest, but we would have to deal
41with certificates).
42
43[jk: added test and version warning]
44
45Signed-off-by: Jeff King <peff@peff.net>
46Signed-off-by: Junio C Hamano <gitster@pobox.com>
47
48Upstream-Status: Backport
49
50http://archive.ubuntu.com/ubuntu/pool/main/g/git/git_2.5.0-1ubuntu0.1.debian.tar.xz
51
52CVE: CVE-2015-7545 #4
53Singed-off-by: Armin Kuster <akuster@mvista.com>
54
55---
56 Documentation/git.txt | 5 -----
57 http.c | 17 +++++++++++++++++
58 t/lib-httpd/apache.conf | 1 +
59 t/t5812-proto-disable-http.sh | 9 +++++++++
60 4 files changed, 27 insertions(+), 5 deletions(-)
61
62Index: git-2.5.0/Documentation/git.txt
63===================================================================
64--- git-2.5.0.orig/Documentation/git.txt 2015-12-11 12:47:18.707849212 -0500
65+++ git-2.5.0/Documentation/git.txt 2015-12-11 12:47:18.703849183 -0500
66@@ -1095,11 +1095,6 @@
67
68 - any external helpers are named by their protocol (e.g., use
69 `hg` to allow the `git-remote-hg` helper)
70-+
71-Note that this controls only git's internal protocol selection.
72-If libcurl is used (e.g., by the `http` transport), it may
73-redirect to other protocols. There is not currently any way to
74-restrict this.
75
76
77 Discussion[[Discussion]]
78Index: git-2.5.0/http.c
79===================================================================
80--- git-2.5.0.orig/http.c 2015-12-11 12:47:18.707849212 -0500
81+++ git-2.5.0/http.c 2015-12-11 12:47:34.171959268 -0500
82@@ -8,6 +8,7 @@
83 #include "credential.h"
84 #include "version.h"
85 #include "pkt-line.h"
86+#include "transport.h"
87 #include "gettext.h"
88
89 int active_requests;
90@@ -340,6 +341,7 @@
91 static CURL *get_curl_handle(void)
92 {
93 CURL *result = curl_easy_init();
94+ long allowed_protocols = 0;
95
96 if (!result)
97 die("curl_easy_init failed");
98@@ -399,6 +401,21 @@
99 #elif LIBCURL_VERSION_NUM >= 0x071101
100 curl_easy_setopt(result, CURLOPT_POST301, 1);
101 #endif
102+#if LIBCURL_VERSION_NUM >= 0x071304
103+ if (is_transport_allowed("http"))
104+ allowed_protocols |= CURLPROTO_HTTP;
105+ if (is_transport_allowed("https"))
106+ allowed_protocols |= CURLPROTO_HTTPS;
107+ if (is_transport_allowed("ftp"))
108+ allowed_protocols |= CURLPROTO_FTP;
109+ if (is_transport_allowed("ftps"))
110+ allowed_protocols |= CURLPROTO_FTPS;
111+ curl_easy_setopt(result, CURLOPT_REDIR_PROTOCOLS, allowed_protocols);
112+#else
113+ if (transport_restrict_protocols())
114+ warning("protocol restrictions not applied to curl redirects because\n"
115+ "your curl version is too old (>= 7.19.4)");
116+#endif
117
118 if (getenv("GIT_CURL_VERBOSE"))
119 curl_easy_setopt(result, CURLOPT_VERBOSE, 1);
120Index: git-2.5.0/t/lib-httpd/apache.conf
121===================================================================
122--- git-2.5.0.orig/t/lib-httpd/apache.conf 2015-12-11 12:47:18.707849212 -0500
123+++ git-2.5.0/t/lib-httpd/apache.conf 2015-12-11 12:47:18.703849183 -0500
124@@ -119,6 +119,7 @@
125 RewriteRule ^/smart-redir-temp/(.*)$ /smart/$1 [R=302]
126 RewriteRule ^/smart-redir-auth/(.*)$ /auth/smart/$1 [R=301]
127 RewriteRule ^/smart-redir-limited/(.*)/info/refs$ /smart/$1/info/refs [R=301]
128+RewriteRule ^/ftp-redir/(.*)$ ftp://localhost:1000/$1 [R=302]
129
130 <IfDefine SSL>
131 LoadModule ssl_module modules/mod_ssl.so
132Index: git-2.5.0/t/t5812-proto-disable-http.sh
133===================================================================
134--- git-2.5.0.orig/t/t5812-proto-disable-http.sh 2015-12-11 12:47:18.707849212 -0500
135+++ git-2.5.0/t/t5812-proto-disable-http.sh 2015-12-11 12:47:18.703849183 -0500
136@@ -16,5 +16,14 @@
137
138 test_proto "smart http" http "$HTTPD_URL/smart/repo.git"
139
140+test_expect_success 'curl redirects respect whitelist' '
141+ test_must_fail env GIT_ALLOW_PROTOCOL=http:https \
142+ git clone "$HTTPD_URL/ftp-redir/repo.git" 2>stderr &&
143+ {
144+ test_i18ngrep "ftp.*disabled" stderr ||
145+ test_i18ngrep "your curl version is too old"
146+ }
147+'
148+
149 stop_httpd
150 test_done