Retrieving LDAP entries from Active Directory

M

Malte

I am using JNDI to retrieve records from Active Directory.

For some of the users the following snippet throws a NullPointerException:

int userAccountControl =
Integer.parseInt((String)att.get("userAccountControl").get());

In fact, just this code: att.get("userAccountControl").get();
throws an exception.

The att object is a result of

att = sr.getAttributes()

where sr is a SearchResult object.

Using an ldap browser I see nothing unusual, the userAccountControl
attribute usually has the value 512, in some instances 514 (invalid).

I'd like to know what might throw this exception.
 
I

iksrazal

Malte said:
I am using JNDI to retrieve records from Active Directory.

For some of the users the following snippet throws a NullPointerException:

int userAccountControl =
Integer.parseInt((String)att.get("userAccountControl").get());

In fact, just this code: att.get("userAccountControl").get();
throws an exception.

The att object is a result of

att = sr.getAttributes()

where sr is a SearchResult object.

Using an ldap browser I see nothing unusual, the userAccountControl
attribute usually has the value 512, in some instances 514 (invalid).

I'd like to know what might throw this exception.

Hard to say just from this code snippet and your schema description.
Plus I only really use OpenLDAP. Even still, I'd try to log all the
attributes when the exception is thrown, using something like...

for (NamingEnumeration ne = attrs.getAll(); ne.hasMoreElements();)
{
Attribute attr = (Attribute)ne.next();
String attrID = attr.getID();
System.out.println (attrID+":");
for (Enumeration vals = attr.getAll();vals.hasMoreElements();)
{
System.out.println ("\t"+vals.nextElement());
}
}

Since you only get the error sometimes, one of your fields must be
unexpectedly null, ie, my guess is that your data is not always
organized as expected.

For what its worth, I do something like:

