Commit 38d44f67 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 37b49c54
......@@ -9,6 +9,7 @@ package main
import (
"bufio"
"errors"
"fmt"
"io"
"log"
......@@ -58,8 +59,6 @@ type AuthCacheKey struct {
// Authorization reply cache
// {} project -> AuthCacheEntry
//
// XXX should be not only project (private_token etc...)
type AuthCache struct {
u *upstream // for which upstream we cache auth
......@@ -178,9 +177,8 @@ func askAuthBackend(u *upstream, project, query string) AuthReply {
// Request to auth backend to verify whether download is possible.
// - first option is via asking as `git fetch` would do, but on Rails
// side this supports only basic auth, not private token.
// - that's why we auth backend to authenticate as if it is request to
// get repo archive XXX
// XXX private_token not propagated, etc ...
// - that's why we auth backend to authenticate as if it was request to
// get repo archive.
// XXX PRIVATE-TOKEN (in header)
// url := project+".git/info/refs?service=git-upload-pack"
url := project+"/repository/archive.zip"
......@@ -189,7 +187,7 @@ func askAuthBackend(u *upstream, project, query string) AuthReply {
}
reqDownloadAccess, err := http.NewRequest("GET", url, nil)
if err != nil {
fail500(authReply.RawReply, "GET git-upload-pack", err)
fail500(authReply.RawReply, fmt.Errorf("GET git-upload-pack: %v", err))
return authReply
}
......@@ -224,7 +222,7 @@ func handleGetBlobRaw(w http.ResponseWriter, r *gitRequest) {
u := r.Request.URL // XXX naming
rawLoc := rawRe.FindStringIndex(u.Path)
if rawLoc == nil {
fail500(w, "extract project name", nil) // XXX err=nil
fail500(w, errors.New("extract project name"))
return
}
project := u.Path[:rawLoc[0]]
......@@ -252,7 +250,7 @@ func handleGetBlobRaw(w http.ResponseWriter, r *gitRequest) {
// this way it will be read one time only and next reads will be empty.
_, err := w.Write(authReply.RawReply.Body.Bytes())
if err != nil {
logContext("writing authReply.RawReply.Body", err)
logError(fmt.Errorf("writing authReply.RawReply.Body: %v", err))
}
return
}
......@@ -269,13 +267,13 @@ func emitBlob(w http.ResponseWriter, repopath string, refpath string) {
queryCmd := gitCommand("", "git", "--git-dir="+repopath, "cat-file", "--batch")
queryStdin, err := queryCmd.StdinPipe()
if err != nil {
fail500(w, "git cat-file --batch; stdin", err)
fail500(w, fmt.Errorf("git cat-file --batch; stdin: %v", err))
return
}
defer queryStdin.Close()
queryStdout, err := queryCmd.StdoutPipe()
if err != nil {
fail500(w, "git cat-file --batch; stdout", err)
fail500(w, fmt.Errorf("git cat-file --batch; stdout: %v", err))
return
}
defer queryStdout.Close()
......@@ -283,7 +281,7 @@ func emitBlob(w http.ResponseWriter, repopath string, refpath string) {
err = queryCmd.Start()
if err != nil {
fail500(w, "git cat-file --batch; start", err)
fail500(w, fmt.Errorf("git cat-file --batch; start: %v", err))
return
}
defer cleanUpProcessGroup(queryCmd)
......@@ -302,13 +300,13 @@ func emitBlob(w http.ResponseWriter, repopath string, refpath string) {
path := strings.Join(refpathv[i:], "/")
_, err := fmt.Fprintf(queryStdin, "%s:%s\n", ref, path)
if err != nil {
fail500(w, "git cat-file --batch; write", err)
fail500(w, fmt.Errorf("git cat-file --batch; write: %v", err))
return
}
reply, err := queryReader.ReadString('\n')
if err != nil {
fail500(w, "git cat-file --batch; read", err)
fail500(w, fmt.Errorf("git cat-file --batch; read: %v", err))
return
}
......@@ -320,7 +318,7 @@ func emitBlob(w http.ResponseWriter, repopath string, refpath string) {
// <sha1> SP <type> SP <size> LF
_, err = fmt.Sscanf(reply, "%s %s %d\n", &sha1, &type_, &size)
if err != nil {
fail500(w, "git cat-file --batch; reply parse", err)
fail500(w, fmt.Errorf("git cat-file --batch; reply parse: %v", err))
return
}
......@@ -355,20 +353,20 @@ func emitBlob(w http.ResponseWriter, repopath string, refpath string) {
// holding some tail bytes in queryReader after chat phase
_, err = io.CopyN(w, queryReader, size)
if err != nil {
logContext("io.CopyN", err)
logError(fmt.Errorf("io.CopyN: %v", err))
return
}
// close git stdin explicitly, so it exits cleanly
err = queryStdin.Close()
if err != nil {
logContext("queryStdin.Close", err)
logError(fmt.Errorf("queryStdin.Close: %v", err))
return
}
err = queryCmd.Wait()
if err != nil {
logContext("wait", err)
logError(fmt.Errorf("wait: %v", err))
return
}
}
......@@ -522,3 +522,29 @@ func TestDeniedBlobDownload(t *testing.T) {
downloadAndExpect("874797c3/files/ruby/popen.rb", 403)
downloadAndExpect("master/non-existing-file", 403)
}
func TestPrivateBlobDownload(t *testing.T) {
// access is ok if token is provided either via query or via header
ts := testServerWithHandler(url, func(w, http.ResponseWriter, r *http.Request) {
log.Println("UPSTREAM", r.Method, r.URL)
token_ok1 := r.URL.Query().Get("aaa_token") == "TOKEN-4AAA"
token_ok2 := r.Header.Get("BBB-TOKEN") == "TOKEN-4BBB"
if !(token_ok1 || token_ok2) {
w.WriteHeader(403)
fmt.Fprintf("w", "Access denied")
}
data, err := json.Marshal(gitOkBody(t))
if err != nil {
t.Fatal(err)
}
w.WriteHeader(200)
w.Write(data)
}
defer ts.Close()
ws := startWorkhorseServer(ts.URL)
defer ws.Close()
download(t, "%s/%s/raw/5f923865/README.md
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment