/// <summary>
/// Authenticates the username and password against the RADIUS server.
/// </summary>
/// <param name="username">Username to be authenticated.</param>
/// <param name="password">Password to be authenticated.</param>
/// <param name="state">State value from a previous challenge response.</param>
/// <returns>Response packet received from the server for the authentication request.</returns>
/// <remarks>
/// <para>
/// The type of response packet (if any) will be one of the following:
/// <list>
/// <item>AccessAccept: If the authentication is successful.</item>
/// <item>AccessReject: If the authentication is not successful.</item>
/// <item>AccessChallenge: If the server need more information from the user.</item>
/// </list>
/// </para>
/// <para>
/// When an AccessChallenge response packet is received from the server, it contains a State attribute
/// that must be included in the AccessRequest packet that is being sent in response to the AccessChallenge
/// response. So if this method returns an AccessChallenge packet, then this method is to be called again
/// with the requested information (from ReplyMessage attribute) in the password field and the value State
/// attribute.
/// </para>
/// </remarks>
public RadiusPacket Authenticate(string username, string password, byte[] state)
{
CheckDisposed();
if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
{
throw new ArgumentException("Username and Password cannot be null.");
}
RadiusPacket request = new RadiusPacket(PacketType.AccessRequest);
byte[] authenticator = RadiusPacket.CreateRequestAuthenticator(m_sharedSecret);
request.Authenticator = authenticator;
request.Attributes.Add(new RadiusPacketAttribute(AttributeType.UserName, username));
request.Attributes.Add(new RadiusPacketAttribute(AttributeType.UserPassword, RadiusPacket.EncryptPassword(password, m_sharedSecret, authenticator)));
// State attribute is used when responding to a AccessChallenge response.
if ((object)state != null)
{
request.Attributes.Add(new RadiusPacketAttribute(AttributeType.State, state));
}
return(ProcessRequest(request));
}