@ -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 ( )