public SecurityBufferDescriptor(SecurityBuffer[] buffers) { if (buffers == null || buffers.Length == 0) { throw new ArgumentException("cannot be null or 0 length", "buffers"); } BufferType = SecurityBufferType.Version; NumBuffers = buffers.Length; //Allocate memory for SecBuffer Array.... BufferPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SecurityBuffer)) * NumBuffers); for (int i = 0; i < buffers.Length; i++) { var currentBuffer = buffers[i]; var currentOffset = i * Marshal.SizeOf(typeof(SecurityBuffer)); Marshal.WriteInt32(BufferPtr, currentOffset, currentBuffer.Count); var length = currentOffset + Marshal.SizeOf(typeof(int)); Marshal.WriteInt32(BufferPtr, length, (int)currentBuffer.BufferType); length = currentOffset + Marshal.SizeOf(typeof(int)) + Marshal.SizeOf(typeof(int)); Marshal.WriteIntPtr(BufferPtr, length, currentBuffer.Token); } }
public SecurityStatus InitializeSecurityContext(ref SafeFreeCredentials credential, ref SafeDeleteContext context, string targetName, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer) { Interop.Secur32.ContextFlags outFlags = Interop.Secur32.ContextFlags.Zero; var retStatus = (SecurityStatus)SafeDeleteContext.InitializeSecurityContext(ref credential, ref context, targetName, RequiredFlags | Interop.Secur32.ContextFlags.InitManualCredValidation, Interop.Secur32.Endianness.Native, inputBuffer, null, outputBuffer, ref outFlags); return MapToSecurityStatus((Interop.SecurityStatus)retStatus); }
public SecurityBufferDescriptor(byte[] secBufferBytes) { BufferType = SecurityBufferType.Version; NumBuffers = 1; var buffer = new SecurityBuffer(secBufferBytes); BufferPtr = Marshal.AllocHGlobal(Marshal.SizeOf(buffer)); Marshal.StructureToPtr(buffer, BufferPtr, false); }
internal static SecurityStatus AcceptSecurityContext(SSPIInterface SecModule, ref SafeFreeCredentials credential, ref SafeDeleteContext context, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, bool remoteCertRequired) { if (Logging.On) { Logging.PrintInfo(Logging.Web, "AcceptSecurityContext(" + "credential = " + credential.ToString() + ", " + "context = " + Logging.ObjectToString(context) + ", " + "remoteCertRequired = " + remoteCertRequired); } return SecModule.AcceptSecurityContext(ref credential, ref context, inputBuffer, outputBuffer, remoteCertRequired); }
public int AcceptSecurityContext(ref SafeFreeCredentials credential, ref SafeDeleteContext context, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, bool remoteCertRequired) { Interop.Secur32.ContextFlags outFlags = Interop.Secur32.ContextFlags.Zero; return SafeDeleteContext.AcceptSecurityContext( ref credential, ref context, ServerRequiredFlags | (remoteCertRequired ? Interop.Secur32.ContextFlags.MutualAuth : Interop.Secur32.ContextFlags.Zero), Interop.Secur32.Endianness.Native, inputBuffer, null, outputBuffer, ref outFlags ); }
internal static SecurityStatus InitializeSecurityContext(SSPIInterface SecModule, SafeFreeCredentials credential, ref SafeDeleteContext context, string targetName, SecurityBuffer[] inputBuffers, SecurityBuffer outputBuffer) { if (Logging.On) { Logging.PrintInfo(Logging.Web, "InitializeSecurityContext(" + "credential = " + credential.ToString() + ", " + "context = " + Logging.ObjectToString(context) + ", " + "targetName = " + targetName); } SecurityStatus errorCode = SecModule.InitializeSecurityContext(credential, ref context, targetName, inputBuffers, outputBuffer); return errorCode; }
public static SecurityStatusPal AcceptSecurityContext(ref SafeFreeCredentials credentialsHandle, ref SafeDeleteContext context, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, bool remoteCertRequired) { Interop.SspiCli.ContextFlags unusedAttributes = default(Interop.SspiCli.ContextFlags); int errorCode = SSPIWrapper.AcceptSecurityContext( GlobalSSPI.SSPISecureChannel, ref credentialsHandle, ref context, ServerRequiredFlags | (remoteCertRequired ? Interop.SspiCli.ContextFlags.MutualAuth : Interop.SspiCli.ContextFlags.Zero), Interop.SspiCli.Endianness.Native, inputBuffer, outputBuffer, ref unusedAttributes); return GetSecurityStatusPalFromWin32Int(errorCode); }
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.Native, inputBuffers, outputBuffer, ref unusedAttributes); return GetSecurityStatusPalFromWin32Int(errorCode); }
internal static SecurityStatus InitializeSecurityContext(SSPIInterface SecModule, ref SafeFreeCredentials credential, ref SafeDeleteContext context, string targetName, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer) { if (Logging.On) { Logging.PrintInfo(Logging.Web, "InitializeSecurityContext(" + "credential = " + credential.ToString() + ", " + "context = " + Logging.ObjectToString(context) + ", " + "targetName = " + targetName); } SecurityStatus errorCode = SecModule.InitializeSecurityContext(ref credential, ref context, targetName, inputBuffer, outputBuffer); if (Logging.On) { Logging.PrintInfo(Logging.Web, SR.Format(SR.net_log_sspi_security_context_input_buffer, "InitializeSecurityContext", (inputBuffer == null ? 0 : inputBuffer.size), outputBuffer.size, (SecurityStatus)errorCode)); } return errorCode; }
private static SecurityStatusPal HandshakeInternal(SafeFreeCredentials credential, ref SafeDeleteContext context, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, bool isServer, bool remoteCertRequired) { Debug.Assert(!credential.IsInvalid); try { if ((null == context) || context.IsInvalid) { context = new SafeDeleteContext(credential, isServer, remoteCertRequired); } byte[] output = null; int outputSize; bool done; if (null == inputBuffer) { done = Interop.OpenSsl.DoSslHandshake(context.SslContext, null, 0, 0, out output, out outputSize); } else { done = Interop.OpenSsl.DoSslHandshake(context.SslContext, inputBuffer.token, inputBuffer.offset, inputBuffer.size, out output, out outputSize); } outputBuffer.size = outputSize; outputBuffer.offset = 0; outputBuffer.token = outputSize > 0 ? output : null; return done ? SecurityStatusPal.OK : SecurityStatusPal.ContinueNeeded; } catch { // TODO: This Debug.Fail is triggering on Linux in many test cases #4317 // Debug.Fail("Exception Caught. - " + ex); return SecurityStatusPal.InternalError; } }
internal static int AcceptSecurityContext(SSPIInterface secModule, SafeFreeCredentials credential, ref SafeDeleteContext context, Interop.SspiCli.ContextFlags inFlags, Interop.SspiCli.Endianness datarep, SecurityBuffer[] inputBuffers, SecurityBuffer outputBuffer, ref Interop.SspiCli.ContextFlags outFlags) { if (NetEventSource.IsEnabled) NetEventSource.Log.AcceptSecurityContext(credential, context, inFlags); int errorCode = secModule.AcceptSecurityContext(credential, ref context, inputBuffers, inFlags, datarep, outputBuffer, ref outFlags); if (NetEventSource.IsEnabled) NetEventSource.Log.SecurityContextInputBuffers(nameof(AcceptSecurityContext), inputBuffers?.Length ?? 0, outputBuffer.size, (Interop.SECURITY_STATUS)errorCode); return 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.Data); decspc[1] = new SecurityBuffer(null, SecurityBufferType.Empty); decspc[2] = new SecurityBuffer(null, SecurityBufferType.Empty); decspc[3] = new SecurityBuffer(null, SecurityBufferType.Empty); Interop.SecurityStatus errorCode = (Interop.SecurityStatus)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.SecurityStatus.OK && decspc[i].type == SecurityBufferType.Data) // or we failed to decode the data, here is the encoded data. || (errorCode != Interop.SecurityStatus.OK && decspc[i].type == SecurityBufferType.Extra)) { offset = decspc[i].offset; count = decspc[i].size; break; } } return GetSecurityStatusPalFromInterop(errorCode); }
public static SecurityStatusPal EncryptMessage(SafeDeleteContext securityContext, byte[] writeBuffer, int size, int headerSize, int trailerSize, out int resultSize) { // Encryption using SCHANNEL requires 4 buffers: header, payload, trailer, empty. SecurityBuffer[] securityBuffer = new SecurityBuffer[4]; securityBuffer[0] = new SecurityBuffer(writeBuffer, 0, headerSize, SecurityBufferType.Header); securityBuffer[1] = new SecurityBuffer(writeBuffer, headerSize, size, SecurityBufferType.Data); securityBuffer[2] = new SecurityBuffer(writeBuffer, headerSize + size, trailerSize, SecurityBufferType.Trailer); securityBuffer[3] = new SecurityBuffer(null, SecurityBufferType.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 GetSecurityStatusPalFromWin32Int(errorCode); }
/// <summary> /// Generate SSPI context /// </summary> /// <param name="handle">SNI connection handle</param> /// <param name="receivedBuff">Receive buffer</param> /// <param name="receivedLength">Received length</param> /// <param name="sendBuff">Send buffer</param> /// <param name="sendLength">Send length</param> /// <param name="serverName">Service Principal Name buffer</param> /// <param name="serverNameLength">Length of Service Principal Name</param> /// <returns>SNI error code</returns> public void GenSspiClientContext(SspiClientContextStatus sspiClientContextStatus, byte[] receivedBuff, ref byte[] sendBuff, byte[] serverName) { SafeDeleteContext securityContext = sspiClientContextStatus.SecurityContext; ContextFlagsPal contextFlags = sspiClientContextStatus.ContextFlags; SafeFreeCredentials credentialsHandle = sspiClientContextStatus.CredentialsHandle; string securityPackage = NegotiationInfoClass.Negotiate; if (securityContext == null) { credentialsHandle = NegotiateStreamPal.AcquireDefaultCredential(securityPackage, false); } SecurityBuffer[] inSecurityBufferArray = null; if (receivedBuff != null) { inSecurityBufferArray = new SecurityBuffer[] { new SecurityBuffer(receivedBuff, SecurityBufferType.SECBUFFER_TOKEN) }; } else { inSecurityBufferArray = new SecurityBuffer[] { }; } int tokenSize = NegotiateStreamPal.QueryMaxTokenSize(securityPackage); SecurityBuffer outSecurityBuffer = new SecurityBuffer(tokenSize, SecurityBufferType.SECBUFFER_TOKEN); ContextFlagsPal requestedContextFlags = ContextFlagsPal.Connection | ContextFlagsPal.Confidentiality | ContextFlagsPal.MutualAuth; string serverSPN = System.Text.Encoding.UTF8.GetString(serverName); SecurityStatusPal statusCode = NegotiateStreamPal.InitializeSecurityContext( credentialsHandle, ref securityContext, serverSPN, requestedContextFlags, inSecurityBufferArray, outSecurityBuffer, ref contextFlags); if (statusCode.ErrorCode == SecurityStatusPalErrorCode.CompleteNeeded || statusCode.ErrorCode == SecurityStatusPalErrorCode.CompAndContinue) { inSecurityBufferArray = new SecurityBuffer[] { outSecurityBuffer }; statusCode = NegotiateStreamPal.CompleteAuthToken(ref securityContext, inSecurityBufferArray); outSecurityBuffer.token = null; } sendBuff = outSecurityBuffer.token; if (sendBuff == null) { sendBuff = Array.Empty <byte>(); } sspiClientContextStatus.SecurityContext = securityContext; sspiClientContextStatus.ContextFlags = contextFlags; sspiClientContextStatus.CredentialsHandle = credentialsHandle; if (IsErrorStatus(statusCode.ErrorCode)) { // Could not access Kerberos Ticket. // // SecurityStatusPalErrorCode.InternalError only occurs in Unix and always comes with a GssApiException, // so we don't need to check for a GssApiException here. if (statusCode.ErrorCode == SecurityStatusPalErrorCode.InternalError) { throw new Exception(SQLMessage.KerberosTicketMissingError() + "\n" + statusCode); } else { throw new Exception(SQLMessage.SSPIGenerateError() + "\n" + statusCode); } } }
/// <summary> /// Reads a sequence of bytes from the current stream. /// </summary> /// <param name="buffer">The buffer that contains decrypted data.</param> /// <param name="offset">The offset in buffer at which to begin storing the decrypted data.</param> /// <param name="count">The maximum number of bytes to get.</param> /// <exception cref="ArgumentOutOfRangeException">Raised when buffer or the internal decryptedBuffer doesn't /// contain enough space /// </exception> /// <exception cref="IOException">Raised when attempting to read from/write to a remote connection which /// has been closed</exception> /// <returns>The actual number of bytes read into the buffer. Could be less than count</returns> public override int Read(byte[] buffer, int offset, int count) { if (offset > buffer.Length - 1) { throw new ArgumentOutOfRangeException("offset"); } if (offset + count > buffer.Length) { throw new ArgumentOutOfRangeException("count"); } if (!IsBufferEmpty()) { if (CheckAvailableCount(count)) { Array.Copy(decryptedBuffer, this.startIndex, buffer, offset, count); this.startIndex += count; return(count); } else { int sizeRead = this.endIndex - this.startIndex; Array.Copy(decryptedBuffer, this.startIndex, buffer, offset, sizeRead); // All data is read, reset indices this.startIndex = 0; this.endIndex = 0; return(sizeRead); } } byte[] encryptedMsg = null; int bytesReceived = 0; byte[] decryptedMsg = null; while (decryptedMsg == null) { // decryptedMsg being null indicates incomplete data, so we continue reading and decrypting. bytesReceived = ReceivePacket(); // The connection has been closed by remote server if (bytesReceived == 0) { return(0); } // There's pooled data, concatenate the buffer together for decryption if (this.pooledBuffer != null && this.pooledBuffer.Length > 0) { encryptedMsg = new byte[this.pooledBuffer.Length + bytesReceived]; Array.Copy(this.pooledBuffer, encryptedMsg, this.pooledBuffer.Length); Array.Copy(recvBuffer, 0, encryptedMsg, this.pooledBuffer.Length, bytesReceived); this.pooledBuffer = null; } else { encryptedMsg = new byte[bytesReceived]; Array.Copy(recvBuffer, encryptedMsg, bytesReceived); } byte[] extraData = null; // Do decryption SecurityBuffer[] securityBuffers = new SecurityBuffer[] { new SecurityBuffer(SecurityBufferType.Data, encryptedMsg), new SecurityBuffer(SecurityBufferType.Empty, null), new SecurityBuffer(SecurityBufferType.Empty, null), new SecurityBuffer(SecurityBufferType.Empty, null) }; context.Decrypt(securityBuffers); for (int i = 0; i < securityBuffers.Length; i++) { if (securityBuffers[i].BufferType == SecurityBufferType.Data) { decryptedMsg = ArrayUtility.ConcatenateArrays(decryptedMsg, securityBuffers[i].Buffer); } else if (securityBuffers[i].BufferType == SecurityBufferType.Extra) { extraData = ArrayUtility.ConcatenateArrays(extraData, securityBuffers[i].Buffer); } } if (extraData != null && extraData.Length > 0) { this.pooledBuffer = extraData; } } Array.Copy(decryptedMsg, 0, this.decryptedBuffer, this.endIndex, decryptedMsg.Length); this.endIndex += decryptedMsg.Length; return(Read(buffer, offset, count)); }
public int AcceptSecurityContext(SafeFreeCredentials credential, ref SafeDeleteContext context, SecurityBuffer[] inputBuffers, Interop.SspiCli.ContextFlags inFlags, Interop.SspiCli.Endianness endianness, SecurityBuffer outputBuffer, ref Interop.SspiCli.ContextFlags outFlags) { return SafeDeleteContext.AcceptSecurityContext(ref credential, ref context, inFlags, endianness, null, inputBuffers, outputBuffer, ref outFlags); }
private unsafe static int EncryptDecryptHelper(OP op, SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber) { Interop.Secur32.SecurityBufferDescriptor sdcInOut = new Interop.Secur32.SecurityBufferDescriptor(input.Length); var unmanagedBuffer = new Interop.Secur32.SecurityBufferStruct[input.Length]; fixed (Interop.Secur32.SecurityBufferStruct* unmanagedBufferPtr = unmanagedBuffer) { sdcInOut.UnmanagedPointer = unmanagedBufferPtr; GCHandle[] pinnedBuffers = new GCHandle[input.Length]; byte[][] buffers = new byte[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; } } // The result is written in the input Buffer passed as type=BufferType.Data. int errorCode; switch (op) { case OP.Encrypt: errorCode = secModule.EncryptMessage(context, sdcInOut, sequenceNumber); break; case OP.Decrypt: errorCode = secModule.DecryptMessage(context, sdcInOut, sequenceNumber); break; case OP.MakeSignature: errorCode = secModule.MakeSignature(context, sdcInOut, sequenceNumber); break; case OP.VerifySignature: errorCode = secModule.VerifySignature(context, sdcInOut, sequenceNumber); break; default: GlobalLog.Assert("SSPIWrapper::EncryptDecryptHelper", "Unknown OP: " + op); throw NotImplemented.ByDesignWithMessage(SR.net_MethodNotImplementedException); } // Marshalling back returned sizes / data. 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 { 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) { GlobalLog.Assert("SSPIWrapper::EncryptDecryptHelper", "Output buffer out of range."); iBuffer.size = 0; iBuffer.offset = 0; iBuffer.token = null; } } } // Backup validate the new sizes. GlobalLog.Assert(iBuffer.offset >= 0 && iBuffer.offset <= (iBuffer.token == null ? 0 : iBuffer.token.Length), "SSPIWrapper::EncryptDecryptHelper|'offset' out of range. [{0}]", iBuffer.offset); GlobalLog.Assert(iBuffer.size >= 0 && iBuffer.size <= (iBuffer.token == null ? 0 : iBuffer.token.Length - iBuffer.offset), "SSPIWrapper::EncryptDecryptHelper|'size' out of range. [{0}]", iBuffer.size); } if (errorCode != 0 && NetEventSource.Log.IsEnabled()) { if (errorCode == Interop.Secur32.SEC_I_RENEGOTIATE) { NetEventSource.PrintError(NetEventSource.ComponentType.Security, SR.Format(SR.event_OperationReturnedSomething, op, "SEC_I_RENEGOTIATE")); } else { NetEventSource.PrintError(NetEventSource.ComponentType.Security, SR.Format(SR.net_log_operation_failed_with_error, op, String.Format(CultureInfo.CurrentCulture, "0X{0:X}", errorCode))); } } return errorCode; } finally { for (int i = 0; i < pinnedBuffers.Length; ++i) { if (pinnedBuffers[i].IsAllocated) { pinnedBuffers[i].Free(); } } } } }
internal static int CompleteAuthToken(SSPIInterface secModule, ref SafeDeleteContext context, SecurityBuffer[] inputBuffers) { int errorCode = secModule.CompleteAuthToken(ref context, inputBuffers); if (SecurityEventSource.Log.IsEnabled()) { SecurityEventSource.Log.OperationReturnedSomething("CompleteAuthToken()", (Interop.SecurityStatus)errorCode); } return errorCode; }
internal static int InitializeSecurityContext(SSPIInterface secModule, ref SafeFreeCredentials credential, ref SafeDeleteContext context, string targetName, Interop.Secur32.ContextFlags inFlags, Interop.Secur32.Endianness datarep, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, ref Interop.Secur32.ContextFlags outFlags) { if (SecurityEventSource.Log.IsEnabled()) { SecurityEventSource.Log.InitializeSecurityContext(credential.ToString(), LoggingHash.ObjectToString(context), targetName, inFlags); } int errorCode = secModule.InitializeSecurityContext(ref credential, ref context, targetName, inFlags, datarep, inputBuffer, outputBuffer, ref outFlags); if (SecurityEventSource.Log.IsEnabled()) { SecurityEventSource.Log.SecurityContextInputBuffer("InitializeSecurityContext", (inputBuffer == null ? 0 : inputBuffer.size), outputBuffer.size, (Interop.SecurityStatus)errorCode); } return errorCode; }
public static SecurityStatusPal InitializeSecurityContext(ref SafeFreeCredentials credential, ref SafeDeleteContext context, string targetName, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer) { return HandshakeInternal(credential, ref context, inputBuffer, outputBuffer, false, false); }
internal static int InitializeSecurityContext(SSPIInterface secModule, ref SafeFreeCredentials credential, ref SafeDeleteContext context, string targetName, Interop.SspiCli.ContextFlags inFlags, Interop.SspiCli.Endianness datarep, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, ref Interop.SspiCli.ContextFlags outFlags) { if (NetEventSource.IsEnabled) NetEventSource.Log.InitializeSecurityContext(credential, context, targetName, inFlags); int errorCode = secModule.InitializeSecurityContext(ref credential, ref context, targetName, inFlags, datarep, inputBuffer, outputBuffer, ref outFlags); if (NetEventSource.IsEnabled) NetEventSource.Log.SecurityContextInputBuffer(nameof(InitializeSecurityContext), inputBuffer?.size ?? 0, outputBuffer.size, (Interop.SECURITY_STATUS)errorCode); return errorCode; }
public static SecurityStatusPal AcceptSecurityContext(ref SafeFreeCredentials credential, ref SafeDeleteContext context, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, bool remoteCertRequired) { return HandshakeInternal(credential, ref context, inputBuffer, outputBuffer, true, remoteCertRequired); }
internal static int ApplyControlToken(SSPIInterface secModule, ref SafeDeleteContext context, SecurityBuffer[] inputBuffers) { int errorCode = secModule.ApplyControlToken(ref context, inputBuffers); if (NetEventSource.IsEnabled) NetEventSource.Log.OperationReturnedSomething(nameof(ApplyControlToken), (Interop.SECURITY_STATUS)errorCode); return errorCode; }
public static SecurityStatusPal InitializeSecurityContext(SafeFreeCredentials credential, ref SafeDeleteContext context, string targetName, SecurityBuffer[] inputBuffers, SecurityBuffer outputBuffer) { Debug.Assert(inputBuffers.Length == 2); Debug.Assert(inputBuffers[1].token == null); return HandshakeInternal(credential, ref context, inputBuffers[0], outputBuffer, false, false); }
private unsafe static int EncryptDecryptHelper(OP op, SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber) { Interop.SspiCli.SecBufferDesc sdcInOut = new Interop.SspiCli.SecBufferDesc(input.Length); var unmanagedBuffer = new Interop.SspiCli.SecBuffer[input.Length]; fixed (Interop.SspiCli.SecBuffer* unmanagedBufferPtr = unmanagedBuffer) { sdcInOut.pBuffers = unmanagedBufferPtr; GCHandle[] pinnedBuffers = new GCHandle[input.Length]; byte[][] buffers = new byte[input.Length][]; try { for (int i = 0; i < input.Length; i++) { SecurityBuffer iBuffer = input[i]; unmanagedBuffer[i].cbBuffer = iBuffer.size; unmanagedBuffer[i].BufferType = iBuffer.type; if (iBuffer.token == null || iBuffer.token.Length == 0) { unmanagedBuffer[i].pvBuffer = IntPtr.Zero; } else { pinnedBuffers[i] = GCHandle.Alloc(iBuffer.token, GCHandleType.Pinned); unmanagedBuffer[i].pvBuffer = Marshal.UnsafeAddrOfPinnedArrayElement(iBuffer.token, iBuffer.offset); buffers[i] = iBuffer.token; } } // The result is written in the input Buffer passed as type=BufferType.Data. int errorCode; switch (op) { case OP.Encrypt: errorCode = secModule.EncryptMessage(context, sdcInOut, sequenceNumber); break; case OP.Decrypt: errorCode = secModule.DecryptMessage(context, sdcInOut, sequenceNumber); break; case OP.MakeSignature: errorCode = secModule.MakeSignature(context, sdcInOut, sequenceNumber); break; case OP.VerifySignature: errorCode = secModule.VerifySignature(context, sdcInOut, sequenceNumber); break; default: NetEventSource.Fail(null, $"Unknown OP: {op}"); throw NotImplemented.ByDesignWithMessage(SR.net_MethodNotImplementedException); } // Marshalling back returned sizes / data. for (int i = 0; i < input.Length; i++) { SecurityBuffer iBuffer = input[i]; iBuffer.size = unmanagedBuffer[i].cbBuffer; iBuffer.type = unmanagedBuffer[i].BufferType; if (iBuffer.size == 0) { iBuffer.offset = 0; iBuffer.token = null; } 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].pvBuffer >= bufferAddress && (byte*)unmanagedBuffer[i].pvBuffer + iBuffer.size <= bufferAddress + buffers[j].Length) { iBuffer.offset = (int)((byte*)unmanagedBuffer[i].pvBuffer - bufferAddress); iBuffer.token = buffers[j]; break; } } if (j >= input.Length) { NetEventSource.Fail(null, "Output buffer out of range."); iBuffer.size = 0; iBuffer.offset = 0; iBuffer.token = null; } } } // Backup validate the new sizes. if (iBuffer.offset < 0 || iBuffer.offset > (iBuffer.token == null ? 0 : iBuffer.token.Length)) { NetEventSource.Fail(null, $"'offset' out of range. [{iBuffer.offset}]"); } if (iBuffer.size < 0 || iBuffer.size > (iBuffer.token == null ? 0 : iBuffer.token.Length - iBuffer.offset)) { NetEventSource.Fail(null, $"'size' out of range. [{iBuffer.size}]"); } } if (NetEventSource.IsEnabled && errorCode != 0) { if (errorCode == Interop.SspiCli.SEC_I_RENEGOTIATE) { NetEventSource.Error(null, SR.Format(SR.event_OperationReturnedSomething, op, "SEC_I_RENEGOTIATE")); } else { NetEventSource.Error(null, SR.Format(SR.net_log_operation_failed_with_error, op, $"0x{0:X}")); } } return errorCode; } finally { for (int i = 0; i < pinnedBuffers.Length; ++i) { if (pinnedBuffers[i].IsAllocated) { pinnedBuffers[i].Free(); } } } } }
internal static int AcceptSecurityContext(SSPIInterface secModule, SafeFreeCredentials credential, ref SafeDeleteContext context, Interop.Secur32.ContextFlags inFlags, Interop.Secur32.Endianness datarep, SecurityBuffer[] inputBuffers, SecurityBuffer outputBuffer, ref Interop.Secur32.ContextFlags outFlags) { if (SecurityEventSource.Log.IsEnabled()) { SecurityEventSource.Log.AcceptSecurityContext(credential.ToString(), LoggingHash.ObjectToString(context), inFlags); } int errorCode = secModule.AcceptSecurityContext(credential, ref context, inputBuffers, inFlags, datarep, outputBuffer, ref outFlags); if (SecurityEventSource.Log.IsEnabled()) { SecurityEventSource.Log.SecurityContextInputBuffers("AcceptSecurityContext", (inputBuffers == null ? 0 : inputBuffers.Length), outputBuffer.size, (Interop.SecurityStatus)errorCode); } return errorCode; }
public byte[] Decrypt(byte[] encryptedContent) { if (encryptedContent == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("encryptedContent"); ThrowIfDisposed(); SecurityBuffer[] securityBuffer = new SecurityBuffer[2]; securityBuffer[0] = new SecurityBuffer(encryptedContent, 0, encryptedContent.Length, BufferType.Stream); securityBuffer[1] = new SecurityBuffer(0, BufferType.Data); int errorCode = SspiWrapper.DecryptMessage(this.securityContext, securityBuffer, 0, true); if (errorCode != 0) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(errorCode)); } for (int i = 0; i < securityBuffer.Length; ++i) { if (securityBuffer[i].type == BufferType.Data) { return securityBuffer[i].token; } } OnBadData(); return null; }
public static int VerifySignature(SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber) { return EncryptDecryptHelper(OP.VerifySignature, secModule, context, input, sequenceNumber); }
public byte[] Encrypt(byte[] input) { if (input == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("input"); ThrowIfDisposed(); SecurityBuffer[] securityBuffer = new SecurityBuffer[3]; byte[] tokenBuffer = DiagnosticUtility.Utility.AllocateByteArray(SecuritySizes.SecurityTrailer); securityBuffer[0] = new SecurityBuffer(tokenBuffer, 0, tokenBuffer.Length, BufferType.Token); byte[] dataBuffer = DiagnosticUtility.Utility.AllocateByteArray(input.Length); Buffer.BlockCopy(input, 0, dataBuffer, 0, input.Length); securityBuffer[1] = new SecurityBuffer(dataBuffer, 0, dataBuffer.Length, BufferType.Data); byte[] paddingBuffer = DiagnosticUtility.Utility.AllocateByteArray(SecuritySizes.BlockSize); securityBuffer[2] = new SecurityBuffer(paddingBuffer, 0, paddingBuffer.Length, BufferType.Padding); int errorCode = SspiWrapper.EncryptMessage(this.securityContext, securityBuffer, 0); if (errorCode != 0) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(errorCode)); } int tokenLen = 0; int paddingLen = 0; for (int i = 0; i < securityBuffer.Length; ++i) { if (securityBuffer[i].type == BufferType.Token) tokenLen = securityBuffer[i].size; else if (securityBuffer[i].type == BufferType.Padding) paddingLen = securityBuffer[i].size; } byte[] encryptedData = DiagnosticUtility.Utility.AllocateByteArray(checked(tokenLen + dataBuffer.Length + paddingLen)); Buffer.BlockCopy(tokenBuffer, 0, encryptedData, 0, tokenLen); Buffer.BlockCopy(dataBuffer, 0, encryptedData, tokenLen, dataBuffer.Length); Buffer.BlockCopy(paddingBuffer, 0, encryptedData, tokenLen + dataBuffer.Length, paddingLen); return encryptedData; }
public int CompleteAuthToken(ref SafeDeleteContext refContext, SecurityBuffer[] inputBuffers) { return SafeDeleteContext.CompleteAuthToken(ref refContext, inputBuffers); }
public byte[] GetOutgoingBlob(byte[] incomingBlob, ChannelBinding channelbinding, ExtendedProtectionPolicy protectionPolicy) { ThrowIfDisposed(); int statusCode = 0; // use the confidentiality option to ensure we can encrypt messages SspiContextFlags requestedFlags = SspiContextFlags.Confidentiality | SspiContextFlags.ReplayDetect | SspiContextFlags.SequenceDetect; if (this.doMutualAuth) { requestedFlags |= SspiContextFlags.MutualAuth; } if (this.impersonationLevel == TokenImpersonationLevel.Delegation) { requestedFlags |= SspiContextFlags.Delegate; } else if (this.isServer == false && this.impersonationLevel == TokenImpersonationLevel.Identification) { requestedFlags |= SspiContextFlags.InitIdentify; } else if (this.isServer == false && this.impersonationLevel == TokenImpersonationLevel.Anonymous) { requestedFlags |= SspiContextFlags.InitAnonymous; } ExtendedProtectionPolicyHelper policyHelper = new ExtendedProtectionPolicyHelper(channelbinding, protectionPolicy); if (isServer) { if (policyHelper.PolicyEnforcement == PolicyEnforcement.Always && policyHelper.ChannelBinding == null && policyHelper.ProtectionScenario != ProtectionScenario.TrustedProxy) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.SecurityChannelBindingMissing))); } if (policyHelper.PolicyEnforcement == PolicyEnforcement.WhenSupported) { requestedFlags |= SspiContextFlags.ChannelBindingAllowMissingBindings; } if (policyHelper.ProtectionScenario == ProtectionScenario.TrustedProxy) { requestedFlags |= SspiContextFlags.ChannelBindingProxyBindings; } } List<SecurityBuffer> list = new List<SecurityBuffer>(2); if (incomingBlob != null) { list.Add(new SecurityBuffer(incomingBlob, BufferType.Token)); } // when deciding if the channel binding should be added to the security buffer // it is necessary to differentiate between client and server. // Server rules were added to policyHelper as they are shared with Kerb and I want them consistent // Client adds if not null. if (this.isServer) { if (policyHelper.ShouldAddChannelBindingToASC()) { list.Add(new SecurityBuffer(policyHelper.ChannelBinding)); } } else { if (policyHelper.ChannelBinding != null) { list.Add(new SecurityBuffer(policyHelper.ChannelBinding)); } } SecurityBuffer[] inSecurityBuffer = null; if (list.Count > 0) { inSecurityBuffer = list.ToArray(); } SecurityBuffer outSecurityBuffer = new SecurityBuffer(this.tokenSize, BufferType.Token); if (!this.isServer) { //client session statusCode = SspiWrapper.InitializeSecurityContext(this.credentialsHandle, ref this.securityContext, this.servicePrincipalName, requestedFlags, Endianness.Network, inSecurityBuffer, outSecurityBuffer, ref this.contextFlags); } else { // server session //This check is to save an unnecessary ASC call. bool isServerSecurityContextNull = this.securityContext == null; SspiContextFlags serverContextFlags = this.contextFlags; statusCode = SspiWrapper.AcceptSecurityContext(this.credentialsHandle, ref this.securityContext, requestedFlags, Endianness.Network, inSecurityBuffer, outSecurityBuffer, ref this.contextFlags); if (statusCode == (int)SecurityStatus.InvalidToken && !isServerSecurityContextNull) { // Call again into ASC after deleting the Securitycontext. If this securitycontext is not deleted // then when the client sends NTLM blob the service will treat it as Nego2blob and will fail to authenticate the client. this.contextFlags = serverContextFlags; CloseContext(); statusCode = SspiWrapper.AcceptSecurityContext(this.credentialsHandle, ref this.securityContext, requestedFlags, Endianness.Network, inSecurityBuffer, outSecurityBuffer, ref this.contextFlags); } } if (DiagnosticUtility.ShouldTraceInformation) { IMD.SecurityTraceRecordHelper.TraceChannelBindingInformation(policyHelper, this.isServer, channelbinding); } if ((statusCode & unchecked((int)0x80000000)) != 0) { if (!this.isServer && this.interactiveNegoLogonEnabled && SecurityUtils.IsOSGreaterThanOrEqualToWin7() && SspiWrapper.IsSspiPromptingNeeded((uint)statusCode) && SspiWrapper.IsNegotiateExPackagePresent()) { // If we have prompted enough number of times (DefaultMaxPromptAttempts) with wrong credentials, then we do not prompt again and throw. if (MaxPromptAttempts >= DefaultMaxPromptAttempts) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(statusCode, SR.GetString(SR.InvalidClientCredentials))); } IntPtr ppAuthIdentity = IntPtr.Zero; uint errorCode = SspiWrapper.SspiPromptForCredential(this.servicePrincipalName, this.clientPackageName, out ppAuthIdentity, ref this.saveClientCredentialsOnSspiUi); if (errorCode == (uint)CredentialStatus.Success) { IntPtr ppNewAuthIdentity = IntPtr.Zero; if (!this.allowNtlm) { // When Ntlm is explicitly disabled we don't want the collected //creds from the Kerb/NTLM tile to be used for NTLM auth. uint status = UnsafeNativeMethods.SspiExcludePackage(ppAuthIdentity, "NTLM", out ppNewAuthIdentity); } else { ppNewAuthIdentity = ppAuthIdentity; } this.credentialsHandle = SspiWrapper.AcquireCredentialsHandle(this.clientPackageName, CredentialUse.Outbound, ref ppNewAuthIdentity); if (IntPtr.Zero != ppNewAuthIdentity) { UnsafeNativeMethods.SspiFreeAuthIdentity(ppNewAuthIdentity); } CloseContext(); MaxPromptAttempts++; return this.GetOutgoingBlob(null, channelbinding, protectionPolicy); } else { // Call into SspiPromptForCredential had an error. Time to throw. if (IntPtr.Zero != ppAuthIdentity) { UnsafeNativeMethods.SspiFreeAuthIdentity(ppAuthIdentity); } CloseContext(); this.isCompleted = true; throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception((int)errorCode, SR.GetString(SR.SspiErrorOrInvalidClientCredentials))); } } CloseContext(); this.isCompleted = true; if (!this.isServer && (statusCode == (int)SecurityStatus.TargetUnknown || statusCode == (int)SecurityStatus.WrongPrincipal)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(statusCode, SR.GetString(SR.IncorrectSpnOrUpnSpecified, this.servicePrincipalName))); } else { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(statusCode, SR.GetString(SR.InvalidSspiNegotiation))); } } if (DiagnosticUtility.ShouldTraceInformation) { if (this.isServer) { SecurityTraceRecordHelper.TraceServiceOutgoingSpnego(this); } else { SecurityTraceRecordHelper.TraceClientOutgoingSpnego(this); } } if (statusCode == (int)SecurityStatus.OK) { // we're done this.isCompleted = true; // These must all be true to check service binding // 1. we are the service (listener) // 2. caller is not anonymous // 3. protocol is not Kerberos // 4. policy is set to check service binding // if (isServer && ((this.contextFlags & SspiContextFlags.AcceptAnonymous) == 0) && (string.Compare(this.ProtocolName, NegotiationInfoClass.Kerberos, StringComparison.OrdinalIgnoreCase) != 0) && policyHelper.ShouldCheckServiceBinding) { // in the server case the servicePrincipalName is the defaultServiceBinding if (DiagnosticUtility.ShouldTraceInformation) { string serviceBindingNameSentByClient; SspiWrapper.QuerySpecifiedTarget(securityContext, out serviceBindingNameSentByClient); IMD.SecurityTraceRecordHelper.TraceServiceNameBindingOnServer( serviceBindingNameSentByClient, this.servicePrincipalName, policyHelper.ServiceNameCollection); } policyHelper.CheckServiceBinding(this.securityContext, this.servicePrincipalName); } } else { // we need to continue } return outSecurityBuffer.token; }
public int InitializeSecurityContext(SafeFreeCredentials credential, ref SafeDeleteContext context, string targetName, Interop.SspiCli.ContextFlags inFlags, Interop.SspiCli.Endianness endianness, SecurityBuffer[] inputBuffers, SecurityBuffer outputBuffer, ref Interop.SspiCli.ContextFlags outFlags) { return SafeDeleteContext.InitializeSecurityContext(ref credential, ref context, targetName, inFlags, endianness, null, inputBuffers, outputBuffer, ref outFlags); }
internal NtlmSspPacket(Frame parentFrame, int packetStartIndex, int packetEndIndex) : base(parentFrame, packetStartIndex, packetEndIndex, "NTLMSSP") { this.domainName = null; this.userName = null; this.hostName = null; this.lanManagerResponse = null; this.ntlmResponse = null; int packetIndex = packetStartIndex; //0x4e544c4d53535000 = "NTLMSSP" if (Utils.ByteConverter.ReadNullTerminatedString(parentFrame.Data, ref packetIndex) != "NTLMSSP") { throw new Exception("Expected NTLMSSP signature string missing!"); } uint messageType = Utils.ByteConverter.ToUInt32(parentFrame.Data, packetIndex); //message type is normally 0x00000001 = Negotiate packetIndex += 4; if (messageType == (uint)NtlmMessageTypes.Negotiate) { /* * Description Content * 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" (0x4e544c4d53535000) * 8 NTLM Message Type long (0x01000000) * 12 Flags long * (16) Supplied Domain (Optional) security buffer * (24) Supplied Workstation (Optional) security buffer * (32) OS Version Structure (Optional) 8 bytes * (32) (40) start of data block (if required) */ } else if (messageType == (uint)NtlmMessageTypes.Challenge) { // Description Content //0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" (0x4e544c4d53535000) //8 NTLM Message Type long (0x02000000) //12 Target Name security buffer //20 Flags long //24 Challenge 8 bytes //(32) Context (optional) 8 bytes (two consecutive longs) //(40) Target Information (optional) security buffer //(48) OS Version Structure (Optional) 8 bytes //32 (48) (56) start of data block bool dataIsUnicode = false; SecurityBuffer domainNameSecurityBuffer = new SecurityBuffer(parentFrame.Data, ref packetIndex); //see if we have unicode data if (domainNameSecurityBuffer.length > 0) { dataIsUnicode = (parentFrame.Data[packetStartIndex + domainNameSecurityBuffer.offset + domainNameSecurityBuffer.length - 1] == (byte)0x00); } packetIndex += 4;//skip flags this.ntlmChallenge = Utils.ByteConverter.ReadHexString(parentFrame.Data, 8, packetIndex); if (!this.ParentFrame.QuickParse) { this.Attributes.Add("NTLM Challenge", this.ntlmChallenge); } if (domainNameSecurityBuffer.length > 0) { packetIndex = packetStartIndex + (int)domainNameSecurityBuffer.offset; this.domainName = Utils.ByteConverter.ReadString(parentFrame.Data, ref packetIndex, domainNameSecurityBuffer.length, dataIsUnicode, true); if (!this.ParentFrame.QuickParse) { this.Attributes.Add("Domain Name", this.domainName); } } } else if (messageType == (uint)NtlmMessageTypes.Authentication) { // Description Content //0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" (0x4e544c4d53535000) //8 NTLM Message Type long (0x03000000) //12 LM/LMv2 Response security buffer //20 NTLM/NTLMv2 Response security buffer //28 Target Name security buffer //36 User Name security buffer //44 Workstation Name security buffer //(52) Session Key (optional) security buffer //(60) Flags (optional) long //(64) OS Version Structure (Optional) 8 bytes //52 (64) (72) start of data block bool dataIsUnicode = false; SecurityBuffer lanManagerSecurityBuffer = new SecurityBuffer(parentFrame.Data, ref packetIndex); SecurityBuffer ntLanManagerSecurityBuffer = new SecurityBuffer(parentFrame.Data, ref packetIndex); SecurityBuffer domainNameSecurityBuffer = new SecurityBuffer(parentFrame.Data, ref packetIndex); SecurityBuffer userNameSecurityBuffer = new SecurityBuffer(parentFrame.Data, ref packetIndex); SecurityBuffer workstationNameSecurityBuffer = new SecurityBuffer(parentFrame.Data, ref packetIndex); SecurityBuffer sessionKeySecurityBuffer = new SecurityBuffer(parentFrame.Data, ref packetIndex); //see if we have unicode data if (domainNameSecurityBuffer.length > 0) { dataIsUnicode = (parentFrame.Data[packetStartIndex + domainNameSecurityBuffer.offset + domainNameSecurityBuffer.length - 1] == (byte)0x00); } else if (userNameSecurityBuffer.length > 0) { dataIsUnicode = (parentFrame.Data[packetStartIndex + userNameSecurityBuffer.offset + userNameSecurityBuffer.length - 1] == (byte)0x00); } else if (workstationNameSecurityBuffer.length > 0) { dataIsUnicode = (parentFrame.Data[packetStartIndex + workstationNameSecurityBuffer.offset + workstationNameSecurityBuffer.length - 1] == (byte)0x00); } //extract the data if (lanManagerSecurityBuffer.length > 0) { byte[] bufferData = lanManagerSecurityBuffer.GetBufferData(parentFrame.Data, packetStartIndex); this.lanManagerResponse = Utils.ByteConverter.ReadHexString(bufferData, bufferData.Length); if (!this.ParentFrame.QuickParse) { this.Attributes.Add("LAN Manager Response", this.lanManagerResponse); } } if (ntLanManagerSecurityBuffer.length > 0) { byte[] bufferData = ntLanManagerSecurityBuffer.GetBufferData(parentFrame.Data, PacketStartIndex); this.ntlmResponse = Utils.ByteConverter.ReadHexString(bufferData, bufferData.Length); if (!this.ParentFrame.QuickParse) { this.Attributes.Add("NTLM Response", this.ntlmResponse); } } if (domainNameSecurityBuffer.length > 0) { packetIndex = packetStartIndex + (int)domainNameSecurityBuffer.offset; this.domainName = Utils.ByteConverter.ReadString(parentFrame.Data, ref packetIndex, domainNameSecurityBuffer.length, dataIsUnicode, true); if (!this.ParentFrame.QuickParse) { this.Attributes.Add("Domain Name", this.domainName); } } if (userNameSecurityBuffer.length > 0) { packetIndex = packetStartIndex + (int)userNameSecurityBuffer.offset; this.userName = Utils.ByteConverter.ReadString(parentFrame.Data, ref packetIndex, userNameSecurityBuffer.length, dataIsUnicode, true); if (!this.ParentFrame.QuickParse) { this.Attributes.Add("User Name", this.userName); } } if (workstationNameSecurityBuffer.length > 0) { packetIndex = packetStartIndex + (int)workstationNameSecurityBuffer.offset; this.hostName = Utils.ByteConverter.ReadString(parentFrame.Data, ref packetIndex, workstationNameSecurityBuffer.length, dataIsUnicode, true); if (!this.ParentFrame.QuickParse) { this.Attributes.Add("Host Name", this.hostName); } } } }