public NTStatus AcceptSecurityContext(ref object context, byte[] inputToken, out byte[] outputToken)
        {
            outputToken = null;
            if (!AuthenticationMessageUtils.IsSignatureValid(inputToken))
            {
                return(NTStatus.SEC_E_INVALID_TOKEN);
            }

            MessageTypeName messageType = AuthenticationMessageUtils.GetMessageType(inputToken);

            if (messageType == MessageTypeName.Negotiate)
            {
                NegotiateMessage input = new NegotiateMessage(inputToken);
                ChallengeMessage output;
                NTStatus         status = GetChallengeMessage(out context, input, out output);
                outputToken = output.GetBytes();
                return(status);
            }
            else if (messageType == MessageTypeName.Authenticate)
            {
                AuthenticateMessage message = new AuthenticateMessage(inputToken);
                return(Authenticate(context, message));
            }
            else
            {
                return(NTStatus.SEC_E_INVALID_TOKEN);
            }
        }
Пример #2
0
        public byte[] GetBytes()
        {
            int fixedLength = 32;

            if ((NegotiateFlags & NegotiateFlags.Version) > 0)
            {
                fixedLength += 8;
            }
            int payloadLength = DomainName.Length * 2 + Workstation.Length * 2;

            byte[] buffer = new byte[fixedLength + payloadLength];
            ByteWriter.WriteAnsiString(buffer, 0, AuthenticateMessage.ValidSignature, 8);
            LittleEndianWriter.WriteUInt32(buffer, 8, (uint)MessageType);
            LittleEndianWriter.WriteUInt32(buffer, 12, (uint)NegotiateFlags);

            if ((NegotiateFlags & NegotiateFlags.Version) > 0)
            {
                Version.WriteBytes(buffer, 32);
            }

            int offset = fixedLength;

            AuthenticationMessageUtils.WriteBufferPointer(buffer, 16, (ushort)(DomainName.Length * 2), (uint)offset);
            ByteWriter.WriteUTF16String(buffer, ref offset, DomainName);
            AuthenticationMessageUtils.WriteBufferPointer(buffer, 16, (ushort)(Workstation.Length * 2), (uint)offset);
            ByteWriter.WriteUTF16String(buffer, ref offset, Workstation);

            return(buffer);
        }
Пример #3
0
        public bool HasMicField()
        {
            if (!AuthenticationMessageUtils.IsNTLMv2NTResponse(NtChallengeResponse))
            {
                return(false);
            }

            NTLMv2ClientChallenge challenge;

            try
            {
                challenge = new NTLMv2ClientChallenge(NtChallengeResponse, 16);
            }
            catch
            {
                return(false);
            }

            int index = challenge.AVPairs.IndexOfKey(AVPairKey.Flags);

            if (index >= 0)
            {
                byte[] value = challenge.AVPairs[index].Value;
                if (value.Length == 4)
                {
                    int flags = LittleEndianConverter.ToInt32(value, 0);
                    return((flags & 0x02) > 0);
                }
            }

            return(false);
        }
Пример #4
0
        public byte[] GetBytes()
        {
            int fixedLength = 48;

            if ((NegotiateFlags & NegotiateFlags.Version) > 0)
            {
                fixedLength += 8;
            }

            int payloadLength = TargetName.Length * 2 + TargetInfo.Length;

            byte[] buffer = new byte[fixedLength + payloadLength];
            ByteWriter.WriteAnsiString(buffer, 0, AuthenticateMessage.ValidSignature, 8);
            LittleEndianWriter.WriteUInt32(buffer, 8, (uint)MessageType);
            LittleEndianWriter.WriteUInt32(buffer, 20, (uint)NegotiateFlags);
            ByteWriter.WriteBytes(buffer, 24, ServerChallenge);
            if ((NegotiateFlags & NegotiateFlags.Version) > 0)
            {
                Version.WriteBytes(buffer, 48);
            }

            int offset = fixedLength;

            AuthenticationMessageUtils.WriteBufferPointer(buffer, 12, (ushort)(TargetName.Length * 2), (uint)offset);
            ByteWriter.WriteUTF16String(buffer, ref offset, TargetName);
            AuthenticationMessageUtils.WriteBufferPointer(buffer, 40, (ushort)TargetInfo.Length, (uint)offset);
            ByteWriter.WriteBytes(buffer, ref offset, TargetInfo);

            return(buffer);
        }
