mirror of
https://github.com/go-gitea/gitea.git
synced 2025-10-01 08:08:44 +02:00
refactor
This commit is contained in:
parent
66866260a5
commit
838b984029
@ -15,25 +15,6 @@ import (
|
|||||||
"github.com/ProtonMail/go-crypto/openpgp/packet"
|
"github.com/ProtonMail/go-crypto/openpgp/packet"
|
||||||
)
|
)
|
||||||
|
|
||||||
// __________________ ________ ____ __.
|
|
||||||
// / _____/\______ \/ _____/ | |/ _|____ ___.__.
|
|
||||||
// / \ ___ | ___/ \ ___ | <_/ __ < | |
|
|
||||||
// \ \_\ \| | \ \_\ \ | | \ ___/\___ |
|
|
||||||
// \______ /|____| \______ / |____|__ \___ > ____|
|
|
||||||
// \/ \/ \/ \/\/
|
|
||||||
// _________ .__ __
|
|
||||||
// \_ ___ \ ____ _____ _____ |__|/ |_
|
|
||||||
// / \ \/ / _ \ / \ / \| \ __\
|
|
||||||
// \ \___( <_> ) Y Y \ Y Y \ || |
|
|
||||||
// \______ /\____/|__|_| /__|_| /__||__|
|
|
||||||
// \/ \/ \/
|
|
||||||
// ____ ____ .__ _____.__ __ .__
|
|
||||||
// \ \ / /___________|__|/ ____\__| ____ _____ _/ |_|__| ____ ____
|
|
||||||
// \ Y // __ \_ __ \ \ __\| |/ ___\\__ \\ __\ |/ _ \ / \
|
|
||||||
// \ /\ ___/| | \/ || | | \ \___ / __ \| | | ( <_> ) | \
|
|
||||||
// \___/ \___ >__| |__||__| |__|\___ >____ /__| |__|\____/|___| /
|
|
||||||
// \/ \/ \/ \/
|
|
||||||
|
|
||||||
// This file provides functions relating commit verification
|
// This file provides functions relating commit verification
|
||||||
|
|
||||||
// CommitVerification represents a commit validation of signature
|
// CommitVerification represents a commit validation of signature
|
||||||
@ -41,8 +22,8 @@ type CommitVerification struct {
|
|||||||
Verified bool
|
Verified bool
|
||||||
Warning bool
|
Warning bool
|
||||||
Reason string
|
Reason string
|
||||||
SigningUser *user_model.User
|
SigningUser *user_model.User // if Verified, then SigningUser is non-nil
|
||||||
CommittingUser *user_model.User
|
CommittingUser *user_model.User // if Verified, then CommittingUser is non-nil
|
||||||
SigningEmail string
|
SigningEmail string
|
||||||
SigningKey *GPGKey
|
SigningKey *GPGKey
|
||||||
SigningSSHKey *PublicKey
|
SigningSSHKey *PublicKey
|
||||||
|
@ -22,9 +22,9 @@ import (
|
|||||||
type Commit struct {
|
type Commit struct {
|
||||||
Tree // FIXME: bad design, this field can be nil if the commit is from "last commit cache"
|
Tree // FIXME: bad design, this field can be nil if the commit is from "last commit cache"
|
||||||
|
|
||||||
ID ObjectID // The ID of this commit object
|
ID ObjectID // The ID of this commit object
|
||||||
Author *Signature
|
Author *Signature // never nil
|
||||||
Committer *Signature
|
Committer *Signature // never nil
|
||||||
CommitMessage string
|
CommitMessage string
|
||||||
Signature *CommitSignature
|
Signature *CommitSignature
|
||||||
|
|
||||||
|
@ -24,47 +24,42 @@ import (
|
|||||||
|
|
||||||
// ParseCommitWithSignature check if signature is good against keystore.
|
// ParseCommitWithSignature check if signature is good against keystore.
|
||||||
func ParseCommitWithSignature(ctx context.Context, c *git.Commit) *asymkey_model.CommitVerification {
|
func ParseCommitWithSignature(ctx context.Context, c *git.Commit) *asymkey_model.CommitVerification {
|
||||||
var committer *user_model.User
|
committer, err := user_model.GetUserByEmail(ctx, c.Committer.Email)
|
||||||
if c.Committer != nil {
|
if err != nil && !user_model.IsErrUserNotExist(err) {
|
||||||
var err error
|
log.Error("GetUserByEmail: %v", err)
|
||||||
// Find Committer account
|
return &asymkey_model.CommitVerification{
|
||||||
committer, err = user_model.GetUserByEmail(ctx, c.Committer.Email) // This finds the user by primary email or activated email so commit will not be valid if email is not
|
Verified: false,
|
||||||
if err != nil { // Skipping not user for committer
|
Reason: "gpg.error.no_committer_account", // this error is not right, but such error should seldom happen
|
||||||
committer = &user_model.User{
|
|
||||||
Name: c.Committer.Name,
|
|
||||||
Email: c.Committer.Email,
|
|
||||||
}
|
|
||||||
// We can expect this to often be an ErrUserNotExist. in the case
|
|
||||||
// it is not, however, it is important to log it.
|
|
||||||
if !user_model.IsErrUserNotExist(err) {
|
|
||||||
log.Error("GetUserByEmail: %v", err)
|
|
||||||
return &asymkey_model.CommitVerification{
|
|
||||||
CommittingUser: committer,
|
|
||||||
Verified: false,
|
|
||||||
Reason: "gpg.error.no_committer_account",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ParseCommitWithSignatureCommitter(ctx, c, committer)
|
return ParseCommitWithSignatureCommitter(ctx, c, committer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseCommitWithSignatureCommitter parses a commit's GPG or SSH signature.
|
||||||
|
// If the commit is singed by an instance key, then committer is nil.
|
||||||
func ParseCommitWithSignatureCommitter(ctx context.Context, c *git.Commit, committer *user_model.User) *asymkey_model.CommitVerification {
|
func ParseCommitWithSignatureCommitter(ctx context.Context, c *git.Commit, committer *user_model.User) *asymkey_model.CommitVerification {
|
||||||
// If no signature just report the committer
|
// If no signature, just report the committer
|
||||||
if c.Signature == nil {
|
if c.Signature == nil {
|
||||||
return &asymkey_model.CommitVerification{
|
return &asymkey_model.CommitVerification{
|
||||||
CommittingUser: committer,
|
CommittingUser: committer,
|
||||||
Verified: false, // Default value
|
Verified: false,
|
||||||
Reason: "gpg.error.not_signed_commit", // Default value
|
Reason: "gpg.error.not_signed_commit",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// to support instance key, we need a fake committer user (not really needed, but legacy code accesses the committer without nil-check)
|
||||||
// If this a SSH signature handle it differently
|
if committer == nil {
|
||||||
if strings.HasPrefix(c.Signature.Signature, "-----BEGIN SSH SIGNATURE-----") {
|
committer = &user_model.User{
|
||||||
return ParseCommitWithSSHSignature(ctx, c, committer)
|
Name: c.Committer.Name,
|
||||||
|
Email: c.Committer.Email,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if strings.HasPrefix(c.Signature.Signature, "-----BEGIN SSH SIGNATURE-----") {
|
||||||
|
return parseCommitWithSSHSignature(ctx, c, committer)
|
||||||
|
}
|
||||||
|
return parseCommitWithGPGSignature(ctx, c, committer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseCommitWithGPGSignature(ctx context.Context, c *git.Commit, committer *user_model.User) *asymkey_model.CommitVerification {
|
||||||
// Parsing signature
|
// Parsing signature
|
||||||
sig, err := asymkey_model.ExtractSignature(c.Signature.Signature)
|
sig, err := asymkey_model.ExtractSignature(c.Signature.Signature)
|
||||||
if err != nil { // Skipping failed to extract sign
|
if err != nil { // Skipping failed to extract sign
|
||||||
@ -96,7 +91,7 @@ func ParseCommitWithSignatureCommitter(ctx context.Context, c *git.Commit, commi
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Now try to associate the signature with the committer, if present
|
// Now try to associate the signature with the committer, if present
|
||||||
if committer.ID != 0 {
|
if committer != nil && committer.ID != 0 {
|
||||||
keys, err := db.Find[asymkey_model.GPGKey](ctx, asymkey_model.FindGPGKeyOptions{
|
keys, err := db.Find[asymkey_model.GPGKey](ctx, asymkey_model.FindGPGKeyOptions{
|
||||||
OwnerID: committer.ID,
|
OwnerID: committer.ID,
|
||||||
})
|
})
|
||||||
@ -165,7 +160,7 @@ func ParseCommitWithSignatureCommitter(ctx context.Context, c *git.Commit, commi
|
|||||||
}
|
}
|
||||||
if err := gpgSettings.LoadPublicKeyContent(); err != nil {
|
if err := gpgSettings.LoadPublicKeyContent(); err != nil {
|
||||||
log.Error("Error getting default signing key: %s %v", gpgSettings.KeyID, err)
|
log.Error("Error getting default signing key: %s %v", gpgSettings.KeyID, err)
|
||||||
} else if commitVerification := VerifyWithGPGSettings(ctx, &gpgSettings, sig, c.Signature.Payload, committer, keyID); commitVerification != nil {
|
} else if commitVerification := verifyWithGPGSettings(ctx, &gpgSettings, sig, c.Signature.Payload, committer, keyID); commitVerification != nil {
|
||||||
if commitVerification.Reason == asymkey_model.BadSignature {
|
if commitVerification.Reason == asymkey_model.BadSignature {
|
||||||
defaultReason = asymkey_model.BadSignature
|
defaultReason = asymkey_model.BadSignature
|
||||||
} else {
|
} else {
|
||||||
@ -180,7 +175,7 @@ func ParseCommitWithSignatureCommitter(ctx context.Context, c *git.Commit, commi
|
|||||||
} else if defaultGPGSettings == nil {
|
} else if defaultGPGSettings == nil {
|
||||||
log.Warn("Unable to get defaultGPGSettings for unattached commit: %s", c.ID.String())
|
log.Warn("Unable to get defaultGPGSettings for unattached commit: %s", c.ID.String())
|
||||||
} else if defaultGPGSettings.Sign {
|
} else if defaultGPGSettings.Sign {
|
||||||
if commitVerification := VerifyWithGPGSettings(ctx, defaultGPGSettings, sig, c.Signature.Payload, committer, keyID); commitVerification != nil {
|
if commitVerification := verifyWithGPGSettings(ctx, defaultGPGSettings, sig, c.Signature.Payload, committer, keyID); commitVerification != nil {
|
||||||
if commitVerification.Reason == asymkey_model.BadSignature {
|
if commitVerification.Reason == asymkey_model.BadSignature {
|
||||||
defaultReason = asymkey_model.BadSignature
|
defaultReason = asymkey_model.BadSignature
|
||||||
} else {
|
} else {
|
||||||
@ -295,7 +290,7 @@ func HashAndVerifyForKeyID(ctx context.Context, sig *packet.Signature, payload s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func VerifyWithGPGSettings(ctx context.Context, gpgSettings *git.GPGSettings, sig *packet.Signature, payload string, committer *user_model.User, keyID string) *asymkey_model.CommitVerification {
|
func verifyWithGPGSettings(ctx context.Context, gpgSettings *git.GPGSettings, sig *packet.Signature, payload string, committer *user_model.User, keyID string) *asymkey_model.CommitVerification {
|
||||||
// First try to find the key in the db
|
// First try to find the key in the db
|
||||||
if commitVerification := HashAndVerifyForKeyID(ctx, sig, payload, committer, gpgSettings.KeyID, gpgSettings.Name, gpgSettings.Email); commitVerification != nil {
|
if commitVerification := HashAndVerifyForKeyID(ctx, sig, payload, committer, gpgSettings.KeyID, gpgSettings.Name, gpgSettings.Email); commitVerification != nil {
|
||||||
return commitVerification
|
return commitVerification
|
||||||
@ -375,10 +370,10 @@ func verifySSHCommitVerificationByInstanceKey(c *git.Commit, committerUser, sign
|
|||||||
return verifySSHCommitVerification(c.Signature.Signature, c.Signature.Payload, sshPubKey, committerUser, signerUser, committerGitEmail)
|
return verifySSHCommitVerification(c.Signature.Signature, c.Signature.Payload, sshPubKey, committerUser, signerUser, committerGitEmail)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseCommitWithSSHSignature check if signature is good against keystore.
|
// parseCommitWithSSHSignature check if signature is good against keystore.
|
||||||
func ParseCommitWithSSHSignature(ctx context.Context, c *git.Commit, committerUser *user_model.User) *asymkey_model.CommitVerification {
|
func parseCommitWithSSHSignature(ctx context.Context, c *git.Commit, committerUser *user_model.User) *asymkey_model.CommitVerification {
|
||||||
// Now try to associate the signature with the committer, if present
|
// Now try to associate the signature with the committer, if present
|
||||||
if committerUser.ID != 0 {
|
if committerUser != nil && committerUser.ID != 0 {
|
||||||
keys, err := db.Find[asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{
|
keys, err := db.Find[asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{
|
||||||
OwnerID: committerUser.ID,
|
OwnerID: committerUser.ID,
|
||||||
NotKeytype: asymkey_model.KeyTypePrincipal,
|
NotKeytype: asymkey_model.KeyTypePrincipal,
|
||||||
|
@ -41,7 +41,7 @@ Initial commit with signed file
|
|||||||
Name: "User Two",
|
Name: "User Two",
|
||||||
Email: "user2@example.com",
|
Email: "user2@example.com",
|
||||||
}
|
}
|
||||||
ret := ParseCommitWithSSHSignature(t.Context(), commit, committingUser)
|
ret := parseCommitWithSSHSignature(t.Context(), commit, committingUser)
|
||||||
require.NotNil(t, ret)
|
require.NotNil(t, ret)
|
||||||
assert.True(t, ret.Verified)
|
assert.True(t, ret.Verified)
|
||||||
assert.False(t, ret.Warning)
|
assert.False(t, ret.Warning)
|
||||||
|
@ -35,13 +35,6 @@ func ParseCommitsWithSignature(ctx context.Context, repo *repo_model.Repository,
|
|||||||
|
|
||||||
for _, c := range oldCommits {
|
for _, c := range oldCommits {
|
||||||
committerUser := emailUsers.GetByEmail(c.Committer.Email) // FIXME: why ValidateCommitsWithEmails uses "Author", but ParseCommitsWithSignature uses "Committer"?
|
committerUser := emailUsers.GetByEmail(c.Committer.Email) // FIXME: why ValidateCommitsWithEmails uses "Author", but ParseCommitsWithSignature uses "Committer"?
|
||||||
if committerUser == nil {
|
|
||||||
committerUser = &user_model.User{
|
|
||||||
Name: c.Committer.Name,
|
|
||||||
Email: c.Committer.Email,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
signCommit := &asymkey_model.SignCommit{
|
signCommit := &asymkey_model.SignCommit{
|
||||||
UserCommit: c,
|
UserCommit: c,
|
||||||
Verification: asymkey_service.ParseCommitWithSignatureCommitter(ctx, c.Commit, committerUser),
|
Verification: asymkey_service.ParseCommitWithSignatureCommitter(ctx, c.Commit, committerUser),
|
||||||
|
@ -147,7 +147,7 @@
|
|||||||
<div class="flex-text-inline">
|
<div class="flex-text-inline">
|
||||||
{{if or (ne .Commit.Committer.Name .Commit.Author.Name) (ne .Commit.Committer.Email .Commit.Author.Email)}}
|
{{if or (ne .Commit.Committer.Name .Commit.Author.Name) (ne .Commit.Committer.Email .Commit.Author.Email)}}
|
||||||
<span class="text grey">{{ctx.Locale.Tr "repo.diff.committed_by"}}</span>
|
<span class="text grey">{{ctx.Locale.Tr "repo.diff.committed_by"}}</span>
|
||||||
{{if ne .Verification.CommittingUser.ID 0}}
|
{{if and .Verification.CommittingUser .Verification.CommittingUser.ID}}
|
||||||
{{ctx.AvatarUtils.Avatar .Verification.CommittingUser 20}}
|
{{ctx.AvatarUtils.Avatar .Verification.CommittingUser 20}}
|
||||||
<a href="{{.Verification.CommittingUser.HomeLink}}"><strong>{{.Commit.Committer.Name}}</strong></a>
|
<a href="{{.Verification.CommittingUser.HomeLink}}"><strong>{{.Commit.Committer.Name}}</strong></a>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user