LdapExtLoginModule throws NullPointerException during rolesS
neelixx Sep 26, 2005 10:12 PMI 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