/// <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> /// 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> /// read struct from bytes. All sub class override this to unmarshal itself. /// </summary> /// <param name="start">the start to read bytes</param> /// <param name="packetBytes">the bytes of struct</param> /// <returns>the read result, if success, return true.</returns> protected override bool ReadStructFromBytes( byte[] packetBytes, int start ) { AUTHENTICATE_MESSAGE authenticate = new AUTHENTICATE_MESSAGE(); authenticate.LmChallengeResponseFields = NlmpUtility.BytesToStruct <MESSAGE_FIELDS>( packetBytes, ref start); authenticate.NtChallengeResponseFields = NlmpUtility.BytesToStruct <MESSAGE_FIELDS>( packetBytes, ref start); authenticate.DomainNameFields = NlmpUtility.BytesToStruct <MESSAGE_FIELDS>( packetBytes, ref start); authenticate.UserNameFields = NlmpUtility.BytesToStruct <MESSAGE_FIELDS>( packetBytes, ref start); authenticate.WorkstationFields = NlmpUtility.BytesToStruct <MESSAGE_FIELDS>( packetBytes, ref start); authenticate.EncryptedRandomSessionKeyFields = NlmpUtility.BytesToStruct <MESSAGE_FIELDS>( packetBytes, ref start); authenticate.NegotiateFlags = (NegotiateTypes)NlmpUtility.BytesToStruct <uint>( packetBytes, ref start); authenticate.Version = NlmpUtility.BytesToStruct <VERSION>( packetBytes, ref start); authenticate.MIC = NlmpUtility.ReadBytes( packetBytes, ref start, NlmpUtility.AUTHENTICATE_MESSAGE_MIC_CONST_SIZE); int currentIndex = 0; while (currentIndex != start) { currentIndex = start; if (authenticate.DomainNameFields.Len != 0 && authenticate.DomainNameFields.BufferOffset == start) { authenticate.DomainName = NlmpUtility.ReadBytes( packetBytes, ref start, authenticate.DomainNameFields.Len); continue; } else if (authenticate.EncryptedRandomSessionKeyFields.Len != 0 && authenticate.EncryptedRandomSessionKeyFields.BufferOffset == start) { authenticate.EncryptedRandomSessionKey = NlmpUtility.ReadBytes( packetBytes, ref start, authenticate.EncryptedRandomSessionKeyFields.Len); continue; } else if (authenticate.LmChallengeResponseFields.Len != 0 && authenticate.LmChallengeResponseFields.BufferOffset == start) { authenticate.LmChallengeResponse = NlmpUtility.ReadBytes( packetBytes, ref start, authenticate.LmChallengeResponseFields.Len); continue; } else if (authenticate.NtChallengeResponseFields.Len != 0 && authenticate.NtChallengeResponseFields.BufferOffset == start) { authenticate.NtChallengeResponse = NlmpUtility.ReadBytes( packetBytes, ref start, authenticate.NtChallengeResponseFields.Len); continue; } else if (authenticate.UserNameFields.Len != 0 && authenticate.UserNameFields.BufferOffset == start) { authenticate.UserName = NlmpUtility.ReadBytes( packetBytes, ref start, authenticate.UserNameFields.Len); continue; } else if (authenticate.WorkstationFields.Len != 0 && authenticate.WorkstationFields.BufferOffset == start) { authenticate.Workstation = NlmpUtility.ReadBytes( packetBytes, ref start, authenticate.WorkstationFields.Len); continue; } else { break; } } this.payload = authenticate; return(true); }