com.enterprisedt.net.ftp.ssl
Class SSLFTPStandardValidator

java.lang.Object
  extended by com.enterprisedt.net.ftp.ssl.SSLFTPStandardValidator
All Implemented Interfaces:
SSLFTPValidator

public class SSLFTPStandardValidator
extends java.lang.Object
implements SSLFTPValidator

Standard server certificate validator (SSLFTPValidator). This validator performs the following validation tests:

  1. Check to see if the client recommends that the certificate should be accepted. This happens if (1) the server's certificate was verified from the root certificates store (see SSLFTPClient.getRootCertificateStore()). or (2) server validation has been switched off see SSLFTPClient.setValidateServer(boolean)).
  2. Ensure that the length of the certificate chain is no more than 2, which indicates that the certificate was issued to the server directly by a CA (Certificate Authority).
  3. Check that the CN (Common Name) of the subject of the server certificate matches the server's hostname.
  4. Check that today's date is within the valid period of the certificate.

The second test, host-name checking, is sometimes problematic and may be disabled by passing a flag to the constructor. This, however, is strongly discouraged and should be done only if the FTPS server's certificate cannot be configured so that its CN parameter contains its host-name.

Be warned that disabling host-name checking opens the opportunity for man-in-the-middle attacks. This scenario is when an attacker has stolen the certificate and private key of a server, and then set up another server using these with the aim of impersonating the former. Since internet naming is such that only one server can have a particular host-name, it is very difficult for the attacker to make their host-name match the host-name on the certificate. However, if the host-name is not matched with the name on the certificate then this possibility opens.

Author:
Hans Andersen

Field Summary
protected  boolean hostNameCheckingEnabled
          Flag indicating whether or not host-name checking is enabled.
static int MAX_CERTIFICATE_CHAIN_LENGTH
          Maximum allowed length of the certificate chain.
protected  SSLFTPCertificateStore rootCertificateStore
          Reference to SSLFTPClient's root certificate store.
protected  java.lang.String[] serverCommonNames
          Name with which the certificate's CommonName (CN) will be compared.
 
Constructor Summary
SSLFTPStandardValidator()
          Default constructor.
SSLFTPStandardValidator(boolean checkHostNames)
          Creates a standard validator with host-name checking enabled or disabled depending on the setting of the hostNameCheckingEnabled flag.
SSLFTPStandardValidator(java.lang.String serverCommonName)
          Creates a standard validator that will compare the CommonName on the server certificate with the given string rather than the host-name.
SSLFTPStandardValidator(java.lang.String[] serverCommonNames)
          Creates a standard validator that will compare the CommonName on the server certificate each of the names in the given array rather than the host-name.
 
Method Summary
protected  boolean checkChainLength(int chainLength)
          Checks the length of the certificate-chain, but making sure that it is less than or equal to MAX_CERTIFICATE_CHAIN_LENGTH.
protected  boolean checkCommonName(java.lang.String certCommonName, java.lang.String serverHostName)
          Checks that the common name is the same as the server's host-name or (alternatively) one of the names passed into the constructor.
protected  boolean checkDateRange(java.util.Date validFrom, java.util.Date validUntil)
          Checks that today's date falls between validFrom and validTo.
 boolean validateServerCertificate(boolean recommendValidate, java.util.Vector certificateChain, java.lang.String serverHostName)
          Applies the validation tests described in the class description (see above) and throws an exception if any of them fail.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

MAX_CERTIFICATE_CHAIN_LENGTH

public static int MAX_CERTIFICATE_CHAIN_LENGTH
Maximum allowed length of the certificate chain. By default, this variable is set to 2, but it may be changed programmatically if a different length-limit is desired.


hostNameCheckingEnabled

protected boolean hostNameCheckingEnabled
Flag indicating whether or not host-name checking is enabled.


serverCommonNames

protected java.lang.String[] serverCommonNames
Name with which the certificate's CommonName (CN) will be compared. If serverCommonName is set then the certificate's CN will be compared with it instead of the host-name.


rootCertificateStore

protected SSLFTPCertificateStore rootCertificateStore
Reference to SSLFTPClient's root certificate store.

Constructor Detail

SSLFTPStandardValidator

public SSLFTPStandardValidator()
Default constructor. Creates a standard validator with host-name checking enabled.


SSLFTPStandardValidator

public SSLFTPStandardValidator(java.lang.String serverCommonName)
Creates a standard validator that will compare the CommonName on the server certificate with the given string rather than the host-name.

Parameters:
serverCommonName - Name with which the certificate's CommonName (CN) will be compared.

SSLFTPStandardValidator

public SSLFTPStandardValidator(java.lang.String[] serverCommonNames)
Creates a standard validator that will compare the CommonName on the server certificate each of the names in the given array rather than the host-name.

