git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 4/4] git-daemon support for user-relative paths.
@ 2005-11-01 22:59 Andreas Ericsson
  2005-11-02  0:14 ` Junio C Hamano
  0 siblings, 1 reply; 6+ messages in thread
From: Andreas Ericsson @ 2005-11-01 22:59 UTC (permalink / raw)


Dropped a fair amount of redundant functionality in favour of the library
code in path.c. git-upload-pack is now called with canonicalized paths.

Added option --strict-paths to retain old behaviour (documented).

Signed-off-by: Andreas Ericsson <ae@op5.se>

---

 Documentation/git-daemon.txt |   17 +++++-
 daemon.c                     |  128 ++++++++++++++----------------------------
 2 files changed, 58 insertions(+), 87 deletions(-)

applies-to: c40ce0cb704af8d7d1d655bcf709e7621db60e0e
e35eb905a06718894a6c79f73d763122fff2a61a
diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt
index 67c5f22..25f03df 100644
--- a/Documentation/git-daemon.txt
+++ b/Documentation/git-daemon.txt
@@ -8,7 +8,7 @@ git-daemon - A really simple server for 
 SYNOPSIS
 --------
 'git-daemon' [--verbose] [--syslog] [--inetd | --port=n] [--export-all]
-             [--timeout=n] [--init-timeout=n] [directory...]
+             [--timeout=n] [--init-timeout=n] [--strict-paths] [directory...]
 
 DESCRIPTION
 -----------
@@ -29,10 +29,16 @@ This is ideally suited for read-only upd
 
 OPTIONS
 -------
+--strict-paths::
+	Match paths exactly (i.e. don't allow "/foo/repo" when the real path is
+	"/foo/repo.git" or "/foo/repo/.git") and don't do user-relative paths.
+	git-daemon will refuse to start when this option is enabled and no
+	whitelist is specified.
+
 --export-all::
 	Allow pulling from all directories that look like GIT repositories
-	(have the 'objects' subdirectory and a 'HEAD' file), even if they
-	do not have the 'git-daemon-export-ok' file.
+	(have the 'objects' and 'refs' subdirectories as well as a 'HEAD' file),
+	even if they do not have the 'git-daemon-export-ok' file.
 
 --inetd::
 	Have the server run as an inetd service.
@@ -57,6 +63,11 @@ OPTIONS
 --verbose::
 	Log details about the incoming connections and requested files.
 
+<directory>::
+	A directory to add to the whitelist of allowed directory. Unless
+	--strict-paths is specified this will also include subdirectories
+	of each named directory.
+	
 Author
 ------
 Written by Linus Torvalds <torvalds@osdl.org> and YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
diff --git a/daemon.c b/daemon.c
index c3f8641..7b36363 100644
--- a/daemon.c
+++ b/daemon.c
@@ -10,16 +10,18 @@
 #include "pkt-line.h"
 #include "cache.h"
 
-static int log_syslog;
+static int log_syslog = 0;
 static int verbose;
 
 static const char daemon_usage[] =
 "git-daemon [--verbose] [--syslog] [--inetd | --port=n] [--export-all]\n"
-"           [--timeout=n] [--init-timeout=n] [directory...]";
+"           [--timeout=n] [--init-timeout=n] [--strict-paths] [directory...]";
 
 /* List of acceptable pathname prefixes */
 static char **ok_paths = NULL;
 
+static int strict_paths = 0;
+
 /* If this is set, git-daemon-export-ok is not required */
 static int export_all_trees = 0;
 
@@ -81,69 +83,49 @@ static void loginfo(const char *err, ...
 	va_end(params);
 }
 
-static int path_ok(const char *dir)
+static const char *path_ok(const char *dir)
 {
-	const char *p = dir;
-	char **pp;
-	int sl, ndot;
-
-	/* The pathname here should be an absolute path. */
-	if ( *p++ != '/' )
-		return 0;
-
-	sl = 1;  ndot = 0;
-
-	for (;;) {
-		if ( *p == '.' ) {
-			ndot++;
-		} else if ( *p == '\0' ) {
-			/* Reject "." and ".." at the end of the path */
-			if ( sl && ndot > 0 && ndot < 3 )
-				return 0;
+	const char *path = is_git_repo(dir, strict_paths);
 
-			/* Otherwise OK */
-			break;
-		} else if ( *p == '/' ) {
-			/* Refuse "", "." or ".." */
-			if ( sl && ndot < 3 )
-				return 0;
-			sl = 1;
-			ndot = 0;
-		} else {
-			sl = ndot = 0;
-		}
-		p++;
+	/* No such directory or not a git archive */
+	if(!path) {
+		logerror("'%s': unable to chdir or not a git archive", dir);
+		return NULL;
 	}
 
 	if ( ok_paths && *ok_paths ) {
-		int ok = 0;
-		int dirlen = strlen(dir);
+		char **pp = NULL;
+		int dirlen = strlen(path);
 
 		for ( pp = ok_paths ; *pp ; pp++ ) {
 			int len = strlen(*pp);
-			if ( len <= dirlen &&
-			     !strncmp(*pp, dir, len) &&
-			     (dir[len] == '/' || dir[len] == '\0') ) {
-				ok = 1;
-				break;
+			if ( len <= dirlen && !strncmp(*pp, path, len) ) {
+				if( path[len] == '\0' || (!strict_paths && path[len] == '/') )
+					return path;
 			}
 		}
-
-		if ( !ok )
-			return 0; /* Path not in whitelist */
+	}
+	else {
+		/* Be backwards compatible */
+		if(!strict_paths)
+			return path;
 	}
 
-	return 1;		/* Path acceptable */
+	logerror("'%s': not in whitelist", path);
+	return NULL;		/* Fallthrough. Deny by default */
 }
 
-static int set_dir(const char *dir)
+static int upload(char *dir)
 {
-	if (!path_ok(dir)) {
-		errno = EACCES;
-		return -1;
-	}
+	/* Timeout as string */
+	char timeout_buf[64];
+	const char *path;
+
+	loginfo("Request for '%s'", dir);
 
-	if ( chdir(dir) )
+	/* path_ok() canonicalizes the path, chdir()'s
+	 * and does whitelist checking */
+	if(!(path = path_ok(dir)))
 		return -1;
 
 	/*
@@ -152,45 +134,16 @@ static int set_dir(const char *dir)
 	 * We want a readable HEAD, usable "objects" directory, and
 	 * a "git-daemon-export-ok" flag that says that the other side
 	 * is ok with us doing this.
+	 *
+	 * path_ok() uses is_git_repo() though, so we only need to
+	 * check if the path is exported.
 	 */
 	if (!export_all_trees && access("git-daemon-export-ok", F_OK)) {
+		logerror("'%s': not exported", path);
 		errno = EACCES;
 		return -1;
 	}
 
-	if (access("objects/", X_OK) || access("HEAD", R_OK)) {
-		errno = EINVAL;
-		return -1;
-	}
-
-	/* If all this passed, we're OK */
-	return 0;
-}
-
-static int upload(char *dir)
-{
-	/* Try paths in this order */
-	static const char *paths[] = { "%s", "%s/.git", "%s.git", "%s.git/.git", NULL };
-	const char **pp;
-	/* Enough for the longest path above including final null */
-	int buflen = strlen(dir)+10;
-	char *dirbuf = xmalloc(buflen);
-	/* Timeout as string */
-	char timeout_buf[64];
-
-	loginfo("Request for '%s'", dir);
-
-	for ( pp = paths ; *pp ; pp++ ) {
-		snprintf(dirbuf, buflen, *pp, dir);
-		if ( !set_dir(dirbuf) )
-			break;
-	}
-
-	if ( !*pp ) {
-		logerror("Cannot set directory '%s': %s", dir, strerror(errno));
-		return -1;
-	}
-
 	/*
 	 * We'll ignore SIGTERM from now on, we have a
 	 * good client.
@@ -200,7 +153,7 @@ static int upload(char *dir)
 	snprintf(timeout_buf, sizeof timeout_buf, "--timeout=%u", timeout);
 
 	/* git-upload-pack only ever reads stuff, so this is safe */
-	execlp("git-upload-pack", "git-upload-pack", "--strict", timeout_buf, ".", NULL);
+	execlp("git-upload-pack", "git-upload-pack", "--strict", timeout_buf, path, NULL);
 	return -1;
 }
 
@@ -216,7 +169,7 @@ static int execute(void)
 	if (len && line[len-1] == '\n')
 		line[--len] = 0;
 
-	if (!strncmp("git-upload-pack /", line, 17))
+	if (!strncmp("git-upload-pack ", line, 16))
 		return upload(line+16);
 
 	logerror("Protocol error: '%s'", line);
@@ -615,6 +568,10 @@ int main(int argc, char **argv)
 		if (!strncmp(arg, "--init-timeout=", 15)) {
 			init_timeout = atoi(arg+15);
 		}
+		if (!strcmp(arg, "--strict-paths")) {
+			strict_paths = 1;
+			continue;
+		}
 		if (!strcmp(arg, "--")) {
 			ok_paths = &argv[i+1];
 			break;
@@ -626,6 +583,9 @@ int main(int argc, char **argv)
 		usage(daemon_usage);
 	}
 
+	if(strict_paths && (!ok_paths || !*ok_paths))
+		die("git-daemon: option --strict-paths requires a whitelist");
+
 	if (inetd_mode) {
 		fclose(stderr); //FIXME: workaround
 		return execute();
---
0.99.9.GIT

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

* Re: [PATCH 4/4] git-daemon support for user-relative paths.
  2005-11-01 22:59 [PATCH 4/4] git-daemon support for user-relative paths Andreas Ericsson
@ 2005-11-02  0:14 ` Junio C Hamano
  2005-11-02  8:17   ` Andreas Ericsson
  2005-11-02  8:21   ` Andreas Ericsson
  0 siblings, 2 replies; 6+ messages in thread
