Author: rwinston Date: Sat Aug 26 05:09:50 2006 New Revision: 437151 URL: http://svn.apache.org/viewvc?rev=437151&view=rev Log: Added FTPS impl based on submission inb https://issues.apache.org/jira/browse/NET-28
Added: jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/FTPSCommand.java jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/FTPSReply.java Modified: jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/FTPSClient.java jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/FTPSSocketFactory.java Modified: jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/FTPSClient.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/FTPSClient.java?rev=437151&r1=437150&r2=437151&view=diff ============================================================================== --- jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/FTPSClient.java (original) +++ jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/FTPSClient.java Sat Aug 26 05:09:50 2006 @@ -1,12 +1,11 @@ -/* - * Copyright 2001-2006 The Apache Software Foundation - * +/** + * * Licensed 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 - * + * + * 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. @@ -23,160 +22,629 @@ import java.net.InetAddress; import java.net.Socket; import java.net.SocketException; +import java.security.KeyManagementException; import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.util.Enumeration; +import java.util.Vector; +import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; 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; - +import javax.net.ssl.TrustManagerFactory; /** - * - * This class extends [EMAIL PROTECTED] org.apache.commons.net.ftp.FTPClient} to add - * the necessary methods that implement SSL/TLS-FTPS. - * + * FTP over SSL processing. */ public class FTPSClient extends FTPClient { - // Represent the method to the FTP command AUTH... - private String sslContext; - - // Secure context (can be "TLS" or "SSL") - private SSLContext context; - - private String pbsz; - private String prot; - - /** - * Default constructor that selects some default options (TLS encryption) - * - */ - public FTPSClient() { - this("JCEKS", "TLS", "password", "0", "P"); - } - - - /** - * - * Constructor that initializes the secure connection. - * - * @param keyStoreName Type of instance KeyStore, JKS for Java 1.3 y JCEKS for Java 1.4 - * @param sslContext Type of the instance SSLContext, can be SSL or TLS. - * @param password The password to access the KeyStore. - * @param pbsz Protection buffer size (Use 0 to indicate streaming) - * @param prot The protection level for the data channel - */ - public FTPSClient(String keyStoreName, String sslContext, String password, String pbsz, String prot) { - this.sslContext = sslContext; - this.pbsz = pbsz; - this.prot = prot; - - try { - KeyStore keyStore = KeyStore.getInstance(keyStoreName); - - keyStore.load(null, password.toCharArray()); - - KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - - keyManagerFactory.init(keyStore, password.toCharArray()); - - this.context = SSLContext.getInstance(sslContext); - - this.context.init( - keyManagerFactory.getKeyManagers(), - new TrustManager[] { (TrustManager) new FTPSTrustManager() }, null - ); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * @see org.apache.commons.net.SocketClient#connect(java.net.InetAddress, int, java.net.InetAddress, int) - */ - public void connect(InetAddress address, int port, InetAddress localAddress, int localPort) throws SocketException, IOException - { - super.connect(address, port, localAddress, localPort); - - this.secure(this.pbsz,this.prot); - } - - /** - * @see org.apache.commons.net.SocketClient#connect(java.net.InetAddress, int) - */ - public void connect(InetAddress address, int port) throws SocketException, IOException - { - super.connect(address, port); - - this.secure(this.pbsz,this.prot); - } - - /** - * @see org.apache.commons.net.SocketClient#connect(java.lang.String, int, java.net.InetAddress, int) - */ - public void connect(String address, int port, InetAddress localAddress, int localPort) throws SocketException, IOException - { - super.connect(address, port, localAddress, localPort); - - this.secure(this.pbsz,this.prot); - } - - /** - * @see org.apache.commons.net.SocketClient#connect(java.lang.String, int) - */ - public void connect(String address, int port) throws SocketException, IOException - { - super.connect(address, port); - - this.secure(this.pbsz,this.prot); - } - - /** - * - * Initialize the secure connection with the FTP server, throw the AUTH SSL o TLS command. - * Get the socket with the server, starting the "handshake" making the socket, with a layer of securety, - * and initializing the stream of connection. - * - * - * @param pbsz Protection Buffer Size: "0" is a good value - * @param prot Data Channel Protection Level: - * Posible values: - * C - Clear - * S - Safe - * E - Confidential - * P - PrivateType of secure connection - * - * @throws IOException If there is any problem with the connection. - */ - protected void secure(String pbsz, String prot) throws IOException { - this.sendCommand("AUTH", sslContext); - - SSLSocket socket = (SSLSocket)this.context.getSocketFactory().createSocket(this._socket_, this.getRemoteAddress().getHostAddress(), this.getRemotePort(), true); - - socket.startHandshake(); - - this._socket_ = socket; - - this._controlInput_ = new BufferedReader(new InputStreamReader(socket.getInputStream(), getControlEncoding())); - this._controlOutput_ = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), getControlEncoding())); - - this.setSocketFactory(new FTPSSocketFactory(this.context)); - - this.sendCommand("PBSZ", pbsz); - this.sendCommand("PROT", prot); - } - - /** - * @see org.apache.commons.net.ftp.FTPCliente#_openDataConnection_(java.lang.String, int) - */ - protected Socket _openDataConnection_(int command, String arg) throws IOException { - Socket socket = super._openDataConnection_(command, arg); - if (socket != null) { - ((SSLSocket)socket).startHandshake(); - } - return socket; - } - + /** keystore algorithm name. */ + public static String KEYSTORE_ALGORITHM; + /** truststore algorithm name. */ + public static String TRUSTSTORE_ALGORITHM; + /** provider name. */ + public static String PROVIDER; + /** truststore type. */ + public static String STORE_TYPE; + + /** The value that I can set in PROT command */ + private static final String[] PROT_COMMAND_VALUE = {"C","E","S","P"}; + /** Default PROT Command */ + private static final String DEFAULT_PROT = "C"; + /** Default protocol name */ + private static final String DEFAULT_PROTOCOL = "TLS"; + + /** The security mode. (True - Implicit Mode / False - Explicit Mode) */ + private boolean isImplicit; + /** The use SSL/TLS protocol. */ + private String protocol = DEFAULT_PROTOCOL; + /** The AUTH Command value */ + private String auth = DEFAULT_PROTOCOL; + /** The KeyManager object. */ + private KeyManager[] keyManager = null; + /** The TrustManager object */ + private TrustManager[] trustManager = null; + /** The context object. */ + private SSLContext context; + /** The socket object. */ + private Socket planeSocket; + /** The established socket flag. */ + private boolean isCreation = true; + /** The use client mode flag. */ + private boolean isClientMode = true; + /** The need client auth flag. */ + private boolean isNeedClientAuth = false; + /** The want client auth flag. */ + private boolean isWantClientAuth = false; + /** The cipher suites */ + private String[] suites = null; + /** The protocol versions */ + private String[] protocols = null; + + /** + * Constructor for FTPSClient. + * @throws NoSuchAlgorithmException A requested cryptographic algorithm + * is not available in the environment. + */ + public FTPSClient() throws NoSuchAlgorithmException { + this.protocol = DEFAULT_PROTOCOL; + this.isImplicit = false; + context = SSLContext.getInstance(protocol); + } + + /** + * Constructor for FTPSClient. + * @param isImplicit The secutiry mode(Implicit/Explicit). + * @throws NoSuchAlgorithmException A requested cryptographic algorithm + * is not available in the environment. + */ + public FTPSClient(boolean isImplicit) throws NoSuchAlgorithmException { + this.protocol = DEFAULT_PROTOCOL; + this.isImplicit = isImplicit; + context = SSLContext.getInstance(protocol); + } + + /** + * Constructor for FTPSClient. + * @param conType The context type + * @throws NoSuchAlgorithmException A requested cryptographic algorithm + * is not available in the environment. + */ + public FTPSClient(String protocol) throws NoSuchAlgorithmException { + this.protocol = protocol; + this.isImplicit = false; + context = SSLContext.getInstance(protocol); + } + + /** + * Constructor for FTPSClient. + * @param conType The context type + * @param isImplicit The secutiry mode(Implicit/Explicit). + * @throws NoSuchAlgorithmException A requested cryptographic algorithm + * is not available in the environment. + */ + public FTPSClient(String protocol, boolean isImplicit) + throws NoSuchAlgorithmException { + this.protocol = protocol; + this.isImplicit = isImplicit; + context = SSLContext.getInstance(protocol); + } + + /** + * Create KeyManager[] object. + * @param ks The KeyStore objects. + * @param storePass The Store password. + * @throws NoSuchAlgorithmException A requested cryptographic + * algorithm is not available in the environment. + * @throws NoSuchProviderException A requested cryptographic provider + * is not available in the environment. + * @throws UnrecoverableKeyException This exception is thrown + * if a key in the keystore cannot be recovered. + * @throws KeyStoreException This is the generic KeyStore exception. + * @throws KeyManagementException It is the generic KeyManager exception. + */ + public void createKeyManager(KeyStore ks, String storePass) + throws NoSuchAlgorithmException, NoSuchProviderException, + KeyStoreException,UnrecoverableKeyException,KeyManagementException{ + if (ks == null) { + keyManager = null; + return; + } + if (KEYSTORE_ALGORITHM == null) + KEYSTORE_ALGORITHM = KeyManagerFactory.getDefaultAlgorithm(); + KeyManagerFactory kmf; + if (PROVIDER == null) { + kmf = KeyManagerFactory.getInstance(KEYSTORE_ALGORITHM); + } else { + kmf = KeyManagerFactory.getInstance(KEYSTORE_ALGORITHM, PROVIDER); + } + if (kmf == null) { + keyManager = null; + return; + } + kmf.init(ks, storePass.toCharArray()); + keyManager = kmf.getKeyManagers(); + context.init(keyManager, trustManager, null); + } + + /** + * Create TrustManager[] object. + * @param ks The KeyStore object. + * @throws NoSuchAlgorithmException A requested cryptographic algorithm + * is not available in the environment. + * @throws NoSuchProviderException A requested cryptographic provider + * is not available in the environment. + * @throws KeyStoreException This is the generic KeyStore exception. + * @throws KeyManagementException It is the generic KeyManager exception. + */ + public void createTrustManager(KeyStore ks) + throws NoSuchAlgorithmException, NoSuchProviderException, + KeyStoreException, KeyManagementException { + if (ks == null) trustManager = null; + if (TRUSTSTORE_ALGORITHM == null) + TRUSTSTORE_ALGORITHM = TrustManagerFactory.getDefaultAlgorithm(); + TrustManagerFactory tmf; + if (PROVIDER == null) { + tmf = TrustManagerFactory.getInstance(TRUSTSTORE_ALGORITHM); + } else { + tmf = TrustManagerFactory.getInstance( + TRUSTSTORE_ALGORITHM, PROVIDER); + } + if (tmf == null) { + trustManager = null; + return; + } + tmf.init(ks); + trustManager = tmf.getTrustManagers(); + context.init(keyManager, trustManager, null); + } + + /** + * Create TrustManager[] object. + * @param _ks The KeyStore objects. + * @throws KeyStoreException This is the generic KeyStore exception. + * @throws CertificateException This exception indicates one of + * a variety of certificate problems. + * @throws NoSuchAlgorithmException A requested cryptographic algorithm + * is not available in the environment. + * @throws NoSuchProviderException A requested cryptographic provider + * is not available in the environment. + * @throws KeyManagementException It is the generic KeyManager exception. + * @throws IOException + */ + public void createTrustManager(Vector ks) throws KeyStoreException, + NoSuchAlgorithmException, CertificateException, + IOException, NoSuchProviderException, KeyManagementException { + if (ks == null) { + trustManager = null; + return; + } + KeyStore _ks; + if (STORE_TYPE == null) { + _ks = KeyStore.getInstance(KeyStore.getDefaultType()); + } else { + _ks = KeyStore.getInstance(STORE_TYPE); + } + _ks.load(null, null); + int n = 0; + // as for every keystore + for (int i = 0; i < ks.size(); i++) { + // as for every alias + KeyStore wks = ((KeyStore) ks.get(i)); + for (Enumeration e = wks.aliases(); e.hasMoreElements();) { + String alias = (String) e.nextElement(); + _ks.setCertificateEntry(String.valueOf(n), + wks.getCertificate(alias)); + n++; + } + } + createTrustManager(_ks); + } + + /** + * Set AUTH command use value. + * This processing is done before connected processing. + * @param auth AUTH command use value. + */ + public void setAuthValue(String auth) { + this.auth = auth; + } + + /** + * Return AUTH command use value. + * @return AUTH command use value. + */ + public String getAuthValue() { + return this.auth; + } + + /** + * I work to be connected. Opens a Socket connected to a remote host + * at the specified port and originating from the current host at + * a system assigned port. + * @param address The name of the remote host. + * @param port The port to connect to on the remote host. + * @throws SocketException If the socket timeout could not be set. + * @throws IOException If the socket could not be opened. + * In most cases you will only want to catch IOException since + * SocketException is derived from it. + * @see org.apache.commons.net.SocketClient#connect(java.lang.String, int) + */ + public void connect(String address, int port) + throws SocketException, IOException { + super.connect(address, port); + } + + /** + * I work to be connected. Opens a Socket connected to a remote host + * at the specified port and originating from the current host at + * a system assigned port. + * @param address The name of the remote host. + * @param port The port to connect to on the remote host. + * @throws SocketException If the socket timeout could not be set. + * @throws IOException If the socket could not be opened. + * In most cases you will only want to catch IOException since + * SocketException is derived from it. + * @see org.apache.commons.net.SocketClient + * #connect(java.net.InetAddress, int) + */ + public void connect(InetAddress address, int port) + throws SocketException, IOException { + super.connect(address, port); + } + + /** + * I work to be connected. Opens a Socket connected to a remote host + * at the specified port and originating from the specified + * local address and port. + * @param address The name of the remote host. + * @param port The port to connect to on the remote host. + * @param localAddress The local address to use. + * @param localPort The local port to use. + * @throws SocketException If the socket timeout could not be set. + * @throws IOException If the socket could not be opened. + * In most cases you will only want to catch IOException since + * SocketException is derived from it. + * @see org.apache.commons.net.SocketClient + * #connect(java.net.InetAddress, int, java.net.InetAddress, int) + */ + public void connect(InetAddress address, int port, + InetAddress localAddress, int localPort) + throws SocketException, IOException { + super.connect(address, port, localAddress, localPort); + } + + /** + * I work to be connected. Opens a Socket connected to a remote host + * at the specified port and originating from the specified + * local address and port. + * @param address The name of the remote host. + * @param port The port to connect to on the remote host. + * @param localAddress The local address to use. + * @param localPort The local port to use. + * @throws SocketException If the socket timeout could not be set. + * @throws IOException If the socket could not be opened. + * In most cases you will only want to catch IOException since + * SocketException is derived from it. + * @see org.apache.commons.net.SocketClient + * #connect(java.lang.String, int, java.net.InetAddress, int) + */ + public void connect(String address, int port, InetAddress localAddress, + int localPort) throws SocketException, IOException { + super.connect(address, port, localAddress, localPort); + } + + /** + * 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 throw by _connectAction_. + * @see org.apache.commons.net.SocketClient#_connectAction_() + */ + protected void _connectAction_() throws IOException { + // Implicit mode. + if (isImplicit) sslNegotiation(); + super._connectAction_(); + // Explicit mode. + if (!isImplicit) { + execAUTH(); + sslNegotiation(); + } + } + + /** + * I carry out an AUTH command. + * @throws SSLException If it server reply code not equal "234" and "334". + * @throws IOException If an I/O error occurs while either sending + * the command. + */ + private void execAUTH() throws SSLException, IOException { + int replyCode = sendCommand( + FTPSCommand._commands[FTPSCommand.AUTH], auth); + if (FTPSReply.SECURITY_MECHANISM_IS_OK == replyCode) { + // replyCode = 334 + // I carry out an ADAT command. + } else if (FTPSReply.SECURITY_DATA_EXCHANGE_COMPLETE != replyCode) { + throw new SSLException(getReplyString()); + } + } + + /** + * SSL/TLS negotiation. I acquire an SSL socket of a control + * connection and carry out handshake processing. + * @throws IOException A handicap breaks out by sever negotiation. + */ + private void sslNegotiation() throws IOException { + // Evacuation not ssl socket. + planeSocket = _socket_; + + SSLSocketFactory ssf = context.getSocketFactory(); + String ip = _socket_.getInetAddress().getHostAddress(); + int port = _socket_.getPort(); + SSLSocket socket = + (SSLSocket) ssf.createSocket(_socket_, ip, port, true); + socket.setEnableSessionCreation(isCreation); + socket.setUseClientMode(isClientMode); + // server mode + if (!isClientMode) { + socket.setNeedClientAuth(isNeedClientAuth); + socket.setWantClientAuth(isWantClientAuth); + } + if (protocols != null) socket.setEnabledProtocols(protocols); + if (suites != null) socket.setEnabledCipherSuites(suites); + + socket.startHandshake(); + + _socket_ = socket; + _controlInput = new BufferedReader(new InputStreamReader( + socket .getInputStream(), getControlEncoding())); + _controlOutput = new BufferedWriter(new OutputStreamWriter( + socket.getOutputStream(), getControlEncoding())); + } + + /** + * Controls whether new SSL session may be established by this socket. + * @param isCreation The established socket flag. + */ + public void setEnabledSessionCreation(boolean isCreation) { + this.isCreation = isCreation; + } + + /** + * Returns true if new SSL sessions may be established by this socket. + * When a socket does not have a ssl socket, This return False. + * @return true - Indicates that sessions may be created; + * this is the default. + * false - indicates that an existing session must be resumed. + */ + public boolean getEnableSeeionCreation() { + if (_socket_ instanceof SSLSocket) + return ((SSLSocket)_socket_).getEnableSessionCreation(); + return false; + } + + /** + * Configures the socket to require client authentication. + * @param isNeedClientAuth The need client auth flag. + */ + public void setNeedClientAuth(boolean isNeedClientAuth) { + this.isNeedClientAuth = isNeedClientAuth; + } + + /** + * Returns true if the socket will require client authentication. + * When a socket does not have a ssl socket, This return False. + * @return true - If the server mode socket should request + * that the client authenticate itself. + */ + public boolean getNeedClientAuth() { + if (_socket_ instanceof SSLSocket) + return ((SSLSocket)_socket_).getNeedClientAuth(); + return false; + } + + /** + * Configures the socket to request client authentication, + * but only if such a request is appropriate to the cipher + * suite negotiated. + * @param isWantClientAuth The want client auth flag. + */ + public void setWantClientAuth(boolean isWantClientAuth) { + this.isWantClientAuth = isWantClientAuth; + } + + /** + * Returns true if the socket will request client authentication. + * When a socket does not have a ssl socket, This return False. + * @return true - If the server mode socket should request + * that the client authenticate itself. + */ + public boolean getWantClientAuth() { + if (_socket_ instanceof SSLSocket) + return ((SSLSocket)_socket_).getWantClientAuth(); + return false; + } + + /** + * Configures the socket to use client (or server) mode in its first + * handshake. + * @param isClientMode The use client mode flag. + */ + public void setUseClientMode(boolean isClientMode) { + this.isClientMode = isClientMode; + } + + /** + * Returns true if the socket is set to use client mode + * in its first handshake. + * When a socket does not have a ssl socket, This return False. + * @return true - If the socket should start its first handshake + * in "client" mode. + */ + public boolean getUseClientMode() { + if (_socket_ instanceof SSLSocket) + return ((SSLSocket)_socket_).getUseClientMode(); + return false; + } + + /** + * Controls which particular cipher suites are enabled for use on this + * connection. I perform setting before a server negotiation. + * @param suites The cipher suites. + */ + public void setEnabledCipherSuites(String[] suites) { + this.suites = suites; + } + + /** + * Returns the names of the cipher suites which could be enabled + * for use on this connection. + * When a socket does not have a ssl socket, This return null. + * @return An array of cipher suite names. + */ + 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 protocols The protocol versions. + */ + public void setEnabledProtocols(String[] protocols) { + this.protocols = protocols; + } + + /** + * Returns the names of the protocol versions which are currently + * enabled for use on this connection. + * When a socket does not have a ssl socket, This return null. + * @return An array of protocols. + */ + public String[] getEnabledProtocols() { + if (_socket_ instanceof SSLSocket) + return ((SSLSocket)_socket_).getEnabledProtocols(); + return null; + } + + /** + * I carry out an PBSZ command. pbsz value: 0 to (2^32)-1 decimal integer. + * @param pbsz Protection Buffer Size. + * @throws SSLException If it server reply code not equal "200". + * @throws IOException If an I/O error occurs while either sending + * the command. + */ + public void execPBSZ(long pbsz) throws SSLException, IOException { + if (pbsz < 0 || 4294967295L < pbsz) + throw new IllegalArgumentException(); + if (FTPSReply.COMMAND_OK != sendCommand( + FTPSCommand._commands[FTPSCommand.PBSZ],String.valueOf(pbsz))) + throw new SSLException(getReplyString()); + } + + /** + * I carry out an PROT command.</br> + * C - Clear</br> + * S - Safe(SSL protocol only)</br> + * E - Confidential(SSL protocol only)</br> + * P - Private + * @param prot Data Channel Protection Level. + * @throws SSLException If it server reply code not equal "200". + * @throws IOException If an I/O error occurs while either sending + * the command. + */ + public void execPROT(String prot) throws SSLException, IOException { + if (prot == null) prot = DEFAULT_PROT; + if (!checkPROTValue(prot)) throw new IllegalArgumentException(); + if (FTPSReply.COMMAND_OK != sendCommand( + FTPSCommand._commands[FTPSCommand.PROT], prot)) + throw new SSLException(getReplyString()); + if (DEFAULT_PROT.equals(prot)) { + setSocketFactory(null); + } else { + setSocketFactory(new FTPSSocketFactory(context)); + } + } + + /** + * I check the value that I can set in PROT Command value. + * @param prot Data Channel Protection Level. + * @return True - A set point is right / False - A set point is not right + */ + private boolean checkPROTValue(String prot) { + for (int p = 0; p < PROT_COMMAND_VALUE.length; p++) { + if (PROT_COMMAND_VALUE[p].equals(prot)) return true; + } + return false; + } + + /** + * I carry out an ftp command. + * When a CCC command was carried out, I steep socket and SocketFactory + * in a state of not ssl. + * @parm command ftp command. + * @return server reply. + * @throws IOException If an I/O error occurs while either sending + * the command. + * @see org.apache.commons.net.ftp.FTP#sendCommand(java.lang.String) + */ + public int sendCommand(String command, String args) throws IOException { + int repCode = super.sendCommand(command, args); + if (FTPSCommand._commands[FTPSCommand.CCC].equals(command)) { + if (FTPSReply.COMMAND_OK == repCode) { + _socket_ = planeSocket; + setSocketFactory(null); + } else { + throw new SSLException(getReplyString()); + } + } + return repCode; + } + + /** + * I return a socket of the data connection that I acquired. + * When I ssl it and communicate, I return the SSL socket which + * carried out handshake processing. + * @pram command The text representation of the FTP command to send. + * @param arg The arguments to the FTP command. + * If this parameter is set to null, then the command is sent with + * no argument. + * @return A Socket corresponding to the established data connection. + * Null is returned if an FTP protocol error is reported at any point + * during the establishment and initialization of the connection. + * @throws IOException If there is any problem with the connection. + * @see org.apache.commons.net.ftp.FTPCliente + * #_openDataConnection_(java.lang.String, int) + */ + protected Socket _openDataConnection_(int command, String arg) + throws IOException { + Socket socket = super._openDataConnection_(command, arg); + if (socket != null && socket instanceof SSLSocket) { + SSLSocket sslSocket = (SSLSocket)socket; + sslSocket.setUseClientMode(isClientMode); + sslSocket.setEnableSessionCreation(isCreation); + // server mode + if (!isClientMode) { + sslSocket.setNeedClientAuth(isNeedClientAuth); + sslSocket.setWantClientAuth(isWantClientAuth); + } + if (suites != null) + sslSocket.setEnabledCipherSuites(suites); + if (protocols != null) + sslSocket.setEnabledProtocols(protocols); + sslSocket.startHandshake(); + } + return socket; + } } - Added: jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/FTPSCommand.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/FTPSCommand.java?rev=437151&view=auto ============================================================================== --- jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/FTPSCommand.java (added) +++ jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/FTPSCommand.java Sat Aug 26 05:09:50 2006 @@ -0,0 +1,46 @@ +/** + * + * Licensed 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.ftp; + +/** + * I acquire a command added in FTPS. + */ +public final class FTPSCommand { + public static final int AUTH = 0; + public static final int ADAT = 1; + public static final int PBSZ = 2; + public static final int PROT = 3; + public static final int CCC = 4; + + public static final int AUTHENTICATION_SECURITY_MECHANISM = AUTH; + public static final int AUTHENTICATION_SECURITY_DATA = ADAT; + public static final int PROTECTION_BUFFER_SIZE = PBSZ; + public static final int DATA_CHANNEL_PROTECTION_LEVEL = PROT; + public static final int CLEAR_COMMAND_CHANNEL = CCC; + + static final String[] _commands = {"AUTH","ADAT","PBSZ","PROT","CCC"}; + + /** + * Retrieve the FTPS command string corresponding to a specified + * command code. + * <p> + * @param command The command code. + * @return The FTPS command string corresponding to a specified + * command code. + */ + public static final String getCommand(int command) { + return _commands[command]; + } +} Added: jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/FTPSReply.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/FTPSReply.java?rev=437151&view=auto ============================================================================== --- jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/FTPSReply.java (added) +++ jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/FTPSReply.java Sat Aug 26 05:09:50 2006 @@ -0,0 +1,131 @@ +/** + * + * Licensed 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.ftp; + +/** + * I confirm a response cord of a command added in FTPS. + */ +public final class FTPSReply { + public static final int CODE_200 = 200; + public static final int CODE_234 = 234; + public static final int CODE_235 = 235; + public static final int CODE_334 = 334; + public static final int CODE_335 = 335; + public static final int CODE_421 = 421; + public static final int CODE_431 = 431; + public static final int CODE_500 = 500; + public static final int CODE_501 = 501; + public static final int CODE_502 = 502; + public static final int CODE_503 = 503; + public static final int CODE_504 = 504; + public static final int CODE_530 = 530; + public static final int CODE_533 = 533; + public static final int CODE_534 = 534; + public static final int CODE_535 = 535; + public static final int CODE_536 = 536; + + public static final int COMMAND_OK = CODE_200; + public static final int SECURITY_DATA_EXCHANGE_COMPLETE = CODE_234; + public static final int SECURITY_DATA_EXCHANGE_SUCCESSFULLY = CODE_235; + public static final int SECURITY_MECHANISM_IS_OK = CODE_334; + public static final int SECURITY_DATA_IS_ACCEPTABLE = CODE_335; + public static final int SERVICE_NOT_AVAILABLE = CODE_421; + public static final int UNAVAILABLE_RESOURCE = CODE_431; + public static final int UNRECOGNIZED_COMMAND = CODE_500; + public static final int SYNTAX_ERROR_IN_ARGUMENTS = CODE_501; + public static final int COMMAND_NOT_IMPLEMENTED = CODE_502; + public static final int BAD_COMMAND_SEQUENCE = CODE_503; + public static final int COMMAND_NOT_IMPLEMENTED_FOR_PARAMETER=CODE_504; + public static final int NOT_LOGGED_IN = CODE_530; + public static final int DENIED_FOR_POLICY_REASONS = CODE_533; + public static final int REQUEST_DENIED = CODE_534; + public static final int FAILED_SECURITY_CHECK = CODE_535; + public static final int REQUESTED_PROT_LEVEL_NOT_SUPPORTED = CODE_536; + + /** + * Determine if a reply code is a positive preliminary response. All + * codes beginning with a 1 are positive preliminary responses. + * Postitive preliminary responses are used to indicate tentative success. + * No further commands can be issued to the FTP server after a positive + * preliminary response until a follow up response is received from the + * server. + * <p> + * @param reply The reply code. + * @return True if a reply code is a postive preliminary pesponse, + * false if not. + */ + public static boolean isPositivePreliminary(int reply) { + return (reply >= 100 && reply < 200); + } + + /** + * Determine if a reply code is a positive completion response. All + * codes beginning with a 2 are positive completion responses. + * The FTP server will send a positive completion response on the final + * successful completion of a command. + * <p> + * @param reply The reply code. + * @return True if a reply code is a postive completion response, + * false if not. + */ + public static boolean isPositiveCompletion(int reply) { + return (reply >= 200 && reply < 300); + } + + /** + * Determine if a reply code is a positive intermediate response. All + * codes beginning with a 3 are positive intermediate responses. + * The FTP server will send a positive intermediate response on the + * successful completion of one part of a multi-part sequence of + * commands. For example, after a successful USER command, a positive + * intermediate response will be sent to indicate that the server is + * ready for the PASS command. + * <p> + * @param reply The reply code. + * @return True if a reply code is a postive intermediate response, + * false if not. + */ + public static boolean isPositiveIntermediate(int reply) { + return (reply >= 300 && reply < 400); + } + + /** + * Determine if a reply code is a negative transient response. All + * codes beginning with a 4 are negative transient responses. + * The FTP server will send a negative transient response on the + * failure of a command that can be reattempted with success. + * <p> + * @param reply The reply code. + * @return True if a reply code is a negative transient response, + * false if not. + */ + public static boolean isNegativeTransient(int reply) { + return (reply >= 400 && reply < 500); + } + + /** + * Determine if a reply code is a negative permanent response. All + * codes beginning with a 5 are negative permanent responses. + * The FTP server will send a negative permanent response on the + * failure of a command that cannot be reattempted with success. + * <p> + * @param reply The reply code. + * @return True if a reply code is a negative permanent response, + * false if not. + */ + public static boolean isNegativePermanent(int reply) { + return (reply >= 500 && reply < 600); + } +} Modified: jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/FTPSSocketFactory.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/FTPSSocketFactory.java?rev=437151&r1=437150&r2=437151&view=diff ============================================================================== --- jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/FTPSSocketFactory.java (original) +++ jakarta/commons/proper/net/branches/JDK_1_5_BRANCH/src/main/java/org/apache/commons/net/ftp/FTPSSocketFactory.java Sat Aug 26 05:09:50 2006 @@ -1,18 +1,19 @@ -/* - * Copyright 2001-2006 The Apache Software Foundation - * +/** + * Copyright 2006 Paul Ferraro & Jose Juan Montiel + * * Licensed 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 - * + * + * 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.ftp; import java.io.IOException; @@ -23,65 +24,52 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.SSLServerSocket; -import javax.net.ssl.SSLSocket; import org.apache.commons.net.SocketFactory; -public class FTPSSocketFactory implements SocketFactory -{ - private SSLContext context; - - public FTPSSocketFactory(SSLContext context) - { - this.context = context; - } - - public Socket createSocket(String address, int port) throws UnknownHostException, IOException - { - return this.init(this.context.getSocketFactory().createSocket(address, port)); - } - - public Socket createSocket(InetAddress address, int port) throws IOException - { - return this.init(this.context.getSocketFactory().createSocket(address, port)); - } - - public Socket createSocket(String address, int port, InetAddress localAddress, int localPort) throws UnknownHostException, IOException - { - return this.init(this.context.getSocketFactory().createSocket(address, port, localAddress, localPort)); - } - - public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException - { - return this.init(this.context.getSocketFactory().createSocket(address, port, localAddress, localPort)); - } - - public ServerSocket createServerSocket(int port) throws IOException - { - return this.init(this.context.getServerSocketFactory().createServerSocket(port)); - } - - public ServerSocket createServerSocket(int port, int backlog) throws IOException - { - return this.init(this.context.getServerSocketFactory().createServerSocket(port, backlog)); - } - - public ServerSocket createServerSocket(int port, int backlog, InetAddress ifAddress) throws IOException - { - return this.init(this.context.getServerSocketFactory().createServerSocket(port, backlog, ifAddress)); - } - - public Socket init(Socket socket) throws IOException - { - ((SSLSocket) socket).startHandshake(); - - return socket; - } - - public ServerSocket init(ServerSocket socket) throws IOException - { - ((SSLServerSocket) socket).setUseClientMode(true); - - return socket; - } +/** + * + * Implementation of org.apache.commons.net.SocketFactory + * + */ +public class FTPSSocketFactory implements SocketFactory { + + private SSLContext context; + + public FTPSSocketFactory(SSLContext context) { + this.context = context; + } + + public Socket createSocket(String address, int port) throws UnknownHostException, IOException { + return this.context.getSocketFactory().createSocket(address, port); + } + + public Socket createSocket(InetAddress address, int port) throws IOException { + return this.context.getSocketFactory().createSocket(address, port); + } + + public Socket createSocket(String address, int port, InetAddress localAddress, int localPort) throws UnknownHostException, IOException { + return this.context.getSocketFactory().createSocket(address, port, localAddress, localPort); + } + + public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { + return this.context.getSocketFactory().createSocket(address, port, localAddress, localPort); + } + + public ServerSocket createServerSocket(int port) throws IOException { + return this.init(this.context.getServerSocketFactory().createServerSocket(port)); + } + + public ServerSocket createServerSocket(int port, int backlog) throws IOException { + return this.init(this.context.getServerSocketFactory().createServerSocket(port, backlog)); + } + + public ServerSocket createServerSocket(int port, int backlog, InetAddress ifAddress) throws IOException { + return this.init(this.context.getServerSocketFactory().createServerSocket(port, backlog, ifAddress)); + } + + public ServerSocket init(ServerSocket socket) throws IOException { + ((SSLServerSocket) socket).setUseClientMode(true); + return socket; + } } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]