Ejemplo n.º 1
0
        void Decode(byte[] message, int startIndex, int length)
        {
            ValidateArguments(message, startIndex, length);

            Flags = (NtlmFlags)BitConverterLE.ToUInt32(message, startIndex + 20);

            Buffer.BlockCopy(message, startIndex + 24, serverChallenge, 0, 8);

            var targetNameLength = BitConverterLE.ToUInt16(message, startIndex + 12);
            var targetNameOffset = BitConverterLE.ToUInt16(message, startIndex + 16);

            if (targetNameLength > 0)
            {
                var encoding = (Flags & NtlmFlags.NegotiateUnicode) != 0 ? Encoding.Unicode : Encoding.UTF8;

                TargetName = encoding.GetString(message, startIndex + targetNameOffset, targetNameLength);
            }

            if ((Flags & NtlmFlags.NegotiateVersion) != 0 && length >= 56)
            {
                // decode the OS Version
                int major = message[startIndex + 48];
                int minor = message[startIndex + 49];
                int build = BitConverterLE.ToUInt16(message, startIndex + 50);

                OSVersion = new Version(major, minor, build);
            }

            // The Target Info block is optional.
            if (length >= 48 && targetNameOffset >= 48)
            {
                var targetInfoLength = BitConverterLE.ToUInt16(message, startIndex + 40);
                var targetInfoOffset = BitConverterLE.ToUInt16(message, startIndex + 44);

                if (targetInfoLength > 0 && targetInfoOffset < length && targetInfoLength <= (length - targetInfoOffset))
                {
                    TargetInfo = new NtlmTargetInfo(message, startIndex + targetInfoOffset, targetInfoLength, (Flags & NtlmFlags.NegotiateUnicode) != 0);
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Copy the attribute value pairs to another TargetInfo.
        /// </summary>
        /// <remarks>
        /// Copies the attribute value pairs to another TargetInfo.
        /// </remarks>
        public void CopyTo(NtlmTargetInfo targetInfo)
        {
            targetInfo.attributes.Clear();

            foreach (var attribute in attributes)
            {
                if (attribute is NtlmAttributeTimestampValuePair timestamp)
                {
                    targetInfo.attributes.Add(new NtlmAttributeTimestampValuePair(timestamp.Attribute, timestamp.Value, timestamp.Size));
                }
                else if (attribute is NtlmAttributeFlagsValuePair flags)
                {
                    targetInfo.attributes.Add(new NtlmAttributeFlagsValuePair(flags.Attribute, flags.Value, flags.Size));
                }
                else if (attribute is NtlmAttributeByteArrayValuePair array)
                {
                    targetInfo.attributes.Add(new NtlmAttributeByteArrayValuePair(array.Attribute, array.Value));
                }
                else if (attribute is NtlmAttributeStringValuePair str)
                {
                    targetInfo.attributes.Add(new NtlmAttributeStringValuePair(str.Attribute, str.Value));
                }
            }
        }
Ejemplo n.º 3
0
        public void ComputeNtlmV2(string targetName, bool unverifiedTargetName, byte[] channelBinding)
        {
            var targetInfo = new NtlmTargetInfo();
            int avFlags    = 0;

            // If the CHALLENGE_MESSAGE contains a TargetInfo field
            if (challenge.TargetInfo != null)
            {
                challenge.TargetInfo.CopyTo(targetInfo);

                if (targetInfo.Flags.HasValue)
                {
                    avFlags = targetInfo.Flags.Value;
                }

                // If the CHALLENGE_MESSAGE TargetInfo field (section 2.2.1.2) has an MsvAvTimestamp present, the client SHOULD provide a MIC.
                if (challenge.TargetInfo?.Timestamp != null)
                {
                    // If there is an AV_PAIR structure (section 2.2.2.1) with the AvId field set to MsvAvFlags, then in the Value field, set bit 0x2 to 1.
                    // Else add an AV_PAIR structure and set the AvId field to MsvAvFlags and the Value field bit 0x2 to 1.
                    targetInfo.Flags = avFlags |= 0x2;

                    // Temporarily set the MIC to Z16.
                    Mic = Z16;
                }

                // If ClientSuppliedTargetName (section 3.1.1.2) is not NULL
                if (targetName != null)
                {
                    // If UnverifiedTargetName (section 3.1.1.2) is TRUE, then in AvId field = MsvAvFlags set 0x00000004 bit.
                    if (unverifiedTargetName)
                    {
                        targetInfo.Flags = avFlags |= 0x4;
                    }

                    // Add an AV_PAIR structure and set the AvId field to MsvAvTargetName and the Value field to ClientSuppliedTargetName without
                    // terminating NULL.
                    targetInfo.TargetName = targetName;
                }
                else
                {
                    // Else add an AV_PAIR structure and set the AvId field to MsvAvTargetName and the Value field to an empty string without terminating NULL.
                    targetInfo.TargetName = string.Empty;
                }

                // The client SHOULD send the channel binding AV_PAIR:
                // If the ClientChannelBindingsUnhashed (section 3.1.1.2) is not NULL
                if (channelBinding != null)
                {
                    // Add an AV_PAIR structure and set the AvId field to MsvAvChannelBindings and the Value field to MD5_HASH(ClientChannelBindingsUnhashed).
                    targetInfo.ChannelBinding = NtlmUtils.MD5(channelBinding);
                }
                else
                {
                    // Else add an AV_PAIR structure and set the AvId field to MsvAvChannelBindings and the Value field to Z(16).
                    targetInfo.ChannelBinding = Z16;
                }
            }

            var encodedTargetInfo = targetInfo.Encode((Flags & NtlmFlags.NegotiateUnicode) != 0);

            // Note: For NTLMv2, the sessionBaseKey is the same as the keyExchangeKey.
            NtlmUtils.ComputeNtlmV2(challenge, Domain, UserName, Password, encodedTargetInfo, clientChallenge, Timestamp, out var ntChallengeResponse, out var lmChallengeResponse, out var keyExchangeKey);

            NtChallengeResponse = ntChallengeResponse;
            LmChallengeResponse = lmChallengeResponse;

            if ((Flags & NtlmFlags.NegotiateKeyExchange) != 0 && (Flags & (NtlmFlags.NegotiateSign | NtlmFlags.NegotiateSeal)) != 0)
            {
                ExportedSessionKey        = NtlmUtils.NONCE(16);
                EncryptedRandomSessionKey = NtlmUtils.RC4K(keyExchangeKey, ExportedSessionKey);
            }
            else
            {
                ExportedSessionKey        = keyExchangeKey;
                EncryptedRandomSessionKey = null;
            }

            // If the CHALLENGE_MESSAGE TargetInfo field (section 2.2.1.2) has an MsvAvTimestamp present, the client SHOULD provide a MIC.
            if ((avFlags & 0x2) != 0)
            {
                Mic = NtlmUtils.HMACMD5(ExportedSessionKey, NtlmUtils.ConcatenationOf(negotiate.Encode(), challenge.Encode(), Encode()));
            }
        }