Пример #5
0
 public NegotiateMessage(byte[] buffer)
 {
     Signature      = ByteReader.ReadAnsiString(buffer, 0, 8);
     MessageType    = (MessageTypeName)LittleEndianConverter.ToUInt32(buffer, 8);
     NegotiateFlags = (NegotiateFlags)LittleEndianConverter.ToUInt32(buffer, 12);
     DomainName     = AuthenticationMessageUtils.ReadAnsiStringBufferPointer(buffer, 16);
     Workstation    = AuthenticationMessageUtils.ReadAnsiStringBufferPointer(buffer, 24);
     if ((NegotiateFlags & NegotiateFlags.Version) > 0)
     {
         Version = new NTLMVersion(buffer, 32);
     }
 }
Пример #6
0
        public byte[] GetBytes()
        {
            if ((NegotiateFlags & NegotiateFlags.KeyExchange) == 0)
            {
                EncryptedRandomSessionKey = new byte[0];
            }

            int fixedLength = 64;

            if ((NegotiateFlags & NegotiateFlags.Version) > 0)
            {
                fixedLength += NtlmVersion.Length;
            }
            if (MIC != null)
            {
                fixedLength += MIC.Length;
            }
            int payloadLength = LmChallengeResponse.Length + NtChallengeResponse.Length + DomainName.Length * 2 + UserName.Length * 2 + WorkStation.Length * 2 + EncryptedRandomSessionKey.Length;

            byte[] buffer = new byte[fixedLength + payloadLength];
            ByteWriter.WriteAnsiString(buffer, 0, ValidSignature, 8);
            LittleEndianWriter.WriteUInt32(buffer, 8, (uint)MessageType);
            LittleEndianWriter.WriteUInt32(buffer, 60, (uint)NegotiateFlags);
            int offset = 64;

            if ((NegotiateFlags & NegotiateFlags.Version) > 0)
            {
                Version.WriteBytes(buffer, offset);
                offset += NtlmVersion.Length;
            }
            if (MIC != null)
            {
                ByteWriter.WriteBytes(buffer, offset, MIC);
                offset += MIC.Length;
            }

            AuthenticationMessageUtils.WriteBufferPointer(buffer, 28, (ushort)(DomainName.Length * 2), (uint)offset);
            ByteWriter.WriteUTF16String(buffer, ref offset, DomainName);
            AuthenticationMessageUtils.WriteBufferPointer(buffer, 36, (ushort)(UserName.Length * 2), (uint)offset);
            ByteWriter.WriteUTF16String(buffer, ref offset, UserName);
            AuthenticationMessageUtils.WriteBufferPointer(buffer, 44, (ushort)(WorkStation.Length * 2), (uint)offset);
            ByteWriter.WriteUTF16String(buffer, ref offset, WorkStation);
            AuthenticationMessageUtils.WriteBufferPointer(buffer, 12, (ushort)LmChallengeResponse.Length, (uint)offset);
            ByteWriter.WriteBytes(buffer, ref offset, LmChallengeResponse);
            AuthenticationMessageUtils.WriteBufferPointer(buffer, 20, (ushort)NtChallengeResponse.Length, (uint)offset);
            ByteWriter.WriteBytes(buffer, ref offset, NtChallengeResponse);
            AuthenticationMessageUtils.WriteBufferPointer(buffer, 52, (ushort)EncryptedRandomSessionKey.Length, (uint)offset);
            ByteWriter.WriteBytes(buffer, ref offset, EncryptedRandomSessionKey);

            return(buffer);
        }
Пример #7
0
 public ChallengeMessage(byte[] buffer)
 {
     Signature       = ByteReader.ReadAnsiString(buffer, 0, 8);
     MessageType     = (MessageTypeName)LittleEndianConverter.ToUInt32(buffer, 8);
     TargetName      = AuthenticationMessageUtils.ReadUnicodeStringBufferPointer(buffer, 12);
     NegotiateFlags  = (NegotiateFlags)LittleEndianConverter.ToUInt32(buffer, 20);
     ServerChallenge = ByteReader.ReadBytes(buffer, 24, 8);
     // Reserved
     TargetInfo = AuthenticationMessageUtils.ReadBufferPointer(buffer, 40);
     if ((NegotiateFlags & NegotiateFlags.Version) > 0)
     {
         Version = new NTLMVersion(buffer, 48);
     }
 }
