@@ -364,7 +364,7 @@ internal static unsafe int InitializeSecurityContext(
364
364
string ? targetName ,
365
365
Interop . SspiCli . ContextFlags inFlags ,
366
366
Interop . SspiCli . Endianness endianness ,
367
- InputSecurityBuffers inSecBuffers ,
367
+ ref InputSecurityBuffers inSecBuffers ,
368
368
ref ProtocolToken outToken ,
369
369
ref Interop . SspiCli . ContextFlags outFlags )
370
370
{
@@ -503,60 +503,15 @@ internal static unsafe int InitializeSecurityContext(
503
503
504
504
// In some cases schannel may not process all the given data.
505
505
// and it will return them back as SECBUFFER_EXTRA, expecting caller to
506
- // feed them in again. Since we don't have good way how to flow the input back,
507
- // we will try it again as separate call and we will return combined output from first and second try.
508
- // That makes processing of outBuffer somewhat complicated.
506
+ // feed them in again. Propagate this information back up.
509
507
if ( inSecBuffers . Count > 1 && inUnmanagedBuffer [ 1 ] . BufferType == SecurityBufferType . SECBUFFER_EXTRA && inSecBuffers . _item1 . Type == SecurityBufferType . SECBUFFER_EMPTY )
510
508
{
511
- // OS function did not use all provided data and turned EMPTY to EXTRA
512
- // https://learn.microsoft.com/windows/win32/secauthn/extra-buffers-returned-by-schannel
509
+ inSecBuffers . _item1 . Type = inUnmanagedBuffer [ 1 ] . BufferType ;
513
510
514
- int leftover = inUnmanagedBuffer [ 1 ] . cbBuffer ;
515
- int processed = inSecBuffers . _item0 . Token . Length - inUnmanagedBuffer [ 1 ] . cbBuffer ;
516
-
517
- /* skip over processed data and try it again. */
518
- inUnmanagedBuffer [ 0 ] . cbBuffer = leftover ;
519
- inUnmanagedBuffer [ 0 ] . pvBuffer = inUnmanagedBuffer [ 0 ] . pvBuffer + processed ;
520
- inUnmanagedBuffer [ 1 ] . BufferType = SecurityBufferType . SECBUFFER_EMPTY ;
521
- inUnmanagedBuffer [ 1 ] . cbBuffer = 0 ;
522
-
523
- outUnmanagedBuffer . cbBuffer = 0 ;
524
-
525
- if ( outoutBuffer != IntPtr . Zero )
526
- {
527
- Interop . SspiCli . FreeContextBuffer ( outoutBuffer ) ;
528
- outoutBuffer = IntPtr . Zero ;
529
- }
530
-
531
- errorCode = MustRunInitializeSecurityContext (
532
- ref inCredentials ,
533
- isContextAbsent ,
534
- ( byte * ) namePtr ,
535
- inFlags ,
536
- endianness ,
537
- & inSecurityBufferDescriptor ,
538
- refContext ! ,
539
- ref outSecurityBufferDescriptor ,
540
- ref outFlags ,
541
- null ) ;
542
-
543
- if ( isSspiAllocated )
544
- {
545
- outoutBuffer = outUnmanagedBuffer . pvBuffer ;
546
-
547
- if ( outUnmanagedBuffer . cbBuffer > 0 )
548
- {
549
- outToken . EnsureAvailableSpace ( outUnmanagedBuffer . cbBuffer ) ;
550
- new Span < byte > ( ( byte * ) outUnmanagedBuffer . pvBuffer , outUnmanagedBuffer . cbBuffer ) . CopyTo ( outToken . AvailableSpan ) ;
551
- outToken . Size += outUnmanagedBuffer . cbBuffer ;
552
- }
553
- }
554
-
555
- if ( inUnmanagedBuffer [ 1 ] . BufferType == SecurityBufferType . SECBUFFER_EXTRA )
556
- {
557
- // we are left with unprocessed data again. fail with SEC_E_INCOMPLETE_MESSAGE hResult.
558
- errorCode = unchecked ( ( int ) 0x80090318 ) ;
559
- }
511
+ // since SecurityBuffer type does not have separate Length field,
512
+ // we point to the unused portion of the input buffer.
513
+ Debug . Assert ( inSecBuffers . _item0 . Token . Length > inUnmanagedBuffer [ 1 ] . cbBuffer ) ;
514
+ inSecBuffers . _item1 . Token = inSecBuffers . _item0 . Token . Slice ( inSecBuffers . _item0 . Token . Length - inUnmanagedBuffer [ 1 ] . cbBuffer ) ;
560
515
}
561
516
}
562
517
}
@@ -676,7 +631,7 @@ internal static unsafe int AcceptSecurityContext(
676
631
ref SafeDeleteSslContext ? refContext ,
677
632
Interop . SspiCli . ContextFlags inFlags ,
678
633
Interop . SspiCli . Endianness endianness ,
679
- InputSecurityBuffers inSecBuffers ,
634
+ ref InputSecurityBuffers inSecBuffers ,
680
635
ref ProtocolToken outToken ,
681
636
ref Interop . SspiCli . ContextFlags outFlags )
682
637
{
@@ -807,51 +762,17 @@ internal static unsafe int AcceptSecurityContext(
807
762
}
808
763
outToken . Size = length ;
809
764
765
+ // In some cases schannel may not process all the given data.
766
+ // and it will return them back as SECBUFFER_EXTRA, expecting caller to
767
+ // feed them in again. Propagate this information back up.
810
768
if ( inSecBuffers . Count > 1 && inUnmanagedBuffer [ 1 ] . BufferType == SecurityBufferType . SECBUFFER_EXTRA && inSecBuffers . _item1 . Type == SecurityBufferType . SECBUFFER_EMPTY )
811
769
{
812
- // OS function did not use all provided data and turned EMPTY to EXTRA
813
- // https://learn.microsoft.com/windows/win32/secauthn/extra-buffers-returned-by-schannel
814
-
815
- int leftover = inUnmanagedBuffer [ 1 ] . cbBuffer ;
816
- int processed = inSecBuffers . _item0 . Token . Length - inUnmanagedBuffer [ 1 ] . cbBuffer ;
817
-
818
- /* skip over processed data and try it again. */
819
- inUnmanagedBuffer [ 0 ] . cbBuffer = leftover ;
820
- inUnmanagedBuffer [ 0 ] . pvBuffer = inUnmanagedBuffer [ 0 ] . pvBuffer + processed ;
821
- inUnmanagedBuffer [ 1 ] . BufferType = SecurityBufferType . SECBUFFER_EMPTY ;
822
- inUnmanagedBuffer [ 1 ] . cbBuffer = 0 ;
823
-
824
- outUnmanagedBuffer [ 0 ] . cbBuffer = 0 ;
825
- if ( isSspiAllocated && outUnmanagedBuffer [ 0 ] . pvBuffer != IntPtr . Zero )
826
- {
827
- Interop . SspiCli . FreeContextBuffer ( outUnmanagedBuffer [ 0 ] . pvBuffer ) ;
828
- outUnmanagedBuffer [ 0 ] . pvBuffer = IntPtr . Zero ;
829
- }
770
+ inSecBuffers . _item1 . Type = inUnmanagedBuffer [ 1 ] . BufferType ;
830
771
831
- errorCode = MustRunAcceptSecurityContext_SECURITY (
832
- ref inCredentials ,
833
- isContextAbsent ,
834
- & inSecurityBufferDescriptor ,
835
- inFlags ,
836
- endianness ,
837
- refContext ! ,
838
- ref outSecurityBufferDescriptor ,
839
- ref outFlags ,
840
- null ) ;
841
-
842
- index = outUnmanagedBuffer [ 0 ] . cbBuffer == 0 && outUnmanagedBuffer [ 1 ] . cbBuffer > 0 ? 1 : 0 ;
843
- if ( outUnmanagedBuffer [ index ] . cbBuffer > 0 )
844
- {
845
- outToken . EnsureAvailableSpace ( outUnmanagedBuffer [ index ] . cbBuffer ) ;
846
- new Span < byte > ( ( byte * ) outUnmanagedBuffer [ index ] . pvBuffer , outUnmanagedBuffer [ index ] . cbBuffer ) . CopyTo ( outToken . AvailableSpan ) ;
847
- outToken . Size += outUnmanagedBuffer [ index ] . cbBuffer ;
848
- }
849
-
850
- if ( inUnmanagedBuffer [ 1 ] . BufferType == SecurityBufferType . SECBUFFER_EXTRA )
851
- {
852
- // we are left with unprocessed data again. fail with SEC_E_INCOMPLETE_MESSAGE hResult.
853
- errorCode = unchecked ( ( int ) 0x80090318 ) ;
854
- }
772
+ // since SecurityBuffer type does not have separate Length field,
773
+ // we point to the unused portion of the input buffer.
774
+ Debug . Assert ( inSecBuffers . _item0 . Token . Length > inUnmanagedBuffer [ 1 ] . cbBuffer ) ;
775
+ inSecBuffers . _item1 . Token = inSecBuffers . _item0 . Token . Slice ( inSecBuffers . _item0 . Token . Length - inUnmanagedBuffer [ 1 ] . cbBuffer ) ;
855
776
}
856
777
}
857
778
}
0 commit comments