1 2 Previous Next 20 Replies Latest reply on Jan 18, 2005 12:33 PM by kookywon

    UsersRolesLoginModule AND CLIENT-CERT (desperately)

    skyfalke Newbie

      Hello there.

      I wonder what happened to my topic that I posted yesterday (25.)!?!
      But that is not the major problem I am struggling with. The past days I made several desperate efforts to use mutual authentication via certificates.

      The SSL handshake works so far - no problem here. But I need to use the content of the client-certificate which is sent to the server for more specific authorization with role-based information from property files (UsersRolesLoginModule).

      Here are some snippets of the current project:

      - the connector in the jboss-service.xml of the built-in Tomcat:

       <Connector className = "org.apache.coyote.tomcat4.CoyoteConnector"
       address="${jboss.bind.address}" port = "8443" scheme = "https" secure = "true">
       <Factory className = "org.apache.coyote.tomcat4.CoyoteServerSocketFactory"
       keystoreFile=".../server.ks"
       keystorePass="keystorepass"
       clientAuth="true"
       protocol = "TLS"/>
       </Connector>
      

      As you see the attribute "clientAuth" is set to "true".

      - the application 's deployment descriptor (web.xml):
       <user-data-constraint>
       <transport-guarantee>CONFIDENTIAL</transport-guarantee>
       </user-data-constraint>
       </security-constraint>
      
       <login-config>
       <auth-method>CLIENT-CERT</auth-method>
       <realm-name>Default</realm-name>
       </login-config>
      

      The web module itself should use client-certificate-based authentication for the resources specified in the security-constraint element.

      I use the UsersRolesLoginModule which is declared in conf/login-config.xml. And I suppose that the problem starts right there.
      What I try to do is using client-cerificates combined with security-roles. Therefore I specifiy usernames and the associated roles within users.properties and roles.properties, respectively. But I am not sure how to name the users?

      -> My first try was to use the "common name" of the certificate (e.g. "client1").

      -> Secondly I tried the complete "distinguished name" (e.g. "cn\=client1,ou\=org_unit,o\=org,l\=city,st\=state,c\=de")

      As you can easily guess neither the first nor the second attempt was successful.
      Maybe the UsersRolesLoginModule is not capable of extracting data from the certificate. What about the database login module if property files cannot be used?

      The internet does not seem to have an answer for this problem. ;o( So please help...

      A huge THX in advance
      Matthias Falkenberg aka skyfalke.




        • 1. Re: UsersRolesLoginModule AND CLIENT-CERT (desperately)
          Dietmar Scheidl Newbie

          Hi,

          which release do you use? Have a look at the 4.0.0DR4. There you will find a CertRolesLoginModule which should do exactly what you are looking for.

          I have not tried it but it should give you a hint.

          Didi

          • 2. Re: UsersRolesLoginModule AND CLIENT-CERT (desperately)
            skyfalke Newbie

            @Didi1976:
            Thank you for the hint concerning JBoss 4.0.0DR4. But I have to use JBoss 3.2.3. Nevertheless, I would like to know where you got the information from?

            Do you or anybody else think realizing the authentication with the UsersRolesLoginModule or the DatabaseServerLoginModule it is not possible?

            Ciao
            skyfalke

            • 3. Re: UsersRolesLoginModule AND CLIENT-CERT (desperately)
              Dietmar Scheidl Newbie

              Hi,

              I would suggest to write it yourself. As starting point just download the source of 4.0.0DR4 and take CertRolesLoginModule and AbstractCertLoginModule. Try to backport them to run in 3.2.3.

              The info is from the sources. I had to write a similar LoginModule for 3.2.1. My source is not that nice but it works for me:

              package test;
              
              import org.jboss.security.auth.spi.AbstractServerLoginModule;
              import javax.security.auth.Subject;
              import javax.security.auth.callback.*;
              import javax.security.auth.login.*;
              import java.util.Map;
              import java.security.acl.Group;
              import java.security.Principal;
              import org.jboss.security.SimplePrincipal;
              import org.jboss.security.SimpleGroup;
              import java.security.cert.*;
              import java.security.cert.*;
              import org.apache.log4j.Logger;
              
              /**
               * ClientCertificateLoginModule<br>
               * Login Module which checks the supplied certificate<br>
               * <br>
               * Usage within login-config.xml:<br>
               * <pre>
               * <application-policy name = "cc">
               * <authentication>
               * <login-module code = "test.ClientCertificateLoginModule"
               * flag = "required">
               * <module-option name = "unauthenticatedIdentity">test</module-option>
               * </login-module>
               * </authentication>
               * </application-policy>
               * </pre>
               * <pre>
               * </pre>
               * <p>Copyright (c) 2002 SoftSolution EDV GmbH</p>
               */
              public class ClientCertificateLoginModule extends AbstractServerLoginModule
              {
               private Principal identity;
              
               public void initialize(Subject subject, CallbackHandler callbackHandler,
               Map sharedState, Map options)
               {
               super.initialize(subject,callbackHandler,sharedState,options);
              
               if( log.isDebugEnabled() )
               {
               log.debug( "initialize" );
               log.debug( "subject=" + subject );
               log.debug( "callbackHandler=" + callbackHandler );
               log.debug( "sharedState=" + sharedState );
               log.debug( "options=" + options );
               }
              
               javax.security.auth.callback.NameCallback nameCb =
               new javax.security.auth.callback.NameCallback("Name");
               org.jboss.security.auth.callback.ObjectCallback objCb =
               new org.jboss.security.auth.callback.ObjectCallback("Certificate Chain");
              
               javax.security.auth.callback.Callback[] cbs =
               new javax.security.auth.callback.Callback[2];
               cbs[0] = nameCb;
               cbs[1] = objCb;
              
               try
               {
               // Get the name and the certificates from the callback handler
               callbackHandler.handle(cbs);
               this.sharedState.put("javax.security.auth.login.name",nameCb.getName());
               this.sharedState.put("javax.security.auth.login.password",objCb.getCredential());
               }
               catch( Exception e )
               {
               log.error("Exception in initializing LoginModule",e);
               }
               }
              
              
               public boolean login() throws LoginException
               {
               // Check if the certificate is valid
               java.security.cert.X509Certificate[] certs =
               (java.security.cert.X509Certificate[])sharedState.get("javax.security.auth.login.password");
              
               if( certs != null )
               {
               try
               {
               certs[0].checkValidity();
              
               // Generate a Principal
               String tmpString = String.valueOf(certs[0].getSubjectDN());
               int cnIndex = tmpString.indexOf("CN=");
               int cnIndexEnd = tmpString.indexOf(",",cnIndex);
               if( cnIndexEnd > -1 )
               {
               identity = new SimplePrincipal(tmpString.substring(cnIndex+3,cnIndexEnd));
               }
               else
               {
               identity = new SimplePrincipal(tmpString.substring(cnIndex+3));
               }
              
               loginOk = true;
               }
               catch (CertificateExpiredException ex)
               {
               log.info("Certificate expired " + certs[0].getSubjectDN(),ex);
               loginOk = false;
               }
               catch (CertificateNotYetValidException ex)
               {
               log.info("Certificate not yet valid " + certs[0].getSubjectDN(),ex);
               loginOk = false;
               }
               }
               else
               {
               identity = new SimplePrincipal(String.valueOf(options.get("unauthenticatedIdentity")));
               loginOk = true;
               }
              
               if( log.isDebugEnabled() )
               {
               log.debug( "login ok=" + loginOk + " principal=" + identity);
               }
              
               return loginOk;
               }
              
               public Group[] getRoleSets()
               {
               Group[] groups = null;
              
               // set the groups of a user
               groups = new Group[1];
               SimpleGroup rolesGroup = new SimpleGroup("Roles");
               rolesGroup.addMember(new SimplePrincipal("User"));
               groups[0] = rolesGroup;
              
               return groups;
               }
              
               public Principal getIdentity()
               {
               return identity;
               }
              }
              


              Put it into your ejb.jar and add the lines to login-config.xml. That's all.

              Hope my example helps. Just add the logic to get the correct roles. My example only checks if the certificate is valid. Play around and have fun with it.

              Didi

              • 4. Re: UsersRolesLoginModule AND CLIENT-CERT (desperately)
                Scott Stark Master

                The certificate login modules from 4.0 have been backported to 3.2 and I have created an example of securing the jmx-console using client certs:

                http://www.jboss.org/wiki/Wiki.jsp?page=BaseCertLoginModule

                • 5. Re: UsersRolesLoginModule AND CLIENT-CERT (desperately)
                  skyfalke Newbie

                  @Mr Stark:
                  Could you please tell me whether the BaseCertLoginModule already ships with JBoss 3.2.3?

                  Additionally I would like to know what kind of SSL connector to use:

                  Currently I rely on http://www.nsdev.org/jboss/stories/jboss-ssl.html.

                  <Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
                   address="${jboss.bind.address}" port="8443" scheme="https"
                   secure="true" >
                   <Factory className = "org.apache.coyote.tomcat4.CoyoteServerSocketFactory"
                   keystoreFile="ssl/server/server.ks"
                   keystorePass="keystorepass"
                   clientAuth="true"
                   protocol="TLS"/>
                  </Connector>
                  


                  This configuration works without any problems: The Server and Client exchange the certificates.

                  The example given by Mr Stark involves a SecurityDomain and I assume the Connector has to be like:

                  <Connector className="org.apache.catalina.connector.http.HttpConnector"
                   port="8443" scheme="https" secure="true" >
                   <Factory className = "org.jboss.web.catalina.security.SSLServerSocketFactory"
                   securityDomainName="java:/jaas/..."
                   clientAuth="true"
                   protocol="TLS"/>
                  </Connector>
                  


                  But if I do so, the application is not willing to work. (mozilla 1.6: "The connection was refused when attempting to contact localhost:8443.")

                  I searched on the internet and found:
                  $JBOSS_DIST/server/default/conf/jboss-service.xml
                  We want JaasSecurityDomain as SecurityManagerClass instead of JaasSecurityManager, so we need to change this in the file:
                  
                  <!-- JAAS security manager and realm mapping -->
                  <mbean code="org.jboss.security.plugins.JaasSecurityManagerService"
                   name="jboss.security:service=JaasSecurityManager">
                   <attribute name="SecurityManagerClassName">
                   org.jboss.security.plugins.JaasSecurityDomain
                   </attribute>
                  </mbean>
                  


                  But even with this modification of the $JBOSS_DIST/server/default/conf/jboss-service.xml it not working.

                  Could anybody give me a hint on which Connector to use?

                  Lots of thanks to Mr Stark and Didi1976 and anybody else thinking about this.

                  • 6. Re: UsersRolesLoginModule AND CLIENT-CERT (desperately)
                    Scott Stark Master

                    No, BaseCertLoginModule will be in 3.2.4.

                    I gave no Connector configuraton in the referenced wiki page, but either one you show will work provided that the server keystore contains the client cert and it is signed by a trusted CA or the javax.net.ssl.trustStore points to a keystore with the CA cert that signed the client cert.

                    • 7. Re: UsersRolesLoginModule AND CLIENT-CERT (desperately)
                      kookywon Newbie

                      I am trying to solve cert based authentication as well. I am using jboss 3.2.5. (Do I need to upgrade?)

                      Anyway, I generated a certificate and imported the client certificate into my server keystore via keytool.

                      I setup web.xml and jboss.xml according to the BaseCertLoginModule. I setup the following security domain in jboss-service.xml:

                      <mbean code="org.jboss.security.plugins.JaasSecurityDomain"
                       name="jboss.web:service=SecurityDomain">
                       <constructor>
                       <arg type="java.lang.String" value="ws-cert"/>
                       </constructor>
                       <attribute name="KeyStoreURL">${jboss.server.config.url}/security/dev.server.keystore</attribute>
                       <attribute name="KeyStorePass">changeit</attribute>
                       </mbean>
                      


                      I added the login module to login-config.xml:

                      <application-policy name = "cert-login">
                       <authentication>
                       <login-module code="org.jboss.security.auth.spi.BaseCertLoginModule"
                       flag = "required">
                       <module-option name="password-stacking">useFirstPass</module-option>
                       <module-option name="securityDomain">java:/jaas/ws-cert</module-option>
                       </login-module>
                       <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
                       flag = "required">
                       <module-option name="password-stacking">useFirstPass</module-option>
                       <module-option name="usersProperties">users.properties</module-option>
                       <module-option name="rolesProperties">roles.properties</module-option>
                       </login-module>
                       </authentication>
                       </application-policy>
                      


                      and created the following entries in
                      users.properties
                      CN\=CO\ CSE\ Client,\ OU\=Child\ Support\ Enforcement,\ O\=State\ of\ Colorado,\ L\=Denver,\ ST\=CO,\ C\=US=password


                      and roles.properties:
                      CN\=CO\ CSE\ Client,\ OU\=Child\ Support\ Enforcement,\ O\=State\ of\ Colorado,\ L\=Denver,\ ST\=CO,\ C\=US=co-client
                      W=co-client


                      where 'W' is the role who is granted access via web.xml.

                      However, I get a (401)Cannot authenticate with the provided credentials error. The article mentions registering this user with the server certificate keystore. Is this something different than trusting the certificate with the VM. If so, how do I accomplish this?

                      Thank you

                      • 8. Re: UsersRolesLoginModule AND CLIENT-CERT (desperately)
                        Scott Stark Master

                        The

                        CN=CO CSE Client, OU=Child Support Enforcement, O=State of Colorado, L=Denver, ST=CO, C=US=password
                        certificate needs to be in the server keystore. Its signer also needs to be in the server keystore as a trusted entry, or in a seperate trust store.

                        • 9. Re: UsersRolesLoginModule AND CLIENT-CERT (desperately)
                          kookywon Newbie

                          This is the part I don't understand. How do you add an entry to they keystore. When I open it up in a text editor it looks like a binary file. Is there a tool that you use to add it (keytool) or do you just fire text in at the end?

                          • 10. Re: UsersRolesLoginModule AND CLIENT-CERT (desperately)
                            kookywon Newbie

                            okay, figured out how to register the certificate with my keystore:

                            keytool -import -alias "CN=CO CSE Client, OU=Child Support Enforcement, O=State of Colorado, L=Denver, ST=CO, C=US" -file dev.client.cer -trustcacerts -keystore dev.server.keystore


                            and added the alias (with control characters) to the users.properties and roles.properties files. I'm getting the following exception now:

                            java.lang.NullPointerException
                             at org.jboss.security.plugins.JaasSecurityManager.getPrincipal(JaasSecurityManager.java:271)
                             at org.jboss.web.tomcat.security.JBossSecurityMgrRealm.authenticate(JBossSecurityMgrRealm.java:173)

                            I think this is because it can't find the user based on the certificate, is this correct?

                            Also when I'm closing down jboss, I get this exception:

                            14:28:19,593 WARN [ServiceController] Problem destroying service jboss.web:service=SecurityDomain
                            java.lang.reflect.UndeclaredThrowableException
                             at $Proxy0.destroy(Unknown Source)
                             at org.jboss.system.ServiceController.destroy(ServiceController.java:514)

                            with this line:

                            Caused by: javax.management.InstanceNotFoundException: jboss.web:service=SecurityDomain is not registered.


                            My security domain entry in jboss-service.xml is exactly like the example in the article. Any reason why I would be getting this error?

                            • 11. Re: UsersRolesLoginModule AND CLIENT-CERT (desperately)
                              Scott Stark Master

                              The JaasSecurityDomain has not been initialized correctly. There was a startup problem that was fixed in 3.2.6 so try that version.

                              • 12. Re: UsersRolesLoginModule AND CLIENT-CERT (desperately)
                                kookywon Newbie

                                That absolutely fixed my problem, everything is working correctly now. I upgraded to 3.2.6, copied over my directories and config files and it ran the way it was supposed to. Thanks for your help.

                                • 13. Re: UsersRolesLoginModule AND CLIENT-CERT (desperately)
                                  kookywon Newbie

                                  Okay got this working on my workstation (Windows, java 1.4.1.03, jboss 3.2.6) and can talk to the webservice from another workstation.

                                  However, when I move the webservice to the dev server (Linux, java 1.4.1.03, jboss 3.2.6) I get this error:

                                  (401)Cannot authenticate with the provided credentials

                                  I copied over my config files to linux directly from my windows configuration after setting up a new server keystore. What gives?

                                  • 14. Re: UsersRolesLoginModule AND CLIENT-CERT (desperately)
                                    Scott Stark Master

                                    Probably a problem with the file encoding/white space differences on the two platforms.

                                    1 2 Previous Next