예제 #1
0
        public static void ComputeNtlmV2(NtlmChallengeMessage type2, string domain, string userName, string password, byte[] targetInfo, byte[] clientChallenge, long?time, out byte[] ntChallengeResponse, out byte[] lmChallengeResponse, out byte[] sessionBaseKey)
        {
            if (userName.Length == 0 && password.Length == 0)
            {
                // Special case for anonymous authentication
                ntChallengeResponse = null;
                lmChallengeResponse = Z1;
                sessionBaseKey      = null;
                return;
            }

            var timestamp   = (time ?? DateTime.UtcNow.Ticks) - 504911232000000000;
            var responseKey = NTOWFv2(domain, userName, password);

            // Note: If NTLM v2 authentication is used, the client SHOULD send the timestamp in the CHALLENGE_MESSAGE.
            if (type2.TargetInfo?.Timestamp != null)
            {
                timestamp = type2.TargetInfo.Timestamp.Value;
            }

            var temp  = ConcatenationOf(Responserversion, HiResponserversion, Z6, BitConverterLE.GetBytes(timestamp), clientChallenge, Z4, targetInfo, Z4);
            var proof = HMACMD5(responseKey, type2.ServerChallenge, temp);

            sessionBaseKey = HMACMD5(responseKey, proof);

            ntChallengeResponse = ConcatenationOf(proof, temp);
            Array.Clear(proof, 0, proof.Length);
            Array.Clear(temp, 0, temp.Length);

            var hash = HMACMD5(responseKey, type2.ServerChallenge, clientChallenge);

            Array.Clear(responseKey, 0, responseKey.Length);

            // Note: If NTLM v2 authentication is used and the CHALLENGE_MESSAGE TargetInfo field (section 2.2.1.2) has an
            // MsvAvTimestamp present, the client SHOULD NOT send the LmChallengeResponse and SHOULD send Z(24) instead.
            if (type2.TargetInfo?.Timestamp == null)
            {
                lmChallengeResponse = ConcatenationOf(hash, clientChallenge);
            }
            else
            {
                lmChallengeResponse = Z24;
            }
            Array.Clear(hash, 0, hash.Length);
        }
예제 #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 NtlmAuthenticateMessage(byte[] message, int startIndex, int length) : base(3)
 {
     Decode(message, startIndex, length);
     challenge = null;
 }