git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* git smart-http do not authent to allow git ls-remote to be called anonymously
@ 2012-09-30 14:35 乙酸鋰
  2012-10-01  0:53 ` Shawn Pearce
  2012-10-01  1:09 ` Jeff King
  0 siblings, 2 replies; 7+ messages in thread
From: 乙酸鋰 @ 2012-09-30 14:35 UTC (permalink / raw)
  To: git

Hi,

I use smart-http on Apache.
If nothing to be pushed / pulled, I do not want password to be
supplied. And allow git ls-remote to run without password

*.git/info/refs?service=git-upload-pack
*.git/info/refs?service=git-receive-pack

I only need authentication on

*.git/git-upload-pack
*.git/git-receive-pack

/etc/apache/httpd.conf

<LocationMatch "^/git/.*/git-(upload|receive)-pack$">
    AuthType Basic
    AuthName "staff only"
    AuthUserFile /etc/apache/apache.pwd
    Require valid-user
</LocationMatch>

However this does not work. It does not ask for password at all.

I use Ubuntu 10.04, Apache 2.2.14, Git 1.7.11.3.

Directory structure: any depth (more than 1 subdir) of path from /git
to .git folders

Could you advise how to configure this? Is this a bug?

Regards,
ch3cooli

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: git smart-http do not authent to allow git ls-remote to be called anonymously
  2012-09-30 14:35 git smart-http do not authent to allow git ls-remote to be called anonymously 乙酸鋰
@ 2012-10-01  0:53 ` Shawn Pearce
  2012-10-01  1:09 ` Jeff King
  1 sibling, 0 replies; 7+ messages in thread
From: Shawn Pearce @ 2012-10-01  0:53 UTC (permalink / raw)
  To: 乙酸鋰; +Cc: git

On Sun, Sep 30, 2012 at 7:35 AM, 乙酸鋰 <ch3cooli@gmail.com> wrote:
> I use smart-http on Apache.
> If nothing to be pushed / pulled, I do not want password to be
> supplied. And allow git ls-remote to run without password
>
> *.git/info/refs?service=git-upload-pack
> *.git/info/refs?service=git-receive-pack
>
> I only need authentication on
>
> *.git/git-upload-pack
> *.git/git-receive-pack
>
> /etc/apache/httpd.conf
>
> <LocationMatch "^/git/.*/git-(upload|receive)-pack$">
>     AuthType Basic
>     AuthName "staff only"
>     AuthUserFile /etc/apache/apache.pwd
>     Require valid-user
> </LocationMatch>
>
> However this does not work. It does not ask for password at all.

This sounds like a bug in your Apache configuration. I would verify it
prompts for a password as expected before worrying about the Git
client:

  curl -v http://localhost/git/blah/git-upload-pack

should fail with a 401 requesting access to "staff only". Once this is
working, git will present authorization as necessary during the
/git-upload-pack|git-receive-pack calls.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: git smart-http do not authent to allow git ls-remote to be called anonymously
  2012-09-30 14:35 git smart-http do not authent to allow git ls-remote to be called anonymously 乙酸鋰
  2012-10-01  0:53 ` Shawn Pearce
@ 2012-10-01  1:09 ` Jeff King
       [not found]   ` <CAHtLG6QFu1rOfUeWREwVG540WvXtM1SnH6aHEJ9dKLzwNxbkVg@mail.gmail.com>
  1 sibling, 1 reply; 7+ messages in thread
From: Jeff King @ 2012-10-01  1:09 UTC (permalink / raw)
  To: 乙酸鋰; +Cc: Shawn O. Pearce, git

On Sun, Sep 30, 2012 at 10:35:35PM +0800, 乙酸鋰 wrote:

> I use smart-http on Apache.
> If nothing to be pushed / pulled, I do not want password to be
> supplied. And allow git ls-remote to run without password
> 
> *.git/info/refs?service=git-upload-pack
> *.git/info/refs?service=git-receive-pack
> 
> I only need authentication on
> 
> *.git/git-upload-pack
> *.git/git-receive-pack
> 
> /etc/apache/httpd.conf
> 
> <LocationMatch "^/git/.*/git-(upload|receive)-pack$">
>     AuthType Basic
>     AuthName "staff only"
>     AuthUserFile /etc/apache/apache.pwd
>     Require valid-user
> </LocationMatch>
> 
> However this does not work. It does not ask for password at all.

What is "it" in the final sentence? Does the server not tell the git
client that authorization is required, and actually serve the request?
If so, then that is a bug in your apache config.

Or is it that the server tells git that it needs authorization, but git
does not prompt, and instead just fails with "Authentication failed". In
that case, the issue is that you need a newer git client. Traditionally
the client expected to handle authentication during the initial
"info/refs" request. I added support for handling authentication during
later requests in commit b81401c, which is in git v1.7.11.7 and
v1.7.12.1.

You should reconsider whether this is what you really want, though. With
the configuration you showed, anyone will be able to get a list of all
refs and their sha1s. So they would know all your branch names, and they
could even potentially find out what's in your branches by making
offline guesses and comparing them to your branch sha1s (the feasibility
of this would depend on exactly what you're storing).

-Peff

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: git smart-http do not authent to allow git ls-remote to be called anonymously
       [not found]     ` <CAHtLG6T=hFsSy=ScRK2cYBoUcmAG_tsg12FiFMTvzpHGmPTzfg@mail.gmail.com>
