2020-07-10 14:17:51 +00:00
|
|
|
package object
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"crypto/ecdsa"
|
|
|
|
|
|
|
|
"github.com/nspcc-dev/neofs-api-go/service"
|
|
|
|
crypto "github.com/nspcc-dev/neofs-crypto"
|
2020-07-24 13:54:03 +00:00
|
|
|
"github.com/nspcc-dev/neofs-node/pkg/services/id"
|
|
|
|
"github.com/pkg/errors"
|
2020-07-10 14:17:51 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2020-07-24 13:54:03 +00:00
|
|
|
var errCreatedAfterExpiration = errors.New("creation epoch number is greater than expired one")
|
2020-07-10 14:17:51 +00:00
|
|
|
|
2020-07-24 13:54:03 +00:00
|
|
|
var errTokenExpired = errors.New("token is expired")
|
2020-07-10 14:17:51 +00:00
|
|
|
|
2020-07-24 13:54:03 +00:00
|
|
|
var errForbiddenSpawn = errors.New("request spawn is forbidden")
|
2020-07-10 14:17:51 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2020-07-24 13:54:03 +00:00
|
|
|
if err := id.VerifyKey(token); err != nil {
|
2020-07-10 14:17:51 +00:00
|
|
|
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
|
|
|
|
}
|