001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      https://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.net.ftp;
019
020import java.io.BufferedReader;
021import java.io.BufferedWriter;
022import java.io.IOException;
023import java.io.InputStreamReader;
024import java.io.OutputStreamWriter;
025import java.net.Inet6Address;
026import java.net.InetAddress;
027import java.net.InetSocketAddress;
028import java.net.ServerSocket;
029import java.net.Socket;
030import java.util.Base64;
031
032import javax.net.ssl.HostnameVerifier;
033import javax.net.ssl.KeyManager;
034import javax.net.ssl.SSLContext;
035import javax.net.ssl.SSLException;
036import javax.net.ssl.SSLHandshakeException;
037import javax.net.ssl.SSLSocket;
038import javax.net.ssl.SSLSocketFactory;
039import javax.net.ssl.TrustManager;
040
041import org.apache.commons.io.IOUtils;
042import org.apache.commons.net.util.SSLContextUtils;
043import org.apache.commons.net.util.SSLSocketUtils;
044import org.apache.commons.net.util.TrustManagerUtils;
045
046/**
047 * FTP over SSL processing. If desired, the JVM property -Djavax.net.debug=all can be used to see wire-level SSL details.
048 *
049 * Warning: the hostname is not verified against the certificate by default, use {@link #setHostnameVerifier(HostnameVerifier)} or
050 * {@link #setEndpointCheckingEnabled(boolean)} (on Java 1.7+) to enable verification. Verification is only performed on client mode connections.
051 *
052 * @since 2.0
053 */
054public class FTPSClient extends FTPClient {
055
056// From http://www.iana.org/assignments/port-numbers
057
058//    ftps-data   989/tcp    ftp protocol, data, over TLS/SSL
059//    ftps-data   989/udp    ftp protocol, data, over TLS/SSL
060//    ftps        990/tcp    ftp protocol, control, over TLS/SSL
061//    ftps        990/udp    ftp protocol, control, over TLS/SSL
062
063    /** Default FTPS data port. */
064    public static final int DEFAULT_FTPS_DATA_PORT = 989;
065
066    /** Default FTPS port. */
067    public static final int DEFAULT_FTPS_PORT = 990;
068
069    /** The value that I can set in PROT command (C = Clear, P = Protected) */
070    private static final String[] PROT_COMMAND_VALUE = { "C", "E", "S", "P" };
071
072    /** Default PROT Command */
073    private static final String DEFAULT_PROT = "C";
074
075    /** Default secure socket protocol name, i.e. TLS */
076    private static final String DEFAULT_PROTOCOL = "TLS";
077
078    /** The AUTH (Authentication/Security Mechanism) command. */
079    private static final String CMD_AUTH = "AUTH";
080
081    /** The ADAT (Authentication/Security Data) command. */
082    private static final String CMD_ADAT = "ADAT";
083
084    /** The PROT (Data Channel Protection Level) command. */
085    private static final String CMD_PROT = "PROT";
086
087    /** The PBSZ (Protection Buffer Size) command. */
088    private static final String CMD_PBSZ = "PBSZ";
089
090    /** The MIC (Integrity Protected Command) command. */
091    private static final String CMD_MIC = "MIC";
092
093    /** The CONF (Confidentiality Protected Command) command. */
094    private static final String CMD_CONF = "CONF";
095
096    /** The ENC (Privacy Protected Command) command. */
097    private static final String CMD_ENC = "ENC";
098
099    /** The CCC (Clear Command Channel) command. */
100    private static final String CMD_CCC = "CCC";
101
102    /** @deprecated - not used - may be removed in a future release */
103    @Deprecated
104    public static String KEYSTORE_ALGORITHM;
105
106    /** @deprecated - not used - may be removed in a future release */
107    @Deprecated
108    public static String TRUSTSTORE_ALGORITHM;
109
110    /** @deprecated - not used - may be removed in a future release */
111    @Deprecated
112    public static String PROVIDER;
113
114    /** @deprecated - not used - may be removed in a future release */
115    @Deprecated
116    public static String STORE_TYPE;
117
118    /** The security mode. (True - Implicit Mode / False - Explicit Mode) */
119    private final boolean isImplicit;
120
121    /** The secure socket protocol to be used, e.g. SSL/TLS. */
122    private final String protocol;
123
124    /** The AUTH Command value */
125    private String auth = DEFAULT_PROTOCOL;
126
127    /** The context object. */
128    private SSLContext context;
129
130    /** The socket object. */
131    private Socket plainSocket;
132
133    /** Controls whether a new SSL session may be established by this socket. Default true. */
134    private boolean isCreation = true;
135
136    /** The use client mode flag. */
137    private boolean isClientMode = true;
138
139    /** The need client auth flag. */
140    private boolean isNeedClientAuth;
141
142    /** The want client auth flag. */
143    private boolean isWantClientAuth;
144
145    /** The cipher suites */
146    private String[] suites;
147
148    /** The protocol versions */
149    private String[] protocols;
150
151    /**
152     * The FTPS {@link TrustManager} implementation, default validate only {@link TrustManagerUtils#getValidateServerCertificateTrustManager()}.
153     */
154    private TrustManager trustManager = TrustManagerUtils.getValidateServerCertificateTrustManager();
155
156    /** The {@link KeyManager}, default null (i.e. use system default). */
157    private KeyManager keyManager;
158
159    /** The {@link HostnameVerifier} to use post-TLS, default null (i.e. no verification). */
160    private HostnameVerifier hostnameVerifier;
161
162    /** Use Java 1.7+ HTTPS Endpoint Identification Algorithm. */
163    private boolean tlsEndpointChecking;
164
165    /**
166     * Constructor for FTPSClient, calls {@link #FTPSClient(String, boolean)}.
167     *
168     * Sets protocol to {@link #DEFAULT_PROTOCOL} - i.e. TLS - and security mode to explicit (isImplicit = false)
169     */
170    public FTPSClient() {
171        this(DEFAULT_PROTOCOL, false);
172    }
173
174    /**
175     * Constructor for FTPSClient, using {@link #DEFAULT_PROTOCOL} - i.e. TLS Calls {@link #FTPSClient(String, boolean)}
176     *
177     * @param isImplicit The security mode (Implicit/Explicit).
178     */
179    public FTPSClient(final boolean isImplicit) {
180        this(DEFAULT_PROTOCOL, isImplicit);
181    }
182
183    /**
184     * Constructor for FTPSClient, using {@link #DEFAULT_PROTOCOL} - i.e. TLS The default TrustManager is set from
185     * {@link TrustManagerUtils#getValidateServerCertificateTrustManager()}
186     *
187     * @param isImplicit The security mode(Implicit/Explicit).
188     * @param context    A pre-configured SSL Context
189     */
190    public FTPSClient(final boolean isImplicit, final SSLContext context) {
191        this(DEFAULT_PROTOCOL, isImplicit);
192        this.context = context;
193    }
194
195    /**
196     * Constructor for FTPSClient, using {@link #DEFAULT_PROTOCOL} - i.e. TLS and isImplicit {@code false} Calls {@link #FTPSClient(boolean, SSLContext)}
197     *
198     * @param context A pre-configured SSL Context
199     */
200    public FTPSClient(final SSLContext context) {
201        this(false, context);
202    }
203
204    /**
205     * Constructor for FTPSClient, using explicit mode, calls {@link #FTPSClient(String, boolean)}.
206     *
207     * @param protocol the protocol to use
208     */
209    public FTPSClient(final String protocol) {
210        this(protocol, false);
211    }
212
213    /**
214     * Constructor for FTPSClient allowing specification of protocol and security mode. If isImplicit is true, the port is set to {@link #DEFAULT_FTPS_PORT}
215     * i.e. 990. The default TrustManager is set from {@link TrustManagerUtils#getValidateServerCertificateTrustManager()}
216     *
217     * @param protocol   the protocol
218     * @param isImplicit The security mode(Implicit/Explicit).
219     */
220    public FTPSClient(final String protocol, final boolean isImplicit) {
221        this.protocol = protocol;
222        this.isImplicit = isImplicit;
223        if (isImplicit) {
224            setDefaultPort(DEFAULT_FTPS_PORT);
225        }
226    }
227
228    /**
229     * Because there are so many connect() methods, the _connectAction_() method is provided as a means of performing some action immediately after establishing
230     * a connection, rather than reimplementing all the connect() methods.
231     *
232     * @throws IOException If there is any problem with establishing the connection.
233     * @see org.apache.commons.net.SocketClient#_connectAction_()
234     */
235    @Override
236    protected void _connectAction_() throws IOException {
237        // Implicit mode.
238        if (isImplicit) {
239            applySocketAttributes();
240            sslNegotiation();
241        }
242        super._connectAction_();
243        // Explicit mode.
244        if (!isImplicit) {
245            execAUTH();
246            sslNegotiation();
247        }
248    }
249
250    /**
251     * Returns a socket of the data connection. Wrapped as an {@link SSLSocket}, which carries out handshake processing.
252     *
253     * @param command The int representation of the FTP command to send.
254     * @param arg     The arguments to the FTP command. If this parameter is set to null, then the command is sent with no arguments.
255     * @return corresponding to the established data connection. Null is returned if an FTP protocol error is reported at any point during the establishment and
256     *         initialization of the connection.
257     * @throws IOException If there is any problem with the connection.
258     * @see FTPClient#_openDataConnection_(int, String)
259     * @deprecated (3.3) Use {@link FTPClient#_openDataConnection_(FTPCmd, String)} instead
260     */
261    @Override
262    // Strictly speaking this is not needed, but it works round a Clirr bug
263    // So rather than invoke the parent code, we do it here
264    @Deprecated
265    protected Socket _openDataConnection_(final int command, final String arg) throws IOException {
266        return _openDataConnection_(FTPCommand.getCommand(command), arg);
267    }
268
269    /**
270     * Returns a socket of the data connection. Wrapped as an {@link SSLSocket}, which carries out handshake processing.
271     *
272     * @param command The textual representation of the FTP command to send.
273     * @param arg     The arguments to the FTP command. If this parameter is set to null, then the command is sent with no arguments.
274     * @return corresponding to the established data connection. Null is returned if an FTP protocol error is reported at any point during the establishment and
275     *         initialization of the connection.
276     * @throws IOException If there is any problem with the connection.
277     * @see FTPClient#_openDataConnection_(int, String)
278     * @since 3.2
279     */
280    @Override
281    protected Socket _openDataConnection_(final String command, final String arg) throws IOException {
282        final Socket socket = openDataSecureConnection(command, arg);
283        _prepareDataSocket_(socket);
284        if (socket instanceof SSLSocket) {
285            final SSLSocket sslSocket = (SSLSocket) socket;
286
287            sslSocket.setUseClientMode(isClientMode);
288            sslSocket.setEnableSessionCreation(isCreation);
289
290            // server mode
291            if (!isClientMode) {
292                sslSocket.setNeedClientAuth(isNeedClientAuth);
293                sslSocket.setWantClientAuth(isWantClientAuth);
294            }
295            if (suites != null) {
296                sslSocket.setEnabledCipherSuites(suites);
297            }
298            if (protocols != null) {
299                sslSocket.setEnabledProtocols(protocols);
300            }
301            sslSocket.startHandshake();
302        }
303
304        return socket;
305    }
306
307    /**
308     * Performs any custom initialization for a newly created SSLSocket (before the SSL handshake happens). Called by {@link #_openDataConnection_(int, String)}
309     * immediately after creating the socket. The default implementation is a no-op
310     *
311     * @param socket the socket to set up
312     * @throws IOException on error
313     * @since 3.1
314     */
315    protected void _prepareDataSocket_(final Socket socket) throws IOException {
316    }
317
318    /**
319     * Check the value that can be set in PROT Command value.
320     *
321     * @param prot Data Channel Protection Level.
322     * @return True - A set point is right / False - A set point is not right
323     */
324    private boolean checkPROTValue(final String prot) {
325        for (final String element : PROT_COMMAND_VALUE) {
326            if (element.equals(prot)) {
327                return true;
328            }
329        }
330        return false;
331    }
332
333    /**
334     * Closes sockets.
335     *
336     * @param socket    main socket for proxy if enabled.
337     * @param sslSocket SSL socket.
338     * @throws IOException closing sockets is not successful.
339     */
340    private void closeSockets(final Socket socket, final Socket sslSocket) throws IOException {
341        IOUtils.close(socket, sslSocket);
342    }
343
344    /**
345     * Create SSL socket from plain socket.
346     *
347     * @param socket
348     * @return SSL Socket
349     * @throws IOException
350     */
351    private SSLSocket createSSLSocket(final Socket socket) throws IOException {
352        if (socket != null) {
353            final SSLSocketFactory f = context.getSocketFactory();
354            return (SSLSocket) f.createSocket(socket, _hostname_, socket.getPort(), false);
355        }
356        return null;
357    }
358
359    /**
360     * Closes the connection to the FTP server and restores connection parameters to the default values.
361     * <p>
362     * Calls {@code setSocketFactory(null)} and {@code setServerSocketFactory(null)} to reset the factories that may have been changed during the session, e.g.
363     * by {@link #execPROT(String)}
364     *
365     * @throws IOException If an error occurs while disconnecting.
366     * @since 3.0
367     */
368    @Override
369    public void disconnect() throws IOException {
370        super.disconnect();
371        IOUtils.close(plainSocket);
372        setSocketFactory(null);
373        setServerSocketFactory(null);
374    }
375
376    /**
377     * Sends the ADAT command with the specified authentication data.
378     *
379     * @param data The data to send with the command.
380     * @return server reply.
381     * @throws IOException If an I/O error occurs while sending the command.
382     * @since 3.0
383     */
384    public int execADAT(final byte[] data) throws IOException {
385        if (data != null) {
386            return sendCommand(CMD_ADAT, Base64.getEncoder().encodeToString(data));
387        }
388        return sendCommand(CMD_ADAT);
389    }
390
391    /**
392     * Sends the AUTH command.
393     *
394     * @throws SSLException If the server reply code equals neither "234" nor "334".
395     * @throws IOException  If an I/O error occurs while either sending the command.
396     */
397    protected void execAUTH() throws SSLException, IOException {
398        final int replyCode = sendCommand(CMD_AUTH, auth);
399        if (FTPReply.SECURITY_MECHANISM_IS_OK == replyCode) {
400            // replyCode = 334
401            // I carry out an ADAT command.
402        } else if (FTPReply.SECURITY_DATA_EXCHANGE_COMPLETE != replyCode) {
403            throw new SSLException(getReplyString());
404        }
405    }
406
407    /**
408     * Sends the AUTH command with the specified mechanism.
409     *
410     * @param mechanism The mechanism name to send with the command.
411     * @return server reply.
412     * @throws IOException If an I/O error occurs while sending the command.
413     * @since 3.0
414     */
415    public int execAUTH(final String mechanism) throws IOException {
416        return sendCommand(CMD_AUTH, mechanism);
417    }
418
419    /**
420     * 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
421     * {@link Socket} instances
422     *
423     * @return server reply.
424     * @throws IOException If an I/O error occurs while sending the command.
425     * @since 3.0
426     */
427    public int execCCC() throws IOException {
428
429// This will be performed by sendCommand(String, String)
430//        if (FTPReply.isPositiveCompletion(repCode)) {
431//            _socket_.close();
432//            _socket_ = plainSocket;
433//            _controlInput_ = new BufferedReader(
434//                new InputStreamReader(
435//                    _socket_.getInputStream(), getControlEncoding()));
436//            _controlOutput_ = new BufferedWriter(
437//                new OutputStreamWriter(
438//                    _socket_.getOutputStream(), getControlEncoding()));
439//        }
440        return sendCommand(CMD_CCC);
441    }
442
443    /**
444     * Sends the CONF command with the specified data.
445     *
446     * @param data The data to send with the command.
447     * @return server reply.
448     * @throws IOException If an I/O error occurs while sending the command.
449     * @since 3.0
450     */
451    public int execCONF(final byte[] data) throws IOException {
452        if (data != null) {
453            return sendCommand(CMD_CONF, Base64.getEncoder().encodeToString(data));
454        }
455        return sendCommand(CMD_CONF, ""); // perhaps "=" or just sendCommand(String)?
456    }
457
458    /**
459     * Sends the ENC command with the specified data.
460     *
461     * @param data The data to send with the command.
462     * @return server reply.
463     * @throws IOException If an I/O error occurs while sending the command.
464     * @since 3.0
465     */
466    public int execENC(final byte[] data) throws IOException {
467        if (data != null) {
468            return sendCommand(CMD_ENC, Base64.getEncoder().encodeToString(data));
469        }
470        return sendCommand(CMD_ENC, ""); // perhaps "=" or just sendCommand(String)?
471    }
472
473    /**
474     * Sends the MIC command with the specified data.
475     *
476     * @param data The data to send with the command.
477     * @return server reply.
478     * @throws IOException If an I/O error occurs while sending the command.
479     * @since 3.0
480     */
481    public int execMIC(final byte[] data) throws IOException {
482        if (data != null) {
483            return sendCommand(CMD_MIC, Base64.getEncoder().encodeToString(data));
484        }
485        return sendCommand(CMD_MIC, ""); // perhaps "=" or just sendCommand(String)?
486    }
487
488    /**
489     * PBSZ command. pbsz value: 0 to (2^32)-1 decimal integer.
490     *
491     * @param pbsz Protection Buffer Size.
492     * @throws SSLException If the server reply code does not equal "200".
493     * @throws IOException  If an I/O error occurs while sending the command.
494     * @see #parsePBSZ(long)
495     */
496    public void execPBSZ(final long pbsz) throws SSLException, IOException {
497        if (pbsz < 0 || 4294967295L < pbsz) { // 32-bit unsigned number
498            throw new IllegalArgumentException();
499        }
500        final int status = sendCommand(CMD_PBSZ, String.valueOf(pbsz));
501        if (FTPReply.COMMAND_OK != status) {
502            throw new SSLException(getReplyString());
503        }
504    }
505
506    /**
507     * PROT command.
508     * <ul>
509     * <li>C - Clear</li>
510     * <li>S - Safe(SSL protocol only)</li>
511     * <li>E - Confidential(SSL protocol only)</li>
512     * <li>P - Private</li>
513     * </ul>
514     * <strong>N.B.</strong> the method calls {@link #setSocketFactory(javax.net.SocketFactory)} and
515     * {@link #setServerSocketFactory(javax.net.ServerSocketFactory)}
516     *
517     * @param prot Data Channel Protection Level, if {@code null}, use {@link #DEFAULT_PROT}.
518     * @throws SSLException If the server reply code does not equal {@code 200}.
519     * @throws IOException  If an I/O error occurs while sending the command.
520     */
521    public void execPROT(String prot) throws SSLException, IOException {
522        if (prot == null) {
523            prot = DEFAULT_PROT;
524        }
525        if (!checkPROTValue(prot)) {
526            throw new IllegalArgumentException();
527        }
528        if (FTPReply.COMMAND_OK != sendCommand(CMD_PROT, prot)) {
529            throw new SSLException(getReplyString());
530        }
531        if (DEFAULT_PROT.equals(prot)) {
532            setSocketFactory(null);
533            setServerSocketFactory(null);
534        } else {
535            setSocketFactory(new FTPSSocketFactory(context));
536            setServerSocketFactory(new FTPSServerSocketFactory(context));
537            initSslContext();
538        }
539    }
540
541    /**
542     * Extract the data from a reply with a prefix, e.g. PBSZ=1234 => 1234
543     *
544     * @param prefix the prefix to find
545     * @param reply  where to find the prefix
546     * @return the remainder of the string after the prefix, or null if the prefix was not present.
547     */
548    private String extractPrefixedData(final String prefix, final String reply) {
549        final int idx = reply.indexOf(prefix);
550        if (idx == -1) {
551            return null;
552        }
553        // Cannot use trim before substring as leading space would affect the offset.
554        return reply.substring(idx + prefix.length()).trim();
555    }
556
557    /**
558     * Gets AUTH command use value.
559     *
560     * @return AUTH command use value.
561     */
562    public String getAuthValue() {
563        return auth;
564    }
565
566    /**
567     * Gets 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}
568     * instance, returns null.
569     *
570     * @return An array of cipher suite names, or {@code null}
571     */
572    public String[] getEnabledCipherSuites() {
573        if (_socket_ instanceof SSLSocket) {
574            return ((SSLSocket) _socket_).getEnabledCipherSuites();
575        }
576        return null;
577    }
578
579    /**
580     * Gets the names of the protocol versions which are currently enabled for use on this connection. When the underlying {@link Socket} is not an
581     * {@link SSLSocket} instance, returns null.
582     *
583     * @return An array of protocols, or {@code null}
584     */
585    public String[] getEnabledProtocols() {
586        if (_socket_ instanceof SSLSocket) {
587            return ((SSLSocket) _socket_).getEnabledProtocols();
588        }
589        return null;
590    }
591
592    /**
593     * Gets 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
594     * {@link SSLSocket} with {@link SSLSocket}{@link #getEnableSessionCreation()}) enabled, this returns False.
595     *
596     * @return true - Indicates that sessions may be created; this is the default. false - indicates that an existing session must be resumed.
597     */
598    public boolean getEnableSessionCreation() {
599        if (_socket_ instanceof SSLSocket) {
600            return ((SSLSocket) _socket_).getEnableSessionCreation();
601        }
602        return false;
603    }
604
605    /**
606     * Gets the currently configured {@link HostnameVerifier}. The verifier is only used on client mode connections.
607     *
608     * @return A HostnameVerifier instance.
609     * @since 3.4
610     */
611    public HostnameVerifier getHostnameVerifier() {
612        return hostnameVerifier;
613    }
614
615    /**
616     * Gets the {@link KeyManager} instance.
617     *
618     * @return The {@link KeyManager} instance
619     */
620    private KeyManager getKeyManager() {
621        return keyManager;
622    }
623
624    /**
625     * Gets true if the socket will require client authentication. When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns false.
626     *
627     * @return true - If the server mode socket should request that the client authenticate itself.
628     */
629    public boolean getNeedClientAuth() {
630        if (_socket_ instanceof SSLSocket) {
631            return ((SSLSocket) _socket_).getNeedClientAuth();
632        }
633        return false;
634    }
635
636    /**
637     * Gets the secure socket protocol to be used, e.g. SSL/TLS.
638     *
639     * @return the protocol
640     * @since 3.11.0
641     */
642    protected String getProtocol() {
643        return protocol;
644    }
645
646    /**
647     * Gets the protocol versions. The {@link #getEnabledProtocols()} method gets the value from the socket while
648     * this method gets its value from this instance's config.
649     *
650     * @return a clone of the protocols, may be null
651     * @since 3.11.0
652     */
653    protected String[] getProtocols() {
654        return protocols == null ? null : protocols.clone();
655    }
656
657    /**
658     * Gets the cipher suites. The {@link #getEnabledCipherSuites()} method gets the value from the socket while
659     * this method gets its value from this instance's config.
660     *
661     * @return a clone of the suites, may be null
662     * @since 3.11.0
663     */
664    protected String[] getSuites() {
665        return suites == null ? null : suites.clone();
666    }
667
668    /**
669     * Gets the currently configured {@link TrustManager}.
670     *
671     * @return A TrustManager instance.
672     */
673    public TrustManager getTrustManager() {
674        return trustManager;
675    }
676
677    /**
678     * Gets whether the socket is set to use client mode in its first handshake. When the underlying {@link Socket} is not an {@link SSLSocket} instance,
679     * returns false.
680     *
681     * @return true - If the socket should start its first handshake in "client" mode.
682     */
683    public boolean getUseClientMode() {
684        if (_socket_ instanceof SSLSocket) {
685            return ((SSLSocket) _socket_).getUseClientMode();
686        }
687        return false;
688    }
689
690    /**
691     * Gets whether the socket will request client authentication. When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns false.
692     *
693     * @return true - If the server mode socket should request that the client authenticate itself.
694     */
695    public boolean getWantClientAuth() {
696        if (_socket_ instanceof SSLSocket) {
697            return ((SSLSocket) _socket_).getWantClientAuth();
698        }
699        return false;
700    }
701
702    /**
703     * Performs a lazy init of the SSL context
704     *
705     * @throws IOException
706     */
707    private void initSslContext() throws IOException {
708        if (context == null) {
709            context = SSLContextUtils.createSSLContext(protocol, getKeyManager(), getTrustManager());
710        }
711    }
712
713    /**
714     * Tests the use client mode flag. The {@link #getUseClientMode()} method gets the value from the socket while
715     * this method gets its value from this instance's config.
716     *
717     * @return True If the socket should start its first handshake in "client" mode.
718     * @since 3.11.0
719     */
720    protected boolean isClientMode() {
721        return isClientMode;
722    }
723
724    /**
725     * Tests whether a new SSL session may be established by this socket. Default true
726     *
727     * @return True if session may be established
728     * @since 3.11.0
729     */
730    protected boolean isCreation() {
731        return isCreation;
732    }
733
734    /**
735     * Tests whether or not endpoint identification using the HTTPS algorithm on Java 1.7+ is enabled. The default behavior is for this to be disabled.
736     *
737     * This check is only performed on client mode connections.
738     *
739     * @return True if enabled, false if not.
740     * @since 3.4
741     */
742    public boolean isEndpointCheckingEnabled() {
743        return tlsEndpointChecking;
744    }
745
746    /**
747     * Tests the security mode. (True - Implicit Mode / False - Explicit Mode).
748     *
749     * @return True if enabled, false if not.
750     * @since 3.11.0
751     */
752    protected boolean isImplicit() {
753        return isImplicit;
754    }
755
756    /**
757     * Tests the need client auth flag. The {@link #getNeedClientAuth()} method gets the value from the socket while
758     * this method gets its value from this instance's config.
759     *
760     * @return True if enabled, false if not.
761     * @since 3.11.0
762     */
763    protected boolean isNeedClientAuth() {
764        return isNeedClientAuth;
765    }
766
767    /**
768     * Tests the want client auth flag. The {@link #getWantClientAuth()} method gets the value from the socket while
769     * this method gets its value from this instance's config.
770     *
771     * @return True if enabled, false if not.
772     * @since 3.11.0
773     */
774    protected boolean isWantClientAuth() {
775        return isWantClientAuth;
776    }
777
778    /**
779     * Establishes a data connection with the FTP server, returning a Socket for the connection if successful. If a restart offset has been set with
780     * {@link #setRestartOffset(long)}, a REST command is issued to the server with the offset as an argument before establishing the data connection. Active
781     * mode connections also cause a local PORT command to be issued.
782     *
783     * @param command The text representation of the FTP command to send.
784     * @param arg     The arguments to the FTP command. If this parameter is set to null, then the command is sent with no argument.
785     * @return A Socket corresponding to the established data connection. Null is returned if an FTP protocol error is reported at any point during the
786     *         establishment and initialization of the connection.
787     * @throws IOException If an I/O error occurs while either sending a command to the server or receiving a reply from the server.
788     * @since 3.1
789     */
790    private Socket openDataSecureConnection(final String command, final String arg) throws IOException {
791        if (getDataConnectionMode() != ACTIVE_LOCAL_DATA_CONNECTION_MODE && getDataConnectionMode() != PASSIVE_LOCAL_DATA_CONNECTION_MODE) {
792            return null;
793        }
794
795        final boolean isInet6Address = getRemoteAddress() instanceof Inet6Address;
796
797        final Socket socket;
798        Socket sslSocket = null;
799        final int soTimeoutMillis = DurationUtils.toMillisInt(getDataTimeout());
800        if (getDataConnectionMode() == ACTIVE_LOCAL_DATA_CONNECTION_MODE) {
801            // if no activePortRange was set (correctly) -> getActivePort() = 0
802            // -> new ServerSocket(0) -> bind to any free local port
803            try (ServerSocket server = _serverSocketFactory_.createServerSocket(getActivePort(), 1, getHostAddress())) {
804                // Try EPRT only if remote server is over IPv6, if not use PORT,
805                // because EPRT has no advantage over PORT on IPv4.
806                // It could even have the disadvantage,
807                // that EPRT will make the data connection fail, because
808                // today's intelligent NAT Firewalls are able to
809                // substitute IP addresses in the PORT command,
810                // but might not be able to recognize the EPRT command.
811                if (isInet6Address) {
812                    if (!FTPReply.isPositiveCompletion(eprt(getReportHostAddress(), server.getLocalPort()))) {
813                        return null;
814                    }
815                } else if (!FTPReply.isPositiveCompletion(port(getReportHostAddress(), server.getLocalPort()))) {
816                    return null;
817                }
818
819                if (getRestartOffset() > 0 && !restart(getRestartOffset())) {
820                    return null;
821                }
822
823                if (!FTPReply.isPositivePreliminary(sendCommand(command, arg))) {
824                    return null;
825                }
826
827                // For now, let's just use the data timeout value for waiting for
828                // the data connection. It may be desirable to let this be a
829                // separately configurable value. In any case, we really want
830                // to allow preventing the accept from blocking indefinitely.
831                if (soTimeoutMillis >= 0) {
832                    server.setSoTimeout(soTimeoutMillis);
833                }
834                socket = server.accept();
835
836                // Ensure the timeout is set before any commands are issued on the new socket
837                if (soTimeoutMillis >= 0) {
838                    socket.setSoTimeout(soTimeoutMillis);
839                }
840                if (getReceiveDataSocketBufferSize() > 0) {
841                    socket.setReceiveBufferSize(getReceiveDataSocketBufferSize());
842                }
843                if (getSendDataSocketBufferSize() > 0) {
844                    socket.setSendBufferSize(getSendDataSocketBufferSize());
845                }
846            }
847        } else { // We must be in PASSIVE_LOCAL_DATA_CONNECTION_MODE
848
849            // Try EPSV command first on IPv6 - and IPv4 if enabled.
850            // When using IPv4 with NAT it has the advantage
851            // to work with more rare configurations.
852            // E.g. if FTP server has a static PASV address (external network)
853            // and the client is coming from another internal network.
854            // In that case the data connection after PASV command would fail,
855            // while EPSV would make the client succeed by taking just the port.
856            final boolean attemptEPSV = isUseEPSVwithIPv4() || isInet6Address;
857            if (attemptEPSV && epsv() == FTPReply.ENTERING_EPSV_MODE) {
858                _parseExtendedPassiveModeReply(_replyLines.get(0));
859            } else {
860                if (isInet6Address) {
861                    return null; // Must use EPSV for IPV6
862                }
863                // If EPSV failed on IPV4, revert to PASV
864                if (pasv() != FTPReply.ENTERING_PASSIVE_MODE) {
865                    return null;
866                }
867                _parsePassiveModeReply(_replyLines.get(0));
868            }
869
870            if (getProxy() != null) {
871                socket = new Socket(getProxy());
872            } else {
873                socket = _socketFactory_.createSocket();
874            }
875
876            if (getReceiveDataSocketBufferSize() > 0) {
877                socket.setReceiveBufferSize(getReceiveDataSocketBufferSize());
878            }
879            if (getSendDataSocketBufferSize() > 0) {
880                socket.setSendBufferSize(getSendDataSocketBufferSize());
881            }
882            if (getPassiveLocalIPAddress() != null) {
883                socket.bind(new InetSocketAddress(getPassiveLocalIPAddress(), 0));
884            }
885
886            // For now, let's just use the data timeout value for waiting for
887            // the data connection. It may be desirable to let this be a
888            // separately configurable value. In any case, we really want
889            // to allow preventing the accept from blocking indefinitely.
890            if (soTimeoutMillis >= 0) {
891                socket.setSoTimeout(soTimeoutMillis);
892            }
893
894            socket.connect(new InetSocketAddress(getPassiveHost(), getPassivePort()), connectTimeout);
895
896            if (getProxy() != null) {
897                sslSocket = context.getSocketFactory().createSocket(socket, getPassiveHost(), getPassivePort(), true);
898            }
899
900            if (getRestartOffset() > 0 && !restart(getRestartOffset())) {
901                closeSockets(socket, sslSocket);
902                return null;
903            }
904
905            if (!FTPReply.isPositivePreliminary(sendCommand(command, arg))) {
906                closeSockets(socket, sslSocket);
907                return null;
908            }
909        }
910
911        if (isRemoteVerificationEnabled() && !verifyRemote(socket)) {
912            // Grab the host before we close the socket to avoid NET-663
913            final InetAddress socketHost = socket.getInetAddress();
914
915            closeSockets(socket, sslSocket);
916
917            throw new IOException(
918                    "Host attempting data connection " + socketHost.getHostAddress() + " is not same as server " + getRemoteAddress().getHostAddress());
919        }
920
921        return getProxy() != null ? sslSocket : socket;
922    }
923
924    /**
925     * Parses the given ADAT response line and base64-decodes the data.
926     *
927     * @param reply The ADAT reply to parse.
928     * @return the data in the reply, base64-decoded.
929     * @since 3.0
930     */
931    public byte[] parseADATReply(final String reply) {
932        if (reply == null) {
933            return null;
934        }
935        return Base64.getDecoder().decode(extractPrefixedData("ADAT=", reply));
936    }
937
938    /**
939     * PBSZ command. pbsz value: 0 to (2^32)-1 decimal integer. Issues the command and parses the response to return the negotiated value.
940     *
941     * @param pbsz Protection Buffer Size.
942     * @throws SSLException If the server reply code does not equal "200".
943     * @throws IOException  If an I/O error occurs while sending the command.
944     * @return the negotiated value.
945     * @see #execPBSZ(long)
946     * @since 3.0
947     */
948    public long parsePBSZ(final long pbsz) throws SSLException, IOException {
949        execPBSZ(pbsz);
950        long minvalue = pbsz;
951        final String remainder = extractPrefixedData("PBSZ=", getReplyString());
952        if (remainder != null) {
953            final long replysz = Long.parseLong(remainder);
954            if (replysz < minvalue) {
955                minvalue = replysz;
956            }
957        }
958        return minvalue;
959    }
960
961    // DEPRECATED - for API compatibility only - DO NOT USE
962
963    /**
964     * Send an FTP command. A successful CCC (Clear Command Channel) command causes the underlying {@link SSLSocket} instance to be assigned to a plain
965     * {@link Socket}
966     *
967     * @param command The FTP command.
968     * @return server reply.
969     * @throws IOException  If an I/O error occurs while sending the command.
970     * @throws SSLException if a CCC command fails
971     * @see org.apache.commons.net.ftp.FTP#sendCommand(String)
972     */
973    // Would like to remove this method, but that will break any existing clients that are using CCC
974    @Override
975    public int sendCommand(final String command, final String args) throws IOException {
976        final int repCode = super.sendCommand(command, args);
977        /* If CCC is issued, restore socket i/o streams to unsecured versions */
978        if (CMD_CCC.equals(command)) {
979            if (FTPReply.COMMAND_OK != repCode) {
980                throw new SSLException(getReplyString());
981            }
982            _socket_.close();
983            _socket_ = plainSocket;
984            _controlInput_ = new BufferedReader(new InputStreamReader(_socket_.getInputStream(), getControlEncoding()));
985            _controlOutput_ = new BufferedWriter(new OutputStreamWriter(_socket_.getOutputStream(), getControlEncoding()));
986        }
987        return repCode;
988    }
989
990    /**
991     * Sets AUTH command use value. This processing is done before connected processing.
992     *
993     * @param auth AUTH command use value.
994     */
995    public void setAuthValue(final String auth) {
996        this.auth = auth;
997    }
998
999    /**
1000     * Sets which particular cipher suites are enabled for use on this connection. Called before server negotiation.
1001     *
1002     * @param cipherSuites The cipher suites.
1003     */
1004    public void setEnabledCipherSuites(final String[] cipherSuites) {
1005        suites = cipherSuites.clone();
1006    }
1007
1008    /**
1009     * Sets which particular protocol versions are enabled for use on this connection. I perform setting before a server negotiation.
1010     *
1011     * @param protocolVersions The protocol versions.
1012     */
1013    public void setEnabledProtocols(final String[] protocolVersions) {
1014        protocols = protocolVersions.clone();
1015    }
1016
1017    /**
1018     * Sets whether a new SSL session may be established by this socket.
1019     *
1020     * @param isCreation The established socket flag.
1021     */
1022    public void setEnabledSessionCreation(final boolean isCreation) {
1023        this.isCreation = isCreation;
1024    }
1025
1026    /**
1027     * Sets automatic endpoint identification checking using the HTTPS algorithm is supported on Java 1.7+. The default behavior is for this to be disabled.
1028     *
1029     * This check is only performed on client mode connections.
1030     *
1031     * @param enable Enable automatic endpoint identification checking using the HTTPS algorithm on Java 1.7+.
1032     * @since 3.4
1033     */
1034    public void setEndpointCheckingEnabled(final boolean enable) {
1035        tlsEndpointChecking = enable;
1036    }
1037
1038    /**
1039     * Sets to override the default {@link HostnameVerifier} to use. The verifier is only used on client mode connections.
1040     *
1041     * @param newHostnameVerifier The HostnameVerifier implementation to set or {@code null} to disable.
1042     * @since 3.4
1043     */
1044    public void setHostnameVerifier(final HostnameVerifier newHostnameVerifier) {
1045        hostnameVerifier = newHostnameVerifier;
1046    }
1047
1048    /**
1049     * Sets a {@link KeyManager} to use
1050     *
1051     * @param keyManager The KeyManager implementation to set.
1052     * @see org.apache.commons.net.util.KeyManagerUtils
1053     */
1054    public void setKeyManager(final KeyManager keyManager) {
1055        this.keyManager = keyManager;
1056    }
1057
1058    /**
1059     * Sets the socket to require client authentication.
1060     *
1061     * @param isNeedClientAuth The need client auth flag.
1062     */
1063    public void setNeedClientAuth(final boolean isNeedClientAuth) {
1064        this.isNeedClientAuth = isNeedClientAuth;
1065    }
1066
1067    /**
1068     * Sets to override the default {@link TrustManager} to use; if set to {@code null}, the default TrustManager from the JVM will be used.
1069     *
1070     * @param trustManager The TrustManager implementation to set, may be {@code null}
1071     * @see org.apache.commons.net.util.TrustManagerUtils
1072     */
1073    public void setTrustManager(final TrustManager trustManager) {
1074        this.trustManager = trustManager;
1075    }
1076
1077    /**
1078     * Sets the socket to use client (or server) mode in its first handshake.
1079     *
1080     * @param isClientMode The use client mode flag.
1081     */
1082    public void setUseClientMode(final boolean isClientMode) {
1083        this.isClientMode = isClientMode;
1084    }
1085
1086    /**
1087     * Sets the socket to request client authentication, but only if such a request is appropriate to the cipher suite negotiated.
1088     *
1089     * @param isWantClientAuth The want client auth flag.
1090     */
1091    public void setWantClientAuth(final boolean isWantClientAuth) {
1092        this.isWantClientAuth = isWantClientAuth;
1093    }
1094
1095    /**
1096     * SSL/TLS negotiation. Acquires an SSL socket of a control connection and carries out handshake processing.
1097     *
1098     * @throws IOException If server negotiation fails
1099     */
1100    protected void sslNegotiation() throws IOException {
1101        plainSocket = _socket_;
1102        initSslContext();
1103        final SSLSocket socket = createSSLSocket(_socket_);
1104        socket.setEnableSessionCreation(isCreation);
1105        socket.setUseClientMode(isClientMode);
1106
1107        // client mode
1108        if (isClientMode) {
1109            if (tlsEndpointChecking) {
1110                SSLSocketUtils.enableEndpointNameVerification(socket);
1111            }
1112        } else { // server mode
1113            socket.setNeedClientAuth(isNeedClientAuth);
1114            socket.setWantClientAuth(isWantClientAuth);
1115        }
1116
1117        if (protocols != null) {
1118            socket.setEnabledProtocols(protocols);
1119        }
1120        if (suites != null) {
1121            socket.setEnabledCipherSuites(suites);
1122        }
1123        socket.startHandshake();
1124
1125        // TODO the following setup appears to duplicate that in the super class methods
1126        _socket_ = socket;
1127        _controlInput_ = new BufferedReader(new InputStreamReader(socket.getInputStream(), getControlEncoding()));
1128        _controlOutput_ = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), getControlEncoding()));
1129
1130        if (isClientMode && hostnameVerifier != null && !hostnameVerifier.verify(_hostname_, socket.getSession())) {
1131            throw new SSLHandshakeException("Hostname doesn't match certificate");
1132        }
1133    }
1134}
1135