@ 2012-10-14  6:30       ` Jeff King
       [not found]         ` <CAHtLG6QR4CtC3RkVE3FQXhrZPJem6SZbrJFyn9K_4yHzhzYt1Q@mail.gmail.com>
  0 siblings, 1 reply; 7+ messages in thread
From: Jeff King @ 2012-10-14  6:30 UTC (permalink / raw)
  To: 乙酸鋰; +Cc: git

[re-adding git@vger; please keep discussion on-list]

On Sun, Oct 14, 2012 at 01:29:13PM +0800, 乙酸鋰 wrote:

> Sorry, it does not serve the request. It returns http 401.
> But if I add the username and password as a part of the URL, it succeeds.

In that case, then you probably need to upgrade your client version of
git, as I mentioned here:

> >> Or is it that the server tells git that it needs authorization, but git
> >> does not prompt, and instead just fails with "Authentication failed". In
> >> that case, the issue is that you need a newer git client. Traditionally
> >> the client expected to handle authentication during the initial
> >> "info/refs" request. I added support for handling authentication during
> >> later requests in commit b81401c, which is in git v1.7.11.7 and
> >> v1.7.12.1.

-Peff

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: git smart-http do not authent to allow git ls-remote to be called anonymously
       [not found]             ` <CAHtLG6SsMgwquaD_Rd0YvR9Ues-u1ktEdOXC2MAfEM9Naac=5g@mail.gmail.com>
@ 2012-10-31 11:53               ` Jeff King
  2012-10-31 11:55                 ` [PATCH 1/2] remote-curl: hoist gzip buffer size to top of post_rpc Jeff King
  2012-10-31 12:01                 ` [PATCH 2/2] remote-curl: retry failed requests for auth even with gzip Jeff King
  0 siblings, 2 replies; 7+ messages in thread
From: Jeff King @ 2012-10-31 11:53 UTC (permalink / raw)
  To: 乙酸鋰; +Cc: git

[+cc git@vger; please keep discussion on the list]

On Sun, Oct 28, 2012 at 01:26:51PM +0800, 乙酸鋰 wrote:

> > POST /git/Cat1/SubCat1/xsp.git/git-upload-pack HTTP/1.1
> User-Agent: git/1.8.0
> Host: localhost
> Accept-Encoding: gzip
> Content-Type: application/x-git-upload-pack-request
> Accept: application/x-git-upload-pack-result
> Content-Length: 190
> 
> * The requested URL returned error: 401
> * Closing connection #0
> Username for 'http://localhost': user
> Password for 'http://user@localhost':
> fatal: The remote end hung up unexpectedly

OK, I see what is going on. The code in b81401c to retry POST requests
does not handle gzipped contents, and upload-pack tends to gzip what it
sends.

Your apache configuration is not really something that we ever intended
to support, and I am a little dubious of the security tradeoff being
made. But it is actually pretty easy for us to support, and it
eliminates a special case from the code, so I am tempted to do so.

The following patch series (on top of the current master, as they
require some cleanup that did not make it into 1.8.0) seems to fix it
for me.

  [1/2]: remote-curl: hoist gzip buffer size to top of post_rpc
  [2/2]: remote-curl: retry failed requests for auth even with gzip

