package org.mailster.smtp.core.commands.impl; import java.io.IOException; import org.apache.mina.core.session.IoSession; import org.mailster.smtp.core.SMTPContext; import org.mailster.smtp.core.SMTPState; import org.mailster.smtp.core.auth.LoginFailedException; import org.mailster.smtp.core.commands.AbstractCommand; /** * The AUTH command implementation. * * @author De Oliveira Edouard <doe_wanted@yahoo.fr> * @author Marco Trevisan <mrctrevisan@yahoo.it> */ public class AuthCommand extends AbstractCommand { public static final String VERB = "AUTH"; public static final String AUTH_CANCEL_COMMAND = "*"; /** Creates a new instance of AuthCommand */ public AuthCommand() { super(VERB, "The AUTH command allow to select the authentication mechanism to use\n"+ "when authenticating with the server", "<mechanism> [<initial-response>]\n" + " mechanism = a string identifying a SASL authentication mechanism,\n" + " initial-response = an optional base64-encoded response"); } @Override public boolean isAuthRequired() { return false; } public void execute(String commandString, IoSession ioSession, SMTPContext ctx) throws IOException { SMTPState smtpState = ctx.getSMTPState(); if (smtpState.isAuthenticated()) { sendResponse(ioSession, "503 Refusing any other AUTH command"); return; } boolean authenticating = smtpState.isAuthenticating(); if (!authenticating) { String[] args = getArgs(commandString); // Let's check the command syntax if (args.length < 2) { sendResponse(ioSession, "501 Syntax: " + VERB + " mechanism [initial-response]"); return; } // Let's check if we support the required authentication mechanism String mechanism = args[1]; if (!ctx.getAuthenticationHandler().getAuthenticationMechanisms().contains( mechanism.toUpperCase())) { sendResponse(ioSession, "504 Unrecognized authentication type"); return; } } // OK, let's go trough the authentication process. // The authentication process may require a series of // challenge-responses try { if (authenticating && commandString.trim().equals(AUTH_CANCEL_COMMAND)) { // RFC 2554 explicitly states this: sendResponse(ioSession, "501 Authentication canceled by client"); return; } StringBuilder response = new StringBuilder(); boolean finished = ctx.getAuthenticationHandler().auth(commandString, response, ctx); smtpState.setAuthenticating(!finished); if (!finished) { // challenge-response iteration sendResponse(ioSession, response.toString()); return; } smtpState.setAuthenticated(true); sendResponse(ioSession, "235 Authentication successful"); } catch (LoginFailedException ex) { sendResponse(ioSession, "535 Authentication failure"); smtpState.setAuthenticated(false); smtpState.setAuthenticating(false); } } }