From: Junio C Hamano @ 2005-11-02  0:14 UTC (permalink / raw)
  To: Andreas Ericsson; +Cc: git

Andreas Ericsson <ae@op5.se> writes:

> +             [--timeout=n] [--init-timeout=n] [--strict-paths] [directory...]

Why not just --strict?

> @@ -10,16 +10,18 @@
>  #include "pkt-line.h"
>  #include "cache.h"
>  
> -static int log_syslog;
> +static int log_syslog = 0;

I'd drop this.

>  /* If this is set, git-daemon-export-ok is not required */
>  static int export_all_trees = 0;
>  
> @@ -81,69 +83,49 @@ static void loginfo(const char *err, ...
>  	va_end(params);
>  }
>  
> -static int path_ok(const char *dir)
> +static const char *path_ok(const char *dir)
>  {
> +	const char *path = is_git_repo(dir, strict_paths);
> +	/* No such directory or not a git archive */
> +	if(!path) {
> +		logerror("'%s': unable to chdir or not a git archive", dir);
> +		return NULL;
>  	}
>  
>  	if ( ok_paths && *ok_paths ) {
> +		char **pp = NULL;
> +		int dirlen = strlen(path);
>  
>  		for ( pp = ok_paths ; *pp ; pp++ ) {
>  			int len = strlen(*pp);
> +			if ( len <= dirlen && !strncmp(*pp, path, len) ) {
> +				if( path[len] == '\0' || (!strict_paths && path[len] == '/') )
> +					return path;
>  			}
>  		}

Sorry, but I am a bit confused.  Does this mean that you need to
list all directories under --strict-paths, instead of saying
"/pub/scm and everything under it is OK"?

I like the general direction this set is taking, but let's let
it simmer for a while.

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

* Re: [PATCH 4/4] git-daemon support for user-relative paths.
  2005-11-02  0:14 ` Junio C Hamano
@ 2005-11-02  8:17   ` Andreas Ericsson
  2005-11-02  9:30     ` Junio C Hamano
  2005-11-02  8:21   ` Andreas Ericsson
  1 sibling, 1 reply; 6+ messages in thread
From: Andreas Ericsson @ 2005-11-02  8:17 UTC (permalink / raw)
  To: git

Junio C Hamano wrote:
> Andreas Ericsson <ae@op5.se> writes:
> 
> 
>>+             [--timeout=n] [--init-timeout=n] [--strict-paths] [directory...]
> 
> 
> Why not just --strict?
> 
> 
>>@@ -10,16 +10,18 @@
>> #include "pkt-line.h"
>> #include "cache.h"
>> 
>>-static int log_syslog;
>>+static int log_syslog = 0;
> 
> 
> I'd drop this.
> 

No can do. It has to be set either here or down in main. It's nice to 
have the default in the declaration.

> 
>> /* If this is set, git-daemon-export-ok is not required */
>> static int export_all_trees = 0;
>> 
>>@@ -81,69 +83,49 @@ static void loginfo(const char *err, ...
>> 	va_end(params);
>> }
>> 
>>-static int path_ok(const char *dir)
>>+static const char *path_ok(const char *dir)
>> {
>>+	const char *path = is_git_repo(dir, strict_paths);
>>+	/* No such directory or not a git archive */
>>+	if(!path) {
>>+		logerror("'%s': unable to chdir or not a git archive", dir);
>>+		return NULL;
>> 	}
>> 
>> 	if ( ok_paths && *ok_paths ) {
>>+		char **pp = NULL;
>>+		int dirlen = strlen(path);
>> 
>> 		for ( pp = ok_paths ; *pp ; pp++ ) {
>> 			int len = strlen(*pp);
>>+			if ( len <= dirlen && !strncmp(*pp, path, len) ) {
>>+				if( path[len] == '\0' || (!strict_paths && path[len] == '/') )
>>+					return path;
>> 			}
>> 		}
> 
> 
> Sorry, but I am a bit confused.  Does this mean that you need to
> list all directories under --strict-paths, instead of saying
> "/pub/scm and everything under it is OK"?
> 

Only if --strict-paths is set, otherwise it works as usual. It's 
documented in the man-page, but perhaps it's a bit too paranoid.

> I like the general direction this set is taking, but let's let
> it simmer for a while.
> 

Ok. I'll take that to mean "hold off on the --server-root and --userdir 
patch for a while" then.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231

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

* Re: [PATCH 4/4] git-daemon support for user-relative paths.
  2005-11-02  0:14 ` Junio C Hamano
  2005-11-02  8:17   ` Andreas Ericsson
@ 2005-11-02  8:21   ` Andreas Ericsson
  1 sibling, 0 replies; 6+ messages in thread
From: Andreas Ericsson @ 2005-11-02  8:21 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

Junio C Hamano wrote:
> Andreas Ericsson <ae@op5.se> writes:
> 
> 
>>+             [--timeout=n] [--init-timeout=n] [--strict-paths] [directory...]
> 
> 
> Why not just --strict?
> 

It's a bit clearer what it is that's strict, and allows for future 
--strict-* options to be added without breaking anyones init-scripts.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231

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

* Re: [PATCH 4/4] git-daemon support for user-relative paths.
  2005-11-02  8:17   ` Andreas Ericsson
@ 2005-11-02  9:30     ` Junio C Hamano
  2005-11-02  9:39       ` Andreas Ericsson
  0 siblings, 1 reply; 6+ messages in thread
From: Junio C Hamano @ 2005-11-02  9:30 UTC (permalink / raw)
  To: Andreas Ericsson; +Cc: git

Andreas Ericsson <ae@op5.se> writes:

> Junio C Hamano wrote:
>>> -static int log_syslog;
>>>+static int log_syslog = 0;
>> I'd drop this.
>
> No can do. It has to be set either here or down in main. It's nice to 
> have the default in the declaration.

Isn't "static int log_syslog" in BSS to be initialized to zero anyway?

>> I like the general direction this set is taking, but let's let
>> it simmer for a while.
>
> Ok. I'll take that to mean "hold off on the --server-root and --userdir 
> patch for a while" then.

I do not mind keeping it in the proposed updates branch for
people to see and experiment with, but not in the master branch,
at least for now.

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

* Re: [PATCH 4/4] git-daemon support for user-relative paths.
  2005-11-02  9:30     ` Junio C Hamano
@ 2005-11-02  9:39       ` Andreas Ericsson
  0 siblings, 0 replies; 6+ messages in thread
From: Andreas Ericsson @ 2005-11-02  9:39 UTC (permalink / raw)
  To: git

Junio C Hamano wrote:
> Andreas Ericsson <ae@op5.se> writes:
> 
> 
>>Junio C Hamano wrote:
>>
>>>>-static int log_syslog;
>>>>+static int log_syslog = 0;
>>>
>>>I'd drop this.
>>
>>No can do. It has to be set either here or down in main. It's nice to 
>>have the default in the declaration.
> 
> 
> Isn't "static int log_syslog" in BSS to be initialized to zero anyway?
> 

I would have thought so, but it wasn't when I tested it. This could be a 
compiler-bug in my end, I suppose, but spelling it out enhances 
readability and leaves no room for doubt which is always nice.

>>
>>Ok. I'll take that to mean "hold off on the --server-root and --userdir 
>>patch for a while" then.
> 
> 
> I do not mind keeping it in the proposed updates branch for
> people to see and experiment with, but not in the master branch,
> at least for now.
> 

I'll cook it up then.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231

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

end of thread, other threads:[~2005-11-02  9:39 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-11-01 22:59 [PATCH 4/4] git-daemon support for user-relative paths Andreas Ericsson
2005-11-02  0:14 ` Junio C Hamano
2005-11-02  8:17   ` Andreas Ericsson
2005-11-02  9:30     ` Junio C Hamano
2005-11-02  9:39       ` Andreas Ericsson
2005-11-02  8:21   ` Andreas Ericsson

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 NNTP newsgroup(s).