-Peff

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/2] remote-curl: hoist gzip buffer size to top of post_rpc
  2012-10-31 11:53               ` Jeff King
@ 2012-10-31 11:55                 ` Jeff King
  2012-10-31 12:01                 ` [PATCH 2/2] remote-curl: retry failed requests for auth even with gzip Jeff King
  1 sibling, 0 replies; 7+ messages in thread
From: Jeff King @ 2012-10-31 11:55 UTC (permalink / raw)
  To: 乙酸鋰; +Cc: git

When we gzip the post data for a smart-http rpc request, we
compute the gzip body and its size inside the "use_gzip"
conditional. We keep track of the body after the conditional
ends, but not the size. Let's remember both, which will
enable us to retry failed gzip requests in a future patch.

Signed-off-by: Jeff King <peff@peff.net>
---
This is a tiny change conceptually, but the name change makes the diff
quite noisy. Thus I pulled it into a separate patch from 2/2.

 remote-curl.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/remote-curl.c b/remote-curl.c
index aefafd3..10cd47d 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -413,6 +413,7 @@ static int post_rpc(struct rpc_state *rpc)
 	struct curl_slist *headers = NULL;
 	int use_gzip = rpc->gzip_request;
 	char *gzip_body = NULL;
+	size_t gzip_size;
 	int err, large_request = 0;
 
 	/* Try to load the entire request, if we can fit it into the
@@ -478,19 +479,18 @@ retry:
 		 * we can try to deflate it ourselves, this may save on.
 		 * the transfer time.
 		 */
-		size_t size;
 		git_zstream stream;
 		int ret;
 
 		memset(&stream, 0, sizeof(stream));
 		git_deflate_init_gzip(&stream, Z_BEST_COMPRESSION);
-		size = git_deflate_bound(&stream, rpc->len);
-		gzip_body = xmalloc(size);
+		gzip_size = git_deflate_bound(&stream, rpc->len);
+		gzip_body = xmalloc(gzip_size);
 
 		stream.next_in = (unsigned char *)rpc->buf;
 		stream.avail_in = rpc->len;
 		stream.next_out = (unsigned char *)gzip_body;
-		stream.avail_out = size;
+		stream.avail_out = gzip_size;
 
 		ret = git_deflate(&stream, Z_FINISH);
 		if (ret != Z_STREAM_END)
@@ -500,16 +500,16 @@ retry:
 		if (ret != Z_OK)
 			die("cannot deflate request; zlib end error %d", ret);
 
-		size = stream.total_out;
+		gzip_size = stream.total_out;
 
 		headers = curl_slist_append(headers, "Content-Encoding: gzip");
 		curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, gzip_body);
-		curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, size);
+		curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, gzip_size);
 
 		if (options.verbosity > 1) {
 			fprintf(stderr, "POST %s (gzip %lu to %lu bytes)\n",
 				rpc->service_name,
-				(unsigned long)rpc->len, (unsigned long)size);
+				(unsigned long)rpc->len, (unsigned long)gzip_size);
 			fflush(stderr);
 		}
 	} else {
-- 
1.8.0.207.gdf2154c

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/2] remote-curl: retry failed requests for auth even with gzip
  2012-10-31 11:53               ` Jeff King
  2012-10-31 11:55                 ` [PATCH 1/2] remote-curl: hoist gzip buffer size to top of post_rpc Jeff King
@ 2012-10-31 12:01                 ` Jeff King
  1 sibling, 0 replies; 7+ messages in thread
From: Jeff King @ 2012-10-31 12:01 UTC (permalink / raw)
  To: 乙酸鋰; +Cc: git

Commit b81401c taught the post_rpc function to retry the
http request after prompting for credentials. However, it
did not handle two cases:

  1. If we have a large request, we do not retry. That's OK,
     since we would have sent a probe (with retry) already.

  2. If we are gzipping the request, we do not retry. That
     was considered OK, because the intended use was for
     push (e.g., listing refs is OK, but actually pushing
     objects is not), and we never gzip on push.

This patch teaches post_rpc to retry even a gzipped request.
This has two advantages:

  1. It is possible to configure a "half-auth" state for
     fetching, where the set of refs and their sha1s are
     advertised, but one cannot actually fetch objects.

     This is not a recommended configuration, as it leaks
     some information about what is in the repository (e.g.,
     an attacker can try brute-forcing possible content in
     your repository and checking whether it matches your
     branch sha1). However, it can be slightly more
     convenient, since a no-op fetch will not require a
     password at all.

  2. It future-proofs us should we decide to ever gzip more
     requests.

Signed-off-by: Jeff King <peff@peff.net>
---
I doubt we would ever want to gzip push requests. The bulk of the data
is objects, which are already compressed. In theory we could gzip the
non-pack parts, but that would first mean splitting them into a separate
request. The tiny bit of savings are almost certainly not worth the
complexity.

