I think I have answered 1 and 3 on my own by reading newsgroups.
But I would still like an easy way to convert the pwdLastSet attribute
and know how to set the password in active directory.
My program now looks like this.
#!/usr/bin/perl -w
use strict;
my $perllib;
BEGIN { $ENV{PERL_LIB} =~ m/(.*)/; $perllib = $1 } # untaint PERL_LIB
use lib $perllib;
use Net::LDAP;
use Net::LDAPS;
use Net::LDAP::Extension::SetPassword;
use Net::LDAP::RootDSE;
use Net::LDAP::Constant;
my $addr = "**********";
my $short_user = "jeffk";
my $user = "CORUSENT\\$short_user";
my $pass = "*********";
my $new_password = "*********";
my $path = "DC=corusent,DC=intra";
my $ldap = Net::LDAP->new($addr) or die "$@";
my $login = $ldap->bind($user, password=> $pass);
my @srcargs1 = (
base => $path,
scope => "sub",
filter => "(sAMAccountName=$short_user)",
attrs => ['unicodePwd', 'memberOf',
'pwdLastSet', 'displayName', 'description', 'managedBy',
'distinguishedName', 'createTimeStamp'
, 'modifyTimeStamp'],
);
my $search = $ldap->search(@srcargs1);
foreach my $entry ($search->entries) {
my $DN = $entry->get_value("distinguishedName");
my $pwdLastSet = $entry->get_value("pwdLastSet");
my $displayName = $entry->get_value("displayName");
if ((defined $DN) && ($DN ne '')){
print "$short_user is not empty\n";
print "\nDN : " . $DN;
print "\npwdLastSet : " . $pwdLastSet;
print "\ndisplayName : " . $displayName;
print "\n\n";
}
my $newPassword = '1fotcn$75';
my $secureLDAP = Net::LDAPS->new( $addr );
$secureLDAP->bind($DN, password => $pass);
#$secureLDAP->root_dse->supported_extension(
LDAP_EXTENSION_WHO_AM_I );
$secureLDAP->root_dse->supported_extension(
"LDAP_EXTENSION_PASSWORD_MODIFY" );
my $mesg = $secureLDAP->set_password( user => $short_user
,oldpasswd => $pass, newpassword=> $newPassword);
die "error: ", $mesg->code(), ": ", $mesg->error(), " \n" if
($mesg->code());
print "changed your password to", $mesg->gen_password() , "\n";
}
print "\n\n";
and I am now getting the error
error: 2: 0000203D: LdapErr: DSID-0C090C7D, comment: Unknown extended
request OID, data 0, vece
Which I have tried to resolve using the support_extension function which
did not fix the problem. If I don't put the quotes I get BAREWORD not
allowed LDAP_EXTENSION_PASSWORD_MODIFY when trying to run my program.
________________________________
From: Jeff Kalbfleisch
Sent: Tuesday, February 06, 2007 6:38 PM
To: '[email protected]'
Subject: 4 issues with Net::LDAP and Active Directory
I have 4 issues which I do not understand and I have searched the
Net::LDAP documentation up and down and cannot figure it out.
1. pwdLastSet is only available for the DN of the user who is logged
in. (That seems a little odd, why is that?) and yes I logged in as
another user using LDAP and it was available for them and not me.
2. pwdLastSet is some Active Directory timestamp (Why oh why cant
Microsoft just use utc like every other application on the planet.). Is
there a function included with Net::LDAP to convert this number into
utc. So I can tell when the user last set their password in meaningful
terms in perl on linux.
3. I have real difficult with determining the DN. In my program you
can see that I looked at the Server Level DN(At least that is what I
think it is. I got it by seeing what I was a member of. My sysadmin for
Active Directory told me my DN to start). If I knew my login name is
there a way I can find my DN easily.
4. I do not seem to be able to set the value of unicodePwd even though
I can change my own password in Active Directory.
Any help is appreciated.
Jeff K
----------------------------------------------------------
When the time comes and my password is going to expire I can set my
password leading me to believe that I can change my own password and my
sysadmin for Active directory swears up and down that each user has the
rights to modify their own password. And I suspect maybe the password is
not in unicodePwd field as suggested because I do not see that field
when I list all the properties of my DN.
Or maybe its hidden for security reasons?
And I get the following Access rights Violation error.
Display Date [CN=Jeff Kalbfleisch,OU=Nelvana,DC=corusent,DC=intra] [Dec
31, 1969] [128126604183974767]<h1>Software error:</h1>
<pre>00000005: SecErr: DSID-031A0F44, problem 4003
(INSUFF_ACCESS_RIGHTS), data 0
at ldappass_set line 120.</pre>
<p>
For help, please send mail to this site's webmaster, giving this error
message
and the time and date of the error.
</p>
[Tue Feb 6 18:14:01 2007] ldappass_set: 00000005: SecErr:
DSID-031A0F44, problem 4003 (INSUFF_ACCESS_RIGHTS), data 0
[Tue Feb 6 18:14:01 2007] ldappass_set: at ldappass_set line 120.
I wrote this code which gives the above result
my $ldap = Net::LDAPS->new("myDNS") or die "$@";
my $login = "CORUSENT\\jeffk";
my $password = "-----"; # I emptied this field for security reasons
my $message = $ldap->bind($login, password=>$password, version=> 3);
my $schema = $ldap->schema();
my $dse = $ldap->root_dse();
my $resultCode = $message->{'resultCode'};
#Nel::Core::Common::dump($dse);
my $mesg = $ldap->search(
base => "OUR BASE DN",
filter => "cn=*"
);
$mesg->code && die $mesg->error;
my @entries = $mesg->entries;
my @all_nelvana_DNs;
foreach my $entr ( @entries ) {
my $attr;
foreach $attr ( sort $entr->attributes ) {
next if ( $attr =~ /;binary$/ );
if ($attr eq 'member'){
@all_nelvana_DNs = $entr->get_value($attr);
}
}
}
foreach my $DN(@all_nelvana_DNs){
#if ($DN !~ 'Richard Gopaul') { next; }
if ($DN !~ 'Jeff Kalbfleisch') { next; }
my $ldap_hash = &get_dn_hash($ldap,$DN);
my $pwdLastSet = $ldap_hash->{pwdLastSet}[0];
my $date = &get_date($pwdLastSet);
my $display_date = $date->get_display_date();
print "\nDisplay Date [$DN] [$display_date] [$pwdLastSet]";
my $newPW = "---------"; # PURPOSLY BLANKED OUT BY ME FOR THIS
POSTING
&set_password($ldap,$DN,$newPW);
}
sub get_dn_hash(){
my $ldap = shift;
my $DN = shift;
my %ldap_record;
my $ldap_record = \%ldap_record;
# Do An LDAP Search On This USER
my $mesg2 = $ldap->search(
base => $DN,
filter => "cn=*",
);
my @entries = $mesg2->entries;
foreach my $entry(@entries){
my $asn = $entry->{asn};
my $attributes = $asn->{attributes};
foreach my $attribute(@$attributes){
my $type = $attribute->{type};
my $vals = $attribute->{vals};
$ldap_record->{$type} = $vals;
}
}
return $ldap_record;
}
sub set_password(){
my $ldap = shift;
my $DN = shift;
my $newPW = shift;
my $charmap = Unicode::Map8->new('latin1') or die;
my $newUniPW =
$charmap->tou('"'.$newPW.'"')->byteswap()->utf16();
$mesg = $ldap->modify($DN,
changes => [
replace => [ unicodePwd => $newUniPW ]]);
$mesg->code && die $mesg->error;
}
Corus(tm) Entertainment Inc. / Nelvana
________________________________
Jeff Kalbfleisch
135 Liberty Street, suite 100
416.535.0935
[EMAIL PROTECTED]
Programmer/Analyst
Toronto, Ontario M6K 1A7
ext. 3255
Corus(tm) is a trade-mark of Corus(tm) Entertainment Inc. or a
subsidiary thereof, which might be used under licence.