Reputation: 842
According to all the documentation I've read, the maximum size of a result set when querying Active Directory is 1000 records. If you need more than 1000, you are told to use Net::LDAP::Control::Paged in order to page through and get more than 1000 records, which I have attempted to do. For some reason, I am still only getting 1000 records back, despite using a paged control. I am using the same code that others have claimed to be using successfully without any luck. Am I missing something here? Please note that I do not have administrative access to the AD servers, so changing the configuration is not an option for me. I've pasted the relevant code below so you can point out whatever I might have done wrong.
#!perl -w
use strict;
use Net::LDAP;
use Net::LDAP::Control::Paged;
use Net::LDAP::Constant qw( LDAP_CONTROL_PAGED );
my $LDAPServer = "<LDAP SERVER ADDRESS>";
my $base = "<BASE DN>";
my $user = "<LDAP USER>";
my $pass = "<PASSWORD>";
my $page = Net::LDAP::Control::Paged->new(size => 1000) or die $!;
my $errorConnectionStr = "";
my $ldap;
my $mesg;
my $cookie;
$ldap = Net::LDAP->new($LDAPServer);
$mesg = $ldap->bind($user, password => $pass, version => 3);
open(OUT,">users.csv");
print OUT "sAMAccountName,sn,givenName\n";
my $filter = "(&(objectClass=person)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(!(objectClass=computer)))";
my @attribs = ("sn", "givenName", "sAMAccountName", "distinguishedName");
my @args = (
base => $base,
scope => 'sub',
filter => $filter,
attrs => @attribs,
pagesize => 1000,
control => [$page]
);
while(1) {
$mesg = $ldap->search(@args) or die $!;
while (my $entry = $mesg->pop_entry()) {
my $print = 1;
my $dn = $entry->dn();
my $uid = $entry->get_value('sAMAccountName');
my $ln = $entry->get_value('sn');
my $fn = $entry->get_value('givenName');
if($dn =~ m/.*Resources.*/) {
$print = 0;
}
if(defined($uid) && defined($ln) && defined($fn)) {
if($print == 1) {
print OUT "$uid,$ln,$fn\n";
}
}
}
my ($resp) = $mesg->control(LDAP_CONTROL_PAGED) or last;
$cookie = $resp->cookie or last;
$page->cookie($cookie);
}
if($cookie) {
print "Abnormal exit\n";
$page->cookie($cookie);
$page->size(0);
$ldap->search(@args);
}
close(OUT);
$ldap->unbind;
Upvotes: 2
Views: 6175
Reputation: 1
You can't use a size of 1000 since it's the AD limit and hence doesn't page. Needs to be something less than that. Try 999 and be happy.
Upvotes: -2
Reputation: 2454
You need attrs => \@attrs,
in @args
. Without the backslash you're interpolating an odd number of elements ('attrs'
plus the four elements of the array) and the search method doesn't see the pagesize
argument.
Upvotes: 1
Reputation: 31
I just used it for the first time, and it works here. My seach is pretty simple (show all objects in a container). I'm listing 11.5k groups by grabbing them in 800-group pages. My code is nearly identical to yours (it's a mixture of the example on the Net::LDAP::Control::Paged man page and yours), except I don't specify a page size in the search:
while (1) {
my $mesg = $x->{ldap}->search(base => $x->{config}->{gbase},
scope => 'sub',
control => [$page],
filter => 'cn=*',
attrs => \@attrs,
);
die "LDAP error: server says ",$mesg->error,"\n" if $mesg->code;
foreach my $entry ( $mesg->entries ) {
my $cn = $entry->get_value('cn');
my $desc = $entry->get_value('description');
print "$cn - $desc\n";
}
# Get cookie from paged control
my($resp) = $mesg->control( LDAP_CONTROL_PAGED ) or last;
$cookie = $resp->cookie or last;
# Set cookie in paged control
$page->cookie($cookie);
}
Upvotes: 0