But the future-proofing might still be valuable if we ever modify the
protocol to have a new phase.

 remote-curl.c           | 11 ++++++++++-
 t/lib-httpd/apache.conf |  7 +++++++
 t/t5551-http-fetch.sh   | 15 +++++++++++++++
 3 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/remote-curl.c b/remote-curl.c
index 10cd47d..fac2bef 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -474,6 +474,15 @@ retry:
 			fflush(stderr);
 		}
 
+	} else if (gzip_body) {
+		/*
+		 * If we are looping to retry authentication, then the previous
+		 * run will have set up the headers and gzip buffer already,
+		 * and we just need to send it.
+		 */
+		curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, gzip_body);
+		curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, gzip_size);
+
 	} else if (use_gzip && 1024 < rpc->len) {
 		/* The client backend isn't giving us compressed data so
 		 * we can try to deflate it ourselves, this may save on.
@@ -530,7 +539,7 @@ retry:
 	curl_easy_setopt(slot->curl, CURLOPT_FILE, rpc);
 
 	err = run_slot(slot);
-	if (err == HTTP_REAUTH && !large_request && !use_gzip)
+	if (err == HTTP_REAUTH && !large_request)
 		goto retry;
 	if (err != HTTP_OK)
 		err = -1;
diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf
index ec8618d..15a3c71 100644
--- a/t/lib-httpd/apache.conf
+++ b/t/lib-httpd/apache.conf
@@ -96,6 +96,13 @@ SSLEngine On
 	Require valid-user
 </LocationMatch>
 
+<LocationMatch "^/auth-fetch/.*/git-upload-pack$">
+	AuthType Basic
+	AuthName "git-auth"
+	AuthUserFile passwd
+	Require valid-user
+</LocationMatch>
+
 <IfDefine DAV>
 	LoadModule dav_module modules/mod_dav.so
 	LoadModule dav_fs_module modules/mod_dav_fs.so
diff --git a/t/t5551-http-fetch.sh b/t/t5551-http-fetch.sh
index 7380f2a..5f174da 100755
--- a/t/t5551-http-fetch.sh
+++ b/t/t5551-http-fetch.sh
@@ -129,6 +129,21 @@ test_expect_success 'clone from auth-only-for-push repository' '
 	test_cmp expect actual
 '
 
+test_expect_success 'clone from auth-only-for-objects repository' '
+	echo two >expect &&
+	set_askpass user@host &&
+	git clone --bare "$HTTPD_URL/auth-fetch/smart/repo.git" half-auth &&
+	expect_askpass both user@host &&
+	git --git-dir=half-auth log -1 --format=%s >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'no-op half-auth fetch does not require a password' '
+	set_askpass wrong &&
+	git --git-dir=half-auth fetch &&
+	expect_askpass none
+'
+
 test -n "$GIT_TEST_LONG" && test_set_prereq EXPENSIVE
 
 test_expect_success EXPENSIVE 'create 50,000 tags in the repo' '
-- 
1.8.0.207.gdf2154c

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2012-10-31 12:01 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-30 14:35 git smart-http do not authent to allow git ls-remote to be called anonymously 乙酸鋰
2012-10-01  0:53 ` Shawn Pearce
2012-10-01  1:09 ` Jeff King
     [not found]   ` <CAHtLG6QFu1rOfUeWREwVG540WvXtM1SnH6aHEJ9dKLzwNxbkVg@mail.gmail.com>
     [not found]     ` <CAHtLG6T=hFsSy=ScRK2cYBoUcmAG_tsg12FiFMTvzpHGmPTzfg@mail.gmail.com>
2012-10-14  6:30       ` Jeff King
     [not found]         ` <CAHtLG6QR4CtC3RkVE3FQXhrZPJem6SZbrJFyn9K_4yHzhzYt1Q@mail.gmail.com>
     [not found]           ` <20121026134907.GK1455@sigill.intra.peff.net>
     [not found]             ` <CAHtLG6SsMgwquaD_Rd0YvR9Ues-u1ktEdOXC2MAfEM9Naac=5g@mail.gmail.com>
2012-10-31 11:53               ` Jeff King
2012-10-31 11:55                 ` [PATCH 1/2] remote-curl: hoist gzip buffer size to top of post_rpc Jeff King
2012-10-31 12:01                 ` [PATCH 2/2] remote-curl: retry failed requests for auth even with gzip Jeff King

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).