Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package org.apache.cloudstack.ca.provider;

import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
Expand Down Expand Up @@ -91,6 +92,17 @@ public void checkClientTrusted(final X509Certificate[] certificates, final Strin
return;
}

if (authStrictness) {
if (caCertificate == null) {
throw new CertificateException("Root CA certificate is required to validate client: " + clientAddress);
}
try {
primaryClientCertificate.verify(caCertificate.getPublicKey());
} catch (final GeneralSecurityException e) {
throw new CertificateException("Client certificate signature verification failed for client: " + clientAddress, e);
}
}

// Revocation check
final BigInteger serialNumber = primaryClientCertificate.getSerialNumber();
if (serialNumber == null || crlDao.findBySerial(serialNumber) != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,70 @@ public void setUp() throws Exception {
"CN=cloudstack.apache.org", "SHA256withRSA", 0, Collections.singletonList("cloudstack.apache.org"), Collections.singletonList(clientIp));
}

@Test
public void testAuthStrictWithRootSignedClientCertificate() throws Exception {
final X509Certificate certificate = CertUtils.generateV3Certificate(caCertificate, caKeypair, clientKeypair.getPublic(),
"CN=client", "SHA256withRSA", 1, null, Collections.singletonList(clientIp));
final RootCACustomTrustManager trustManager = new RootCACustomTrustManager(clientIp, true, false, certMap, caCertificate, crlDao);

trustManager.checkClientTrusted(new X509Certificate[]{certificate}, "RSA");

Assert.assertEquals(certificate, certMap.get(clientIp));
}

@Test
public void testAuthStrictWithSelfSignedClientCertificate() throws Exception {
final X509Certificate certificate = CertUtils.generateV3Certificate(null, clientKeypair, clientKeypair.getPublic(),
"CN=client", "SHA256withRSA", 1, null, Collections.singletonList(clientIp));

assertCertificateRejected(new X509Certificate[]{certificate}, caCertificate);
}

@Test
public void testAuthStrictWithDifferentRootUsingSameSubject() throws Exception {
final KeyPair otherKeypair = CertUtils.generateRandomKeyPair(1024);
final X509Certificate otherCa = CertUtils.generateV3Certificate(null, otherKeypair, otherKeypair.getPublic(),
"CN=ca", "SHA256withRSA", 365, null, null);
final X509Certificate certificate = CertUtils.generateV3Certificate(otherCa, otherKeypair, clientKeypair.getPublic(),
"CN=client", "SHA256withRSA", 1, null, Collections.singletonList(clientIp));

assertCertificateRejected(new X509Certificate[]{certificate, otherCa}, caCertificate);
}

@Test
public void testAuthStrictWithUntrustedClientAndTrustedRootInChain() throws Exception {
final X509Certificate certificate = CertUtils.generateV3Certificate(null, clientKeypair, clientKeypair.getPublic(),
"CN=client", "SHA256withRSA", 1, null, Collections.singletonList(clientIp));

assertCertificateRejected(new X509Certificate[]{certificate, caCertificate}, caCertificate);
}

@Test
public void testAuthStrictWithoutRootCertificate() throws Exception {
assertCertificateRejected(new X509Certificate[]{expiredClientCertificate}, null);
}

private void assertCertificateRejected(final X509Certificate[] certificates, final X509Certificate rootCertificate) throws Exception {
final RootCACustomTrustManager trustManager = new RootCACustomTrustManager(clientIp, true, true, certMap, rootCertificate, crlDao);
try {
trustManager.checkClientTrusted(certificates, "RSA");
Assert.fail("Expected client certificate rejection");
} catch (final CertificateException expected) {
Assert.assertTrue(certMap.isEmpty());
}
}

@Test
public void testAuthNotStrictWithSelfSignedClientCertificate() throws Exception {
final X509Certificate certificate = CertUtils.generateV3Certificate(null, clientKeypair, clientKeypair.getPublic(),
"CN=client", "SHA256withRSA", 1, null, Collections.singletonList(clientIp));
final RootCACustomTrustManager trustManager = new RootCACustomTrustManager(clientIp, false, true, certMap, caCertificate, crlDao);

trustManager.checkClientTrusted(new X509Certificate[]{certificate}, "RSA");

Assert.assertEquals(certificate, certMap.get(clientIp));
}

@Test
public void testAuthNotStrictWithInvalidCert() throws Exception {
final RootCACustomTrustManager trustManager = new RootCACustomTrustManager(clientIp, false, true, certMap, caCertificate, crlDao);
Expand Down