--- lib/A3C/LDAP/Server.pm 2008/06/26 20:46:33 222 +++ lib/A3C/LDAP/Server.pm 2008/06/26 21:57:33 223 @@ -2,13 +2,20 @@ use strict; use warnings; -use Data::Dumper; -use lib '../lib'; -use Net::LDAP::Constant qw(LDAP_SUCCESS); +use Net::LDAP::Constant qw( + LDAP_SUCCESS + LDAP_STRONG_AUTH_NOT_SUPPORTED + LDAP_UNAVAILABLE + LDAP_OPERATIONS_ERROR +); use Net::LDAP::Server; +use Net::LDAP::Filter; use base 'Net::LDAP::Server'; -use fields qw(); +use fields qw(upstream); + +use A3C::LDAP; +use Data::Dump qw/dump/; use constant RESULT_OK => { 'matchedDN' => '', @@ -26,25 +33,91 @@ # the bind operation sub bind { - my $self = shift; - my $reqData = shift; - print Dumper($reqData); + my ($self,$req) = @_; + + warn "## bind req = ",dump($req); + + defined($req->{authentication}->{simple}) or return { + matchedDN => '', + errorMessage => '', + resultCode => LDAP_STRONG_AUTH_NOT_SUPPORTED, + }; + + $self->{upstream} ||= A3C::LDAP->new->ldap or return { + matchedDN => '', + errorMessage => $@, + resultCode => LDAP_UNAVAILABLE, + }; + + warn "## upstream = ",dump( $self->{upstream} ); +# warn "upstream not Net::LDAP but ",ref($self->{upstream}) unless ref($self->{upstream}) eq 'Net::LDAP'; + return RESULT_OK; } # the search operation sub search { - my $self = shift; - my $reqData = shift; - print "Searching...\n"; - print Dumper($reqData); - my $base = $reqData->{'baseObject'}; - - my @entries; - if ($reqData->{'scope'}) { + my ($self,$req) = @_; + + warn "## search req = ",dump( $req ); + if ( ! $self->{upstream} ) { + warn "search without bind"; + return { + matchedDN => '', + errorMessage => 'dude, bind first', + resultCode => LDAP_OPERATIONS_ERROR, + }; } - warn ">> ",Dumper( @entries ); + + my $filter; + if (defined $req->{filter}) { + # $req->{filter} is a ASN1-decoded tree; luckily, this is exactly the + # internal representation Net::LDAP::Filter uses. [FIXME] Eventually + # Net::LDAP::Filter should provide a corresponding constructor. + bless($req->{filter}, 'Net::LDAP::Filter'); + $filter = $req->{filter}->as_string; +# $filter = '(&' . $req->{filter}->as_string +# . '(objectClass=hrEduPerson)(host=aai.irb.hr))'; + } + + warn "search upstream for $filter"; + + my $search = $self->{upstream}->search( + base => $req->{baseObject}, + scope => $req->{scope}, + deref => $req->{derefAliases}, + sizelimit => $req->{sizeLimit}, + timelimit => $req->{timeLimit}, + typesonly => $req->{typesOnly}, + filter => $filter, + attrs => $req->{attributes}, + raw => qr/.*/, + ); + + warn "# search = ",dump( $search ); + + if ( $search->code != LDAP_SUCCESS ) { + warn "ERROR: ",$search->code,": ",$search->server_error; + return { + matchedDN => '', + errorMessage => $search->server_error, + resultCode => $search->code, + }; + }; + + my @entries = $search->entries; + warn "## got ", $search->count, " entries for ", $filter; + foreach my $entry (@entries) { + $entry->changetype('add'); # Don't record changes. +# foreach my $attr ($entry->attributes) { +# if ($attr =~ /;lang-en$/) { +# $entry->delete($attr); +# } +# } + } + + warn "## entries = ",dump( @entries ); return RESULT_OK, @entries; }