SSL & Referrals - LDAPS://vs.LDAP:// :636
I have a short example program that attempts to follow referrals in an LDAP directory using SSL,
when I modify an entry in a consumer directory.
I can only get this to work if I modify the referral string that is returned from the referralException.
The referral string that is returned is always of the form "LDAPS://myserver" .
If I change this referral string to "LDAP://myserver:636" the program will work just fine.
I've seen this same kind of problem in the "java ldap jdk" jar file and also in perl/ldap .
If I don't modify the referral string, I get a NamingException saying that it is "Not an LDAP URL".
Does anyone know why this is necessary? Is there a supported workaround ?
The following code demonstrates this. Modify the two lines marked "CHANGE" and specify
an attribute, attribute value and an entry's distinguished name to use in a directory (that is set up to follow referrals using SSL).Once it works, you can comment out the block of code that changes the
referral string and the error will occur.
To Run , type:
java JNDITest ldap://yourdirectory:636 "bind distinguished name" "bind password"
Note: you can also generate the same error with a standalone SSL ldap directory by entering
the directory name in the "ldaps" format
example:
java JNDITest ldaps://yourdirectory "bind distinguished name" "bind password"
// Example of what JNDI does with SSL/referrals
import java.util.*;
import java.util.Hashtable;
import java.util.Enumeration;
import javax.naming.*;
import javax.naming.directory.*;
public class JNDITest
{
public JNDITest()
{
}
public static void main(String args[])
{
if (args.length != 3)
{
System.out.println("Usage: java JNDITest ldaphost dn pwd");
System.exit(0);
}
JNDITest jt = new JNDITest();
DirContext ctx = null;
SearchControls constraints = null;
Hashtable env = null;
boolean ok;
try
{
env = new Hashtable();
env.put
(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put
(Context.PROVIDER_URL, args[0]);
//SSL
env.put(Context.SECURITY_PROTOCOL, "ssl");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL,args[1]);
env.put(Context.SECURITY_CREDENTIALS, args[2]);
//referrals
env.put(Context.REFERRAL, "throw");
ctx = new InitialDirContext(env);
constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
}
catch (Exception e)
{
System.out.println("Error in init:"+e.toString());
e.printStackTrace();
System.exit(0);
}
// attempt modification
int cnt = 0;
ok = true;
while (ok)
{
try
{
ModificationItem[] mods = new ModificationItem[1];
mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute("YOURATTRIBUTE","YOURATTRIBUTEVALUE"));//CHANGE
ctx.modifyAttributes("YOUR ENTRY'S DISTINGUISHED NAME",// CHANGE
mods);
ok = false;
}
catch (ReferralException r)
{
String referral = (String) r.getReferralInfo();
System.out.println("ReferralException info="+referral);
//
//Comment out this block of code and the program will throw an exception
//
// strip off the ldaps and replace it with ldap going to port 636
if ((referral.startsWith("ldaps"))||(referral.startsWith("LDAPS")))
{
String newer = "ldap://";
int i = referral.indexOf("//");
if (i<0)
{System.out.println("err in referral:"+referral);
System.exit(1);}
i = i + 2;
newer = newer + referral.substring(i) + ":636";
referral = newer;
System.out.println("Referral changed to:"+referral);
}
//-
env.put(Context.PROVIDER_URL, referral);
try {ctx = new InitialDirContext(env);}
catch (Exception xx)
{
System.out.println("Exception in new init:"+xx.toString());
System.exit(0);
}
System.out.println("SUCCESS on new context");
cnt++;
if (cnt > 4) {ok = false;}
}
catch (Exception ee)
{
System.out.println("Error in mods:"+ee.toString());
System.exit(0);
}
}
} //main
}

