You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by no...@apache.org on 2012/01/12 15:17:36 UTC
svn commit: r1230560 - in /james/protocols/trunk:
api/src/main/java/org/apache/james/protocols/api/
pop3/src/main/java/org/apache/james/protocols/pop3/
pop3/src/main/java/org/apache/james/protocols/pop3/core/
pop3/src/test/java/org/apache/james/protoco...
Author: norman
Date: Thu Jan 12 14:17:35 2012
New Revision: 1230560
URL: http://svn.apache.org/viewvc?rev=1230560&view=rev
Log:
Add support for APOP. See PROTOCOL-87
Added:
james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/AbstractApopCmdHandler.java
Modified:
james/protocols/trunk/api/src/main/java/org/apache/james/protocols/api/ProtocolConfigurationImpl.java
james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/POP3ProtocolHandlerChain.java
james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/POP3Session.java
james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/AbstractPassCmdHandler.java
james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/WelcomeMessageHandler.java
james/protocols/trunk/pop3/src/test/java/org/apache/james/protocols/pop3/POP3ServerTest.java
Modified: james/protocols/trunk/api/src/main/java/org/apache/james/protocols/api/ProtocolConfigurationImpl.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/api/src/main/java/org/apache/james/protocols/api/ProtocolConfigurationImpl.java?rev=1230560&r1=1230559&r2=1230560&view=diff
==============================================================================
--- james/protocols/trunk/api/src/main/java/org/apache/james/protocols/api/ProtocolConfigurationImpl.java (original)
+++ james/protocols/trunk/api/src/main/java/org/apache/james/protocols/api/ProtocolConfigurationImpl.java Thu Jan 12 14:17:35 2012
@@ -19,6 +19,9 @@
package org.apache.james.protocols.api;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
/**
* Default implementation of a {@link ProtocolConfiguration} which allows to easily set the different configurations.
@@ -31,14 +34,29 @@ public class ProtocolConfigurationImpl i
private String greeting;
private String softwareName = "JAMES Protocols Server";
- private String helloName = "localhost";
+ private String helloName = null;
+ private static final String DEFAULT_HELLO_NAME;
+
+ static {
+ String hName;
+ try {
+ hName = InetAddress.getLocalHost().getHostName();
+ } catch (UnknownHostException e) {
+ hName = "localhost";
+ }
+ DEFAULT_HELLO_NAME = hName;
+ }
/*
+ *
* (non-Javadoc)
*
* @see org.apache.james.protocols.pop3.POP3Configuration#getHelloName()
*/
public String getHelloName() {
+ if (helloName == null) {
+ return DEFAULT_HELLO_NAME;
+ }
return helloName;
}
Modified: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/POP3ProtocolHandlerChain.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/POP3ProtocolHandlerChain.java?rev=1230560&r1=1230559&r2=1230560&view=diff
==============================================================================
--- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/POP3ProtocolHandlerChain.java (original)
+++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/POP3ProtocolHandlerChain.java Thu Jan 12 14:17:35 2012
@@ -54,24 +54,28 @@ public class POP3ProtocolHandlerChain ex
}
/**
- * The {@link AbstractPassCmdHandler} to use. If a <code>not null</code> {@link AbstractPassCmdHandler} is given, the {@link POP3ProtocolHandlerChain}
+ * The {@link AbstractPassCmdHandler}'s to use. If at least one {@link AbstractPassCmdHandler} is given, the {@link POP3ProtocolHandlerChain}
* will add all default handlers
*
- * @param passHandler
+ * @param authHandlers
* @throws WiringException
*/
- public POP3ProtocolHandlerChain(AbstractPassCmdHandler passHandler) throws WiringException {
- if (passHandler != null) {
- addAll(initDefaultHandlers(passHandler));
+ public POP3ProtocolHandlerChain(AbstractPassCmdHandler... authHandlers) throws WiringException {
+ if (authHandlers != null && authHandlers.length > 0) {
+ addAll(initDefaultHandlers(authHandlers));
wireExtensibleHandlers();
}
}
- protected List<ProtocolHandler> initDefaultHandlers(AbstractPassCmdHandler passHandler) {
+ protected List<ProtocolHandler> initDefaultHandlers(AbstractPassCmdHandler... authHandlers) {
List<ProtocolHandler> handlers = new ArrayList<ProtocolHandler>();
+ // add all pass handlers
+ for (AbstractPassCmdHandler handler: authHandlers) {
+ handlers.add(handler);
+ }
+
handlers.add(new CapaCmdHandler());
handlers.add(new UserCmdHandler());
- handlers.add(passHandler);
handlers.add(new ListCmdHandler());
handlers.add(new UidlCmdHandler());
handlers.add(new RsetCmdHandler());
Modified: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/POP3Session.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/POP3Session.java?rev=1230560&r1=1230559&r2=1230560&view=diff
==============================================================================
--- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/POP3Session.java (original)
+++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/POP3Session.java Thu Jan 12 14:17:35 2012
@@ -30,6 +30,7 @@ public interface POP3Session extends Pro
final static String UID_LIST = "UID_LIST";
final static String DELETED_UID_LIST = "DELETED_UID_LIST";
+ final static String APOP_TIMESTAMP = "APOP_TIMESTAMP";
// Authentication states for the POP3 interaction
/** Waiting for user id */
Added: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/AbstractApopCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/AbstractApopCmdHandler.java?rev=1230560&view=auto
==============================================================================
--- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/AbstractApopCmdHandler.java (added)
+++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/AbstractApopCmdHandler.java Thu Jan 12 14:17:35 2012
@@ -0,0 +1,103 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.protocols.pop3.core;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.james.protocols.api.ProtocolSession.State;
+import org.apache.james.protocols.api.Request;
+import org.apache.james.protocols.api.Response;
+import org.apache.james.protocols.pop3.POP3Response;
+import org.apache.james.protocols.pop3.POP3Session;
+import org.apache.james.protocols.pop3.mailbox.Mailbox;
+
+/**
+ * Handles the APOP command
+ *
+ * @author Maurer
+ *
+ */
+public abstract class AbstractApopCmdHandler extends AbstractPassCmdHandler{
+
+ private static final Collection<String> COMMANDS = Collections.unmodifiableCollection(Arrays.asList("APOP"));
+
+ @Override
+ public Response onCommand(POP3Session session, Request request) {
+ if (session.getAttachment(POP3Session.APOP_TIMESTAMP, State.Connection) == null) {
+ // APOP timestamp was not found in the session so APOP is not supported
+ return POP3Response.ERR;
+ }
+
+ String parameters = request.getArgument();
+ String parts[] = null;
+ boolean syntaxError = false;
+ if (parameters != null) {
+ parts = parameters.split(" ");
+ if (parts.length != 2) {
+ syntaxError = true;
+ }
+ } else {
+ syntaxError = true;
+ }
+ if (!syntaxError && session.getHandlerState() == POP3Session.AUTHENTICATION_READY) {
+
+ Response response = doAuth(session, parts[0], parts[1]);
+
+ if (POP3Response.OK_RESPONSE.equals(response.getRetCode())) {
+ // the auth was successful so set the user
+ session.setUser(parts[0]);
+ }
+ return response;
+ } else {
+ session.setHandlerState(POP3Session.AUTHENTICATION_READY);
+ return AUTH_FAILED;
+ }
+
+ }
+
+ @Override
+ public Collection<String> getImplCommands() {
+ return COMMANDS;
+ }
+
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.james.protocols.pop3.core.AbstractPassCmdHandler#auth(org.apache.james.protocols.pop3.POP3Session, java.lang.String, java.lang.String)
+ */
+ protected final Mailbox auth(POP3Session session, String username, String password) throws Exception {
+ return auth(session, (String)session.getAttachment(POP3Session.APOP_TIMESTAMP, State.Connection), username, password);
+ }
+
+
+ /**
+ * Authenticate a {@link POP3Session} and returns the {@link Mailbox} for it. If it can not get authenticated it will return <code>null</code>.
+ *
+ * @param session
+ * @param apopTimestamp
+ * @param user
+ * @param digest
+ * @return mailbox
+ * @throws Exception
+ */
+ protected abstract Mailbox auth(POP3Session session, String apopTimestamp, String user, String digest) throws Exception;
+}
Modified: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/AbstractPassCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/AbstractPassCmdHandler.java?rev=1230560&r1=1230559&r2=1230560&view=diff
==============================================================================
--- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/AbstractPassCmdHandler.java (original)
+++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/AbstractPassCmdHandler.java Thu Jan 12 14:17:35 2012
@@ -36,7 +36,7 @@ import org.apache.james.protocols.pop3.m
public abstract class AbstractPassCmdHandler extends RsetCmdHandler {
private static final Collection<String> COMMANDS = Collections.unmodifiableCollection(Arrays.asList("PASS"));
private static final Response UNEXPECTED_ERROR = new POP3Response(POP3Response.ERR_RESPONSE, "Unexpected error accessing mailbox").immutable();
- private static final Response AUTH_FAILED = new POP3Response(POP3Response.ERR_RESPONSE, "Authentication failed.").immutable();
+ protected static final Response AUTH_FAILED = new POP3Response(POP3Response.ERR_RESPONSE, "Authentication failed.").immutable();
/**
* Handler method called upon receipt of a PASS command. Reads in and
@@ -44,33 +44,45 @@ public abstract class AbstractPassCmdHan
*/
public Response onCommand(POP3Session session, Request request) {
String parameters = request.getArgument();
- POP3Response response = null;
if (session.getHandlerState() == POP3Session.AUTHENTICATION_USERSET && parameters != null) {
- String passArg = parameters;
- try {
- Mailbox mailbox = auth(session, passArg);
- if (mailbox != null) {
- session.setUserMailbox(mailbox);
- stat(session);
-
- StringBuilder responseBuffer = new StringBuilder(64).append("Welcome ").append(session.getUser());
- response = new POP3Response(POP3Response.OK_RESPONSE, responseBuffer.toString());
- session.setHandlerState(POP3Session.TRANSACTION);
- } else {
- session.setHandlerState(POP3Session.AUTHENTICATION_READY);
- return AUTH_FAILED;
- }
- } catch (Exception e) {
- session.getLogger().error("Unexpected error accessing mailbox for " + session.getUser(), e);
- session.setHandlerState(POP3Session.AUTHENTICATION_READY);
- return UNEXPECTED_ERROR;
- }
+ return doAuth(session, session.getUser(), parameters);
} else {
session.setHandlerState(POP3Session.AUTHENTICATION_READY);
return AUTH_FAILED;
}
+ }
+
+
+ /**
+ * Authenticate a user and return the {@link Response}
+ *
+ * @param session
+ * @param user
+ * @param pass
+ * @return response
+ */
+ protected final Response doAuth(POP3Session session, String user, String pass) {
+ try {
+ Mailbox mailbox = auth(session, user, pass);
- return response;
+ if (mailbox != null) {
+ session.setUserMailbox(mailbox);
+ stat(session);
+
+ session.setHandlerState(POP3Session.TRANSACTION);
+
+
+ StringBuilder responseBuffer = new StringBuilder(64).append("Welcome ").append(session.getUser());
+ return new POP3Response(POP3Response.OK_RESPONSE, responseBuffer.toString());
+ } else {
+ session.setHandlerState(POP3Session.AUTHENTICATION_READY);
+ return AUTH_FAILED;
+ }
+ } catch (Exception e) {
+ session.getLogger().error("Unexpected error accessing mailbox for " + session.getUser(), e);
+ session.setHandlerState(POP3Session.AUTHENTICATION_READY);
+ return UNEXPECTED_ERROR;
+ }
}
/**
@@ -84,9 +96,10 @@ public abstract class AbstractPassCmdHan
* Authenticate a {@link POP3Session} and returns the {@link Mailbox} for it. If it can not get authenticated it will return <code>null</code>.
*
* @param session
+ * @param user
* @param password
* @return mailbox
*
*/
- protected abstract Mailbox auth(POP3Session session, String password) throws Exception;
+ protected abstract Mailbox auth(POP3Session session, String username, String password) throws Exception;
}
Modified: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/WelcomeMessageHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/WelcomeMessageHandler.java?rev=1230560&r1=1230559&r2=1230560&view=diff
==============================================================================
--- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/WelcomeMessageHandler.java (original)
+++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/WelcomeMessageHandler.java Thu Jan 12 14:17:35 2012
@@ -19,7 +19,7 @@
package org.apache.james.protocols.pop3.core;
-
+import org.apache.james.protocols.api.ProtocolSession.State;
import org.apache.james.protocols.api.Response;
import org.apache.james.protocols.api.handler.ConnectHandler;
import org.apache.james.protocols.pop3.POP3Response;
@@ -33,11 +33,19 @@ public class WelcomeMessageHandler imple
*/
public Response onConnect(POP3Session session) {
StringBuilder responseBuffer = new StringBuilder();
- // Initially greet the connector
- // Format is: Sat, 24 Jan 1998 13:16:09 -0500
- responseBuffer.append(session.getConfiguration().getHelloName()).append(" POP3 server (").append(session.getConfiguration().getSoftwareName()).append(") ready ");
+
+ // Generate the timestamp which can be also used with APOP. See RFC1939 APOP
+ responseBuffer.append("<").append(session.getSessionID()).append(".").append(System.currentTimeMillis()).append("@").append(session.getConfiguration().getHelloName()).append("> ");
+
+ // store the timestamp for later usage
+ session.setAttachment(POP3Session.APOP_TIMESTAMP, responseBuffer.toString(), State.Connection);
+
+ // complete the response banner and send it back to the client
+ responseBuffer.append("POP3 server (").append(session.getConfiguration().getSoftwareName()).append(") ready ");
POP3Response response = new POP3Response(POP3Response.OK_RESPONSE, responseBuffer.toString());
return response;
}
+
+
}
Modified: james/protocols/trunk/pop3/src/test/java/org/apache/james/protocols/pop3/POP3ServerTest.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/test/java/org/apache/james/protocols/pop3/POP3ServerTest.java?rev=1230560&r1=1230559&r2=1230560&view=diff
==============================================================================
--- james/protocols/trunk/pop3/src/test/java/org/apache/james/protocols/pop3/POP3ServerTest.java (original)
+++ james/protocols/trunk/pop3/src/test/java/org/apache/james/protocols/pop3/POP3ServerTest.java Thu Jan 12 14:17:35 2012
@@ -39,8 +39,10 @@ import java.util.concurrent.atomic.Atomi
import org.apache.commons.net.pop3.POP3Client;
import org.apache.commons.net.pop3.POP3MessageInfo;
+import org.apache.commons.net.pop3.POP3Reply;
import org.apache.james.protocols.api.handler.WiringException;
import org.apache.james.protocols.netty.NettyServer;
+import org.apache.james.protocols.pop3.core.AbstractApopCmdHandler;
import org.apache.james.protocols.pop3.core.AbstractPassCmdHandler;
import org.apache.james.protocols.pop3.mailbox.Mailbox;
import org.apache.james.protocols.pop3.mailbox.MessageMetaData;
@@ -462,6 +464,42 @@ public class POP3ServerTest {
}
}
+
+
+ @Test
+ public void testAPop() throws Exception {
+ InetSocketAddress address = new InetSocketAddress("127.0.0.1", TestUtils.getFreePort());
+
+ NettyServer server = null;
+ try {
+ TestApopCmdHandler handler = new TestApopCmdHandler();
+ server = new NettyServer(createProtocol(handler));
+ server.setListenAddresses(address);
+ server.bind();
+
+ POP3Client client = new POP3Client();
+ client.connect(address.getAddress().getHostAddress(), address.getPort());
+ String welcomeMessage = client.getReplyString();
+
+ // check for valid syntax that include all info needed for APOP
+ assertTrue(welcomeMessage.trim().matches("\\+OK \\<\\d+\\.\\d+@.+\\> .+"));
+
+ int reply = client.sendCommand("APOP invalid invalid");
+ assertEquals(POP3Reply.ERROR, reply);
+
+ handler.add("valid", new MockMailbox("id"));
+ reply = client.sendCommand("APOP valid valid");
+ assertEquals(POP3Reply.OK, reply);
+
+ assertTrue(client.logout());
+
+ } finally {
+ if (server != null) {
+ server.unbind();
+ }
+ }
+
+ }
private void checkMessage(Message message, Reader reader) throws IOException {
int read = 0;
int i = -1;
@@ -503,12 +541,26 @@ public class POP3ServerTest {
public void add(String username, Mailbox mailbox) {
mailboxes.put(username, mailbox);
}
+
+ protected Mailbox auth(POP3Session session, String username, String password) throws Exception{
+ return mailboxes.get(username);
+ }
- @Override
- protected Mailbox auth(POP3Session session, String password) {
- return mailboxes.get(session.getUser());
+
+ }
+
+ private final class TestApopCmdHandler extends AbstractApopCmdHandler {
+ private final Map<String, Mailbox> mailboxes = new HashMap<String, Mailbox>();
+
+ public void add(String username, Mailbox mailbox) {
+ mailboxes.put(username, mailbox);
}
+ @Override
+ protected Mailbox auth(POP3Session session, String apopTimestamp, String user, String digest) throws Exception {
+ return mailboxes.get(user);
+ }
+
}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org