commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From s...@apache.org
Subject svn commit: r1076369 - in /commons/proper/net/trunk/src: changes/changes.xml main/java/org/apache/commons/net/pop3/ExtendedPOP3Client.java main/java/org/apache/commons/net/pop3/POP3.java main/java/org/apache/commons/net/pop3/POP3Reply.java
Date Wed, 02 Mar 2011 20:40:37 GMT
Author: sebb
Date: Wed Mar  2 20:40:36 2011
New Revision: 1076369

URL: http://svn.apache.org/viewvc?rev=1076369&view=rev
Log:
NET-352 SASL PLAIN & CRAM-MD5 authentication

Added:
    commons/proper/net/trunk/src/main/java/org/apache/commons/net/pop3/ExtendedPOP3Client.java
  (with props)
Modified:
    commons/proper/net/trunk/src/changes/changes.xml
    commons/proper/net/trunk/src/main/java/org/apache/commons/net/pop3/POP3.java
    commons/proper/net/trunk/src/main/java/org/apache/commons/net/pop3/POP3Reply.java

Modified: commons/proper/net/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/changes/changes.xml?rev=1076369&r1=1076368&r2=1076369&view=diff
==============================================================================
--- commons/proper/net/trunk/src/changes/changes.xml (original)
+++ commons/proper/net/trunk/src/changes/changes.xml Wed Mar  2 20:40:36 2011
@@ -54,6 +54,9 @@ The <action> type attribute can be add,u
 
     <body>
         <release version="3.0" date="TBA" description="TBA">
+            <action issue="NET-352" dev="sebb" type="add" due-to="Bogdan Drozdowski" due-to-email="bogdandr
# op . pl">
+            SASL PLAIN & CRAM-MD5 authentication.
+            </action>
             <action issue="NET-357" dev="sebb" type="add" due-to="Bogdan Drozdowski" due-to-email="bogdandr
# op . pl">
             The POP3 client does not support SSL/TLS connections.
             </action>

