@@ -424,60 +424,40 @@ func (h *serviceHandler) sendFile(contentType, file string) {
424
424
// one or more key=value pairs separated by colons
425
425
var safeGitProtocolHeader = regexp .MustCompile (`^[0-9a-zA-Z]+=[0-9a-zA-Z]+(:[0-9a-zA-Z]+=[0-9a-zA-Z]+)*$` )
426
426
427
- func getGitConfig (ctx gocontext.Context , option , dir string ) string {
428
- out , _ , err := git .NewCommand (ctx , "config" ).AddDynamicArguments (option ).RunStdString (& git.RunOpts {Dir : dir })
429
- if err != nil {
430
- log .Error ("%v - %s" , err , out )
431
- }
432
- return out [0 : len (out )- 1 ]
433
- }
434
-
435
- func getConfigSetting (ctx gocontext.Context , service , dir string ) bool {
436
- service = strings .ReplaceAll (service , "-" , "" )
437
- setting := getGitConfig (ctx , "http." + service , dir )
438
-
439
- if service == "uploadpack" {
440
- return setting != "false"
441
- }
442
-
443
- return setting == "true"
444
- }
445
-
446
- func hasAccess (ctx gocontext.Context , service string , h serviceHandler , checkContentType bool ) bool {
447
- if checkContentType {
448
- if h .r .Header .Get ("Content-Type" ) != fmt .Sprintf ("application/x-git-%s-request" , service ) {
449
- return false
450
- }
427
+ func prepareGitCmdWithAllowedService (service string , h * serviceHandler ) (* git.Command , error ) {
428
+ if service == "receive-pack" && h .cfg .ReceivePack {
429
+ return git .NewCommand (h .r .Context (), "receive-pack" ), nil
451
430
}
452
-
453
- if ! (service == "upload-pack" || service == "receive-pack" ) {
454
- return false
455
- }
456
- if service == "receive-pack" {
457
- return h .cfg .ReceivePack
458
- }
459
- if service == "upload-pack" {
460
- return h .cfg .UploadPack
431
+ if service == "upload-pack" && h .cfg .UploadPack {
432
+ return git .NewCommand (h .r .Context (), "upload-pack" ), nil
461
433
}
462
434
463
- return getConfigSetting ( ctx , service , h . dir )
435
+ return nil , fmt . Errorf ( " service %q is not allowed" , service )
464
436
}
465
437
466
- func serviceRPC (ctx gocontext. Context , h serviceHandler , service string ) {
438
+ func serviceRPC (h * serviceHandler , service string ) {
467
439
defer func () {
468
440
if err := h .r .Body .Close (); err != nil {
469
441
log .Error ("serviceRPC: Close: %v" , err )
470
442
}
471
443
}()
472
444
473
- if ! hasAccess (ctx , service , h , true ) {
445
+ expectedContentType := fmt .Sprintf ("application/x-git-%s-request" , service )
446
+ if h .r .Header .Get ("Content-Type" ) != expectedContentType {
447
+ log .Error ("Content-Type (%q) doesn't match expected: %q" , h .r .Header .Get ("Content-Type" ), expectedContentType )
448
+ h .w .WriteHeader (http .StatusUnauthorized )
449
+ return
450
+ }
451
+
452
+ cmd , err := prepareGitCmdWithAllowedService (service , h )
453
+ if err != nil {
454
+ log .Error ("Failed to prepareGitCmdWithService: %v" , err )
474
455
h .w .WriteHeader (http .StatusUnauthorized )
475
456
return
476
457
}
477
458
478
459
h .w .Header ().Set ("Content-Type" , fmt .Sprintf ("application/x-git-%s-result" , service ))
479
460
480
- var err error
481
461
reqBody := h .r .Body
482
462
483
463
// Handle GZIP.
@@ -498,8 +478,7 @@ func serviceRPC(ctx gocontext.Context, h serviceHandler, service string) {
498
478
}
499
479
500
480
var stderr bytes.Buffer
501
- // the service is generated by ourselves, so it's safe to trust it
502
- cmd := git .NewCommand (h .r .Context (), git .ToTrustedCmdArgs ([]string {service })... ).AddArguments ("--stateless-rpc" ).AddDynamicArguments (h .dir )
481
+ cmd .AddArguments ("--stateless-rpc" ).AddDynamicArguments (h .dir )
503
482
cmd .SetDescription (fmt .Sprintf ("%s %s %s [repo_path: %s]" , git .GitExecutable , service , "--stateless-rpc" , h .dir ))
504
483
if err := cmd .Run (& git.RunOpts {
505
484
Dir : h .dir ,
@@ -520,15 +499,15 @@ func serviceRPC(ctx gocontext.Context, h serviceHandler, service string) {
520
499
func ServiceUploadPack (ctx * context.Context ) {
521
500
h := httpBase (ctx )
522
501
if h != nil {
523
- serviceRPC (ctx , * h , "upload-pack" )
502
+ serviceRPC (h , "upload-pack" )
524
503
}
525
504
}
526
505
527
506
// ServiceReceivePack implements Git Smart HTTP protocol
528
507
func ServiceReceivePack (ctx * context.Context ) {
529
508
h := httpBase (ctx )
530
509
if h != nil {
531
- serviceRPC (ctx , * h , "receive-pack" )
510
+ serviceRPC (h , "receive-pack" )
532
511
}
533
512
}
534
513
@@ -537,7 +516,7 @@ func getServiceType(r *http.Request) string {
537
516
if ! strings .HasPrefix (serviceType , "git-" ) {
538
517
return ""
539
518
}
540
- return strings .Replace (serviceType , "git-" , "" , 1 )
519
+ return strings .TrimPrefix (serviceType , "git-" )
541
520
}
542
521
543
522
func updateServerInfo (ctx gocontext.Context , dir string ) []byte {
@@ -563,16 +542,15 @@ func GetInfoRefs(ctx *context.Context) {
563
542
return
564
543
}
565
544
h .setHeaderNoCache ()
566
- if hasAccess ( ctx , getServiceType (h .r ), * h , false ) {
567
- service := getServiceType ( h . r )
568
-
545
+ service := getServiceType (h .r )
546
+ cmd , err := prepareGitCmdWithAllowedService ( service , h )
547
+ if err == nil {
569
548
if protocol := h .r .Header .Get ("Git-Protocol" ); protocol != "" && safeGitProtocolHeader .MatchString (protocol ) {
570
549
h .environ = append (h .environ , "GIT_PROTOCOL=" + protocol )
571
550
}
572
551
h .environ = append (os .Environ (), h .environ ... )
573
552
574
- // the service is generated by ourselves, so we can trust it
575
- refs , _ , err := git .NewCommand (ctx , git .ToTrustedCmdArgs ([]string {service })... ).AddArguments ("--stateless-rpc" , "--advertise-refs" , "." ).RunStdBytes (& git.RunOpts {Env : h .environ , Dir : h .dir })
553
+ refs , _ , err := cmd .AddArguments ("--stateless-rpc" , "--advertise-refs" , "." ).RunStdBytes (& git.RunOpts {Env : h .environ , Dir : h .dir })
576
554
if err != nil {
577
555
log .Error (fmt .Sprintf ("%v - %s" , err , string (refs )))
578
556
}
0 commit comments