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

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