[#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 <alexey@nspcc.ru>
This commit is contained in:
Alex Vanin 2020-11-19 17:17:15 +03:00 committed by Alex Vanin
parent a14bb6292b
commit f0537b35c1
2 changed files with 25 additions and 22 deletions

View file

@ -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())
}

View file

@ -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
}