@@ -11,7 +11,6 @@ import (
11
11
"os"
12
12
"os/exec"
13
13
"path/filepath"
14
- "regexp"
15
14
"strconv"
16
15
"strings"
17
16
"time"
@@ -20,7 +19,7 @@ import (
20
19
asymkey_model "code.gitea.io/gitea/models/asymkey"
21
20
git_model "code.gitea.io/gitea/models/git"
22
21
"code.gitea.io/gitea/models/perm"
23
- "code.gitea.io/gitea/modules/container "
22
+ "code.gitea.io/gitea/models/repo "
24
23
"code.gitea.io/gitea/modules/git"
25
24
"code.gitea.io/gitea/modules/json"
26
25
"code.gitea.io/gitea/modules/lfstransfer"
@@ -37,14 +36,6 @@ import (
37
36
"github.com/urfave/cli/v2"
38
37
)
39
38
40
- const (
41
- verbUploadPack = "git-upload-pack"
42
- verbUploadArchive = "git-upload-archive"
43
- verbReceivePack = "git-receive-pack"
44
- verbLfsAuthenticate = "git-lfs-authenticate"
45
- verbLfsTransfer = "git-lfs-transfer"
46
- )
47
-
48
39
// CmdServ represents the available serv sub-command.
49
40
var CmdServ = & cli.Command {
50
41
Name : "serv" ,
@@ -78,22 +69,6 @@ func setup(ctx context.Context, debug bool) {
78
69
}
79
70
}
80
71
81
- var (
82
- // keep getAccessMode() in sync
83
- allowedCommands = container .SetOf (
84
- verbUploadPack ,
85
- verbUploadArchive ,
86
- verbReceivePack ,
87
- verbLfsAuthenticate ,
88
- verbLfsTransfer ,
89
- )
90
- allowedCommandsLfs = container .SetOf (
91
- verbLfsAuthenticate ,
92
- verbLfsTransfer ,
93
- )
94
- alphaDashDotPattern = regexp .MustCompile (`[^\w-\.]` )
95
- )
96
-
97
72
// fail prints message to stdout, it's mainly used for git serv and git hook commands.
98
73
// The output will be passed to git client and shown to user.
99
74
func fail (ctx context.Context , userMessage , logMsgFmt string , args ... any ) error {
@@ -139,19 +114,20 @@ func handleCliResponseExtra(extra private.ResponseExtra) error {
139
114
140
115
func getAccessMode (verb , lfsVerb string ) perm.AccessMode {
141
116
switch verb {
142
- case verbUploadPack , verbUploadArchive :
117
+ case git . CmdVerbUploadPack , git . CmdVerbUploadArchive :
143
118
return perm .AccessModeRead
144
- case verbReceivePack :
119
+ case git . CmdVerbReceivePack :
145
120
return perm .AccessModeWrite
146
- case verbLfsAuthenticate , verbLfsTransfer :
121
+ case git . CmdVerbLfsAuthenticate , git . CmdVerbLfsTransfer :
147
122
switch lfsVerb {
148
- case "upload" :
123
+ case git . CmdSubVerbLfsUpload :
149
124
return perm .AccessModeWrite
150
- case "download" :
125
+ case git . CmdSubVerbLfsDownload :
151
126
return perm .AccessModeRead
152
127
}
153
128
}
154
129
// should be unreachable
130
+ setting .PanicInDevOrTesting ("unknown verb: %s %s" , verb , lfsVerb )
155
131
return perm .AccessModeNone
156
132
}
157
133
@@ -230,12 +206,12 @@ func runServ(c *cli.Context) error {
230
206
log .Debug ("SSH_ORIGINAL_COMMAND: %s" , os .Getenv ("SSH_ORIGINAL_COMMAND" ))
231
207
}
232
208
233
- words , err := shellquote .Split (cmd )
209
+ sshCmdArgs , err := shellquote .Split (cmd )
234
210
if err != nil {
235
211
return fail (ctx , "Error parsing arguments" , "Failed to parse arguments: %v" , err )
236
212
}
237
213
238
- if len (words ) < 2 {
214
+ if len (sshCmdArgs ) < 2 {
239
215
if git .DefaultFeatures ().SupportProcReceive {
240
216
// for AGit Flow
241
217
if cmd == "ssh_info" {
@@ -246,25 +222,21 @@ func runServ(c *cli.Context) error {
246
222
return fail (ctx , "Too few arguments" , "Too few arguments in cmd: %s" , cmd )
247
223
}
248
224
249
- verb := words [0 ]
250
- repoPath := strings .TrimPrefix (words [1 ], "/" )
251
-
252
- var lfsVerb string
253
-
254
- rr := strings .SplitN (repoPath , "/" , 2 )
255
- if len (rr ) != 2 {
225
+ repoPath := strings .TrimPrefix (sshCmdArgs [1 ], "/" )
226
+ repoPathFields := strings .SplitN (repoPath , "/" , 2 )
227
+ if len (repoPathFields ) != 2 {
256
228
return fail (ctx , "Invalid repository path" , "Invalid repository path: %v" , repoPath )
257
229
}
258
230
259
- username := rr [0 ]
260
- reponame := strings .TrimSuffix (rr [1 ], ".git" )
231
+ username := repoPathFields [0 ]
232
+ reponame := strings .TrimSuffix (repoPathFields [1 ], ".git" ) // “the-repo-name" or "the-repo-name.wiki"
261
233
262
234
// LowerCase and trim the repoPath as that's how they are stored.
263
235
// This should be done after splitting the repoPath into username and reponame
264
236
// so that username and reponame are not affected.
265
237
repoPath = strings .ToLower (strings .TrimSpace (repoPath ))
266
238
267
- if alphaDashDotPattern . MatchString (reponame ) {
239
+ if ! repo . IsValidSSHAccessRepoName (reponame ) {
268
240
return fail (ctx , "Invalid repo name" , "Invalid repo name: %s" , reponame )
269
241
}
270
242
@@ -286,22 +258,23 @@ func runServ(c *cli.Context) error {
286
258
}()
287
259
}
288
260
289
- if allowedCommands .Contains (verb ) {
290
- if allowedCommandsLfs .Contains (verb ) {
291
- if ! setting .LFS .StartServer {
292
- return fail (ctx , "LFS Server is not enabled" , "" )
293
- }
294
- if verb == verbLfsTransfer && ! setting .LFS .AllowPureSSH {
295
- return fail (ctx , "LFS SSH transfer is not enabled" , "" )
296
- }
297
- if len (words ) > 2 {
298
- lfsVerb = words [2 ]
299
- }
300
- }
301
- } else {
261
+ verb , lfsVerb := sshCmdArgs [0 ], ""
262
+ if ! git .IsAllowedVerbForServe (verb ) {
302
263
return fail (ctx , "Unknown git command" , "Unknown git command %s" , verb )
303
264
}
304
265
266
+ if git .IsAllowedVerbForServeLfs (verb ) {
267
+ if ! setting .LFS .StartServer {
268
+ return fail (ctx , "LFS Server is not enabled" , "" )
269
+ }
270
+ if verb == git .CmdVerbLfsTransfer && ! setting .LFS .AllowPureSSH {
271
+ return fail (ctx , "LFS SSH transfer is not enabled" , "" )
272
+ }
273
+ if len (sshCmdArgs ) > 2 {
274
+ lfsVerb = sshCmdArgs [2 ]
275
+ }
276
+ }
277
+
305
278
requestedMode := getAccessMode (verb , lfsVerb )
306
279
307
280
results , extra := private .ServCommand (ctx , keyID , username , reponame , requestedMode , verb , lfsVerb )
@@ -310,7 +283,7 @@ func runServ(c *cli.Context) error {
310
283
}
311
284
312
285
// LFS SSH protocol
313
- if verb == verbLfsTransfer {
286
+ if verb == git . CmdVerbLfsTransfer {
314
287
token , err := getLFSAuthToken (ctx , lfsVerb , results )
315
288
if err != nil {
316
289
return err
@@ -319,7 +292,7 @@ func runServ(c *cli.Context) error {
319
292
}
320
293
321
294
// LFS token authentication
322
- if verb == verbLfsAuthenticate {
295
+ if verb == git . CmdVerbLfsAuthenticate {
323
296
url := fmt .Sprintf ("%s%s/%s.git/info/lfs" , setting .AppURL , url .PathEscape (results .OwnerName ), url .PathEscape (results .RepoName ))
324
297
325
298
token , err := getLFSAuthToken (ctx , lfsVerb , results )
0 commit comments