Re: GIT, libcurl and GSS-Negotiate

2014-05-17 Thread Jeff King
On Fri, May 16, 2014 at 10:34:10PM +, 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


Re: GIT, libcurl and GSS-Negotiate

2014-05-16 Thread brian m. carlson
On Mon, May 12, 2014 at 04:21:53PM -0400, Jeff King wrote:
 On Sat, May 10, 2014 at 09:01:32PM +, brian m. carlson wrote:
  * Make git understand that it really needs to try again with different
credentials in this case (how to do that is unknown).
 
 It should be pretty straightforward to loop again; http_request_reauth
 just needs to turn into a for-loop on getting HTTP_REAUTH, rather than a
 static two-tries (I even had a patch for this a while ago, but the
 function has changed a bit in the interim).
 
 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.

  * Provide some way of forcing git to use a particular authentication
protocol.
 
 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.

-- 
brian m. carlson / brian with sandals: Houston, Texas, US
+1 832 623 2791 | http://www.crustytoothpaste.net/~bmc | My opinion only
OpenPGP: RSA v4 4096b: 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187


signature.asc
Description: Digital signature


Re: GIT, libcurl and GSS-Negotiate

2014-05-12 Thread Carlos Martín Nieto
On Sat, 2014-05-10 at 21:01 +, brian m. carlson wrote:
 On Mon, May 05, 2014 at 12:21:33PM +0200, Ivo Bellin Salarin wrote:
  Well, I'm on Windows.
  using `git version 1.9.2.msysgit.0`.
  
  You can find all the exchanges, recorded with wireshark, of the
  following usecases:
  * git vanilla (not working),
  * VisualStudio2013 with libgit (working)
  * curl (--ntlm, working)
  * curl (--negotiate, not working)
 
 Okay, so what it looks like is that for some reason, the server and
 libcurl refuse to connect with Negotiate authentication.  git uses
 CURLAUTH_ANY, and libcurl picks the best choice: Negotiate.  The
 difference between your setup and mine is that I'm using Negotiate with
 Kerberos 5, and you're using Negotiate with NTLM.
 
 What it looks like is happening is that git is offering Negotiate data,
 and then your server is responding with a 401 Unauthorized.  libgit2
 (presumably using WinHTTP) continues in this case, retrying with a
 longer set of credential containing more data, but git gives up.

While libgit2 does use WinHTTP by default on Windows, Visual Studio
overrides this and uses their own HTTP transport (which makes the .NET
stack to handle it) because of the way the prefer to do things, with
just the one persistent connection to TFS.

But details aside, the code Visual Studio uses to do authentication has
nothing to do with any of the others.

   cmn


--
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


Re: GIT, libcurl and GSS-Negotiate

2014-05-12 Thread Jeff King
On Sat, May 10, 2014 at 09:01:32PM +, brian m. carlson wrote:

 What it looks like is happening is that git is offering Negotiate data,
 and then your server is responding with a 401 Unauthorized.  libgit2
 (presumably using WinHTTP) continues in this case, retrying with a
 longer set of credential containing more data, but git gives up.
 
 Both responses comply with RFC 2616, by my reading.  I guess there are a
 couple of choices here:
 
 * Make your web server happy with the data that it gets passed
   initially.
 * Make git understand that it really needs to try again with different
   credentials in this case (how to do that is unknown).

It should be pretty straightforward to loop again; http_request_reauth
just needs to turn into a for-loop on getting HTTP_REAUTH, rather than a
static two-tries (I even had a patch for this a while ago, but the
function has changed a bit in the interim).

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.

 * Provide some way of forcing git to use a particular authentication
   protocol.

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.

-Peff
--
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


Re: GIT, libcurl and GSS-Negotiate

2014-05-10 Thread brian m. carlson
On Mon, May 05, 2014 at 12:21:33PM +0200, Ivo Bellin Salarin wrote:
 Well, I'm on Windows.
 using `git version 1.9.2.msysgit.0`.
 
 You can find all the exchanges, recorded with wireshark, of the
 following usecases:
 * git vanilla (not working),
 * VisualStudio2013 with libgit (working)
 * curl (--ntlm, working)
 * curl (--negotiate, not working)

Okay, so what it looks like is that for some reason, the server and
libcurl refuse to connect with Negotiate authentication.  git uses
CURLAUTH_ANY, and libcurl picks the best choice: Negotiate.  The
difference between your setup and mine is that I'm using Negotiate with
Kerberos 5, and you're using Negotiate with NTLM.

What it looks like is happening is that git is offering Negotiate data,
and then your server is responding with a 401 Unauthorized.  libgit2
(presumably using WinHTTP) continues in this case, retrying with a
longer set of credential containing more data, but git gives up.

Both responses comply with RFC 2616, by my reading.  I guess there are a
couple of choices here:

* Make your web server happy with the data that it gets passed
  initially.
* Make git understand that it really needs to try again with different
  credentials in this case (how to do that is unknown).
* Provide some way of forcing git to use a particular authentication
  protocol.

-- 
brian m. carlson / brian with sandals: Houston, Texas, US
+1 832 623 2791 | http://www.crustytoothpaste.net/~bmc | My opinion only
OpenPGP: RSA v4 4096b: 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187


signature.asc
Description: Digital signature


Re: GIT, libcurl and GSS-Negotiate

2014-05-05 Thread Ivo Bellin Salarin
Well, I'm on Windows.
using `git version 1.9.2.msysgit.0`.

