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