You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ssh_key_commit_verification.go 2.1KB

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