/**
Gets a java object from LDAP associated by a distiguished name.
<p>
This method is inteneded to be used for schemas like inetOrgPerson
for attributes
such as userCertificate;binary
<p>
@param type Which attribute to search for and return
@param results Complete list of all available entries for the
requested DN
@return Object or null if there are problems
*/
private Object doLookup (NamingEnumeration results, String type)
throws WSSecurityException
{
try
{
Fwlog.debug(this, Fwlog.DB, "doLookup...");
if (results.hasMore())
{
SearchResult sr = (SearchResult) results.next();
javax.naming.directory.Attributes xanswer =
sr.getAttributes();
javax.naming.directory.Attribute attribute =
xanswer.get(type);
// check if attribute missing
if (null==attribute)
{
throw new IllegalStateException("\nERROR: Attribute type not
found: " + type);
}

// retrieve attribute as object and return
Object o = attribute.get();
if (null == o)
{
throw new IllegalStateException("Recieved null object for
attribute type: " + type);
}

return o;
}
else
{
throw new IllegalStateException("Empty Subject recieved");
}
}//end try
catch ( Exception e )
{
Fwlog.error(this, Fwlog.DB, "doLookup() failed for for type: " +
type);
Fwlog.error(this, Fwlog.DB, e);
}
}

HTH,
iksrazal
http://www.braziloutsource.com/
 
N

Nigel Wade

Malte said:
I am using JNDI to retrieve records from Active Directory.

For some of the users the following snippet throws a NullPointerException:

int userAccountControl =
Integer.parseInt((String)att.get("userAccountControl").get());

In fact, just this code: att.get("userAccountControl").get();
throws an exception.

The att object is a result of

att = sr.getAttributes()

where sr is a SearchResult object.

Using an ldap browser I see nothing unusual, the userAccountControl
attribute usually has the value 512, in some instances 514 (invalid).

I'd like to know what might throw this exception.

From the limited code and description it's impossible to give a definitive
answer.

But the error means that either att is null, or that att.get() returned
null. Since you haven't told us what either of them we can only speculate
as to why they are null.

NOTE: if att is of type Attributes then Attributes.get() can return null, as
can Attribute.get().
 
M

Malte

Nigel said:
From the limited code and description it's impossible to give a definitive
answer.

But the error means that either att is null, or that att.get() returned
null. Since you haven't told us what either of them we can only speculate
as to why they are null.

NOTE: if att is of type Attributes then Attributes.get() can return null, as
can Attribute.get().


att is not null. att.get() returns null. All other fields in the att
variable can be queried. Only the userAccountControl cannot. The
userAccountControl field has the value 512 (verified using ldab browser).

Actually, att.get() throws an exception, just trying to query the darned
thing, that is what worries me.
 
N

Nigel Wade

Malte said:
att is not null. att.get() returns null. All other fields in the att
variable can be queried. Only the userAccountControl cannot. The
userAccountControl field has the value 512 (verified using ldab browser).

Did you request it in the list of return attributes?
Does the user you bind to the LDAP server have permission to read or search
that attribute?
Actually, att.get() throws an exception, just trying to query the darned
thing, that is what worries me.

What exception?
 
M

Malte

Nigel said:
Did you request it in the list of return attributes?
Does the user you bind to the LDAP server have permission to read or search
that attribute?

No, I did not use the return attributes way of querying ldap. The user I
use to bind has permission to read all attributes and retrieve up to
8000 entries (the server has less than 6000).

Not using a list of return attributes should give me all? Or is this
where the mistake is?
What exception?

NullPointerException.
 
M

Malte

Malte said:
No, I did not use the return attributes way of querying ldap. The user I
use to bind has permission to read all attributes and retrieve up to
8000 entries (the server has less than 6000).

Not using a list of return attributes should give me all? Or is this
where the mistake is?


NullPointerException.
I should add that my program has run without a hitch for approx. 13
months. I never changed this part of the program, and the JDK used is
the same. The customer swears they did not change anything in Active
Directory. Obviouslly, at least one of these statements has to be false ;-)
 
N

Nigel Wade

Malte said:
No, I did not use the return attributes way of querying ldap. The user I
use to bind has permission to read all attributes and retrieve up to
8000 entries (the server has less than 6000).

Not using a list of return attributes should give me all? Or is this
where the mistake is?

It should return all the readable attributes.
How are you querying the ActiveDirectory, and how are you enumerating the
returned results?
NullPointerException.

I presume that att it of class BasicAttributes? att.get(String) method
should not result in a NullPointerException unless att itself is null, or,
perhaps if the argument string is null (the docs say that the argument must
be non-null).
 
M

Malte

Nigel said:
Malte wrote:

The basic process is this:

1. Get a DirContext (OK)

2. Call this function:

private NamingEnumeration getAlladUsers(DirContext ctx) throws Exception {
SearchControls ctls = new SearchControls();
ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
// next two statements get data from a Properties file
String filter = basicProperties.getProperty("sourceSearchFilter");
String searchLevel =
basicProperties.getProperty("sourceSearchFromLevel");
answer = ctx.search(searchLevel, filter, ctls);

return answer;
}

3. Process the NamingEnumeration

// some code removed because it is redundant (to this snippet)

while (adList.hasMore()) { // for each record // adList is the
"answer" NamingEnumeration returned form the getAlladUser method.

sr = (SearchResult)adList.next(); // get the SearchResult object
att = sr.getAttributes(); // get the Attributes object

if (att == null) {
continue;
}

tmp = (String)att.get("cn").get(); // save the "cn" value
if (tmp == null) {
continue;
}

String sAMA = (String)att.get("sAMAccountName").get();

if (sAMA == null) {
continue;
}

int validUser = 512;
int inactiveUser = 2;
int userAccountControl =
//!!!!!!!!!!! This is where it bombs out. Even
att.get("userAccountControl").get() returns null, so it is not related
to the Integer.parseInt() call
Integer.parseInt((String)att.get("userAccountControl").get());
if (
(validUser == (userAccountControl & validUser)) &&
(inactiveUser != (userAccountControl & inactiveUser))
) {

// rest of the code is more of the same
 
N

Nigel Wade

Malte said:
The basic process is this:

1. Get a DirContext (OK)

2. Call this function:

private NamingEnumeration getAlladUsers(DirContext ctx) throws Exception {
SearchControls ctls = new SearchControls();
ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
// next two statements get data from a Properties file
String filter = basicProperties.getProperty("sourceSearchFilter");
String searchLevel =
basicProperties.getProperty("sourceSearchFromLevel");
answer = ctx.search(searchLevel, filter, ctls);

return answer;
}

3. Process the NamingEnumeration

// some code removed because it is redundant (to this snippet)

while (adList.hasMore()) { // for each record // adList is the
"answer" NamingEnumeration returned form the getAlladUser method.

sr = (SearchResult)adList.next(); // get the SearchResult object
att = sr.getAttributes(); // get the Attributes object

if (att == null) {
continue;
}

tmp = (String)att.get("cn").get(); // save the "cn" value
if (tmp == null) {
continue;
}

String sAMA = (String)att.get("sAMAccountName").get();

if (sAMA == null) {
continue;
}

int validUser = 512;
int inactiveUser = 2;
int userAccountControl =
//!!!!!!!!!!! This is where it bombs out. Even
att.get("userAccountControl").get() returns null, so it is not related
to the Integer.parseInt() call
Integer.parseInt((String)att.get("userAccountControl").get());
if (
(validUser == (userAccountControl & validUser)) &&
(inactiveUser != (userAccountControl & inactiveUser))
) {

// rest of the code is more of the same

That all looks perfectly fine.

In your comment above you say that att.get("userAccountControl").get()
returns null. Do you really mean that, or is it that
att.get("userAccountControl") returns null, and
att.get("userAccountControl").get() throws NullPointerException? I could
understand that. If "userAccountControl" isn't found in the list of
attributes for the entry then att.get("userAccountControl") will return
null, so attempting to invoke <null>.get() will throw the Exception.

Can you verify the case of "userAccountControl" in the entry? It might be a
simple failure to match on case. I use the BasicAttributes(true) method of
searching which performs case insensitive search. I can't spot a similar
method of specifying case insensitive search using SearchControls though.
Of course, this might be a red herring...
 
M

Malte

Nigel said:
That all looks perfectly fine.

In your comment above you say that att.get("userAccountControl").get()
returns null. Do you really mean that, or is it that
att.get("userAccountControl") returns null, and
att.get("userAccountControl").get() throws NullPointerException? I could
understand that. If "userAccountControl" isn't found in the list of
attributes for the entry then att.get("userAccountControl") will return
null, so attempting to invoke <null>.get() will throw the Exception.

Can you verify the case of "userAccountControl" in the entry? It might be a
simple failure to match on case. I use the BasicAttributes(true) method of
searching which performs case insensitive search. I can't spot a similar
method of specifying case insensitive search using SearchControls though.
Of course, this might be a red herring...

Thank you for your reply. The userAccountControl attribute is the same,
including case, for all 5000 entries in Active Directory. I have
verified, using ldapbrowser that the value is '512'. My program bombs
out for approx. 80% of the 5000 entries. Always when querying the
userAccountControl attribute, which ALWAYS has a value, sometimes 512,
sometimes 514 (inactive user), and sometimes other values.

Just this call att.get("userAccountControl").get() throws the
nullpointer exception, which baffles me, because the result should be
just null, it should not throw an exception.

I have been wondering if I should set my queries up specifying exactly
which attributes I want, but as it is I get them all and query only
approx. 12 of them (title, l, streetAddress, department,
physicalDeliveryAddress, etc.).
 
N

Nigel Wade

Malte said:
Thank you for your reply. The userAccountControl attribute is the same,
including case, for all 5000 entries in Active Directory. I have
verified, using ldapbrowser that the value is '512'. My program bombs
out for approx. 80% of the 5000 entries. Always when querying the
userAccountControl attribute, which ALWAYS has a value, sometimes 512,
sometimes 514 (inactive user), and sometimes other values.

Just this call att.get("userAccountControl").get() throws the
nullpointer exception, which baffles me, because the result should be
just null, it should not throw an exception.

As I've said before, this will throw NullPointerException if
userAccountControl is not one of the attributes returned by the search. You
must test the return value of Attributes.get(String) invocation for null,
before you attempt to get the actual value with the second invocation of
Attribute.get().
I have been wondering if I should set my queries up specifying exactly
which attributes I want, but as it is I get them all and query only
approx. 12 of them (title, l, streetAddress, department,
physicalDeliveryAddress, etc.).

Is it always the same entries which cause the problem? What happens if you
restrict the search so that only a few entries are returned, but include
those which cause the problem?

I would use a network protocol analyser and look at what is actually being
returned by the LDAP server, provided it's not encrypted.
 
M

Malte

Nigel said:
Malte wrote:




As I've said before, this will throw NullPointerException if
userAccountControl is not one of the attributes returned by the search. You
must test the return value of Attributes.get(String) invocation for null,
before you attempt to get the actual value with the second invocation of
Attribute.get().




Is it always the same entries which cause the problem? What happens if you
restrict the search so that only a few entries are returned, but include
those which cause the problem?

I would use a network protocol analyser and look at what is actually being
returned by the LDAP server, provided it's not encrypted.
You have given a couple of pointer, that I will follow up on. Thanks a
lot for helping.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top