Пример #8
0
 public AuthenticateMessage(byte[] buffer)
 {
     Signature                 = ByteReader.ReadAnsiString(buffer, 0, 8);
     MessageType               = (MessageTypeName)LittleEndianConverter.ToUInt32(buffer, 8);
     LmChallengeResponse       = AuthenticationMessageUtils.ReadBufferPointer(buffer, 12);
     NtChallengeResponse       = AuthenticationMessageUtils.ReadBufferPointer(buffer, 20);
     DomainName                = AuthenticationMessageUtils.ReadUnicodeStringBufferPointer(buffer, 28);
     UserName                  = AuthenticationMessageUtils.ReadUnicodeStringBufferPointer(buffer, 36);
     WorkStation               = AuthenticationMessageUtils.ReadUnicodeStringBufferPointer(buffer, 44);
     EncryptedRandomSessionKey = AuthenticationMessageUtils.ReadBufferPointer(buffer, 52);
     NegotiateFlags            = (NegotiateFlags)LittleEndianConverter.ToUInt32(buffer, 60);
     if ((NegotiateFlags & NegotiateFlags.Version) > 0)
     {
         Version = new NTLMVersion(buffer, 64);
     }
 }
Пример #9
0
        /// <summary>
        /// LM v2 / NTLM v2
        /// </summary>
        private bool AuthenticateV2(string domainName, string accountName, string password, byte[] serverChallenge, byte[] lmResponse, byte[] ntResponse)
        {
            byte[] _LMv2ClientChallenge = ByteReader.ReadBytes(lmResponse, 16, 8);
            byte[] expectedLMv2Response = NTLMCryptography.ComputeLMv2Response(serverChallenge, _LMv2ClientChallenge, password, accountName, domainName);
            if (ByteUtils.AreByteArraysEqual(expectedLMv2Response, lmResponse))
            {
                return(true);
            }

            if (AuthenticationMessageUtils.IsNTLMv2NTResponse(ntResponse))
            {
                byte[] clientNTProof = ByteReader.ReadBytes(ntResponse, 0, 16);
                byte[] clientChallengeStructurePadded = ByteReader.ReadBytes(ntResponse, 16, ntResponse.Length - 16);
                byte[] expectedNTProof = NTLMCryptography.ComputeNTLMv2Proof(serverChallenge, clientChallengeStructurePadded, password, accountName, domainName);

                return(ByteUtils.AreByteArraysEqual(clientNTProof, expectedNTProof));
            }
            return(false);
        }
Пример #10
0
        public NTStatus AcceptSecurityContext(ref object context, byte[] inputToken, out byte[]?outputToken)
        {
            outputToken = null;
            if (!AuthenticationMessageUtils.IsSignatureValid(inputToken))
            {
                return(NTStatus.SEC_E_INVALID_TOKEN);
            }

            MessageTypeName messageType = AuthenticationMessageUtils.GetMessageType(inputToken);

            if (messageType != MessageTypeName.Negotiate)
            {
                return(messageType == MessageTypeName.Authenticate ? Authenticate(context, inputToken) : NTStatus.SEC_E_INVALID_TOKEN);
            }

            NTStatus status = GetChallengeMessage(out context, inputToken, out outputToken);

            return(status);
        }
