0 Replies Latest reply on Sep 26, 2005 10:12 PM by Aaron

    LdapExtLoginModule throws NullPointerException during rolesS

    Aaron Novice

      I was going to add this to JIRA, but wanted to check here first.

      When I launch the test suite for LdapExtLoginModule, it keeps throwing a NullPointerException when executing login(). What is strange, is that everything completes successfully from the network, including the final bind after the role search.

      First, my environment:
      Linux Fedora Core 4
      Eclipse 3.0
      JDK1.5.0_05
      JBoss4.0.3RC2

      Next, let's explain how I am running the test:

      /*
       * JBoss, Home of Professional Open Source
       *
       * Distributable under LGPL license.
       * See terms of license at gnu.org.
       */
      package com.decorativeconcepts.jboss.test;
      
      import java.lang.reflect.Method;
      import java.security.acl.Group;
      import java.util.HashMap;
      import java.util.Set;
      import javax.security.auth.Subject;
      import javax.security.auth.login.AppConfigurationEntry;
      import javax.security.auth.login.Configuration;
      import javax.security.auth.login.LoginContext;
      
      import junit.framework.TestCase;
      import junit.framework.TestSuite;
      import org.jboss.security.SimplePrincipal;
      import org.jboss.security.auth.callback.UsernamePasswordHandler;
      
      /** Tests of the LoginModule classes.
      
       @author Scott.Stark@jboss.org
       @version $Revised: 1.7.6.2 by apaxson $
       @author apaxson@decorativeconcepts.com
       */
      public class LoginModulesTestCase extends TestCase
      {
       static
       {
       try
       {
       Configuration.setConfiguration(new TestConfig());
       System.out.println("Installed TestConfig as JAAS Configuration");
       }
       catch(Exception e)
       {
       e.printStackTrace();
       }
       }
       /** Hard coded login configurations for the test cases. The configuration
       name corresponds to the unit test function that uses the configuration.
       */
       static class TestConfig extends Configuration
       {
       public void refresh()
       {
       }
      
       public AppConfigurationEntry[] getAppConfigurationEntry(String name)
       {
       AppConfigurationEntry[] entry = null;
       try
       {
       Class[] parameterTypes = {};
       Method m = getClass().getDeclaredMethod(name, parameterTypes);
       Object[] args = {};
       entry = (AppConfigurationEntry[]) m.invoke(this, args);
       }
       catch(Exception e)
       {
       }
       return entry;
       }
      
       AppConfigurationEntry[] testLdapToActiveDirectory() {
       String name = "org.jboss.security.auth.spi.LdapExtLoginModule";
       HashMap options = new HashMap();
       options.put("java.naming.factory.initial","com.sun.jndi.ldap.LdapCtxFactory");
       options.put("java.naming.provider.url","ldap://ldap1.mycompany.com:389");
       options.put("java.naming.security.authentication","simple");
      
       options.put("bindDN","cn=query User,cn=Users,dc=mycompany,dc=com");
       options.put("bindCredential","password");
       options.put("baseCtxDN","cn=Users,dc=mycompany,dc=com");
       options.put("baseFilter","(cn={0})");
       options.put("rolesCtxDN","cn=Users,dc=mycompany,dc=com");
       options.put("roleFilter","(member={1})");
       options.put("roleAttributeID","memberOf");
       options.put("roleAttributeIsDN","true");
       options.put("roleNameAttributeID","name");
       options.put("roleRecursion","0");
      
       AppConfigurationEntry ace = new AppConfigurationEntry(name,
       AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
       AppConfigurationEntry[] entry = {ace};
       return entry;
       }
       }
      
       public LoginModulesTestCase(String testName)
       {
       super(testName);
       }
      
       public void testLdapToNCEActiveDirectory() throws Exception {
       System.out.println("testLdapToActiveDirectory");
       UsernamePasswordHandler handler = new UsernamePasswordHandler("apaxson","mypassword".toCharArray());
       LoginContext lc = new LoginContext("testLdapToActiveDirectory",handler);
       lc.login();
      
       Subject subject = lc.getSubject();
       System.out.println("Subject: " + subject);
      
       Set groups = subject.getPrincipals(Group.class);
       Set principals = subject.getPrincipals();
      
       // Assertions
       //assertTrue("Principals contains 'apaxson'", principals.contains(new SimplePrincipal("apaxson@mycompany.com")));
       //assertTrue("Principals contains Roles", groups.contains(new SimplePrincipal("Roles")));
       //iterate through the groups
       //Group roles = (Group) groups.iterator().next();
       //assertTrue("Member has Role - 'Payroll'", roles.isMember(new SimplePrincipal("Payroll")));
       //assertFalse("Member does not have Role - 'JBossAdmin'",roles.isMember(new SimplePrincipal("JBossAdmin")));
      
       }
      
       public static void main(java.lang.String[] args)
       {
       System.setErr(System.out);
       TestSuite suite = new TestSuite(LoginModulesTestCase.class);
       junit.textui.TestRunner.run(suite);
       }
      
      }
      


      And my LDAP LDIF Data:

      dn: CN=DataWhse Admins,CN=Users,DC=mycompany,DC=com
      changetype: add
      member: CN=APaxson,CN=Users,DC=mycompany,DC=com
      cn: DataWhse Admins
      distinguishedName: CN=DataWhse Admins,CN=Users,DC=mycompany,DC=com
      objectClass: group
      name: DataWhse Admins
      sAMAccountName: DataWhse Admins
      
      
      dn: CN=Exchange Admins,CN=Users,DC=mycompany,DC=com
      changetype: add
      member: CN=APaxson,CN=Users,DC=mycompany,DC=com
      cn: Exchange Admins
      distinguishedName: CN=Exchange Admins,CN=Users,DC=mycompany,DC=com
      objectClass: group
      name: Exchange Admins
      sAMAccountName: Exchange Admins
      
      
      dn: CN=IT,CN=Users,DC=mycompany,DC=com
      changetype: add
      member: CN=APaxson,CN=Users,DC=mycompany,DC=com
      cn: IT
      description: Information Technology group
      distinguishedName: CN=IT,CN=Users,DC=mycompany,DC=com
      objectClass: group
      name: IT
      sAMAccountName: IT
      
      dn: CN=Payroll,CN=Users,DC=mycompany,DC=com
      changetype: add
      member: CN=APaxson,CN=Users,DC=mycompany,DC=com
      cn: Payroll
      distinguishedName: CN=Payroll,CN=Users,DC=mycompany,DC=com
      objectClass: group
      name: Payroll
      sAMAccountName: Payroll
      
      dn: CN=Portal Admins,CN=Users,DC=mycompany,DC=com
      changetype: add
      member: CN=APaxson,CN=Users,DC=mycompany,DC=com
      cn: Portal Admins
      distinguishedName: CN=Portal Admins,CN=Users,DC=mycompany,DC=com
      objectClass: group
      name: Portal Admins
      sAMAccountName: Portal Admins
      
      
      dn: CN=query User,CN=Users,DC=mycompany,DC=com
      changetype: add
      cn: query User
      description: Used to query LDAP attributes from various applications
      displayName: query User
      givenName: query
      distinguishedName: CN=query User,CN=Users,DC=mycompany,DC=com
      objectClass: user
      name: query User
      sAMAccountName: query
      sn: User
      userPrincipalName: query@mycompany.com
      
      
      dn: CN=Crystal Enterprise Designers,CN=Users,DC=mycompany,DC=com
      changetype: add
      member: CN=APaxson,CN=Users,DC=mycompany,DC=com
      cn: Crystal Enterprise Designers
      distinguishedName:
       CN=Crystal Enterprise Designers,CN=Users,DC=mycompany,DC=com
      objectCategory:
       CN=Group,CN=Schema,CN=Configuration,DC=decorativeconcepts,DC=com
      objectClass: group
      name: Crystal Enterprise Designers
      sAMAccountName: Crystal Enterprise Designers
      
      
      dn: CN=APaxson,CN=Users,DC=mycompany,DC=com
      changetype: add
      memberOf: CN=Crystal Enterprise Designers,CN=Users,DC=mycompany,DC=com
      memberOf: CN=Portal Admins,CN=Users,DC=mycompany,DC=com
      memberOf: CN=Payroll,CN=Users,DC=mycompany,DC=com
      memberOf: CN=IT,CN=Users,DC=mycompany,DC=com
      memberOf: CN=Exchange Admins,CN=Users,DC=mycompany,DC=com
      memberOf: CN=DataWhse Admins,CN=Users,DC=mycompany,DC=com
      memberOf: CN=Administrators,CN=Builtin,DC=mycompany,DC=com
      memberOf: CN=Domain Users,CN=Users,DC=mycompany,DC=com
      distinguishedName: CN=APaxson,CN=Users,DC=mycompany,DC=com
      objectClass: user
      name: APaxson
      sAMAccountName: APaxson
      


      And now, the exception code

      javax.security.auth.login.LoginException: java.lang.NullPointerException
       at org.jboss.security.auth.spi.LdapExtLoginModule.rolesSearch(LdapExtLoginModule.java:306)
       at org.jboss.security.auth.spi.LdapExtLoginModule.createLdapInitContext(LdapExtLoginModule.java:231)
       at org.jboss.security.auth.spi.LdapExtLoginModule.validatePassword(LdapExtLoginModule.java:129)
       at org.jboss.security.auth.spi.UsernamePasswordLoginModule.login(UsernamePasswordLoginModule.java:163)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:585)
       at javax.security.auth.login.LoginContext.invoke(LoginContext.java:769)
       at javax.security.auth.login.LoginContext.access$000(LoginContext.java:186)
       at javax.security.auth.login.LoginContext$4.run(LoginContext.java:683)
       at java.security.AccessController.doPrivileged(Native Method)
       at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
       at javax.security.auth.login.LoginContext.login(LoginContext.java:579)
       at com.decorativeconcepts.jboss.test.LoginModulesTestCase.testLdapToActiveDirectory(LoginModulesTestCase.java:474)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:585)
       at junit.framework.TestCase.runTest(TestCase.java:154)
       at junit.framework.TestCase.runBare(TestCase.java:127)
       at junit.framework.TestResult$1.protect(TestResult.java:106)
       at junit.framework.TestResult.runProtected(TestResult.java:124)
       at junit.framework.TestResult.run(TestResult.java:109)
       at junit.framework.TestCase.run(TestCase.java:118)
       at junit.framework.TestSuite.runTest(TestSuite.java:208)
       at junit.framework.TestSuite.run(TestSuite.java:203)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:436)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:311)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
      
       at javax.security.auth.login.LoginContext.invoke(LoginContext.java:872)
       at javax.security.auth.login.LoginContext.access$000(LoginContext.java:186)
       at javax.security.auth.login.LoginContext$4.run(LoginContext.java:683)
       at java.security.AccessController.doPrivileged(Native Method)
       at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
       at javax.security.auth.login.LoginContext.login(LoginContext.java:579)
       at com.decorativeconcepts.jboss.test.LoginModulesTestCase.testLdapToActiveDirectory(LoginModulesTestCase.java:474)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:585)
       at junit.framework.TestCase.runTest(TestCase.java:154)
       at junit.framework.TestCase.runBare(TestCase.java:127)
       at junit.framework.TestResult$1.protect(TestResult.java:106)
       at junit.framework.TestResult.runProtected(TestResult.java:124)
       at junit.framework.TestResult.run(TestResult.java:109)
       at junit.framework.TestCase.run(TestCase.java:118)
       at junit.framework.TestSuite.runTest(TestSuite.java:208)
       at junit.framework.TestSuite.run(TestSuite.java:203)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:436)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:311)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
      
      


      And finally, the packet trace. You can see here:

      Bind as the query user for performing searches in AD
      Binding successful
      Search AD for the authenticating user
      Search successful. Return DN
      Unbind successful
      Bind as the found DN user
      Binding successful
      Query roles for the DN User
      Search complete. Returns 7 results.
      Unbind successful

      So why the NullPointerException? If it's because it's not parsing my roles right, then what is causing the elegant "unbind" when rolesSearch() completed?

      Rather than bunching up the packet trace in this post, I'll place a link to it. It's just a text file, with all the LDAP packets expanded to see the data, but it requires "full-screen" to be able to read it well.

      http://aaron.thepaxson5.org/blog/files/ldapCapture-modified.txt

      Please let me know if I need to post this to JIRA, or if it's something else. I couldn't find anything about this on JIRA.

      Thanks!
      --Aaron