Fix CRL verification failing due to client cert not being in chain (#29582)
closes #19853 Signed-off-by: Micah Algard <micahalgard@gmail.com> Signed-off-by: rmartinc <rmartinc@redhat.com> Co-authored-by: Micah Algard <micahalgard@gmail.com> Co-authored-by: rmartinc <rmartinc@redhat.com>
This commit is contained in:
parent
34a61d72e5
commit
74a80997c7
6 changed files with 172 additions and 12 deletions
|
@ -51,16 +51,15 @@ public final class CRLUtils {
|
||||||
* @throws GeneralSecurityException if some error in validation happens. Typically certificate not valid, or CRL signature not valid
|
* @throws GeneralSecurityException if some error in validation happens. Typically certificate not valid, or CRL signature not valid
|
||||||
*/
|
*/
|
||||||
public static void check(X509Certificate[] certs, X509CRL crl, KeycloakSession session) throws GeneralSecurityException {
|
public static void check(X509Certificate[] certs, X509CRL crl, KeycloakSession session) throws GeneralSecurityException {
|
||||||
if (certs.length < 2) {
|
if (certs == null || certs.length < 1) {
|
||||||
throw new GeneralSecurityException("Not possible to verify signature on CRL. X509 certificate doesn't have CA chain available on it");
|
throw new GeneralSecurityException("Not possible to verify signature on CRL because no certificate chain was passed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
X500Principal crlIssuerPrincipal = crl.getIssuerX500Principal();
|
X500Principal crlIssuerPrincipal = crl.getIssuerX500Principal();
|
||||||
X509Certificate crlSignatureCertificate = null;
|
X509Certificate crlSignatureCertificate = null;
|
||||||
|
|
||||||
// Try to find the certificate in the CA chain, which was used to sign the CRL
|
// Try to find the certificate in the CA chain, which was used to sign the CRL
|
||||||
for (int i=1 ; i<certs.length ; i++) {
|
for (X509Certificate currentCACert: certs) {
|
||||||
X509Certificate currentCACert = certs[i];
|
|
||||||
if (crlIssuerPrincipal.equals(currentCACert.getSubjectX500Principal())) {
|
if (crlIssuerPrincipal.equals(currentCACert.getSubjectX500Principal())) {
|
||||||
crlSignatureCertificate = currentCACert;
|
crlSignatureCertificate = currentCACert;
|
||||||
|
|
||||||
|
@ -110,12 +109,9 @@ public final class CRLUtils {
|
||||||
|
|
||||||
// Check if CRL issuer has trust anchor with the checked certificate (See https://tools.ietf.org/html/rfc5280#section-6.3.3 , paragraph (f))
|
// Check if CRL issuer has trust anchor with the checked certificate (See https://tools.ietf.org/html/rfc5280#section-6.3.3 , paragraph (f))
|
||||||
Set<X500Principal> certificateCAPrincipals = Arrays.asList(certs).stream()
|
Set<X500Principal> certificateCAPrincipals = Arrays.asList(certs).stream()
|
||||||
.map(X509Certificate::getSubjectX500Principal)
|
.map(X509Certificate::getIssuerX500Principal)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
// Remove the checked certificate itself
|
|
||||||
certificateCAPrincipals.remove(certs[0].getSubjectX500Principal());
|
|
||||||
|
|
||||||
X509Certificate currentCRLAnchorCertificate = crlSignatureCertificate;
|
X509Certificate currentCRLAnchorCertificate = crlSignatureCertificate;
|
||||||
X500Principal currentCRLAnchorPrincipal = crlIssuerPrincipal;
|
X500Principal currentCRLAnchorPrincipal = crlIssuerPrincipal;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
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
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -0,0 +1,54 @@
|
||||||
|
-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||||
|
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
|
||||||
|
-----END ENCRYPTED PRIVATE KEY-----
|
|
@ -71,6 +71,8 @@
|
||||||
<include>ca.crt</include>
|
<include>ca.crt</include>
|
||||||
<include>client.crt</include>
|
<include>client.crt</include>
|
||||||
<include>client.key</include>
|
<include>client.key</include>
|
||||||
|
<include>client-ca.crt</include>
|
||||||
|
<include>client-ca.key</include>
|
||||||
<include>*.crl</include>
|
<include>*.crl</include>
|
||||||
</includes>
|
</includes>
|
||||||
</resource>
|
</resource>
|
||||||
|
|
|
@ -183,10 +183,18 @@ public abstract class AbstractX509AuthenticationTest extends AbstractTestRealmKe
|
||||||
|
|
||||||
cliArgs.append("--ignore-ssl-errors=true ");
|
cliArgs.append("--ignore-ssl-errors=true ");
|
||||||
cliArgs.append("--web-security=false ");
|
cliArgs.append("--web-security=false ");
|
||||||
cliArgs.append("--ssl-certificates-path=").append(authServerHome).append(certificatesPath).append(" ");
|
if (certificatesPath != null) {
|
||||||
cliArgs.append("--ssl-client-certificate-file=").append(authServerHome).append(clientCertificateFile).append(" ");
|
cliArgs.append("--ssl-certificates-path=").append(authServerHome).append(certificatesPath).append(" ");
|
||||||
cliArgs.append("--ssl-client-key-file=").append(authServerHome).append(clientKeyFile).append(" ");
|
}
|
||||||
cliArgs.append("--ssl-client-key-passphrase=" + clientKeyPassword).append(" ");
|
if (clientCertificateFile != null) {
|
||||||
|
cliArgs.append("--ssl-client-certificate-file=").append(authServerHome).append(clientCertificateFile).append(" ");
|
||||||
|
}
|
||||||
|
if (clientKeyFile != null) {
|
||||||
|
cliArgs.append("--ssl-client-key-file=").append(authServerHome).append(clientKeyFile).append(" ");
|
||||||
|
}
|
||||||
|
if (clientKeyPassword != null) {
|
||||||
|
cliArgs.append("--ssl-client-key-passphrase=").append(clientKeyPassword).append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
phantomjsCliArgs = new SetSystemProperty("keycloak.phantomjs.cli.args", cliArgs.toString());
|
phantomjsCliArgs = new SetSystemProperty("keycloak.phantomjs.cli.args", cliArgs.toString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.keycloak.testsuite.x509;
|
||||||
|
|
||||||
|
import org.jboss.arquillian.drone.api.annotation.Drone;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.ClassRule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.keycloak.authentication.authenticators.x509.X509AuthenticatorConfigModel;
|
||||||
|
import org.keycloak.authentication.authenticators.x509.X509AuthenticatorConfigModel.IdentityMapperType;
|
||||||
|
import org.keycloak.authentication.authenticators.x509.X509AuthenticatorConfigModel.MappingSourceType;
|
||||||
|
import org.keycloak.testsuite.util.PhantomJSBrowser;
|
||||||
|
import org.openqa.selenium.WebDriver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author rmartinc
|
||||||
|
*/
|
||||||
|
public class X509SingleCertificateBrowserCRLTest extends AbstractX509AuthenticationTest {
|
||||||
|
|
||||||
|
@ClassRule
|
||||||
|
public static CRLRule crlRule = new CRLRule();
|
||||||
|
|
||||||
|
@Drone
|
||||||
|
@PhantomJSBrowser
|
||||||
|
private WebDriver phantomJS;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void replaceTheDefaultDriver() {
|
||||||
|
replaceDefaultWebDriver(phantomJS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void onBeforeTestClass() {
|
||||||
|
// configure single certificate without CA cert
|
||||||
|
configurePhantomJS(null, "/client-ca.crt", "/client-ca.key", "password");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void loginSuccessWithSingleCertificateEmptyRevocationListFromHttp() throws Exception {
|
||||||
|
X509AuthenticatorConfigModel config =
|
||||||
|
new X509AuthenticatorConfigModel()
|
||||||
|
.setCRLEnabled(true)
|
||||||
|
.setCRLRelativePath(CRLRule.CRL_RESPONDER_ORIGIN + "/" + EMPTY_CRL_PATH)
|
||||||
|
.setConfirmationPageAllowed(true)
|
||||||
|
.setMappingSourceType(MappingSourceType.SUBJECTDN_EMAIL)
|
||||||
|
.setUserIdentityMapperType(IdentityMapperType.USERNAME_EMAIL);
|
||||||
|
x509BrowserLogin(config, userId, "test-user@localhost", "test-user@localhost");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue