commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From s...@apache.org
Subject svn commit: r1074008 - in /commons/proper/net/trunk/src: changes/changes.xml main/java/org/apache/commons/net/smtp/SMTPSClient.java main/java/org/apache/commons/net/smtp/SMTPSTrustManager.java
Date Thu, 24 Feb 2011 01:40:26 GMT
Author: sebb
Date: Thu Feb 24 01:40:26 2011
New Revision: 1074008

URL: http://svn.apache.org/viewvc?rev=1074008&view=rev
Log:
NET-356 The SMTP client does not support SSL/TLS connections

Added:
    commons/proper/net/trunk/src/main/java/org/apache/commons/net/smtp/SMTPSClient.java  
(with props)
    commons/proper/net/trunk/src/main/java/org/apache/commons/net/smtp/SMTPSTrustManager.java
  (with props)
Modified:
    commons/proper/net/trunk/src/changes/changes.xml

Modified: commons/proper/net/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/changes/changes.xml?rev=1074008&r1=1074007&r2=1074008&view=diff
==============================================================================
--- commons/proper/net/trunk/src/changes/changes.xml (original)
+++ commons/proper/net/trunk/src/changes/changes.xml Thu Feb 24 01:40:26 2011
@@ -40,7 +40,7 @@ The <action> type attribute can be add,u
 <document>
     <properties>
         <title>Changes</title>
-        <author email="rwinston@apache.org">Rory Winston</author>
+        <author email="dev@commons.apache.org">Apache Commons devlopers</author>
     </properties>
 
     <!-- NOTE: 
@@ -52,7 +52,10 @@ The <action> type attribute can be add,u
      -->
 
     <body>
-        <release version="TBA" date="TBA" description="TBA"
+        <release version="2.3" date="TBA" description="TBA">
+            <action issue="NET-356" dev="sebb" type="add" dueTo="Bogdan Drozdowski">
+            The SMTP client does not support SSL/TLS connections
+            </action>
             <action issue="NET-358" dev="sebb" type="add">
             Implement copy Listener in FTPClient file operations
             </action>

