I am experimenting with JAAS on Tomcat 7.0.30 and am trying to use JAASMemoryLoginModule as a simple test. Unfortunately, I am getting a null pointer exception when I try to login to my web application.

My tomcat-users.xml file is basically equivalent to:

<tomcat-users>

 <role rolename="role1"/>
 <role rolename="role2"/>

 <user username="user1" password="password1" roles="role1"/>
 <user username="user2" password="password2" roles="role1, role2"/>

</tomcat-users>


My jaas.config file is trivial as well:

Catalina {
org.apache.catalina.realm.JAASMemoryLoginModule REQUIRED debug=true;
};

My realm element is nested inside an engine element in server.xml:

    <Realm className="org.apache.catalina.realm.JAASRealm"
             userClassNames="org.apache.catalina.realm.GenericPrincipal"
             roleClassNames="org.apache.catalina.realm.GenericPrincipal"/>

The stack trace for my exception is as follows:

java.lang.NullPointerException
       at java.lang.String.compareTo(String.java:1167)
       at java.lang.String.compareTo(String.java:92)
       at java.util.Arrays.mergeSort(Arrays.java:1144)
       at java.util.Arrays.sort(Arrays.java:1079)
at org.apache.catalina.realm.GenericPrincipal.<init>(GenericPrincipal.java:134) at org.apache.catalina.realm.GenericPrincipal.<init>(GenericPrincipal.java:106) at org.apache.catalina.realm.JAASRealm.createPrincipal(JAASRealm.java:556) at org.apache.catalina.realm.JAASRealm.authenticate(JAASRealm.java:441) at org.apache.catalina.realm.JAASRealm.authenticate(JAASRealm.java:332) at org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:295) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:450) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
       at java.lang.Thread.run(Thread.java:619)

This exception is occurring when we are trying to construct a new GenericPrincipal instance at the end of the createPrincipal method in the org.apache.catalina.realm.JAASRealm class.

   // Return the resulting Principal for our authenticated user

return new GenericPrincipal(username, null, roles, userPrincipal, loginContext);

The "roles" argument is a list of Strings taken from the names of role principals, as shown in this snippet from the same method:

   if (roleClasses.contains(principalClass)) {

       roles.add(principal.getName());

       if( log.isDebugEnabled() ) {
log.debug(sm.getString("jaasRealm.rolePrincipalAdd", principal.getName()));
       }
   }

The problem is that in the commit method of the org.apache.catalina.realm.JAASMemoryLoginModule class, role principals are added to the subject with the name set to null, as shown below (note: the first argument to the GenericPrincipal constructor is the name).

   public boolean commit() throws LoginException {

       log.debug("commit " + principal);
// If authentication was not successful, just return false

       if (principal == null)
           return (false);

       // Add our Principal to the Subject if needed

       if (!subject.getPrincipals().contains(principal)) {

           subject.getPrincipals().add(principal);

// Add the roles as additional subjects as per the contract with the JAASRealm

           if (principal instanceof GenericPrincipal) {

               String roles[] = ((GenericPrincipal) principal).getRoles();

               for (int i = 0; i < roles.length; i++) {

// ********** Here is the line that I think may be wrong *********** subject.getPrincipals().add(new GenericPrincipal(null, roles[i], null));
               }
           }
       }

       committed = true;

       return (true);
   }

As a result, the "roles" list in the createPrincipal method in the org.apache.catalina.realm.JAASRealm class (see above) contains a number of null Strings, which leads to a null pointer exception in the GenericPrincipal constructor, when it calls Arrays.sort, as shown below.

public GenericPrincipal(String name, String password, List<String> roles, Principal userPrincipal, LoginContext loginContext) {
       super();
       this.name = name;
       this.password = password;
       this.userPrincipal = userPrincipal;
       if (roles != null) {
           this.roles = new String[roles.size()];
           this.roles = roles.toArray(this.roles);
           if (this.roles.length > 0)
               Arrays.sort(this.roles);
       }
       this.loginContext = loginContext;
   }

This seems like it could be a bug, but given that I am new to JAAS on Tomcat, I may just be doing something wrong. Any JAAS/Tomcat experts out there able to point me in the right direction?

Jim Doble


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to