Return-Path: Delivered-To: apmail-commons-commits-archive@minotaur.apache.org Received: (qmail 50514 invoked from network); 24 Feb 2011 01:40:49 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 24 Feb 2011 01:40:49 -0000 Received: (qmail 82627 invoked by uid 500); 24 Feb 2011 01:40:49 -0000 Delivered-To: apmail-commons-commits-archive@commons.apache.org Received: (qmail 82540 invoked by uid 500); 24 Feb 2011 01:40:48 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 82532 invoked by uid 99); 24 Feb 2011 01:40:48 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 24 Feb 2011 01:40:48 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 24 Feb 2011 01:40:46 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id CCB1323889F7; Thu, 24 Feb 2011 01:40:26 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit 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 -0000 To: commits@commons.apache.org From: sebb@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110224014026.CCB1323889F7@eris.apache.org> 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 type attribute can be add,u Changes - Rory Winston + Apache Commons devlopers - + + The SMTP client does not support SSL/TLS connections + Implement copy Listener in FTPClient file operations 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 null. + */ + 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 null. + */ + 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