JBoss 6 BaseCertLoginModule bug?
feijtel Jan 25, 2011 1:32 AMHello,
I've been working on using a DatabaseCertLoginModule on my application and ran into the following error:
HTTP Status 401 - Cannot authenticate with the provided credentials
I enabled SSL debug with the -D option in the launch configuration of JBoss to obtain more information. This shows that the SSL handshake succeeds, a certificate match is found, etc. So the technical SSL stuff works.
After that, my configured login module is executed. And that's where something goes wrong.
I think I have narrowed it down to the class BaseCertLoginModule (superclass of DatabaseCertLoginModule). This class is distributed in the jar jbosssx.jar in the jboss/lib directory. I decompiled this class to get an idea of what's going on.
The method validateCredential in this class contains the following code snippet (domain is the configured securityDomain):
if (domain != null) {
keyStore = domain.getKeyStore();
trustStore = domain.getTrustStore();
}
if (trustStore == null)
trustStore = keyStore;
if (keyStore != null && cert != null) {
// Look for the cert in the keystore using the alias
X509Certificate storeCert = null;
try {
storeCert = (X509Certificate) keyStore.getCertificate(alias);
... /* trace logging part left out*/
} catch (KeyStoreException e) {
log.warn("failed to find the certificate for " + alias, e);
}
// Ensure that the two certs are equal
if (cert.equals(storeCert))
isValid = true;
} else {
log.warn("Domain, KeyStore, or cert is null. Unable to validate the certificate.");
}
The trustStore and the keyStore are retrieved from the security domain. If the trustStore is null, the trustStore is set to the keyStore. And then, and this is what really surprises me, the keyStore is used to get the certificate:
storeCert = (X509Certificate) keyStore.getCertificate(alias);
Should this not be the trustStore??? We happen to have a separate keyStore and trustStore, and this piece of code will never find our trusted certificate, as this is not in the keyStore but in our trustStore.
To test this, I wrote my own loginmodule class, which is an extend of DatabaseCertLoginModule class. I then overrid the method validateCredential, copied the original code and adjusted it to make sure the trustStore is used. And then it all works!
Is this a bug in the BaseCertLoginModule class? Seems so...Cause the variable trustStore isn't used at all anymore in the method after the null check and setting the keyStore as trustStore. That does not make any sense.
Below I've posted my service xml that I created (along with a myapp-security-config.xml to define the login module details). Here I define both the keyStore and the trustStore.
myapp-service.xml
<?xml version="1.0" encoding="UTF-8"?>
<server>
<mbean code="org.jboss.security.plugins.JaasSecurityDomain" name="jboss.security:service=SecurityDomain">
<constructor>
<arg type="java.lang.String" value="myappwebservices" />
</constructor>
<attribute name="KeyStoreURL">D:/jboss/server/default/conf/myapp.keystore</attribute>
<attribute name="KeyStorePass">thepassword</attribute>
<attribute name="TrustStoreURL">D:/jboss/server/default/conf/myapp.truststore</attribute>
<attribute name="TrustStorePass">thepassword</attribute>
<depends>jboss.security:service=JaasSecurityManager</depends>
</mbean>
<mbean code="org.jboss.security.auth.login.DynamicLoginConfig" name="jboss:service=DynamicLoginConfig">
<attribute name="AuthConfig">
META-INF/myapp-security-config.xml
</attribute>
<depends optional-attribute-name="LoginConfigService">
jboss.security:service=XMLLoginConfig
</depends>
<depends optional-attribute-name="SecurityManagerService">jboss.security:service=JaasSecurityManager</depends>
</mbean>
</server>
I'm currently migrating my application from JBoss 4 to JBoss 6, and as a verification, I checked this class on the JBoss 4 platform. On Jboss 4, its also the keyStore being used and not the trustStore. I could of course simply change my service xml and define the keyStore with the path to my trustStore, but that seems rather wrong to me.
Any JBoss expert can confirm that this is a bug?