diff --git a/pkg/innerring/processors/container/common.go b/pkg/innerring/processors/container/common.go index e6ee24ad66..f753f6953b 100644 --- a/pkg/innerring/processors/container/common.go +++ b/pkg/innerring/processors/container/common.go @@ -4,7 +4,14 @@ import ( "crypto/ecdsa" "errors" "fmt" - + "slices" + + "github.com/nspcc-dev/neo-go/pkg/core/block" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "github.com/nspcc-dev/neo-go/pkg/crypto/hash" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" + "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neofs-node/pkg/morph/client/neofsid" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" @@ -88,6 +95,44 @@ func (cp *Processor) verifySignature(v signatureVerificationData) error { if user.NewFromECDSAPublicKey(ecdsa.PublicKey(signerPub)) != v.ownerContainer { return errors.New("session token is not signed by the container owner") } + case 3: // TODO: use const after SDK upgrade + invocScript, verifScript := sig.Value(), sig.PublicKeyBytes() + if len(verifScript) > 0 { + issuer := tok.Issuer() + acc := hash.Hash160(verifScript) + if inToken := util.Uint160(issuer[1:][:util.Uint160Size]); inToken != acc { + return fmt.Errorf("session token's issuer account %s not equals the verification script hash %s", inToken, acc) + } + // TODO: scripts may be stateless like simple- or multi-signature, they do not require exec on a VM + iatEpoch := tok.Iat() + iatHeight, err := interface { + HeightAtEpoch(uint64) (uint32, error) + }(nil).HeightAtEpoch(tok.Iat()) + if err != nil { + return fmt.Errorf("get FS chain height (session iat: epoch#%d): %w", iatEpoch, err) + } + blkHdr, err := interface { + GetBlockHeaderByIndex(uint32) (block.Header, error) + }(nil).GetBlockHeaderByIndex(iatHeight) + if err != nil { + return fmt.Errorf("get FS chain block header (session iat: epoch#%d, height#%d): %w", iatHeight, iatEpoch, err) + } + // FIXME: add signed token data to the exec context + tx := &transaction.Transaction{ + Script: slices.Concat(invocScript, verifScript), + Signers: []transaction.Signer{{Account: acc}}, + // FIXME: what else? + } + // w8 4 https://github.com/nspcc-dev/neo-go/issues/3836 + ok, err := unwrap.Bool(cp.cnrClient.Morph().InvokeContainedScript(tx, blkHdr, trigger.Verification)) + if err != nil { + return fmt.Errorf("invoke contained auth script on FS chain (session iat: epoch#%d, height#%d): %w", iatHeight, iatEpoch, err) + } + if !ok { + return fmt.Errorf("auth script run on FS chain resulted in false (session iat: epoch#%d, height#%d)", iatHeight, iatEpoch) + } + } else { // FIXME: what? + } } if keyProvided && !tok.AssertAuthKey(&key) { @@ -111,6 +156,7 @@ func (cp *Processor) verifySignature(v signatureVerificationData) error { return fmt.Errorf("check session lifetime: %w", err) } + // TODO: support N3 accounts as well if !tok.VerifySessionDataSignature(v.signedData, v.signature) { return errors.New("invalid signature calculated with session key") }