Added: commons/proper/net/trunk/src/main/java/org/apache/commons/net/pop3/ExtendedPOP3Client.java
URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/main/java/org/apache/commons/net/pop3/ExtendedPOP3Client.java?rev=1076369&view=auto
==============================================================================
--- commons/proper/net/trunk/src/main/java/org/apache/commons/net/pop3/ExtendedPOP3Client.java
(added)
+++ commons/proper/net/trunk/src/main/java/org/apache/commons/net/pop3/ExtendedPOP3Client.java
Wed Mar  2 20:40:36 2011
@@ -0,0 +1,161 @@
+/*
+ * 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.commons.net.pop3;
+
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.commons.net.pop3.POP3Client;
+import org.apache.commons.net.pop3.POP3Reply;
+import org.apache.commons.net.util.Base64;
+
+
+/**
+ * A POP3 Cilent class with protocol and authentication extensions support
+ * (RFC2449 and RFC2195).
+ * @see POP3Client
+ */
+public class ExtendedPOP3Client extends POP3SClient
+{
+    /** The CAPA command. */
+    public static final String capaCommand = "CAPA";
+    /** The AUTH command. */
+    public static final String authCommand = "AUTH";
+
+    /**
+     * The default ExtendedPOP3Client constructor.
+     * Creates a new Extended POP3 Client.
+     * @throws NoSuchAlgorithmException 
+     */
+    public ExtendedPOP3Client() throws NoSuchAlgorithmException
+    {
+        super();
+    }
+
+    /***
+     * Send a CAPA command to the POP3 server.
+     * @return True if the command was successful, false if not.
+     * @exception IOException If a network I/O error occurs in the process of
+     *        sending the NOOP command.
+     ***/
+    public boolean capa() throws IOException
+    {
+        return (sendCommand(capaCommand) == POP3Reply.OK);
+    }
+
+    /***
+     * Authenticate to the POP3 server by sending the AUTH command with the
+     * selected mechanism, using the given username and the given password.
+     * <p>
+     * @return True if successfully completed, false if not.
+     * @exception IOException  If an I/O error occurs while either sending a
+     *      command to the server or receiving a reply from the server.
+     * @exception NoSuchAlgorithmException If the CRAM hash algorithm
+     *      cannot be instantiated by the Java runtime system.
+     * @exception InvalidKeyException If the CRAM hash algorithm
+     *      failed to use the given password.
+     * @exception InvalidKeySpecException If the CRAM hash algorithm
+     *      failed to use the given password.
+     ***/
+    public boolean auth(ExtendedPOP3Client.AUTH_METHOD method,
+                        String username, String password)
+                        throws IOException, NoSuchAlgorithmException,
+                        InvalidKeyException, InvalidKeySpecException
+    {
+        if (sendCommand(authCommand + " " + AUTH_METHOD.getAuthName(method))
+        != POP3Reply.OK_INT) return false;
+
+        if (method.equals(AUTH_METHOD.PLAIN))
+        {
+            // the server sends an empty response ("+ "), so we don't have to read it.
+            return sendCommand(
+                new String(
+                    Base64.encodeBase64(("\000" + username + "\000" + password).getBytes())
+                    )
+                ) == POP3Reply.OK;
+        }
+        else if (method.equals(AUTH_METHOD.CRAM_MD5))
+        {
+            // get the CRAM challenge
+            byte[] serverChallenge = Base64.decodeBase64(getReplyString().substring(2).trim());
+            // get the Mac instance
+            Mac hmac_md5 = Mac.getInstance("HmacMD5");
+            hmac_md5.init(new SecretKeySpec(password.getBytes(), "HmacMD5"));
+            // compute the result:
+            byte[] hmacResult = _convertToHexString(hmac_md5.doFinal(serverChallenge)).getBytes();
+            // join the byte arrays to form the reply
+            byte[] usernameBytes = username.getBytes();
+            byte[] toEncode = new byte[usernameBytes.length + 1 /* the space */ + hmacResult.length];
+            System.arraycopy(usernameBytes, 0, toEncode, 0, usernameBytes.length);
+            toEncode[usernameBytes.length] = ' ';
+            System.arraycopy(hmacResult, 0, toEncode, usernameBytes.length + 1, hmacResult.length);
+            // send the reply and read the server code:
+            return sendCommand(new String(Base64.encodeBase64(toEncode))) == POP3Reply.OK;
+        }
+        else return false; // safety check
+    }
+
+    /**
+     * Converts the given byte array to a String containing the hex values of the bytes.
+     * For example, the byte 'A' will be converted to '41', because this is the ASCII code
+     * (and the byte value) of the capital letter 'A'.
+     * @param a The byte array to convert.
+     * @return The resulting String of hex codes.
+     */
+    private String _convertToHexString(byte[] a)
+    {
+        String result = "";
+        for (int i = 0; i < a.length; i++)
+        {
+            if ( (a[i] & 0x0FF) <= 15 ) result += "0";
+            result += Integer.toHexString(a[i] & 0x0FF);
+        }
+        return result;
+    }
+
+    /**
+     * The enumeration of currently-supported authentication methods.
+     */
+    public static enum AUTH_METHOD
+    {
+        /** The standarised (RFC4616) PLAIN method, which sends the password unencrypted
(insecure). */
+        PLAIN("PLAIN"),
+
+        /** The standarised (RFC2195) CRAM-MD5 method, which doesn't send the password (secure).
*/
+        CRAM_MD5("CRAM_MD5");
+
+        private final String methodName;
+
+        AUTH_METHOD(String methodName){
+            this.methodName = methodName;
+        }
+        /**
+         * Gets the name of the given authentication method suitable for the server.
+         * @param method The authentication method to get the name for.
+         * @return The name of the given authentication method suitable for the server.
+         */
+        public static final String getAuthName(AUTH_METHOD method)
+        {
+            return method.methodName;
+        }
+    }
+}

