From: Andrej Ricnik-Bay, _V-IT-Systemhaus-Perl-LDAP von extern
Hi *,
running this script from a Linux machine against our Active Directory
---------------------------< schnipp schnapp >--------------------------
#!/usr/bin/perl
use Net::LDAPS;
$ldap = Net::LDAP->new(
'ldaps://<my_dc>:636',
timeout => 1000,
verify => 'require',
capath => '/etc/ssl/certs/',
) || die "cant make initial connection: $@";
$result - $ldap->bind(
'<my_dn>',
password => '<my_pass>',
) || die $!;
$ldap->unbind();
exit;
---------------------------< schnipp schnapp >--------------------------
gives the following result:
cant make initial connection: IO::Socket::SSL: Timeout at ./x line 4,
<DATA> line 253.
Any idea, why this might happen?
The same script from any Windows box in here works as expected.
versions:
- Novell SLES 10 (x86_64)
- Net::LDAP 0.36
- Net::SSLeay 1.32
- openssl 0.9.8a-18.23
TIA.
Bye.
Michael.
From: Mathieu PARENT
Hi,
This patch implements Intermediate Message and RFC 4533.
Notes:
- The only intrusive change is in lib/Net/LDAP/Search.pm
- Net::LDAP::Intermediate::SyncInfo is not enabled by default (see
lib/Net/LDAP/Intermediate.pm line 18) as there are decoding errors
within ASN (see my previous mail).
Waiting for feedback before (I hope) inclusion.
Regards
Mathieu Parent
---
MANIFEST | 5 +
lib/Net/LDAP/ASN.pm | 52 +++++++-
lib/Net/LDAP/Constant.pm | 46 ++++++-
lib/Net/LDAP/Control.pm | 15 ++-
lib/Net/LDAP/Control/SyncDone.pm | 152 +++++++++++++++++++++
lib/Net/LDAP/Control/SyncRequest.pm | 165 +++++++++++++++++++++++
lib/Net/LDAP/Control/SyncState.pm | 165 +++++++++++++++++++++++
lib/Net/LDAP/Intermediate.pm | 236 +++++++++++++++++++++++++++++++++
lib/Net/LDAP/Intermediate/SyncInfo.pm | 140 +++++++++++++++++++
lib/Net/LDAP/Search.pm | 14 ++-
10 files changed, 986 insertions(+), 4 deletions(-)
create mode 100644 lib/Net/LDAP/Control/SyncDone.pm
create mode 100644 lib/Net/LDAP/Control/SyncRequest.pm
create mode 100644 lib/Net/LDAP/Control/SyncState.pm
create mode 100644 lib/Net/LDAP/Intermediate.pm
create mode 100644 lib/Net/LDAP/Intermediate/SyncInfo.pm
diff --git a/MANIFEST b/MANIFEST
index 185ce57..161f716 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -60,6 +60,9 @@ lib/Net/LDAP/Control/PreRead.pm
lib/Net/LDAP/Control/ProxyAuth.pm
lib/Net/LDAP/Control/Sort.pm
lib/Net/LDAP/Control/SortResult.pm
+lib/Net/LDAP/Control/SyncDone.pm
+lib/Net/LDAP/Control/SyncRequest.pm
+lib/Net/LDAP/Control/SyncState.pm
lib/Net/LDAP/Control/VLV.pm
lib/Net/LDAP/Control/VLVResponse.pm
lib/Net/LDAP/DSML.pm
@@ -74,6 +77,8 @@ lib/Net/LDAP/FAQ.pod
lib/Net/LDAP/Filter.pm
lib/Net/LDAP/Filter.pod
lib/Net/LDAP/FilterMatch.pm
+lib/Net/LDAP/Intermediate.pm
+lib/Net/LDAP/Intermediate/SyncInfo.pm
lib/Net/LDAP/LDIF.pm
lib/Net/LDAP/LDIF.pod
lib/Net/LDAP/Message.pm
diff --git a/lib/Net/LDAP/ASN.pm b/lib/Net/LDAP/ASN.pm
index f894c13..82b7c17 100644
--- a/lib/Net/LDAP/ASN.pm
+++ b/lib/Net/LDAP/ASN.pm
@@ -1,7 +1,7 @@
package Net::LDAP::ASN;
-$VERSION = "0.06";
+$VERSION = "0.07";
use Convert::ASN1;
@@ -441,6 +441,56 @@ $asn->prepare(<<LDAP_ASN) or die $asn->error;
objectName LDAPDN,
attributes PartialAttributeList }
+ -- RFC-4533 LDAP Content Synchronization Operation
+
+ syncUUID ::= OCTET STRING -- (SIZE(16))
+
+ syncCookie ::= OCTET STRING
+
+ syncRequestValue ::= SEQUENCE {
+ mode ENUMERATED {
+ -- 0 unused
+ refreshOnly (1),
+ -- 2 reserved
+ refreshAndPersist (3)
+ }
+ cookie syncCookie OPTIONAL,
+ reloadHint BOOLEAN -- DEFAULT FALSE
+ }
+
+ syncStateValue ::= SEQUENCE {
+ state ENUMERATED {
+ present (0),
+ add (1),
+ modify (2),
+ delete (3)
+ }
+ entryUUID syncUUID,
+ cookie syncCookie OPTIONAL
+ }
+
+ syncDoneValue ::= SEQUENCE {
+ cookie syncCookie OPTIONAL,
+ refreshDeletes BOOLEAN -- DEFAULT FALSE
+ }
+
+ syncInfoValue ::= CHOICE {
+ newcookie [0] syncCookie,
+ refreshDelete [1] SEQUENCE {
+ refreshDeleteCookie syncCookie OPTIONAL,
+ refreshDeleteDone BOOLEAN -- DEFAULT TRUE
+ }
+ refreshPresent [2] SEQUENCE {
+ refreshDeletecookie syncCookie OPTIONAL,
+ refreshDeleteDone BOOLEAN -- DEFAULT TRUE
+ }
+ syncIdSet [3] SEQUENCE {
+ cookie syncCookie OPTIONAL,
+ refreshDeletes BOOLEAN, -- DEFAULT FALSE
+ syncUUIDs SET OF syncUUID
+ }
+ }
+
LDAP_ASN
1;
diff --git a/lib/Net/LDAP/Constant.pm b/lib/Net/LDAP/Constant.pm
index 6d84ab6..a9bebe9 100644
--- a/lib/Net/LDAP/Constant.pm
+++ b/lib/Net/LDAP/Constant.pm
@@ -4,7 +4,7 @@
package Net::LDAP::Constant;
-$VERSION = "0.06";
+$VERSION = "0.07";
use Carp;
@@ -481,6 +481,14 @@ The referral hop limit has been exceeded.
=item LDAP_CONTROL_ASSERTION (1.3.6.1.1.12)
+=item LDAP_CONTROL_SYNC (1.3.6.1.4.1.4203.1.9.1.1)
+
+=item LDAP_CONTROL_SYNC_STATE (1.3.6.1.4.1.4203.1.9.1.2)
+
+=item LDAP_CONTROL_SYNC_DONE (1.3.6.1.4.1.4203.1.9.1.3)
+
+=item LDAP_SYNC_INFO (1.3.6.1.4.1.4203.1.9.1.4)
+
=back
=head2 Control constants
@@ -523,6 +531,42 @@ The previous password was changed too recently.
The new password was used too recently.
+=item LDAP_SYNC_NONE (0) [LDAP_CONTROL_SYNC]
+
+=item LDAP_SYNC_REFRESH_ONLY (1) [LDAP_CONTROL_SYNC]
+
+=item LDAP_SYNC_RESERVED (2) [LDAP_CONTROL_SYNC]
+
+=item LDAP_SYNC_REFRESH_AND_PERSIST (3) [LDAP_CONTROL_SYNC]
+
+=item LDAP_SYNC_REFRESH_PRESENTS (0) [LDAP_SYNC_INFO]
+
+=item LDAP_SYNC_REFRESH_DELETES (1) [LDAP_SYNC_INFO]
+
+=item LDAP_TAG_SYNC_NEW_COOKIE (0x80) [LDAP_SYNC_INFO]
+
+=item LDAP_TAG_SYNC_REFRESH_DELETE (0xa1) [LDAP_SYNC_INFO]
+
+=item LDAP_TAG_SYNC_REFRESH_PRESENT (0xa2) [LDAP_SYNC_INFO]
+
+=item LDAP_TAG_SYNC_ID_SET (0xa3) [LDAP_SYNC_INFO]
+
+=item LDAP_TAG_SYNC_COOKIE (0x04) [LDAP_SYNC_INFO]
+
+=item LDAP_TAG_REFRESHDELETES (0x01) [LDAP_SYNC_INFO]
+
+=item LDAP_TAG_REFRESHDONE (0x01) [LDAP_SYNC_INFO]
+
+=item LDAP_TAG_RELOAD_HINT (0x01) [LDAP_CONTROL_SYNC]
+
+=item LDAP_SYNC_PRESENT (0) [LDAP_CONTROL_SYNC_STATE]
+
+=item LDAP_SYNC_ADD (1) [LDAP_CONTROL_SYNC_STATE]
+
+=item LDAP_SYNC_MODIFY (2) [LDAP_CONTROL_SYNC_STATE]
+
+=item LDAP_SYNC_DELETE (3) [LDAP_CONTROL_SYNC_STATE]
+
=back
=head2 Extension OIDs
diff --git a/lib/Net/LDAP/Control.pm b/lib/Net/LDAP/Control.pm
index 0cbbbef..c3b36e8 100644
--- a/lib/Net/LDAP/Control.pm
+++ b/lib/Net/LDAP/Control.pm
@@ -21,9 +21,12 @@ use Net::LDAP::Constant qw(
LDAP_CONTROL_PASSWORDPOLICY
LDAP_CONTROL_PREREAD
LDAP_CONTROL_POSTREAD
+ LDAP_CONTROL_SYNC
+ LDAP_CONTROL_SYNC_STATE
+ LDAP_CONTROL_SYNC_DONE
);
-$VERSION = "0.08";
+$VERSION = "0.09";
my %Pkg2Type = (
@@ -49,6 +52,10 @@ my %Pkg2Type = (
'Net::LDAP::Control::PreRead' => LDAP_CONTROL_PREREAD,
'Net::LDAP::Control::PostRead' => LDAP_CONTROL_POSTREAD,
+
+ 'Net::LDAP::Control::SyncRequest' => LDAP_CONTROL_SYNC,
+ 'Net::LDAP::Control::SyncState' => LDAP_CONTROL_SYNC_STATE,
+ 'Net::LDAP::Control::SyncDone' => LDAP_CONTROL_SYNC_DONE,
#
#LDAP_CONTROL_PWEXPIRED
#LDAP_CONTROL_PWEXPIRING
@@ -294,10 +301,16 @@ L<Net::LDAP>
L<Net::LDAP::Control::EntryChange>
L<Net::LDAP::Control::ManageDsaIT>
L<Net::LDAP::Control::Paged>
+L<Net::LDAP::Control::PasswordPolicy>
L<Net::LDAP::Control::PersistentSearch>
+L<Net::LDAP::Control::PostRead>
+L<Net::LDAP::Control::PreRead>
L<Net::LDAP::Control::ProxyAuth>
L<Net::LDAP::Control::Sort>
L<Net::LDAP::Control::SortResult>
+L<Net::LDAP::Control::SyncDone>
+L<Net::LDAP::Control::SyncRequest>
+L<Net::LDAP::Control::SyncState>
L<Net::LDAP::Control::VLV>
L<Net::LDAP::Control::VLVResponse>
diff --git a/lib/Net/LDAP/Control/SyncDone.pm b/lib/Net/LDAP/Control/SyncDone.pm
new file mode 100644
index 0000000..7fcb0d9
--- /dev/null
+++ b/lib/Net/LDAP/Control/SyncDone.pm
@@ -0,0 +1,152 @@
+# Copyright (c) 2008 Mathieu Parent <math.parent@gmail.com>. All
rights reserved.
+# This program is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+
+package Net::LDAP::Control::SyncDone;
+
+use vars qw(@ISA $VERSION);
+use Net::LDAP::Control;
+
+@ISA = qw(Net::LDAP::Control);
+$VERSION = "0.01";
+
+use Net::LDAP::ASN qw(syncDoneValue);
+use strict;
+
+# use some kind of hack here:
+# - calling the control without args means: response,
+# - giving an argument: means: request
+sub init {
+ my($self) = @_;
+
+ delete $self->{asn};
+
+ unless (exists $self->{value}) {
+ $self->{asn} = {
+ cookie => $self->{cookie} || '',
+ refreshDeletes => $self->{refreshDeletes} || '0',
+ };
+ }
+
+ $self;
+}
+
+sub cookie {
+ my $self = shift;
+ $self->{asn} ||= $syncDoneValue->decode($self->{value});
+ if (@_) {
+ delete $self->{value};
+ return $self->{asn}{cookie} = shift || 0;
+ }
+ $self->{asn}{cookie};
+}
+
+sub refreshDeletes {
+ my $self = shift;
+ $self->{asn} ||= $syncDoneValue->decode($self->{value});
+ if (@_) {
+ delete $self->{value};
+ return $self->{asn}{refreshDeletes} = shift || 0;
+ }
+ $self->{asn}{refreshDeletes};
+}
+
+sub value {
+ my $self = shift;
+
+ exists $self->{value}
+ ? $self->{value}
+ : $self->{value} = $syncDoneValue->encode($self->{asn});
+}
+
+1;
+
+
+__END__
+
+=head1 NAME
+
+Net::LDAP::Control::SyncDone - LDAPv3 Sync Done control object
+
+=head1 SYNOPSIS
+
+ use Net::LDAP;
+ use Net::LDAP::Control::SyncRequest;
+ use Net::LDAP::Constant qw(
+ LDAP_SYNC_REFRESH_ONLY
+ LDAP_SYNC_REFRESH_AND_PERSIST
+ LDAP_SUCCESS );
+
+ $ldap = Net::LDAP->new( "ldap.mydomain.eg" );
+
+ $req = Net::LDAP::Control::SyncRequest->new( mode => LDAP_SYNC_REFRESH_ONLY );
+ my $mesg = $ldap->search(base=> 'dc=mydomain,dc='eg',
+ scope => 'sub',
+ control => [ $req ],
+ callback => \&searchCallback, # call for each entry
+ filter => "(objectClass=*)",
+ attrs => [ '*']);
+ sub searchCallback {
+ my $message = shift;
+ my $entry = shift;
+ my @controls = $message->control;
+
+ if($controls[0]->isa('Net::LDAP::Control::SyncState')) {
+ print "Received Sync State Control\n";
+ print $entry->dn()."\n";
+ print 'State: '.$controls[0]->state."\n".', entryUUID:
'.$controls[0]->entryUUID.', cookie: '.$controls[0]->cookie;
+ } elsif($controls[0]->isa('Net::LDAP::Control::SyncDone')) {
+ print "Received Sync Done Control\n";
+ print 'Cookie: '.$controls[0]->cookie.', refreshDeletes:
'.$controls[0]->refreshDeletes;
+ }
+ }
+
+=head1 DESCRIPTION
+
+C<Net::LDAP::Control::SyncDone> provides an interface for the creation and
+manipulation of objects that represent the C<Sync Request Control> as described
+by RFC 4533.
+
+=head1 CONSTRUCTOR ARGUMENTS
+
+In addition to the constructor arguments described in
+L<Net::LDAP::Control> the following are provided.
+
+=over 4
+
+=item cookie
+
+=item refreshDeletes
+
+=back
+
+=head1 METHODS
+
+As with L<Net::LDAP::Control> each constructor argument
+described above is also avaliable as a method on the object which will
+return the current value for the attribute if called without an argument,
+and set a new value for the attribute if called with an argument.
+
+=head1 SEE ALSO
+
+L<Net::LDAP>,
+L<Net::LDAP::Control>,
+L<Net::LDAP::Control::SyncRequest>,
+L<Net::LDAP::Control::SyncState>,
+http://www.ietf.org/rfc/rfc4533.txt
+
+=head1 AUTHOR
+
+Mathieu Parent E<lt>math.parent@gmail.comE<gt>
+
+Please report any bugs, or post any suggestions, to the perl-ldap mailing list
+E<lt>perl-ldap@perl.orgE<gt>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2008 Mathieu Parent. All rights reserved. This program is
+free software; you can redistribute it and/or modify it under the same
+terms as Perl itself.
+
+=cut
+
diff --git a/lib/Net/LDAP/Control/SyncRequest.pm
b/lib/Net/LDAP/Control/SyncRequest.pm
new file mode 100644
index 0000000..b33868d
--- /dev/null
+++ b/lib/Net/LDAP/Control/SyncRequest.pm
@@ -0,0 +1,165 @@
+# Copyright (c) 2008 Mathieu Parent <math.parent@gmail.com>. All
rights reserved.
+# This program is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+
+package Net::LDAP::Control::SyncRequest;
+
+use vars qw(@ISA $VERSION);
+use Net::LDAP::Control;
+
+@ISA = qw(Net::LDAP::Control);
+$VERSION = "0.01";
+
+use Net::LDAP::ASN qw(syncRequestValue);
+use strict;
+
+# use some kind of hack here:
+# - calling the control without args means: response,
+# - giving an argument: means: request
+sub init {
+ my($self) = @_;
+
+ delete $self->{asn};
+
+ unless (exists $self->{value}) {
+ $self->{asn} = {
+ mode => $self->{mode} || '1',
+ cookie => $self->{cookie} || '',
+ reloadHint => $self->{reloadHint} || '0',
+ };
+ }
+
+ $self;
+}
+
+sub mode {
+ my $self = shift;
+ $self->{asn} ||= $syncRequestValue->decode($self->{value});
+ if (@_) {
+ delete $self->{value};
+ return $self->{asn}{mode} = shift || 0;
+ }
+ $self->{asn}{mode};
+}
+
+sub cookie {
+ my $self = shift;
+ $self->{asn} ||= $syncRequestValue->decode($self->{value});
+ if (@_) {
+ delete $self->{value};
+ return $self->{asn}{cookie} = shift || 0;
+ }
+ $self->{asn}{cookie};
+}
+
+sub reloadHint {
+ my $self = shift;
+ $self->{asn} ||= $syncRequestValue->decode($self->{value});
+ if (@_) {
+ delete $self->{value};
+ return $self->{asn}{reloadHint} = shift || 0;
+ }
+ $self->{asn}{reloadHint};
+}
+
+sub value {
+ my $self = shift;
+
+ exists $self->{value}
+ ? $self->{value}
+ : $self->{value} = $syncRequestValue->encode($self->{asn});
+}
+
+1;
+
+
+__END__
+
+=head1 NAME
+
+Net::LDAP::Control::SyncRequest - LDAPv3 Sync Request control object
+
+=head1 SYNOPSIS
+
+ use Net::LDAP;
+ use Net::LDAP::Control::SyncRequest;
+ use Net::LDAP::Constant qw(
+ LDAP_SYNC_REFRESH_ONLY
+ LDAP_SYNC_REFRESH_AND_PERSIST
+ LDAP_SUCCESS );
+
+ $ldap = Net::LDAP->new( "ldap.mydomain.eg" );
+
+ $req = Net::LDAP::Control::SyncRequest->new( mode => LDAP_SYNC_REFRESH_ONLY );
+ my $mesg = $ldap->search(base=> 'dc=mydomain,dc='eg',
+ scope => 'sub',
+ control => [ $req ],
+ callback => \&searchCallback, # call for each entry
+ filter => "(objectClass=*)",
+ attrs => [ '*']);
+ sub searchCallback {
+ my $message = shift;
+ my $entry = shift;
+ my @controls = $message->control;
+
+ if($controls[0]->isa('Net::LDAP::Control::SyncState')) {
+ print "Received Sync State Control\n";
+ print $entry->dn()."\n";
+ print 'State: '.$controls[0]->state."\n".', entryUUID:
'.$controls[0]->entryUUID.', cookie: '.$controls[0]->cookie;
+ } elsif($controls[0]->isa('Net::LDAP::Control::SyncDone')) {
+ print "Received Sync Done Control\n";
+ print 'Cookie: '.$controls[0]->cookie.', refreshDeletes:
'.$controls[0]->refreshDeletes;
+ }
+ }
+
+=head1 DESCRIPTION
+
+C<Net::LDAP::Control::SyncRequest> provides an interface for the creation and
+manipulation of objects that represent the C<Sync Request Control> as described
+by RFC 4533.
+
+=head1 CONSTRUCTOR ARGUMENTS
+
+In addition to the constructor arguments described in
+L<Net::LDAP::Control> the following are provided.
+
+=over 4
+
+=item mode
+
+=item cookie
+
+=item reloadHint
+
+=back
+
+=head1 METHODS
+
+As with L<Net::LDAP::Control> each constructor argument
+described above is also avaliable as a method on the object which will
+return the current value for the attribute if called without an argument,
+and set a new value for the attribute if called with an argument.
+
+=head1 SEE ALSO
+
+L<Net::LDAP>,
+L<Net::LDAP::Control>,
+L<Net::LDAP::Control::SyncState>,
+L<Net::LDAP::Control::SyncDone>,
+http://www.ietf.org/rfc/rfc4533.txt
+
+=head1 AUTHOR
+
+Mathieu Parent E<lt>math.parent@gmail.comE<gt>
+
+Please report any bugs, or post any suggestions, to the perl-ldap mailing list
+E<lt>perl-ldap@perl.orgE<gt>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2008 Mathieu Parent. All rights reserved. This program is
+free software; you can redistribute it and/or modify it under the same
+terms as Perl itself.
+
+=cut
+
diff --git a/lib/Net/LDAP/Control/SyncState.pm
b/lib/Net/LDAP/Control/SyncState.pm
new file mode 100644
index 0000000..b069e42
--- /dev/null
+++ b/lib/Net/LDAP/Control/SyncState.pm
@@ -0,0 +1,165 @@
+# Copyright (c) 2008 Mathieu Parent <math.parent@gmail.com>. All
rights reserved.
+# This program is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+
+package Net::LDAP::Control::SyncState;
+
+use vars qw(@ISA $VERSION);
+use Net::LDAP::Control;
+
+@ISA = qw(Net::LDAP::Control);
+$VERSION = "0.01";
+
+use Net::LDAP::ASN qw(syncStateValue);
+use strict;
+
+# use some kind of hack here:
+# - calling the control without args means: response,
+# - giving an argument: means: request
+sub init {
+ my($self) = @_;
+
+ delete $self->{asn};
+
+ unless (exists $self->{value}) {
+ $self->{asn} = {
+ state => $self->{state} || '',
+ entryUUID => $self->{entryUUID} || '',
+ cookie => $self->{cookie} || '',
+ };
+ }
+
+ $self;
+}
+
+sub state {
+ my $self = shift;
+ $self->{asn} ||= $syncStateValue->decode($self->{value});
+ if (@_) {
+ delete $self->{value};
+ return $self->{asn}{state} = shift || 0;
+ }
+ $self->{asn}{state};
+}
+
+sub entryUUID {
+ my $self = shift;
+ $self->{asn} ||= $syncStateValue->decode($self->{value});
+ if (@_) {
+ delete $self->{value};
+ return $self->{asn}{entryUUID} = shift || 0;
+ }
+ $self->{asn}{entryUUID};
+}
+
+sub cookie {
+ my $self = shift;
+ $self->{asn} ||= $syncStateValue->decode($self->{value});
+ if (@_) {
+ delete $self->{value};
+ return $self->{asn}{cookie} = shift || 0;
+ }
+ $self->{asn}{cookie};
+}
+
+sub value {
+ my $self = shift;
+
+ exists $self->{value}
+ ? $self->{value}
+ : $self->{value} = $syncStateValue->encode($self->{asn});
+}
+
+1;
+
+
+__END__
+
+=head1 NAME
+
+Net::LDAP::Control::SyncState - LDAPv3 Sync State control object
+
+=head1 SYNOPSIS
+
+ use Net::LDAP;
+ use Net::LDAP::Control::SyncRequest;
+ use Net::LDAP::Constant qw(
+ LDAP_SYNC_REFRESH_ONLY
+ LDAP_SYNC_REFRESH_AND_PERSIST
+ LDAP_SUCCESS );
+
+ $ldap = Net::LDAP->new( "ldap.mydomain.eg" );
+
+ $req = Net::LDAP::Control::SyncRequest->new( mode => LDAP_SYNC_REFRESH_ONLY );
+ my $mesg = $ldap->search(base=> 'dc=mydomain,dc='eg',
+ scope => 'sub',
+ control => [ $req ],
+ callback => \&searchCallback, # call for each entry
+ filter => "(objectClass=*)",
+ attrs => [ '*']);
+ sub searchCallback {
+ my $message = shift;
+ my $entry = shift;
+ my @controls = $message->control;
+
+ if($controls[0]->isa('Net::LDAP::Control::SyncState')) {
+ print "Received Sync State Control\n";
+ print $entry->dn()."\n";
+ print 'State: '.$controls[0]->state."\n".', entryUUID:
'.$controls[0]->entryUUID.', cookie: '.$controls[0]->cookie;
+ } elsif($controls[0]->isa('Net::LDAP::Control::SyncDone')) {
+ print "Received Sync Done Control\n";
+ print 'Cookie: '.$controls[0]->cookie.', refreshDeletes:
'.$controls[0]->refreshDeletes;
+ }
+ }
+
+=head1 DESCRIPTION
+
+C<Net::LDAP::Control::SyncState> provides an interface for the creation and
+manipulation of objects that represent the C<Sync State Control> as described
+by RFC 4533.
+
+=head1 CONSTRUCTOR ARGUMENTS
+
+In addition to the constructor arguments described in
+L<Net::LDAP::Control> the following are provided.
+
+=over 4
+
+=item state
+
+=item entryUIID
+
+=item cookie
+
+=back
+
+=head1 METHODS
+
+As with L<Net::LDAP::Control> each constructor argument
+described above is also avaliable as a method on the object which will
+return the current value for the attribute if called without an argument,
+and set a new value for the attribute if called with an argument.
+
+=head1 SEE ALSO
+
+L<Net::LDAP>,
+L<Net::LDAP::Control>,
+L<Net::LDAP::Control::SyncRequest>,
+L<Net::LDAP::Control::SyncDone>,
+http://www.ietf.org/rfc/rfc4533.txt
+
+=head1 AUTHOR
+
+Mathieu Parent E<lt>math.parent@gmail.comE<gt>
+
+Please report any bugs, or post any suggestions, to the perl-ldap mailing list
+E<lt>perl-ldap@perl.orgE<gt>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2008 Mathieu Parent. All rights reserved. This program is
+free software; you can redistribute it and/or modify it under the same
+terms as Perl itself.
+
+=cut
+
diff --git a/lib/Net/LDAP/Intermediate.pm b/lib/Net/LDAP/Intermediate.pm
new file mode 100644
index 0000000..b95b849
--- /dev/null
+++ b/lib/Net/LDAP/Intermediate.pm
@@ -0,0 +1,236 @@
+# Copyright (c) 2008 Mathieu Parent <math.parent@gmail.com>. All
rights reserved.
+# This program is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+
+package Net::LDAP::Intermediate;
+
+use vars qw($VERSION);
+use strict;
+
+use Net::LDAP::Constant qw(
+ LDAP_SYNC_INFO
+);
+
+$VERSION = "0.01";
+
+my %Class2ResponseName = (
+
+ #'Net::LDAP::Intermediate::SyncInfo' => LDAP_SYNC_INFO, #disabled
as decoding doesn't work
+);
+
+my %ResponseName2Class = reverse %Class2ResponseName;
+
+sub register {
+ my($class,$responseName) = @_;
+
+ require Carp and Carp::croak("$responseName is already registered
to $ResponseName2Class{$responseName}")
+ if exists $ResponseName2Class{$responseName} and
$ResponseName2Class{$responseName} ne $class;
+
+ require Carp and Carp::croak("$class is already registered to
$Class2ResponseName{$class}")
+ if exists $Class2ResponseName{$class} and
$Class2ResponseName{$class} ne $responseName;
+
+ $ResponseName2Class{$responseName} = $class;
+ $Class2ResponseName{$class} = $responseName;
+}
+
+sub new {
+ my $self = shift;
+ my $class = ref($self) || $self;
+ my $responseName = (@_ & 1) ? shift : undef;
+ my %args = @_;
+
+ $args{'responseName'} ||= $responseName || $Class2ResponseName{$class} || '';
+
+ unless ($args{responseName} =~ /^\d+(?:\.\d+)+$/) {
+ $args{error} = 'Invalid responseName';
+ return bless \%args;
+ }
+
+ if ($class eq __PACKAGE__ and exists
$ResponseName2Class{$args{responseName}}) {
+ $class = $ResponseName2Class{$args{responseName}};
+ eval "require $class" or die $@;
+ }
+
+ delete $args{error};
+
+ bless(\%args, $class)->init;
+}
+
+
+sub from_asn {
+ my $self = shift;
+ my $asn = shift;
+ my $class = ref($self) || $self;
+
+ if ($class eq __PACKAGE__ and exists
$ResponseName2Class{$asn->{responseName}}) {
+ $class = $ResponseName2Class{$asn->{responseName}};
+ eval "require $class" or die $@;
+ }
+
+ delete $asn->{error};
+
+ bless($asn, $class)->init;
+}
+
+sub to_asn {
+ my $self = shift;
+ $self->responseValue; # Ensure value is there
+ $self;
+}
+
+sub responseName { shift->{responseName} }
+
+sub responseValue {
+ my $self = shift;
+ $self->{responseValue} = shift if @_;
+ $self->{responseValue} || undef
+}
+
+sub valid { ! exists shift->{error} }
+sub error { shift->{error} }
+sub init { shift }
+
+1;
+
+__END__
+
+
+=head1 NAME
+
+Net::LDAP::Intermediate - LDAPv3 intermediate response object base class
+
+=head1 SYNOPSIS
+
+ use Net::LDAP::Intermediate;
+
+=head1 DESCRIPTION
+
+C<Net::LDAP::Intermediate> is a base-class for LDAPv3 intermediate
response objects.
+
+=cut
+
+##
+## Need more blurb in here about intermediate responses
+##
+
+=head1 CONSTRUCTORS
+
+=over 4
+
+=item new ( ARGS )
+
+ARGS is a list of name/value pairs, valid arguments are:
+
+=over 4
+
+=item responseName
+
+A dotted-decimal representation of an OBJECT IDENTIFIER which
+uniquely identifies the intermediate response. This prevents conflicts between
+intermediate response names.
+
+=item responseValue
+
+Optional information associated with the intermediate response. It's
format is specific
+to the particular intermediate response.
+
+=back
+
+=item from_asn ( ASN )
+
+ASN is a HASH reference, normally extracted from a PDU. It will contain
+a C<responseName> element and optionally C<responseValue> element. On
+return ASN will be blessed into a package. If C<responseName> is a registered
+OID, then ASN will be blessed into the registered package, if not then ASN
+will be blessed into Net::LDAP::Intermediate.
+
+This constructor is used internally by Net::LDAP and assumes that HASH
+passed contains a valid intermediate response. It should be used with
B<caution>.
+
+=back
+
+=head1 METHODS
+
+In addition to the methods listed below, each of the named parameters
+to C<new> is also avaliable as a method. C<responseName> will return the OID of
+the intermediate response object. C<responseValue> is set/get methods and will
+return the current value for each attribute if called without arguments,
+but may also be called with arguments to set new values.
+
+=over 4
+
+=item error ()
+
+If there has been an error returns a description of the error,
otherwise it will
+return C<undef>
+
+=item init ()
+
+C<init> will be called as the last step in both contructors. What it
does will depend
+on the sub-class. It must always return the object.
+
+=item register ( OID )
+
+C<register> is provided for sub-class implementors. It should be
called as a class method
+on a sub-class of Net::LDAP::Intermediate with the OID that the class
will handle. Net::LDAP::Intermediate
+will remember this class and OID pair and use it in the following
+situations.
+
+=over 4
+
+=item *
+
+C<new> is called as a class method on the Net::LDAP::Intermediate
package and OID is passed
+as the responseName. The returned object will be blessed into the
package that registered
+the OID.
+
+=item *
+
+C<new> is called as a class method on a registered package and the
C<responseName> is not
+specified. The C<responseName> will be set to the OID registered by
that package.
+
+=item *
+
+C<from_asn> is called to construct an object from ASN. The returned
object will be
+blessed into the package which was registered to handle the OID in the ASN.
+
+=back
+
+=item ( to_asn )
+
+Returns a structure suitable for passing to Convert::ASN1 for
+encoding. This method will be called by L<Net::LDAP> when the
+intermediate response is used.
+
+The base class implementation of this method will call the
C<responseValue> method
+without arguments to allow a sub-class to encode it's value. Sub-classes
+should not need to override this method.
+
+=item valid ()
+
+Returns true if the object is valid and can be encoded. The default
implementation
+for this method is to return TRUE if there is no error, but
sub-classes may override that.
+
+=back
+
+=head1 SEE ALSO
+
+L<Net::LDAP>
+L<Net::LDAP::Extension>
+L<Net::LDAP::Search>
+L<Net::LDAP::Intermediate::SyncInfo>
+
+=head1 AUTHOR
+
+Mathieu Parent E<lt>math.parent@gmail.comE<gt>
+
+Please report any bugs, or post any suggestions, to the perl-ldap mailing list
+E<lt>perl-ldap@perl.orgE<gt>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2008 Mathieu Parent. All rights reserved. This program is
+free software; you can redistribute it and/or modify it under the same
+terms as Perl itself.
+
+=cut
diff --git a/lib/Net/LDAP/Intermediate/SyncInfo.pm
b/lib/Net/LDAP/Intermediate/SyncInfo.pm
new file mode 100644
index 0000000..ed8205a
--- /dev/null
+++ b/lib/Net/LDAP/Intermediate/SyncInfo.pm
@@ -0,0 +1,140 @@
+# Copyright (c) 2008 Mathieu Parent <math.parent@gmail.com>. All
rights reserved.
+# This program is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+
+package Net::LDAP::Intermediate::SyncInfo;
+
+use vars qw(@ISA $VERSION);
+use Net::LDAP::Intermediate;
+
+@ISA = qw(Net::LDAP::Intermediate);
+$VERSION = "0.01";
+
+use Net::LDAP::ASN qw(syncInfoValue);
+use strict;
+
+# use some kind of hack here:
+# - calling the control without args means: response,
+# - giving an argument: means: request
+sub init {
+ my($self) = @_;
+
+ delete $self->{asn};
+
+ unless (exists $self->{responseValue}) {
+ $self->{asn} = {
+ newcookie => $self->{newcookie} || '',
+ };
+ }
+
+ $self;
+}
+
+sub newcookie {
+ my $self = shift;
+ $self->{asn} ||= $syncInfoValue->decode($self->{responseValue});
+ if (@_) {
+ delete $self->{responseValue};
+ return $self->{asn}{newcookie} = shift || 0;
+ }
+ $self->{asn}{cookie};
+}
+
+sub responseValue {
+ my $self = shift;
+
+ exists $self->{responseValue}
+ ? $self->{responseValue}
+ : $self->{responseValue} = $syncInfoValue->encode($self->{asn});
+}
+
+1;
+
+
+__END__
+
+=head1 NAME
+
+Net::LDAP::Intermediate::SyncInfo - LDAPv3 Sync Info Message object
+
+=head1 SYNOPSIS
+
+ use Net::LDAP;
+ use Net::LDAP::Control::SyncRequest;
+ use Net::LDAP::Constant qw(
+ LDAP_SYNC_REFRESH_ONLY
+ LDAP_SYNC_REFRESH_AND_PERSIST
+ LDAP_SUCCESS );
+
+ $ldap = Net::LDAP->new( "ldap.mydomain.eg" );
+
+ $req = Net::LDAP::Control::SyncRequest->new( mode => LDAP_SYNC_REFRESH_ONLY );
+ my $mesg = $ldap->search(base=> 'dc=mydomain,dc='eg',
+ scope => 'sub',
+ control => [ $req ],
+ callback => \&searchCallback, # call for each entry
+ filter => "(objectClass=*)",
+ attrs => [ '*']);
+ sub searchCallback {
+ my $message = shift;
+ my $entry = shift;
+ my @controls = $message->control;
+
+ if($controls[0]->isa('Net::LDAP::Control::SyncState')) {
+ print "Received Sync State Control\n";
+ print $entry->dn()."\n";
+ print 'State: '.$controls[0]->state."\n".', entryUUID:
'.$controls[0]->entryUUID.', cookie: '.$controls[0]->cookie;
+ } elsif($controls[0]->isa('Net::LDAP::Control::SyncDone')) {
+ print "Received Sync Done Control\n";
+ print 'Cookie: '.$controls[0]->cookie.', refreshDeletes:
'.$controls[0]->refreshDeletes;
+ }
+ }
+
+=head1 DESCRIPTION
+
+C<Net::LDAP::Intermediate::SyncInfo> provides an interface for the creation and
+manipulation of objects that represent the C<Sync Info Message> as described
+by RFC 4533.
+
+=head1 CONSTRUCTOR ARGUMENTS
+
+In addition to the constructor arguments described in
+L<Net::LDAP::Intermediate> the following are provided.
+
+=over 4
+
+=item TODO
+
+=back
+
+=head1 METHODS
+
+As with L<Net::LDAP::Intermediate> each constructor argument
+described above is also avaliable as a method on the object which will
+return the current value for the attribute if called without an argument,
+and set a new value for the attribute if called with an argument.
+
+=head1 SEE ALSO
+
+L<Net::LDAP>,
+L<Net::LDAP::Intermediate>,
+L<Net::LDAP::Control>,
+L<Net::LDAP::Control::SyncRequest>,
+L<Net::LDAP::Control::SyncState>,
+http://www.ietf.org/rfc/rfc4533.txt
+
+=head1 AUTHOR
+
+Mathieu Parent E<lt>math.parent@gmail.comE<gt>
+
+Please report any bugs, or post any suggestions, to the perl-ldap mailing list
+E<lt>perl-ldap@perl.orgE<gt>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2008 Mathieu Parent. All rights reserved. This program is
+free software; you can redistribute it and/or modify it under the same
+terms as Perl itself.
+
+=cut
+
diff --git a/lib/Net/LDAP/Search.pm b/lib/Net/LDAP/Search.pm
index ed1617b..d8c3568 100644
--- a/lib/Net/LDAP/Search.pm
+++ b/lib/Net/LDAP/Search.pm
@@ -8,11 +8,12 @@ use strict;
use vars qw(@ISA $VERSION);
use Net::LDAP::Message;
use Net::LDAP::Entry;
+use Net::LDAP::Intermediate;
use Net::LDAP::Filter;
use Net::LDAP::Constant qw(LDAP_SUCCESS LDAP_DECODING_ERROR);
@ISA = qw(Net::LDAP::Message);
-$VERSION = "0.11";
+$VERSION = "0.12";
sub first_entry { # compat
@@ -63,6 +64,17 @@ sub decode {
return $self;
}
+ elsif ($data = delete $result->{protocolOp}{intermediateResponse}) {
+
+ my $intermediate = Net::LDAP::Intermediate->from_asn($data);
+
+ push(@{$self->{'intermediate'} ||= []}, [$intermediate]);
+
+ $self->{callback}->($self, $intermediate)
+ if (defined $self->{callback});
+
+ return $self;
+ }
$self->set_error(LDAP_DECODING_ERROR, "LDAP decode error");
return;
--
1.5.6
From: Daniel Stutz, Graham Barr
Hi all,
I wonder if the condition for the sync() calls in LDAP::Extension is
correct. It checks for the existence of $self->{Code}. Shouldn't that be
$self->{resultCode} ?
In general, I am not sure, if calling sync() based on the existence of
resultCode is correct when sending messages asynchronously. When you
send a request message you want to know if the encoding and sending has
succeeded. You don't want to wait for the response message.
Can you help me to understand the reason for the reuse of the request
message object for holding the response message?
Thank you.
Kind regards,
Daniel
From: Daniel Stutz, Chris Ridd, Graham Barr
Hi all,
according to RFC 4511 an ExtendedResponse has the following format:
ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
COMPONENTS OF LDAPResult,
responseName [10] LDAPOID OPTIONAL,
responseValue [11] OCTET STRING OPTIONAL }
RFC 4511 obsoletes RFC 2251 where the ExtendedResponse was defined as:
ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
COMPONENTS OF LDAPResult,
responseName [10] LDAPOID OPTIONAL,
response [11] OCTET STRING OPTIONAL }
The obsolete structure is still used in LDAP::ASN.pm and in
Net::LDAP::Extension the attribute as well as the accessor is also
called "response".
Kind regards,
Daniel
From: Daniel Stutz, Graham Barr
Hi all,
Message::decode calls LDAP::_forgetmesg
as far as I understand the architecture of Net::LDAP this should not be
done for IntermediateResponse messages. Is that correct?
Thank you.
Kind regards,
Daniel
--- Message.pm.orig 2008-07-16 10:01:18.000000000 +0200
+++ Message.pm 2008-07-16 10:02:01.000000000 +0200
@@ -143,7 +143,9 @@
# tell our LDAP client to forget us as this message has now completed
# all communications with the server
- $self->parent->_forgetmesg($self);
+ unless( $result->{protocolOp}{intermediateResponse} ){
+ $self->parent->_forgetmesg($self);
+ }
$self->{callback}->($self)
if (defined $self->{callback});
From: A. Farber, Alexander Farber, Miller, Don C., Markus Moeller
Hello,
does anybody please know how set the checkbox
"User must change password at next logon" for
a new user in Active directory?
In VBScript it is done by: obj.Put "pwdLastSet", 0
but I can't find the Net::LDAP counterpart for that (and
I can't use Win32::OLE because my script runs on Linux)
After reading http://support.microsoft.com/kb/305144
I've tried setting 0x800000 bit in userAccountControl -
but it doesn't work (the user is created fine though):
use constant NORMAL_ACCOUNT => 0x200;
use constant PASSWORD_EXPIRED => 0x800000;
$result = $ldap->add($dn,
attr => [
objectClass => 'user',
#objectClass => [qw(top person organizationalPerson
user)],
sAMAccountName => $uid,
userPrincipalName => $uid . '@' . DOMAIN,
givenName => $first,
sn => $last,
displayName => $fullname,
description => $fullname,
mail => $mail,
l => $city,
physicalDeliveryOfficeName => $city,
company => $company,
]
);
$result->code && die 'Failed to add entry: ', $result->error;
$charmap = Unicode::Map8->new('latin1') or die $!;
$unipwd = $charmap->tou('"' . $password . '"')->byteswap()->utf16();
$result = $ldap->modify($dn, add => { unicodePwd => $unipwd } );
$result->code && die 'Failed to modify entry: ', $result->error;
$result = $ldap->modify($dn, replace => { userAccountControl =>
NORMAL_ACCOUNT | PASSWORD_EXPIRED } );
$result->code && die 'Failed to modify entry: ', $result->error;
Any hints please?
Alex
PS: I'm so happy I can work with Perl after I've finally
enabled LDAP/SSL in our domain controllers...
From: Manuel Vacelet, Chris Ridd, Christopher A Bongaarts
Hello,
My question is probably more related to my own understanding of perl
than Net::LDAP module but it causes some headaches to me :)
The following code just works fine:
1 use strict;
2 use warnings;
3 use Net::LDAP;
4 my @servers =
['ldap://ldap5.example.com','ldap://ldap-fallback-eu.example.com','ldap://ldap.example.com','ldap://ldap2.example.com'];
5 my $ldap = Net::LDAP->new(@servers) or die "Unable to connect to
ldap server: $@\n";
But, if I change [] by () in the servers array affectation L4, I get an error:
Unable to connect to ldap server: IO::Socket::INET: Bad hostname ''
I googled at bit but faild to find an explanation for the difference
between the list and the array definition. (The funniest part comes
when it works when the list contains an odd number of elements).
My very problem is that the list of available ldap server comes from a
configuration variable (a scalar) I split for Net::LDAP->new.
Thanks for your help,
-- Manuel
From: Daniel Stutz, Graham Barr, Chris Ridd
Hi all,
I am trying to implement an Net::LDAP::Extension and hit the wall, when
the first LDAPResponse from the server arrives.
ASN1::_decode returns an error, when it is called on that LDAPResponse,
which should contain an ExtendedResponse.
I extended Net::LDAP to write the pdu to a file before it calls
LDAPResponse->decode on it.
The pdu is attached. As well as the ASN1 extracted from Net::LDAP::ASN
and a small scrip, that also can't parse the pdu.
Kind regards,
Daniel
From: Clément OUDOT
Hello,
I belong to the LemonLDAP::NG[1] community, which open source software is
a websso for Apache using mod_perl and of course Net::LDAP (we are doing
authentication and authorization trough LDAP).
I recently added the password policy support to our authentication portal,
so a user can know if its account is locked or its password expired.
The problem is that it only works if we have perl-ldap >= 0.35, and the
major Linux distributions still provide perl-ldap 0.34.
So we protect calls to password policy module with eval functions, and we
face a problem when exporting the constants. The source code is:
http://svn.forge.objectweb.org/cgi-bin/viewcvs.cgi/lemonldap/trunk/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/AuthLDAP.pm?rev=333&view=markup
The pb is exporting constants is done when compiling, and not when running
the code. So in the actual code, the constants are not exported (we need
to remove the eval or use {} around eval arguments). But this will raise
errors for people with perl-ldap library <= 0.34.
Did you have any suggestions to resolve this pb?
Thanks for your help!
Clement OUDOT.
[1] http://wiki.lemonldap.objectweb.org/xwiki/bin/view/NG/Presentation
From: Vartak, Yash V, Chris Ridd, Justin Alcorn, Kurt Zeilenga
Dist,
I am using Net::LDAP to generate reports out of Microsoft Active
Directory, here my LDAP filter is expected to return roughly around
12,000 - 13,000 records.
But due to Admin limits on Active Directory the number of entries
returned are restricted to 1000, due to security reasons it's not
possible to increase admin limit on AD.
What could be work around for this particular problem? So that the
search returns full 12000 + records and I can process all of them later,
instead of present 1000
Yash Vartak
System Engineer
Neptune Orient Lines Ltd
Company Registration Number: 196800632D
Direct Tel: (65) 6371 4483
Fax: (65) 6371 6161
e-mail: Yash_Vartak@apl.com
Website: http://www.nol.com.sg <http://www.nol.com.sg>
This message is intended for the recipient(s) named above. It may
contain confidential or privileged information. If you are not the
intended recipient, please notify the sender immediately by replying to
this message and then delete it from your system. Do not copy, use or
circulate this communication. Thank you.
From: dakin999
I am looking for any generic perl code that is doing some thing like
following. Any code help will be really helpful.
1. Reads from a database(oracle) following columns:
Customer_No, Fname, Lname, Password.
2. Encrypts the password in SHA1_Base64 format.
3. Use the perl-ldap add object to create a ldif record with the same
columns (as in step 1, but password in the SHA1_Base64 encrypted
string).
4. Create a CSV file with same columns as in step 1, exculding the
password.
5. Add the ldif data into SUN LDAP directory.
Thanks in advance.
From: Mathieu PARENT, Graham Barr
Hi,
I have implemented LDAP Content Synchronization Operation (rfc4533) in
perl-ldap (See the attached patch). This is used by the OpenLDAP
server and provide features similar to Persistent Searches in a more
consistent way.
This is my first try in this code, any feedback is welcome.
I don't know how to handle the Sync Info Message which is an LDAP
Intermediate Response Message (see 2.5 in RFC). perl-ldap doesn't
seems to support intermediate responses in response to LDAP::Search.
What is the way to correct this ?
thanks
Mathieu Parent
From: Richard Burkert
This E-mail, including any attachments, may be intended solely for the personal
and confidential use of the sender and recipient(s) named above. This message
may include advisory, consultative and/or deliberative material and, as such,
would be privileged and confidential and not a public document. Any Information
in this e-mail identifying a client of the Department of Human Services is
confidential. If you have received this e-mail in error, you must not review,
transmit, convert to hard copy, copy, use or disseminate this e-mail or any
attachments to it and you must delete this message. You are requested to notify
the sender by return e-mail.
From: Young, Darren, Clément OUDOT, Vartak, Yash V
Is there any way to check to see if a Net::LDAP object is
connected/bound to a server?
As in:
$ldap = Net::LDAP->new($server);
$mesg = $ldap->bind($stuff);
if ( $ldap->is_connected($possibly_some_server) ) {
print("Connected\n");
}
if ( $mesg->is_bound($possibly_with_a_dn) ) {
Print("Bound\n");
}
etc, etc...
From: Zumwalt, Robert, Andrej Ricnik-Bay, Chris Ridd
I am getting a error:
Using the following DN:
DISPLAYNAME=Name
1,MAIL=dev_05272008_1601_1@blah.com,OU=OSS_8781150020001601_200805281457
19695574,O=blah.com,O=consumer,O=site
I believe the problem lies in the space in the displayname, as names
without a space are added just fine, however after reading over
Net::LDAP::Utils and RFC 2253 it only states that leading and trailing
spaces have to be converted to a \20. So in my attempts to fix this I
have changed "DISPLAYNAME=Name 1" to:
DISPLAYNAME='Name 1'
DISPLAYNAME=Name\201
DISPLAYNAME=Name\ 1
Yet nothing I have tried so far has helped...
Thoughts or suggestions?
Robert Zumwalt
E-MAIL CONFIDENTIALITY NOTICE:
The contents of this e-mail message and
any attachments are intended solely for the
addressee(s) and may contain confidential
and/or legally privileged information. If you
are not the intended recipient of this message
or if this message has been addressed to you
in error, please immediately alert the sender
by reply e-mail and then delete this message
and any attachments. If you are not the
intended recipient, you are notified that
any use, dissemination, distribution, copying,
or storage of this message or any attachment
is strictly prohibited.
From: Nicholas Piper
Dear list,
I'm trying to cause a 'slave' LDAP directory (in this case, the
Embedded LDAP server in WebLogic 8.1sp5) to become the same as a
'primary' directory (also in WL 8.1sp5).
The approach taken so far is to perform an ldapsearch on both, then
use ldifdiff.pl (from the LDAP perl's contrib directory) and finally
use ldapmodify (testing with OpenLDAP's, but will be using HP-UX's) to
import the changes.
We use ldifsort.pl before ldifdiff.pl, as per the recommendation in
ldifdiff.pl.
Our problem is that this process creates an LDIF file which contains
actions we need to be performed in a particular order, but they are
not in that order yet. For example, the output of ldifdiff.pl might
be:
dn: ou=EPredicate,ou=newrealm,dc=examples
changetype: add
objectclass: organizationalUnit
objectclass: top
ou: EPredicate
dn: ou=newrealm,dc=examples
changetype: add
objectClass: organizationalUnit
objectClass: top
ou: newrealm
but in order for ldapmodify to be successful, the file would need to
be:
dn: ou=newrealm,dc=examples
changetype: add
objectClass: organizationalUnit
objectClass: top
ou: newrealm
dn: ou=EPredicate,ou=newrealm,dc=examples
changetype: add
objectclass: organizationalUnit
objectclass: top
ou: EPredicate
A similar problem happens with delete, which need to be depth-first.
Is there a straight forward way to order the file so the adds are
depth-last, and then the deletes are depth-first? I would expect this
to be a common problem, so it's possible that I'm misunderstanding
some part.
Any advice gratefully received!
Thank you,
Nick
From: Clément OUDOT, Vartak, Yash V
Dist,
While working with Net::LDAP and AD I noticed that wild card
filter
((objectclass=user)(l=yokohama)(deptment=marketing)(c=jp)(!(memberOF:
CN=JAP_EMP_Mktg_SEC,OU=Users&Groups,OU=JAP,DC=ALNIPPOE,DC=com)))
returns me right results
how ever below filter fails
((objectclass=user)(l=yokohama)(deptment=marketing)(c=jp)(!(memberOF:
*JAP_EMP_Mktg*)))
Fails
The wild cards work well with other directories , except for Active
Directory , have others noticed this?
Yash Vartak
System Engineer
Neptune Orient Lines Ltd
Company Registration Number: 196800632D
Direct Tel: (65) 6371 4483
Fax: (65) 6371 6161
e-mail: Yash_Vartak@apl.com
Website: http://www.nol.com.sg <http://www.nol.com.sg>
This message is intended for the recipient(s) named above. It may
contain confidential or privileged information. If you are not the
intended recipient, please notify the sender immediately by replying to
this message and then delete it from your system. Do not copy, use or
circulate this communication. Thank you.
From: Cyril Cheneson, Miller, Don C.
Hi all,
I m using Net::LDAP to connect to a LDAP server and create/modify users.
I have a predefined LDAP user I m using to bind with and then
create/modify accounts.
My slapd.conf has the following:
access to attrs=userPassword,shadowLastChange
by dn="cn=admin,dc=mydomain,dc=com" write
by dn="uid=cyril,ou=People,dc=mydomain,dc=com" write
by anonymous auth
by self write
by * none
access to dn.base="" by * read
# The admin dn has full write access, everyone else
# can read everything.
access to *
by dn="cn=admin,dc=mydomain,dc=com" write
by dn="uid=cyril,ou=People,dc=mydomain,dc=com" write
by * read
So if I understood well, the dn
"uid=cyril,ou=People,dc=mydomain,dc=com" has write access(and there
for delete, and read)
to everything, just like the admin.
But when I try to create a user (being binded with
"uid=cyril,ou=People,dc=mydomain,dc=com"), I got an "insufficient
access" error (50) from Net::LDAP (from $resp->error and $resp->code
)but the user is created.
Has anyone seen this behavior as well?
Should I rely on another value to check if the action has been
performed successfully?
I have also tried with the LDAP admin account and no error has been thrown.
Thanks for your help
Cyril
--
----------------------------------
Cyril
"We will encourage you to develop the three great virtues of a programmer:
laziness, impatience, and hubris."
-- Larry Wall, creator of the Perl programming language
From: Srinivas N, Peter Marschall
Hi,
I have been working with LDAP server configurations from some time and
now I want to integrate the LDAP in my project.
I want to use LDAP to authenticate the users when they login to my portal.
I found Net::LDAP as a good perl module that can be used to serve my purpose.
I was successful in executing search statements and here is the code
#! /usr/bin/perl
use Net::LDAP;
$ldap = Net::LDAP->new ( "<ip address>" ) or die "Connection Failed $@";
$mesg = $ldap->bind ( "<user name>",
password => "<password>",
version => 3 );
$base = "dc=example,dc=com";
$mesg = $ldap->search ( # perform a search
base => $base,
filter => "(objectclass=*)"
);
$mesg->code && die $mesg->error;
foreach $entry ($mesg->all_entries) { $entry->dump; }
for the above code I got the following correct output:
------------------------------------------------------------------------
dn:dc=example,dc=com
dc: example
description: Root LDAP entry for example.com
objectClass: dcObject
organizationalUnit
ou: rootobject
------------------------------------------------------------------------
dn:ou=People,dc=example,dc=com
ou: People
description: All people in organisation
objectClass: organizationalUnit
------------------------------------------------------------------------
dn:uid=srinivas,ou=People,dc=example,dc=com
uid: srinivas
cn: srinivas
objectClass: account
posixAccount
top
shadowAccount
userPassword: {crypt}$1$zYwJ/asE$DsYRb6CXjzJihNyTV2lC9.
shadowLastChange: 13986
shadowMax: 99999
shadowWarning: 7
loginShell: /bin/bash
uidNumber: 503
gidNumber: 100
homeDirectory: /home/srinivas
now when I am trying to execute compare function whose code is
$mesg = $ldap->compare( $base,
attr => "uid",
value => "srinivas"
);
$mesg->code && die $mesg->error;
foreach $entry ($mesg->all_entries) { $entry->dump; }
I am getting following error when I execute the above script
No such attribute at ldap_compare.pl line 34, <DATA> line 259.
Can any one suggest whether there are any additional attributed that
are to be added or any other why that I can compare my username and
password for authentication.
Can you tell me how to authenticate users with this module with
username and password from a CGI page.
Any suggestion will be helpful.
Thanks in Advance.
Srinivas.
From: Phil Pennock, Graham Barr
From: Graham Barr
On Mar 23, 2008, at 3:35 PM, Mark Fuller via RT wrote:
> I have noticed odd (and incorrect) behavior when updating an attribute
> which is not defined as multi-value.
>
> The following example works, but it sets the attribute to the second
> value. This is arbitrary. Worse, it shouldn't work because the
> attribute
> is not defined as multi-value.
>
> $ldap_mesg = $ldap_conn->modify($dn,
> changes => [
> replace => [ 'attr_name' => ['val_1',
> 'val2'] ]
> ]);
>
> However, if you add a third value it will error with code 65. This is
> the expected behavior. But, it should do that with two values.
>
> This is using Sun Directory Server v5. I'm running Net::LDAP .34 on
> Win
> XP Pro.
what do you see, in both cases, if you turn on debugging with
$ldap_conn->debug(15); just before you call to modify ?
Graham.
From: Zumwalt, Robert, Quanah Gibson-Mount, Gerry Smyth
Is there a way to designate a separate read port from write port? Or do
I need to create 2 separate connections if I want to perform this type
of action?
Robert Zumwalt
E-MAIL CONFIDENTIALITY NOTICE:
The contents of this e-mail message and
any attachments are intended solely for the
addressee(s) and may contain confidential
and/or legally privileged information. If you
are not the intended recipient of this message
or if this message has been addressed to you
in error, please immediately alert the sender
by reply e-mail and then delete this message
and any attachments. If you are not the
intended recipient, you are notified that
any use, dissemination, distribution, copying,
or storage of this message or any attachment
is strictly prohibited.
From: Clément OUDOT, Chris Ridd
Hello,
I'm using Net::LDAP for several years (scripts, LemonLDAP::NG project)
and I try now to use Password Policy (with overlay ppolicy in OpenLDAP).
As I see, no control module has been implemented to deals with Password
Policy control response. So I propose myself to write one (on the model
of the VLVresponse for example).
Can you give me some advice on how to write this kind of module (main
coding rules), as my goal is to contribute it to the perl-ldap project ?
Or maybe someone on this list has already done the work ?
Regards,
--
Clement OUDOT
http://www.ohloh.net/accounts/15526
From: Markus Moeller
How can I set SASL security options ? I want to use ldap with SASL/GSSAPI
and control the maxssf security setting.
Is this part of Net::LDAP or Authen::SASL ?
Thank you
Markus
From: Zumwalt, Robert, Chris Ridd
I have a module which makes several sequential calls to the LDAP server
and after the first 10-15 calls my connection seems to be getting
dropped.
Is there a method in net::ldap which allows me to check the state of the
connection to see if it is still good before attempting to reuse it?
Thank you
Robert Zumwalt
E-MAIL CONFIDENTIALITY NOTICE:
The contents of this e-mail message and
any attachments are intended solely for the
addressee(s) and may contain confidential
and/or legally privileged information. If you
are not the intended recipient of this message
or if this message has been addressed to you
in error, please immediately alert the sender
by reply e-mail and then delete this message
and any attachments. If you are not the
intended recipient, you are notified that
any use, dissemination, distribution, copying,
or storage of this message or any attachment
is strictly prohibited.
From: Markus Moeller, Peter Marschall
I am new to LDAP.pm and like to query several ldap servers for
redundancy/failover. The documentation says that the host can be an array:
"HOST may also be a reference to an array of hosts, host-port pairs or URIs
to try. Each will be tried in order until a connection is made. Only when
all have failed will the result of undef be returned."
When I use the below perl script with 192.168.1.12 being the good ldap
server and 192.168.1.18 a bad ldap server (e.g. switched off). I get
./ldap_query.pl
IO::Socket::SSL: connect: timeout at ./ldap_query.pl line 4, <DATA> line
228.
an error. But I would expect the same result as with
$ldap = Net::LDAPS->new( '192.168.1.12', timeout => 2, version => 3) or die
"$@";
./ldap_query.pl
MM Result: 500
only delayed by max 2 seconds.
What is wrong in my script as I don't get a syntax error or similar ?
Thank you
Markus
#!/usr/bin/perl
use Net::LDAPS;
$ldap = Net::LDAPS->new( '192.168.1.18 192.168.1.12', timeout => 2, version
=> 3) or die "$@";
$mesg = $ldap->bind('cn=ldap user,cn=users,dc=win2003r2,dc=home', password
=> 'TestPass!') ;
$mesg = $ldap->search( # perform a search
base => "dc=win2003r2,dc=home",
filter => "(samaccountname=mm)",
attrs => ["employeeid"]
);
$mesg->code && die $mesg->error;
foreach $entry ($mesg->entries) {
$ref=$entry->get_value('employeeid');print "MM Result: $ref\n"; }
$mesg = $ldap->unbind; # take down session
From: info, Michael Alan Dorman, Justin Alcorn
Hi everybody,
i tried to get all elements of my ldap by using the source code:
<---
#!/usr/bin/perl
use strict;
use DBI;
use Net::SMTP;
use Net::LDAP;
use Net::LDAP::LDIF;
use Net::LDAP::Control::Paged;
use Net::LDAP::Constant qw(LDAP_CONTROL_PAGED);
my $ad_ldap_dn =
"cn=myuserid,ou=benutzerkonten,dc=my,dc=domain,dc=com";
my $ad_ldap_password = "MySecretPassword";
my $ad_ldap_server = "my.domain.com";
my $item;
my $ad_ldap = Net::LDAP->new($ad_ldap_server, version => 3) or die
"unable to connect to ad ldap: $@";
my $result = $ad_ldap->bind($ad_ldap_dn, password => $ad_ldap_password);
my $page = Net::LDAP::Control::Paged->new(size => 1000);
my $cookie;
my @args = ( base => "ou=benutzerkonten,dc=my,dc=domain,dc=com",
scope => 'sub',
attrs => ['cn', 'sn', 'givenname', 'department','objectClass'],
filter => "(cn=*)",
control => [ $page ]
);
while (my $ad_search = $ad_ldap->search(@args)) {
while (my $ad_user = $ad_search->shift_entry) {
foreach $item ($ad_user)
{
my $personalnummer = "";
my $koe = "";
my $vorname = "";
my $nachname = "";
my $objectClass = "";
$personalnummer = $item->get_value ( 'cn' );
$koe = $item->get_value ( 'department' );
$vorname = $item->get_value ( 'givenname' );
$nachname = $item->get_value ( 'sn' );
$objectClass = $item->get_value ( 'objectClass' );
if ( ($vorname eq "Jochen") || $nachname eq "Wirth" ||
$nachname eq "Zinkel" )
{
print $vorname.", ".$nachname." (".$personalnummer.") - $koe
Klasse: $objectClass gefunden...\n";
}
}
my ($resp) = $ad_search->control(LDAP_CONTROL_PAGED);
$cookie = $resp->cookie or last;
$page->cookie($cookie);
}
if (!$cookie)
{
last;
}
}
$ad_ldap->unbind();
<---
but still there are some datasets missing :(
I changed the filter to:
- filter => "(cn=*)",
- filter => "(sn=*)",
- filter => "($objectClass=*)",
Using the filter i got
- 6282
- 6394
- 6289
elements...
But this are still not all elements...
Is there a easy way to get all ldap elements?
Thanks for help
Andy