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); } }
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); }
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); }
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); }
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); } }
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); }
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); } }
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); } }
/// <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); }
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); }
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); }