Explorar o código

Check deploy keys when Gogs is run with Service.RequireSignInView=true (#4078)

* Check deploy keys when Gogs is run with require_sign_in_view

Check if the deploy key can access to a repository. A deploy key
doesn't represent an gogs user, so in a site with Service.RequireSignInView
activated we should give read access only in the repositories where
this deploy key is in use. In other case, a deploy service or system
using an active deploy key can get read access to all the repositories
in a Gogs service.

* Refactoring: Comments starts in a new line

* Minor change in a comment

* Code cleaning. Replace spaces with tabs
Pablo Saavedra %!s(int64=8) %!d(string=hai) anos
pai
achega
0081c6911d
Modificáronse 2 ficheiros con 48 adicións e 26 borrados
  1. 44 26
      cmd/serve.go
  2. 4 0
      modules/setting/setting.go

+ 44 - 26
cmd/serve.go

@@ -41,6 +41,7 @@ var CmdServ = cli.Command{
 
 func setup(logPath string) {
 	setting.NewContext()
+	setting.NewService()
 	log.NewGitLogger(filepath.Join(setting.LogRootPath, logPath))
 
 	models.LoadConfigs()
@@ -61,6 +62,37 @@ func parseCmd(cmd string) (string, string) {
 	return ss[0], strings.Replace(ss[1], "'/", "'", 1)
 }
 
+func getKey(cmdKey string) *models.PublicKey {
+	keys := strings.Split(cmdKey, "-")
+	if len(keys) != 2 {
+		fail("Key ID format error", "Invalid key argument: %s", cmdKey)
+	}
+
+	key, err := models.GetPublicKeyByID(com.StrTo(keys[1]).MustInt64())
+	if err != nil {
+		fail("Invalid key ID", "Invalid key ID[%s]: %v", cmdKey, err)
+	}
+	return key
+}
+
+func checkDeployKey(key *models.PublicKey, repo *models.Repository) {
+	// Check if this deploy key belongs to current repository.
+	if !models.HasDeployKey(key.ID, repo.ID) {
+		fail("Key access denied", "Deploy key access denied: [key_id: %d, repo_id: %d]", key.ID, repo.ID)
+	}
+
+	// Update deploy key activity.
+	deployKey, err := models.GetDeployKeyByRepo(key.ID, repo.ID)
+	if err != nil {
+		fail("Internal error", "GetDeployKey: %v", err)
+	}
+
+	deployKey.Updated = time.Now()
+	if err = models.UpdateDeployKey(deployKey); err != nil {
+		fail("Internal error", "UpdateDeployKey: %v", err)
+	}
+}
+
 var (
 	allowedCommands = map[string]models.AccessMode{
 		"git-upload-pack":    models.ACCESS_MODE_READ,
@@ -199,38 +231,15 @@ func runServ(c *cli.Context) error {
 		keyID int64
 		user  *models.User
 	)
+	key := getKey(c.Args()[0])
+	keyID = key.ID
 	if requestedMode == models.ACCESS_MODE_WRITE || repo.IsPrivate {
-		keys := strings.Split(c.Args()[0], "-")
-		if len(keys) != 2 {
-			fail("Key ID format error", "Invalid key argument: %s", c.Args()[0])
-		}
-
-		key, err := models.GetPublicKeyByID(com.StrTo(keys[1]).MustInt64())
-		if err != nil {
-			fail("Invalid key ID", "Invalid key ID[%s]: %v", c.Args()[0], err)
-		}
-		keyID = key.ID
-
 		// Check deploy key or user key.
 		if key.Type == models.KEY_TYPE_DEPLOY {
 			if key.Mode < requestedMode {
 				fail("Key permission denied", "Cannot push with deployment key: %d", key.ID)
 			}
-			// Check if this deploy key belongs to current repository.
-			if !models.HasDeployKey(key.ID, repo.ID) {
-				fail("Key access denied", "Deploy key access denied: [key_id: %d, repo_id: %d]", key.ID, repo.ID)
-			}
-
-			// Update deploy key activity.
-			deployKey, err := models.GetDeployKeyByRepo(key.ID, repo.ID)
-			if err != nil {
-				fail("Internal error", "GetDeployKey: %v", err)
-			}
-
-			deployKey.Updated = time.Now()
-			if err = models.UpdateDeployKey(deployKey); err != nil {
-				fail("Internal error", "UpdateDeployKey: %v", err)
-			}
+			checkDeployKey(key, repo)
 		} else {
 			user, err = models.GetUserByKeyID(key.ID)
 			if err != nil {
@@ -250,6 +259,15 @@ func runServ(c *cli.Context) error {
 					user.Name, requestedMode, repoPath)
 			}
 		}
+	} else  {
+		// if public and read ...
+		// Check if the key can access to the repository in case of it is a deploy key (a deploy keys != user key).
+		// A deploy key doesn't represent a signed in user, so in a site with Service.RequireSignInView activated
+		// we should give read access only in repositories where this deploy key is in use. In other case, a server
+		// or system  using an active deploy key can get read access to all the repositories in a Gogs service.
+		if key.Type == models.KEY_TYPE_DEPLOY && setting.Service.RequireSignInView {
+			checkDeployKey(key, repo)
+		}
 	}
 
 	uuid := gouuid.NewV4().String()

+ 4 - 0
modules/setting/setting.go

@@ -806,6 +806,10 @@ func newWebhookService() {
 	Webhook.PagingNum = sec.Key("PAGING_NUM").MustInt(10)
 }
 
+func NewService() {
+	newService()
+}
+
 func NewServices() {
 	newService()
 	newLogService()