Parameters:
serverCommonName - Name with which the certificate's CommonName (CN) will be compared.

SSLFTPStandardValidator

public SSLFTPStandardValidator(boolean checkHostNames)
Creates a standard validator with host-name checking enabled or disabled depending on the setting of the hostNameCheckingEnabled flag. Disabling host-name checking is strongly discouraged and should be done only if the FTPS server's certificate cannot be configured so that its CN parameter contains its host-name.

Disabling host-name checking opens the opportunity for man-in-the-middle attacks. This scenario is when an attacker has stolen the certificate and private key of a server, and then set up another server using these with the aim of impersonating the former. Since internet naming is such that only one server can have a particular host-name, it is very difficult for the attacker to make their host-name match the host-name on the certificate. However, if the host-name is not matched with the name on the certificate then this possibility opens.

Parameters:
checkHostNames - Determines if host-names should be checked.
Method Detail

checkChainLength

protected boolean checkChainLength(int chainLength)
Checks the length of the certificate-chain, but making sure that it is less than or equal to MAX_CERTIFICATE_CHAIN_LENGTH.

Code:

 protected boolean checkChainLength(int chainLength) {
     return chainLength <= MAX_CERTIFICATE_CHAIN_LENGTH;
 }
 

Parameters:
chainLength - Length of the certificate chain.
Returns:
true if the chain is less than or equal to MAX_CERTIFICATE_CHAIN_LENGTH.

checkCommonName

protected boolean checkCommonName(java.lang.String certCommonName,
                                  java.lang.String serverHostName)
Checks that the common name is the same as the server's host-name or (alternatively) one of the names passed into the constructor. The common name is the CN (Common Name) attribute of the server certificates subject.

Code:

   if (serverCommonNames==null || !hostNameCheckingEnabled) {
     return certCommonName.toLowerCase().equals(serverHostName.toLowerCase());
   } else {
     for (int i=0; i
 where serverCommonNames is the array of name that are optionally specified 
 in the constructor.

Parameters:
certCommonName - The CN (Common Name) attribute of the server certificates subject.
serverHostName - The server's hostname.
Returns:
Result of a caseless comparison between commonName and serverHostName or (alternatively) one of the names passed into the constructor.

checkDateRange

protected boolean checkDateRange(java.util.Date validFrom,
                                 java.util.Date validUntil)
Checks that today's date falls between validFrom and validTo.

Code:

 protected boolean checkDateRange(Date validFrom, Date validUntil) {
     Date today = new Date();
     return !today.before(validFrom) && !today.after(validUntil);
 }
 

Parameters:
validFrom - Date that the server's certificate is valid from.
validUntil - Date that the server's certificate is valid from until.
Returns:
true if date falls between input dates

validateServerCertificate

public boolean validateServerCertificate(boolean recommendValidate,
                                         java.util.Vector certificateChain,
                                         java.lang.String serverHostName)
                                  throws SSLFTPException
Applies the validation tests described in the class description (see above) and throws an exception if any of them fail.

 public boolean validateServerCertificate( 
     boolean recommendValidate,
     Vector certificateChain, 
     String serverHostName) 
     throws SSLFTPException {
     
     if (!recommendValidate)
                           return false;
 
     if (!checkChainLength(certificateChain.size())) 
         throw new SSLFTPException(...error message...);
 
     SSLFTPCertificate serverCertificate = (SSLFTPCertificate) certificateChain.lastElement();
 
     String commonName = serverCertificate.getSubjectName().getCommonName(); 
     if (!checkCommonName(commonName, serverHostName)) 
         throw new SSLFTPException(...error message...);
 
     if (!checkDateRange(serverCertificate.getValidityNotBefore(), 
                         serverCertificate.getValidityNotAfter())) 
         throw new SSLFTPException(...error message...);
 
     return true; 
 }
 

Specified by:
validateServerCertificate in interface SSLFTPValidator
Parameters:
recommendValidate - flag indicating whether the client recommends that the certificate should be accepted. It will be true if the (1) the server's certificate was verified from the root certificates store (see SSLFTPClient.getRootCertificateStore()). or (2) server validation has been switched off see SSLFTPClient.setValidateServer(boolean)).
certificateChain - chain of certificates (SSLFTPCertificate objects) with the server's certificate appearing last and the root certificate issuer (usually a Certificate Authority - CA) appearing first. Under most circumstances, the vector has only 2 elements; the certificate of the CA and the certificate of the server.
serverHostName - the host-name of the server that we are connected to.
Returns:
true if the certificate is valid. If the certificate is invalid then the method should either return false or throw an SSLFTPException with details describing the failure. If false is returned then a generic server certificate validation failure exception will be thrown.
Throws:
SSLFTPException - Thrown if the certificate is found to be invalid.


Copyright © 2001-2009 Enterprise Distributed Technologies Ltd. All Rights Reserved.