Re: Setting LDAP_SERVER_PERMISSIVE_MODIFY_OID to allow empty values in AD

"Alexander Farber" <[email protected]>
Newsgroups gmane.comp.lang.perl.modules.ldap
Message-ID <[email protected]>
On Wed, Dec 3, 2008 at 6:43 PM, Graham Barr <[email protected]> wrote:
> On Dec 2, 2008, at 8:20 AM, A. Farber wrote:
>> I have a script which reads phone numbers from a CSV file
>> and stores them in Active Directory (w2k3), so that you can
>> find a user phone number in the address book of Exchange.
>>
>> After some searching I've found a suggestion to set
>> LDAP_SERVER_PERMISSIVE_MODIFY_OID so that
>> AD does not prevent me from emptying empty values:
>> http://msdn.microsoft.com/en-us/library/aa366984.aspx

> Try
> use constant LDAP_SERVER_PERMISSIVE_MODIFY_OID  '1.2.840.113556.1.4.1413';
>
> $mod = $ldap->modify($entry,
>  control => [ { type => LDAP_SERVER_PERMISSIVE_MODIFY_OID } ],
>  replace => {
>    homePhone => $href->{HOME},
>    mobile => $href->{MOBILE},
>    facsimileTelephoneNumber => $href->{FAX}
>  }
> );
>

Thank you, but unfortunately I still get:

Failed to modify user: 00000057: LdapErr: DSID-0C090A85, comment:
Error in attribute conversion operation, data 0, vece at
./fix-phones.pl line 78, <> line 374.

Regards
Alex
fix-phones.txt (text/plain, 2.5 KB)
#!/usr/bin/perl -wT

# This script imports phone numbers into AD
# Usage: ./fix-phones.pl phonebook.csv
# Execute "sudo yum install perl-LDAP" first if needed

use strict;
use Net::LDAPS;
use Data::Dumper;
use constant LDAP_SERVER_PERMISSIVE_MODIFY_OID => '1.2.840.113556.1.4.1413';

$ENV{PATH} = '/bin:/usr/bin';
$Data::Dumper::Useqq = 1;

use constant ROOTDN   => 'OU=Imported,OU=User Accounts,DC=internal,DC=XXX,DC=com';
use constant DOMAIN   => 'internal.XXX.com';
use constant SERVER   => ['ablwdc01.' . DOMAIN, 'ablwdc02.' . DOMAIN, 'ablwdc03.' . DOMAIN];
use constant ADMIN    => 'Admin';
use constant ADMPW    => 'XXXXXX';

my ($rot13, $ldap, $search, $mod, $href, %phones);

($rot13 = ADMPW) =~ y/A-Za-z/N-ZA-Mn-za-m/;
$ldap = Net::LDAPS->new(SERVER) or 
	die('Can not connect to LDAP server');
$ldap->bind(ADMIN . '@' . DOMAIN, password => $rot13) or
	die('Can not bind to LDAP server as ' . ADMIN);

while(<>) {
	tr/"//d;
	tr/\r//d;
	next unless /^([^,]+),[^,]+,([^,]*),([^,]*),([^,\n]*)/;
	my ($full, $home, $mobile, $fax) = ($1, $2, $3, $4);

	$full =~ s/\xDF/ss/g;
	# replace german umlauts by asterisks
	$full =~ s/[\xC0-\xFF]/\*/g;
	# split full name in first and last name
	next unless $full =~ /^(\S+)\s+(\S+)$/;
	my ($last, $first) = ($1, $2);

	my $filter = "(&(objectCategory=Person)(objectClass=User)(givenName=$first)(sn=$last))";

	# Workaround: AD does not like it if you set empty attributes to empty, so use 'n/a' as default
	#$phones{$filter} = {HOME => $home || 'n/a', MOBILE => $mobile || 'n/a', FAX => $fax || 'n/a'};
	$phones{$filter} = {HOME => $home, MOBILE => $mobile, FAX => $fax};
}

#print STDERR Dumper(\%phones);
#exit 0;

while (my ($filter, $href) = each %phones) {

	$search = $ldap->search(
	    base    => ROOTDN,
	    attrs   => [qw(givenName sn)],
	    filter  => $filter,
	    sizelimit => 1,
	);
	$search->code() && die $search->error();

	foreach my $entry ($search->entries()) { 
		my $givenName   = $entry->get_value('givenName');
		my $sn          = $entry->get_value('sn');

		next unless $givenName && $sn;

		printf STDERR "%-16s %-16s -> %16s %16s %16s\n", 
		    $givenName, $sn, $href->{HOME}, $href->{MOBILE}, $href->{FAX};

		$mod = $ldap->modify($entry, 
		    control => [ { type => LDAP_SERVER_PERMISSIVE_MODIFY_OID } ],
		    replace => { 
			homePhone => $href->{HOME},
			mobile => $href->{MOBILE}, 
			facsimileTelephoneNumber => $href->{FAX} });
		$mod->code() && die 'Failed to modify user: ' . $mod->error();

		#$entry->dump; 
	}
}

$ldap->unbind();
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.