package org.mailster.smtp.core.auth.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;
import org.mailster.smtp.core.SMTPContext;
import org.mailster.smtp.core.auth.AuthenticationHandler;
import org.mailster.smtp.core.auth.Credential;
import org.mailster.smtp.core.auth.LoginFailedException;
import org.mailster.smtp.core.auth.LoginValidator;
import org.mailster.smtp.util.Base64;
/**
* Implements the SMTP AUTH LOGIN mechanism.<br />
* You are only required to plug your LoginValidator implementation
* for username and password validation to take effect.
*
* @author Marco Trevisan <mrctrevisan@yahoo.it>
* @author De Oliveira Edouard <doe_wanted@yahoo.fr>
*/
public class LoginAuthenticationHandler implements AuthenticationHandler
{
private String username;
private String password;
private LoginValidator helper;
private List<String> authentificationMechanisms;
/** Creates a new instance of LoginAuthenticationHandler */
public LoginAuthenticationHandler(LoginValidator helper)
{
this.helper = helper;
authentificationMechanisms = new ArrayList<String>(1);
authentificationMechanisms.add("LOGIN");
}
/**
*
*/
public List<String> getAuthenticationMechanisms()
{
return Collections.unmodifiableList(authentificationMechanisms);
}
/**
*
*/
public boolean auth(String clientInput, StringBuilder response, SMTPContext ctx)
throws LoginFailedException
{
StringTokenizer stk = new StringTokenizer(clientInput);
String token = stk.nextToken();
if (token.trim().equalsIgnoreCase("AUTH"))
{
// The RFC2554 "initial-response" parameter must not be present
// The line must be in the form of "AUTH LOGIN"
if (!stk.nextToken().trim().equalsIgnoreCase("LOGIN"))
{
// Mechanism mismatch
response.append("504 AUTH mechanism mismatch");
return true;
}
if (stk.hasMoreTokens())
{
// the client submitted an initial response
response.append("535 Initial response not allowed in AUTH LOGIN");
return true;
}
response.append("334 ").append(Base64.encodeToString("Username:".getBytes(), false));
return false;
}
if (username == null)
{
byte[] decoded = Base64.decode(clientInput);
if (decoded == null)
{
throw new LoginFailedException();
}
this.username = new String(decoded);
response.append("334 ").append(Base64.encodeToString("Password:".getBytes(), false));
return false;
}
byte[] decoded = Base64.decode(clientInput);
if (decoded == null)
{
throw new LoginFailedException();
}
this.password = new String(decoded);
try
{
helper.login(username, password);
resetState();
}
catch (LoginFailedException lfe)
{
resetState();
throw lfe;
}
ctx.setCredential(new Credential(username));
return true;
}
/**
*
*/
public void resetState()
{
this.username = null;
this.password = null;
}
}