Пример #11
0
        public override NTStatus Authenticate(object context, byte[] authenticateMessageBytes)
        {
            AuthenticateMessage message;

            try
            {
                message = new AuthenticateMessage(authenticateMessageBytes);
            }
            catch
            {
                return(NTStatus.SEC_E_INVALID_TOKEN);
            }

            if (!(context is AuthContext authContext))
            {
                // There are two possible reasons for authContext to be null:
                // 1. We have a bug in our implementation, let's assume that's not the case,
                //    according to [MS-SMB2] 3.3.5.5.1 we aren't allowed to return SEC_E_INVALID_HANDLE anyway.
                // 2. The client sent AuthenticateMessage without sending NegotiateMessage first,
                //    in this case the correct response is SEC_E_INVALID_TOKEN.
                return(NTStatus.SEC_E_INVALID_TOKEN);
            }

            authContext.DomainName  = message.DomainName;
            authContext.UserName    = message.UserName;
            authContext.WorkStation = message.WorkStation;
            if (message.Version != null)
            {
                authContext.OSVersion = message.Version.ToString();
            }

            if ((message.NegotiateFlags & NegotiateFlags.Anonymous) > 0)
            {
                if (!EnableGuestLogin)
                {
                    return(NTStatus.STATUS_LOGON_FAILURE);
                }
                authContext.IsGuest = true;
                return(NTStatus.STATUS_SUCCESS);
            }

            if (!m_loginCounter.HasRemainingLoginAttempts(message.UserName.ToLower()))
            {
                return(NTStatus.STATUS_ACCOUNT_LOCKED_OUT);
            }

            string password = m_GetUserPassword(message.UserName);

            if (password == null)
            {
                if (EnableGuestLogin)
                {
                    authContext.IsGuest = true;
                    return(NTStatus.STATUS_SUCCESS);
                }

                if (m_loginCounter.HasRemainingLoginAttempts(message.UserName.ToLower(), true))
                {
                    return(NTStatus.STATUS_LOGON_FAILURE);
                }

                return(NTStatus.STATUS_ACCOUNT_LOCKED_OUT);
            }

            bool success;

            byte[] serverChallenge = authContext.ServerChallenge;
            byte[] sessionBaseKey;
            byte[] keyExchangeKey = null;
            if ((message.NegotiateFlags & NegotiateFlags.ExtendedSessionSecurity) > 0)
            {
                if (AuthenticationMessageUtils.IsNTLMv1ExtendedSessionSecurity(message.LmChallengeResponse))
                {
                    // NTLM v1 Extended Session Security:
                    success = AuthenticateV1Extended(password, serverChallenge, message.LmChallengeResponse, message.NtChallengeResponse);
                    if (success)
                    {
                        // https://msdn.microsoft.com/en-us/library/cc236699.aspx
                        sessionBaseKey = new MD4().GetByteHashFromBytes(NtlmCryptography.NTOWFv1(password));
                        byte[] lmowf = NtlmCryptography.LMOWFv1(password);
                        keyExchangeKey = NtlmCryptography.KXKey(sessionBaseKey, message.NegotiateFlags, message.LmChallengeResponse, serverChallenge, lmowf);
                    }
                }
                else
                {
                    // NTLM v2:
                    success = AuthenticateV2(message.DomainName, message.UserName, password, serverChallenge, message.LmChallengeResponse, message.NtChallengeResponse);
                    if (success)
                    {
                        // https://msdn.microsoft.com/en-us/library/cc236700.aspx
                        byte[] responseKeyNT = NtlmCryptography.NTOWFv2(password, message.UserName, message.DomainName);
                        byte[] ntProofStr    = ByteReader.ReadBytes(message.NtChallengeResponse, 0, 16);
                        using HMACMD5 hmacmd5 = new HMACMD5(responseKeyNT);
                        sessionBaseKey        = hmacmd5.ComputeHash(ntProofStr);
                        keyExchangeKey        = sessionBaseKey;
                    }
                }
            }
            else
            {
                success = AuthenticateV1(password, serverChallenge, message.LmChallengeResponse, message.NtChallengeResponse);
                if (success)
                {
                    // https://msdn.microsoft.com/en-us/library/cc236699.aspx
                    sessionBaseKey = new MD4().GetByteHashFromBytes(NtlmCryptography.NTOWFv1(password));
                    byte[] lmowf = NtlmCryptography.LMOWFv1(password);
                    keyExchangeKey = NtlmCryptography.KXKey(sessionBaseKey, message.NegotiateFlags, message.LmChallengeResponse, serverChallenge, lmowf);
                }
            }

            if (success)
            {
                // https://msdn.microsoft.com/en-us/library/cc236676.aspx
                // https://blogs.msdn.microsoft.com/openspecification/2010/04/19/ntlm-keys-and-sundry-stuff/
                if ((message.NegotiateFlags & NegotiateFlags.KeyExchange) > 0)
                {
                    authContext.SessionKey = RC4.Decrypt(keyExchangeKey, message.EncryptedRandomSessionKey);
                }
                else
                {
                    authContext.SessionKey = keyExchangeKey;
                }
                return(NTStatus.STATUS_SUCCESS);
            }

            if (m_loginCounter.HasRemainingLoginAttempts(message.UserName.ToLower(), true))
            {
                return(NTStatus.STATUS_LOGON_FAILURE);
            }

            return(NTStatus.STATUS_ACCOUNT_LOCKED_OUT);
        }