Skip to content

Commit 7a3bf37

Browse files
committed
Move ParseCommitWithSSHSignature to service layer
1 parent d54418a commit 7a3bf37

File tree

2 files changed

+66
-81
lines changed

2 files changed

+66
-81
lines changed

models/asymkey/ssh_key_commit_verification.go

Lines changed: 0 additions & 80 deletions
This file was deleted.

services/asymkey/commit.go

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
package asymkey
55

66
import (
7+
"bytes"
78
"context"
9+
"fmt"
810
"strings"
911

1012
asymkey_model "code.gitea.io/gitea/models/asymkey"
@@ -14,6 +16,7 @@ import (
1416
"code.gitea.io/gitea/modules/log"
1517
"code.gitea.io/gitea/modules/setting"
1618

19+
"github.com/42wim/sshsig"
1720
"github.com/ProtonMail/go-crypto/openpgp/packet"
1821
)
1922

@@ -57,7 +60,7 @@ func ParseCommitWithSignatureCommitter(ctx context.Context, c *git.Commit, commi
5760

5861
// If this a SSH signature handle it differently
5962
if strings.HasPrefix(c.Signature.Signature, "-----BEGIN SSH SIGNATURE-----") {
60-
return asymkey_model.ParseCommitWithSSHSignature(ctx, c, committer)
63+
return ParseCommitWithSSHSignature(ctx, c, committer)
6164
}
6265

6366
// Parsing signature
@@ -361,3 +364,65 @@ func VerifyWithGPGSettings(ctx context.Context, gpgSettings *git.GPGSettings, si
361364
}
362365
return nil
363366
}
367+
368+
// ParseCommitWithSSHSignature check if signature is good against keystore.
369+
func ParseCommitWithSSHSignature(ctx context.Context, c *git.Commit, committer *user_model.User) *asymkey_model.CommitVerification {
370+
// Now try to associate the signature with the committer, if present
371+
if committer.ID != 0 {
372+
keys, err := db.Find[asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{
373+
OwnerID: committer.ID,
374+
NotKeytype: asymkey_model.KeyTypePrincipal,
375+
})
376+
if err != nil { // Skipping failed to get ssh keys of user
377+
log.Error("ListPublicKeys: %v", err)
378+
return &asymkey_model.CommitVerification{
379+
CommittingUser: committer,
380+
Verified: false,
381+
Reason: "gpg.error.failed_retrieval_gpg_keys",
382+
}
383+
}
384+
385+
committerEmailAddresses, err := user_model.GetEmailAddresses(ctx, committer.ID)
386+
if err != nil {
387+
log.Error("GetEmailAddresses: %v", err)
388+
}
389+
390+
activated := false
391+
for _, e := range committerEmailAddresses {
392+
if e.IsActivated && strings.EqualFold(e.Email, c.Committer.Email) {
393+
activated = true
394+
break
395+
}
396+
}
397+
398+
for _, k := range keys {
399+
if k.Verified && activated {
400+
commitVerification := verifySSHCommitVerification(c.Signature.Signature, c.Signature.Payload, k, committer, committer, c.Committer.Email)
401+
if commitVerification != nil {
402+
return commitVerification
403+
}
404+
}
405+
}
406+
}
407+
408+
return &asymkey_model.CommitVerification{
409+
CommittingUser: committer,
410+
Verified: false,
411+
Reason: asymkey_model.NoKeyFound,
412+
}
413+
}
414+
415+
func verifySSHCommitVerification(sig, payload string, k *asymkey_model.PublicKey, committer, signer *user_model.User, email string) *asymkey_model.CommitVerification {
416+
if err := sshsig.Verify(bytes.NewBuffer([]byte(payload)), []byte(sig), []byte(k.Content), "git"); err != nil {
417+
return nil
418+
}
419+
420+
return &asymkey_model.CommitVerification{ // Everything is ok
421+
CommittingUser: committer,
422+
Verified: true,
423+
Reason: fmt.Sprintf("%s / %s", signer.Name, k.Fingerprint),
424+
SigningUser: signer,
425+
SigningSSHKey: k,
426+
SigningEmail: email,
427+
}
428+
}

0 commit comments

Comments
 (0)