7 Replies Latest reply on Jan 27, 2011 6:58 AM by mmoyses

    JBoss 6 BaseCertLoginModule bug?

    feijtel

      Hello,

       

      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?

        • 1. JBoss 6 BaseCertLoginModule bug?
          feijtel

          Anyone able to judge my previous post? It seems like a bug to me. So I had hoped to either get confirmation, or someone telling me I've made a mistake.

           

          Thanks!

          • 2. JBoss 6 BaseCertLoginModule bug?
            fabrizio.benedetti

            Yes, it seems a bug. And also Jboss 6 is affected.

             

            I just solved writing my own "verifier", setting the moduel option in the application-policy:

            <module-option name="verifier">com.foo.bar.security.auth.certs.MyX509CertificateVerifier</module-option>

            and implementing the method public boolean verify(X509Certificate cert, String alias, KeyStore keyStore, KeyStore trustStore).

            Here you can take the right variable (trustStore) and eventually put your stuff (I check the cert expiration).

             

            In this way you don't have to modify jboss sources, reusing your class for future releases.

             

            Regards.

            Fabrizio

            1 of 1 people found this helpful
            • 3. JBoss 6 BaseCertLoginModule bug?
              mmoyses

              I know using the keystore is not intuitive but it's not a bug. The login module was designed that way. See this wiki.

              • 4. Re: JBoss 6 BaseCertLoginModule bug?
                feijtel

                I don't think I agree with you Marcus. The example in the wiki might work with just a keystore, but there is nothing wrong with using both a keystore and a truststore.

                 

                Besides that, the code seems to take in account that there is a truststore. And since it does that, it should check the truststore and not the keystore.

                 

                This line of code says it all I think:

                 

                   if (trustStore == null)

                       trustStore = keyStore;

                 

                If there is no trustStore, then the trustStore is considered to be the keyStore.

                 

                Adjusting the code I posted below and replacing the keyStore with trustStore in the lines:

                 

                          if (keyStore != null && cert != null) {

                and                storeCert = (X509Certificate) keyStore.getCertificate(alias);

                 

                will make this work perfectly for both for those who use just a keyStore and for those who use a keyStore and a trustStore.

                • 5. Re: JBoss 6 BaseCertLoginModule bug?
                  mmoyses

                  It's a simple enough change in the code and I'm not against it.

                  I created https://issues.jboss.org/browse/SECURITY-558 to track it.

                  Thanks for your feedback.

                  • 6. JBoss 6 BaseCertLoginModule bug?
                    feijtel

                    Thanks a lot for registering this as an issue.

                    • 7. Re: JBoss 6 BaseCertLoginModule bug?
                      mmoyses

                      Issue resolved.

                      Cheers