git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 3/3] daemon: Support a --user-path option.

From
MWMark Wooding <mdw@distorted.org.uk>
Date
Feb 3, 2006, 20:27 UTC
Message-ID
<20060203202706.1895.70864.stgit@metalzone.distorted.org.uk>
In-Reply-To
<20060203202330.1895.60474.stgit@metalzone.distorted.org.uk>
From: Mark Wooding <mwooding@ponder.ncipher.com>

If we're invoked with --user-path=FOO option, then a URL of the form git://~USER/PATH/... resolves to the path HOME/FOO/PATH/..., where HOME is USER's home directory. This is done instead of any transformation due to --base-path, so you can use both at the same time. This lets users set up their own git repositories to be served by a central daemon, without them all having to be in the same place, and without the git-daemon being allowed to roam the entire filesystem freely, or exposing details of filesystem layout on URLs.

Signed-off-by: Mark Wooding <mdw@distorted.org.uk>
---
 Documentation/git-daemon.txt |   11 +++++++++--
 daemon.c                     |   36 +++++++++++++++++++++++++++++++++---
 2 files changed, 42 insertions(+), 5 deletions(-)
diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt
index a20e053..2e48a10 100644
--- a/Documentation/git-daemon.txt
+++ b/Documentation/git-daemon.txt
@@ -10,7 +10,7 @@ SYNOPSIS
 [verse]
 'git-daemon' [--verbose] [--syslog] [--inetd | --port=n] [--export-all]
              [--timeout=n] [--init-timeout=n] [--strict-paths]
-             [--base-path=path] [directory...]
+             [--base-path=path] [--user-path=path] [directory...]
 
 DESCRIPTION
 -----------
@@ -43,7 +43,7 @@ OPTIONS
 	'--base-path=/srv/git' on example.com, then if you later try to pull
 	'git://example.com/hello.git', `git-daemon` will interpret the path
 	as '/srv/git/hello.git'. Home directories (the '~login' notation)
-	access is disabled.
+	access is disabled unless '--user-path' is also given.
 
 --export-all::
 	Allow pulling from all directories that look like GIT repositories
@@ -70,6 +70,13 @@ OPTIONS
 	Log to syslog instead of stderr. Note that this option does not imply
 	--verbose, thus by default only error conditions will be logged.
 
+--user-path::
+	Rewrite a request for "~user/something" to
+	"home/user-path/something".  Useful in conjunction with
+	'--base-path', if you want to restrict the daemon from roaming
+	the entire filesystem without preventing users from publishing
+	their own repositories.
+
 --verbose::
 	Log details about the incoming connections and requested files.
 
diff --git a/daemon.c b/daemon.c
index 6b88c0c..95b9c7e 100644
--- a/daemon.c
+++ b/daemon.c
@@ -6,6 +6,7 @@
 #include <netdb.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <pwd.h>
 #include <syslog.h>
 #include "pkt-line.h"
 #include "cache.h"
@@ -17,7 +18,7 @@ static int verbose;
 static const char daemon_usage[] =
 "git-daemon [--verbose] [--syslog] [--inetd | --port=n] [--export-all]\n"
 "           [--timeout=n] [--init-timeout=n] [--strict-paths]\n"
-"           [--base-path=path] [directory...]";
+"           [--base-path=path] [--user-path=path] [directory...]";
 
 /* List of acceptable pathname prefixes */
 static char **ok_paths = NULL;
@@ -28,6 +29,7 @@ static int export_all_trees = 0;
 
 /* Take all paths relative to this one if non-NULL */
 static char *base_path = NULL;
+static char *user_path = NULL;
 
 /* Timeout, and initial timeout */
 static unsigned int timeout = 0;
@@ -137,14 +139,34 @@ static int avoid_alias(char *p)
 static char *path_ok(char *dir)
 {
 	char *path;
+	static char rpath[PATH_MAX];
 
 	if (avoid_alias(dir)) {
 		logerror("'%s': aliased", dir);
 		return NULL;
 	}
 
-	if (base_path) {
-		static char rpath[PATH_MAX];
+	if (user_path && *dir == '~') {
+		struct passwd *pw;
+		char *u, *p;
+
+		u = dir + 1;
+		p = strchr(u, '/');
+		if (!p) {
+			logerror("'%s': Missing / after user name", dir);
+			return NULL;
+		}
+		*p = 0;
+		pw = getpwnam(u);
+		*p++ = '/';
+		if (!pw) {
+			logerror("'%s': User not found", u);
+			return NULL;
+		}
+		snprintf(rpath, PATH_MAX, "%s/%s/%s",
+			 pw->pw_dir, user_path, p);
+		dir = rpath;
+	} else if (base_path) {
 		if (*dir != '/') {
 			/* Forbid possible base-path evasion using ~paths. */
 			logerror("'%s': Non-absolute path denied (base-path active)", dir);
@@ -491,6 +513,10 @@ static int socksetup(int port, int **soc
 			/* Note: error is not fatal */
 		}
 #endif
+		if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes))) {
+			close(sockfd);
+			continue;	/* not fatal */
+		}
 
 		if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
 			       &yes, sizeof(yes))) {
@@ -673,6 +699,10 @@ int main(int argc, char **argv)
 			base_path = arg+12;
 			continue;
 		}
+		if (!strncmp(arg, "--user-path=", 12)) {
+			user_path = arg+12;
+			continue;
+		}
 		if (!strcmp(arg, "--")) {
 			ok_paths = &argv[i+1];
 			break;
Previous: Mark WoodingNext: Junio C Hamano
Message 7 of 13 in “git-daemon hacking”
  1. 0/3 git-daemon hackingMark Wooding, Feb 3, 2006
  2. 1/3 daemon: Provide missing argument for logerror() call.Mark Wooding, Feb 3, 2006
  3. 2/3 daemon: Set SO_REUSEADDR on listening sockets.Mark Wooding, Feb 3, 2006
  4. Junio C HamanoFeb 3, 2006
  5. Junio C HamanoFeb 4, 2006
  6. Mark WoodingFeb 4, 2006
  7. 3/3 daemon: Support a --user-path option.Mark Wooding, Feb 3, 2006
  8. Junio C HamanoFeb 3, 2006
  9. Junio C HamanoFeb 4, 2006
  10. Mark WoodingFeb 4, 2006
  11. Junio C HamanoFeb 4, 2006
  12. Mark WoodingFeb 4, 2006
  13. Junio C HamanoFeb 4, 2006

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.