Commit a77699ce authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gato

Chain order was inverted and added option to disable parts of the validation.

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@3273 b35dd754-fafc-0310-a699-88a17e54d16e
parent 2e318eb6
...@@ -50,6 +50,26 @@ class ServerTrustManager implements X509TrustManager { ...@@ -50,6 +50,26 @@ class ServerTrustManager implements X509TrustManager {
// when the remote server requests to do EXTERNAL SASL // when the remote server requests to do EXTERNAL SASL
} }
/**
* Given the partial or complete certificate chain provided by the peer, build a certificate
* path to a trusted root and return if it can be validated and is trusted for server SSL
* authentication based on the authentication type. The authentication type is the key
* exchange algorithm portion of the cipher suites represented as a String, such as "RSA",
* "DHE_DSS". Note: for some exportable cipher suites, the key exchange algorithm is
* determined at run time during the handshake. For instance, for
* TLS_RSA_EXPORT_WITH_RC4_40_MD5, the authType should be RSA_EXPORT when an ephemeral
* RSA key is used for the key exchange, and RSA when the key from the server certificate
* is used. Checking is case-sensitive.<p>
*
* By default certificates are going to be verified. This includes verifying the certificate
* chain, the root certificate and the certificates validity. However, it is possible to
* disable certificates validation as a whole or each specific validation.
*
* @param x509Certificates an ordered array of peer X.509 certificates with the peer's own
* certificate listed first and followed by any certificate authorities.
* @param string the key exchange algorithm used.
* @throws CertificateException if the certificate chain is not trusted by this TrustManager.
*/
public void checkServerTrusted(X509Certificate[] x509Certificates, String string) public void checkServerTrusted(X509Certificate[] x509Certificates, String string)
throws CertificateException { throws CertificateException {
...@@ -59,13 +79,14 @@ class ServerTrustManager implements X509TrustManager { ...@@ -59,13 +79,14 @@ class ServerTrustManager implements X509TrustManager {
if (verify) { if (verify) {
int nSize = x509Certificates.length; int nSize = x509Certificates.length;
String peerIdentity = getPeerIdentity(x509Certificates[nSize - 1]); String peerIdentity = getPeerIdentity(x509Certificates[0]);
if (JiveGlobals.getBooleanProperty("xmpp.server.certificate.verify.chain", true)) {
// Working down the chain, for every certificate in the chain, // Working down the chain, for every certificate in the chain,
// verify that the subject of the certificate is the issuer of the // verify that the subject of the certificate is the issuer of the
// next certificate in the chain. // next certificate in the chain.
Principal principalLast = null; Principal principalLast = null;
for (int i = 0; i < nSize; i++) { for (int i = nSize -1; i >= 0 ; i--) {
X509Certificate x509certificate = x509Certificates[i]; X509Certificate x509certificate = x509Certificates[i];
Principal principalIssuer = x509certificate.getIssuerDN(); Principal principalIssuer = x509certificate.getIssuerDN();
Principal principalSubject = x509certificate.getSubjectDN(); Principal principalSubject = x509certificate.getSubjectDN();
...@@ -73,7 +94,7 @@ class ServerTrustManager implements X509TrustManager { ...@@ -73,7 +94,7 @@ class ServerTrustManager implements X509TrustManager {
if (principalIssuer.equals(principalLast)) { if (principalIssuer.equals(principalLast)) {
try { try {
PublicKey publickey = PublicKey publickey =
x509Certificates[i - 1].getPublicKey(); x509Certificates[i + 1].getPublicKey();
x509Certificates[i].verify(publickey); x509Certificates[i].verify(publickey);
} }
catch (GeneralSecurityException generalsecurityexception) { catch (GeneralSecurityException generalsecurityexception) {
...@@ -88,15 +109,19 @@ class ServerTrustManager implements X509TrustManager { ...@@ -88,15 +109,19 @@ class ServerTrustManager implements X509TrustManager {
} }
principalLast = principalSubject; principalLast = principalSubject;
} }
}
// Verify that the the first certificate in the chain was issued if (JiveGlobals.getBooleanProperty("xmpp.server.certificate.verify.root", true)) {
// Verify that the the last certificate in the chain was issued
// by a third-party that the client trusts. // by a third-party that the client trusts.
boolean trusted = false; boolean trusted = false;
try { try {
trusted = trustStore.getCertificateAlias(x509Certificates[0]) != null; trusted = trustStore.getCertificateAlias(x509Certificates[nSize - 1]) != null;
if (!trusted && nSize == 1 && JiveGlobals if (!trusted && nSize == 1 && JiveGlobals
.getBooleanProperty("xmpp.server.certificate.accept-selfsigned", false)) { .getBooleanProperty("xmpp.server.certificate.accept-selfsigned", false))
Log.warn("Accepting self-signed certificate of remote server: " + peerIdentity); {
Log.warn("Accepting self-signed certificate of remote server: " +
peerIdentity);
trusted = true; trusted = true;
} }
} }
...@@ -106,13 +131,24 @@ class ServerTrustManager implements X509TrustManager { ...@@ -106,13 +131,24 @@ class ServerTrustManager implements X509TrustManager {
if (!trusted) { if (!trusted) {
throw new CertificateException("root certificate not trusted of " + peerIdentity); throw new CertificateException("root certificate not trusted of " + peerIdentity);
} }
}
// Verify that the last certificate in the chain corresponds to // Verify that the first certificate in the chain corresponds to
// the server we desire to authenticate. // the server we desire to authenticate.
if (!server.equals(peerIdentity)) { // Check if the certificate uses a wildcard indicating that subdomains are valid
if (peerIdentity.startsWith("*.")) {
// Remove the wildcard
peerIdentity = peerIdentity.replace("*.", "");
// Check if the requested subdomain matches the certified domain
if (!server.endsWith(peerIdentity)) {
throw new CertificateException("target verification failed of " + peerIdentity);
}
}
else if (!server.equals(peerIdentity)) {
throw new CertificateException("target verification failed of " + peerIdentity); throw new CertificateException("target verification failed of " + peerIdentity);
} }
if (JiveGlobals.getBooleanProperty("xmpp.server.certificate.verify.validity", true)) {
// For every certificate in the chain, verify that the certificate // For every certificate in the chain, verify that the certificate
// is valid at the current time. // is valid at the current time.
Date date = new Date(); Date date = new Date();
...@@ -126,6 +162,7 @@ class ServerTrustManager implements X509TrustManager { ...@@ -126,6 +162,7 @@ class ServerTrustManager implements X509TrustManager {
} }
} }
} }
}
/** /**
* Returns the identity of the remote server as defined in the specified certificate. The * Returns the identity of the remote server as defined in the specified certificate. The
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment