On Fri, May 16, 2014 at 10:34:10PM +0000, brian m. carlson wrote:

> > The tricky part is figuring out when to return HTTP_NOAUTH ("do not try
> > again, we failed") versus HTTP_REAUTH ("get credentials and try again")
> > in handle_curl_result. Right now the decision is based on "did we have a
> > username and password for this request?" I'm not clear on what extra
> > bits would be needed to decide to continue in the case you guys are
> > discussing.
> 
> I'm honestly not sure, either.  That's why I said, "how to do that is
> unknown".
> 
> However, if you base64-decode the two Negotiate replies in the
> successful attempt with WinHTTP and pass it through od -tc, you'll see
> that the second reply contains some form of user ID that the first one
> does not.  The curl binary sends an identical reply for the first pass,
> but then gives up and does not try a second pass.  I don't know if
> libcurl is able to provide the data required in the second pass.
> 
> All of this is way outside my knowledge, since my Kerberos/GSSAPI
> Negotiate requests look very different than the NTLM ones.

Mine too. I think a good place to start would be somebody who has a
setup to replicate the problem dumping the curl data (either from
GIT_CURL_VERBOSE, or instrumenting git with some curl_easy_getinfo
calls), and seeing what is interesting.

> > Yeah, we just set CURLAUTH_ANY now, but it would be fairly trivial to
> > add "http.authtype" and "http.proxyauthtype" to map to CURLOPT_HTTPAUTH
> > and CURLOPT_PROXYAUTH.
> 
> This might be the easiest option.

I can help with working up a patch, but I don't have any meaningful way
to test it.

The patch below might help somebody get started. I don't know if
CURLAUTH_ONLY would be useful to be able to set, too.

diff --git a/http.c b/http.c
index 94e1afd..ba56f7e 100644
--- a/http.c
+++ b/http.c
@@ -51,6 +51,9 @@ struct credential http_auth = CREDENTIAL_INIT;
 static int http_proactive_auth;
 static const char *user_agent;
 
+static long curl_http_authtype;
+static long curl_proxy_authtype;
+
 #if LIBCURL_VERSION_NUM >= 0x071700
 /* Use CURLOPT_KEYPASSWD as is */
 #elif LIBCURL_VERSION_NUM >= 0x070903
@@ -143,6 +146,37 @@ static void process_curl_messages(void)
 }
 #endif
 
+static int parse_auth_type(const char *var, const char *value, long *type)
+{
+       static struct {
+               const char *name;
+               long value;
+       } types[] = {
+                { "basic", CURLAUTH_BASIC },
+                { "digest", CURLAUTH_DIGEST },
+#if CURL_VERSION >= 0x071303
+                { "digest-ie", CURLAUTH_DIGEST_IE },
+#endif
+                { "negotiate", CURLAUTH_GSSNEGOTIATE },
+#if CURL_VERSION >= 0x071600
+                { "ntlm-wb", CURLAUTH_NTLM_WB },
+#endif
+                { "ntlm", CURLAUTH_NTLM }
+       };
+       int i;
+
+       if (!value)
+               return config_error_nonbool(var);
+
+       for (i = 0; i < ARRAY_SIZE(types); i++)
+               if (!strcmp(value, types[i].name))
+                       *type |= types[i].value;
+
+       if (i == ARRAY_SIZE(types))
+               return error("unknown auth type for '%s': %s", var, value);
+       return 0;
+}
+
 static int http_options(const char *var, const char *value, void *cb)
 {
        if (!strcmp("http.sslverify", var)) {
@@ -216,6 +250,11 @@ static int http_options(const char *var, const char 
*value, void *cb)
        if (!strcmp("http.useragent", var))
                return git_config_string(&user_agent, var, value);
 
+       if (!strcmp("http.authtype", var))
+               return parse_auth_type(var, value, &curl_http_authtype);
+       if (!strcmp("http.proxyauthtype", var))
+               return parse_auth_type(var, value, &curl_proxy_authtype);
+
        /* Fall back on the default ones */
        return git_default_config(var, value, cb);
 }
@@ -296,6 +335,17 @@ static void set_curl_keepalive(CURL *c)
 }
 #endif
 
+static void set_curl_authtype(CURL *c, CURLoption option, long value)
+{
+       if (value)
+               curl_easy_setopt(c, option, value);
+       else {
+#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
+               curl_easy_setopt(c, option, CURLAUTH_ANY);
+#endif
+       }
+}
+
 static CURL *get_curl_handle(void)
 {
        CURL *result = curl_easy_init();
@@ -313,8 +363,13 @@ static CURL *get_curl_handle(void)
 #if LIBCURL_VERSION_NUM >= 0x070907
        curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
 #endif
-#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
-       curl_easy_setopt(result, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
+
+#if LIBCURL_VERSION_NUM >= 0x070a06
+       set_curl_authtype(result, CURLOPT_HTTPAUTH, curl_http_authtype);
+#endif
+
+#if LIBCURL_VERSION_NUM >= 0x070a07
+       set_curl_authtype(result, CURLOPT_PROXYAUTH, curl_proxy_authtype);
 #endif
 
        if (http_proactive_auth)
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to