Added: commons/proper/net/trunk/src/main/java/org/apache/commons/net/smtp/SMTPSClient.java
URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/main/java/org/apache/commons/net/smtp/SMTPSClient.java?rev=1074008&view=auto
==============================================================================
--- commons/proper/net/trunk/src/main/java/org/apache/commons/net/smtp/SMTPSClient.java (added)
+++ commons/proper/net/trunk/src/main/java/org/apache/commons/net/smtp/SMTPSClient.java Thu
Feb 24 01:40:26 2011
@@ -0,0 +1,318 @@
+/*
+ * 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.smtp;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+
+/**
+ * SMTP over SSL processing. Copied from FTPSClient.java and modified to suit SMTP.
+ * If implicit mode is selected (NOT the default), SSL/TLS negotiation starts right
+ * after the connection has been established. In explicit mode (the default), SSL/TLS
+ * negotiation starts when the user calls execTLS() and the server accepts the command.
+ * Implicit usage:
+ *               SMTPSClient c = new SMTPSClient(true);
+ *               c.connect("127.0.0.1", 465);
+ * Explicit usage:
+ *               SMTPSClient c = new SMTPSClient();
+ *               c.connect("127.0.0.1", 25);
+ *               if (c.execTLS()) { /rest of the commands here/ }
+ */
+public class SMTPSClient extends SMTPClient
+{
+    /** The TLS start command. */
+    private static final String tlsCommand = "STARTTLS";
+    /** Default secure socket protocol name, like TLS */
+    private static final String DEFAULT_PROTOCOL = "TLS";
+
+    /** The security mode. True - Implicit Mode / False - Explicit Mode. */
+    private final boolean isImplicit;
+    /** The secure socket protocol to be used, like SSL/TLS. */
+    private final String protocol;
+    /** The context object. */
+    private SSLContext context = null;
+    /** The cipher suites. SSLSockets have a default set of these anyway,
+        so no initialization required. */
+    private String[] suites = null;
+    /** The protocol versions. */
+    private String[] protocols = null;
+
+    /** The {@link TrustManager} implementation, default {@link SMTPSTrustManager}. */
+    private TrustManager trustManager = new SMTPSTrustManager();
+
+    /** The {@link KeyManager}. */
+    private KeyManager keyManager = null; // seems not to be required
+
+    /**
+     * Constructor for SMTPSClient.
+     * Sets security mode to explicit (isImplicit = false).
+     * @throws NoSuchAlgorithmException A requested cryptographic algorithm
+     * is not available in the environment.
+     */
+    public SMTPSClient() throws NoSuchAlgorithmException
+    {
+        this(DEFAULT_PROTOCOL, false);
+    }
+
+    /**
+     * Constructor for SMTPSClient.
+     * @param implicit The security mode (Implicit/Explicit).
+     * @throws NoSuchAlgorithmException A requested cryptographic algorithm
+     * is not available in the environment.
+     */
+    public SMTPSClient(boolean implicit) throws NoSuchAlgorithmException
+    {
+        this(DEFAULT_PROTOCOL, implicit);
+    }
+
+    /**
+     * Constructor for SMTPSClient.
+     * @param proto the protocol.
+     * @throws NoSuchAlgorithmException A requested cryptographic algorithm
+     * is not available in the environment.
+     */
+    public SMTPSClient(String proto) throws NoSuchAlgorithmException
+    {
+        this(proto, false);
+    }
+
+    /**
+     * Constructor for SMTPSClient.
+     * @param proto the protocol.
+     * @param implicit The security mode(Implicit/Explicit).
+     * @throws NoSuchAlgorithmException A requested cryptographic algorithm
+     * is not available in the environment.
+     */
+    public SMTPSClient(String proto, boolean implicit)
+            throws NoSuchAlgorithmException
+    {
+        protocol = proto;
+        isImplicit = implicit;
+    }
+
+    /**
+     * Constructor for SMTPSClient.
+     * @param implicit The security mode(Implicit/Explicit).
+     * @param ctx A pre-configured SSL Context.
+     */
+    public SMTPSClient(boolean implicit, SSLContext ctx)
+    {
+        isImplicit = implicit;
+        context = ctx;
+        protocol = DEFAULT_PROTOCOL;
+    }
+
+    /**
+     * Constructor for SMTPSClient.
+     * @param context A pre-configured SSL Context.
+     */
+    public SMTPSClient(SSLContext context)
+    {
+        this(false, context);
+    }
+
+    /**
+     * Because there are so many connect() methods,
+     * the _connectAction_() method is provided as a means of performing
+     * some action immediately after establishing a connection,
+     * rather than reimplementing all of the connect() methods.
+     * @throws IOException If it is thrown by _connectAction_().
+     * @see org.apache.commons.net.SocketClient#_connectAction_()
+     */
+    @Override
+    protected void _connectAction_() throws IOException
+    {
+        // Implicit mode.
+        if (isImplicit) performSSLNegotiation();
+        super._connectAction_();
+        // Explicit mode - don't do anything. The user calls execTLS()
+    }
+
+    /**
+     * Performs a lazy init of the SSL context.
+     * @throws IOException When could not initialize the SSL context.
+     */
+    private void initSSLContext() throws IOException
+    {
+        if (context == null)
+        {
+            try
+            {
+                context = SSLContext.getInstance(protocol);
+                context.init(new KeyManager[] { getKeyManager() },
+                             new TrustManager[] { getTrustManager() },
+                             null);
+            }
+            catch (KeyManagementException e)
+            {
+                IOException ioe = new IOException("Could not initialize SSL context");
+                ioe.initCause(e);
+                throw ioe;
+            }
+            catch (NoSuchAlgorithmException e)
+            {
+                IOException ioe = new IOException("Could not initialize SSL context");
+                ioe.initCause(e);
+                throw ioe;
+            }
+        }
+    }
+
+    /**
+     * SSL/TLS negotiation. Acquires an SSL socket of a
+     * connection and carries out handshake processing.
+     * @throws IOException If server negotiation fails.
+     */
+    private void performSSLNegotiation() throws IOException
+    {
+        initSSLContext();
+
+        SSLSocketFactory ssf = context.getSocketFactory();
+        String ip = _socket_.getInetAddress().getHostAddress();
+        int port = _socket_.getPort();
+        SSLSocket socket =
+            (SSLSocket) ssf.createSocket(_socket_, ip, port, true);
+        socket.setEnableSessionCreation(true);
+        socket.setUseClientMode(true);
+
+        if (protocols != null) socket.setEnabledProtocols(protocols);
+        if (suites != null) socket.setEnabledCipherSuites(suites);
+        socket.startHandshake();
+
+        _socket_ = socket;
+        _input_ = socket.getInputStream();
+        _output_ = socket.getOutputStream();
+    }
+
+    /**
+     * Get the {@link KeyManager} instance.
+     * @return The current {@link KeyManager} instance.
+     */
+    private KeyManager getKeyManager()
+    {
+        return keyManager;
+    }
+
+    /**
+     * Set a {@link KeyManager} to use.
+     * @param newKeyManager The KeyManager implementation to set.
+     */
+    public void setKeyManager(KeyManager newKeyManager)
+    {
+        keyManager = newKeyManager;
+    }
+
+    /**
+     * Controls which particular cipher suites are enabled for use on this
+     * connection. Called before server negotiation.
+     * @param cipherSuites The cipher suites.
+     */
+    public void setEnabledCipherSuites(String[] cipherSuites)
+    {
+        suites = new String[cipherSuites.length];
+        System.arraycopy(cipherSuites, 0, suites, 0, cipherSuites.length);
+    }
+
+    /**
+     * Returns the names of the cipher suites which could be enabled
+     * for use on this connection.
+     * When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns null.
+     * @return An array of cipher suite names, or <code>null</code>.
+     */
+    public String[] getEnabledCipherSuites()
+    {
+        if (_socket_ instanceof SSLSocket)
+        {
+            return ((SSLSocket)_socket_).getEnabledCipherSuites();
+        }
+        return null;
+    }
+
+    /**
+     * Controls which particular protocol versions are enabled for use on this
+     * connection. I perform setting before a server negotiation.
+     * @param protocolVersions The protocol versions.
+     */
+    public void setEnabledProtocols(String[] protocolVersions)
+    {
+        protocols = new String[protocolVersions.length];
+        System.arraycopy(protocolVersions, 0, protocols, 0, protocolVersions.length);
+    }
+
+    /**
+     * Returns the names of the protocol versions which are currently
+     * enabled for use on this connection.
+     * When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns null.
+     * @return An array of protocols, or <code>null</code>.
+     */
+    public String[] getEnabledProtocols()
+    {
+        if (_socket_ instanceof SSLSocket)
+        {
+            return ((SSLSocket)_socket_).getEnabledProtocols();
+        }
+        return null;
+    }
+
+    /**
+     * The TLS command execution.
+     * @throws SSLException If the server reply code is not positive.
+     * @throws IOException If an I/O error occurs while sending
+     * the command or performing the negotiation.
+     * @return TRUE if the command and negotiation succeeded.
+     */
+    public boolean execTLS() throws SSLException, IOException
+    {
+        if (!SMTPReply.isPositiveCompletion(sendCommand(tlsCommand)))
+        {
+            return false;
+            //throw new SSLException(getReplyString());
+        }
+        performSSLNegotiation();
+        return true;
+    }
+
+    /**
+     * Get the currently configured {@link TrustManager}.
+     * @return A TrustManager instance.
+     */
+    public TrustManager getTrustManager()
+    {
+        return trustManager;
+    }
+
+    /**
+     * Override the default {@link TrustManager} to use.
+     * @param newTrustManager The TrustManager implementation to set.
+     */
+    public void setTrustManager(TrustManager newTrustManager)
+    {
+        trustManager = newTrustManager;
+    }
+}
+
+/* kate: indent-width 4; replace-tabs on; */

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

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

