From 313a1810aee0bceafad8500a6c1771ec441531d3 Mon Sep 17 00:00:00 2001 From: William Hilton Date: Mon, 6 Jul 2020 23:07:42 -0400 Subject: [PATCH 1/3] Enable Git Wire Protocol v2 over HTTP --- modules/git/command.go | 6 ++++++ routers/repo/http.go | 16 +++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/modules/git/command.go b/modules/git/command.go index 14fab4ef3c8eb..52c14a9337fcf 100644 --- a/modules/git/command.go +++ b/modules/git/command.go @@ -227,6 +227,12 @@ func (c *Command) RunInDirWithEnv(dir string, env []string) (string, error) { return string(stdout), nil } +// RunInDirWithEnvBytes executes the command in given directory +// and returns stdout in []byte and error (combined with stderr). +func (c *Command) RunInDirWithEnvBytes(dir string, env []string) ([]byte, error) { + return c.RunInDirTimeoutEnv(env, -1, dir) +} + // RunTimeout executes the command in default working directory with given timeout, // and returns stdout in string and error (combined with stderr). func (c *Command) RunTimeout(timeout time.Duration) (string, error) { diff --git a/routers/repo/http.go b/routers/repo/http.go index 0481b46bdef7b..2faf672d1bcc2 100644 --- a/routers/repo/http.go +++ b/routers/repo/http.go @@ -483,6 +483,9 @@ var routes = []route{ {regexp.MustCompile(`(.*?)/objects/pack/pack-[0-9a-f]{40}\.idx$`), "GET", getIdxFile}, } +// one or more key=value pairs separated by colons +var safeGitProtocolHeader = regexp.MustCompile(`^[0-9a-zA-Z]+=[0-9a-zA-Z]+(:[0-9a-zA-Z]+=[0-9a-zA-Z]+)*$`) + func getGitConfig(option, dir string) string { out, err := git.NewCommand("config", option).RunInDir(dir) if err != nil { @@ -553,6 +556,10 @@ func serviceRPC(h serviceHandler, service string) { // set this for allow pre-receive and post-receive execute h.environ = append(h.environ, "SSH_ORIGINAL_COMMAND="+service) + if protocol := h.r.Header.Get("Git-Protocol"); protocol != "" && safeGitProtocolHeader.MatchString(protocol) { + h.environ = append(h.environ, "GIT_PROTOCOL="+protocol) + } + ctx, cancel := gocontext.WithCancel(git.DefaultContext) defer cancel() var stderr bytes.Buffer @@ -560,6 +567,8 @@ func serviceRPC(h serviceHandler, service string) { cmd.Dir = h.dir if service == "receive-pack" { cmd.Env = append(os.Environ(), h.environ...) + } else { + cmd.Env = h.environ } cmd.Stdout = h.w cmd.Stdin = reqBody @@ -610,7 +619,12 @@ func getInfoRefs(h serviceHandler) { h.setHeaderNoCache() if hasAccess(getServiceType(h.r), h, false) { service := getServiceType(h.r) - refs, err := git.NewCommand(service, "--stateless-rpc", "--advertise-refs", ".").RunInDirBytes(h.dir) + + if protocol := h.r.Header.Get("Git-Protocol"); protocol != "" && safeGitProtocolHeader.MatchString(protocol) { + h.environ = append(h.environ, "GIT_PROTOCOL="+protocol) + } + + refs, err := git.NewCommand(service, "--stateless-rpc", "--advertise-refs", ".").RunInDirWithEnvBytes(h.dir, h.environ) if err != nil { log.Error(fmt.Sprintf("%v - %s", err, string(refs))) } From de0a80a04e4db9028ac07d82db150c2afbfa9627 Mon Sep 17 00:00:00 2001 From: William Hilton Date: Tue, 7 Jul 2020 14:15:53 -0400 Subject: [PATCH 2/3] use RunInDirTimeoutEnv --- modules/git/command.go | 6 ------ routers/repo/http.go | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/modules/git/command.go b/modules/git/command.go index 52c14a9337fcf..14fab4ef3c8eb 100644 --- a/modules/git/command.go +++ b/modules/git/command.go @@ -227,12 +227,6 @@ func (c *Command) RunInDirWithEnv(dir string, env []string) (string, error) { return string(stdout), nil } -// RunInDirWithEnvBytes executes the command in given directory -// and returns stdout in []byte and error (combined with stderr). -func (c *Command) RunInDirWithEnvBytes(dir string, env []string) ([]byte, error) { - return c.RunInDirTimeoutEnv(env, -1, dir) -} - // RunTimeout executes the command in default working directory with given timeout, // and returns stdout in string and error (combined with stderr). func (c *Command) RunTimeout(timeout time.Duration) (string, error) { diff --git a/routers/repo/http.go b/routers/repo/http.go index 2faf672d1bcc2..83b3e8ee966d0 100644 --- a/routers/repo/http.go +++ b/routers/repo/http.go @@ -624,7 +624,7 @@ func getInfoRefs(h serviceHandler) { h.environ = append(h.environ, "GIT_PROTOCOL="+protocol) } - refs, err := git.NewCommand(service, "--stateless-rpc", "--advertise-refs", ".").RunInDirWithEnvBytes(h.dir, h.environ) + refs, err := git.NewCommand(service, "--stateless-rpc", "--advertise-refs", ".").RunInDirTimeoutEnv(h.environ, -1, h.dir) if err != nil { log.Error(fmt.Sprintf("%v - %s", err, string(refs))) } From 0acb5cf79967f193d828be1d07a11cfeba8c94f8 Mon Sep 17 00:00:00 2001 From: William Hilton Date: Tue, 7 Jul 2020 15:11:54 -0400 Subject: [PATCH 3/3] pass $HOME environment variable to git upload-pack --- routers/repo/http.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/routers/repo/http.go b/routers/repo/http.go index 83b3e8ee966d0..565ee5eff4622 100644 --- a/routers/repo/http.go +++ b/routers/repo/http.go @@ -565,11 +565,7 @@ func serviceRPC(h serviceHandler, service string) { var stderr bytes.Buffer cmd := exec.CommandContext(ctx, git.GitExecutable, service, "--stateless-rpc", h.dir) cmd.Dir = h.dir - if service == "receive-pack" { - cmd.Env = append(os.Environ(), h.environ...) - } else { - cmd.Env = h.environ - } + cmd.Env = append(os.Environ(), h.environ...) cmd.Stdout = h.w cmd.Stdin = reqBody cmd.Stderr = &stderr @@ -623,6 +619,7 @@ func getInfoRefs(h serviceHandler) { if protocol := h.r.Header.Get("Git-Protocol"); protocol != "" && safeGitProtocolHeader.MatchString(protocol) { h.environ = append(h.environ, "GIT_PROTOCOL="+protocol) } + h.environ = append(os.Environ(), h.environ...) refs, err := git.NewCommand(service, "--stateless-rpc", "--advertise-refs", ".").RunInDirTimeoutEnv(h.environ, -1, h.dir) if err != nil {