/// <summary> /// initialize the response of challenge /// </summary> /// <param name="flags">the flag for challenge</param> /// <param name="challenge">the challenge packet</param> /// <param name="targetInfo">the target info of avpairs</param> /// <param name="responseKeyLM">the response lm key</param> /// <param name="lmChallengeResponse">the challenge lm response</param> /// <param name="ntChallengeResponse">the nt challenge response</param> private void InitializeChallengeResponse( NegotiateTypes flags, NlmpChallengePacket challenge, ICollection <AV_PAIR> targetInfo, out byte[] responseKeyLM, out byte[] lmChallengeResponse, out byte[] ntChallengeResponse ) { // responseKeyNT byte[] responseKeyNT = NlmpUtility.GetResponseKeyNt( this.client.Config.Version, this.currentActiveCredential.DomainName, this.currentActiveCredential.AccountName, this.currentActiveCredential.Password); // responseKeyLM responseKeyLM = NlmpUtility.GetResponseKeyLm( this.client.Config.Version, this.currentActiveCredential.DomainName, this.currentActiveCredential.AccountName, this.currentActiveCredential.Password); // lmChallengeResponse lmChallengeResponse = null; // ntChallengeResponse ntChallengeResponse = null; ComputeResponse( flags, challenge.Payload.ServerChallenge, targetInfo, responseKeyNT, responseKeyLM, out lmChallengeResponse, out ntChallengeResponse); UpdateLmChallengeResponse(targetInfo, ref lmChallengeResponse); }
/// <summary> /// initialize the exportedSessionKey and internal keys /// </summary> /// <param name="flags">the flags of challenge</param> /// <param name="challenge">the challenge packet</param> /// <param name="responseKeyLM">the response key lm</param> /// <param name="lmChallengeResponse">the challenge response lm</param> /// <param name="encryptedRandomSessionKey">the encrypted random session key</param> /// <param name="exportedSessionKey">the exported session key</param> private void InitializeKeys( NegotiateTypes flags, NlmpChallengePacket challenge, byte[] responseKeyLM, byte[] lmChallengeResponse, out byte[] encryptedRandomSessionKey, out byte[] exportedSessionKey ) { // keyExchangeKey byte[] keyExchangeKey = null; // get random session key NlmpUtility.GetEncryptedRandomSessionKey( this.client.Config.Version, flags, this.client.Context.SessionBaseKey, lmChallengeResponse, responseKeyLM, challenge.Payload.ServerChallenge, out encryptedRandomSessionKey, out keyExchangeKey, out exportedSessionKey); this.client.Context.ClientSigningKey = NlmpUtility.SignKey(flags, exportedSessionKey, "Client"); this.client.Context.ServerSigningKey = NlmpUtility.SignKey(flags, exportedSessionKey, "Server"); this.client.Context.ClientSealingKey = NlmpUtility.SealKey(flags, exportedSessionKey, "Client"); this.client.Context.ServerSealingKey = NlmpUtility.SealKey(flags, exportedSessionKey, "Server"); NlmpUtility.RC4Init(this.client.Context.ClientHandle, this.client.Context.ClientSealingKey); NlmpUtility.RC4Init(this.client.Context.ServerHandle, this.client.Context.ServerSealingKey); }
/// <summary> /// create a challenge packet. This packet contains CHALLENGE_MESSAGE. The CHALLENGE_MESSAGE defines an NTLM /// challenge message that is sent from the server to the client. The CHALLENGE_MESSAGE is used by the server /// to challenge the client to prove its identity. /// </summary> /// <param name="negotiateFlags">The client sets flags to indicate options it supports.</param> /// <param name="version"> /// This structure is used for debugging purposes only. In normal (non-debugging) protocol messages, it is /// ignored and does not affect the NTLM message processing. /// </param> /// <param name="serverChallenge">contains the NTLM challenge. The challenge is a 64-bit nonce.</param> /// <param name="targetName"> /// TargetName contains the name of the server authentication realm, and MUST be expressed in the negotiated /// character set. A server that is a member of a domain returns the domain of which it is a member, and a /// server that is not a member of a domain returns the server name. This param can be null. /// </param> /// <param name="targetInfo"> /// TargetInfo contains a sequence of AV_PAIR structures.This param can be null. /// </param> /// <returns>the NlmpChallengePacket</returns> /// <noException></noException> public NlmpChallengePacket CreateChallengePacket( NegotiateTypes negotiateFlags, VERSION version, ulong serverChallenge, string targetName, ICollection <AV_PAIR> targetInfo ) { NlmpChallengePacket packet = new NlmpChallengePacket(); packet.SetNegotiateFlags(negotiateFlags); if (NlmpUtility.IsVersionRequired(negotiateFlags)) { packet.SetVersion(version); } packet.SetServerChallenge(serverChallenge); if (NlmpUtility.IsDomainType(negotiateFlags) || NlmpUtility.IsServerType(negotiateFlags)) { packet.SetTargetName(targetName); } // generate bytes of targetinfo byte[] targetInfoBytes = NlmpUtility.AvPairCollectionGetBytes(targetInfo); // initialize targetinfofield packet.SetTargetInfo(targetInfoBytes); return(packet); }
/// <summary> /// compute response /// </summary> /// <param name="flags">the flags for challenge</param> /// <param name="serverChallenge">the server challenge</param> /// <param name="targetInfo">the target info contains avpairs</param> /// <param name="responseKeyNT">the response nt key</param> /// <param name="responseKeyLM">the response lm key</param> /// <param name="lmChallengeResponse">the challenge response lm</param> /// <param name="ntChallengeResponse">the challenge response nt</param> private void ComputeResponse( NegotiateTypes flags, ulong serverChallenge, ICollection <AV_PAIR> targetInfo, byte[] responseKeyNT, byte[] responseKeyLM, out byte[] lmChallengeResponse, out byte[] ntChallengeResponse ) { // clientChallenge, a random 8 bytes. ulong clientChallenge = NlmpUtility.BytesToSecurityUInt64(NlmpUtility.Nonce(8)); // time ulong time = 0; if (!NlmpUtility.IsNtlmV1(this.client.Config.Version)) { time = NlmpUtility.GetTime(targetInfo); } byte[] sessionBaseKey = null; // compute response NlmpUtility.ComputeResponse( this.client.Config.Version, flags, responseKeyNT, responseKeyLM, serverChallenge, clientChallenge, time, NlmpUtility.AvPairCollectionGetBytes(targetInfo), out ntChallengeResponse, out lmChallengeResponse, out sessionBaseKey); // save key to context this.client.Context.SessionBaseKey = sessionBaseKey; }
/// <summary> /// create a challenge packet. This packet contains CHALLENGE_MESSAGE. The CHALLENGE_MESSAGE defines an NTLM /// challenge message that is sent from the server to the client. The CHALLENGE_MESSAGE is used by the server /// to challenge the client to prove its identity. /// </summary> /// <param name="negotiateFlags">The client sets flags to indicate options it supports.</param> /// <param name="version"> /// This structure is used for debugging purposes only. In normal (non-debugging) protocol messages, it is /// ignored and does not affect the NTLM message processing. /// </param> /// <param name="serverChallenge">contains the NTLM challenge. The challenge is a 64-bit nonce.</param> /// <param name="targetName"> /// TargetName contains the name of the server authentication realm, and MUST be expressed in the negotiated /// character set. A server that is a member of a domain returns the domain of which it is a member, and a /// server that is not a member of a domain returns the server name. This param can be null. /// </param> /// <param name="targetInfo"> /// TargetInfo contains a sequence of AV_PAIR structures.This param can be null. /// </param> /// <returns>the NlmpChallengePacket</returns> /// <noException></noException> public NlmpChallengePacket CreateChallengePacket( NegotiateTypes negotiateFlags, VERSION version, ulong serverChallenge, string targetName, ICollection<AV_PAIR> targetInfo ) { NlmpChallengePacket packet = new NlmpChallengePacket(); packet.SetNegotiateFlags(negotiateFlags); if (NlmpUtility.IsVersionRequired(negotiateFlags)) { packet.SetVersion(version); } packet.SetServerChallenge(serverChallenge); if (NlmpUtility.IsDomainType(negotiateFlags) || NlmpUtility.IsServerType(negotiateFlags)) { packet.SetTargetName(targetName); } // generate bytes of targetinfo byte[] targetInfoBytes = NlmpUtility.AvPairCollectionGetBytes(targetInfo); // initialize targetinfofield packet.SetTargetInfo(targetInfoBytes); return packet; }
/// <summary> /// initialize the negotiate flags /// </summary> /// <returns>the negotiate flags for authenticate</returns> private NegotiateTypes InitializeNegotiateFlags() { NegotiateTypes flags = this.Context.ClientConfigFlags; flags |= NegotiateTypes.NTLMSSP_NEGOTIATE_TARGET_INFO; return(flags); }
/// <summary> /// get the security token,using the token from server /// </summary> /// <param name="serverToken">the token from server challenge</param> /// <returns>the security token</returns> private byte[] GetSecurityToken( byte[] serverToken ) { if (this.client == null) { throw new InvalidOperationException("The client is null! You must initialize this field first!"); } // the challenge packet from server NlmpChallengePacket challenge = new NlmpChallengePacket(serverToken); NegotiateTypes flags = InitializeNegotiateFlags(challenge.Payload.NegotiateFlags); // the target info ICollection <AV_PAIR> targetInfo = InitializeTargetInfo(challenge.Payload.TargetInfo); // responseKeyLM byte[] responseKeyLM; // lmChallengeResponse byte[] lmChallengeResponse; // ntChallengeResponse byte[] ntChallengeResponse; // initialize the challenge response InitializeChallengeResponse( flags, challenge, targetInfo, out responseKeyLM, out lmChallengeResponse, out ntChallengeResponse); // encryptedRandomSessionKey byte[] encryptedRandomSessionKey = null; // exportedSessionKey byte[] exportedSessionKey = null; // initialize keys InitializeKeys( flags, challenge, responseKeyLM, lmChallengeResponse, out encryptedRandomSessionKey, out exportedSessionKey); // save the exported sessionkey this.client.Context.ExportedSessionKey = exportedSessionKey; // create challenge packet NlmpAuthenticatePacket packet = this.client.CreateAuthenticatePacket( flags, NlmpUtility.GetVersion(), lmChallengeResponse, ntChallengeResponse, this.currentActiveCredential.DomainName, this.currentActiveCredential.AccountName, Environment.MachineName, encryptedRandomSessionKey); // initialize the mic of challenge packet InitializeChallengeMIC(exportedSessionKey, targetInfo, packet, challenge); return(packet.ToBytes()); }
/// <summary> /// Constructor /// </summary> /// <param name="flags">Negotiation flags.</param> /// <param name="clientCredential">Client account credential.</param> /// <param name="isDomainJoined">Joined in a domain or not</param> /// <param name="netbiosDomainName">Netbios domain name.</param> /// <param name="netbiosMachineName">Netbios machine name.</param> public NlmpServerSecurityConfig( NegotiateTypes flags, NlmpClientCredential clientCredential, bool isDomainJoined, string netbiosDomainName, string netbiosMachineName) : base(SecurityPackageType.Ntlm) { this.negotiateflags = flags; this.clientCredential = clientCredential; this.isDomainJoined = isDomainJoined; this.netbiosDomainName = netbiosDomainName; this.netbiosMachineName = netbiosMachineName; this.targetName = clientCredential.TargetName; }
/// <summary> /// Constructor /// </summary> /// <param name="flags">Negotiation flags.</param> /// <param name="clientCredential">Client account credential.</param> /// <param name="isDomainJoined">Joined in a domain or not</param> /// <param name="netbiosDomainName">Netbios domain name.</param> /// <param name="netbiosMachineName">Netbios machine name.</param> public NlmpServerSecurityConfig( NegotiateTypes flags, NlmpClientCredential clientCredential, bool isDomainJoined, string netbiosDomainName, string netbiosMachineName) : base(SecurityPackageType.Ntlm) { this.negotiateflags = flags; this.clientCredential = clientCredential; this.isDomainJoined = isDomainJoined; this.netbiosDomainName = netbiosDomainName; this.netbiosMachineName = netbiosMachineName; this.targetName = clientCredential.TargetName; }
/// <summary> /// constructor /// </summary> /// <param name="flags">the negotiate flags indicates the capabilities of server or client</param> /// <param name="clientCredential"> /// the credential of client. server sdk can not retrieve password from AD/Account Database;<para/> /// instead, server sdk get the user credential from this parameter. /// </param> /// <param name="isDomainJoined">whether the server joined to domain</param> /// <param name="netbiosDomainName">the netbios domain name of server</param> /// <param name="netbiosMachineName">the netbios machine name of server</param> public NlmpServerSecurityContext( NegotiateTypes flags, NlmpClientCredential clientCredential, bool isDomainJoined, string netbiosDomainName, string netbiosMachineName) { this.version = new NlmpVersion(); this.nlmpServer = new NlmpServer(); this.nlmpServer.Context.NegFlg = flags; this.nlmpServer.Context.ClientCredential = clientCredential; this.nlmpServer.Context.IsDomainJoined = isDomainJoined; this.nlmpServer.Context.NbDomainName = netbiosDomainName; this.nlmpServer.Context.NbMachineName = netbiosMachineName; this.needContinueProcessing = true; }
/// <summary> /// constructor /// </summary> /// <param name="flags">the negotiate flags indicates the capabilities of server or client</param> /// <param name="isDomainJoined">whether the server joined to domain</param> /// <param name="netbiosDomainName">the netbios domain name of server</param> /// <param name="netbiosMachineName">the netbios machine name of server</param> /// <param name="verifyAuthenticatePacketInDcMethod"> /// the delegate method used to verify authentication packet in AD/Account Database; /// </param> public NlmpServerSecurityContext( NegotiateTypes flags, bool isDomainJoined, string netbiosDomainName, string netbiosMachineName, VerifyAuthenticatePacketInDcMethod verifyAuthenticatePacketInDcMethod) { this.version = new NlmpVersion(); this.nlmpServer = new NlmpServer(); this.nlmpServer.Context.NegFlg = flags; this.nlmpServer.Context.ClientCredential = null; this.nlmpServer.Context.IsDomainJoined = isDomainJoined; this.nlmpServer.Context.NbDomainName = netbiosDomainName; this.nlmpServer.Context.NbMachineName = netbiosMachineName; this.needContinueProcessing = true; this.verifyAuthenticatePacketInDc = verifyAuthenticatePacketInDcMethod; }
/// <summary> /// generated negotiate flags for challenge packet /// </summary> /// <param name="negotiatePacket">the negotiate packet from client</param> /// <returns>the negotiate flags to generate challenge packet</returns> private NegotiateTypes GeneratedNegotiateFlags(NlmpNegotiatePacket negotiatePacket) { NegotiateTypes negotiateFlags = this.nlmpServer.Context.NegFlg; // in the connectionless mode, the negotiate is null, return the flags in context. if (negotiatePacket == null) { return(negotiateFlags); } // Unicode or oem if (NegotiateTypes.NTLMSSP_NEGOTIATE_UNICODE == (negotiatePacket.Payload.NegotiateFlags & NegotiateTypes.NTLMSSP_NEGOTIATE_UNICODE)) { negotiateFlags |= NegotiateTypes.NTLMSSP_NEGOTIATE_UNICODE; } else if (NegotiateTypes.NTLM_NEGOTIATE_OEM == (negotiatePacket.Payload.NegotiateFlags & NegotiateTypes.NTLM_NEGOTIATE_OEM)) { negotiateFlags |= NegotiateTypes.NTLM_NEGOTIATE_OEM; } // extended security or lm if (NegotiateTypes.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY == (negotiatePacket.Payload.NegotiateFlags & NegotiateTypes.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY)) { negotiateFlags |= NegotiateTypes.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY; } else if (NegotiateTypes.NTLMSSP_NEGOTIATE_LM_KEY == (negotiatePacket.Payload.NegotiateFlags & NegotiateTypes.NTLMSSP_NEGOTIATE_LM_KEY)) { negotiateFlags |= NegotiateTypes.NTLMSSP_NEGOTIATE_LM_KEY; } // target info if (NegotiateTypes.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY == (negotiateFlags & NegotiateTypes.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY)) { negotiateFlags |= NegotiateTypes.NTLMSSP_NEGOTIATE_TARGET_INFO; } return(negotiateFlags); }
/// <summary> /// Update ServerChallenge to this context /// </summary> /// <param name="serverChallenge">the serverChallenge to update</param> public void UpdateServerChallenge(ulong serverChallenge) { #region Prepare the Nlmp Negotiate Flags // the flags for negotiage NegotiateTypes nlmpFlags = NegotiateTypes.NTLMSSP_NEGOTIATE_NTLM | NegotiateTypes.NTLM_NEGOTIATE_OEM; #endregion #region Prepare the ServerName List <AV_PAIR> pairs = new List <AV_PAIR>(); NlmpUtility.AddAVPair(pairs, AV_PAIR_IDs.MsvAvEOL, 0x00, null); #endregion this.challenge = this.nlmpServer.CreateChallengePacket(nlmpFlags, NlmpUtility.GetVersion(), serverChallenge, GenerateTargetName(), pairs); this.token = this.challenge.ToBytes(); }
/// <summary> /// initialize the negotiate flags /// </summary> /// <returns>the negotiate flags for authenticate</returns> private NegotiateTypes InitializeNegotiateFlags(NegotiateTypes challengeFlags) { NegotiateTypes flags = this.Context.ClientConfigFlags; flags |= NegotiateTypes.NTLMSSP_NEGOTIATE_TARGET_INFO; // A==1: The choice of character set encoding MUST be Unicode. // A==0 and B==1: The choice of character set encoding MUST be OEM. // A==0 and B==0: The protocol MUST return SEC_E_INVALID_TOKEN. if (NegotiateTypes.NTLMSSP_NEGOTIATE_UNICODE == (challengeFlags & NegotiateTypes.NTLMSSP_NEGOTIATE_UNICODE)) { if (flags.HasFlag(NegotiateTypes.NTLM_NEGOTIATE_OEM)) { flags ^= NegotiateTypes.NTLM_NEGOTIATE_OEM; } if (!flags.HasFlag(NegotiateTypes.NTLMSSP_NEGOTIATE_UNICODE)) { flags |= NegotiateTypes.NTLMSSP_NEGOTIATE_UNICODE; } } else if (NegotiateTypes.NTLM_NEGOTIATE_OEM == (challengeFlags & NegotiateTypes.NTLM_NEGOTIATE_OEM)) { if (flags.HasFlag(NegotiateTypes.NTLMSSP_NEGOTIATE_UNICODE)) { flags ^= NegotiateTypes.NTLMSSP_NEGOTIATE_UNICODE; } if (!flags.HasFlag(NegotiateTypes.NTLM_NEGOTIATE_OEM)) { flags |= NegotiateTypes.NTLM_NEGOTIATE_OEM; } } else { throw new Exception("The protocol MUST return SEC_E_INVALID_TOKEN"); } return(flags); }
/// <summary> /// accept the negotiate packet, generated the challenge packet. /// </summary> /// <param name="negotiatePacket">the negotiate packet</param> private void AcceptNegotiatePacket(NlmpNegotiatePacket negotiatePacket) { // save the negotiate, to valid the mic when authenticate. this.negotiate = negotiatePacket; // generated negotiate flags for challenge packet NegotiateTypes negotiateFlags = GeneratedNegotiateFlags(negotiatePacket); // initialize target name string targetName = GenerateTargetName(); // initialize av pairs. ICollection <AV_PAIR> targetInfo = GenerateTargetInfo(); VERSION sspiVersion = NlmpUtility.GetVersion(); // the serverChallenge is 8 bytes. ulong serverChallenge = BitConverter.ToUInt64(NlmpUtility.Nonce(8), 0); NlmpChallengePacket challengePacket = this.nlmpServer.CreateChallengePacket( negotiateFlags, sspiVersion, serverChallenge, targetName, targetInfo); this.challenge = challengePacket; this.token = challengePacket.ToBytes(); }
/// <summary> /// set the negotiate flags /// </summary> /// <param name="negotiateFlags">the new flags</param> public abstract void SetNegotiateFlags( NegotiateTypes negotiateFlags );
/// <summary> /// set the negotiate flags /// </summary> /// <param name="negotiateFlags">the new flags</param> public override void SetNegotiateFlags( NegotiateTypes negotiateFlags ) { payload.NegotiateFlags = negotiateFlags; }
/// <summary> /// set the negotiate flags /// </summary> /// <param name="negotiateFlags">the new flags</param> public override void SetNegotiateFlags(NegotiateTypes negotiateFlags) { }
/// <summary> /// constructor /// </summary> /// <param name="flags">the negotiate flags indicates the capabilities of server or client</param> /// <param name="clientCredential"> /// the credential of client. server sdk can not retrieve password from AD/Account Database;<para/> /// instead, server sdk get the user credential from this parameter. /// </param> /// <param name="isDomainJoined">whether the server joined to domain</param> /// <param name="netbiosDomainName">the netbios domain name of server</param> /// <param name="netbiosMachineName">the netbios machine name of server</param> public NlmpServerSecurityContext( NegotiateTypes flags, NlmpClientCredential clientCredential, bool isDomainJoined, string netbiosDomainName, string netbiosMachineName) { this.version = new NlmpVersion(); this.nlmpServer = new NlmpServer(); this.nlmpServer.Context.NegFlg = flags; this.nlmpServer.Context.ClientCredential = clientCredential; this.nlmpServer.Context.IsDomainJoined = isDomainJoined; this.nlmpServer.Context.NbDomainName = netbiosDomainName; this.nlmpServer.Context.NbMachineName = netbiosMachineName; this.needContinueProcessing = true; }
/// <summary> /// constructor /// </summary> /// <param name="flags">the negotiate flags indicates the capabilities of server or client</param> /// <param name="isDomainJoined">whether the server joined to domain</param> /// <param name="netbiosDomainName">the netbios domain name of server</param> /// <param name="netbiosMachineName">the netbios machine name of server</param> /// <param name="verifyAuthenticatePacketInDcMethod"> /// the delegate method used to verify authentication packet in AD/Account Database; /// </param> public NlmpServerSecurityContext( NegotiateTypes flags, bool isDomainJoined, string netbiosDomainName, string netbiosMachineName, VerifyAuthenticatePacketInDcMethod verifyAuthenticatePacketInDcMethod) { this.version = new NlmpVersion(); this.nlmpServer = new NlmpServer(); this.nlmpServer.Context.NegFlg = flags; this.nlmpServer.Context.ClientCredential = null; this.nlmpServer.Context.IsDomainJoined = isDomainJoined; this.nlmpServer.Context.NbDomainName = netbiosDomainName; this.nlmpServer.Context.NbMachineName = netbiosMachineName; this.needContinueProcessing = true; this.verifyAuthenticatePacketInDc = verifyAuthenticatePacketInDcMethod; }
/// <summary> /// set the negotiate flags /// </summary> /// <param name="negotiateFlags">the new flags</param> public abstract void SetNegotiateFlags( NegotiateTypes negotiateFlags );
public void GetSecurityToken( NlmpVersion ntlmVersion, string domainName, string userName, string password, ulong serverTime, ulong serverChallenge, out byte[] caseInsensitivePassword, out byte[] caseSensitivePassword) { if (ntlmVersion != NlmpVersion.v1 && ntlmVersion != NlmpVersion.v2) { throw new ArgumentException( string.Format("the ntlmVersion({0}) must be valid NlmpVersion value", ntlmVersion), "ntlmVersion"); } caseInsensitivePassword = null; caseSensitivePassword = null; #region Prepare the TargetInfo byte[] targetInfo = null; List <AV_PAIR> pairs = new List <AV_PAIR>(); NlmpUtility.AddAVPair(pairs, AV_PAIR_IDs.MsvAvEOL, 0x00, null); targetInfo = NlmpUtility.AvPairCollectionGetBytes(pairs); #endregion #region Prepare the Nlmp Negotiate Flags // the flags for negotiate NegotiateTypes nlmpFlags = NegotiateTypes.NTLMSSP_NEGOTIATE_NTLM | NegotiateTypes.NTLM_NEGOTIATE_OEM; #endregion // exported to application for the SessionKey. byte[] sessionBaseKey = null; #region Prepare the keys // responseKeyNT byte[] responseKeyNT = NlmpUtility.GetResponseKeyNt(ntlmVersion, domainName, userName, password); // responseKeyLM byte[] responseKeyLM = NlmpUtility.GetResponseKeyLm(ntlmVersion, domainName, userName, password); #endregion #region Compute Response // clientChallenge, a 8 bytes random number. ulong clientChallenge = BitConverter.ToUInt64(NlmpUtility.Nonce(8), 0); // compute response NlmpUtility.ComputeResponse( ntlmVersion, nlmpFlags, responseKeyNT, responseKeyLM, serverChallenge, clientChallenge, serverTime, targetInfo, out caseSensitivePassword, out caseInsensitivePassword, out sessionBaseKey); #endregion }
/// <summary> /// set the negotiate flags /// </summary> /// <param name="negotiateFlags">the new flags</param> public override void SetNegotiateFlags( NegotiateTypes negotiateFlags ) { payload.NegotiateFlags = negotiateFlags; }
/// <summary> /// initialize the response of challenge /// </summary> /// <param name="flags">the flag for challenge</param> /// <param name="challenge">the challenge packet</param> /// <param name="targetInfo">the target info of avpairs</param> /// <param name="responseKeyLM">the response lm key</param> /// <param name="lmChallengeResponse">the challenge lm response</param> /// <param name="ntChallengeResponse">the nt challenge response</param> private void InitializeChallengeResponse( NegotiateTypes flags, NlmpChallengePacket challenge, ICollection<AV_PAIR> targetInfo, out byte[] responseKeyLM, out byte[] lmChallengeResponse, out byte[] ntChallengeResponse ) { // responseKeyNT byte[] responseKeyNT = NlmpUtility.GetResponseKeyNt( this.client.Config.Version, this.currentActiveCredential.DomainName, this.currentActiveCredential.AccountName, this.currentActiveCredential.Password); // responseKeyLM responseKeyLM = NlmpUtility.GetResponseKeyLm( this.client.Config.Version, this.currentActiveCredential.DomainName, this.currentActiveCredential.AccountName, this.currentActiveCredential.Password); // lmChallengeResponse lmChallengeResponse = null; // ntChallengeResponse ntChallengeResponse = null; ComputeResponse( flags, challenge.Payload.ServerChallenge, targetInfo, responseKeyNT, responseKeyLM, out lmChallengeResponse, out ntChallengeResponse); UpdateLmChallengeResponse(challenge.Payload.TargetInfo, ref lmChallengeResponse); }
/// <summary> /// this function create an authenticate packet. /// after client received the challenge packet from server, client create an authenticate packet to server. /// the authenticate packet contains the authentication information of user that is generated by the credential /// of user. /// this function does not set the mic field of packet. it must be set manually if need. /// </summary> /// <param name="negotiateFlags">this flags indicates the capabilities that client supports.</param> /// <param name="version"> /// This structure is used for debugging purposes only. In normal (non-debugging) protocol messages, it is /// ignored and does not affect the NTLM message processing. /// </param> /// <param name="lmChallengeResponse"> /// An LM_RESPONSE or LMv2_RESPONSE structure that contains the computed LM response to the challenge. If /// NTLM v2 authentication is configured, LmChallengeResponse MUST be an LMv2_RESPONSE structure. Otherwise, /// it MUST be an LM_RESPONSE structure. /// </param> /// <param name="ntChallengeResponse"> /// An NTLM_RESPONSE or NTLMv2_RESPONSE structure that contains the computed NT response to the challenge. /// If NTLM v2 authentication is configured, NtChallengeResponse MUST be an NTLMv2_RESPONSE. Otherwise, it /// MUST be an NTLM_RESPONSE structure. /// </param> /// <param name="domainName"> /// The domain or computer name hosting the user account. DomainName MUST be encoded in the negotiated /// character set. This param can not be null. /// </param> /// <param name="userName"> /// The name of the user to be authenticated. UserName MUST be encoded in the negotiated character set. This /// param can not be null. /// </param> /// <param name="workstation"> /// The name of the computer to which the user is logged on. Workstation MUST be encoded in the negotiated /// character set. This param can not be null. /// </param> /// <param name="encryptedRandomSessionKey"> /// The client's encrypted random session key. This param can be null. /// </param> /// <returns>the authenticate packet</returns> /// <exception cref="System.ArgumentNullException"> /// when LM is using, the ntChallengeResponse should be null! /// </exception> public NlmpAuthenticatePacket CreateAuthenticatePacket( NegotiateTypes negotiateFlags, VERSION version, byte[] lmChallengeResponse, byte[] ntChallengeResponse, string domainName, string userName, string workstation, byte[] encryptedRandomSessionKey ) { #region Parameter check if (domainName == null) { throw new ArgumentNullException("domainName"); } if (userName == null) { throw new ArgumentNullException("userName"); } if (workstation == null) { throw new ArgumentNullException("workstation"); } if (NlmpUtility.IsLm(negotiateFlags) && ntChallengeResponse != null) { throw new ArgumentException( "when LM is using, the ntChallengeResponse should be null!", "ntChallengeResponse"); } #endregion NlmpAuthenticatePacket packet = new NlmpAuthenticatePacket(); // update flags packet.SetNegotiateFlags(negotiateFlags); // if version required, update version if (NlmpUtility.IsVersionRequired(negotiateFlags)) { packet.SetVersion(version); } // update domain name packet.SetDomainName(domainName); // update user name packet.SetUserName(userName); // if version required, update workstation if (NlmpUtility.IsVersionRequired(negotiateFlags)) { packet.SetWorkstation(workstation); } // update lmChallengeResponse packet.SetLmChallengeResponse(lmChallengeResponse); // update ntChallengeResponse packet.SetNtChallengeResponse(ntChallengeResponse); // update encryptedRandomSessionKey packet.SetEncryptedRandomSessionKey(encryptedRandomSessionKey); return(packet); }
/// <summary> /// this function create a negotiate packet. /// client send the negotiate packet to server to indicate the supported capabilities. /// in connection-oriented mode, this is the first packet that client send to server. /// </summary> /// <param name="negotiateFlags">this flags indicates the capabilities that client supports.</param> /// <param name="version"> /// This structure is used for debugging purposes only. In normal (non-debugging) protocol messages, it is /// ignored and does not affect the NTLM message processing. /// </param> /// <param name="domainName"> /// DomainName contains the name of the client authentication domain that MUST be encoded using the OEM /// character set. This param can not be null. /// </param> /// <param name="workstationName"> /// WorkstationName contains the name of the client machine that MUST be encoded using the OEM character /// set. Otherwise, this data is not present. This param can not be null. /// </param> /// <returns>the negotiate packet</returns> /// <exception cref="ArgumentNullException">domainName must not be null</exception> /// <exception cref="ArgumentNullException">workstationName must not be null</exception> /// <exception cref="ArgumentException"> /// when version is required, the domainName and workstationName must be string.Empty /// </exception> public NlmpNegotiatePacket CreateNegotiatePacket( NegotiateTypes negotiateFlags, VERSION version, string domainName, string workstationName ) { #region Parameter validation if (NlmpUtility.IsConnectionless(negotiateFlags)) { throw new NotSupportedException("NEGOTIATE message is not supported under Connectionless mode."); } if (NlmpUtility.IsDomainNameSupplied(negotiateFlags) && (domainName == null)) { throw new ArgumentNullException("domainName"); } if (NlmpUtility.IsWorkstationSupplied(negotiateFlags) && (workstationName == null)) { throw new ArgumentNullException("workstationName"); } if (NlmpUtility.IsVersionRequired(negotiateFlags)) { if (domainName.Length != 0) { throw new ArgumentException( "when version is required, the domainName should be string.Empty!", "domainName"); } if (workstationName.Length != 0) { throw new ArgumentException( "when version is required, the workstationName should be string.Empty!", "workstationName"); } } else { if (NlmpUtility.IsDomainNameSupplied(negotiateFlags) && domainName.Length == 0) { throw new ArgumentException( "when version is not required, the domainName should not be string.Empty!", "domainName"); } if (NlmpUtility.IsWorkstationSupplied(negotiateFlags) && workstationName.Length == 0) { throw new ArgumentException( "when version is not required, the workstationName should not be string.Empty!", "workstationName"); } } #endregion NlmpNegotiatePacket packet = new NlmpNegotiatePacket(); packet.SetNegotiateFlags(negotiateFlags); if (NlmpUtility.IsVersionRequired(negotiateFlags)) { packet.SetVersion(version); } if (NlmpUtility.IsDomainNameSupplied(negotiateFlags)) { packet.SetDomainName(domainName); } if (NlmpUtility.IsWorkstationSupplied(negotiateFlags)) { packet.SetWorkstationName(workstationName); } return(packet); }
/// <summary> /// this function create an authenticate packet. /// after client received the challenge packet from server, client create an authenticate packet to server. /// the authenticate packet contains the authentication information of user that is generated by the credential /// of user. /// this function does not set the mic field of packet. it must be set manually if need. /// </summary> /// <param name="negotiateFlags">this flags indicates the capabilities that client supports.</param> /// <param name="version"> /// This structure is used for debugging purposes only. In normal (non-debugging) protocol messages, it is /// ignored and does not affect the NTLM message processing. /// </param> /// <param name="lmChallengeResponse"> /// An LM_RESPONSE or LMv2_RESPONSE structure that contains the computed LM response to the challenge. If /// NTLM v2 authentication is configured, LmChallengeResponse MUST be an LMv2_RESPONSE structure. Otherwise, /// it MUST be an LM_RESPONSE structure. /// </param> /// <param name="ntChallengeResponse"> /// An NTLM_RESPONSE or NTLMv2_RESPONSE structure that contains the computed NT response to the challenge. /// If NTLM v2 authentication is configured, NtChallengeResponse MUST be an NTLMv2_RESPONSE. Otherwise, it /// MUST be an NTLM_RESPONSE structure. /// </param> /// <param name="domainName"> /// The domain or computer name hosting the user account. DomainName MUST be encoded in the negotiated /// character set. This param can not be null. /// </param> /// <param name="userName"> /// The name of the user to be authenticated. UserName MUST be encoded in the negotiated character set. This /// param can not be null. /// </param> /// <param name="workstation"> /// The name of the computer to which the user is logged on. Workstation MUST be encoded in the negotiated /// character set. This param can not be null. /// </param> /// <param name="encryptedRandomSessionKey"> /// The client's encrypted random session key. This param can be null. /// </param> /// <returns>the authenticate packet</returns> /// <exception cref="System.ArgumentNullException"> /// when LM is using, the ntChallengeResponse should be null! /// </exception> public NlmpAuthenticatePacket CreateAuthenticatePacket( NegotiateTypes negotiateFlags, VERSION version, byte[] lmChallengeResponse, byte[] ntChallengeResponse, string domainName, string userName, string workstation, byte[] encryptedRandomSessionKey ) { #region Parameter check if (domainName == null) { throw new ArgumentNullException("domainName"); } if (userName == null) { throw new ArgumentNullException("userName"); } if (workstation == null) { throw new ArgumentNullException("workstation"); } if (NlmpUtility.IsLm(negotiateFlags) && ntChallengeResponse != null) { throw new ArgumentException( "when LM is using, the ntChallengeResponse should be null!", "ntChallengeResponse"); } #endregion NlmpAuthenticatePacket packet = new NlmpAuthenticatePacket(); // update flags packet.SetNegotiateFlags(negotiateFlags); // if version required, update version if (NlmpUtility.IsVersionRequired(negotiateFlags)) { packet.SetVersion(version); } // update domain name packet.SetDomainName(domainName); // update user name packet.SetUserName(userName); // if version required, update workstation if (NlmpUtility.IsVersionRequired(negotiateFlags)) { packet.SetWorkstation(workstation); } // update lmChallengeResponse packet.SetLmChallengeResponse(lmChallengeResponse); // update ntChallengeResponse packet.SetNtChallengeResponse(ntChallengeResponse); // update encryptedRandomSessionKey packet.SetEncryptedRandomSessionKey(encryptedRandomSessionKey); return packet; }
/// <summary> /// compute response /// </summary> /// <param name="flags">the flags for challenge</param> /// <param name="serverChallenge">the server challenge</param> /// <param name="targetInfo">the target info contains avpairs</param> /// <param name="responseKeyNT">the response nt key</param> /// <param name="responseKeyLM">the response lm key</param> /// <param name="lmChallengeResponse">the challenge response lm</param> /// <param name="ntChallengeResponse">the challenge response nt</param> private void ComputeResponse( NegotiateTypes flags, ulong serverChallenge, ICollection<AV_PAIR> targetInfo, byte[] responseKeyNT, byte[] responseKeyLM, out byte[] lmChallengeResponse, out byte[] ntChallengeResponse ) { // clientChallenge, a random 8 bytes. ulong clientChallenge = NlmpUtility.BytesToSecurityUInt64(NlmpUtility.Nonce(8)); // time ulong time = 0; if (!NlmpUtility.IsNtlmV1(this.client.Config.Version)) { time = NlmpUtility.GetTime(targetInfo); } byte[] sessionBaseKey = null; // compute response NlmpUtility.ComputeResponse( this.client.Config.Version, flags, responseKeyNT, responseKeyLM, serverChallenge, clientChallenge, time, NlmpUtility.AvPairCollectionGetBytes(targetInfo), out ntChallengeResponse, out lmChallengeResponse, out sessionBaseKey); // save key to context this.client.Context.SessionBaseKey = sessionBaseKey; }
/// <summary> /// this function create a negotiate packet. /// client send the negotiate packet to server to indicate the supported capabilities. /// in connection-oriented mode, this is the first packet that client send to server. /// </summary> /// <param name="negotiateFlags">this flags indicates the capabilities that client supports.</param> /// <param name="version"> /// This structure is used for debugging purposes only. In normal (non-debugging) protocol messages, it is /// ignored and does not affect the NTLM message processing. /// </param> /// <param name="domainName"> /// DomainName contains the name of the client authentication domain that MUST be encoded using the OEM /// character set. This param can not be null. /// </param> /// <param name="workstationName"> /// WorkstationName contains the name of the client machine that MUST be encoded using the OEM character /// set. Otherwise, this data is not present. This param can not be null. /// </param> /// <returns>the negotiate packet</returns> /// <exception cref="ArgumentNullException">domainName must not be null</exception> /// <exception cref="ArgumentNullException">workstationName must not be null</exception> /// <exception cref="ArgumentException"> /// when version is required, the domainName and workstationName must be string.Empty /// </exception> public NlmpNegotiatePacket CreateNegotiatePacket( NegotiateTypes negotiateFlags, VERSION version, string domainName, string workstationName ) { if (NlmpUtility.IsConnectionless(negotiateFlags)) { throw new NotSupportedException("NEGOTIATE message is not supported under Connectionless mode."); } if (domainName == null) { throw new ArgumentNullException("domainName"); } if (workstationName == null) { throw new ArgumentNullException("workstationName"); } #region Parameter validation if (NlmpUtility.IsVersionRequired(negotiateFlags)) { if (domainName.Length != 0) { throw new ArgumentException( "when version is required, the domainName should be string.Empty!", "domainName"); } if (workstationName.Length != 0) { throw new ArgumentException( "when version is required, the workstationName should be string.Empty!", "workstationName"); } } else { if (NlmpUtility.IsDomainNameSupplied(negotiateFlags) && domainName.Length == 0) { throw new ArgumentException( "when version is not required, the domainName should not be string.Empty!", "domainName"); } if (NlmpUtility.IsWorkstationSupplied(negotiateFlags) && workstationName.Length == 0) { throw new ArgumentException( "when version is not required, the workstationName should not be string.Empty!", "workstationName"); } } #endregion NlmpNegotiatePacket packet = new NlmpNegotiatePacket(); packet.SetNegotiateFlags(negotiateFlags); if (NlmpUtility.IsVersionRequired(negotiateFlags)) { packet.SetVersion(version); } else { if (NlmpUtility.IsDomainNameSupplied(negotiateFlags)) { packet.SetDomainName(domainName); } if (NlmpUtility.IsWorkstationSupplied(negotiateFlags)) { packet.SetWorkstationName(workstationName); } } return packet; }
/// <summary> /// initialize the exportedSessionKey and internal keys /// </summary> /// <param name="flags">the flags of challenge</param> /// <param name="challenge">the challenge packet</param> /// <param name="responseKeyLM">the response key lm</param> /// <param name="lmChallengeResponse">the challenge response lm</param> /// <param name="encryptedRandomSessionKey">the encrypted random session key</param> /// <param name="exportedSessionKey">the exported session key</param> private void InitializeKeys( NegotiateTypes flags, NlmpChallengePacket challenge, byte[] responseKeyLM, byte[] lmChallengeResponse, out byte[] encryptedRandomSessionKey, out byte[] exportedSessionKey ) { // keyExchangeKey byte[] keyExchangeKey = null; // get random session key NlmpUtility.GetEncryptedRandomSessionKey( this.client.Config.Version, flags, this.client.Context.SessionBaseKey, lmChallengeResponse, responseKeyLM, challenge.Payload.ServerChallenge, out encryptedRandomSessionKey, out keyExchangeKey, out exportedSessionKey); this.client.Context.ClientSigningKey = NlmpUtility.SignKey(flags, exportedSessionKey, "Client"); this.client.Context.ServerSigningKey = NlmpUtility.SignKey(flags, exportedSessionKey, "Server"); this.client.Context.ClientSealingKey = NlmpUtility.SealKey(flags, exportedSessionKey, "Client"); this.client.Context.ServerSealingKey = NlmpUtility.SealKey(flags, exportedSessionKey, "Server"); NlmpUtility.RC4Init(this.client.Context.ClientHandle, this.client.Context.ClientSealingKey); NlmpUtility.RC4Init(this.client.Context.ServerHandle, this.client.Context.ServerSealingKey); }
/// <summary> /// set the negotiate flags /// </summary> /// <param name="negotiateFlags">the new flags</param> public override void SetNegotiateFlags(NegotiateTypes negotiateFlags) { }