Added: commons/proper/net/trunk/src/main/java/org/apache/commons/net/smtp/SMTPSTrustManager.java
URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/main/java/org/apache/commons/net/smtp/SMTPSTrustManager.java?rev=1074008&view=auto
==============================================================================
--- commons/proper/net/trunk/src/main/java/org/apache/commons/net/smtp/SMTPSTrustManager.java
(added)
+++ commons/proper/net/trunk/src/main/java/org/apache/commons/net/smtp/SMTPSTrustManager.java
Thu Feb 24 01:40:26 2011
@@ -0,0 +1,54 @@
+/*
+ * 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.smtp;
+
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * Custom {@link TrustManager} implementation, taken from FTPSTrustManager.
+ * @author Bogdan Drozdowski, bogdandr # op . pl
+ */
+public class SMTPSTrustManager implements X509TrustManager
+{
+    private static final X509Certificate[] EMPTY_X509CERTIFICATE_ARRAY = new X509Certificate[]{};
+
+    /**
+     * No-op
+     */
+    public void checkClientTrusted(X509Certificate[] certificates, String authType)
+    {
+        return;
+    }
+
+    public void checkServerTrusted(X509Certificate[] certificates, String authType) throws
CertificateException
+    {
+        for (int i = 0; i < certificates.length; ++i)
+        {
+            certificates[i].checkValidity();
+        }
+    }
+
+    public X509Certificate[] getAcceptedIssuers()
+    {
+        return EMPTY_X509CERTIFICATE_ARRAY;
+    }
+}

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

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



Mime
View raw message