@@ -5,6 +5,7 @@ package asymkey
5
5
6
6
import (
7
7
"context"
8
+ "fmt"
8
9
"strings"
9
10
10
11
asymkey_model "code.gitea.io/gitea/models/asymkey"
@@ -14,6 +15,7 @@ import (
14
15
"code.gitea.io/gitea/modules/log"
15
16
"code.gitea.io/gitea/modules/setting"
16
17
18
+ "github.com/42wim/sshsig"
17
19
"github.com/ProtonMail/go-crypto/openpgp/packet"
18
20
)
19
21
@@ -57,7 +59,7 @@ func ParseCommitWithSignatureCommitter(ctx context.Context, c *git.Commit, commi
57
59
58
60
// If this a SSH signature handle it differently
59
61
if strings .HasPrefix (c .Signature .Signature , "-----BEGIN SSH SIGNATURE-----" ) {
60
- return asymkey_model . ParseCommitWithSSHSignature (ctx , c , committer )
62
+ return ParseCommitWithSSHSignature (ctx , c , committer )
61
63
}
62
64
63
65
// Parsing signature
@@ -361,3 +363,65 @@ func VerifyWithGPGSettings(ctx context.Context, gpgSettings *git.GPGSettings, si
361
363
}
362
364
return nil
363
365
}
366
+
367
+ // ParseCommitWithSSHSignature check if signature is good against keystore.
368
+ func ParseCommitWithSSHSignature (ctx context.Context , c * git.Commit , committer * user_model.User ) * asymkey_model.CommitVerification {
369
+ // Now try to associate the signature with the committer, if present
370
+ if committer .ID != 0 {
371
+ keys , err := db .Find [asymkey_model.PublicKey ](ctx , asymkey_model.FindPublicKeyOptions {
372
+ OwnerID : committer .ID ,
373
+ NotKeytype : asymkey_model .KeyTypePrincipal ,
374
+ })
375
+ if err != nil { // Skipping failed to get ssh keys of user
376
+ log .Error ("ListPublicKeys: %v" , err )
377
+ return & asymkey_model.CommitVerification {
378
+ CommittingUser : committer ,
379
+ Verified : false ,
380
+ Reason : "gpg.error.failed_retrieval_gpg_keys" ,
381
+ }
382
+ }
383
+
384
+ committerEmailAddresses , err := user_model .GetEmailAddresses (ctx , committer .ID )
385
+ if err != nil {
386
+ log .Error ("GetEmailAddresses: %v" , err )
387
+ }
388
+
389
+ activated := false
390
+ for _ , e := range committerEmailAddresses {
391
+ if e .IsActivated && strings .EqualFold (e .Email , c .Committer .Email ) {
392
+ activated = true
393
+ break
394
+ }
395
+ }
396
+
397
+ for _ , k := range keys {
398
+ if k .Verified && activated {
399
+ commitVerification := verifySSHCommitVerification (c .Signature .Signature , c .Signature .Payload , k , committer , committer , c .Committer .Email )
400
+ if commitVerification != nil {
401
+ return commitVerification
402
+ }
403
+ }
404
+ }
405
+ }
406
+
407
+ return & asymkey_model.CommitVerification {
408
+ CommittingUser : committer ,
409
+ Verified : false ,
410
+ Reason : asymkey_model .NoKeyFound ,
411
+ }
412
+ }
413
+
414
+ func verifySSHCommitVerification (sig , payload string , k * asymkey_model.PublicKey , committer , signer * user_model.User , email string ) * asymkey_model.CommitVerification {
415
+ if err := sshsig .Verify (strings .NewReader (payload ), []byte (sig ), []byte (k .Content ), "git" ); err != nil {
416
+ return nil
417
+ }
418
+
419
+ return & asymkey_model.CommitVerification { // Everything is ok
420
+ CommittingUser : committer ,
421
+ Verified : true ,
422
+ Reason : fmt .Sprintf ("%s / %s" , signer .Name , k .Fingerprint ),
423
+ SigningUser : signer ,
424
+ SigningSSHKey : k ,
425
+ SigningEmail : email ,
426
+ }
427
+ }
0 commit comments