From 23c52770148e5c7e35ceee7c7d71695ffb0d3636 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Fri, 28 May 2021 15:39:27 +0300 Subject: [PATCH] [#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 --- pkg/innerring/processors/container/common.go | 41 +++++++++++++++++++ .../processors/container/process_container.go | 35 +++++++++++++--- .../processors/container/process_eacl.go | 13 ++++-- 3 files changed, 80 insertions(+), 9 deletions(-) diff --git a/pkg/innerring/processors/container/common.go b/pkg/innerring/processors/container/common.go index 73112a3b6..be4da01c5 100644 --- a/pkg/innerring/processors/container/common.go +++ b/pkg/innerring/processors/container/common.go @@ -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 +} diff --git a/pkg/innerring/processors/container/process_container.go b/pkg/innerring/processors/container/process_container.go index 41c98fa33..c5f82ac4a 100644 --- a/pkg/innerring/processors/container/process_container.go +++ b/pkg/innerring/processors/container/process_container.go @@ -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 { diff --git a/pkg/innerring/processors/container/process_eacl.go b/pkg/innerring/processors/container/process_eacl.go index 8b4ef1572..920ffbd4e 100644 --- a/pkg/innerring/processors/container/process_eacl.go +++ b/pkg/innerring/processors/container/process_eacl.go @@ -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)