Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Oh great ones, I have googled and googled, and I humbly stumble to your gates for help. Using Net::LDAP I am querying Active directory from UNIX, yet I only get back 1000 lines (I should get back ~3k). To make matters worse, when I query from windows, I get back my appropriate amount. First, UNIX:
my $page = Net::LDAP::Control::Paged->new( size => 10000 ); my $ldap = Net::LDAP->new("ad.host:389") or die "$@"; $ldap->bind('cn=user,ou=serviceAccts,cn=sub,dc=company,dc=com', passwo +rd=>'password'); my $mesg = $ldap->search(port=>389, scope=>'subtree', pagesize=>1000, filter=>"(&(objectclass=userProxy)(memberOf=c +n=My Group,ou=groups,cn=sub,dc=compnay,dc=com))", control=>[ $page ], base=>"CN=sub,DC=company,DC=com");
now the windows:
my $strFilter = "(memberOf=cn=GDTNA APP Cognos,ou=groups,cn=esso,dc=bs +ci,dc=com);"; my $strAttrs = "cn,distinguishedName;"; my $strScope = "subtree"; my $objConn = Win32::OLE->CreateObject("ADODB.Connection"); $objConn->{Provider} = "ADsDSOObject"; $objConn->Properties->{'User ID'} = 'cn=user,ou=serviceAccts,cn=sub, +dc=company,dc=com'; $objConn->Properties->{'Password'} = 'password'; $objConn->Open; my $commObj = Win32::OLE->new('ADODB.Command'); $commObj->{ActiveConnection} = $objConn; $commObj->Properties->{'Page Size'} = 1000; $query = $strBase . $strFilter . $strAttrs . $strScope; $commObj->{CommandText} = $query; my $objRS = $commObj->Execute($query);
Thanks awesome ones!

Replies are listed 'Best First'.
Re: ldap query only returning 1k lines
by kennethk (Abbot) on May 13, 2009 at 20:32 UTC
    I've never used Net::LDAP, but I can't help but notice that you are only getting 1k results and have set your pagesize to 1000 in your search parameters. I don't see a pagesize option in the documentation, but if it behaves like sizelimit and timelimit options, you should likely set it equal to 0 (no limit), omit it or perhaps the 10,000 you set in your Net::LDAP::Control::Paged constructor.
      No dice. Even if I remove that, replace with sizelimit and adjust from 100 to 10000 it still doesn't jive. Great idea though. I appreciate the try!
Re: ldap query only returning 1k lines
by NetWallah (Canon) on May 13, 2009 at 21:37 UTC
    Here is some code that worked for me, running on Windows, in an AD environment:
    # lists all users in an Everyone OU #This logs in to LDAP and generates a CSV file with each members displ +ay name and then a list of their groups. use strict; use Net::LDAP; use Net::LDAP::Control::Paged; use Net::LDAP::Constant ( "LDAP_CONTROL_PAGED" ); my $ldap = Net::LDAP->new('your.domaincontroller.com') or die "Could n +ot connect to Domain controller $@"; # params for Net::LDAP::new # bind to a directory with dn and password my $mesg = $ldap->bind( 'ldapreadonlyUsername', password => 'LDAPRead0nlyPassword' ); die $mesg->error if $mesg->code; # How many LDAP query results to grab for each paged round # Set to under 1000 for Active Directory my $page = Net::LDAP::Control::Paged->new( size => 100 ); my $fields = ['displayName','memberOf','useraccountcontrol']; my $strFilter = "(&(objectclass=user)(objectcategory=person)" # A + User # . "(!useraccountcontrol:1.2.840.113556.1.4.803:=2)" # + NOT Disabled . "(useraccountcontrol:dn:1.2.840.113556.1.4.803:=2)" +#The 1.2.840.113556.1.4.803 is a logical AND. . ")"; my $result = $ldap->search ( base => "dc=CompanyDomainName,dc=com", filter => $strFilter, attrs => $fields, control => [ $page ], ); die $result->error if $result->code; for my $item ( $result->entries) { next unless defined $item->get_value("displayName"); my $user; $user->{groups} = [ ref ( $item->get_value('memberOf') ) ? @{$item->get_value('memberOf')} : ($item->get_value('memberOf')) ]; $user->{groups} = [ map { /CN=(.+?),/ ; $1 } @{$user->{groups}} ]; print '"',$item->get_value("displayName"),'",'; print join(",", map { '"' . $_ . '"' } sort @{$user->{groups}} +),"\n"; } # Get cookie from paged control my($resp) = $mesg->control( LDAP_CONTROL_PAGED ) or print "-- No mo +re data (1) --\n"; ## last; my $cookie = $resp->cookie or print "-- No more data (2) --\n"; # Sh +ould do LAST here.. # Set cookie in paged control $page->cookie($cookie);

         ..to maintain is to slowly feel your soul, sanity and sentience ebb away as you become one with the Evil.

      I think this is getting closer. When I see you're line:
      # How many LDAP query results to grab for each paged round # Set to under 1000 for Active Directory my $page = Net::LDAP::Control::Paged->new( size => 100 );
      I see you are set to 100. If I set mine to 100, I only get 100 entries. If I set mine to 1000, I get 1000 lines. If I set it any higher than 1000, I still only get 1000 entries. Does that ring any bells for anyone or jive?
        From http://support.microsoft.com/kb/315071, You can use NTDSUTIL to define policy/ parameters:

        MaxPageSize - This value controls the maximum number of objects that are returned in a single search result, independent of how large each returned object is. To perform a search where the result might exceed this number of objects, the client must specify the paged search control. This is to group the returned results in groups that are no larger than the MaxPageSize value. To summarize, MaxPageSize controls the number of objects that are returned in a single search result.

        Default value: 1,000

             ..to maintain is to slowly feel your soul, sanity and sentience ebb away as you become one with the Evil.