frostfs-node/pkg/network/transport/object/grpc/token.go
Stanislav Bogatyrev b7b5079934 Add Inner Ring code
2020-07-24 17:07:37 +03:00

105 lines
2.4 KiB
Go

package object
import (
"context"
"crypto/ecdsa"
"github.com/nspcc-dev/neofs-api-go/service"
crypto "github.com/nspcc-dev/neofs-crypto"
"github.com/nspcc-dev/neofs-node/pkg/services/id"
"github.com/pkg/errors"
)
type sessionTokenVerifier interface {
verifySessionToken(context.Context, service.SessionToken) error
}
type complexTokenVerifier struct {
verifiers []sessionTokenVerifier
}
type tokenSignatureVerifier struct {
ownerKeys []*ecdsa.PublicKey
}
type tokenEpochsVerifier struct {
epochRecv EpochReceiver
}
type tokenPreProcessor struct {
staticVerifier sessionTokenVerifier
}
var errCreatedAfterExpiration = errors.New("creation epoch number is greater than expired one")
var errTokenExpired = errors.New("token is expired")
var errForbiddenSpawn = errors.New("request spawn is forbidden")
func (s tokenPreProcessor) preProcess(ctx context.Context, req serviceRequest) error {
token := req.GetSessionToken()
if token == nil {
return nil
}
if !allowedSpawn(token.GetVerb(), req.Type()) {
return errForbiddenSpawn
}
if err := id.VerifyKey(token); err != nil {
return err
}
ownerKeyBytes := token.GetOwnerKey()
verifier := newComplexTokenVerifier(
s.staticVerifier,
&tokenSignatureVerifier{
ownerKeys: []*ecdsa.PublicKey{
crypto.UnmarshalPublicKey(ownerKeyBytes),
},
},
)
return verifier.verifySessionToken(ctx, token)
}
func newComplexTokenVerifier(verifiers ...sessionTokenVerifier) sessionTokenVerifier {
return &complexTokenVerifier{
verifiers: verifiers,
}
}
func (s complexTokenVerifier) verifySessionToken(ctx context.Context, token service.SessionToken) error {
for i := range s.verifiers {
if s.verifiers[i] == nil {
continue
} else if err := s.verifiers[i].verifySessionToken(ctx, token); err != nil {
return err
}
}
return nil
}
func (s tokenSignatureVerifier) verifySessionToken(ctx context.Context, token service.SessionToken) error {
verifiedToken := service.NewVerifiedSessionToken(token)
for i := range s.ownerKeys {
if err := service.VerifySignatureWithKey(s.ownerKeys[i], verifiedToken); err != nil {
return err
}
}
return nil
}
func (s tokenEpochsVerifier) verifySessionToken(ctx context.Context, token service.SessionToken) error {
if expired := token.ExpirationEpoch(); token.CreationEpoch() > expired {
return errCreatedAfterExpiration
} else if s.epochRecv.Epoch() > expired {
return errTokenExpired
}
return nil
}