Active Directory LDAP query with PagedResultsControl help

Hello everyone,
I would like to first say that I am not a developer of any sort but I can usually fight my way through some scripting languages…most of the time with ugly form.

After a few days of reading java docs and examples, I have been successful at querying our Active Directory for some user attributes in a Project. However, [color=#FF0040]Microsoft limits the results in one search to 1000 and I need more[/color]. One option is to increase the Page size on the Domain Controller but that’s not an option. The other is using PagedResultsControl. I’ve read the documents and examples and it seems like you set a PageSize, create a cookie, and pass the cookie back and forth with the server until it’s null. This should give x number of results per request and continue to iterate through.

The problem is that I just don’t understand Jython and Java enough to know what’s going wrong. My gateway is version 7.5.3 (Windows 2008R2) and when I run the following portion of code:

from java.util import *
from javax.naming import *
from javax.naming.directory import *
from javax.naming.ldap import *
import java.util.Hashtable
import java.util.Enumeration

env = Hashtable()
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory")
env.put(Context.PROVIDER_URL, "ldap://servername:389")
env.put(Context.SECURITY_AUTHENTICATION, "simple")
env.put(Context.SECURITY_PRINCIPAL, "CN=username,OU=Users,DC=domain,DC=com")
env.put(Context.SECURITY_CREDENTIALS, "password")

ctx = InitialLdapContext(env,None)

pageSize = 10

ctxCtls = Control(PagedResultsControl(pageSize,Control.CRITICAL))

ctx.setRequestControls(ctxCtls)

I get the following error:

TypeError: No visible constructors for class (javax.naming.ldap.Control)

I have a feeling this is either something very simple or I’m way over my head with this stuff. I would have given up long ago had it not been so easy to get 1000 results with InitialDirContext.

I understand this may be out of the scope of support on this forum but with the amount of expertise I’ve witnessed while lurking, I’m hoping someone can point me in the right direction. Thank you.

Anthony

This is a little bit of a shot in the dark but can you try the following and see if it works:

ctxCtls = [PagedResultsControl(pageSize,Control.CRITICAL)]

ctx.setRequestControls(ctxCtls)

Looking through the javadocs i see that setRequestControls takes an argument of Control[]. PagedResultsControl implements the Control interface so you should just be able to pass a list of PagedResultsControls to the setRequestControls function.

The error you’re getting seems to be referring to the fact that you’re trying to get an instance of Control which is only an interface and doesn’t have a constructor. Let me know how this works out for you.

Dave,
Thank you! That worked perfectly and got me one step further. I am able to request any number of results now but I’m still trying to figure out how to read the response back from the server and set up the cookie exchange to iterate through the results until it’s null.

Just wanted to give you an update. I’ll debug further tonight and post back on my success.

I’m having an issue trying to get the contents of getResponseControls() into a cookie so I can pass it back to the server with the:

ctx.setRequestControls([PagedResultsControl(pageSize,cookie,Control.CRITICAL)])

The error I get is:

[quote]TypeError: javax.naming.ldap.PagedResultsControl(): 2nd arg can’t be coerced to byte[]
[/quote]

When I print the cookie after the getResponseControls(), it looks like this:

[quote]array(javax.naming.ldap.Control, [javax.naming.ldap.PagedResultsResponseControl@533706])
[/quote]

I’m wondering if that is a string or something that needs to be converted into a byte. I started messing around with building a byte of zeros with jarray.zeros and also tried converting using jarray.array but I’m not having any luck…presumably because I suck at this stuff. But I am exhausting all research before posting on this great forum.

Here’s what I’m up to so far by using the example at forums.oracle.com/thread/1157644

[code]from java.util import *
from javax.naming import *
from javax.naming.directory import *
from javax.naming.ldap import *
import java.util.Hashtable
import java.util.Enumeration
import jarray

env = Hashtable()
env.put(Context.INITIAL_CONTEXT_FACTORY, “com.sun.jndi.ldap.LdapCtxFactory”)
env.put(Context.PROVIDER_URL, “ldap://servername:389”)
env.put(Context.SECURITY_AUTHENTICATION, “simple”)
env.put(Context.SECURITY_PRINCIPAL, “CN=username,DC=Users,DC=cosma,DC=com”)
env.put(Context.SECURITY_CREDENTIALS, “password”)

ctx = InitialLdapContext(env,None)

searchCtls = SearchControls()
returnedAtts = (“sn”,“givenName”,“cn”)
searchCtls.setReturningAttributes(returnedAtts)
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE)

pageSize = 5
cookie = jarray.zeros(1024,‘b’)

ctx.setRequestControls([PagedResultsControl(pageSize,Control.CRITICAL)])

totalResults = 0

results = ctx.search(“dc=bgm,dc=cosma,dc=com”,“objectclass=user”,searchCtls)

while (results != “” and results.hasMoreElements()):
entry = results.next()
try:
print entry.getName()
totalResults = totalResults + 1
except:
pass

cookie = ctx.getResponseControls()
ctx.setRequestControls([PagedResultsControl(pageSize,cookie,Control.CRITICAL)])
[/code]

A quick glance at the docs (docs.oracle.com/javase/tutorial/ … sults.html) shows that the cookie should be a byte[] that you obtain from getCookie() called on the PagedResultsResponseControl you get back, not the PagedResultsResponseControl itself, which it looks like you’re using.

Thanks for pointing me in the right direction guys. I read the javadocs but sometimes it’s difficult for me to understand how to incorporate classes within Jython due to the lengthy Java syntax. Anyway, we got it working…had to have a real developer help with the looping.

Here’s the code if anyone is interested. I have the pageSize set to 1000 because that’s what Active Directory restricts to by default.

[code]from java.util import *
from javax.naming import *
from javax.naming.directory import *
from javax.naming.ldap import *
import java.util.Hashtable
import java.util.Enumeration

env = Hashtable()
env.put(Context.INITIAL_CONTEXT_FACTORY, “com.sun.jndi.ldap.LdapCtxFactory”)
env.put(Context.PROVIDER_URL, “ldap://server:389”)
env.put(Context.SECURITY_AUTHENTICATION, “simple”)
env.put(Context.SECURITY_PRINCIPAL, “CN=username,DC=Users,DC=domain,DC=com”)
env.put(Context.SECURITY_CREDENTIALS, “password”)

ctx = InitialLdapContext(env,None)

searchCtls = SearchControls()
returnedAtts = (“sn”,“givenName”,“cn”)
searchCtls.setReturningAttributes(returnedAtts)
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE)

pageSize = 1000
cookie = None

ctx.setRequestControls([PagedResultsControl(pageSize,Control.CRITICAL)])

results = ctx.search(“dc=subdomain,dc=domain,dc=com”,"(&(objectCategory=person)(objectClass=user))",searchCtls)

while (results != “” and results.hasMoreElements()):
entry = results.next()
attrs=entry.getAttributes()
try:
print attrs.get(“givenName”).get() + " " + attrs.get(“sn”).get()
except:
pass

i=0
boolEnd=0

while boolEnd==0:
controls = ctx.getResponseControls()
prrc = controls[i]
cookie = prrc.getCookie()

ctx.setRequestControls([PagedResultsControl(pageSize,cookie,Control.CRITICAL)])
results = ctx.search("dc=subdomain,dc=domain,dc=com","(&(objectCategory=person)(objectClass=user))",searchCtls)

if cookie!= None:

	while (results != "" and results.hasMoreElements()):
	
		entry = results.next() 
		attrs=entry.getAttributes()       
		try:
			print attrs.get("givenName").get() + " " + attrs.get("sn").get()
		except:
			pass
	
else:
	boolEnd=1

print “------------------------------------------------------”
ctx.close()
[/code]

I’m sure there is some exception handling I need to do and probably investigate SSL or TLS to avoid sending credentials in plain text. Anyway, thanks again for everyone’s help.

1 Like