FTPSClient.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. package org.apache.commons.net.ftp;

  18. import java.io.BufferedReader;
  19. import java.io.BufferedWriter;
  20. import java.io.IOException;
  21. import java.io.InputStreamReader;
  22. import java.io.OutputStreamWriter;
  23. import java.net.Inet6Address;
  24. import java.net.InetAddress;
  25. import java.net.InetSocketAddress;
  26. import java.net.ServerSocket;
  27. import java.net.Socket;
  28. import java.util.Base64;

  29. import javax.net.ssl.HostnameVerifier;
  30. import javax.net.ssl.KeyManager;
  31. import javax.net.ssl.SSLContext;
  32. import javax.net.ssl.SSLException;
  33. import javax.net.ssl.SSLHandshakeException;
  34. import javax.net.ssl.SSLSocket;
  35. import javax.net.ssl.SSLSocketFactory;
  36. import javax.net.ssl.TrustManager;

  37. import org.apache.commons.net.util.SSLContextUtils;
  38. import org.apache.commons.net.util.SSLSocketUtils;
  39. import org.apache.commons.net.util.TrustManagerUtils;

  40. /**
  41.  * FTP over SSL processing. If desired, the JVM property -Djavax.net.debug=all can be used to see wire-level SSL details.
  42.  *
  43.  * Warning: the hostname is not verified against the certificate by default, use {@link #setHostnameVerifier(HostnameVerifier)} or
  44.  * {@link #setEndpointCheckingEnabled(boolean)} (on Java 1.7+) to enable verification. Verification is only performed on client mode connections.
  45.  *
  46.  * @since 2.0
  47.  */
  48. public class FTPSClient extends FTPClient {

  49. // From http://www.iana.org/assignments/port-numbers

  50. //    ftps-data   989/tcp    ftp protocol, data, over TLS/SSL
  51. //    ftps-data   989/udp    ftp protocol, data, over TLS/SSL
  52. //    ftps        990/tcp    ftp protocol, control, over TLS/SSL
  53. //    ftps        990/udp    ftp protocol, control, over TLS/SSL

  54.     /** Default FTPS data port. */
  55.     public static final int DEFAULT_FTPS_DATA_PORT = 989;

  56.     /** Default FTPS port. */
  57.     public static final int DEFAULT_FTPS_PORT = 990;

  58.     /** The value that I can set in PROT command (C = Clear, P = Protected) */
  59.     private static final String[] PROT_COMMAND_VALUE = { "C", "E", "S", "P" };

  60.     /** Default PROT Command */
  61.     private static final String DEFAULT_PROT = "C";

  62.     /** Default secure socket protocol name, i.e. TLS */
  63.     private static final String DEFAULT_PROTOCOL = "TLS";

  64.     /** The AUTH (Authentication/Security Mechanism) command. */
  65.     private static final String CMD_AUTH = "AUTH";

  66.     /** The ADAT (Authentication/Security Data) command. */
  67.     private static final String CMD_ADAT = "ADAT";

  68.     /** The PROT (Data Channel Protection Level) command. */
  69.     private static final String CMD_PROT = "PROT";

  70.     /** The PBSZ (Protection Buffer Size) command. */
  71.     private static final String CMD_PBSZ = "PBSZ";

  72.     /** The MIC (Integrity Protected Command) command. */
  73.     private static final String CMD_MIC = "MIC";

  74.     /** The CONF (Confidentiality Protected Command) command. */
  75.     private static final String CMD_CONF = "CONF";

  76.     /** The ENC (Privacy Protected Command) command. */
  77.     private static final String CMD_ENC = "ENC";

  78.     /** The CCC (Clear Command Channel) command. */
  79.     private static final String CMD_CCC = "CCC";

  80.     /** @deprecated - not used - may be removed in a future release */
  81.     @Deprecated
  82.     public static String KEYSTORE_ALGORITHM;

  83.     /** @deprecated - not used - may be removed in a future release */
  84.     @Deprecated
  85.     public static String TRUSTSTORE_ALGORITHM;

  86.     /** @deprecated - not used - may be removed in a future release */
  87.     @Deprecated
  88.     public static String PROVIDER;

  89.     /** @deprecated - not used - may be removed in a future release */
  90.     @Deprecated
  91.     public static String STORE_TYPE;

  92.     /** The security mode. (True - Implicit Mode / False - Explicit Mode) */
  93.     private final boolean isImplicit;

  94.     /** The secure socket protocol to be used, e.g. SSL/TLS. */
  95.     private final String protocol;

  96.     /** The AUTH Command value */
  97.     private String auth = DEFAULT_PROTOCOL;

  98.     /** The context object. */
  99.     private SSLContext context;

  100.     /** The socket object. */
  101.     private Socket plainSocket;

  102.     /** Controls whether a new SSL session may be established by this socket. Default true. */
  103.     private boolean isCreation = true;

  104.     /** The use client mode flag. */
  105.     private boolean isClientMode = true;

  106.     /** The need client auth flag. */
  107.     private boolean isNeedClientAuth;

  108.     /** The want client auth flag. */
  109.     private boolean isWantClientAuth;

  110.     /** The cipher suites */
  111.     private String[] suites;

  112.     /** The protocol versions */
  113.     private String[] protocols;

  114.     /**
  115.      * The FTPS {@link TrustManager} implementation, default validate only {@link TrustManagerUtils#getValidateServerCertificateTrustManager()}.
  116.      */
  117.     private TrustManager trustManager = TrustManagerUtils.getValidateServerCertificateTrustManager();

  118.     /** The {@link KeyManager}, default null (i.e. use system default). */
  119.     private KeyManager keyManager;

  120.     /** The {@link HostnameVerifier} to use post-TLS, default null (i.e. no verification). */
  121.     private HostnameVerifier hostnameVerifier;

  122.     /** Use Java 1.7+ HTTPS Endpoint Identification Algorithm. */
  123.     private boolean tlsEndpointChecking;

  124.     /**
  125.      * Constructor for FTPSClient, calls {@link #FTPSClient(String, boolean)}.
  126.      *
  127.      * Sets protocol to {@link #DEFAULT_PROTOCOL} - i.e. TLS - and security mode to explicit (isImplicit = false)
  128.      */
  129.     public FTPSClient() {
  130.         this(DEFAULT_PROTOCOL, false);
  131.     }

  132.     /**
  133.      * Constructor for FTPSClient, using {@link #DEFAULT_PROTOCOL} - i.e. TLS Calls {@link #FTPSClient(String, boolean)}
  134.      *
  135.      * @param isImplicit The security mode (Implicit/Explicit).
  136.      */
  137.     public FTPSClient(final boolean isImplicit) {
  138.         this(DEFAULT_PROTOCOL, isImplicit);
  139.     }

  140.     /**
  141.      * Constructor for FTPSClient, using {@link #DEFAULT_PROTOCOL} - i.e. TLS The default TrustManager is set from
  142.      * {@link TrustManagerUtils#getValidateServerCertificateTrustManager()}
  143.      *
  144.      * @param isImplicit The security mode(Implicit/Explicit).
  145.      * @param context    A pre-configured SSL Context
  146.      */
  147.     public FTPSClient(final boolean isImplicit, final SSLContext context) {
  148.         this(DEFAULT_PROTOCOL, isImplicit);
  149.         this.context = context;
  150.     }

  151.     /**
  152.      * Constructor for FTPSClient, using {@link #DEFAULT_PROTOCOL} - i.e. TLS and isImplicit {@code false} Calls {@link #FTPSClient(boolean, SSLContext)}
  153.      *
  154.      * @param context A pre-configured SSL Context
  155.      */
  156.     public FTPSClient(final SSLContext context) {
  157.         this(false, context);
  158.     }

  159.     /**
  160.      * Constructor for FTPSClient, using explicit mode, calls {@link #FTPSClient(String, boolean)}.
  161.      *
  162.      * @param protocol the protocol to use
  163.      */
  164.     public FTPSClient(final String protocol) {
  165.         this(protocol, false);
  166.     }

  167.     /**
  168.      * Constructor for FTPSClient allowing specification of protocol and security mode. If isImplicit is true, the port is set to {@link #DEFAULT_FTPS_PORT}
  169.      * i.e. 990. The default TrustManager is set from {@link TrustManagerUtils#getValidateServerCertificateTrustManager()}
  170.      *
  171.      * @param protocol   the protocol
  172.      * @param isImplicit The security mode(Implicit/Explicit).
  173.      */
  174.     public FTPSClient(final String protocol, final boolean isImplicit) {
  175.         this.protocol = protocol;
  176.         this.isImplicit = isImplicit;
  177.         if (isImplicit) {
  178.             setDefaultPort(DEFAULT_FTPS_PORT);
  179.         }
  180.     }

  181.     /**
  182.      * Because there are so many connect() methods, the _connectAction_() method is provided as a means of performing some action immediately after establishing
  183.      * a connection, rather than reimplementing all the connect() methods.
  184.      *
  185.      * @throws IOException If there is any problem with establishing the connection.
  186.      * @see org.apache.commons.net.SocketClient#_connectAction_()
  187.      */
  188.     @Override
  189.     protected void _connectAction_() throws IOException {
  190.         // Implicit mode.
  191.         if (isImplicit) {
  192.             applySocketAttributes();
  193.             sslNegotiation();
  194.         }
  195.         super._connectAction_();
  196.         // Explicit mode.
  197.         if (!isImplicit) {
  198.             execAUTH();
  199.             sslNegotiation();
  200.         }
  201.     }

  202.     /**
  203.      * Returns a socket of the data connection. Wrapped as an {@link SSLSocket}, which carries out handshake processing.
  204.      *
  205.      * @param command The int representation of the FTP command to send.
  206.      * @param arg     The arguments to the FTP command. If this parameter is set to null, then the command is sent with no arguments.
  207.      * @return corresponding to the established data connection. Null is returned if an FTP protocol error is reported at any point during the establishment and
  208.      *         initialization of the connection.
  209.      * @throws IOException If there is any problem with the connection.
  210.      * @see FTPClient#_openDataConnection_(int, String)
  211.      * @deprecated (3.3) Use {@link FTPClient#_openDataConnection_(FTPCmd, String)} instead
  212.      */
  213.     @Override
  214.     // Strictly speaking this is not needed, but it works round a Clirr bug
  215.     // So rather than invoke the parent code, we do it here
  216.     @Deprecated
  217.     protected Socket _openDataConnection_(final int command, final String arg) throws IOException {
  218.         return _openDataConnection_(FTPCommand.getCommand(command), arg);
  219.     }

  220.     /**
  221.      * Returns a socket of the data connection. Wrapped as an {@link SSLSocket}, which carries out handshake processing.
  222.      *
  223.      * @param command The textual representation of the FTP command to send.
  224.      * @param arg     The arguments to the FTP command. If this parameter is set to null, then the command is sent with no arguments.
  225.      * @return corresponding to the established data connection. Null is returned if an FTP protocol error is reported at any point during the establishment and
  226.      *         initialization of the connection.
  227.      * @throws IOException If there is any problem with the connection.
  228.      * @see FTPClient#_openDataConnection_(int, String)
  229.      * @since 3.2
  230.      */
  231.     @Override
  232.     protected Socket _openDataConnection_(final String command, final String arg) throws IOException {
  233.         final Socket socket = openDataSecureConnection(command, arg);
  234.         _prepareDataSocket_(socket);
  235.         if (socket instanceof SSLSocket) {
  236.             final SSLSocket sslSocket = (SSLSocket) socket;

  237.             sslSocket.setUseClientMode(isClientMode);
  238.             sslSocket.setEnableSessionCreation(isCreation);

  239.             // server mode
  240.             if (!isClientMode) {
  241.                 sslSocket.setNeedClientAuth(isNeedClientAuth);
  242.                 sslSocket.setWantClientAuth(isWantClientAuth);
  243.             }
  244.             if (suites != null) {
  245.                 sslSocket.setEnabledCipherSuites(suites);
  246.             }
  247.             if (protocols != null) {
  248.                 sslSocket.setEnabledProtocols(protocols);
  249.             }
  250.             sslSocket.startHandshake();
  251.         }

  252.         return socket;
  253.     }

  254.     /**
  255.      * Performs any custom initialization for a newly created SSLSocket (before the SSL handshake happens). Called by {@link #_openDataConnection_(int, String)}
  256.      * immediately after creating the socket. The default implementation is a no-op
  257.      *
  258.      * @param socket the socket to set up
  259.      * @throws IOException on error
  260.      * @since 3.1
  261.      */
  262.     protected void _prepareDataSocket_(final Socket socket) throws IOException {
  263.     }

  264.     /**
  265.      * Check the value that can be set in PROT Command value.
  266.      *
  267.      * @param prot Data Channel Protection Level.
  268.      * @return True - A set point is right / False - A set point is not right
  269.      */
  270.     private boolean checkPROTValue(final String prot) {
  271.         for (final String element : PROT_COMMAND_VALUE) {
  272.             if (element.equals(prot)) {
  273.                 return true;
  274.             }
  275.         }
  276.         return false;
  277.     }

  278.     /**
  279.      * Close open sockets.
  280.      *
  281.      * @param socket    main socket for proxy if enabled
  282.      * @param sslSocket ssl socket
  283.      * @throws IOException closing sockets is not successful
  284.      */
  285.     private void closeSockets(final Socket socket, final Socket sslSocket) throws IOException {
  286.         if (socket != null) {
  287.             socket.close();
  288.         }
  289.         if (sslSocket != null) {
  290.             sslSocket.close();
  291.         }
  292.     }

  293.     /**
  294.      * Create SSL socket from plain socket.
  295.      *
  296.      * @param socket
  297.      * @return SSL Socket
  298.      * @throws IOException
  299.      */
  300.     private SSLSocket createSSLSocket(final Socket socket) throws IOException {
  301.         if (socket != null) {
  302.             final SSLSocketFactory f = context.getSocketFactory();
  303.             return (SSLSocket) f.createSocket(socket, _hostname_, socket.getPort(), false);
  304.         }
  305.         return null;
  306.     }

  307.     /**
  308.      * Closes the connection to the FTP server and restores connection parameters to the default values.
  309.      * <p>
  310.      * Calls {@code setSocketFactory(null)} and {@code setServerSocketFactory(null)} to reset the factories that may have been changed during the session, e.g.
  311.      * by {@link #execPROT(String)}
  312.      *
  313.      * @throws IOException If an error occurs while disconnecting.
  314.      * @since 3.0
  315.      */
  316.     @Override
  317.     public void disconnect() throws IOException {
  318.         super.disconnect();
  319.         if (plainSocket != null) {
  320.             plainSocket.close();
  321.         }
  322.         setSocketFactory(null);
  323.         setServerSocketFactory(null);
  324.     }

  325.     /**
  326.      * Sends the ADAT command with the specified authentication data.
  327.      *
  328.      * @param data The data to send with the command.
  329.      * @return server reply.
  330.      * @throws IOException If an I/O error occurs while sending the command.
  331.      * @since 3.0
  332.      */
  333.     public int execADAT(final byte[] data) throws IOException {
  334.         if (data != null) {
  335.             return sendCommand(CMD_ADAT, Base64.getEncoder().encodeToString(data));
  336.         }
  337.         return sendCommand(CMD_ADAT);
  338.     }

  339.     /**
  340.      * Sends the AUTH command.
  341.      *
  342.      * @throws SSLException If the server reply code equals neither "234" nor "334".
  343.      * @throws IOException  If an I/O error occurs while either sending the command.
  344.      */
  345.     protected void execAUTH() throws SSLException, IOException {
  346.         final int replyCode = sendCommand(CMD_AUTH, auth);
  347.         if (FTPReply.SECURITY_MECHANISM_IS_OK == replyCode) {
  348.             // replyCode = 334
  349.             // I carry out an ADAT command.
  350.         } else if (FTPReply.SECURITY_DATA_EXCHANGE_COMPLETE != replyCode) {
  351.             throw new SSLException(getReplyString());
  352.         }
  353.     }

  354.     /**
  355.      * Sends the AUTH command with the specified mechanism.
  356.      *
  357.      * @param mechanism The mechanism name to send with the command.
  358.      * @return server reply.
  359.      * @throws IOException If an I/O error occurs while sending the command.
  360.      * @since 3.0
  361.      */
  362.     public int execAUTH(final String mechanism) throws IOException {
  363.         return sendCommand(CMD_AUTH, mechanism);
  364.     }

  365.     /**
  366.      * Sends the CCC command to the server. The CCC (Clear Command Channel) command causes the underlying {@link SSLSocket} instance to be assigned to a plain
  367.      * {@link Socket} instances
  368.      *
  369.      * @return server reply.
  370.      * @throws IOException If an I/O error occurs while sending the command.
  371.      * @since 3.0
  372.      */
  373.     public int execCCC() throws IOException {

  374. // This will be performed by sendCommand(String, String)
  375. //        if (FTPReply.isPositiveCompletion(repCode)) {
  376. //            _socket_.close();
  377. //            _socket_ = plainSocket;
  378. //            _controlInput_ = new BufferedReader(
  379. //                new InputStreamReader(
  380. //                    _socket_.getInputStream(), getControlEncoding()));
  381. //            _controlOutput_ = new BufferedWriter(
  382. //                new OutputStreamWriter(
  383. //                    _socket_.getOutputStream(), getControlEncoding()));
  384. //        }
  385.         return sendCommand(CMD_CCC);
  386.     }

  387.     /**
  388.      * Sends the CONF command with the specified data.
  389.      *
  390.      * @param data The data to send with the command.
  391.      * @return server reply.
  392.      * @throws IOException If an I/O error occurs while sending the command.
  393.      * @since 3.0
  394.      */
  395.     public int execCONF(final byte[] data) throws IOException {
  396.         if (data != null) {
  397.             return sendCommand(CMD_CONF, Base64.getEncoder().encodeToString(data));
  398.         }
  399.         return sendCommand(CMD_CONF, ""); // perhaps "=" or just sendCommand(String)?
  400.     }

  401.     /**
  402.      * Sends the ENC command with the specified data.
  403.      *
  404.      * @param data The data to send with the command.
  405.      * @return server reply.
  406.      * @throws IOException If an I/O error occurs while sending the command.
  407.      * @since 3.0
  408.      */
  409.     public int execENC(final byte[] data) throws IOException {
  410.         if (data != null) {
  411.             return sendCommand(CMD_ENC, Base64.getEncoder().encodeToString(data));
  412.         }
  413.         return sendCommand(CMD_ENC, ""); // perhaps "=" or just sendCommand(String)?
  414.     }

  415.     /**
  416.      * Sends the MIC command with the specified data.
  417.      *
  418.      * @param data The data to send with the command.
  419.      * @return server reply.
  420.      * @throws IOException If an I/O error occurs while sending the command.
  421.      * @since 3.0
  422.      */
  423.     public int execMIC(final byte[] data) throws IOException {
  424.         if (data != null) {
  425.             return sendCommand(CMD_MIC, Base64.getEncoder().encodeToString(data));
  426.         }
  427.         return sendCommand(CMD_MIC, ""); // perhaps "=" or just sendCommand(String)?
  428.     }

  429.     /**
  430.      * PBSZ command. pbsz value: 0 to (2^32)-1 decimal integer.
  431.      *
  432.      * @param pbsz Protection Buffer Size.
  433.      * @throws SSLException If the server reply code does not equal "200".
  434.      * @throws IOException  If an I/O error occurs while sending the command.
  435.      * @see #parsePBSZ(long)
  436.      */
  437.     public void execPBSZ(final long pbsz) throws SSLException, IOException {
  438.         if (pbsz < 0 || 4294967295L < pbsz) { // 32-bit unsigned number
  439.             throw new IllegalArgumentException();
  440.         }
  441.         final int status = sendCommand(CMD_PBSZ, String.valueOf(pbsz));
  442.         if (FTPReply.COMMAND_OK != status) {
  443.             throw new SSLException(getReplyString());
  444.         }
  445.     }

  446.     /**
  447.      * PROT command.
  448.      * <ul>
  449.      * <li>C - Clear</li>
  450.      * <li>S - Safe(SSL protocol only)</li>
  451.      * <li>E - Confidential(SSL protocol only)</li>
  452.      * <li>P - Private</li>
  453.      * </ul>
  454.      * <b>N.B.</b> the method calls {@link #setSocketFactory(javax.net.SocketFactory)} and {@link #setServerSocketFactory(javax.net.ServerSocketFactory)}
  455.      *
  456.      * @param prot Data Channel Protection Level, if {@code null}, use {@link #DEFAULT_PROT}.
  457.      * @throws SSLException If the server reply code does not equal {@code 200}.
  458.      * @throws IOException  If an I/O error occurs while sending the command.
  459.      */
  460.     public void execPROT(String prot) throws SSLException, IOException {
  461.         if (prot == null) {
  462.             prot = DEFAULT_PROT;
  463.         }
  464.         if (!checkPROTValue(prot)) {
  465.             throw new IllegalArgumentException();
  466.         }
  467.         if (FTPReply.COMMAND_OK != sendCommand(CMD_PROT, prot)) {
  468.             throw new SSLException(getReplyString());
  469.         }
  470.         if (DEFAULT_PROT.equals(prot)) {
  471.             setSocketFactory(null);
  472.             setServerSocketFactory(null);
  473.         } else {
  474.             setSocketFactory(new FTPSSocketFactory(context));
  475.             setServerSocketFactory(new FTPSServerSocketFactory(context));
  476.             initSslContext();
  477.         }
  478.     }

  479.     /**
  480.      * Extract the data from a reply with a prefix, e.g. PBSZ=1234 => 1234
  481.      *
  482.      * @param prefix the prefix to find
  483.      * @param reply  where to find the prefix
  484.      * @return the remainder of the string after the prefix, or null if the prefix was not present.
  485.      */
  486.     private String extractPrefixedData(final String prefix, final String reply) {
  487.         final int idx = reply.indexOf(prefix);
  488.         if (idx == -1) {
  489.             return null;
  490.         }
  491.         // N.B. Cannot use trim before substring as leading space would affect the offset.
  492.         return reply.substring(idx + prefix.length()).trim();
  493.     }

  494.     /**
  495.      * Return AUTH command use value.
  496.      *
  497.      * @return AUTH command use value.
  498.      */
  499.     public String getAuthValue() {
  500.         return this.auth;
  501.     }

  502.     /**
  503.      * 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}
  504.      * instance, returns null.
  505.      *
  506.      * @return An array of cipher suite names, or {@code null}
  507.      */
  508.     public String[] getEnabledCipherSuites() {
  509.         if (_socket_ instanceof SSLSocket) {
  510.             return ((SSLSocket) _socket_).getEnabledCipherSuites();
  511.         }
  512.         return null;
  513.     }

  514.     /**
  515.      * Returns the names of the protocol versions which are currently enabled for use on this connection. When the underlying {@link Socket} is not an
  516.      * {@link SSLSocket} instance, returns null.
  517.      *
  518.      * @return An array of protocols, or {@code null}
  519.      */
  520.     public String[] getEnabledProtocols() {
  521.         if (_socket_ instanceof SSLSocket) {
  522.             return ((SSLSocket) _socket_).getEnabledProtocols();
  523.         }
  524.         return null;
  525.     }

  526.     /**
  527.      * Returns true if new SSL sessions may be established by this socket. When the underlying {@link Socket} instance is not SSL-enabled (i.e. an instance of
  528.      * {@link SSLSocket} with {@link SSLSocket}{@link #getEnableSessionCreation()}) enabled, this returns False.
  529.      *
  530.      * @return true - Indicates that sessions may be created; this is the default. false - indicates that an existing session must be resumed.
  531.      */
  532.     public boolean getEnableSessionCreation() {
  533.         if (_socket_ instanceof SSLSocket) {
  534.             return ((SSLSocket) _socket_).getEnableSessionCreation();
  535.         }
  536.         return false;
  537.     }

  538.     /**
  539.      * Gets the currently configured {@link HostnameVerifier}. The verifier is only used on client mode connections.
  540.      *
  541.      * @return A HostnameVerifier instance.
  542.      * @since 3.4
  543.      */
  544.     public HostnameVerifier getHostnameVerifier() {
  545.         return hostnameVerifier;
  546.     }

  547.     /**
  548.      * Gets the {@link KeyManager} instance.
  549.      *
  550.      * @return The {@link KeyManager} instance
  551.      */
  552.     private KeyManager getKeyManager() {
  553.         return keyManager;
  554.     }

  555.     /**
  556.      * Returns true if the socket will require client authentication. When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns false.
  557.      *
  558.      * @return true - If the server mode socket should request that the client authenticate itself.
  559.      */
  560.     public boolean getNeedClientAuth() {
  561.         if (_socket_ instanceof SSLSocket) {
  562.             return ((SSLSocket) _socket_).getNeedClientAuth();
  563.         }
  564.         return false;
  565.     }

  566.     /**
  567.      * Gets the secure socket protocol to be used, e.g. SSL/TLS.
  568.      * @since 3.11.0
  569.      * @return the protocol
  570.      */
  571.     protected String getProtocol() {
  572.         return protocol;
  573.     }

  574.     /**
  575.      * Gets the protocol versions. The {@link #getEnabledProtocols()} method gets the value from the socket while
  576.      * this method gets its value from this instance's config.
  577.      * @since 3.11.0
  578.      * @return a clone of the protocols, may be null
  579.      */
  580.     protected String[] getProtocols() {
  581.         return protocols == null ? null : protocols.clone();
  582.     }

  583.     /**
  584.      * Gets the cipher suites. The {@link #getEnabledCipherSuites()} method gets the value from the socket while
  585.      * this method gets its value from this instance's config.
  586.      * @since 3.11.0
  587.      * @return a clone of the suites, may be null
  588.      */
  589.     protected String[] getSuites() {
  590.         return suites == null ? null : suites.clone();
  591.     }

  592.     /**
  593.      * Gets the currently configured {@link TrustManager}.
  594.      *
  595.      * @return A TrustManager instance.
  596.      */
  597.     public TrustManager getTrustManager() {
  598.         return trustManager;
  599.     }

  600.     /**
  601.      * Returns true if the socket is set to use client mode in its first handshake. When the underlying {@link Socket} is not an {@link SSLSocket} instance,
  602.      * returns false.
  603.      *
  604.      * @return true - If the socket should start its first handshake in "client" mode.
  605.      */
  606.     public boolean getUseClientMode() {
  607.         if (_socket_ instanceof SSLSocket) {
  608.             return ((SSLSocket) _socket_).getUseClientMode();
  609.         }
  610.         return false;
  611.     }

  612.     /**
  613.      * Returns true if the socket will request client authentication. When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns false.
  614.      *
  615.      * @return true - If the server mode socket should request that the client authenticate itself.
  616.      */
  617.     public boolean getWantClientAuth() {
  618.         if (_socket_ instanceof SSLSocket) {
  619.             return ((SSLSocket) _socket_).getWantClientAuth();
  620.         }
  621.         return false;
  622.     }

  623.     /**
  624.      * Performs a lazy init of the SSL context
  625.      *
  626.      * @throws IOException
  627.      */
  628.     private void initSslContext() throws IOException {
  629.         if (context == null) {
  630.             context = SSLContextUtils.createSSLContext(protocol, getKeyManager(), getTrustManager());
  631.         }
  632.     }

  633.     /**
  634.      * Gets the use client mode flag. The {@link #getUseClientMode()} method gets the value from the socket while
  635.      * this method gets its value from this instance's config.
  636.      * @since 3.11.0
  637.      * @return True If the socket should start its first handshake in "client" mode.
  638.      */
  639.     protected boolean isClientMode() {
  640.         return isClientMode;
  641.     }

  642.     /**
  643.      * Gets whether a new SSL session may be established by this socket. Default true
  644.      * @since 3.11.0
  645.      * @return True if session may be established
  646.      */
  647.     protected boolean isCreation() {
  648.         return isCreation;
  649.     }

  650.     /**
  651.      * Return whether or not endpoint identification using the HTTPS algorithm on Java 1.7+ is enabled. The default behavior is for this to be disabled.
  652.      *
  653.      * This check is only performed on client mode connections.
  654.      *
  655.      * @return True if enabled, false if not.
  656.      * @since 3.4
  657.      */
  658.     public boolean isEndpointCheckingEnabled() {
  659.         return tlsEndpointChecking;
  660.     }

  661.     /**
  662.      * Gets the security mode. (True - Implicit Mode / False - Explicit Mode)
  663.      * @since 3.11.0
  664.      * @return True if enabled, false if not.
  665.      */
  666.     protected boolean isImplicit() {
  667.         return isImplicit;
  668.     }

  669.     /**
  670.      * Gets the need client auth flag. The {@link #getNeedClientAuth()} method gets the value from the socket while
  671.      * this method gets its value from this instance's config.
  672.      * @since 3.11.0
  673.      * @return True if enabled, false if not.
  674.      */
  675.     protected boolean isNeedClientAuth() {
  676.         return isNeedClientAuth;
  677.     }

  678.     /**
  679.      * Gets the want client auth flag. The {@link #getWantClientAuth()} method gets the value from the socket while
  680.      * this method gets its value from this instance's config.
  681.      * @since 3.11.0
  682.      * @return True if enabled, false if not.
  683.      */
  684.     protected boolean isWantClientAuth() {
  685.         return isWantClientAuth;
  686.     }

  687.     /**
  688.      * Establishes a data connection with the FTP server, returning a Socket for the connection if successful. If a restart offset has been set with
  689.      * {@link #setRestartOffset(long)}, a REST command is issued to the server with the offset as an argument before establishing the data connection. Active
  690.      * mode connections also cause a local PORT command to be issued.
  691.      *
  692.      * @param command The text representation of the FTP command to send.
  693.      * @param arg     The arguments to the FTP command. If this parameter is set to null, then the command is sent with no argument.
  694.      * @return A Socket corresponding to the established data connection. Null is returned if an FTP protocol error is reported at any point during the
  695.      *         establishment and initialization of the connection.
  696.      * @throws IOException If an I/O error occurs while either sending a command to the server or receiving a reply from the server.
  697.      * @since 3.1
  698.      */
  699.     private Socket openDataSecureConnection(final String command, final String arg) throws IOException {
  700.         if (getDataConnectionMode() != ACTIVE_LOCAL_DATA_CONNECTION_MODE && getDataConnectionMode() != PASSIVE_LOCAL_DATA_CONNECTION_MODE) {
  701.             return null;
  702.         }

  703.         final boolean isInet6Address = getRemoteAddress() instanceof Inet6Address;

  704.         final Socket socket;
  705.         Socket sslSocket = null;
  706.         final int soTimeoutMillis = DurationUtils.toMillisInt(getDataTimeout());
  707.         if (getDataConnectionMode() == ACTIVE_LOCAL_DATA_CONNECTION_MODE) {
  708.             // if no activePortRange was set (correctly) -> getActivePort() = 0
  709.             // -> new ServerSocket(0) -> bind to any free local port
  710.             try (final ServerSocket server = _serverSocketFactory_.createServerSocket(getActivePort(), 1, getHostAddress())) {
  711.                 // Try EPRT only if remote server is over IPv6, if not use PORT,
  712.                 // because EPRT has no advantage over PORT on IPv4.
  713.                 // It could even have the disadvantage,
  714.                 // that EPRT will make the data connection fail, because
  715.                 // today's intelligent NAT Firewalls are able to
  716.                 // substitute IP addresses in the PORT command,
  717.                 // but might not be able to recognize the EPRT command.
  718.                 if (isInet6Address) {
  719.                     if (!FTPReply.isPositiveCompletion(eprt(getReportHostAddress(), server.getLocalPort()))) {
  720.                         return null;
  721.                     }
  722.                 } else if (!FTPReply.isPositiveCompletion(port(getReportHostAddress(), server.getLocalPort()))) {
  723.                     return null;
  724.                 }

  725.                 if (getRestartOffset() > 0 && !restart(getRestartOffset())) {
  726.                     return null;
  727.                 }

  728.                 if (!FTPReply.isPositivePreliminary(sendCommand(command, arg))) {
  729.                     return null;
  730.                 }

  731.                 // For now, let's just use the data timeout value for waiting for
  732.                 // the data connection. It may be desirable to let this be a
  733.                 // separately configurable value. In any case, we really want
  734.                 // to allow preventing the accept from blocking indefinitely.
  735.                 if (soTimeoutMillis >= 0) {
  736.                     server.setSoTimeout(soTimeoutMillis);
  737.                 }
  738.                 socket = server.accept();

  739.                 // Ensure the timeout is set before any commands are issued on the new socket
  740.                 if (soTimeoutMillis >= 0) {
  741.                     socket.setSoTimeout(soTimeoutMillis);
  742.                 }
  743.                 if (getReceiveDataSocketBufferSize() > 0) {
  744.                     socket.setReceiveBufferSize(getReceiveDataSocketBufferSize());
  745.                 }
  746.                 if (getSendDataSocketBufferSize() > 0) {
  747.                     socket.setSendBufferSize(getSendDataSocketBufferSize());
  748.                 }
  749.             }
  750.         } else { // We must be in PASSIVE_LOCAL_DATA_CONNECTION_MODE

  751.             // Try EPSV command first on IPv6 - and IPv4 if enabled.
  752.             // When using IPv4 with NAT it has the advantage
  753.             // to work with more rare configurations.
  754.             // E.g. if FTP server has a static PASV address (external network)
  755.             // and the client is coming from another internal network.
  756.             // In that case the data connection after PASV command would fail,
  757.             // while EPSV would make the client succeed by taking just the port.
  758.             final boolean attemptEPSV = isUseEPSVwithIPv4() || isInet6Address;
  759.             if (attemptEPSV && epsv() == FTPReply.ENTERING_EPSV_MODE) {
  760.                 _parseExtendedPassiveModeReply(_replyLines.get(0));
  761.             } else {
  762.                 if (isInet6Address) {
  763.                     return null; // Must use EPSV for IPV6
  764.                 }
  765.                 // If EPSV failed on IPV4, revert to PASV
  766.                 if (pasv() != FTPReply.ENTERING_PASSIVE_MODE) {
  767.                     return null;
  768.                 }
  769.                 _parsePassiveModeReply(_replyLines.get(0));
  770.             }

  771.             if (getProxy() != null) {
  772.                 socket = new Socket(getProxy());
  773.             } else {
  774.                 socket = _socketFactory_.createSocket();
  775.             }

  776.             if (getReceiveDataSocketBufferSize() > 0) {
  777.                 socket.setReceiveBufferSize(getReceiveDataSocketBufferSize());
  778.             }
  779.             if (getSendDataSocketBufferSize() > 0) {
  780.                 socket.setSendBufferSize(getSendDataSocketBufferSize());
  781.             }
  782.             if (getPassiveLocalIPAddress() != null) {
  783.                 socket.bind(new InetSocketAddress(getPassiveLocalIPAddress(), 0));
  784.             }

  785.             // For now, let's just use the data timeout value for waiting for
  786.             // the data connection. It may be desirable to let this be a
  787.             // separately configurable value. In any case, we really want
  788.             // to allow preventing the accept from blocking indefinitely.
  789.             if (soTimeoutMillis >= 0) {
  790.                 socket.setSoTimeout(soTimeoutMillis);
  791.             }

  792.             socket.connect(new InetSocketAddress(getPassiveHost(), getPassivePort()), connectTimeout);

  793.             if (getProxy() != null) {
  794.                 sslSocket = context.getSocketFactory().createSocket(socket, getPassiveHost(), getPassivePort(), true);
  795.             }

  796.             if (getRestartOffset() > 0 && !restart(getRestartOffset())) {
  797.                 closeSockets(socket, sslSocket);
  798.                 return null;
  799.             }

  800.             if (!FTPReply.isPositivePreliminary(sendCommand(command, arg))) {
  801.                 closeSockets(socket, sslSocket);
  802.                 return null;
  803.             }
  804.         }

  805.         if (isRemoteVerificationEnabled() && !verifyRemote(socket)) {
  806.             // Grab the host before we close the socket to avoid NET-663
  807.             final InetAddress socketHost = socket.getInetAddress();

  808.             closeSockets(socket, sslSocket);

  809.             throw new IOException(
  810.                     "Host attempting data connection " + socketHost.getHostAddress() + " is not same as server " + getRemoteAddress().getHostAddress());
  811.         }

  812.         return getProxy() != null ? sslSocket : socket;
  813.     }

  814.     /**
  815.      * Parses the given ADAT response line and base64-decodes the data.
  816.      *
  817.      * @param reply The ADAT reply to parse.
  818.      * @return the data in the reply, base64-decoded.
  819.      * @since 3.0
  820.      */
  821.     public byte[] parseADATReply(final String reply) {
  822.         if (reply == null) {
  823.             return null;
  824.         }
  825.         return Base64.getDecoder().decode(extractPrefixedData("ADAT=", reply));
  826.     }

  827.     /**
  828.      * PBSZ command. pbsz value: 0 to (2^32)-1 decimal integer. Issues the command and parses the response to return the negotiated value.
  829.      *
  830.      * @param pbsz Protection Buffer Size.
  831.      * @throws SSLException If the server reply code does not equal "200".
  832.      * @throws IOException  If an I/O error occurs while sending the command.
  833.      * @return the negotiated value.
  834.      * @see #execPBSZ(long)
  835.      * @since 3.0
  836.      */
  837.     public long parsePBSZ(final long pbsz) throws SSLException, IOException {
  838.         execPBSZ(pbsz);
  839.         long minvalue = pbsz;
  840.         final String remainder = extractPrefixedData("PBSZ=", getReplyString());
  841.         if (remainder != null) {
  842.             final long replysz = Long.parseLong(remainder);
  843.             if (replysz < minvalue) {
  844.                 minvalue = replysz;
  845.             }
  846.         }
  847.         return minvalue;
  848.     }

  849.     // DEPRECATED - for API compatibility only - DO NOT USE

  850.     /**
  851.      * Send an FTP command. A successful CCC (Clear Command Channel) command causes the underlying {@link SSLSocket} instance to be assigned to a plain
  852.      * {@link Socket}
  853.      *
  854.      * @param command The FTP command.
  855.      * @return server reply.
  856.      * @throws IOException  If an I/O error occurs while sending the command.
  857.      * @throws SSLException if a CCC command fails
  858.      * @see org.apache.commons.net.ftp.FTP#sendCommand(String)
  859.      */
  860.     // Would like to remove this method, but that will break any existing clients that are using CCC
  861.     @Override
  862.     public int sendCommand(final String command, final String args) throws IOException {
  863.         final int repCode = super.sendCommand(command, args);
  864.         /* If CCC is issued, restore socket i/o streams to unsecured versions */
  865.         if (CMD_CCC.equals(command)) {
  866.             if (FTPReply.COMMAND_OK != repCode) {
  867.                 throw new SSLException(getReplyString());
  868.             }
  869.             _socket_.close();
  870.             _socket_ = plainSocket;
  871.             _controlInput_ = new BufferedReader(new InputStreamReader(_socket_.getInputStream(), getControlEncoding()));
  872.             _controlOutput_ = new BufferedWriter(new OutputStreamWriter(_socket_.getOutputStream(), getControlEncoding()));
  873.         }
  874.         return repCode;
  875.     }

  876.     /**
  877.      * Sets AUTH command use value. This processing is done before connected processing.
  878.      *
  879.      * @param auth AUTH command use value.
  880.      */
  881.     public void setAuthValue(final String auth) {
  882.         this.auth = auth;
  883.     }

  884.     /**
  885.      * Controls which particular cipher suites are enabled for use on this connection. Called before server negotiation.
  886.      *
  887.      * @param cipherSuites The cipher suites.
  888.      */
  889.     public void setEnabledCipherSuites(final String[] cipherSuites) {
  890.         suites = cipherSuites.clone();
  891.     }

  892.     /**
  893.      * Controls which particular protocol versions are enabled for use on this connection. I perform setting before a server negotiation.
  894.      *
  895.      * @param protocolVersions The protocol versions.
  896.      */
  897.     public void setEnabledProtocols(final String[] protocolVersions) {
  898.         protocols = protocolVersions.clone();
  899.     }

  900.     /**
  901.      * Controls whether a new SSL session may be established by this socket.
  902.      *
  903.      * @param isCreation The established socket flag.
  904.      */
  905.     public void setEnabledSessionCreation(final boolean isCreation) {
  906.         this.isCreation = isCreation;
  907.     }

  908.     /**
  909.      * Automatic endpoint identification checking using the HTTPS algorithm is supported on Java 1.7+. The default behavior is for this to be disabled.
  910.      *
  911.      * This check is only performed on client mode connections.
  912.      *
  913.      * @param enable Enable automatic endpoint identification checking using the HTTPS algorithm on Java 1.7+.
  914.      * @since 3.4
  915.      */
  916.     public void setEndpointCheckingEnabled(final boolean enable) {
  917.         tlsEndpointChecking = enable;
  918.     }

  919.     /**
  920.      * Override the default {@link HostnameVerifier} to use. The verifier is only used on client mode connections.
  921.      *
  922.      * @param newHostnameVerifier The HostnameVerifier implementation to set or {@code null} to disable.
  923.      * @since 3.4
  924.      */
  925.     public void setHostnameVerifier(final HostnameVerifier newHostnameVerifier) {
  926.         hostnameVerifier = newHostnameVerifier;
  927.     }

  928.     /**
  929.      * Sets a {@link KeyManager} to use
  930.      *
  931.      * @param keyManager The KeyManager implementation to set.
  932.      * @see org.apache.commons.net.util.KeyManagerUtils
  933.      */
  934.     public void setKeyManager(final KeyManager keyManager) {
  935.         this.keyManager = keyManager;
  936.     }

  937.     /**
  938.      * Configures the socket to require client authentication.
  939.      *
  940.      * @param isNeedClientAuth The need client auth flag.
  941.      */
  942.     public void setNeedClientAuth(final boolean isNeedClientAuth) {
  943.         this.isNeedClientAuth = isNeedClientAuth;
  944.     }

  945.     /**
  946.      * Override the default {@link TrustManager} to use; if set to {@code null}, the default TrustManager from the JVM will be used.
  947.      *
  948.      * @param trustManager The TrustManager implementation to set, may be {@code null}
  949.      * @see org.apache.commons.net.util.TrustManagerUtils
  950.      */
  951.     public void setTrustManager(final TrustManager trustManager) {
  952.         this.trustManager = trustManager;
  953.     }

  954.     /**
  955.      * Configures the socket to use client (or server) mode in its first handshake.
  956.      *
  957.      * @param isClientMode The use client mode flag.
  958.      */
  959.     public void setUseClientMode(final boolean isClientMode) {
  960.         this.isClientMode = isClientMode;
  961.     }

  962.     /**
  963.      * Configures the socket to request client authentication, but only if such a request is appropriate to the cipher suite negotiated.
  964.      *
  965.      * @param isWantClientAuth The want client auth flag.
  966.      */
  967.     public void setWantClientAuth(final boolean isWantClientAuth) {
  968.         this.isWantClientAuth = isWantClientAuth;
  969.     }

  970.     /**
  971.      * SSL/TLS negotiation. Acquires an SSL socket of a control connection and carries out handshake processing.
  972.      *
  973.      * @throws IOException If server negotiation fails
  974.      */
  975.     protected void sslNegotiation() throws IOException {
  976.         plainSocket = _socket_;
  977.         initSslContext();
  978.         final SSLSocket socket = createSSLSocket(_socket_);
  979.         socket.setEnableSessionCreation(isCreation);
  980.         socket.setUseClientMode(isClientMode);

  981.         // client mode
  982.         if (isClientMode) {
  983.             if (tlsEndpointChecking) {
  984.                 SSLSocketUtils.enableEndpointNameVerification(socket);
  985.             }
  986.         } else { // server mode
  987.             socket.setNeedClientAuth(isNeedClientAuth);
  988.             socket.setWantClientAuth(isWantClientAuth);
  989.         }

  990.         if (protocols != null) {
  991.             socket.setEnabledProtocols(protocols);
  992.         }
  993.         if (suites != null) {
  994.             socket.setEnabledCipherSuites(suites);
  995.         }
  996.         socket.startHandshake();

  997.         // TODO the following setup appears to duplicate that in the super class methods
  998.         _socket_ = socket;
  999.         _controlInput_ = new BufferedReader(new InputStreamReader(socket.getInputStream(), getControlEncoding()));
  1000.         _controlOutput_ = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), getControlEncoding()));

  1001.         if (isClientMode && hostnameVerifier != null && !hostnameVerifier.verify(_hostname_, socket.getSession())) {
  1002.             throw new SSLHandshakeException("Hostname doesn't match certificate");
  1003.         }
  1004.     }
  1005. }