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