diff --git a/CHANGELOG.md b/CHANGELOG.md index fb0b23582f..354b7c2cb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Changelog for NeoFS Node ### Fixed - Resending the header after chunks have already been sent in object service `Get` handler (#3833) - GC deadlock on local object storage shutdown (#3837) +- `owner mismatches signature` for stored objects (#3836) ### Changed diff --git a/internal/crypto/object.go b/internal/crypto/object.go index 717fa1ea85..ab9b69a707 100644 --- a/internal/crypto/object.go +++ b/internal/crypto/object.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" + "github.com/nspcc-dev/neofs-node/pkg/core/version" neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" "github.com/nspcc-dev/neofs-sdk-go/object" @@ -78,7 +79,9 @@ func AuthenticateObject(obj object.Object, fsChain HistoricN3ScriptRunner, ecPar if !verifyECDSAFns[scheme](*ecdsaPub, sig.Value(), obj.GetID().Marshal()) { return schemeError(scheme, errSignatureMismatch) } - if sessionToken == nil && sessionTokenV2 == nil && !ecPart && user.NewFromECDSAPublicKey(*ecdsaPub) != obj.Owner() { + if sessionToken == nil && sessionTokenV2 == nil && !ecPart && + user.NewFromECDSAPublicKey(*ecdsaPub) != obj.Owner() && + version.OwnerSignatureMatchRequired(obj.Version()) { return errors.New("owner mismatches signature") } case neofscrypto.N3: diff --git a/pkg/core/version/version.go b/pkg/core/version/version.go index 97a96c2ddb..5735dd917c 100644 --- a/pkg/core/version/version.go +++ b/pkg/core/version/version.go @@ -22,6 +22,24 @@ func SysObjTargetShouldBeInHeader(v *version.Version) bool { (v.Major() == latestSysObjTargetInPayloadMjr && v.Minor() > latestSysObjTargetInPayloadMnr) } +// OwnerSignatureMatchRequired returns true if an object with the given version +// must have the owner matching the signature's public key. Objects below version +// 2.18 may have a mismatching owner due to a bug that allowed creating such +// objects, so they should not be rejected. +func OwnerSignatureMatchRequired(v *version.Version) bool { + if v == nil || !IsValid(*v) { + return true // assume latest + } + + const ( + ownerMatchMjr = 2 + ownerMatchMnr = 18 + ) + + return v.Major() > ownerMatchMjr || + (v.Major() == ownerMatchMjr && v.Minor() >= ownerMatchMnr) +} + // IsValid checks if Version is not earlier than the genesis version of the NeoFS. func IsValid(v version.Version) bool { const (