From f0537b35c149fef9fadd9a88cf2b6f800ff366fa Mon Sep 17 00:00:00 2001 From: Alex Vanin Date: Thu, 19 Nov 2020 17:17:15 +0300 Subject: [PATCH] [#190] Add isOwnerFromKey helper function in ACL This function takes public key and returns true if owner id was produced by this key. Signed-off-by: Alex Vanin --- pkg/services/object/acl/acl.go | 38 ++++++++++++++++----------- pkg/services/object/acl/classifier.go | 9 +++---- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/pkg/services/object/acl/acl.go b/pkg/services/object/acl/acl.go index bee06cf63..ae6eaf46e 100644 --- a/pkg/services/object/acl/acl.go +++ b/pkg/services/object/acl/acl.go @@ -3,6 +3,7 @@ package acl import ( "bytes" "context" + "crypto/ecdsa" "fmt" acl "github.com/nspcc-dev/neofs-api-go/pkg/acl/eacl" @@ -639,29 +640,17 @@ func isValidBearer(reqInfo requestInfo, st netmap.State) bool { // 3. Then check if container owner signed this token. tokenIssuerKey := crypto.UnmarshalPublicKey(token.GetSignature().GetKey()) - tokenIssuerWallet, err := owner.NEO3WalletFromPublicKey(tokenIssuerKey) - if err != nil { - return false - } - // here we compare `owner.ID -> wallet` with `wallet <- publicKey` - // consider making equal method on owner.ID structure - // we can compare .String() version of owners but don't think it is good idea - // binary comparison is better but MarshalBinary is more expensive - if !bytes.Equal(reqInfo.owner.ToV2().GetValue(), tokenIssuerWallet.Bytes()) { + if !isOwnerFromKey(reqInfo.owner, tokenIssuerKey) { // todo: in this case we can issue all owner keys from neofs.id and check once again return false } // 4. Then check if request sender has rights to use this token. - tokenOwnerField := token.GetBody().GetOwnerID() + tokenOwnerField := owner.NewIDFromV2(token.GetBody().GetOwnerID()) if tokenOwnerField != nil { // see bearer token owner field description requestSenderKey := crypto.UnmarshalPublicKey(reqInfo.senderKey) - requestSenderWallet, err := owner.NEO3WalletFromPublicKey(requestSenderKey) - if err != nil { - return false - } - // the same issue as above - if !bytes.Equal(tokenOwnerField.GetValue(), requestSenderWallet.Bytes()) { + if !isOwnerFromKey(tokenOwnerField, requestSenderKey) { + // todo: in this case we can issue all owner keys from neofs.id and check once again return false } } @@ -677,3 +666,20 @@ func isValidLifetime(lifetime *bearer.TokenLifetime, epoch uint64) bool { // RFC 7519 sections 4.1.4, 4.1.5 return epoch >= lifetime.GetNbf() && epoch <= lifetime.GetExp() } + +func isOwnerFromKey(id *owner.ID, key *ecdsa.PublicKey) bool { + if id == nil || key == nil { + return false + } + + wallet, err := owner.NEO3WalletFromPublicKey(key) + if err != nil { + return false + } + + // here we compare `owner.ID -> wallet` with `wallet <- publicKey` + // consider making equal method on owner.ID structure + // we can compare .String() version of owners but don't think it is good idea + // binary comparison is better but MarshalBinary is more expensive + return bytes.Equal(id.ToV2().GetValue(), wallet.Bytes()) +} diff --git a/pkg/services/object/acl/classifier.go b/pkg/services/object/acl/classifier.go index c3013164e..6528461af 100644 --- a/pkg/services/object/acl/classifier.go +++ b/pkg/services/object/acl/classifier.go @@ -201,15 +201,12 @@ func ownerFromToken(token *session.SessionToken) (*owner.ID, *ecdsa.PublicKey, e // 2. Then check if session token owner issued the session token tokenIssuerKey := crypto.UnmarshalPublicKey(token.GetSignature().GetKey()) - tokenIssuerWallet, err := owner.NEO3WalletFromPublicKey(tokenIssuerKey) - if err != nil { - return nil, nil, errors.Wrap(ErrMalformedRequest, "invalid token issuer key") - } + tokenOwner := owner.NewIDFromV2(token.GetBody().GetOwnerID()) - if !bytes.Equal(token.GetBody().GetOwnerID().GetValue(), tokenIssuerWallet.Bytes()) { + if !isOwnerFromKey(tokenOwner, tokenIssuerKey) { // todo: in this case we can issue all owner keys from neofs.id and check once again return nil, nil, errors.Wrap(ErrMalformedRequest, "invalid session token owner") } - return owner.NewIDFromV2(token.GetBody().GetOwnerID()), tokenIssuerKey, nil + return tokenOwner, tokenIssuerKey, nil }