code.gitea.io/gitea@v1.21.7/models/asymkey/ssh_key_commit_verification.go (about) 1 // Copyright 2021 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package asymkey 5 6 import ( 7 "bytes" 8 "context" 9 "fmt" 10 "strings" 11 12 "code.gitea.io/gitea/models/db" 13 user_model "code.gitea.io/gitea/models/user" 14 "code.gitea.io/gitea/modules/git" 15 "code.gitea.io/gitea/modules/log" 16 17 "github.com/42wim/sshsig" 18 ) 19 20 // ParseCommitWithSSHSignature check if signature is good against keystore. 21 func ParseCommitWithSSHSignature(ctx context.Context, c *git.Commit, committer *user_model.User) *CommitVerification { 22 // Now try to associate the signature with the committer, if present 23 if committer.ID != 0 { 24 keys, err := ListPublicKeys(committer.ID, db.ListOptions{}) 25 if err != nil { // Skipping failed to get ssh keys of user 26 log.Error("ListPublicKeys: %v", err) 27 return &CommitVerification{ 28 CommittingUser: committer, 29 Verified: false, 30 Reason: "gpg.error.failed_retrieval_gpg_keys", 31 } 32 } 33 34 committerEmailAddresses, err := user_model.GetEmailAddresses(ctx, committer.ID) 35 if err != nil { 36 log.Error("GetEmailAddresses: %v", err) 37 } 38 39 activated := false 40 for _, e := range committerEmailAddresses { 41 if e.IsActivated && strings.EqualFold(e.Email, c.Committer.Email) { 42 activated = true 43 break 44 } 45 } 46 47 for _, k := range keys { 48 if k.Verified && activated { 49 commitVerification := verifySSHCommitVerification(c.Signature.Signature, c.Signature.Payload, k, committer, committer, c.Committer.Email) 50 if commitVerification != nil { 51 return commitVerification 52 } 53 } 54 } 55 } 56 57 return &CommitVerification{ 58 CommittingUser: committer, 59 Verified: false, 60 Reason: NoKeyFound, 61 } 62 } 63 64 func verifySSHCommitVerification(sig, payload string, k *PublicKey, committer, signer *user_model.User, email string) *CommitVerification { 65 if err := sshsig.Verify(bytes.NewBuffer([]byte(payload)), []byte(sig), []byte(k.Content), "git"); err != nil { 66 return nil 67 } 68 69 return &CommitVerification{ // Everything is ok 70 CommittingUser: committer, 71 Verified: true, 72 Reason: fmt.Sprintf("%s / %s", signer.Name, k.Fingerprint), 73 SigningUser: signer, 74 SigningSSHKey: k, 75 SigningEmail: email, 76 } 77 }