Subject: | Error results if the search function returns a Net::LDAP::Reference objects |
The documentation for the user-supplied search function says that it should return an LDAPresult hashref followed by a list of entries coded either as searchResEntry or searchRefEntry structures or as Net::LDAP::Entry or Net::LDAP::Reference objects. When I do the latter an error is reported:
Not a HASH reference at /usr/local/share/perl5/Net/LDAP/Server.pm line 108.
The problem is in sub handle where it parses the list of entries returned from search. Having set $data to the 'asn' field of an entry, which is a hashref in the case of a Net::LDAP::Entry, but an array of URIs in the case of a Net::LDAP::Reference (see below) it then executes "if (defined $data->{'protocolOp'})", which is not a valid operation on an array.
The exact content of the Net::LDAP::Reference object is not well documented, but from comparing the ASN.1 definitions of searchResEntry and searchRefEntry in RFC 4511, and from some reverse engineering by dumping the content returned to a Perl test client from Net::LDAP for search entries and references, I can see that where a Net::LDAP::Entry contains a hashref with 'objectName' and 'attributes' fields, a Net::LDAP::Reference needs to contain an array of URIs. This is validated because an entry formatted as that works to get a reference returned to the client once I have fixed the above problem.
The following is the code in my search function that looks for reference objects read from a .ldif file and generates the Net::LDAP::Reference objects for them:
my $filter = Net::LDAP::Filter->new("(&(objectClass=referral)(ref=*))");
my $refs = _match( $filter, $list );
for (my $i = 0; $i <= $#{$refs}; $i++) {
my $attrs = $$refs[$i]->{asn}->{'attributes'};
for (my $j = 0; $j <= $#{$attrs}; $j++) {
if ($$attrs[$j]->{type} eq 'ref') {
my $ref_to = $$attrs[$j]->{vals}[0];
print STDERR "Found referral: $ref_to\n";
my $ref_entry = { 'asn' => [ $ref_to ] };
push(@{$res}, bless $ref_entry, 'Net::LDAP::Reference');
}
}
}
return ( _make_result(LDAP_SUCCESS), @{$res} );