Skip to content

Commit

Permalink
Issue #5933 ClientCertAuthenticator is not using SslContextFactory fr…
Browse files Browse the repository at this point in the history
…om server

Signed-off-by: olivier lamy <oliver.lamy@gmail.com>
  • Loading branch information
olamy committed Feb 2, 2021
1 parent 5b97d91 commit 4051b63
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 244 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
import org.eclipse.jetty.security.authentication.FormAuthenticator;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.ssl.SslContextFactory;

import java.util.Collection;

/**
* The Default Authenticator Factory.
Expand Down Expand Up @@ -63,8 +66,14 @@ else if (Constraint.__SPNEGO_AUTH.equalsIgnoreCase(auth))
authenticator = new ConfigurableSpnegoAuthenticator();
else if (Constraint.__NEGOTIATE_AUTH.equalsIgnoreCase(auth)) // see Bug #377076
authenticator = new ConfigurableSpnegoAuthenticator(Constraint.__NEGOTIATE_AUTH);
if (Constraint.__CERT_AUTH.equalsIgnoreCase(auth) || Constraint.__CERT_AUTH2.equalsIgnoreCase(auth))
authenticator = new ClientCertAuthenticator();
if (Constraint.__CERT_AUTH.equalsIgnoreCase(auth) || Constraint.__CERT_AUTH2.equalsIgnoreCase(auth)) {
Collection<SslContextFactory> sslContextFactories = server.getBeans( SslContextFactory.class);
if (sslContextFactories.size()!=1){
authenticator = new ClientCertAuthenticator();
} else {
authenticator = new ClientCertAuthenticator(sslContextFactories.iterator().next());
}
}

return authenticator;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,8 @@

package org.eclipse.jetty.security.authentication;

import java.security.KeyStore;
import java.security.Principal;
import java.security.cert.CRL;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.Collection;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
Expand All @@ -29,66 +25,31 @@
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.Authentication.User;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.security.CertificateUtils;
import org.eclipse.jetty.util.security.CertificateValidator;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.security.Password;
import org.eclipse.jetty.util.ssl.SslContextFactory;

public class ClientCertAuthenticator extends LoginAuthenticator
{
/**
* String name of keystore password property.
*/
private static final String PASSWORD_PROPERTY = "org.eclipse.jetty.ssl.password";

/**
* Truststore path
*/
private String _trustStorePath;
/**
* Truststore provider name
*/
private String _trustStoreProvider;
/**
* Truststore type
*/
private String _trustStoreType = "PKCS12";
/**
* Truststore password
* Set to true if SSL certificate validation is not required
* per default it's true as this is the goal of this implementation
*/
private transient Password _trustStorePassword;
private boolean _validateCerts = true;

/**
* Set to true if SSL certificate validation is required
*/
private boolean _validateCerts;
/**
* Path to file that contains Certificate Revocation List
*/
private String _crlPath;
/**
* Maximum certification path length (n - number of intermediate certs, -1 for unlimited)
*/
private int _maxCertPathLength = -1;
/**
* CRL Distribution Points (CRLDP) support
*/
private boolean _enableCRLDP = false;
/**
* On-Line Certificate Status Protocol (OCSP) support
*/
private boolean _enableOCSP = false;
/**
* Location of OCSP Responder
*/
private String _ocspResponderURL;
private SslContextFactory sslContextFactory;

public ClientCertAuthenticator()
{
super();
}

public ClientCertAuthenticator(SslContextFactory sslContextFactory)
{
super();
this.sslContextFactory = sslContextFactory;
}

