transport: add from_user parameter to is_transport_allowed
authorBrandon Williams <bmwill@google.com>
Wed, 14 Dec 2016 22:39:54 +0000 (14:39 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 15 Dec 2016 17:29:13 +0000 (09:29 -0800)
Add a from_user parameter to is_transport_allowed() to allow http to be
able to distinguish between protocol restrictions for redirects versus
initial requests. CURLOPT_REDIR_PROTOCOLS can now be set differently
from CURLOPT_PROTOCOLS to disallow use of protocols with the "user"
policy in redirects.

This change allows callers to query if a transport protocol is allowed,
given that the caller knows that the protocol is coming from the user
(1) or not from the user (0) such as redirects in libcurl. If unknown a
-1 should be provided which falls back to reading
`GIT_PROTOCOL_FROM_USER` to determine if the protocol came from the
user.

Signed-off-by: Brandon Williams <bmwill@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
http.c
t/t5812-proto-disable-http.sh
transport.c
transport.h
diff --git a/http.c b/http.c
index f7c488af8b047627b42c850be1f6883ebab650d9..2208269b33ae11c8b6371309d961b065e9fe5e05 100644 (file)
--- a/http.c
+++ b/http.c
@@ -489,17 +489,17 @@ static void set_curl_keepalive(CURL *c)
 }
 #endif
 
-static long get_curl_allowed_protocols(void)
+static long get_curl_allowed_protocols(int from_user)
 {
        long allowed_protocols = 0;
 
-       if (is_transport_allowed("http"))
+       if (is_transport_allowed("http", from_user))
                allowed_protocols |= CURLPROTO_HTTP;
-       if (is_transport_allowed("https"))
+       if (is_transport_allowed("https", from_user))
                allowed_protocols |= CURLPROTO_HTTPS;
-       if (is_transport_allowed("ftp"))
+       if (is_transport_allowed("ftp", from_user))
                allowed_protocols |= CURLPROTO_FTP;
-       if (is_transport_allowed("ftps"))
+       if (is_transport_allowed("ftps", from_user))
                allowed_protocols |= CURLPROTO_FTPS;
 
        return allowed_protocols;
@@ -588,9 +588,9 @@ static CURL *get_curl_handle(void)
 #endif
 #if LIBCURL_VERSION_NUM >= 0x071304
        curl_easy_setopt(result, CURLOPT_REDIR_PROTOCOLS,
-                        get_curl_allowed_protocols());
+                        get_curl_allowed_protocols(0));
        curl_easy_setopt(result, CURLOPT_PROTOCOLS,
-                        get_curl_allowed_protocols());
+                        get_curl_allowed_protocols(-1));
 #else
        warning("protocol restrictions not applied to curl redirects because\n"
                "your curl version is too old (>= 7.19.4)");
index 044cc152f83b05e090a65268c8818d56adb4422b..d911afd24cd7d43fc412adb34144b90b66082b73 100755 (executable)
@@ -30,5 +30,12 @@ test_expect_success 'curl limits redirects' '
        test_must_fail git clone "$HTTPD_URL/loop-redir/smart/repo.git"
 '
 
+test_expect_success 'http can be limited to from-user' '
+       git -c protocol.http.allow=user \
+               clone "$HTTPD_URL/smart/repo.git" plain.git &&
+       test_must_fail git -c protocol.http.allow=user \
+               clone "$HTTPD_URL/smart-redir-perm/repo.git" redir.git
+'
+
 stop_httpd
 test_done
index fbd799d062577d87f9ffdd8a9e7dcec306a299c2..f50c31a572f35964cb12c2d88ee5748858908cd1 100644 (file)
@@ -676,7 +676,7 @@ static enum protocol_allow_config get_protocol_config(const char *type)
        return PROTOCOL_ALLOW_USER_ONLY;
 }
 
-int is_transport_allowed(const char *type)
+int is_transport_allowed(const char *type, int from_user)
 {
        const struct string_list *whitelist = protocol_whitelist();
        if (whitelist)
@@ -688,7 +688,9 @@ int is_transport_allowed(const char *type)
        case PROTOCOL_ALLOW_NEVER:
                return 0;
        case PROTOCOL_ALLOW_USER_ONLY:
-               return git_env_bool("GIT_PROTOCOL_FROM_USER", 1);
+               if (from_user < 0)
+                       from_user = git_env_bool("GIT_PROTOCOL_FROM_USER", 1);
+               return from_user;
        }
 
        die("BUG: invalid protocol_allow_config type");
@@ -696,7 +698,7 @@ int is_transport_allowed(const char *type)
 
 void transport_check_allowed(const char *type)
 {
-       if (!is_transport_allowed(type))
+       if (!is_transport_allowed(type, -1))
                die("transport '%s' not allowed", type);
 }
 
index 3396e1d434062b884521a490707f48c2c91a205b..4f1c801994fc01c5eca7861d7cea3b1bfcfbcd1e 100644 (file)
@@ -142,10 +142,17 @@ struct transport {
 struct transport *transport_get(struct remote *, const char *);
 
 /*
- * Check whether a transport is allowed by the environment. Type should
- * generally be the URL scheme, as described in Documentation/git.txt
+ * Check whether a transport is allowed by the environment.
+ *
+ * Type should generally be the URL scheme, as described in
+ * Documentation/git.txt
+ *
+ * from_user specifies if the transport was given by the user.  If unknown pass
+ * a -1 to read from the environment to determine if the transport was given by
+ * the user.
+ *
  */
-int is_transport_allowed(const char *type);
+int is_transport_allowed(const char *type, int from_user);
 
 /*
  * Check whether a transport is allowed by the environment,