示例#1
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()));
            }
        }
示例#2
0
        public NtlmAuthenticateMessage(NtlmNegotiateMessage negotiate, NtlmChallengeMessage challenge, string userName, string password, string domain, string workstation) : base(3)
        {
            if (negotiate == null)
            {
                throw new ArgumentNullException(nameof(negotiate));
            }

            if (challenge == null)
            {
                throw new ArgumentNullException(nameof(challenge));
            }

            if (userName == null)
            {
                throw new ArgumentNullException(nameof(userName));
            }

            if (password == null)
            {
                throw new ArgumentNullException(nameof(password));
            }

            clientChallenge = NtlmUtils.NONCE(8);
            this.negotiate  = negotiate;
            this.challenge  = challenge;

            if (!string.IsNullOrEmpty(domain))
            {
                Domain = domain;
            }
            else if ((challenge.Flags & NtlmFlags.TargetTypeDomain) != 0)
            {
                // The server is domain-joined, so the TargetName will be the domain.
                Domain = challenge.TargetName;
            }
            else if (challenge.TargetInfo != null)
            {
                // The server is not domain-joined, so the TargetName will be the machine name of the server.
                Domain = challenge.TargetInfo.DomainName;
            }

            Workstation = workstation;
            UserName    = userName;
            Password    = password;

            // Use only the features supported by both the client and server.
            Flags = negotiate.Flags & challenge.Flags;

            // If the client and server both support NEGOTIATE_UNICODE, disable NEGOTIATE_OEM.
            if ((Flags & NtlmFlags.NegotiateUnicode) != 0)
            {
                Flags &= ~NtlmFlags.NegotiateOem;
            }
            // TODO: throw if Unicode && Oem are both unset?

            // If the client and server both support NEGOTIATE_EXTENDED_SESSIONSECURITY, disable NEGOTIATE_LM_KEY.
            if ((Flags & NtlmFlags.NegotiateExtendedSessionSecurity) != 0)
            {
                Flags &= ~NtlmFlags.NegotiateLanManagerKey;
            }

            // Disable NEGOTIATE_KEY_EXCHANGE if neither NEGOTIATE_SIGN nor NEGOTIATE_SEAL are also present.
            if ((Flags & NtlmFlags.NegotiateKeyExchange) != 0 && (Flags & (NtlmFlags.NegotiateSign | NtlmFlags.NegotiateSeal)) == 0)
            {
                Flags &= ~NtlmFlags.NegotiateKeyExchange;
            }

            // If we had RequestTarget in our initial NEGOTIATE_MESSAGE, include it again in this message(?)
            if ((negotiate.Flags & NtlmFlags.RequestTarget) != 0)
            {
                Flags |= NtlmFlags.RequestTarget;
            }

            // If NEGOTIATE_VERSION is set, grab the OSVersion from our original negotiate message.
            if ((Flags & NtlmFlags.NegotiateVersion) != 0)
            {
                OSVersion = negotiate.OSVersion ?? OSVersion;
            }
        }
示例#3
0
 public NtlmChallengeMessage(NtlmFlags flags, Version osVersion = null) : base(2)
 {
     serverChallenge = NtlmUtils.NONCE(8);
     OSVersion       = osVersion;
     Flags           = flags;
 }