Propchange: commons/proper/net/trunk/src/main/java/org/apache/commons/net/pop3/ExtendedPOP3Client.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/net/trunk/src/main/java/org/apache/commons/net/pop3/ExtendedPOP3Client.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Modified: commons/proper/net/trunk/src/main/java/org/apache/commons/net/pop3/POP3.java
URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/main/java/org/apache/commons/net/pop3/POP3.java?rev=1076369&r1=1076368&r2=1076369&view=diff
==============================================================================
--- commons/proper/net/trunk/src/main/java/org/apache/commons/net/pop3/POP3.java (original)
+++ commons/proper/net/trunk/src/main/java/org/apache/commons/net/pop3/POP3.java Wed Mar 
2 20:40:36 2011
@@ -70,6 +70,8 @@ public class POP3 extends SocketClient
     public static final int UPDATE_STATE = 2;
 
     static final String _OK = "+OK";
+    // The reply indicating intermediate response to a command.
+    static final String _OK_INT = "+ ";
     static final String _ERROR = "-ERR";
 
     // We have to ensure that the protocol communication is in ASCII
@@ -121,6 +123,8 @@ public class POP3 extends SocketClient
             _replyCode = POP3Reply.OK;
         else if (line.startsWith(_ERROR))
             _replyCode = POP3Reply.ERROR;
+        else if (line.startsWith(_OK_INT))
+            _replyCode = POP3Reply.OK_INT;
         else
             throw new
             MalformedServerReplyException(
@@ -242,7 +246,7 @@ public class POP3 extends SocketClient
      * <p>
      * @param command  The POP3 command to send.
      * @param args     The command arguments.
-     * @return  The server reply code (either POP3Reply.OK or POP3Reply.ERROR).
+     * @return  The server reply code (either POP3Reply.OK, POP3Reply.ERROR or POP3Reply.OK_INT).
      ***/
     public int sendCommand(String command, String args) throws IOException
     {
@@ -273,7 +277,7 @@ public class POP3 extends SocketClient
      * reply code.
      * <p>
      * @param command  The POP3 command to send.
-     * @return  The server reply code (either POP3Reply.OK or POP3Reply.ERROR).
+     * @return  The server reply code (either POP3Reply.OK, POP3Reply.ERROR or POP3Reply.OK_INT).
      ***/
     public int sendCommand(String command) throws IOException
     {
@@ -286,7 +290,7 @@ public class POP3 extends SocketClient
      * @param command  The POP3 command to send
      *                  (one of the POP3Command constants).
      * @param args     The command arguments.
-     * @return  The server reply code (either POP3Reply.OK or POP3Reply.ERROR).
+     * @return  The server reply code (either POP3Reply.OK, POP3Reply.ERROR or POP3Reply.OK_INT).
      ***/
     public int sendCommand(int command, String args) throws IOException
     {
@@ -299,7 +303,7 @@ public class POP3 extends SocketClient
      * <p>
      * @param command  The POP3 command to send
      *                  (one of the POP3Command constants).
-     * @return  The server reply code (either POP3Reply.OK or POP3Reply.ERROR).
+     * @return  The server reply code (either POP3Reply.OK, POP3Reply.ERROR or POP3Reply.OK_INT).
      ***/
     public int sendCommand(int command) throws IOException
     {

Modified: commons/proper/net/trunk/src/main/java/org/apache/commons/net/pop3/POP3Reply.java
URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/main/java/org/apache/commons/net/pop3/POP3Reply.java?rev=1076369&r1=1076368&r2=1076369&view=diff
==============================================================================
--- commons/proper/net/trunk/src/main/java/org/apache/commons/net/pop3/POP3Reply.java (original)
+++ commons/proper/net/trunk/src/main/java/org/apache/commons/net/pop3/POP3Reply.java Wed
Mar  2 20:40:36 2011
@@ -32,6 +32,9 @@ public final class POP3Reply
     /*** The reply code indicating failure of an operation. ***/
     public static final int ERROR = 1;
 
+    /** The reply code indicating intermediate response to a command. */
+    public static final int OK_INT = 2;
+
     // Cannot be instantiated.
     private POP3Reply()
     {}



Mime
View raw message