Skip to content

Commit

Permalink
push + pull now works with reverse proxy + basic auth on apache 2.4
Browse files Browse the repository at this point in the history
  • Loading branch information
Gogs authored and bkcsoft committed Dec 29, 2016
1 parent 937b4b5 commit 37eec6c
Showing 1 changed file with 75 additions and 62 deletions.
137 changes: 75 additions & 62 deletions routers/repo/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,85 +83,98 @@ func HTTP(ctx *context.Context) {

// check access
if askAuth {
authHead := ctx.Req.Header.Get("Authorization")
if len(authHead) == 0 {
ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=\".\"")
ctx.Error(http.StatusUnauthorized)
return
}

auths := strings.Fields(authHead)
// currently check basic auth
// TODO: support digit auth
// FIXME: middlewares/context.go did basic auth check already,
// maybe could use that one.
if len(auths) != 2 || auths[0] != "Basic" {
ctx.HandleText(http.StatusUnauthorized, "no basic auth and digit auth")
return
}
authUsername, authPasswd, err = base.BasicAuthDecode(auths[1])
if err != nil {
ctx.HandleText(http.StatusUnauthorized, "no basic auth and digit auth")
return
}

authUser, err = models.UserSignIn(authUsername, authPasswd)
if err != nil {
if !models.IsErrUserNotExist(err) {
ctx.Handle(http.StatusInternalServerError, "UserSignIn error: %v", err)
if setting.Service.EnableReverseProxyAuth {
authUsername = ctx.Req.Header.Get(setting.ReverseProxyAuthUser)
if len(authUsername) == 0 {
ctx.HandleText(401, "reverse proxy login error. authUsername empty")
return
}

// Assume username now is a token.
token, err := models.GetAccessTokenBySHA(authUsername)
authUser, err = models.GetUserByName(authUsername)
if err != nil {
if models.IsErrAccessTokenNotExist(err) || models.IsErrAccessTokenEmpty(err) {
ctx.HandleText(http.StatusUnauthorized, "invalid token")
} else {
ctx.Handle(http.StatusInternalServerError, "GetAccessTokenBySha", err)
}
ctx.HandleText(401, "reverse proxy login error, got error while running GetUserByName")
return
}
}else{
authHead := ctx.Req.Header.Get("Authorization")
if len(authHead) == 0 {
ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=\".\"")
ctx.Error(http.StatusUnauthorized)
return
}
token.Updated = time.Now()
if err = models.UpdateAccessToken(token); err != nil {
ctx.Handle(http.StatusInternalServerError, "UpdateAccessToken", err)

auths := strings.Fields(authHead)
// currently check basic auth
// TODO: support digit auth
// FIXME: middlewares/context.go did basic auth check already,
// maybe could use that one.
if len(auths) != 2 || auths[0] != "Basic" {
ctx.HandleText(http.StatusUnauthorized, "no basic auth and digit auth")
return
}
authUser, err = models.GetUserByID(token.UID)
authUsername, authPasswd, err = base.BasicAuthDecode(auths[1])
if err != nil {
ctx.Handle(http.StatusInternalServerError, "GetUserByID", err)
ctx.HandleText(http.StatusUnauthorized, "no basic auth and digit auth")
return
}
}

if !isPublicPull {
var tp = models.AccessModeWrite
if isPull {
tp = models.AccessModeRead
authUser, err = models.UserSignIn(authUsername, authPasswd)
if err != nil {
if !models.IsErrUserNotExist(err) {
ctx.Handle(http.StatusInternalServerError, "UserSignIn error: %v", err)
return
}

// Assume username now is a token.
token, err := models.GetAccessTokenBySHA(authUsername)
if err != nil {
if models.IsErrAccessTokenNotExist(err) || models.IsErrAccessTokenEmpty(err) {
ctx.HandleText(http.StatusUnauthorized, "invalid token")
} else {
ctx.Handle(http.StatusInternalServerError, "GetAccessTokenBySha", err)
}
return
}
token.Updated = time.Now()
if err = models.UpdateAccessToken(token); err != nil {
ctx.Handle(http.StatusInternalServerError, "UpdateAccessToken", err)
}
authUser, err = models.GetUserByID(token.UID)
if err != nil {
ctx.Handle(http.StatusInternalServerError, "GetUserByID", err)
return
}
}

has, err := models.HasAccess(authUser, repo, tp)
if err != nil {
ctx.Handle(http.StatusInternalServerError, "HasAccess", err)
return
} else if !has {
if tp == models.AccessModeRead {
has, err = models.HasAccess(authUser, repo, models.AccessModeWrite)
if err != nil {
ctx.Handle(http.StatusInternalServerError, "HasAccess2", err)
return
} else if !has {
if !isPublicPull {
var tp = models.AccessModeWrite
if isPull {
tp = models.AccessModeRead
}

has, err := models.HasAccess(authUser, repo, tp)
if err != nil {
ctx.Handle(http.StatusInternalServerError, "HasAccess", err)
return
} else if !has {
if tp == models.AccessModeRead {
has, err = models.HasAccess(authUser, repo, models.AccessModeWrite)
if err != nil {
ctx.Handle(http.StatusInternalServerError, "HasAccess2", err)
return
} else if !has {
ctx.HandleText(http.StatusForbidden, "User permission denied")
return
}
} else {
ctx.HandleText(http.StatusForbidden, "User permission denied")
return
}
} else {
ctx.HandleText(http.StatusForbidden, "User permission denied")
return
}
}

if !isPull && repo.IsMirror {
ctx.HandleText(http.StatusForbidden, "mirror repository is read-only")
return
if !isPull && repo.IsMirror {
ctx.HandleText(http.StatusForbidden, "mirror repository is read-only")
return
}
}
}
}
Expand Down

0 comments on commit 37eec6c

Please sign in to comment.