public static SecurityStatusPal AcceptSecurityContext(ref SafeFreeCredentials credentialsHandle, ref SafeDeleteSslContext context, byte[] inputBuffer, int offset, int count, ref byte[] outputBuffer, SslAuthenticationOptions sslAuthenticationOptions) { Interop.SspiCli.ContextFlags unusedAttributes = default; ArraySegment <byte> input = inputBuffer != null ? new ArraySegment <byte>(inputBuffer, offset, count) : default; ThreeSecurityBuffers threeSecurityBuffers = default; SecurityBuffer? incomingSecurity = input.Array != null ? new SecurityBuffer(input.Array, input.Offset, input.Count, SecurityBufferType.SECBUFFER_TOKEN) : (SecurityBuffer?)null; Span <SecurityBuffer> inputBuffers = MemoryMarshal.CreateSpan(ref threeSecurityBuffers._item0, 3); GetIncomingSecurityBuffers(sslAuthenticationOptions, in incomingSecurity, ref inputBuffers); var resultBuffer = new SecurityBuffer(outputBuffer, SecurityBufferType.SECBUFFER_TOKEN); int errorCode = SSPIWrapper.AcceptSecurityContext( GlobalSSPI.SSPISecureChannel, credentialsHandle, ref context, ServerRequiredFlags | (sslAuthenticationOptions.RemoteCertRequired ? Interop.SspiCli.ContextFlags.MutualAuth : Interop.SspiCli.ContextFlags.Zero), Interop.SspiCli.Endianness.SECURITY_NATIVE_DREP, inputBuffers, ref resultBuffer, ref unusedAttributes); outputBuffer = resultBuffer.token; return(SecurityStatusAdapterPal.GetSecurityStatusPalFromNativeInt(errorCode)); }
public static SecurityStatusPal DecryptMessage(SafeDeleteContext securityContext, byte[] buffer, ref int offset, ref int count) { // Decryption using SCHANNEL requires four buffers. SecurityBuffer[] decspc = new SecurityBuffer[4]; decspc[0] = new SecurityBuffer(buffer, offset, count, SecurityBufferType.SECBUFFER_DATA); decspc[1] = new SecurityBuffer(null, SecurityBufferType.SECBUFFER_EMPTY); decspc[2] = new SecurityBuffer(null, SecurityBufferType.SECBUFFER_EMPTY); decspc[3] = new SecurityBuffer(null, SecurityBufferType.SECBUFFER_EMPTY); Interop.SECURITY_STATUS errorCode = (Interop.SECURITY_STATUS)SSPIWrapper.DecryptMessage( GlobalSSPI.SSPISecureChannel, securityContext, decspc, 0); count = 0; for (int i = 0; i < decspc.Length; i++) { // Successfully decoded data and placed it at the following position in the buffer, if ((errorCode == Interop.SECURITY_STATUS.OK && decspc[i].type == SecurityBufferType.SECBUFFER_DATA) // or we failed to decode the data, here is the encoded data. || (errorCode != Interop.SECURITY_STATUS.OK && decspc[i].type == SecurityBufferType.SECBUFFER_EXTRA)) { offset = decspc[i].offset; count = decspc[i].size; break; } } return(SecurityStatusAdapterPal.GetSecurityStatusPalFromInterop(errorCode)); }
public static SecurityStatusPal ApplyAlertToken(ref SafeFreeCredentials credentialsHandle, SafeDeleteContext securityContext, TlsAlertType alertType, TlsAlertMessage alertMessage) { Interop.SChannel.SCHANNEL_ALERT_TOKEN alertToken; alertToken.dwTokenType = Interop.SChannel.SCHANNEL_ALERT; alertToken.dwAlertType = (uint)alertType; alertToken.dwAlertNumber = (uint)alertMessage; var bufferDesc = new SecurityBuffer[1]; int alertTokenByteSize = Marshal.SizeOf <Interop.SChannel.SCHANNEL_ALERT_TOKEN>(); IntPtr p = Marshal.AllocHGlobal(alertTokenByteSize); try { var buffer = new byte[alertTokenByteSize]; Marshal.StructureToPtr <Interop.SChannel.SCHANNEL_ALERT_TOKEN>(alertToken, p, false); Marshal.Copy(p, buffer, 0, alertTokenByteSize); bufferDesc[0] = new SecurityBuffer(buffer, SecurityBufferType.SECBUFFER_TOKEN); var errorCode = (Interop.SECURITY_STATUS)SSPIWrapper.ApplyControlToken( GlobalSSPI.SSPISecureChannel, ref securityContext, bufferDesc); return(SecurityStatusAdapterPal.GetSecurityStatusPalFromInterop(errorCode, attachException: true)); } finally { Marshal.FreeHGlobal(p); } }
public static SecurityStatusPal InitializeSecurityContext(ref SafeFreeCredentials credentialsHandle, ref SafeDeleteContext context, string targetName, ArraySegment <byte> input, ref byte[] outputBuffer, SslAuthenticationOptions sslAuthenticationOptions) { Interop.SspiCli.ContextFlags unusedAttributes = default; ThreeSecurityBuffers threeSecurityBuffers = default; SecurityBuffer? incomingSecurity = input.Array != null ? new SecurityBuffer(input.Array, input.Offset, input.Count, SecurityBufferType.SECBUFFER_TOKEN) : (SecurityBuffer?)null; Span <SecurityBuffer> inputBuffers = MemoryMarshal.CreateSpan(ref threeSecurityBuffers._item0, 3); GetIncomingSecurityBuffers(sslAuthenticationOptions, in incomingSecurity, ref inputBuffers); var resultBuffer = new SecurityBuffer(outputBuffer, SecurityBufferType.SECBUFFER_TOKEN); int errorCode = SSPIWrapper.InitializeSecurityContext( GlobalSSPI.SSPISecureChannel, ref credentialsHandle, ref context, targetName, RequiredFlags | Interop.SspiCli.ContextFlags.InitManualCredValidation, Interop.SspiCli.Endianness.SECURITY_NATIVE_DREP, inputBuffers, ref resultBuffer, ref unusedAttributes); outputBuffer = resultBuffer.token; return(SecurityStatusAdapterPal.GetSecurityStatusPalFromNativeInt(errorCode)); }
public static SecurityStatusPal EncryptMessage(SafeDeleteContext securityContext, byte[] input, int offset, int size, int headerSize, int trailerSize, ref byte[] output, out int resultSize) { // Ensure that there is sufficient space for the message output. try { int bufferSizeNeeded = checked (size + headerSize + trailerSize); if (output == null || output.Length < bufferSizeNeeded) { output = new byte[bufferSizeNeeded]; } } catch (Exception e) { if (!ExceptionCheck.IsFatal(e)) { if (GlobalLog.IsEnabled) { GlobalLog.Assert("SslStreamPal.Windows: SecureChannel#" + LoggingHash.HashString(securityContext) + "::Encrypt", "Arguments out of range."); } Debug.Fail("SslStreamPal.Windows: SecureChannel#" + LoggingHash.HashString(securityContext) + "::Encrypt", "Arguments out of range."); } throw; } byte[] writeBuffer = output; // Copy the input into the output buffer to prepare for SCHANNEL's expectations Buffer.BlockCopy(input, offset, writeBuffer, headerSize, size); // Encryption using SCHANNEL requires 4 buffers: header, payload, trailer, empty. SecurityBuffer[] securityBuffer = new SecurityBuffer[4]; securityBuffer[0] = new SecurityBuffer(writeBuffer, 0, headerSize, SecurityBufferType.SECBUFFER_STREAM_HEADER); securityBuffer[1] = new SecurityBuffer(writeBuffer, headerSize, size, SecurityBufferType.SECBUFFER_DATA); securityBuffer[2] = new SecurityBuffer(writeBuffer, headerSize + size, trailerSize, SecurityBufferType.SECBUFFER_STREAM_TRAILER); securityBuffer[3] = new SecurityBuffer(null, SecurityBufferType.SECBUFFER_EMPTY); int errorCode = SSPIWrapper.EncryptMessage(GlobalSSPI.SSPISecureChannel, securityContext, securityBuffer, 0); if (errorCode != 0) { if (GlobalLog.IsEnabled) { GlobalLog.Print("SslStreamPal.Windows: SecureChannel#" + LoggingHash.HashString(securityContext) + "::Encrypt ERROR" + errorCode.ToString("x")); } resultSize = 0; } else { // The full buffer may not be used. resultSize = securityBuffer[0].size + securityBuffer[1].size + securityBuffer[2].size; } return(SecurityStatusAdapterPal.GetSecurityStatusPalFromNativeInt(errorCode)); }
internal static SecurityStatusPal InitializeSecurityContext( ref SafeFreeCredentials credentialsHandle, ref SafeDeleteContext securityContext, string spn, ContextFlagsPal requestedContextFlags, byte[] incomingBlob, ChannelBinding channelBinding, ref byte[] resultBlob, ref ContextFlagsPal contextFlags) { #if netstandard Span <SecurityBuffer> inSecurityBufferSpan = new SecurityBuffer[2]; #else TwoSecurityBuffers twoSecurityBuffers = default; Span <SecurityBuffer> inSecurityBufferSpan = MemoryMarshal.CreateSpan(ref twoSecurityBuffers._item0, 2); #endif int inSecurityBufferSpanLength = 0; if (incomingBlob != null && channelBinding != null) { inSecurityBufferSpan[0] = new SecurityBuffer(incomingBlob, SecurityBufferType.SECBUFFER_TOKEN); inSecurityBufferSpan[1] = new SecurityBuffer(channelBinding); inSecurityBufferSpanLength = 2; } else if (incomingBlob != null) { inSecurityBufferSpan[0] = new SecurityBuffer(incomingBlob, SecurityBufferType.SECBUFFER_TOKEN); inSecurityBufferSpanLength = 1; } else if (channelBinding != null) { inSecurityBufferSpan[0] = new SecurityBuffer(channelBinding); inSecurityBufferSpanLength = 1; } inSecurityBufferSpan = inSecurityBufferSpan.Slice(0, inSecurityBufferSpanLength); var outSecurityBuffer = new SecurityBuffer(resultBlob, SecurityBufferType.SECBUFFER_TOKEN); Interop.SspiCli.ContextFlags outContextFlags = Interop.SspiCli.ContextFlags.Zero; // There is only one SafeDeleteContext type on Windows which is SafeDeleteSslContext so this cast is safe. SafeDeleteSslContext sslContext = (SafeDeleteSslContext)securityContext; Interop.SECURITY_STATUS winStatus = (Interop.SECURITY_STATUS)SSPIWrapper.InitializeSecurityContext( GlobalSSPI.SSPIAuth, ref credentialsHandle, ref sslContext, spn, ContextFlagsAdapterPal.GetInteropFromContextFlagsPal(requestedContextFlags), Interop.SspiCli.Endianness.SECURITY_NETWORK_DREP, inSecurityBufferSpan, ref outSecurityBuffer, ref outContextFlags); securityContext = sslContext; resultBlob = outSecurityBuffer.token; contextFlags = ContextFlagsAdapterPal.GetContextFlagsPalFromInterop(outContextFlags); return(SecurityStatusAdapterPal.GetSecurityStatusPalFromInterop(winStatus)); }
internal static SecurityStatusPal CompleteAuthToken( ref SafeDeleteContext securityContext, SecurityBuffer[] inSecurityBufferArray) { Interop.SECURITY_STATUS winStatus = (Interop.SECURITY_STATUS)SSPIWrapper.CompleteAuthToken( GlobalSSPI.SSPIAuth, ref securityContext, inSecurityBufferArray); return(SecurityStatusAdapterPal.GetSecurityStatusPalFromInterop(winStatus)); }
internal static IIdentity GetIdentity(NTAuthentication context) { IIdentity?result; string? name = context.IsServer ? null : context.Spn; string protocol = context.ProtocolName; if (context.IsServer) { SecurityContextTokenHandle?token = null; try { SafeDeleteContext?securityContext = context.GetContext(out SecurityStatusPal status); if (status.ErrorCode != SecurityStatusPalErrorCode.OK) { throw new Win32Exception((int)SecurityStatusAdapterPal.GetInteropFromSecurityStatusPal(status)); } name = QueryContextAssociatedName(securityContext !); if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(context, $"NTAuthentication: The context is associated with [{name}]"); } // This will return a client token when conducted authentication on server side. // This token can be used for impersonation. We use it to create a WindowsIdentity and hand it out to the server app. Interop.SECURITY_STATUS winStatus = (Interop.SECURITY_STATUS)SSPIWrapper.QuerySecurityContextToken( GlobalSSPI.SSPIAuth, securityContext !, out token); if (winStatus != Interop.SECURITY_STATUS.OK) { throw new Win32Exception((int)winStatus); } string authtype = context.ProtocolName; // The following call was also specifying WindowsAccountType.Normal, true. // WindowsIdentity.IsAuthenticated is no longer supported in .NET Core result = new WindowsIdentity(token.DangerousGetHandle(), authtype); return(result); } catch (SecurityException) { // Ignore and construct generic Identity if failed due to security problem. } finally { token?.Dispose(); } } // On the client we don't have access to the remote side identity. result = new GenericIdentity(name ?? string.Empty, protocol); return(result); }
internal static IIdentity GetIdentity(NTAuthentication context) { IIdentity result = null; string name = context.IsServer ? context.AssociatedName : context.Spn; string protocol = context.ProtocolName; if (context.IsServer) { SecurityContextTokenHandle token = null; try { SecurityStatusPal status; SafeDeleteContext securityContext = context.GetContext(out status); if (status.ErrorCode != SecurityStatusPalErrorCode.OK) { throw new Win32Exception((int)SecurityStatusAdapterPal.GetInteropFromSecurityStatusPal(status)); } // This will return a client token when conducted authentication on server side. // This token can be used for impersonation. We use it to create a WindowsIdentity and hand it out to the server app. Interop.SECURITY_STATUS winStatus = (Interop.SECURITY_STATUS)SSPIWrapper.QuerySecurityContextToken( GlobalSSPI.SSPIAuth, securityContext, out token); if (winStatus != Interop.SECURITY_STATUS.OK) { throw new Win32Exception((int)winStatus); } string authtype = context.ProtocolName; // TODO #5241: // The following call was also specifying WindowsAccountType.Normal, true. // WindowsIdentity.IsAuthenticated is no longer supported in CoreFX. result = new WindowsIdentity(token.DangerousGetHandle(), authtype); return(result); } catch (SecurityException) { // Ignore and construct generic Identity if failed due to security problem. } finally { if (token != null) { token.Dispose(); } } } // On the client we don't have access to the remote side identity. result = new GenericIdentity(name, protocol); return(result); }
internal static SecurityStatusPal AcceptSecurityContext( SafeFreeCredentials?credentialsHandle, ref SafeDeleteContext?securityContext, ContextFlagsPal requestedContextFlags, ReadOnlySpan <byte> incomingBlob, ChannelBinding?channelBinding, ref byte[]?resultBlob, out int resultBlobLength, ref ContextFlagsPal contextFlags) { InputSecurityBuffers inputBuffers = default; if (!incomingBlob.IsEmpty) { inputBuffers.SetNextBuffer(new InputSecurityBuffer(incomingBlob, SecurityBufferType.SECBUFFER_TOKEN)); } if (channelBinding != null) { inputBuffers.SetNextBuffer(new InputSecurityBuffer(channelBinding)); } var outSecurityBuffer = new SecurityBuffer(resultBlob, SecurityBufferType.SECBUFFER_TOKEN); Interop.SspiCli.ContextFlags outContextFlags = Interop.SspiCli.ContextFlags.Zero; // There is only one SafeDeleteContext type on Windows which is SafeDeleteSslContext so this cast is safe. SafeDeleteSslContext?sslContext = (SafeDeleteSslContext?)securityContext; Interop.SECURITY_STATUS winStatus = (Interop.SECURITY_STATUS)SSPIWrapper.AcceptSecurityContext( GlobalSSPI.SSPIAuth, credentialsHandle, ref sslContext, ContextFlagsAdapterPal.GetInteropFromContextFlagsPal(requestedContextFlags), Interop.SspiCli.Endianness.SECURITY_NETWORK_DREP, inputBuffers, ref outSecurityBuffer, ref outContextFlags); // SSPI Workaround // If a client sends up a blob on the initial request, Negotiate returns SEC_E_INVALID_HANDLE // when it should return SEC_E_INVALID_TOKEN. if (winStatus == Interop.SECURITY_STATUS.InvalidHandle && securityContext == null && !incomingBlob.IsEmpty) { winStatus = Interop.SECURITY_STATUS.InvalidToken; } Debug.Assert(outSecurityBuffer.offset == 0); resultBlob = outSecurityBuffer.token; resultBlobLength = outSecurityBuffer.size; securityContext = sslContext; contextFlags = ContextFlagsAdapterPal.GetContextFlagsPalFromInterop(outContextFlags); return(SecurityStatusAdapterPal.GetSecurityStatusPalFromInterop(winStatus)); }
internal static SecurityStatusPal CompleteAuthToken( ref SafeDeleteContext securityContext, byte[] incomingBlob) { var inSecurityBuffer = new SecurityBuffer(incomingBlob, SecurityBufferType.SECBUFFER_TOKEN); Interop.SECURITY_STATUS winStatus = (Interop.SECURITY_STATUS)SSPIWrapper.CompleteAuthToken( GlobalSSPI.SSPIAuth, ref securityContext, in inSecurityBuffer); return(SecurityStatusAdapterPal.GetSecurityStatusPalFromInterop(winStatus)); }
public static SecurityStatusPal ApplyShutdownToken(ref SafeFreeCredentials credentialsHandle, SafeDeleteContext securityContext) { int shutdownToken = Interop.SChannel.SCHANNEL_SHUTDOWN; var bufferDesc = new SecurityBuffer[1]; var buffer = BitConverter.GetBytes(shutdownToken); bufferDesc[0] = new SecurityBuffer(buffer, SecurityBufferType.SECBUFFER_TOKEN); var errorCode = (Interop.SECURITY_STATUS)SSPIWrapper.ApplyControlToken( GlobalSSPI.SSPISecureChannel, ref securityContext, bufferDesc); return(SecurityStatusAdapterPal.GetSecurityStatusPalFromInterop(errorCode, attachException: true)); }
internal static SecurityStatusPal CompleteAuthToken( ref SafeDeleteContext?securityContext, byte[]?incomingBlob) { // There is only one SafeDeleteContext type on Windows which is SafeDeleteSslContext so this cast is safe. SafeDeleteSslContext?sslContext = (SafeDeleteSslContext?)securityContext; var inSecurityBuffer = new SecurityBuffer(incomingBlob, SecurityBufferType.SECBUFFER_TOKEN); Interop.SECURITY_STATUS winStatus = (Interop.SECURITY_STATUS)SSPIWrapper.CompleteAuthToken( GlobalSSPI.SSPIAuth, ref sslContext, in inSecurityBuffer); securityContext = sslContext; return(SecurityStatusAdapterPal.GetSecurityStatusPalFromInterop(winStatus)); }
public static SecurityStatusPal AcceptSecurityContext(ref SafeFreeCredentials credentialsHandle, ref SafeDeleteContext context, SecurityBuffer[] inputBuffers, SecurityBuffer outputBuffer, SslAuthenticationOptions sslAuthenticationOptions) { Interop.SspiCli.ContextFlags unusedAttributes = default(Interop.SspiCli.ContextFlags); int errorCode = SSPIWrapper.AcceptSecurityContext( GlobalSSPI.SSPISecureChannel, credentialsHandle, ref context, ServerRequiredFlags | (sslAuthenticationOptions.RemoteCertRequired ? Interop.SspiCli.ContextFlags.MutualAuth : Interop.SspiCli.ContextFlags.Zero), Interop.SspiCli.Endianness.SECURITY_NATIVE_DREP, inputBuffers, outputBuffer, ref unusedAttributes); return(SecurityStatusAdapterPal.GetSecurityStatusPalFromNativeInt(errorCode)); }
public static unsafe SecurityStatusPal DecryptMessage(SafeDeleteContext securityContext, byte[] buffer, ref int offset, ref int count) { const int NumSecBuffers = 4; // data + empty + empty + empty var unmanagedBuffer = stackalloc Interop.SspiCli.SecBuffer[NumSecBuffers]; var sdcInOut = new Interop.SspiCli.SecBufferDesc(NumSecBuffers); sdcInOut.pBuffers = unmanagedBuffer; fixed(byte *bufferPtr = buffer) { Interop.SspiCli.SecBuffer *dataBuffer = &unmanagedBuffer[0]; dataBuffer->BufferType = SecurityBufferType.SECBUFFER_DATA; dataBuffer->pvBuffer = (IntPtr)bufferPtr + offset; dataBuffer->cbBuffer = count; for (int i = 1; i < NumSecBuffers; i++) { Interop.SspiCli.SecBuffer *emptyBuffer = &unmanagedBuffer[i]; emptyBuffer->BufferType = SecurityBufferType.SECBUFFER_EMPTY; emptyBuffer->pvBuffer = IntPtr.Zero; emptyBuffer->cbBuffer = 0; } Interop.SECURITY_STATUS errorCode = (Interop.SECURITY_STATUS)GlobalSSPI.SSPISecureChannel.DecryptMessage(securityContext, ref sdcInOut, 0); // Decrypt may repopulate the sec buffers, likely with header + data + trailer + empty. // We need to find the data. count = 0; for (int i = 0; i < NumSecBuffers; i++) { // Successfully decoded data and placed it at the following position in the buffer, if ((errorCode == Interop.SECURITY_STATUS.OK && unmanagedBuffer[i].BufferType == SecurityBufferType.SECBUFFER_DATA) // or we failed to decode the data, here is the encoded data. || (errorCode != Interop.SECURITY_STATUS.OK && unmanagedBuffer[i].BufferType == SecurityBufferType.SECBUFFER_EXTRA)) { offset = (int)((byte *)unmanagedBuffer[i].pvBuffer - bufferPtr); count = unmanagedBuffer[i].cbBuffer; Debug.Assert(offset >= 0 && count >= 0, $"Expected offset and count greater than 0, got {offset} and {count}"); Debug.Assert(checked (offset + count) <= buffer.Length, $"Expected offset+count <= buffer.Length, got {offset}+{count}>={buffer.Length}"); break; } } return(SecurityStatusAdapterPal.GetSecurityStatusPalFromInterop(errorCode)); } }
internal static SecurityStatusPal InitializeSecurityContext( ref SafeFreeCredentials?credentialsHandle, ref SafeDeleteContext?securityContext, string?spn, ContextFlagsPal requestedContextFlags, ReadOnlySpan <byte> incomingBlob, ChannelBinding?channelBinding, ref byte[]?resultBlob, out int resultBlobLength, ref ContextFlagsPal contextFlags) { InputSecurityBuffers inputBuffers = default; if (!incomingBlob.IsEmpty) { inputBuffers.SetNextBuffer(new InputSecurityBuffer(incomingBlob, SecurityBufferType.SECBUFFER_TOKEN)); } if (channelBinding != null) { inputBuffers.SetNextBuffer(new InputSecurityBuffer(channelBinding)); } var outSecurityBuffer = new SecurityBuffer(resultBlob, SecurityBufferType.SECBUFFER_TOKEN); Interop.SspiCli.ContextFlags outContextFlags = Interop.SspiCli.ContextFlags.Zero; // There is only one SafeDeleteContext type on Windows which is SafeDeleteSslContext so this cast is safe. SafeDeleteSslContext?sslContext = (SafeDeleteSslContext?)securityContext; Interop.SECURITY_STATUS winStatus = (Interop.SECURITY_STATUS)SSPIWrapper.InitializeSecurityContext( GlobalSSPI.SSPIAuth, ref credentialsHandle, ref sslContext, spn, ContextFlagsAdapterPal.GetInteropFromContextFlagsPal(requestedContextFlags), Interop.SspiCli.Endianness.SECURITY_NETWORK_DREP, inputBuffers, ref outSecurityBuffer, ref outContextFlags); securityContext = sslContext; Debug.Assert(outSecurityBuffer.offset == 0); resultBlob = outSecurityBuffer.token; resultBlobLength = outSecurityBuffer.size; contextFlags = ContextFlagsAdapterPal.GetContextFlagsPalFromInterop(outContextFlags); return(SecurityStatusAdapterPal.GetSecurityStatusPalFromInterop(winStatus)); }
public static SecurityStatusPal InitializeSecurityContext(SafeFreeCredentials credentialsHandle, ref SafeDeleteContext context, string targetName, SecurityBuffer[] inputBuffers, SecurityBuffer outputBuffer, SslAuthenticationOptions sslAuthenticationOptions) { Interop.SspiCli.ContextFlags unusedAttributes = default(Interop.SspiCli.ContextFlags); int errorCode = SSPIWrapper.InitializeSecurityContext( GlobalSSPI.SSPISecureChannel, credentialsHandle, ref context, targetName, RequiredFlags | Interop.SspiCli.ContextFlags.InitManualCredValidation, Interop.SspiCli.Endianness.SECURITY_NATIVE_DREP, inputBuffers, outputBuffer, ref unusedAttributes); return(SecurityStatusAdapterPal.GetSecurityStatusPalFromNativeInt(errorCode)); }
internal static SecurityStatusPal AcceptSecurityContext( SafeFreeCredentials?credentialsHandle, ref SafeDeleteContext?securityContext, ContextFlagsPal requestedContextFlags, byte[]?incomingBlob, ChannelBinding?channelBinding, ref byte[]?resultBlob, ref ContextFlagsPal contextFlags) { InputSecurityBuffers inputBuffers = default; if (incomingBlob != null) { inputBuffers.SetNextBuffer(new InputSecurityBuffer(incomingBlob, SecurityBufferType.SECBUFFER_TOKEN)); } if (channelBinding != null) { inputBuffers.SetNextBuffer(new InputSecurityBuffer(channelBinding)); } var outSecurityBuffer = new SecurityBuffer(resultBlob, SecurityBufferType.SECBUFFER_TOKEN); Interop.SspiCli.ContextFlags outContextFlags = Interop.SspiCli.ContextFlags.Zero; // There is only one SafeDeleteContext type on Windows which is SafeDeleteSslContext so this cast is safe. SafeDeleteSslContext?sslContext = (SafeDeleteSslContext?)securityContext; Interop.SECURITY_STATUS winStatus = (Interop.SECURITY_STATUS)SSPIWrapper.AcceptSecurityContext( GlobalSSPI.SSPIAuth, credentialsHandle, ref sslContext, ContextFlagsAdapterPal.GetInteropFromContextFlagsPal(requestedContextFlags), Interop.SspiCli.Endianness.SECURITY_NETWORK_DREP, inputBuffers, ref outSecurityBuffer, ref outContextFlags); resultBlob = outSecurityBuffer.token; securityContext = sslContext; contextFlags = ContextFlagsAdapterPal.GetContextFlagsPalFromInterop(outContextFlags); return(SecurityStatusAdapterPal.GetSecurityStatusPalFromInterop(winStatus)); }
internal static SecurityStatusPal AcceptSecurityContext( SafeFreeCredentials credentialsHandle, ref SafeDeleteContext securityContext, ContextFlagsPal requestedContextFlags, SecurityBuffer[] inSecurityBufferArray, SecurityBuffer outSecurityBuffer, ref ContextFlagsPal contextFlags) { Interop.SspiCli.ContextFlags outContextFlags = Interop.SspiCli.ContextFlags.Zero; Interop.SECURITY_STATUS winStatus = (Interop.SECURITY_STATUS)SSPIWrapper.AcceptSecurityContext( GlobalSSPI.SSPIAuth, credentialsHandle, ref securityContext, ContextFlagsAdapterPal.GetInteropFromContextFlagsPal(requestedContextFlags), Interop.SspiCli.Endianness.SECURITY_NETWORK_DREP, inSecurityBufferArray, outSecurityBuffer, ref outContextFlags); contextFlags = ContextFlagsAdapterPal.GetContextFlagsPalFromInterop(outContextFlags); return(SecurityStatusAdapterPal.GetSecurityStatusPalFromInterop(winStatus)); }
internal static SecurityStatusPal InitializeSecurityContext( SafeFreeCredentials credentialsHandle, ref SafeDeleteContext securityContext, string spn, ContextFlagsPal requestedContextFlags, SecurityBuffer[] inSecurityBufferArray, SecurityBuffer outSecurityBuffer, ref ContextFlagsPal contextFlags) { Interop.SspiCli.ContextFlags outContextFlags = Interop.SspiCli.ContextFlags.Zero; Interop.SecurityStatus winStatus = (Interop.SecurityStatus)SSPIWrapper.InitializeSecurityContext( GlobalSSPI.SSPIAuth, credentialsHandle, ref securityContext, spn, ContextFlagsAdapterPal.GetInteropFromContextFlagsPal(requestedContextFlags), Interop.SspiCli.Endianness.Network, inSecurityBufferArray, outSecurityBuffer, ref outContextFlags); contextFlags = ContextFlagsAdapterPal.GetContextFlagsPalFromInterop(outContextFlags); return(SecurityStatusAdapterPal.GetSecurityStatusPalFromInterop(winStatus)); }
public static unsafe SecurityStatusPal EncryptMessage(SafeDeleteContext securityContext, byte[] input, int offset, int size, int headerSize, int trailerSize, ref byte[] output, out int resultSize) { // Ensure that there is sufficient space for the message output. int bufferSizeNeeded; try { bufferSizeNeeded = checked (size + headerSize + trailerSize); } catch { if (GlobalLog.IsEnabled) { GlobalLog.Assert("SslStreamPal.Windows: SecureChannel#" + LoggingHash.HashString(securityContext) + "::Encrypt", "Arguments out of range."); } Debug.Fail("SslStreamPal.Windows: SecureChannel#" + LoggingHash.HashString(securityContext) + "::Encrypt", "Arguments out of range."); throw; } if (output == null || output.Length < bufferSizeNeeded) { output = new byte[bufferSizeNeeded]; } // Copy the input into the output buffer to prepare for SCHANNEL's expectations Buffer.BlockCopy(input, offset, output, headerSize, size); const int NumSecBuffers = 4; // header + data + trailer + empty var unmanagedBuffer = stackalloc Interop.SspiCli.SecBuffer[NumSecBuffers]; var sdcInOut = new Interop.SspiCli.SecBufferDesc(NumSecBuffers); sdcInOut.pBuffers = unmanagedBuffer; fixed(byte *outputPtr = output) { Interop.SspiCli.SecBuffer *headerSecBuffer = &unmanagedBuffer[0]; headerSecBuffer->BufferType = SecurityBufferType.SECBUFFER_STREAM_HEADER; headerSecBuffer->pvBuffer = (IntPtr)outputPtr; headerSecBuffer->cbBuffer = headerSize; Interop.SspiCli.SecBuffer *dataSecBuffer = &unmanagedBuffer[1]; dataSecBuffer->BufferType = SecurityBufferType.SECBUFFER_DATA; dataSecBuffer->pvBuffer = (IntPtr)(outputPtr + headerSize); dataSecBuffer->cbBuffer = size; Interop.SspiCli.SecBuffer *trailerSecBuffer = &unmanagedBuffer[2]; trailerSecBuffer->BufferType = SecurityBufferType.SECBUFFER_STREAM_TRAILER; trailerSecBuffer->pvBuffer = (IntPtr)(outputPtr + headerSize + size); trailerSecBuffer->cbBuffer = trailerSize; Interop.SspiCli.SecBuffer *emptySecBuffer = &unmanagedBuffer[3]; emptySecBuffer->BufferType = SecurityBufferType.SECBUFFER_EMPTY; emptySecBuffer->cbBuffer = 0; emptySecBuffer->pvBuffer = IntPtr.Zero; int errorCode = GlobalSSPI.SSPISecureChannel.EncryptMessage(securityContext, sdcInOut, 0); if (errorCode != 0) { if (GlobalLog.IsEnabled) { GlobalLog.Print("SslStreamPal.Windows: SecureChannel#" + LoggingHash.HashString(securityContext) + "::Encrypt ERROR" + errorCode.ToString("x")); } resultSize = 0; return(SecurityStatusAdapterPal.GetSecurityStatusPalFromNativeInt(errorCode)); } Debug.Assert(headerSecBuffer->cbBuffer >= 0 && dataSecBuffer->cbBuffer >= 0 && trailerSecBuffer->cbBuffer >= 0); Debug.Assert(checked (headerSecBuffer->cbBuffer + dataSecBuffer->cbBuffer + trailerSecBuffer->cbBuffer) <= output.Length); resultSize = checked (headerSecBuffer->cbBuffer + dataSecBuffer->cbBuffer + trailerSecBuffer->cbBuffer); return(new SecurityStatusPal(SecurityStatusPalErrorCode.OK)); } }
public static Exception GetException(SecurityStatusPal status) { int win32Code = (int)SecurityStatusAdapterPal.GetInteropFromSecurityStatusPal(status); return(new Win32Exception(win32Code)); }
internal static Win32Exception CreateExceptionFromError(SecurityStatusPal statusCode) { return(new Win32Exception((int)SecurityStatusAdapterPal.GetInteropFromSecurityStatusPal(statusCode))); }
public static unsafe SecurityStatusPal EncryptMessage(SafeDeleteContext securityContext, ReadOnlyMemory <byte> input, int headerSize, int trailerSize, ref byte[] output, out int resultSize) { // Ensure that there is sufficient space for the message output. int bufferSizeNeeded; try { bufferSizeNeeded = checked (input.Length + headerSize + trailerSize); } catch { NetEventSource.Fail(securityContext, "Arguments out of range"); throw; } if (output == null || output.Length < bufferSizeNeeded) { output = new byte[bufferSizeNeeded]; } // Copy the input into the output buffer to prepare for SCHANNEL's expectations input.Span.CopyTo(new Span <byte>(output, headerSize, input.Length)); const int NumSecBuffers = 4; // header + data + trailer + empty var unmanagedBuffer = stackalloc Interop.SspiCli.SecBuffer[NumSecBuffers]; var sdcInOut = new Interop.SspiCli.SecBufferDesc(NumSecBuffers); sdcInOut.pBuffers = unmanagedBuffer; fixed(byte *outputPtr = output) { Interop.SspiCli.SecBuffer *headerSecBuffer = &unmanagedBuffer[0]; headerSecBuffer->BufferType = SecurityBufferType.SECBUFFER_STREAM_HEADER; headerSecBuffer->pvBuffer = (IntPtr)outputPtr; headerSecBuffer->cbBuffer = headerSize; Interop.SspiCli.SecBuffer *dataSecBuffer = &unmanagedBuffer[1]; dataSecBuffer->BufferType = SecurityBufferType.SECBUFFER_DATA; dataSecBuffer->pvBuffer = (IntPtr)(outputPtr + headerSize); dataSecBuffer->cbBuffer = input.Length; Interop.SspiCli.SecBuffer *trailerSecBuffer = &unmanagedBuffer[2]; trailerSecBuffer->BufferType = SecurityBufferType.SECBUFFER_STREAM_TRAILER; trailerSecBuffer->pvBuffer = (IntPtr)(outputPtr + headerSize + input.Length); trailerSecBuffer->cbBuffer = trailerSize; Interop.SspiCli.SecBuffer *emptySecBuffer = &unmanagedBuffer[3]; emptySecBuffer->BufferType = SecurityBufferType.SECBUFFER_EMPTY; emptySecBuffer->cbBuffer = 0; emptySecBuffer->pvBuffer = IntPtr.Zero; int errorCode = GlobalSSPI.SSPISecureChannel.EncryptMessage(securityContext, ref sdcInOut, 0); if (errorCode != 0) { if (NetEventSource.IsEnabled) { NetEventSource.Info(securityContext, $"Encrypt ERROR {errorCode:X}"); } resultSize = 0; return(SecurityStatusAdapterPal.GetSecurityStatusPalFromNativeInt(errorCode)); } Debug.Assert(headerSecBuffer->cbBuffer >= 0 && dataSecBuffer->cbBuffer >= 0 && trailerSecBuffer->cbBuffer >= 0); Debug.Assert(checked (headerSecBuffer->cbBuffer + dataSecBuffer->cbBuffer + trailerSecBuffer->cbBuffer) <= output.Length); resultSize = checked (headerSecBuffer->cbBuffer + dataSecBuffer->cbBuffer + trailerSecBuffer->cbBuffer); return(new SecurityStatusPal(SecurityStatusPalErrorCode.OK)); } }