You can find all the exchanges, recorded with wireshark, of the
following usecases:
* git vanilla (not working),
* VisualStudio2013 with libgit (working)
* curl (--ntlm, working)
* curl (--negotiate, not working)

They're available on
[github](https://github.com/nilleb/my-documents/tree/master/msysgit%23git%2C%20issue-171).



On Sat, Apr 26, 2014 at 7:47 PM, brian m. carlson
sand...@crustytoothpaste.net wrote:
 On Thu, Apr 24, 2014 at 07:17:36PM +0200, Ivo Bellin Salarin wrote:
 To shortly resume it, the problem is that:
 * when the authentication method (WWW-Authenticate) is Negotiate AND
 * when the server proposes a NTLMSSP_CHALLENGE in response of the
 client's NTLMSSP_NEGOTIATE,
 = libcurl yields an Authentication problem. Ignoring this.\n
 And the communication is closed.

 At this point, in a normal communication, the client should send a
 NTLMSSP_AUTH containing a Kerberos ticket.

 Having seen the libcurl source code, I think we're passing through the
 lines  from 776 to 780 of
 [http.c](https://github.com/bagder/curl/blob/2e57c7e0fcfb9214b2a9dfa8b3da258ded013b8a/lib/http.c).
 Some guy, on the github issue page, has suggested that this could be
 related to an update of libcurl, when git was at its 1.8.2 version.

 I'm not debugging libcurl, and I can't reproduce this problem @home.
 So, has somebody already experienced the same problem? Is there a
 solution?

 I'm personally using Git with GSS-Negotiate (and MIT Kerberos 5) and it
 does seem to work correctly for me.  For large pushes, your server (and
 any intermediate proxies) will need to support 100 Continue properly, as
 there's simply no other way to make it work.

 What version of curl are you using (and what distro if you didn't
 compile it yourself)?  Also, can you post output of an attempt to push
 with GIT_CURL_VERBOSE=1?

 --
 brian m. carlson / brian with sandals: Houston, Texas, US
 +1 832 623 2791 | http://www.crustytoothpaste.net/~bmc | My opinion only
 OpenPGP: RSA v4 4096b: 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187



-- 
http://www.nilleb.com
--
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


Re: GIT, libcurl and GSS-Negotiate

2014-04-26 Thread brian m. carlson
On Thu, Apr 24, 2014 at 07:17:36PM +0200, Ivo Bellin Salarin wrote:
 To shortly resume it, the problem is that:
 * when the authentication method (WWW-Authenticate) is Negotiate AND
 * when the server proposes a NTLMSSP_CHALLENGE in response of the
 client's NTLMSSP_NEGOTIATE,
 = libcurl yields an Authentication problem. Ignoring this.\n
 And the communication is closed.
 
 At this point, in a normal communication, the client should send a
 NTLMSSP_AUTH containing a Kerberos ticket.
 
 Having seen the libcurl source code, I think we're passing through the
 lines  from 776 to 780 of
 [http.c](https://github.com/bagder/curl/blob/2e57c7e0fcfb9214b2a9dfa8b3da258ded013b8a/lib/http.c).
 Some guy, on the github issue page, has suggested that this could be
 related to an update of libcurl, when git was at its 1.8.2 version.
 
 I'm not debugging libcurl, and I can't reproduce this problem @home.
 So, has somebody already experienced the same problem? Is there a
 solution?

I'm personally using Git with GSS-Negotiate (and MIT Kerberos 5) and it
does seem to work correctly for me.  For large pushes, your server (and
any intermediate proxies) will need to support 100 Continue properly, as
there's simply no other way to make it work.

What version of curl are you using (and what distro if you didn't
compile it yourself)?  Also, can you post output of an attempt to push
with GIT_CURL_VERBOSE=1?

-- 
brian m. carlson / brian with sandals: Houston, Texas, US
+1 832 623 2791 | http://www.crustytoothpaste.net/~bmc | My opinion only
OpenPGP: RSA v4 4096b: 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187


signature.asc
Description: Digital signature


GIT, libcurl and GSS-Negotiate

2014-04-24 Thread Ivo Bellin Salarin
Hello,

I'm having problems while trying to authenticate against a TFS hosted
repository.

I experience the same problem in git for windows and in git for linux
(both versions are 1.9.2).

The problem is described on a [github msysgit/git
issue](https://github.com/msysgit/git/issues/171)

To shortly resume it, the problem is that:
* when the authentication method (WWW-Authenticate) is Negotiate AND
* when the server proposes a NTLMSSP_CHALLENGE in response of the
client's NTLMSSP_NEGOTIATE,
= libcurl yields an Authentication problem. Ignoring this.\n
And the communication is closed.

At this point, in a normal communication, the client should send a
NTLMSSP_AUTH containing a Kerberos ticket.

Having seen the libcurl source code, I think we're passing through the
lines  from 776 to 780 of
[http.c](https://github.com/bagder/curl/blob/2e57c7e0fcfb9214b2a9dfa8b3da258ded013b8a/lib/http.c).
Some guy, on the github issue page, has suggested that this could be
related to an update of libcurl, when git was at its 1.8.2 version.

I'm not debugging libcurl, and I can't reproduce this problem @home.
So, has somebody already experienced the same problem? Is there a
solution?

Many thanks in advance,
Ivo
-- 
http://www.nilleb.com
--
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