[#525] ir/container: Check session verb and container ID

Token of the container session should be written out with container context.
The context should have the verb corresponding to the operation. If an
operation is performed on a fixed container, the session should be
propagated to it or to all user containers

Implement all described checks in validation of `Put` / `Delete` / `SetEACL`
events.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
Leonard Lyubich 2021-05-28 15:39:27 +03:00 committed by Leonard Lyubich
parent 25d87809c8
commit 23c5277014
3 changed files with 80 additions and 9 deletions

View file

@ -8,12 +8,19 @@ import (
"fmt"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
"github.com/nspcc-dev/neofs-api-go/pkg/session"
"github.com/nspcc-dev/neofs-api-go/util/signature"
signature2 "github.com/nspcc-dev/neofs-api-go/v2/signature"
)
var (
errWrongSessionContext = errors.New("wrong session context")
errWrongSessionVerb = errors.New("wrong token verb")
errWrongCID = errors.New("wrong container ID")
)
type ownerIDSource interface {
OwnerID() *owner.ID
}
@ -125,3 +132,37 @@ func (cp *Processor) checkSessionToken(token *session.Token) error {
return cp.checkKeyOwnership(token, key)
}
type verbAssert func(*session.ContainerContext) bool
func contextWithVerifiedVerb(tok *session.Token, verbAssert verbAssert) (*session.ContainerContext, error) {
c := session.GetContainerContext(tok)
if c == nil {
return nil, errWrongSessionContext
}
if !verbAssert(c) {
return nil, errWrongSessionVerb
}
return c, nil
}
func checkTokenContext(tok *session.Token, verbAssert verbAssert) error {
_, err := contextWithVerifiedVerb(tok, verbAssert)
return err
}
func checkTokenContextWithCID(tok *session.Token, id *cid.ID, verbAssert verbAssert) error {
c, err := contextWithVerifiedVerb(tok, verbAssert)
if err != nil {
return err
}
tokCID := c.Container()
if tokCID != nil && !tokCID.Equal(id) {
return errWrongCID
}
return nil
}

View file

@ -8,6 +8,9 @@ import (
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
containerSDK "github.com/nspcc-dev/neofs-api-go/pkg/container"
cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
"github.com/nspcc-dev/neofs-api-go/pkg/session"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
"github.com/nspcc-dev/neofs-node/pkg/core/container"
containerEvent "github.com/nspcc-dev/neofs-node/pkg/morph/event/container"
"go.uber.org/zap"
@ -67,7 +70,15 @@ func (cp *Processor) checkPutContainer(e *containerEvent.Put) error {
return err
}
// TODO: check verb and CID
if tok != nil {
// check token context
err = checkTokenContext(tok, func(c *session.ContainerContext) bool {
return c.IsForPut()
})
if err != nil {
return err
}
}
cnr.SetSessionToken(tok)
@ -104,10 +115,10 @@ func (cp *Processor) processContainerDelete(delete *containerEvent.Delete) {
}
func (cp *Processor) checkDeleteContainer(e *containerEvent.Delete) error {
cid := e.ContainerID()
binCID := e.ContainerID()
// receive owner of the related container
cnr, err := cp.cnrClient.Get(cid)
cnr, err := cp.cnrClient.Get(binCID)
if err != nil {
return fmt.Errorf("could not receive the container: %w", err)
}
@ -120,13 +131,25 @@ func (cp *Processor) checkDeleteContainer(e *containerEvent.Delete) error {
var checkKeys keys.PublicKeys
if token != nil {
// check token context
// TODO: think how to avoid version casts
idV2 := new(refs.ContainerID)
idV2.SetValue(binCID)
id := cid.NewFromV2(idV2)
err = checkTokenContextWithCID(token, id, func(c *session.ContainerContext) bool {
return c.IsForDelete()
})
if err != nil {
return err
}
key, err := keys.NewPublicKeyFromBytes(token.SessionKey(), elliptic.P256())
if err != nil {
return fmt.Errorf("invalid session key: %w", err)
}
// TODO: check verb and container ID
// check token ownership
err = cp.checkKeyOwnershipWithToken(cnr, key, token)
if err != nil {
@ -143,7 +166,7 @@ func (cp *Processor) checkDeleteContainer(e *containerEvent.Delete) error {
}
// verify signature
cidHash := sha256.Sum256(cid)
cidHash := sha256.Sum256(binCID)
sig := e.Signature()
for _, key := range checkKeys {

View file

@ -8,6 +8,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neofs-api-go/pkg/acl/eacl"
"github.com/nspcc-dev/neofs-api-go/pkg/session"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/container/wrapper"
"github.com/nspcc-dev/neofs-node/pkg/morph/event/container"
"go.uber.org/zap"
@ -67,9 +68,15 @@ func (cp *Processor) checkSetEACL(e container.SetEACL) error {
return err
}
cnr.SetSessionToken(tok)
// TODO: check verb and container ID
if tok != nil {
// check token context
err = checkTokenContextWithCID(tok, table.CID(), func(c *session.ContainerContext) bool {
return c.IsForSetEACL()
})
if err != nil {
return err
}
}
// check key ownership
return cp.checkKeyOwnership(cnr, key)