You can also do this from a non-Windows machine (without Win32). AD can be accessed through LDAP. I use the following at work. You'll have to change some of the specifics for your particular situation. (i.e. The DN, and the username and password to bind with)
Note: This was cut from a larger script, so there may be a bit here or there missing.
use strict;
use warnings;
use Net::LDAP;
use Unicode::Map8;
use Unicode::String qw(utf16);
my $defaultpass = 'default';
my $cn = 'Person to Change';
my $baseDN = "OU=GENERAL USERS,OU=USERS,DC=FOO";
my $ldap = Net::LDAP->new( 'ldaps://ad.foo' ) or return;
$ldap->bind( "cn=$uid,$baseDN", password => "$password");
my $searchDN = "OU=GENERAL USERS,OU=USERS,DC=FOO";
my $mesg = $ldap->search( # perform a search
base => "$searchDN",
filter => "(&(objectCategory=person)(cn=$cn
+))",
);
if ($mesg->entries != 1) {
print "ERROR: Too many or too few users found";
$ldap->unbind;
exit;
}
foreach my $entry ($mesg->entries) {
# build the conversion map from your local character set to Unicod
+e
my $charmap = Unicode::Map8->new('latin1') or die;
# surround the PW with double quotes and convert it to UTF-16
# byteswap() was necessary in experiments on i386 Linux, YMMV
my $newUniPW = $charmap->tou(qq/"$newpass"/)->byteswap()->utf16();
$entry->replace(unicodePwd => $newUniPW);
# Require pass change on next login
$entry->replace(pwdLastSet => 0);
# Update LDAP Entry
my $msg = $entry->update($ldap);
$msg->sync;
if ($msg->is_error()) {
print $msg->error_text();
$ldap->unbind;
exit;
} else {
print "Password reset to $newpass";
}
}
|