diff options
author | Antoine GIRARD <sapk@users.noreply.github.com> | 2018-01-27 17:48:15 +0100 |
---|---|---|
committer | Lauris BH <lauris@nix.lv> | 2018-01-27 18:48:15 +0200 |
commit | 9e842c8a722eb1db50cfbdbe7146b67d3670052f (patch) | |
tree | d0d1f06f9363276289971759c7134149b9ec6860 /modules/lfs/server.go | |
parent | 97fe773491ae69531141316a1178d22c8a5d1257 (diff) | |
download | gitea-9e842c8a722eb1db50cfbdbe7146b67d3670052f.tar.gz gitea-9e842c8a722eb1db50cfbdbe7146b67d3670052f.zip |
Fix SSH auth lfs locks (#3152)
* Fix SSH auth LFS locks
* Activate SSH/lock test
* Remove debug
* Follow @lunny recommendation for AfterLoad method
Diffstat (limited to 'modules/lfs/server.go')
-rw-r--r-- | modules/lfs/server.go | 133 |
1 files changed, 69 insertions, 64 deletions
diff --git a/modules/lfs/server.go b/modules/lfs/server.go index 329d6f00c4..a81d8e5c91 100644 --- a/modules/lfs/server.go +++ b/modules/lfs/server.go @@ -473,7 +473,6 @@ func logRequest(r macaron.Request, status int) { // authenticate uses the authorization string to determine whether // or not to proceed. This server assumes an HTTP Basic auth format. func authenticate(ctx *context.Context, repository *models.Repository, authorization string, requireWrite bool) bool { - accessMode := models.AccessModeRead if requireWrite { accessMode = models.AccessModeWrite @@ -482,86 +481,92 @@ func authenticate(ctx *context.Context, repository *models.Repository, authoriza if !repository.IsPrivate && !requireWrite { return true } - if ctx.IsSigned { accessCheck, _ := models.HasAccess(ctx.User.ID, repository, accessMode) return accessCheck } - if authorization == "" { - return false - } - - if authenticateToken(repository, authorization, requireWrite) { - return true - } - - if !strings.HasPrefix(authorization, "Basic ") { - return false - } - - c, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(authorization, "Basic ")) + user, repo, opStr, err := parseToken(authorization) if err != nil { return false } - cs := string(c) - i := strings.IndexByte(cs, ':') - if i < 0 { - return false - } - user, password := cs[:i], cs[i+1:] - - userModel, err := models.GetUserByName(user) - if err != nil { - return false + ctx.User = user + if opStr == "basic" { + accessCheck, _ := models.HasAccess(ctx.User.ID, repository, accessMode) + return accessCheck } - - if !userModel.ValidatePassword(password) { - return false + if repository.ID == repo.ID { + if requireWrite && opStr != "upload" { + return false + } + return true } - - accessCheck, _ := models.HasAccess(userModel.ID, repository, accessMode) - return accessCheck + return false } -func authenticateToken(repository *models.Repository, authorization string, requireWrite bool) bool { - if !strings.HasPrefix(authorization, "Bearer ") { - return false - } - - token, err := jwt.Parse(authorization[7:], func(t *jwt.Token) (interface{}, error) { - if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok { - return nil, fmt.Errorf("unexpected signing method: %v", t.Header["alg"]) +func parseToken(authorization string) (*models.User, *models.Repository, string, error) { + if authorization == "" { + return nil, nil, "unknown", fmt.Errorf("No token") + } + if strings.HasPrefix(authorization, "Bearer ") { + token, err := jwt.Parse(authorization[7:], func(t *jwt.Token) (interface{}, error) { + if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok { + return nil, fmt.Errorf("unexpected signing method: %v", t.Header["alg"]) + } + return setting.LFS.JWTSecretBytes, nil + }) + if err != nil { + return nil, nil, "unknown", err } - return setting.LFS.JWTSecretBytes, nil - }) - if err != nil { - return false - } - claims, claimsOk := token.Claims.(jwt.MapClaims) - if !token.Valid || !claimsOk { - return false - } - - opStr, ok := claims["op"].(string) - if !ok { - return false - } - - if requireWrite && opStr != "upload" { - return false - } - - repoID, ok := claims["repo"].(float64) - if !ok { - return false + claims, claimsOk := token.Claims.(jwt.MapClaims) + if !token.Valid || !claimsOk { + return nil, nil, "unknown", fmt.Errorf("Token claim invalid") + } + opStr, ok := claims["op"].(string) + if !ok { + return nil, nil, "unknown", fmt.Errorf("Token operation invalid") + } + repoID, ok := claims["repo"].(float64) + if !ok { + return nil, nil, opStr, fmt.Errorf("Token repository id invalid") + } + r, err := models.GetRepositoryByID(int64(repoID)) + if err != nil { + return nil, nil, opStr, err + } + userID, ok := claims["user"].(float64) + if !ok { + return nil, r, opStr, fmt.Errorf("Token user id invalid") + } + u, err := models.GetUserByID(int64(userID)) + if err != nil { + return nil, r, opStr, err + } + return u, r, opStr, nil } - if repository.ID != int64(repoID) { - return false + if strings.HasPrefix(authorization, "Basic ") { + c, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(authorization, "Basic ")) + if err != nil { + return nil, nil, "basic", err + } + cs := string(c) + i := strings.IndexByte(cs, ':') + if i < 0 { + return nil, nil, "basic", fmt.Errorf("Basic auth invalid") + } + user, password := cs[:i], cs[i+1:] + u, err := models.GetUserByName(user) + if err != nil { + return nil, nil, "basic", err + } + if !u.ValidatePassword(password) { + return nil, nil, "basic", fmt.Errorf("Basic auth failed") + } + return u, nil, "basic", nil } - return true + return nil, nil, "unknown", fmt.Errorf("Token not found") } func requireAuth(ctx *context.Context) { |