@Override
public String getAuthMethod()
{
Expand All @@ -113,12 +74,7 @@ public Authentication validateRequest(ServletRequest req, ServletResponse res, b

if (_validateCerts)
{
KeyStore trustStore = getKeyStore(
_trustStorePath, _trustStoreType, _trustStoreProvider,
_trustStorePassword == null ? null : _trustStorePassword.toString());
Collection<? extends CRL> crls = loadCRL(_crlPath);
CertificateValidator validator = new CertificateValidator(trustStore, crls);
validator.validate(certs);
sslContextFactory.validateCerts(certs);
}

for (X509Certificate cert : certs)
Expand All @@ -131,10 +87,7 @@ public Authentication validateRequest(ServletRequest req, ServletResponse res, b
principal = cert.getIssuerDN();
final String username = principal == null ? "clientcert" : principal.getName();

// TODO: investigate if using a raw byte[] is better vs older char[]
final char[] credential = Base64.getEncoder().encodeToString(cert.getSignature()).toCharArray();

UserIdentity user = login(username, credential, req);
UserIdentity user = login(username, "", req);
if (user != null)
{
return new UserAuthentication(getAuthMethod(), user);
Expand All @@ -156,41 +109,6 @@ public Authentication validateRequest(ServletRequest req, ServletResponse res, b
}
}

/**
* Loads keystore using an input stream or a file path in the same
* order of precedence.
*
* Required for integrations to be able to override the mechanism
* used to load a keystore in order to provide their own implementation.
*
* @param storePath path of keystore file
* @param storeType keystore type
* @param storeProvider keystore provider
* @param storePassword keystore password
* @return created keystore
* @throws Exception if unable to get keystore
*/
protected KeyStore getKeyStore(String storePath, String storeType, String storeProvider, String storePassword) throws Exception
{
return CertificateUtils.getKeyStore(Resource.newResource(storePath), storeType, storeProvider, storePassword);
}

/**
* Loads certificate revocation list (CRL) from a file.
*
* Required for integrations to be able to override the mechanism used to
* load CRL in order to provide their own implementation.
*
* @param crlPath path of certificate revocation list file
* @return a (possibly empty) collection view of java.security.cert.CRL objects initialized with the data from the
* input stream.
* @throws Exception if unable to load CRL
*/
protected Collection<? extends CRL> loadCRL(String crlPath) throws Exception
{
return CertificateUtils.loadCRL(crlPath);
}

@Override
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, User validatedUser) throws ServerAuthException
{
Expand All @@ -213,151 +131,4 @@ public void setValidateCerts(boolean validateCerts)
_validateCerts = validateCerts;
}

/**
* @return The file name or URL of the trust store location
*/
public String getTrustStore()
{
return _trustStorePath;
}

/**
* @param trustStorePath The file name or URL of the trust store location
*/
public void setTrustStore(String trustStorePath)
{
_trustStorePath = trustStorePath;
}

/**
* @return The provider of the trust store
*/
public String getTrustStoreProvider()
{
return _trustStoreProvider;
}

/**
* @param trustStoreProvider The provider of the trust store
*/
public void setTrustStoreProvider(String trustStoreProvider)
{
_trustStoreProvider = trustStoreProvider;
}

/**
* @return The type of the trust store (default "PKCS12")
*/
public String getTrustStoreType()
{
return _trustStoreType;
}

/**
* @param trustStoreType The type of the trust store
*/
public void setTrustStoreType(String trustStoreType)
{
_trustStoreType = trustStoreType;
}

/**
* @param password The password for the trust store
*/
public void setTrustStorePassword(String password)
{
_trustStorePassword = Password.getPassword(PASSWORD_PROPERTY, password, null);
}

/**
* Get the crlPath.
*
* @return the crlPath
*/
public String getCrlPath()
{
return _crlPath;
}

/**
* Set the crlPath.
*
* @param crlPath the crlPath to set
*/
public void setCrlPath(String crlPath)
{
_crlPath = crlPath;
}

/**
* @return Maximum number of intermediate certificates in
* the certification path (-1 for unlimited)
*/
public int getMaxCertPathLength()
{
return _maxCertPathLength;
}

/**
* @param maxCertPathLength maximum number of intermediate certificates in
* the certification path (-1 for unlimited)
*/
public void setMaxCertPathLength(int maxCertPathLength)
{
_maxCertPathLength = maxCertPathLength;
}

/**
* @return true if CRL Distribution Points support is enabled
*/
public boolean isEnableCRLDP()
{
return _enableCRLDP;
}

/**
* Enables CRL Distribution Points Support
*
* @param enableCRLDP true - turn on, false - turns off
*/
public void setEnableCRLDP(boolean enableCRLDP)
{
_enableCRLDP = enableCRLDP;
}

/**
* @return true if On-Line Certificate Status Protocol support is enabled
*/
public boolean isEnableOCSP()
{
return _enableOCSP;
}

/**
* Enables On-Line Certificate Status Protocol support
*
* @param enableOCSP true - turn on, false - turn off
*/
public void setEnableOCSP(boolean enableOCSP)
{
_enableOCSP = enableOCSP;
}

/**
* @return Location of the OCSP Responder
*/
public String getOcspResponderURL()
{
return _ocspResponderURL;
}

/**
* Set the location of the OCSP Responder.
*
* @param ocspResponderURL location of the OCSP Responder
*/
public void setOcspResponderURL(String ocspResponderURL)
{
_ocspResponderURL = ocspResponderURL;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2001,6 +2001,13 @@ else if (cipherSuite.contains("WITH_DES_CBC_"))
return 0;
}

public void validateCerts(X509Certificate[] certs) throws Exception {
KeyStore trustStore = loadTrustStore(_trustStoreResource);
Collection<? extends CRL> crls = loadCRL(_crlPath);
CertificateValidator validator = new CertificateValidator(trustStore, crls);
validator.validate(certs);
}

@Override
public String toString()
{
Expand Down

0 comments on commit 4051b63

Please sign in to comment.