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);
 }
Exemple #4
0
 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);
 }
Exemple #5
0
 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
                                 );
 }
Exemple #6
0
        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);
        }
Exemple #9
0
        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;
        }
Exemple #10
0
        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;             
            }
        }
Exemple #11
0
        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);
        }
Exemple #14
0
        /// <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);
                }
            }
        }
Exemple #15
0
        /// <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));
        }
Exemple #16
0
 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);
 }
Exemple #17
0
        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();
                        }
                    }
                }
            }
        }
Exemple #18
0
        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;
        }
Exemple #19
0
        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;
        }
Exemple #20
0
 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);
 }
Exemple #21
0
        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;
        }
Exemple #22
0
 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);
 }
Exemple #23
0
        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;
        }
Exemple #24
0
 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);
 }
Exemple #25
0
        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();
                        }
                    }
                }
            }
        }
Exemple #26
0
        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;
        }
Exemple #28
0
 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;
        }
Exemple #30
0
 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;
        }
Exemple #32
0
 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);
                    }
                }
            }
        }