internal unsafe static extern int AcceptSecurityContext( ref SSPIHandle credentialHandle, [In] void *inContextPtr, [In] SecurityBufferDescriptor inputBuffer, [In] ContextFlags inFlags, [In] Endianness endianness, ref SSPIHandle outContextPtr, [In, Out] SecurityBufferDescriptor outputBuffer, [In, Out] ref ContextFlags attributes, out long timeStamp );
internal unsafe static extern int InitializeSecurityContextW( ref SSPIHandle credentialHandle, [In] void *inContextPtr, [In] byte *targetName, [In] ContextFlags inFlags, [In] int reservedI, [In] Endianness endianness, [In] SecurityBufferDescriptor inputBuffer, [In] int reservedII, ref SSPIHandle outContextPtr, [In, Out] SecurityBufferDescriptor outputBuffer, [In, Out] ref ContextFlags attributes, out long timeStamp );
internal static unsafe void Encrypt <T>(this T context, WritableBuffer outBuffer, ReadableBuffer buffer) where T : ISecureContext { outBuffer.Ensure(context.TrailerSize + context.HeaderSize + buffer.Length); void *outBufferPointer; outBuffer.Memory.TryGetPointer(out outBufferPointer); buffer.CopyTo(outBuffer.Memory.Slice(context.HeaderSize, buffer.Length)); var securityBuff = stackalloc SecurityBuffer[4]; SecurityBufferDescriptor sdcInOut = new SecurityBufferDescriptor(4); securityBuff[0].size = context.HeaderSize; securityBuff[0].type = SecurityBufferType.Header; securityBuff[0].tokenPointer = outBufferPointer; securityBuff[1].size = buffer.Length; securityBuff[1].type = SecurityBufferType.Data; securityBuff[1].tokenPointer = (byte *)outBufferPointer + context.HeaderSize; securityBuff[2].size = context.TrailerSize; securityBuff[2].type = SecurityBufferType.Trailer; securityBuff[2].tokenPointer = (byte *)outBufferPointer + context.HeaderSize + buffer.Length; securityBuff[3].size = 0; securityBuff[3].tokenPointer = null; securityBuff[3].type = SecurityBufferType.Empty; sdcInOut.UnmanagedPointer = securityBuff; var handle = context.ContextHandle; var result = (SecurityStatus)InteropSspi.EncryptMessage(ref handle, 0, sdcInOut, 0); if (result == 0) { outBuffer.Advance(context.HeaderSize + context.TrailerSize + buffer.Length); } else { //Zero out the output buffer before throwing the exception to stop any data being sent in the clear //By a misbehaving underlying channel Span <byte> memoryToClear = new Span <byte>(outBufferPointer, context.HeaderSize + context.TrailerSize + buffer.Length); byte * empty = stackalloc byte[context.HeaderSize + context.TrailerSize + buffer.Length]; memoryToClear.Set(empty, context.HeaderSize + context.TrailerSize + buffer.Length); throw new InvalidOperationException($"There was an issue encrypting the data {result}"); } }
private static unsafe SecurityStatus DecryptMessage(void *buffer, ref int offset, ref int count, SSPIHandle context) { var securityBuff = stackalloc SecurityBuffer[4]; SecurityBufferDescriptor sdcInOut = new SecurityBufferDescriptor(4); securityBuff[0].size = count; securityBuff[0].tokenPointer = buffer; securityBuff[0].type = SecurityBufferType.Data; securityBuff[1].size = 0; securityBuff[1].tokenPointer = null; securityBuff[1].type = SecurityBufferType.Empty; securityBuff[2].size = 0; securityBuff[2].tokenPointer = null; securityBuff[2].type = SecurityBufferType.Empty; securityBuff[3].size = 0; securityBuff[3].tokenPointer = null; securityBuff[3].type = SecurityBufferType.Empty; sdcInOut.UnmanagedPointer = securityBuff; var errorCode = (SecurityStatus)InteropSspi.DecryptMessage(ref context, sdcInOut, 0, null); if (errorCode == 0) { for (int i = 0; i < 4; i++) { if (securityBuff[i].type == SecurityBufferType.Data) { //we have found the data lets find the offset offset = (int)((byte *)securityBuff[i].tokenPointer - (byte *)buffer); if (offset > (count - 1)) { throw new OverflowException(); } count = securityBuff[i].size; return(errorCode); } } } throw new InvalidOperationException($"There was an error ncrypting the data {errorCode}"); }
internal unsafe static extern int CompleteAuthToken( [In] void *inContextPtr, [In, Out] SecurityBufferDescriptor inputBuffers );
internal static unsafe extern int DecryptMessage( [In] ref SSPIHandle contextHandle, [In, Out] SecurityBufferDescriptor inputOutput, [In] uint sequenceNumber, uint *qualityOfProtection );
internal static extern int EncryptMessage( ref SSPIHandle contextHandle, [In] uint qualityOfProtection, [In, Out] SecurityBufferDescriptor inputOutput, [In] uint sequenceNumber );
internal static extern int ApplyControlToken(ref SSPIHandle contextHandle, [In][Out] SecurityBufferDescriptor outputBuffer);
public static unsafe int EncryptDecryptHelper(SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber, bool encrypt, bool isGssBlob) { SecurityBufferDescriptor sdcInOut = new SecurityBufferDescriptor(input.Length); SecurityBufferStruct[] unmanagedBuffer = new SecurityBufferStruct[input.Length]; byte[][] buffers = new byte[input.Length][]; fixed (void* unmanagedBufferPtr = unmanagedBuffer) { sdcInOut.UnmanagedPointer = unmanagedBufferPtr; GCHandle[] pinnedBuffers = new GCHandle[input.Length]; try { for (int i = 0; i < input.Length; ++i) { SecurityBuffer iBuffer = input[i]; unmanagedBuffer[i].count = iBuffer.size; unmanagedBuffer[i].type = iBuffer.type; if (iBuffer.token == null || iBuffer.token.Length == 0) { unmanagedBuffer[i].token = IntPtr.Zero; } else { pinnedBuffers[i] = GCHandle.Alloc(iBuffer.token, GCHandleType.Pinned); unmanagedBuffer[i].token = Marshal.UnsafeAddrOfPinnedArrayElement(iBuffer.token, iBuffer.offset); buffers[i] = iBuffer.token; } } int errorCode; if (encrypt) { errorCode = SafeDeleteContext.EncryptMessage(context, sdcInOut, sequenceNumber); } else { errorCode = SafeDeleteContext.DecryptMessage(context, sdcInOut, sequenceNumber); } // Marshalling back returned sizes (do not marshal the "token" field) for (int i = 0; i < input.Length; ++i) { SecurityBuffer iBuffer = input[i]; iBuffer.size = unmanagedBuffer[i].count; iBuffer.type = unmanagedBuffer[i].type; if (iBuffer.size == 0) { iBuffer.offset = 0; iBuffer.token = null; } else if (isGssBlob && !encrypt && iBuffer.type == BufferType.Data) { iBuffer.token = DiagnosticUtility.Utility.AllocateByteArray(iBuffer.size); Marshal.Copy(unmanagedBuffer[i].token, iBuffer.token, 0, iBuffer.size); } else checked { // Find the buffer this is inside of. Usually they all point inside buffer 0. int j; for (j = 0; j < input.Length; j++) { if (buffers[j] == null) { continue; } byte* bufferAddress = (byte*)Marshal.UnsafeAddrOfPinnedArrayElement(buffers[j], 0); if ((byte*)unmanagedBuffer[i].token >= bufferAddress && (byte*)unmanagedBuffer[i].token + iBuffer.size <= bufferAddress + buffers[j].Length) { iBuffer.offset = (int)((byte*)unmanagedBuffer[i].token - bufferAddress); iBuffer.token = buffers[j]; break; } } if (j >= input.Length) { iBuffer.size = 0; iBuffer.offset = 0; iBuffer.token = null; } if (!(iBuffer.offset >= 0 && iBuffer.offset <= (iBuffer.token == null ? 0 : iBuffer.token.Length))) { DiagnosticUtility.DebugAssert(SR.GetString(SR.SspiWrapperEncryptDecryptAssert1, iBuffer.offset)); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SspiWrapperEncryptDecryptAssert1, iBuffer.offset))); } if (!(iBuffer.size >= 0 && iBuffer.size <= (iBuffer.token == null ? 0 : iBuffer.token.Length - iBuffer.offset))) { DiagnosticUtility.DebugAssert(SR.GetString(SR.SspiWrapperEncryptDecryptAssert2, iBuffer.size)); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SspiWrapperEncryptDecryptAssert2, iBuffer.size))); } } } return errorCode; } finally { for (int i = 0; i < pinnedBuffers.Length; ++i) { if (pinnedBuffers[i].IsAllocated) { pinnedBuffers[i].Free(); } } } } }
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(); } } }