From 2f38fef31af973e8d64036ee66f69d9aefa557bb Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Fri, 4 Jun 2021 18:02:25 +0300 Subject: [PATCH] [#589] ir/container: Verify session token lifetime Session tokens have limited lifetime in NeoFS. Container processor should verify lifetime of the incoming tokens. Define `NetworkState` interface with `Epoch` method to get number of the current epoch. Use Netmap contract client's wrapper as `NetworkState` of Container `Processor`. Check values of token lifetime, and deny if: * NBF value is gt the current epoch; * IAT is gt the current epoch; * EXP is le the current epoch. Signed-off-by: Leonard Lyubich --- go.mod | 2 +- go.sum | Bin 61029 -> 61242 bytes pkg/innerring/innerring.go | 1 + pkg/innerring/processors/container/common.go | 30 ++++++++++++++++++ .../processors/container/processor.go | 15 +++++++++ 5 files changed, 47 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 7399f6f9..6a0d5587 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/multiformats/go-multiaddr v0.3.1 github.com/nspcc-dev/hrw v1.0.9 github.com/nspcc-dev/neo-go v0.95.1 - github.com/nspcc-dev/neofs-api-go v1.27.0 + github.com/nspcc-dev/neofs-api-go v1.27.1-0.20210607102659-cc1163fd5797 github.com/nspcc-dev/neofs-crypto v0.3.0 github.com/nspcc-dev/neofs-sdk-go v0.0.0-20210520210714-9dee13f0d556 github.com/nspcc-dev/tzhash v1.4.0 diff --git a/go.sum b/go.sum index 2d7b4a8d390b95a03ec9651b1640a070d9ca24c4..3c19f2f7ea2624e1b319520f8c465b97ed0b7512 100644 GIT binary patch delta 243 zcmaEQhk4gM<_!gb`U)9_RzCX9<$eZLsYOvPxj}BBi3Py{nI+j~Y1)Ct+6GmLhDCwd zRbi#RnZ9nGn}Y+F$@m%S8t54r7#SLv8JHUy7@3(`>Lw=}8k!lWrI?yqnuE+N2z3h! z$TBi?O7u=i4X!LLbc*l_bqfhduQ2y8NcJ~0GuJi>_A)Uy$_kwvSR_8#Ax~JIfU%oH z@;-2Z9h?~&6j~JIUJ(%L7m!kEs_zjLoU0v~WtN}qWfofEnP!D)msXfLR!tVnmz%sHkC)M4^PRj8T$?4U6iWf_Z5^Zl diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index 89e6ff53..fe2cf89a 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -561,6 +561,7 @@ func New(ctx context.Context, log *zap.Logger, cfg *viper.Viper) (*Server, error FeeProvider: server.feeConfig, ContainerClient: cnrClient, NeoFSIDClient: neofsIDClient, + NetworkState: nmClient, }) if err != nil { return nil, err diff --git a/pkg/innerring/processors/container/common.go b/pkg/innerring/processors/container/common.go index 98e953af..562e780e 100644 --- a/pkg/innerring/processors/container/common.go +++ b/pkg/innerring/processors/container/common.go @@ -106,6 +106,12 @@ func (cp *Processor) checkSessionToken(token *session.Token) error { return errors.New("invalid signature") } + // check lifetime + err := cp.checkTokenLifetime(token) + if err != nil { + return err + } + // check token owner's key ownership key, err := keys.NewPublicKeyFromBytes(token.Signature().Key(), elliptic.P256()) @@ -149,3 +155,27 @@ func checkTokenContextWithCID(tok *session.Token, id *cid.ID, verbAssert verbAss return nil } + +func (cp *Processor) checkTokenLifetime(token *session.Token) error { + curEpoch, err := cp.netState.Epoch() + if err != nil { + return fmt.Errorf("could not read current epoch: %w", err) + } + + nbf := token.Nbf() + if curEpoch < nbf { + return fmt.Errorf("token is not valid yet: nbf %d, cur %d", nbf, curEpoch) + } + + iat := token.Iat() + if curEpoch < iat { + return fmt.Errorf("token is issued in future: iat %d, cur %d", iat, curEpoch) + } + + exp := token.Exp() + if curEpoch >= exp { + return fmt.Errorf("token is expired: exp %d, cur %d", exp, curEpoch) + } + + return nil +} diff --git a/pkg/innerring/processors/container/processor.go b/pkg/innerring/processors/container/processor.go index d68fed24..dcee3ae2 100644 --- a/pkg/innerring/processors/container/processor.go +++ b/pkg/innerring/processors/container/processor.go @@ -31,6 +31,7 @@ type ( feeProvider *config.FeeConfig cnrClient *wrapper.Wrapper // notary must be enabled idClient *neofsid.ClientWrapper + netState NetworkState } // Params of the processor constructor. @@ -43,9 +44,20 @@ type ( FeeProvider *config.FeeConfig ContainerClient *wrapper.Wrapper NeoFSIDClient *neofsid.ClientWrapper + NetworkState NetworkState } ) +// NetworkState is an interface of a component +// that provides access to network state. +type NetworkState interface { + // Epoch must return number of the current epoch. + // + // Must return any error encountered + // which did not allow reading the value. + Epoch() (uint64, error) +} + const ( putNotification = "containerPut" deleteNotification = "containerDelete" @@ -68,6 +80,8 @@ func New(p *Params) (*Processor, error) { return nil, errors.New("ir/container: Container client is not set") case p.NeoFSIDClient == nil: return nil, errors.New("ir/container: NeoFS ID client is not set") + case p.NetworkState == nil: + return nil, errors.New("ir/container: network state is not set") } p.Log.Debug("container worker pool", zap.Int("size", p.PoolSize)) @@ -86,6 +100,7 @@ func New(p *Params) (*Processor, error) { feeProvider: p.FeeProvider, cnrClient: p.ContainerClient, idClient: p.NeoFSIDClient, + netState: p.NetworkState, }, nil }