Dear reader,
I still am unable to add or modify attributes of an DN entry. I've followed the
suggestion from Graham Barr to check the result(error) code after execution of
the ADD and MODIFY as well as change the DN used.Although no checks for errors
were performed in the original script (which at this point is just an attempt
to figure out how things work, and certainly not fit for use in an production
environment), they are clearly visible in the dumped hash. Nevertheless I've
added printing of verbose error info. The info displayed for DN tells me how
many DN's were involved in the action? Two things in the duped hash intrigue
me. First there is an empty 'changes' array and second no discernible value for
'matchedDN'.
So the code now used is as followes:
#!d:\perl\bin\perl.exe
use Data::Dumper;
use Net::LDAP;
use strict;
my
($attr,$err,$ldap,$mesg,$userToAuthenticate,$passwd,@ocs,@atts,@bju_attrs,%add_attrs,%modify_attrs);
@bju_attrs = qw ( givenName sn physicalDeliveryOfficeName telephoneNumber
streetAddress postOfficeBox l st postalCode c co countryCode homePhone pager
mobile facsimileTelephoneNumber ipPhone title department company manager
directReports);
$add_attrs { givenName } = "JustaName";
$modify_attrs {company} = "Roodbms";
$userToAuthenticate = $ARGV[0];
#print STDOUT ("userToAuthenticate= $userToAuthenticate\n");
$passwd = $ARGV[1];
#print STDOUT ("passwd= $passwd\n");
die "No credentials provided\n" if (! $userToAuthenticate or ! $passwd);
$ldap = Net::LDAP->new ( "wserv02.roodbms" ) or die "$@";
$mesg = $ldap->bind ( "$userToAuthenticate",
password => "$passwd",
version => 3 );
print STDOUT ("After: bind\, mesg= \n".Dumper(%$mesg)."\n\n");
#my @Attrs = qw( ); # request all available attributes
# to be returned.
#my $result = LDAPsearch ( $ldap, "sn=ordinary", \...@attrs);
my $result = LDAPsearch ( $ldap, "sn=ordinary", \...@bju_attrs);
print STDOUT ("result= \n".Dumper(%$result)."\n\n");
print_result_by_entry($result);
#
# Now attempt to add/modify (a) value(s) to/of a DN
#
#my $dn = "DC=Roodbms,CN=Users,CN=ordinary"; # This is shown in
LDAPExplorerTool2
my $dn = "CN=ordinary,CN=Users,DC=Roodbms"; # Changed as suggested by Graham
Barr
#
# First attempt: ADD
#
foreach $attr (keys %add_attrs)
{
print STDOUT ("Adding attribute: $attr with value: ".$add_attrs{$attr}."\n");
}
my $result = LDAPaddUsingHash ( $ldap, $dn, \%add_attrs );
$result = LDAPsearch ( $ldap, "sn=ordinary", \...@bju_attrs);
print STDOUT ("result->code= ".$result->code."\n");
print STDOUT ("result (after add)= \n".Dumper(%$result)."\n\n");
print_result_by_entry($result);
print STDOUT LDAPerror("Add",$result);
#
# Then attempt: MODIFY
#
foreach $attr (keys %modify_attrs)
{
print STDOUT ("\nModifying attribute: $attr to: ".$modify_attrs{$attr}."\n");
}
my $result = LDAPmodifyUsingHash ( $ldap, $dn, \%modify_attrs );
$result = LDAPsearch ( $ldap, "sn=ordinary", \...@bju_attrs);
print STDOUT ("result->code= ".$result->code."\n");
print STDOUT ("result (after modify)= \n".Dumper(%$result)."\n\n");
print_result_by_entry($result);
print STDOUT LDAPerror("Modify",$result);
$err = $ldap->unbind;
#
# Several functions to use
#
sub LDAPerror
{
my ($from, $mesg) = @_;
print "Return code: ", $mesg->code."\n";
print "Message: ", $mesg->error_name;
print ", ", $mesg->error_text;
print "MessageID: ", $mesg->mesg_id."\n";
print "DN: ", $mesg->dn;
#---
# Programmer note:
#
# "$mesg->error" DOESN'T work!!!
#
#print "\tMessage: ", $mesg->error;
#-----
}
sub print_result_by_entry
{
my ($result) = @_;
my @entries = $result->entries;
my $entr;
foreach $entr ( @entries )
{
print "DN: ", $entr->dn, "\n";
my $attr;
foreach $attr ( sort $entr->attributes )
{
# skip binary we can't handle
next if ( $attr =~ /;binary$/ );
print " $attr : ", $entr->get_value ( $attr ) ,"\n";
}
print "#-------------------------------\n";
}
}
sub print_result_by_struct
{
my ($struct) = @_;
#------------
#
# Accessing the data as if in a structure
# i.e. Using the "as_struct" method
#
my $href = $result->as_struct;
# get an array of the DN names
my @arrayOfDNs = keys %$href; # use DN hashes
# process each DN using it as a key
foreach ( @arrayOfDNs )
{
print $_, "\n";
my $valref = $$href{$_};
# get an array of the attribute names
# passed for this one DN.
my @arrayOfAttrs = sort keys %$valref; #use Attr hashes
my $attrName;
foreach $attrName (@arrayOfAttrs)
{
# skip any binary data: yuck!
next if ( $attrName =~ /;binary$/ );
# get the attribute value (pointer) using the
# attribute name as the hash
my $attrVal = @$valref{$attrName};
print "\t $attrName: @$attrVal \n";
}
print "#-------------------------------\n";
}
}
sub LDAPsearch
{
my ($ldap,$searchString,$attrs,$base) = @_;
# if they don't pass a base... set it for them
if (!$base ) { $base = "dc=Roodbms"; }
# if they don't pass an array of attributes...
# set up something for them
# if (!$attrs ) { $attrs = [ 'cn','mail' ]; }
# if (!$attrs ) { $attrs = [ 'cn', 'userPrincipalName' ]; }
my $result = $ldap->search ( base => "$base",
scope => "sub",
filter => "$searchString",
attrs => $attrs
);
return $result;
}
sub LDAPmodifyUsingHash
{
my ($ldap, $dn, $whatToChange ) = @_;
my $entry = Net::LDAP::Entry->new('DN');
print STDOUT ("whatToChange= \n".Dumper(%$whatToChange)."\n\n");
# my $result = $ldap->modify ( $dn,
# replace => { $whatToChange }
# );
# return $result;
$entry->changetype('modify');
$entry->replace(%$whatToChange); # for adding and updating
# $entry->replace( "company" => "Roodbms");
$entry->update($ldap);
return $entry;
}
sub LDAPaddUsingHash
{
my ($ldap, $dn, $whatToChange ) = @_;
my $entry = Net::LDAP::Entry->new('DN');
$entry->changetype('add');
print STDOUT ("whatToChange= \n".Dumper(%$whatToChange)."\n\n");
# my $result = $ldap->modify ( $dn,
# add => { $whatToChange }
# );
# return $result;
foreach my $attr (keys %$whatToChange)
{
$entry->add( $attr => $$whatToChange{$attr});
$entry->update($ldap);
}
return $entry;
}
This code has the following effect:
After: bind, mesg=
$VAR1 = 'parent';
$VAR2 = bless( {
'net_ldap_version' => 3,
'net_ldap_scheme' => 'ldap',
'net_ldap_debug' => 0,
'net_ldap_socket' => bless( \*Symbol::GEN0, 'IO::Socket::INET'
),
'net_ldap_host' => 'wserv02.roodbms',
'net_ldap_uri' => 'wserv02.roodbms',
'net_ldap_resp' => {},
'net_ldap_mesg' => {},
'net_ldap_async' => 0,
'net_ldap_port' => 389,
'net_ldap_refcnt' => 1
}, 'Net::LDAP' );
$VAR3 = 'errorMessage';
$VAR4 = '';
$VAR5 = 'ctrl_hash';
$VAR6 = undef;
$VAR7 = 'resultCode';
$VAR8 = 0;
$VAR9 = 'callback';
$VAR10 = undef;
$VAR11 = 'mesgid';
$VAR12 = 1;
$VAR13 = 'matchedDN';
$VAR14 = '';
$VAR15 = 'controls';
$VAR16 = undef;
$VAR17 = 'raw';
$VAR18 = undef;
result=
$VAR1 = 'parent';
$VAR2 = bless( {
'net_ldap_version' => 3,
'net_ldap_scheme' => 'ldap',
'net_ldap_debug' => 0,
'net_ldap_socket' => bless( \*Symbol::GEN0, 'IO::Socket::INET'
),
'net_ldap_host' => 'wserv02.roodbms',
'net_ldap_uri' => 'wserv02.roodbms',
'net_ldap_resp' => {},
'net_ldap_mesg' => {},
'net_ldap_async' => 0,
'net_ldap_port' => 389,
'net_ldap_refcnt' => 1
}, 'Net::LDAP' );
$VAR3 = 'entries';
$VAR4 = [
bless( {
'changes' => [],
'changetype' => 'modify',
'asn' => {
'objectName' => 'CN=ordinary,CN=Users,DC=Roodbms',
'attributes' => [
{
'type' => 'sn',
'vals' => [
'ordinary'
]
},
{
'type' => 'title',
'vals' => [
'Functienaam'
]
},
{
'type' => 'company',
'vals' => [
'BJU'
]
},
{
'type' => 'countryCode',
'vals' => [
'0'
]
}
]
}
}, 'Net::LDAP::Entry' )
];
$VAR5 = 'errorMessage';
$VAR6 = '';
$VAR7 = 'ctrl_hash';
$VAR8 = undef;
$VAR9 = 'resultCode';
$VAR10 = 0;
$VAR11 = 'callback';
$VAR12 = undef;
$VAR13 = 'matchedDN';
$VAR14 = '';
$VAR15 = 'mesgid';
$VAR16 = 2;
$VAR17 = 'controls';
$VAR18 = undef;
$VAR19 = 'raw';
$VAR20 = undef;
DN: CN=ordinary,CN=Users,DC=Roodbms
company : BJU
countryCode : 0
sn : ordinary
title : Functienaam
#-------------------------------
Adding attribute: givenName with value: JustaName
whatToChange=
$VAR1 = 'givenName';
$VAR2 = 'JustaName';
result->code= 0
result (after add)=
$VAR1 = 'parent';
$VAR2 = bless( {
'net_ldap_version' => 3,
'net_ldap_scheme' => 'ldap',
'net_ldap_debug' => 0,
'net_ldap_socket' => bless( \*Symbol::GEN0, 'IO::Socket::INET'
),
'net_ldap_host' => 'wserv02.roodbms',
'net_ldap_uri' => 'wserv02.roodbms',
'net_ldap_resp' => {},
'net_ldap_mesg' => {},
'net_ldap_async' => 0,
'net_ldap_port' => 389,
'net_ldap_refcnt' => 1
}, 'Net::LDAP' );
$VAR3 = 'entries';
$VAR4 = [
bless( {
'changes' => [],
'changetype' => 'modify',
'asn' => {
'objectName' => 'CN=ordinary,CN=Users,DC=Roodbms',
'attributes' => [
{
'type' => 'sn',
'vals' => [
'ordinary'
]
},
{
'type' => 'title',
'vals' => [
'Functienaam'
]
},
{
'type' => 'company',
'vals' => [
'BJU'
]
},
{
'type' => 'countryCode',
'vals' => [
'0'
]
}
]
}
}, 'Net::LDAP::Entry' )
];
$VAR5 = 'errorMessage';
$VAR6 = '';
$VAR7 = 'ctrl_hash';
$VAR8 = undef;
$VAR9 = 'resultCode';
$VAR10 = 0;
$VAR11 = 'callback';
$VAR12 = undef;
$VAR13 = 'matchedDN';
$VAR14 = '';
$VAR15 = 'mesgid';
$VAR16 = 4;
$VAR17 = 'controls';
$VAR18 = undef;
$VAR19 = 'raw';
$VAR20 = undef;
DN: CN=ordinary,CN=Users,DC=Roodbms
company : BJU
countryCode : 0
sn : ordinary
title : Functienaam
#-------------------------------
Return code: 0
Message: LDAP_SUCCESS, Operation completed without error
MessageID: 4
DN: 1
Modifying attribute: company to: Roodbms
whatToChange=
$VAR1 = 'company';
$VAR2 = 'Roodbms';
result->code= 0
result (after modify)=
$VAR1 = 'parent';
$VAR2 = bless( {
'net_ldap_version' => 3,
'net_ldap_scheme' => 'ldap',
'net_ldap_debug' => 0,
'net_ldap_socket' => bless( \*Symbol::GEN0, 'IO::Socket::INET'
),
'net_ldap_host' => 'wserv02.roodbms',
'net_ldap_uri' => 'wserv02.roodbms',
'net_ldap_resp' => {},
'net_ldap_mesg' => {},
'net_ldap_async' => 0,
'net_ldap_port' => 389,
'net_ldap_refcnt' => 1
}, 'Net::LDAP' );
$VAR3 = 'entries';
$VAR4 = [
bless( {
'changes' => [],
'changetype' => 'modify',
'asn' => {
'objectName' => 'CN=ordinary,CN=Users,DC=Roodbms',
'attributes' => [
{
'type' => 'sn',
'vals' => [
'ordinary'
]
},
{
'type' => 'title',
'vals' => [
'Functienaam'
]
},
{
'type' => 'company',
'vals' => [
'BJU'
]
},
{
'type' => 'countryCode',
'vals' => [
'0'
]
}
]
}
}, 'Net::LDAP::Entry' )
];
$VAR5 = 'errorMessage';
$VAR6 = '';
$VAR7 = 'ctrl_hash';
$VAR8 = undef;
$VAR9 = 'resultCode';
$VAR10 = 0;
$VAR11 = 'callback';
$VAR12 = undef;
$VAR13 = 'matchedDN';
$VAR14 = '';
$VAR15 = 'mesgid';
$VAR16 = 6;
$VAR17 = 'controls';
$VAR18 = undef;
$VAR19 = 'raw';
$VAR20 = undef;
DN: CN=ordinary,CN=Users,DC=Roodbms
company : BJU
countryCode : 0
sn : ordinary
title : Functienaam
#-------------------------------
Return code: 0
Message: LDAP_SUCCESS, Operation completed without error
MessageID: 6
DN: 1
As may be seen: although no discernble error (at least for me) has been
detected, neither the ADD nor the MODIFY seems to have any effect. This still
puzzles me.
Thanks for any helpful suggestion(s)!
Piet