@@ -36,7 +36,10 @@ import (
3636)
3737
3838const  (
39- 	lfsAuthenticateVerb  =  "git-lfs-authenticate" 
39+ 	verbUploadPack       =  "git-upload-pack" 
40+ 	verbUploadArchive    =  "git-upload-archive" 
41+ 	verbReceivePack      =  "git-receive-pack" 
42+ 	verbLfsAuthenticate  =  "git-lfs-authenticate" 
4043)
4144
4245// CmdServ represents the available serv sub-command. 
@@ -73,11 +76,16 @@ func setup(ctx context.Context, debug bool) {
7376}
7477
7578var  (
76- 	allowedCommands  =  map [string ]perm.AccessMode {
77- 		"git-upload-pack" :    perm .AccessModeRead ,
78- 		"git-upload-archive" : perm .AccessModeRead ,
79- 		"git-receive-pack" :   perm .AccessModeWrite ,
80- 		lfsAuthenticateVerb :  perm .AccessModeNone ,
79+ 	// anything not in map will return false (zero value) 
80+ 	// keep getAccessMode() in sync 
81+ 	allowedCommands  =  map [string ]bool {
82+ 		verbUploadPack :      true ,
83+ 		verbUploadArchive :   true ,
84+ 		verbReceivePack :     true ,
85+ 		verbLfsAuthenticate : true ,
86+ 	}
87+ 	allowedCommandsLfs  =  map [string ]bool {
88+ 		verbLfsAuthenticate : true ,
8189	}
8290	alphaDashDotPattern  =  regexp .MustCompile (`[^\w-\.]` )
8391)
@@ -124,6 +132,24 @@ func handleCliResponseExtra(extra private.ResponseExtra) error {
124132	return  nil 
125133}
126134
135+ func  getAccessMode (verb  string , lfsVerb  string ) perm.AccessMode  {
136+ 	switch  verb  {
137+ 	case  verbUploadPack , verbUploadArchive :
138+ 		return  perm .AccessModeRead 
139+ 	case  verbReceivePack :
140+ 		return  perm .AccessModeWrite 
141+ 	case  verbLfsAuthenticate :
142+ 		switch  lfsVerb  {
143+ 		case  "upload" :
144+ 			return  perm .AccessModeWrite 
145+ 		case  "download" :
146+ 			return  perm .AccessModeRead 
147+ 		}
148+ 	}
149+ 	// should be unreachable 
150+ 	return  perm .AccessModeNone 
151+ }
152+ 
127153func  runServ (c  * cli.Context ) error  {
128154	ctx , cancel  :=  installSignals ()
129155	defer  cancel ()
@@ -193,17 +219,7 @@ func runServ(c *cli.Context) error {
193219	if  repoPath [0 ] ==  '/'  {
194220		repoPath  =  repoPath [1 :]
195221	}
196- 
197222	var  lfsVerb  string 
198- 	if  verb  ==  lfsAuthenticateVerb  {
199- 		if  ! setting .LFS .StartServer  {
200- 			return  fail (ctx , "Unknown git command" , "LFS authentication request over SSH denied, LFS support is disabled" )
201- 		}
202- 
203- 		if  len (words ) >  2  {
204- 			lfsVerb  =  words [2 ]
205- 		}
206- 	}
207223
208224	rr  :=  strings .SplitN (repoPath , "/" , 2 )
209225	if  len (rr ) !=  2  {
@@ -240,28 +256,28 @@ func runServ(c *cli.Context) error {
240256		}()
241257	}
242258
243- 	requestedMode , has  :=  allowedCommands [verb ]
244- 	if  ! has  {
259+ 	if  allowedCommands [verb ] {
260+ 		if  allowedCommandsLfs [verb ] {
261+ 			if  ! setting .LFS .StartServer  {
262+ 				return  fail (ctx , "Unknown git command" , "LFS authentication request over SSH denied, LFS support is disabled" )
263+ 			}
264+ 			if  len (words ) >  2  {
265+ 				lfsVerb  =  words [2 ]
266+ 			}
267+ 		}
268+ 	} else  {
245269		return  fail (ctx , "Unknown git command" , "Unknown git command %s" , verb )
246270	}
247271
248- 	if  verb  ==  lfsAuthenticateVerb  {
249- 		if  lfsVerb  ==  "upload"  {
250- 			requestedMode  =  perm .AccessModeWrite 
251- 		} else  if  lfsVerb  ==  "download"  {
252- 			requestedMode  =  perm .AccessModeRead 
253- 		} else  {
254- 			return  fail (ctx , "Unknown LFS verb" , "Unknown lfs verb %s" , lfsVerb )
255- 		}
256- 	}
272+ 	requestedMode  :=  getAccessMode (verb , lfsVerb )
257273
258274	results , extra  :=  private .ServCommand (ctx , keyID , username , reponame , requestedMode , verb , lfsVerb )
259275	if  extra .HasError () {
260276		return  fail (ctx , extra .UserMsg , "ServCommand failed: %s" , extra .Error )
261277	}
262278
263279	// LFS token authentication 
264- 	if  verb  ==  lfsAuthenticateVerb  {
280+ 	if  verb  ==  verbLfsAuthenticate  {
265281		url  :=  fmt .Sprintf ("%s%s/%s.git/info/lfs" , setting .AppURL , url .PathEscape (results .OwnerName ), url .PathEscape (results .RepoName ))
266282
267283		now  :=  time .Now ()
@@ -296,22 +312,22 @@ func runServ(c *cli.Context) error {
296312		return  nil 
297313	}
298314
299- 	var  gitcmd  * exec.Cmd 
300315	gitBinPath  :=  filepath .Dir (git .GitExecutable ) // e.g. /usr/bin 
301316	gitBinVerb  :=  filepath .Join (gitBinPath , verb ) // e.g. /usr/bin/git-upload-pack 
317+ 	gitExe  :=  gitBinVerb 
318+ 	gitArgs  :=  make ([]string , 0 , 3 ) // capacity to accommodate max args 
302319	if  _ , err  :=  os .Stat (gitBinVerb ); err  !=  nil  {
303320		// if the command "git-upload-pack" doesn't exist, try to split "git-upload-pack" to use the sub-command with git 
304321		// ps: Windows only has "git.exe" in the bin path, so Windows always uses this way 
305322		verbFields  :=  strings .SplitN (verb , "-" , 2 )
306323		if  len (verbFields ) ==  2  {
307324			// use git binary with the sub-command part: "C:\...\bin\git.exe", "upload-pack", ... 
308- 			gitcmd  =  exec .CommandContext (ctx , git .GitExecutable , verbFields [1 ], repoPath )
325+ 			gitExe  =  git .GitExecutable 
326+ 			gitArgs  =  append (gitArgs , verbFields [1 ])
309327		}
310328	}
311- 	if  gitcmd  ==  nil  {
312- 		// by default, use the verb (it has been checked above by allowedCommands) 
313- 		gitcmd  =  exec .CommandContext (ctx , gitBinVerb , repoPath )
314- 	}
329+ 	gitArgs  =  append (gitArgs , repoPath )
330+ 	gitcmd  :=  exec .CommandContext (ctx , gitExe , gitArgs ... )
315331
316332	process .SetSysProcAttribute (gitcmd )
317333	gitcmd .Dir  =  setting .RepoRootPath 
0 commit comments