-
Bug
-
Resolution: Not an Issue
-
P3
-
None
-
1.3.1
-
x86
-
linux_2.4
This problem is reproduceable a 100% of the time.
Here are the requirements.
Client OS: Linux only. Does not happen on Solaris.
Directory Server: SunONE Directory server. Same failure seen with
many other directory servers as well.
JAVA Version: 1.3.1_08 not seen on 1.4.1_02.
Execute the following code. Provide correct login and password for the previledged users "cn=Directory Manager" but provide wrong password of the
normal user.
import javax.naming.directory.*;
import javax.naming.*;
import java.util.Hashtable;
class Tester{
public static void main(String[] args){
Tester t=new Tester();
t.doTest("ldap://my-system.East.Sun.COM:389/",
"ou=People,o=isp", "cn=Directory Manager", "password", "uid", "TUser", "wrongpass");
try{
Thread.sleep(10000);
} catch (Exception e){}
}
public void doTest( String ldapUrl, String searchContext, String privilegedUserDN, String privilegedUserPwd, String userTag, String userId, String userPasswd )
{
boolean initialBindSucceeded = false;
boolean userFound = false;
boolean userBindSucceeded = false;
DirContext initialCtx = null;
NamingEnumeration searchResults = null;
DirContext userCtx = null;
// Create initial directory Context
Hashtable env = new Hashtable(10);
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapUrl);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, privilegedUserDN);
env.put(Context.SECURITY_CREDENTIALS, privilegedUserPwd);
env.put("java.naming.ldap.derefAliases" , "never");
env.put(Context.REFERRAL, "ignore");
env.put("java.naming.ldap.referral.limit", "0");
try
{
// Bind using privileged user credentials
initialCtx = new InitialDirContext( env );
initialBindSucceeded = initialCtx != null;
if ( initialBindSucceeded )
System.out.println( "Initial bind succeeded." );
// Search for user w/ username from login form
String strSearchFilter = "(" + userTag + "=" + userId + ")";
SearchResult sr = null;
String srDN = null;
SearchControls searchCtls = new SearchControls();
boolean bSubtree = true;
searchCtls.setSearchScope( bSubtree ? SearchControls.SUBTREE_SCOPE : SearchControls.ONELEVEL_SCOPE );
searchResults = initialCtx.search(searchContext, strSearchFilter, search
Ctls);
userFound = searchResults.hasMore() && (sr=(SearchResult)searchResults.next()) != null;
if ( userFound )
{
srDN = sr.getName() + "," + searchContext;
System.out.println( "User found." );
System.out.println( "Search result DN: " + srDN );
}
else
{
throw new RuntimeException( "User not found." );
}
// Bind using login form credentials
env.remove(Context.SECURITY_PRINCIPAL);
env.remove(Context.SECURITY_CREDENTIALS);
env.put(Context.SECURITY_PRINCIPAL, srDN);
env.put(Context.SECURITY_CREDENTIALS, userPasswd);
userCtx = new InitialDirContext( env );
userBindSucceeded = userCtx != null;
if ( userBindSucceeded )
System.out.println( "User bind succeeded." );
Thread.sleep(10000);
}
catch( Exception e )
{
if ( !initialBindSucceeded )
System.out.println( "Initial bind failed: " + e.getMessage() );
if ( !userFound )
System.out.println( "User not found: " + e.getMessage() );
if ( !userBindSucceeded )
System.out.println( "User bind failed: " + e.getMessage() );
e.printStackTrace( System.out );
}
finally
{
System.out.println( "Closing resources...");
try
{
if ( searchResults != null )
searchResults.close();
if ( initialCtx != null )
initialCtx.close();
if ( userCtx != null )
userCtx.close();
}
catch( NamingException ne )
{
System.out.println( "Error trying to close LDAP connection: " + ne.getMessage() );
ne.printStackTrace( System.out );
}
}
}
}
After you run the code you will see that the second connection is still in
the ESTABLISHED state. This is because the InitialDirContext() returned null
but still kept the connection open. In this case there is no way to close the
connection.
Here are the requirements.
Client OS: Linux only. Does not happen on Solaris.
Directory Server: SunONE Directory server. Same failure seen with
many other directory servers as well.
JAVA Version: 1.3.1_08 not seen on 1.4.1_02.
Execute the following code. Provide correct login and password for the previledged users "cn=Directory Manager" but provide wrong password of the
normal user.
import javax.naming.directory.*;
import javax.naming.*;
import java.util.Hashtable;
class Tester{
public static void main(String[] args){
Tester t=new Tester();
t.doTest("ldap://my-system.East.Sun.COM:389/",
"ou=People,o=isp", "cn=Directory Manager", "password", "uid", "TUser", "wrongpass");
try{
Thread.sleep(10000);
} catch (Exception e){}
}
public void doTest( String ldapUrl, String searchContext, String privilegedUserDN, String privilegedUserPwd, String userTag, String userId, String userPasswd )
{
boolean initialBindSucceeded = false;
boolean userFound = false;
boolean userBindSucceeded = false;
DirContext initialCtx = null;
NamingEnumeration searchResults = null;
DirContext userCtx = null;
// Create initial directory Context
Hashtable env = new Hashtable(10);
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapUrl);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, privilegedUserDN);
env.put(Context.SECURITY_CREDENTIALS, privilegedUserPwd);
env.put("java.naming.ldap.derefAliases" , "never");
env.put(Context.REFERRAL, "ignore");
env.put("java.naming.ldap.referral.limit", "0");
try
{
// Bind using privileged user credentials
initialCtx = new InitialDirContext( env );
initialBindSucceeded = initialCtx != null;
if ( initialBindSucceeded )
System.out.println( "Initial bind succeeded." );
// Search for user w/ username from login form
String strSearchFilter = "(" + userTag + "=" + userId + ")";
SearchResult sr = null;
String srDN = null;
SearchControls searchCtls = new SearchControls();
boolean bSubtree = true;
searchCtls.setSearchScope( bSubtree ? SearchControls.SUBTREE_SCOPE : SearchControls.ONELEVEL_SCOPE );
searchResults = initialCtx.search(searchContext, strSearchFilter, search
Ctls);
userFound = searchResults.hasMore() && (sr=(SearchResult)searchResults.next()) != null;
if ( userFound )
{
srDN = sr.getName() + "," + searchContext;
System.out.println( "User found." );
System.out.println( "Search result DN: " + srDN );
}
else
{
throw new RuntimeException( "User not found." );
}
// Bind using login form credentials
env.remove(Context.SECURITY_PRINCIPAL);
env.remove(Context.SECURITY_CREDENTIALS);
env.put(Context.SECURITY_PRINCIPAL, srDN);
env.put(Context.SECURITY_CREDENTIALS, userPasswd);
userCtx = new InitialDirContext( env );
userBindSucceeded = userCtx != null;
if ( userBindSucceeded )
System.out.println( "User bind succeeded." );
Thread.sleep(10000);
}
catch( Exception e )
{
if ( !initialBindSucceeded )
System.out.println( "Initial bind failed: " + e.getMessage() );
if ( !userFound )
System.out.println( "User not found: " + e.getMessage() );
if ( !userBindSucceeded )
System.out.println( "User bind failed: " + e.getMessage() );
e.printStackTrace( System.out );
}
finally
{
System.out.println( "Closing resources...");
try
{
if ( searchResults != null )
searchResults.close();
if ( initialCtx != null )
initialCtx.close();
if ( userCtx != null )
userCtx.close();
}
catch( NamingException ne )
{
System.out.println( "Error trying to close LDAP connection: " + ne.getMessage() );
ne.printStackTrace( System.out );
}
}
}
}
After you run the code you will see that the second connection is still in
the ESTABLISHED state. This is because the InitialDirContext() returned null
but still kept the connection open. In this case there is no way to close the
connection.