From: Andreas Ericsson <ae@op5.se>
To: git@vger.kernel.org
Subject: Re: User-relative paths (was: Server side programs)
Date: Sun, 23 Oct 2005 11:41:52 +0200 [thread overview]
Message-ID: <435B5AE0.1060400@op5.se> (raw)
In-Reply-To: <7vll0l6pn7.fsf@assigned-by-dhcp.cox.net>
[-- Attachment #1: Type: text/plain, Size: 3617 bytes --]
Junio C Hamano wrote:
> Andreas Ericsson <ae@op5.se> writes:
>
>
>>Are git-receive-pack and git-upload-pack the only two binaries that get
>>called directly over a SSH-tunnel?
>
>
> There are git-ssh-fetch and git-ssh-upload which call each other
> (and the older name pairs git-ssh-push and git-sh-pull do so as
> well). However, you do not have to use these commit walkers
> over ssh; fetch-pack/upload-pack pair work quite well.
>
> I think your question is "what is the absolute minimum set of
> binaries you need to allow", so I think the two listed are
> enough. If you want to let your users coming over SSH *create*
> a new repository on your machine, you would need a bit more,
> though (namely, shell access to run mkdir and git-init-db).
>
That's good to know.
>
>>The reason I'm asking is that I'm adding support for userrelative paths
>>(git pull ssh://host:~user/somedir) and removing the possibilities to
>>use a compromised but limited account for finding out what other
>>useraccounts are available.
>
>
> Sorry, it is not clear to me what you are adding. I do this
> regularly:
>
> $ git push kernel.org:git/
> $ git fetch kernel.org:git/
>
> to push into and fetch from $HOME/git/ repository on the other
> end.
>
Looking at the old code I see that that should work. I'll re-work the
patch to take this into account. The help-text was a bit fuzzy however,
and if you tried
$ git fetch ssh://kernel.org:git
it wouldn't work. Here's how I decided it was somehow broken, or at
least non-intuitive:
$ git clone ssh://git.op5.se:git foo
defaulting to local storage area
ssh: ssh: Name or service not known
fatal: unexpected EOF
> Also I can do this already (assuming the other end hangs all
> users under the same directory, presumably /home/$user):
>
> $ git fetch kernel.org:../torvalds/git/
>
> Are you in addition trying to let me do this:
>
> $ git fetch kernel.org:~torvalds/git/
>
> which would work even when ~torvalds == /home/torvalds and
> ~junio == /home2/junio, without having to tell people where
> the user home directories are?
>
Yes. Our servers' home-directories have varying paths and it'd be nice
to be able to pull other team-members code without having to remember
how that particular server is configured.
> At one point, Linus posted an outline of "restricted login shell
> for use with git over ssh". I think you could start from there,
> perhaps extend it so that it checks the binaries *and* pathnames
> the user can specify (e.g. only under your own $HOME is allowed,
> and no /../ in them, or something silly like that).
>
I found this in the archives:
http://article.gmane.org/gmane.comp.version-control.git/5784/match=restricted+login
Is that what you're referring to?
There's no reason why git-upload-pack and git-receive-pack couldn't be
used safely with a perfectly ordinary shell provided we're careful about
giving the same error message for when a directory is missing and when
it isn't a git archive.
Anyways, the attached patch does this. I've tested all the various
syntaxes and they work as expected. rsync, http and local files take the
same syntax as before. I haven't added support for user-relative paths
to the git-daemon (can't see the point, really) although that can be
done easily enough.
This patch works without conflicts alongside Johannes Schindelin's
recent contribution.
Let me know if you want things done differently.
--
Andreas Ericsson andreas.ericsson@op5.se
OP5 AB www.op5.se
Tel: +46 8-230225 Fax: +46 8-230231
[-- Attachment #2: git-userrelative-paths.diff --]
[-- Type: text/plain, Size: 7655 bytes --]
diff --git a/Makefile b/Makefile
index 903c57c..87188ea 100644
--- a/Makefile
+++ b/Makefile
@@ -115,15 +115,18 @@ PROGRAMS = \
git-local-fetch$X git-ls-files$X git-ls-tree$X git-merge-base$X \
git-merge-index$X git-mktag$X git-pack-objects$X git-patch-id$X \
git-peek-remote$X git-prune-packed$X git-read-tree$X \
- git-receive-pack$X git-rev-list$X git-rev-parse$X \
+ git-rev-list$X git-rev-parse$X \
git-send-pack$X git-show-branch$X \
git-show-index$X git-ssh-fetch$X \
git-ssh-upload$X git-tar-tree$X git-unpack-file$X \
git-unpack-objects$X git-update-index$X git-update-server-info$X \
- git-upload-pack$X git-verify-pack$X git-write-tree$X \
+ git-verify-pack$X git-write-tree$X \
git-update-ref$X git-symbolic-ref$X git-check-ref-format$X \
$(SIMPLE_PROGRAMS)
+# server side programs called (possibly) over an ssh-tunnel
+SERVERSIDE_PROGRAMS = git-receive-pack$X git-upload-pack$X
+
# Backward compatibility -- to be removed after 1.0
PROGRAMS += git-ssh-pull$X git-ssh-push$X
@@ -315,7 +318,7 @@ SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)
export prefix TAR INSTALL DESTDIR SHELL_PATH template_dir
### Build rules
-all: $(PROGRAMS) $(SCRIPTS)
+all: $(PROGRAMS) $(SCRIPTS) $(SERVERSIDE_PROGRAMS)
all:
$(MAKE) -C templates
@@ -359,6 +362,9 @@ git-cherry-pick: git-revert
%.o: %.S
$(CC) -o $*.o -c $(ALL_CFLAGS) $<
+$(SERVERSIDE_PROGRAMS) : git-%$X : %.o srvside-ssh.o $(LIB_FILE)
+ $(CC) $(ALL_CFLAGS) -o $@ $(filter %o,$^) $(LIBS)
+
git-%$X: %.o $(LIB_FILE)
$(CC) $(ALL_CFLAGS) -o $@ $(filter %.o,$^) $(LIBS)
@@ -383,6 +389,7 @@ init-db.o: init-db.c
$(LIB_OBJS): $(LIB_H)
$(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H)
+$(patsubst git-%$X,%.o,$(SERVERSIDE_PROGRAMS)): $(LIB_H) srvside-ssh.o
$(DIFF_OBJS): diffcore.h
$(LIB_FILE): $(LIB_OBJS)
@@ -410,9 +417,10 @@ check:
### Installation rules
-install: $(PROGRAMS) $(SCRIPTS)
+install: $(PROGRAMS) $(SCRIPTS) $(SERVERSIDE_PROGRAMS)
$(INSTALL) -d -m755 $(call shellquote,$(DESTDIR)$(bindir))
- $(INSTALL) $(PROGRAMS) $(SCRIPTS) $(call shellquote,$(DESTDIR)$(bindir))
+ $(INSTALL) $(PROGRAMS) $(SERVERSIDE_PROGRAMS) $(SCRIPTS) \
+ $(call shellquote,$(DESTDIR)$(bindir))
sh ./cmd-rename.sh $(call shellquote,$(DESTDIR)$(bindir))
$(MAKE) -C templates install
$(INSTALL) -d -m755 $(call shellquote,$(DESTDIR)$(GIT_PYTHON_DIR))
diff --git a/connect.c b/connect.c
index b171c5d..0d78b3e 100644
--- a/connect.c
+++ b/connect.c
@@ -436,33 +436,44 @@ static int git_tcp_connect(int fd[2], co
int git_connect(int fd[2], char *url, const char *prog)
{
char command[1024];
- char *host, *path;
- char *colon;
+ char *host, *path, *ptr = NULL;
int pipefd[2][2];
pid_t pid;
enum protocol protocol;
+ protocol = PROTO_LOCAL;
host = NULL;
path = url;
- colon = strchr(url, ':');
- protocol = PROTO_LOCAL;
- if (colon) {
- *colon = 0;
- host = url;
- path = colon+1;
- protocol = PROTO_SSH;
- if (!memcmp(path, "//", 2)) {
- char *slash = strchr(path + 2, '/');
- if (slash) {
- int nr = slash - path - 2;
- memmove(path, path+2, nr);
- path[nr] = 0;
- protocol = get_protocol(url);
- host = path;
- path = slash;
- }
+ host = strstr(url, "://");
+ if (host) {
+ *host = '\0';
+ host += 3;
+ protocol = get_protocol(url);
+ }
+ else host = url;
+
+ ptr = strchr(host, ':');
+ path = strchr(host, '/');
+
+ /* leading colon marks relative path for ssh.
+ * Check for host == url and default to PROTO_SSH to allow
+ * $ git fetch kernel.org:git
+ */
+ if(ptr && (!path || ptr < path)) {
+ if(host == url)
+ protocol = PROTO_SSH;
+
+ if(protocol == PROTO_SSH) {
+ *ptr = '\0';
+ path = ptr + 1;
}
}
+ else if(path != url) {
+ /* null-terminate host and copy path if it isn't relative */
+ ptr = strdup(path);
+ *path = '\0';
+ path = ptr;
+ }
if (protocol == PROTO_GIT)
return git_tcp_connect(fd, prog, host, path);
diff --git a/receive-pack.c b/receive-pack.c
index 8f157bc..9a040ff 100644
--- a/receive-pack.c
+++ b/receive-pack.c
@@ -8,6 +8,8 @@ static const char receive_pack_usage[] =
static const char unpacker[] = "git-unpack-objects";
+extern void srvside_chdir(const char *path, int strict);
+
static int show_ref(const char *path, const unsigned char *sha1)
{
packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
@@ -265,18 +267,9 @@ int main(int argc, char **argv)
if (!dir)
usage(receive_pack_usage);
- /* chdir to the directory. If that fails, try appending ".git" */
- if (chdir(dir) < 0) {
- if (chdir(mkpath("%s.git", dir)) < 0)
- die("unable to cd to %s", dir);
- }
-
- /* If we have a ".git" directory, chdir to it */
- chdir(".git");
- putenv("GIT_DIR=.");
+ /* Find the right directory */
+ srvside_chdir(dir, 0);
- if (access("objects", X_OK) < 0 || access("refs/heads", X_OK) < 0)
- die("%s doesn't appear to be a git directory", dir);
write_head_info();
/* EOF */
diff --git a/srvside-ssh.c b/srvside-ssh.c
new file mode 100644
index 0000000..0ed5d30
--- /dev/null
+++ b/srvside-ssh.c
@@ -0,0 +1,63 @@
+#include "cache.h"
+#include <unistd.h>
+#include <pwd.h>
+
+extern const char *__progname;
+
+
+/*
+ * Provide support for user-relative paths, but carefully.
+ *
+ * If someone has compromised an account with access limited to a few
+ * commands (git-receive-pack, git-upload-pack) we don't want to let
+ * them find out about other users through git. We prevent that by the
+ * simple expedient of maintaining the 'path' variable as is and always
+ * supplying the same (not entirely) helpful error message.
+ */
+#define DIR_OOPS \
+ die("%s: '%s': unable to chdir or not a git-archive", __progname, path)
+void srvside_chdir(char *path, int strict)
+{
+ char *dir = path;
+ struct passwd *pw;
+
+ if(chdir(path) < 0 && *path == '~') {
+ char *slash;
+ char *user = (char *)path + 1;
+
+ if((slash = strchr(dir, '/')))
+ *slash = '\0';
+
+ if(!(pw = getpwnam(user))) {
+ if(slash)
+ *slash = '/';
+ DIR_OOPS;
+ }
+ if(chdir(pw->pw_dir) < 0) {
+ DIR_OOPS;
+ }
+
+ /* We're in someones homedir so re-insert the slash (for the
+ * error message) and set dir just beyond it. If there was no
+ * spoon we supply the local one */
+ if(slash) {
+ *slash = '/';
+ dir = slash + 1;
+ }
+ else
+ dir = "./";
+ }
+
+ /* chdir to the directory. If that fails, try appending ".git" */
+ if (chdir(dir) < 0) {
+ if (strict || chdir(mkpath("%s.git", dir)) < 0)
+ DIR_OOPS;
+ }
+ if (!strict)
+ chdir(".git");
+
+ if (access("objects", X_OK) || access("refs", X_OK))
+ DIR_OOPS;
+
+ putenv("GIT_DIR=.");
+}
diff --git a/upload-pack.c b/upload-pack.c
index accdba6..356c9b1 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -5,6 +5,7 @@
#include "object.h"
static const char upload_pack_usage[] = "git-upload-pack [--strict] [--timeout=nn] <dir>";
+extern void srvside_chdir(const char *path, int strict);
#define MAX_HAS 256
#define MAX_NEEDS 256
@@ -202,7 +203,6 @@ static int upload_pack(void)
int main(int argc, char **argv)
{
- const char *dir;
int i;
int strict = 0;
@@ -227,20 +227,10 @@ int main(int argc, char **argv)
if (i != argc-1)
usage(upload_pack_usage);
- dir = argv[i];
- /* chdir to the directory. If that fails, try appending ".git" */
- if (chdir(dir) < 0) {
- if (strict || chdir(mkpath("%s.git", dir)) < 0)
- die("git-upload-pack unable to chdir to %s", dir);
- }
- if (!strict)
- chdir(".git");
-
- if (access("objects", X_OK) || access("refs", X_OK))
- die("git-upload-pack: %s doesn't seem to be a git archive", dir);
+ /* Find the right directory */
+ srvside_chdir(argv[i], strict);
- putenv("GIT_DIR=.");
upload_pack();
return 0;
}
next prev parent reply other threads:[~2005-10-23 9:42 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-10-22 22:22 Server side programs Andreas Ericsson
2005-10-23 0:30 ` Junio C Hamano
2005-10-23 9:41 ` Andreas Ericsson [this message]
2005-10-23 18:37 ` User-relative paths (was: Server side programs) Petr Baudis
2005-10-23 19:50 ` User-relative paths Junio C Hamano
2005-10-23 22:25 ` Petr Baudis
2005-10-23 22:30 ` Junio C Hamano
2005-10-24 6:28 ` Daniel Barkalow
2005-10-25 7:47 ` Andreas Ericsson
2005-10-23 19:56 ` Junio C Hamano
2005-10-23 21:30 ` Linus Torvalds
2005-10-23 22:57 ` Junio C Hamano
2005-10-23 23:02 ` Junio C Hamano
2005-10-24 1:08 ` H. Peter Anvin
2005-10-24 1:37 ` Linus Torvalds
2005-10-24 1:44 ` H. Peter Anvin
2005-10-24 1:56 ` Junio C Hamano
2005-10-24 0:21 ` [PATCH] Add git-shell Junio C Hamano
2005-10-24 0:52 ` Linus Torvalds
2005-10-24 0:55 ` Linus Torvalds
2005-10-24 1:36 ` Junio C Hamano
2005-10-24 2:08 ` User-relative paths Junio C Hamano
2005-10-25 9:11 ` [PATCH] git_progname (was: Re: User-relative paths) Andreas Ericsson
2005-10-25 9:31 ` Petr Baudis
2005-10-25 11:12 ` [PATCH] git_progname Andreas Ericsson
2005-10-25 12:53 ` Andreas Ericsson
2005-10-25 13:32 ` Petr Baudis
2005-10-26 6:07 ` Junio C Hamano
2005-10-27 8:34 ` [PATCH] git_progname (was: Re: User-relative paths) Matthias Urlichs
2005-10-23 0:42 ` Server side programs Linus Torvalds
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=435B5AE0.1060400@op5.se \
--to=ae@op5.se \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).