@@ -79,14 +79,20 @@ type sessionTokenCommonCheckResult struct {
7979 err error
8080}
8181
82+ type sessionTokenV2CommonCheckResult struct {
83+ token session.TokenV2
84+ err error
85+ }
86+
8287type server struct {
8388 protocontainer.UnimplementedContainerServiceServer
8489 signer * ecdsa.PrivateKey
8590 net netmap.State
8691 contract Contract
8792 historicN3ScriptRunner
8893
89- sessionTokenCommonCheckCache * lru.Cache [[sha256 .Size ]byte , sessionTokenCommonCheckResult ]
94+ sessionTokenCommonCheckCache * lru.Cache [[sha256 .Size ]byte , sessionTokenCommonCheckResult ]
95+ sessionTokenV2CommonCheckCache * lru.Cache [[sha256 .Size ]byte , sessionTokenV2CommonCheckResult ]
9096}
9197
9298// New provides protocontainer.ContainerServiceServer based on specified
@@ -99,6 +105,10 @@ func New(s *ecdsa.PrivateKey, net netmap.State, fsChain FSChain, c Contract, nc
99105 if err != nil {
100106 panic (fmt .Errorf ("unexpected error in lru.New: %w" , err ))
101107 }
108+ sessionTokenV2CheckCache , err := lru.New [[sha256 .Size ]byte , sessionTokenV2CommonCheckResult ](1000 )
109+ if err != nil {
110+ panic (fmt .Errorf ("unexpected error in lru.New for v2: %w" , err ))
111+ }
102112 return & server {
103113 signer : s ,
104114 net : net ,
@@ -107,7 +117,8 @@ func New(s *ecdsa.PrivateKey, net netmap.State, fsChain FSChain, c Contract, nc
107117 FSChain : fsChain ,
108118 NetmapContract : nc ,
109119 },
110- sessionTokenCommonCheckCache : sessionTokenCheckCache ,
120+ sessionTokenCommonCheckCache : sessionTokenCheckCache ,
121+ sessionTokenV2CommonCheckCache : sessionTokenV2CheckCache ,
111122 }
112123}
113124
@@ -215,6 +226,96 @@ func (s *server) checkSessionIssuer(id cid.ID, issuer user.ID) error {
215226 return nil
216227}
217228
229+ func (s * server ) getVerifiedSessionTokenV2 (mh * protosession.RequestMetaHeader , reqVerb session.ContainerVerb , reqCnr cid.ID ) (* session.TokenV2 , error ) {
230+ for omh := mh .GetOrigin (); omh != nil ; omh = mh .GetOrigin () {
231+ mh = omh
232+ }
233+ m := mh .GetSessionTokenV2 ()
234+ if m == nil {
235+ return nil , nil
236+ }
237+
238+ b := make ([]byte , m .MarshaledSize ())
239+ m .MarshalStable (b )
240+
241+ cacheKey := sha256 .Sum256 (b )
242+ res , ok := s .sessionTokenV2CommonCheckCache .Get (cacheKey )
243+ if ! ok {
244+ res .token , res .err = s .decodeAndVerifySessionTokenV2Common (m )
245+ s .sessionTokenV2CommonCheckCache .Add (cacheKey , res )
246+ }
247+ if res .err != nil {
248+ return nil , res .err
249+ }
250+
251+ if err := s .verifySessionTokenV2AgainstRequest (res .token , reqVerb , reqCnr ); err != nil {
252+ return nil , err
253+ }
254+
255+ return & res .token , nil
256+ }
257+
258+ func (s * server ) decodeAndVerifySessionTokenV2Common (m * protosession.SessionTokenV2 ) (session.TokenV2 , error ) {
259+ var token session.TokenV2
260+ if err := token .FromProtoMessage (m ); err != nil {
261+ return token , fmt .Errorf ("decode v2: %w" , err )
262+ }
263+
264+ if err := token .Validate (); err != nil {
265+ return token , fmt .Errorf ("invalid v2 token: %w" , err )
266+ }
267+
268+ if ! token .VerifySignature () {
269+ return token , errors .New ("v2 session token signature verification failed" )
270+ }
271+
272+ cur := s .net .CurrentEpoch ()
273+ if ! token .ValidAt (cur ) {
274+ return token , fmt .Errorf ("v2 token is invalid at epoch %d" , cur )
275+ }
276+
277+ return token , nil
278+ }
279+
280+ func (s * server ) verifySessionTokenV2AgainstRequest (token session.TokenV2 , reqVerb session.ContainerVerb , reqCnr cid.ID ) error {
281+ verbV2 := containerVerbToVerbV2 (reqVerb )
282+ if verbV2 == 0 {
283+ return fmt .Errorf ("unsupported container verb for V2: %v" , reqVerb )
284+ }
285+
286+ if ! token .AssertContainer (verbV2 , reqCnr ) {
287+ return errors .New ("v2 session token does not authorize this container operation" )
288+ }
289+
290+ if reqCnr .IsZero () {
291+ return nil
292+ }
293+
294+ issuer := token .Issuer ()
295+ if ! issuer .IsOwnerID () {
296+ return errors .New ("v2 session token issuer must be OwnerID for container operations" )
297+ }
298+
299+ if err := s .checkSessionIssuer (reqCnr , issuer .OwnerID ()); err != nil {
300+ return fmt .Errorf ("verify v2 session issuer: %w" , err )
301+ }
302+
303+ return nil
304+ }
305+
306+ func containerVerbToVerbV2 (verb session.ContainerVerb ) session.VerbV2 {
307+ switch verb {
308+ case session .VerbContainerPut :
309+ return session .VerbV2ContainerPut
310+ case session .VerbContainerDelete :
311+ return session .VerbV2ContainerDelete
312+ case session .VerbContainerSetEACL :
313+ return session .VerbV2ContainerSetEACL
314+ default :
315+ return session .VerbV2Unspecified
316+ }
317+ }
318+
218319func (s * server ) makePutResponse (body * protocontainer.PutResponse_Body , st * protostatus.Status ) (* protocontainer.PutResponse , error ) {
219320 resp := & protocontainer.PutResponse {
220321 Body : body ,
@@ -306,9 +407,17 @@ func (s *server) Put(_ context.Context, req *protocontainer.PutRequest) (*protoc
306407 return s .makeFailedPutResponse (fmt .Errorf ("invalid container: %w" , err ))
307408 }
308409
309- st , err := s .getVerifiedSessionToken (req .GetMetaHeader (), session .VerbContainerPut , cid.ID {})
410+ stV2 , err := s .getVerifiedSessionTokenV2 (req .GetMetaHeader (), session .VerbContainerPut , cid.ID {})
310411 if err != nil {
311- return s .makeFailedPutResponse (fmt .Errorf ("verify session token: %w" , err ))
412+ return s .makeFailedPutResponse (fmt .Errorf ("verify session token v2: %w" , err ))
413+ }
414+
415+ var st * session.Container
416+ if stV2 == nil {
417+ st , err = s .getVerifiedSessionToken (req .GetMetaHeader (), session .VerbContainerPut , cid.ID {})
418+ if err != nil {
419+ return s .makeFailedPutResponse (fmt .Errorf ("verify session token: %w" , err ))
420+ }
312421 }
313422
314423 id , err := s .contract .Put (cnr , mSig .Key , mSig .Sign , st )
@@ -352,9 +461,17 @@ func (s *server) Delete(_ context.Context, req *protocontainer.DeleteRequest) (*
352461 return s .makeDeleteResponse (fmt .Errorf ("invalid ID: %w" , err ))
353462 }
354463
355- st , err := s .getVerifiedSessionToken (req .GetMetaHeader (), session .VerbContainerDelete , id )
464+ stV2 , err := s .getVerifiedSessionTokenV2 (req .GetMetaHeader (), session .VerbContainerDelete , id )
356465 if err != nil {
357- return s .makeDeleteResponse (fmt .Errorf ("verify session token: %w" , err ))
466+ return s .makeDeleteResponse (fmt .Errorf ("verify session token v2: %w" , err ))
467+ }
468+
469+ var st * session.Container
470+ if stV2 == nil {
471+ st , err = s .getVerifiedSessionToken (req .GetMetaHeader (), session .VerbContainerDelete , id )
472+ if err != nil {
473+ return s .makeDeleteResponse (fmt .Errorf ("verify session token: %w" , err ))
474+ }
358475 }
359476
360477 if err := s .contract .Delete (id , mSig .Key , mSig .Sign , st ); err != nil {
@@ -490,9 +607,17 @@ func (s *server) SetExtendedACL(_ context.Context, req *protocontainer.SetExtend
490607 return s .makeSetEACLResponse (errors .New ("missing container ID in eACL table" ))
491608 }
492609
493- st , err := s .getVerifiedSessionToken (req .GetMetaHeader (), session .VerbContainerSetEACL , cnrID )
610+ stV2 , err := s .getVerifiedSessionTokenV2 (req .GetMetaHeader (), session .VerbContainerSetEACL , cnrID )
494611 if err != nil {
495- return s .makeSetEACLResponse (fmt .Errorf ("verify session token: %w" , err ))
612+ return s .makeSetEACLResponse (fmt .Errorf ("verify session token v2: %w" , err ))
613+ }
614+
615+ var st * session.Container
616+ if stV2 == nil {
617+ st , err = s .getVerifiedSessionToken (req .GetMetaHeader (), session .VerbContainerSetEACL , cnrID )
618+ if err != nil {
619+ return s .makeSetEACLResponse (fmt .Errorf ("verify session token: %w" , err ))
620+ }
496621 }
497622
498623 if err := s .contract .PutEACL (eACL , mSig .Key , mSig .Sign , st ); err != nil {
0 commit comments