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) { 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 byte[] GetNegotiatedApplicationProtocol(SafeDeleteContext context) { Interop.SecPkgContext_ApplicationProtocol alpnContext = SSPIWrapper.QueryContextAttributes( GlobalSSPI.SSPISecureChannel, context, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_APPLICATION_PROTOCOL) as Interop.SecPkgContext_ApplicationProtocol; // Check if the context returned is alpn data, with successful negotiation. if (alpnContext == null || alpnContext.ProtoNegoExt != Interop.ApplicationProtocolNegotiationExt.ALPN || alpnContext.ProtoNegoStatus != Interop.ApplicationProtocolNegotiationStatus.Success) { return(null); } return(alpnContext.Protocol); }
// // Security: we temporarily reset thread token to open the handle under process account. // private static SafeFreeCredentials AcquireCredentialsHandle(Interop.SspiCli.CredentialUse credUsage, Interop.SspiCli.SCHANNEL_CRED secureCredential) { // First try without impersonation, if it fails, then try the process account. // I.E. We don't know which account the certificate context was created under. try { // // For app-compat we want to ensure the credential are accessed under >>process<< account. // return(WindowsIdentity.RunImpersonated <SafeFreeCredentials>(SafeAccessTokenHandle.InvalidHandle, () => { return SSPIWrapper.AcquireCredentialsHandle(GlobalSSPI.SSPISecureChannel, SecurityPackage, credUsage, secureCredential); })); } catch { return(SSPIWrapper.AcquireCredentialsHandle(GlobalSSPI.SSPISecureChannel, SecurityPackage, credUsage, secureCredential)); } }
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 void ProcessHandshakeSuccess() { StreamSizes sizes = SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPISecureChannel, this.m_SecurityContext, ContextAttribute.StreamSizes) as StreamSizes; if (sizes != null) { try { this.m_HeaderSize = sizes.header; this.m_TrailerSize = sizes.trailer; this.m_MaxDataSize = sizes.maximumMessage - (this.m_HeaderSize + this.m_TrailerSize); } catch (Exception exception) { NclUtilities.IsFatal(exception); throw; } } this.m_ConnectionInfo = SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPISecureChannel, this.m_SecurityContext, ContextAttribute.ConnectionInfo) as SslConnectionInfo; }
internal SecurityStatus Decrypt(byte[] payload, ref int offset, ref int count) { GlobalLog.Print("SecureChannel#" + Logging.HashString(this) + "::Decrypt() - offset: " + offset.ToString() + " size: " + count.ToString() + " buffersize: " + payload.Length.ToString()); if (offset < 0 || offset > (payload == null ? 0 : payload.Length)) { GlobalLog.Assert(false, "SecureChannel#" + Logging.HashString(this) + "::Encrypt", "Argument 'offset' out of range."); throw new ArgumentOutOfRangeException("offset"); } if (count < 0 || count > (payload == null ? 0 : payload.Length - offset)) { GlobalLog.Assert(false, "SecureChannel#" + Logging.HashString(this) + "::Encrypt", "Argument 'count' out of range."); throw new ArgumentOutOfRangeException("count"); } SecurityStatus secStatus = SSPIWrapper.DecryptMessage(GlobalSSPI.SSPISecureChannel, _securityContext, payload, ref offset, ref count); return(secStatus); }
internal static int MakeSignature(SafeDeleteContext securityContext, byte[] buffer, int offset, int count, [AllowNull] ref byte[] output) { SecPkgContext_Sizes sizes = default; bool success = SSPIWrapper.QueryBlittableContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_SIZES, ref sizes); Debug.Assert(success); // alloc new output buffer if not supplied or too small int resultSize = count + sizes.cbMaxSignature; if (output == null || output.Length < resultSize) { output = new byte[resultSize]; } // make a copy of user data for in-place encryption Buffer.BlockCopy(buffer, offset, output, sizes.cbMaxSignature, count); // setup security buffers for ssp call #if NETSTANDARD2_0 Span <SecurityBuffer> securityBuffer = new SecurityBuffer[2]; #else TwoSecurityBuffers stackBuffer = default; Span <SecurityBuffer> securityBuffer = MemoryMarshal.CreateSpan(ref stackBuffer._item0, 2); #endif securityBuffer[0] = new SecurityBuffer(output, 0, sizes.cbMaxSignature, SecurityBufferType.SECBUFFER_TOKEN); securityBuffer[1] = new SecurityBuffer(output, sizes.cbMaxSignature, count, SecurityBufferType.SECBUFFER_DATA); // call SSP Function int errorCode = SSPIWrapper.MakeSignature(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, 0); // throw if error if (errorCode != 0) { NetEventSource.Info($"MakeSignature threw error: {errorCode.ToString("x", NumberFormatInfo.InvariantInfo)}"); throw new Win32Exception(errorCode); } // return signed size return(securityBuffer[0].size + securityBuffer[1].size); }
private unsafe string[] GetIssuers() { string[] strArray = new string[0]; if (this.IsValidContext) { IssuerListInfoEx ex = (IssuerListInfoEx)SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPISecureChannel, this.m_SecurityContext, ContextAttribute.IssuerListInfoEx); try { if (ex.cIssuers <= 0) { return(strArray); } uint cIssuers = ex.cIssuers; strArray = new string[ex.cIssuers]; _CERT_CHAIN_ELEMENT *handle = (_CERT_CHAIN_ELEMENT *)ex.aIssuers.DangerousGetHandle(); for (int i = 0; i < cIssuers; i++) { _CERT_CHAIN_ELEMENT *_cert_chain_elementPtr2 = handle + i; uint cbSize = _cert_chain_elementPtr2->cbSize; byte * pCertContext = (byte *)_cert_chain_elementPtr2->pCertContext; byte[] encodedDistinguishedName = new byte[cbSize]; for (int j = 0; j < cbSize; j++) { encodedDistinguishedName[j] = pCertContext[j]; } X500DistinguishedName name = new X500DistinguishedName(encodedDistinguishedName); strArray[i] = name.Name; } } finally { if (ex.aIssuers != null) { ex.aIssuers.Close(); } } } return(strArray); }
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 int MakeSignature(SafeDeleteContext securityContext, byte[] buffer, int offset, int count, ref byte[] output) { SecPkgContext_Sizes sizes = SSPIWrapper.QueryContextAttributes( GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_SIZES ) as SecPkgContext_Sizes; // alloc new output buffer if not supplied or too small int resultSize = count + sizes.cbMaxSignature; if (output == null || output.Length < resultSize) { output = new byte[resultSize]; } // make a copy of user data for in-place encryption Buffer.BlockCopy(buffer, offset, output, sizes.cbMaxSignature, count); // setup security buffers for ssp call SecurityBuffer[] securityBuffer = new SecurityBuffer[2]; securityBuffer[0] = new SecurityBuffer(output, 0, sizes.cbMaxSignature, SecurityBufferType.SECBUFFER_TOKEN); securityBuffer[1] = new SecurityBuffer(output, sizes.cbMaxSignature, count, SecurityBufferType.SECBUFFER_DATA); // call SSP Function int errorCode = SSPIWrapper.MakeSignature(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, 0); // throw if error if (errorCode != 0) { NetEventSource.Info($"MakeSignature threw error: {errorCode.ToString("x", NumberFormatInfo.InvariantInfo)}"); throw new Win32Exception(errorCode); } // return signed size return(securityBuffer[0].size + securityBuffer[1].size); }
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)); }
internal unsafe static SafeFreeCredentials AcquireCredentialsHandle(string package, bool isServer, NetworkCredential credential) { SafeSspiAuthDataHandle authData = null; try { Interop.SecurityStatus result = Interop.SspiCli.SspiEncodeStringsAsAuthIdentity( credential.UserName, credential.Domain, credential.Password, out authData); if (result != Interop.SecurityStatus.OK) { if (NetEventSource.Log.IsEnabled()) { NetEventSource.PrintError( NetEventSource.ComponentType.Security, SR.Format( SR.net_log_operation_failed_with_error, "SspiEncodeStringsAsAuthIdentity()", String.Format(CultureInfo.CurrentCulture, "0x{0:X}", (int)result))); } throw new Win32Exception((int)result); } return(SSPIWrapper.AcquireCredentialsHandle(GlobalSSPI.SSPIAuth, package, (isServer ? Interop.SspiCli.CredentialUse.Inbound : Interop.SspiCli.CredentialUse.Outbound), ref authData)); } finally { if (authData != null) { authData.Dispose(); } } }
internal static int Decrypt( SafeDeleteContext securityContext, byte[] buffer, int offset, int count, bool isConfidential, bool isNtlm, out int newOffset, uint sequenceNumber) { if (offset < 0 || offset > (buffer == null ? 0 : buffer.Length)) { NetEventSource.Fail(null, "Argument 'offset' out of range."); throw new ArgumentOutOfRangeException(nameof(offset)); } if (count < 0 || count > (buffer == null ? 0 : buffer.Length - offset)) { NetEventSource.Fail(null, "Argument 'count' out of range."); throw new ArgumentOutOfRangeException(nameof(count)); } if (isNtlm) { return(DecryptNtlm(securityContext, buffer, offset, count, isConfidential, out newOffset, sequenceNumber)); } // // Kerberos and up // TwoSecurityBuffers buffers = default; var securityBuffer = MemoryMarshal.CreateSpan(ref buffers._item0, 2); securityBuffer[0] = new SecurityBuffer(buffer, offset, count, SecurityBufferType.SECBUFFER_STREAM); securityBuffer[1] = new SecurityBuffer(0, SecurityBufferType.SECBUFFER_DATA); int errorCode; if (isConfidential) { errorCode = SSPIWrapper.DecryptMessage(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, sequenceNumber); } else { errorCode = SSPIWrapper.VerifySignature(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, sequenceNumber); } if (errorCode != 0) { Exception e = new Win32Exception(errorCode); if (NetEventSource.IsEnabled) { NetEventSource.Error(null, e); } throw e; } if (securityBuffer[1].type != SecurityBufferType.SECBUFFER_DATA) { throw new InternalException(securityBuffer[1].type); } newOffset = securityBuffer[1].offset; return(securityBuffer[1].size); }
public static void VerifyPackageInfo() { SSPIWrapper.GetVerifyPackageInfo(GlobalSSPI.SSPISecureChannel, SecurityPackage, true); }
internal static string QueryContextAuthenticationPackage(SafeDeleteContext securityContext) { var negotiationInfoClass = SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_NEGOTIATION_INFO) as NegotiationInfoClass; return(negotiationInfoClass?.AuthenticationPackage); }
internal static string QueryContextClientSpecifiedSpn(SafeDeleteContext securityContext) { return(SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_CLIENT_SPECIFIED_TARGET) as string); }
internal MonoTlsConnectionInfo GetMonoConnectionInfo() { return(SSPIWrapper.GetMonoConnectionInfo(m_SecModule, m_SecurityContext)); }
internal static int QueryMaxTokenSize(string package) { return(SSPIWrapper.GetVerifyPackageInfo(GlobalSSPI.SSPIAuth, package, true).MaxToken); }
internal ProtocolToken CreateHelloRequestMessage() { var buffer = SSPIWrapper.CreateHelloRequestMessage(m_SecModule, m_SecurityContext); return(new ProtocolToken(buffer, SecurityStatus.ContinueNeeded)); }
private SecurityStatus GenerateToken(byte[] input, int offset, int count, ref byte[] output) { if ((offset < 0) || (offset > ((input == null) ? 0 : input.Length))) { throw new ArgumentOutOfRangeException("offset"); } if ((count < 0) || (count > ((input == null) ? 0 : (input.Length - offset)))) { throw new ArgumentOutOfRangeException("count"); } SecurityBuffer inputBuffer = null; SecurityBuffer[] inputBuffers = null; if (input != null) { inputBuffer = new SecurityBuffer(input, offset, count, BufferType.Token); inputBuffers = new SecurityBuffer[] { inputBuffer, new SecurityBuffer(null, 0, 0, BufferType.Empty) }; } SecurityBuffer outputBuffer = new SecurityBuffer(null, BufferType.Token); int num = 0; bool flag = false; byte[] thumbPrint = null; try { do { thumbPrint = null; if (this.m_RefreshCredentialNeeded) { flag = this.m_ServerMode ? this.AcquireServerCredentials(ref thumbPrint) : this.AcquireClientCredentials(ref thumbPrint); } if (this.m_ServerMode) { num = SSPIWrapper.AcceptSecurityContext(GlobalSSPI.SSPISecureChannel, ref this.m_CredentialsHandle, ref this.m_SecurityContext, (ContextFlags.AcceptStream | ContextFlags.AllocateMemory | ContextFlags.Confidentiality | ContextFlags.SequenceDetect | ContextFlags.ReplayDetect) | (this.m_RemoteCertRequired ? ContextFlags.MutualAuth : ContextFlags.Zero), Endianness.Native, inputBuffer, outputBuffer, ref this.m_Attributes); } else if (inputBuffer == null) { num = SSPIWrapper.InitializeSecurityContext(GlobalSSPI.SSPISecureChannel, ref this.m_CredentialsHandle, ref this.m_SecurityContext, this.m_Destination, ContextFlags.AcceptIdentify | ContextFlags.AllocateMemory | ContextFlags.Confidentiality | ContextFlags.SequenceDetect | ContextFlags.ReplayDetect, Endianness.Native, inputBuffer, outputBuffer, ref this.m_Attributes); } else { num = SSPIWrapper.InitializeSecurityContext(GlobalSSPI.SSPISecureChannel, this.m_CredentialsHandle, ref this.m_SecurityContext, this.m_Destination, ContextFlags.AcceptIdentify | ContextFlags.AllocateMemory | ContextFlags.Confidentiality | ContextFlags.SequenceDetect | ContextFlags.ReplayDetect, Endianness.Native, inputBuffers, outputBuffer, ref this.m_Attributes); } }while (flag && (this.m_CredentialsHandle == null)); } finally { if (this.m_RefreshCredentialNeeded) { this.m_RefreshCredentialNeeded = false; if (this.m_CredentialsHandle != null) { this.m_CredentialsHandle.Close(); } if ((!flag && (this.m_SecurityContext != null)) && (!this.m_SecurityContext.IsInvalid && !this.m_CredentialsHandle.IsInvalid)) { SslSessionsCache.CacheCredential(this.m_CredentialsHandle, thumbPrint, this.m_ProtocolFlags, this.m_EncryptionPolicy); } } } output = outputBuffer.token; return((SecurityStatus)num); }
internal static unsafe int Encrypt( SafeDeleteContext securityContext, ReadOnlySpan <byte> buffer, bool isConfidential, bool isNtlm, [NotNull] ref byte[]?output) { SecPkgContext_Sizes sizes = default; bool success = SSPIWrapper.QueryBlittableContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_SIZES, ref sizes); Debug.Assert(success); int maxCount = checked (int.MaxValue - 4 - sizes.cbBlockSize - sizes.cbSecurityTrailer); if (buffer.Length > maxCount) { throw new ArgumentOutOfRangeException(nameof(buffer.Length), SR.Format(SR.net_io_out_range, maxCount)); } int resultSize = buffer.Length + sizes.cbSecurityTrailer + sizes.cbBlockSize; if (output == null || output.Length < resultSize + 4) { output = new byte[resultSize + 4]; } // Make a copy of user data for in-place encryption. buffer.CopyTo(output.AsSpan(4 + sizes.cbSecurityTrailer)); fixed(byte *outputPtr = output) { // Prepare buffers TOKEN(signature), DATA and Padding. Interop.SspiCli.SecBuffer *unmanagedBuffer = stackalloc Interop.SspiCli.SecBuffer[3]; Interop.SspiCli.SecBuffer *tokenBuffer = &unmanagedBuffer[0]; Interop.SspiCli.SecBuffer *dataBuffer = &unmanagedBuffer[1]; Interop.SspiCli.SecBuffer *paddingBuffer = &unmanagedBuffer[2]; tokenBuffer->BufferType = SecurityBufferType.SECBUFFER_TOKEN; tokenBuffer->pvBuffer = (IntPtr)(outputPtr + 4); tokenBuffer->cbBuffer = sizes.cbSecurityTrailer; dataBuffer->BufferType = SecurityBufferType.SECBUFFER_DATA; dataBuffer->pvBuffer = (IntPtr)(outputPtr + 4 + sizes.cbSecurityTrailer); dataBuffer->cbBuffer = buffer.Length; paddingBuffer->BufferType = SecurityBufferType.SECBUFFER_PADDING; paddingBuffer->pvBuffer = (IntPtr)(outputPtr + 4 + sizes.cbSecurityTrailer + buffer.Length); paddingBuffer->cbBuffer = sizes.cbBlockSize; Interop.SspiCli.SecBufferDesc sdcInOut = new Interop.SspiCli.SecBufferDesc(3) { pBuffers = unmanagedBuffer }; if (isNtlm && !isConfidential) { dataBuffer->BufferType |= SecurityBufferType.SECBUFFER_READONLY; } uint qop = isConfidential ? 0 : Interop.SspiCli.SECQOP_WRAP_NO_ENCRYPT; int errorCode = GlobalSSPI.SSPIAuth.EncryptMessage(securityContext, ref sdcInOut, qop); if (errorCode != 0) { Exception e = new Win32Exception(errorCode); if (NetEventSource.Log.IsEnabled()) { NetEventSource.Error(null, e); } throw new Win32Exception(errorCode); } // Compacting the result. resultSize = tokenBuffer->cbBuffer; bool forceCopy = false; if (resultSize != sizes.cbSecurityTrailer) { forceCopy = true; output.AsSpan(4 + sizes.cbSecurityTrailer, dataBuffer->cbBuffer).CopyTo(output.AsSpan(4 + resultSize, dataBuffer->cbBuffer)); } resultSize += dataBuffer->cbBuffer; if (paddingBuffer->cbBuffer != 0 && (forceCopy || resultSize != (buffer.Length + sizes.cbSecurityTrailer))) { output.AsSpan(4 + sizes.cbSecurityTrailer + buffer.Length, paddingBuffer->cbBuffer).CopyTo(output.AsSpan(4 + resultSize, paddingBuffer->cbBuffer)); } resultSize += paddingBuffer->cbBuffer; BinaryPrimitives.WriteInt32LittleEndian(output, resultSize); return(resultSize + 4); } }
internal static string QueryContextClientSpecifiedSpn(SafeDeleteContext securityContext) { return(SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.ClientSpecifiedSpn) as string); }
internal static string QueryContextAssociatedName(SafeDeleteContext securityContext) { return(SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.Names) as string); }
internal static int Decrypt( SafeDeleteContext securityContext, byte[] buffer, int offset, int count, bool isConfidential, bool isNtlm, out int newOffset, uint sequenceNumber) { if (offset < 0 || offset > (buffer == null ? 0 : buffer.Length)) { if (GlobalLog.IsEnabled) { GlobalLog.Assert("NTAuthentication#" + LoggingHash.HashString(securityContext) + "::Decrypt", "Argument 'offset' out of range."); } Debug.Fail("NTAuthentication#" + LoggingHash.HashString(securityContext) + "::Decrypt", "Argument 'offset' out of range."); throw new ArgumentOutOfRangeException(nameof(offset)); } if (count < 0 || count > (buffer == null ? 0 : buffer.Length - offset)) { if (GlobalLog.IsEnabled) { GlobalLog.Assert("NTAuthentication#" + LoggingHash.HashString(securityContext) + "::Decrypt", "Argument 'count' out of range."); } Debug.Fail("NTAuthentication#" + LoggingHash.HashString(securityContext) + "::Decrypt", "Argument 'count' out of range."); throw new ArgumentOutOfRangeException(nameof(count)); } if (isNtlm) { return(DecryptNtlm(securityContext, buffer, offset, count, isConfidential, out newOffset, sequenceNumber)); } // // Kerberos and up // var securityBuffer = new SecurityBuffer[2]; securityBuffer[0] = new SecurityBuffer(buffer, offset, count, SecurityBufferType.Stream); securityBuffer[1] = new SecurityBuffer(0, SecurityBufferType.Data); int errorCode; if (isConfidential) { errorCode = SSPIWrapper.DecryptMessage(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, sequenceNumber); } else { errorCode = SSPIWrapper.VerifySignature(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, sequenceNumber); } if (errorCode != 0) { if (GlobalLog.IsEnabled) { GlobalLog.Print("NTAuthentication#" + "::Decrypt() throw Error = " + errorCode.ToString("x", NumberFormatInfo.InvariantInfo)); } throw new Win32Exception(errorCode); } if (securityBuffer[1].type != SecurityBufferType.Data) { throw new InternalException(); } newOffset = securityBuffer[1].offset; return(securityBuffer[1].size); }
/*++ * GenerateToken - Called after each successive state * in the Client - Server handshake. This function * generates a set of bytes that will be sent next to * the server. The server responds, each response, * is pass then into this function, again, and the cycle * repeats until successful connection, or failure. * * Input: * input - bytes from the wire * output - ref to byte [], what we will send to the * server in response * Return: * errorCode - an SSPI error code * --*/ private SecurityStatus GenerateToken(byte[] input, int offset, int count, ref byte[] output) { #if TRACE_VERBOSE GlobalLog.Enter("SecureChannel#" + Logging.HashString(this) + "::GenerateToken, _refreshCredentialNeeded = " + _refreshCredentialNeeded); #endif if (offset < 0 || offset > (input == null ? 0 : input.Length)) { GlobalLog.Assert(false, "SecureChannel#" + Logging.HashString(this) + "::GenerateToken", "Argument 'offset' out of range."); throw new ArgumentOutOfRangeException("offset"); } if (count < 0 || count > (input == null ? 0 : input.Length - offset)) { GlobalLog.Assert(false, "SecureChannel#" + Logging.HashString(this) + "::GenerateToken", "Argument 'count' out of range."); throw new ArgumentOutOfRangeException("count"); } SecurityBuffer incomingSecurity = null; SecurityBuffer[] incomingSecurityBuffers = null; if (input != null) { incomingSecurity = new SecurityBuffer(input, offset, count, SecurityBufferType.Token); incomingSecurityBuffers = new SecurityBuffer[] { incomingSecurity, new SecurityBuffer(null, 0, 0, SecurityBufferType.Empty) }; } SecurityBuffer outgoingSecurity = new SecurityBuffer(null, SecurityBufferType.Token); SecurityStatus errorCode = 0; bool cachedCreds = false; byte[] thumbPrint = null; // // Looping through ASC or ISC with potentially cached credential that could have been // already disposed from a different thread before ISC or ASC dir increment a cred ref count. // try { do { thumbPrint = null; if (_refreshCredentialNeeded) { cachedCreds = _serverMode ? AcquireServerCredentials(ref thumbPrint) : AcquireClientCredentials(ref thumbPrint); } if (_serverMode) { errorCode = SSPIWrapper.AcceptSecurityContext( GlobalSSPI.SSPISecureChannel, ref _credentialsHandle, ref _securityContext, incomingSecurity, outgoingSecurity, _remoteCertRequired ); } else { if (incomingSecurity == null) { errorCode = SSPIWrapper.InitializeSecurityContext( GlobalSSPI.SSPISecureChannel, ref _credentialsHandle, ref _securityContext, _destination, incomingSecurity, outgoingSecurity ); } else { errorCode = SSPIWrapper.InitializeSecurityContext( GlobalSSPI.SSPISecureChannel, _credentialsHandle, ref _securityContext, _destination, incomingSecurityBuffers, outgoingSecurity ); } } } while (cachedCreds && _credentialsHandle == null); } finally { if (_refreshCredentialNeeded) { _refreshCredentialNeeded = false; // // Assuming the ISC or ASC has referenced the credential, // we want to call dispose so to decrement the effective ref count. // if (_credentialsHandle != null) { _credentialsHandle.Dispose(); } // // This call may bump up the credential reference count further. // Note that thumbPrint is retrieved from a safe cert object that was possible cloned from the user passed cert. // if (!cachedCreds && _securityContext != null && !_securityContext.IsInvalid && _credentialsHandle != null && !_credentialsHandle.IsInvalid) { SslSessionsCache.CacheCredential(_credentialsHandle, thumbPrint, _sslProtocols, _serverMode, _encryptionPolicy); } } } output = outgoingSecurity.token; #if TRACE_VERBOSE GlobalLog.Leave("SecureChannel#" + Logging.HashString(this) + "::GenerateToken()", Interop.MapSecurityStatus((uint)errorCode)); #endif return((SecurityStatus)errorCode); }
internal static string QueryContextAssociatedName(SafeDeleteContext securityContext) { return(SSPIWrapper.QueryStringContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_NAMES)); }
public static unsafe SafeFreeContextBufferChannelBinding QueryContextChannelBinding(SafeDeleteContext securityContext, ChannelBindingKind attribute) { return(SSPIWrapper.QueryContextChannelBinding(GlobalSSPI.SSPISecureChannel, securityContext, (Interop.SspiCli.ContextAttribute)attribute)); }
internal static int Encrypt( SafeDeleteContext securityContext, byte[] buffer, int offset, int count, bool isConfidential, bool isNtlm, ref byte[] output, uint sequenceNumber) { SecPkgContext_Sizes sizes = default; bool success = SSPIWrapper.QueryBlittableContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_SIZES, ref sizes); Debug.Assert(success); try { int maxCount = checked (int.MaxValue - 4 - sizes.cbBlockSize - sizes.cbSecurityTrailer); if (count > maxCount || count < 0) { throw new ArgumentOutOfRangeException(nameof(count), SR.Format(SR.net_io_out_range, maxCount)); } } catch (Exception e) when(!ExceptionCheck.IsFatal(e)) { NetEventSource.Fail(null, "Arguments out of range."); throw; } int resultSize = count + sizes.cbSecurityTrailer + sizes.cbBlockSize; if (output == null || output.Length < resultSize + 4) { output = new byte[resultSize + 4]; } // Make a copy of user data for in-place encryption. Buffer.BlockCopy(buffer, offset, output, 4 + sizes.cbSecurityTrailer, count); // Prepare buffers TOKEN(signature), DATA and Padding. ThreeSecurityBuffers buffers = default; var securityBuffer = MemoryMarshal.CreateSpan(ref buffers._item0, 3); securityBuffer[0] = new SecurityBuffer(output, 4, sizes.cbSecurityTrailer, SecurityBufferType.SECBUFFER_TOKEN); securityBuffer[1] = new SecurityBuffer(output, 4 + sizes.cbSecurityTrailer, count, SecurityBufferType.SECBUFFER_DATA); securityBuffer[2] = new SecurityBuffer(output, 4 + sizes.cbSecurityTrailer + count, sizes.cbBlockSize, SecurityBufferType.SECBUFFER_PADDING); int errorCode; if (isConfidential) { errorCode = SSPIWrapper.EncryptMessage(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, sequenceNumber); } else { if (isNtlm) { securityBuffer[1].type |= SecurityBufferType.SECBUFFER_READONLY; } errorCode = SSPIWrapper.MakeSignature(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, 0); } if (errorCode != 0) { Exception e = new Win32Exception(errorCode); if (NetEventSource.IsEnabled) { NetEventSource.Error(null, e); } throw e; } // Compacting the result. resultSize = securityBuffer[0].size; bool forceCopy = false; if (resultSize != sizes.cbSecurityTrailer) { forceCopy = true; Buffer.BlockCopy(output, securityBuffer[1].offset, output, 4 + resultSize, securityBuffer[1].size); } resultSize += securityBuffer[1].size; if (securityBuffer[2].size != 0 && (forceCopy || resultSize != (count + sizes.cbSecurityTrailer))) { Buffer.BlockCopy(output, securityBuffer[2].offset, output, 4 + resultSize, securityBuffer[2].size); } resultSize += securityBuffer[2].size; unchecked { output[0] = (byte)((resultSize) & 0xFF); output[1] = (byte)(((resultSize) >> 8) & 0xFF); output[2] = (byte)(((resultSize) >> 16) & 0xFF); output[3] = (byte)(((resultSize) >> 24) & 0xFF); } return(resultSize + 4); }
internal static int Encrypt( SafeDeleteContext securityContext, byte[] buffer, int offset, int count, bool isConfidential, bool isNtlm, ref byte[] output, uint sequenceNumber) { SecSizes sizes = SSPIWrapper.QueryContextAttributes( GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.Sizes ) as SecSizes; try { int maxCount = checked (Int32.MaxValue - 4 - sizes.BlockSize - sizes.SecurityTrailer); if (count > maxCount || count < 0) { throw new ArgumentOutOfRangeException(nameof(count), SR.Format(SR.net_io_out_range, maxCount)); } } catch (Exception e) { if (!ExceptionCheck.IsFatal(e)) { if (GlobalLog.IsEnabled) { GlobalLog.Assert("NTAuthentication#" + LoggingHash.HashString(securityContext) + "::Encrypt", "Arguments out of range."); } Debug.Fail("NTAuthentication#" + LoggingHash.HashString(securityContext) + "::Encrypt", "Arguments out of range."); } throw; } int resultSize = count + sizes.SecurityTrailer + sizes.BlockSize; if (output == null || output.Length < resultSize + 4) { output = new byte[resultSize + 4]; } // Make a copy of user data for in-place encryption. Buffer.BlockCopy(buffer, offset, output, 4 + sizes.SecurityTrailer, count); // Prepare buffers TOKEN(signature), DATA and Padding. var securityBuffer = new SecurityBuffer[3]; securityBuffer[0] = new SecurityBuffer(output, 4, sizes.SecurityTrailer, SecurityBufferType.Token); securityBuffer[1] = new SecurityBuffer(output, 4 + sizes.SecurityTrailer, count, SecurityBufferType.Data); securityBuffer[2] = new SecurityBuffer(output, 4 + sizes.SecurityTrailer + count, sizes.BlockSize, SecurityBufferType.Padding); int errorCode; if (isConfidential) { errorCode = SSPIWrapper.EncryptMessage(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, sequenceNumber); } else { if (isNtlm) { securityBuffer[1].type |= SecurityBufferType.ReadOnlyFlag; } errorCode = SSPIWrapper.MakeSignature(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, 0); } if (errorCode != 0) { if (GlobalLog.IsEnabled) { GlobalLog.Print("NTAuthentication#" + LoggingHash.HashString(securityContext) + "::Encrypt() throw Error = " + errorCode.ToString("x", NumberFormatInfo.InvariantInfo)); } throw new Win32Exception(errorCode); } // Compacting the result. resultSize = securityBuffer[0].size; bool forceCopy = false; if (resultSize != sizes.SecurityTrailer) { forceCopy = true; Buffer.BlockCopy(output, securityBuffer[1].offset, output, 4 + resultSize, securityBuffer[1].size); } resultSize += securityBuffer[1].size; if (securityBuffer[2].size != 0 && (forceCopy || resultSize != (count + sizes.SecurityTrailer))) { Buffer.BlockCopy(output, securityBuffer[2].offset, output, 4 + resultSize, securityBuffer[2].size); } resultSize += securityBuffer[2].size; unchecked { // TODO (Issue #6063): Should be offset by offset output[0] = (byte)((resultSize) & 0xFF); output[1] = (byte)(((resultSize) >> 8) & 0xFF); output[2] = (byte)(((resultSize) >> 16) & 0xFF); output[3] = (byte)(((resultSize) >> 24) & 0xFF); } return(resultSize + 4); }