public byte[] ProcessContextMessage(ReadableBuffer messageBuffer) { if (messageBuffer.Length == 0) { return(null); } SecurityBufferDescriptor input = new SecurityBufferDescriptor(3); SecurityBuffer * inputBuff = stackalloc SecurityBuffer[3]; void *arrayPointer; if (messageBuffer.IsSingleSpan) { messageBuffer.First.TryGetPointer(out arrayPointer); } else { if (messageBuffer.Length > SecurityContext.MaxStackAllocSize) { throw new OverflowException($"We need to create a buffer on the stack of size {messageBuffer.Length} but the max is {SecurityContext.MaxStackAllocSize}"); } byte *tempBytes = stackalloc byte[messageBuffer.Length]; messageBuffer.CopyTo(new Span <byte>(tempBytes, messageBuffer.Length)); arrayPointer = tempBytes; } inputBuff[0] = new SecurityBuffer() { tokenPointer = arrayPointer, type = SecurityBufferType.Token, size = messageBuffer.Length }; inputBuff[1] = new SecurityBuffer() { size = 0, tokenPointer = null, type = SecurityBufferType.Empty }; if (_securityContext.LengthOfSupportedProtocols > 0) { inputBuff[2].size = _securityContext.LengthOfSupportedProtocols; inputBuff[2].tokenPointer = (void *)_securityContext.AlpnSupportedProtocols; inputBuff[2].type = SecurityBufferType.ApplicationProtocols; } else { inputBuff[2].size = 0; inputBuff[2].tokenPointer = null; inputBuff[2].type = SecurityBufferType.Empty; } input.UnmanagedPointer = inputBuff; SecurityBufferDescriptor output = new SecurityBufferDescriptor(3); SecurityBuffer * outputBuff = stackalloc SecurityBuffer[3]; outputBuff[0].size = 0; outputBuff[0].tokenPointer = null; outputBuff[0].type = SecurityBufferType.Token; outputBuff[1].size = 0; outputBuff[1].tokenPointer = null; outputBuff[1].type = SecurityBufferType.Alert; outputBuff[2].size = 0; outputBuff[2].tokenPointer = null; outputBuff[2].type = SecurityBufferType.Empty; output.UnmanagedPointer = outputBuff; ContextFlags flags = default(ContextFlags); long timestamp; var handle = _securityContext.CredentialsHandle; void * contextptr; var localPointer = _contextPointer; if (_contextPointer.handleHi == IntPtr.Zero && _contextPointer.handleLo == IntPtr.Zero) { contextptr = null; } else { contextptr = &localPointer; } var errorCode = (SecurityStatus)InteropSspi.AcceptSecurityContext(ref handle, contextptr, input, SecurityContext.ServerRequiredFlags, Endianness.Native, ref _contextPointer, output, ref flags, out timestamp); _contextPointer = localPointer; if (errorCode == SecurityStatus.ContinueNeeded || errorCode == SecurityStatus.OK) { byte[] outArray = null; if (outputBuff[0].size > 0) { outArray = new byte[outputBuff[0].size]; Marshal.Copy((IntPtr)outputBuff[0].tokenPointer, outArray, 0, outputBuff[0].size); InteropSspi.FreeContextBuffer((IntPtr)outputBuff[0].tokenPointer); } if (errorCode == SecurityStatus.OK) { ContextStreamSizes ss; //We have a valid context so lets query it for info InteropSspi.QueryContextAttributesW(ref _contextPointer, ContextAttribute.StreamSizes, out ss); _headerSize = ss.header; _trailerSize = ss.trailer; if (_securityContext.LengthOfSupportedProtocols > 0) { _negotiatedProtocol = ApplicationProtocols.FindNegotiatedProtocol(_contextPointer); } _readyToSend = true; } return(outArray); } throw new InvalidOperationException($"We failed to build a server context {errorCode}"); }
public byte[] ProcessContextMessage(ReadableBuffer messageBuffer) { GCHandle handleForAllocation = default(GCHandle); try { SecurityBufferDescriptor output = new SecurityBufferDescriptor(2); SecurityBuffer * outputBuff = stackalloc SecurityBuffer[2]; outputBuff[0].size = 0; outputBuff[0].tokenPointer = null; outputBuff[0].type = SecurityBufferType.Token; outputBuff[1].type = SecurityBufferType.Alert; outputBuff[1].size = 0; outputBuff[1].tokenPointer = null; output.UnmanagedPointer = outputBuff; var handle = _securityContext.CredentialsHandle; SSPIHandle localhandle = _contextPointer; void * contextptr; void * newContextptr; if (_contextPointer.handleHi == IntPtr.Zero && _contextPointer.handleLo == IntPtr.Zero) { contextptr = null; newContextptr = &localhandle; } else { contextptr = &localhandle; newContextptr = null; } ContextFlags unusedAttributes = default(ContextFlags); SecurityBufferDescriptor *pointerToDescriptor = null; if (messageBuffer.Length > 0) { SecurityBufferDescriptor input = new SecurityBufferDescriptor(2); SecurityBuffer * inputBuff = stackalloc SecurityBuffer[2]; inputBuff[0].size = messageBuffer.Length; inputBuff[0].type = SecurityBufferType.Token; if (messageBuffer.IsSingleSpan) { void *arrayPointer; messageBuffer.First.TryGetPointer(out arrayPointer); inputBuff[0].tokenPointer = arrayPointer; } else { if (messageBuffer.Length <= SecurityContext.MaxStackAllocSize) { byte * tempBuffer = stackalloc byte[messageBuffer.Length]; Span <byte> tmpSpan = new Span <byte>(tempBuffer, messageBuffer.Length); messageBuffer.CopyTo(tmpSpan); inputBuff[0].tokenPointer = tempBuffer; } else { //We have to allocate... sorry byte[] tempBuffer = new byte[messageBuffer.Length]; Span <byte> tmpSpan = new Span <byte>(tempBuffer); messageBuffer.CopyTo(tmpSpan); handleForAllocation = GCHandle.Alloc(tempBuffer, GCHandleType.Pinned); inputBuff[0].tokenPointer = (void *)handleForAllocation.AddrOfPinnedObject(); } } outputBuff[1].type = SecurityBufferType.Empty; outputBuff[1].size = 0; outputBuff[1].tokenPointer = null; input.UnmanagedPointer = inputBuff; pointerToDescriptor = &input; } else { if (_securityContext.LengthOfSupportedProtocols > 0) { SecurityBufferDescriptor input = new SecurityBufferDescriptor(1); SecurityBuffer * inputBuff = stackalloc SecurityBuffer[1]; inputBuff[0].size = _securityContext.LengthOfSupportedProtocols; inputBuff[0].tokenPointer = (void *)_securityContext.AlpnSupportedProtocols; inputBuff[0].type = SecurityBufferType.ApplicationProtocols; input.UnmanagedPointer = inputBuff; pointerToDescriptor = &input; } } long timestamp = 0; SecurityStatus errorCode = (SecurityStatus)InteropSspi.InitializeSecurityContextW(ref handle, contextptr, _securityContext.HostName, SecurityContext.RequiredFlags | ContextFlags.InitManualCredValidation, 0, Endianness.Native, pointerToDescriptor, 0, newContextptr, output, ref unusedAttributes, out timestamp); _contextPointer = localhandle; if (errorCode == SecurityStatus.ContinueNeeded || errorCode == SecurityStatus.OK) { byte[] outArray = null; if (outputBuff[0].size > 0) { outArray = new byte[outputBuff[0].size]; Marshal.Copy((IntPtr)outputBuff[0].tokenPointer, outArray, 0, outputBuff[0].size); InteropSspi.FreeContextBuffer((IntPtr)outputBuff[0].tokenPointer); } if (errorCode == SecurityStatus.OK) { ContextStreamSizes ss; //We have a valid context so lets query it for info InteropSspi.QueryContextAttributesW(ref _contextPointer, ContextAttribute.StreamSizes, out ss); _headerSize = ss.header; _trailerSize = ss.trailer; if (_securityContext.LengthOfSupportedProtocols > 0) { _negotiatedProtocol = ApplicationProtocols.FindNegotiatedProtocol(_contextPointer); } _readyToSend = true; } return(outArray); } throw new InvalidOperationException($"An error occured trying to negoiate a session {errorCode}"); } finally { if (handleForAllocation.IsAllocated) { handleForAllocation.Free(); } } }