Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!

Show days left until Active Directory password expires Network
So you want to know how many days until your password expires in Active Directory (AD)? Here's the meat of the code you can run on any AD-bound OS X box, so long as your shortname is the same as the AD name:
#!/bin/bash
pwPolicy=60
user=`whoami`
#use dscl in ineractive mode to find out ADdomain
ADdomain="All Domains"
userRecord=`dscl localhost -read /Active\ Directory/$ADdomain/Users/$user`
lastpwdMS=`echo "$userRecord" | grep -i pwdLastSet | sed 's/pwdLastSet: //'`
todayUnix=`date "+%s"`
lastpwdUnix=`expr $lastpwdMS / 10000000 - 11644473600`
diffUnix=`expr $todayUnix - $lastpwdUnix`
diffdays=`expr $diffUnix / 86400`
daysremaining=`expr $pwPolicy - $diffdays`
echo $daysremaining
I've created a 28KB zip file (ADexpire.zip; Hints mirror) that contains adexpirre.sh, adexpire.php, and adexpire.scpt (and application version) for client/server setup (with code comments). This works for the situation many are in at my work: their machines aren't bound to AD and they don't often log into the file services on an AD server to find out their password expiration! This allows one server to field queries and return a value via http to an AppleScript that runs as a login item.

Hopefully this will help someone else and even better; maybe someone way smarter than me does it in five lines in Perl! ;) Looking forward to the comments and revisions.

[robg adds: I have no way of testing this one...]
    •    
  • Currently 3.00 / 5
  You rated: 3 / 5 (5 votes cast)
 
[43,876 views]  

Show days left until Active Directory password expires | 6 comments | Create New Account
Click here to return to the 'Show days left until Active Directory password expires' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
Show days left until Active Directory password expires
Authored by: kainewynd2 on Oct 03, '06 11:53:04AM

This is one of things that I didn't really realize I needed for my department until it was posted. Thanks.

The first thing I did though, was ditch the local script for favor of a fully web-based solution (using manual entry of username of course). As soon as I pretty it up a bit I think our users are going to be quite happy.



[ Reply to This | # ]
Show days left until Active Directory password expires
Authored by: garythemacguy on Oct 03, '06 12:41:40PM

This looks rather interesting. I'm on annual leave just now, but I think I'll definitely be taking a look at this when I return to the office. Thanks for posting it!



[ Reply to This | # ]
Show days left until Active Directory password expires
Authored by: timdaman on Oct 03, '06 06:02:44PM

I created this script a couple years ago to do this sort of thing for a group in our domain. We had users who used the domain only for email and they needed warnings to tell them to find a computer to reset their password on. I have blanked out information that may identify the site for security reasons. Enjoy.

+++++++++++++++++
#!/usr/bin/perl -w
#
# findOldPwd.pl
#
# This program is designed to run via cron job. It emails users to notify them that password will expire soon.
# This is import because some uses wouldn't otherwise find out until their password expired (such as mail users on the road)
#
# 7/26/2004 Revision 1.0 By Tim Laurence
# Initial release


use Net::LDAP;
use Mail::Send;

# OK so what do all these vars mean?
#
# AD stores time as 10 millionth of seconds since Jan 1st, 12:00AM, 1601AD. Why?!?
# Unix stores time as seconds since Jan 1st, 12:00 AM, 1970.
#
# Thus heavy conversion is needed to get the current time on the local computer and put it into AD time.
#
# fudge is the number of 10 millionths of a second between 1/1/1601 and 1/1/1970 (this was gathered by
# experimentation and not perfectly accurate. I think there years are aprox 365.25 days long but there may
# be leap seconds). It only needs to be accurate to the day so this is good enough.
#
# sevenDays is the number of 10 millionths of a second in 7 days. Watch for seasonal time changes.
#

$fudge = 116444736390271392;
$sevenDays = 6048000000000;



# connect to the LDAP server to gather information
$ldap = Net::LDAP->new( '127.0.0.1' ) or die "$@";

$mesg = $ldap->bind( dn => 'cn=mail_ldap,ou=Mail Objects,DC=blank,DC= blank,DC= blank',
password => 'blank'
);


# die if there was an error above
$mesg->code && die $mesg->error;

# retrieve the maxPwdAge field from the LDAP
$mesg = $ldap->search( base => 'DC= blank,DC= blank,DC= blank',
attrs => 'maxPwdAge',
scope => 'base',
filter => 'distinguishedName=DC= blank,DC= blank,DC= blank'
);

# die if there was an error above
$mesg->code && die $mesg->error;

# Store the result in a standard scalar
# get the first result return by the ldap search
$entry = $mesg->entry(0);

# get the MaxPwdAge attribute from the entry extracted above
# It is the number of 10 millionths of a second old a password is allowed
# to get before it expires. For some reason this value is negative.
@maxPwdAgeArray = $entry->get_value( 'maxPwdAge' );
$maxPwdAge = $maxPwdAgeArray[0];

# get the current time in unix time format
$now = time();

# multiple that value by 10 million and the add the fudge factor, this puts it in AD/Windows format
$now = ($now * 10000000) + $fudge;

# These value help us make a range with-in which passwords will soon expire.
# We want passwords that will expire in the next seven days but not ones that have already
# expired since people whose password expired already can't read their mail, thus no use in pestering them.

# Calculate the value of a pwdLastSet that would expire right now

$expNow = $now + $maxPwdAge;

# Calculate the value of a pwdLastSet that would expire in seven days
$expInSevenDays = $expNow + $sevenDays;

# get list of user for whom to check password expiration
$mesg = $ldap->search( base => 'OU=Mail Objects,DC= blank,DC= blank,DC= blank',
attrs => ['member'],
filter => 'CN=MailUsers'
);

# die if there was an error above
$mesg->code && die $mesg->error;

# Extract the array of mailUsers from the returned object
$entry = $mesg->entry(0);
@members = $entry->get_value( 'member' );

# create a new message sending object
$msg = new Mail::Send;


# set reply to address
$msg->add('Reply-To', '"HelpDesk" <helpdesk@ blank. blank. blank >');
$msg->add('From', '"HelpDesk" <helpdesk@ blank. blank. blank >');

# for each mailUser
foreach $member (@members)
{
# get that mail user's username and time they last set their password
$mesg = $ldap->search( base => "$member",
attrs => ['pwdLastSet', 'sAMAccountName', 'userAccountControl'],
filter => "distinguishedName=$member"
);
# die if there was an error above
$mesg->code && die $mesg->error;

# get the returned user entry from the returned search item
$entry = $mesg->entry(0);
# extract from the entry all the pwdLastSet values (should be and we assume only be one)
@pwdLastSet = $entry->get_value( 'pwdLastSet' );
# extract from the entry all the sAMAccountName(their username) values (should be and we assume only be one)
@sAMAccountName = $entry->get_value( 'sAMAccountName' );
# extract from the entry all the userAccountControl (attributes of their domain account such as if it is subject to password expiration) values (should be and we assume only be one)
@userAccountControl = $entry->get_value( 'userAccountControl' );

# if the pwdLast value is older than the cutoff for passwords that expire in seven days but
# but hasn't expired yet and don't have the "Never expire" flag set in their AD account
if (($pwdLastSet[0] < $expInSevenDays) and ( $pwdLastSet[0] > $expNow ) and !( $userAccountControl[0] & 0x10000 ) )
{
# send them a warning
$howLong = int( ( ( $pwdLastSet[0] - $expNow ) / 10000000 ) / 86400 );

# Define the subject lines used in emails
$normalSubject = "Password expires in $howLong day(s)";
$critSubject = "Warning: Password expires TODAY!!";

# put pretty dates in the email message so it is easy for our users to read
$day = (Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday)[(localtime)[6]];
$month = (January,February,March,April,May,June,July,August,September,October,November,December)[(localtime)[4]];
$mday = (localtime)[3];
$year = 1900 + (localtime)[5];

# set the out going username to current user
$msg->to($sAMAccountName[0]);

# if the password expires today email with a more worrisome subject line
if ( $howLong == 0 )
{
$msg->subject($critSubject);
} else {
$msg->subject($normalSubject);
}

# start a new email with vars defined above
$fh = $msg->open;

# Put the body into the email
print $fh <<"END";
This is an automatic message sent on $day, $month $mday $year

Your password is due to expire in $howLong day(s). When it expires you will lose access to your \@ blank. blank. blank email until the password is changed. You may change it before this happens by logging to one of the many desktop computers in the blank blank at which point you should be prompted to change your password.

If there any questions or problems please don't hesitate to call. Have a great day.


blank blank HelpDesk
helpdesk\@ blank. blank. blank,
(blank)-blank-blank
END

$fh->close; # complete the message and send it
}
}

# clean-up, clean-up, every body every where. ;)
$mesg = $ldap->unbind; # take down session



[ Reply to This | # ]
Show days left until Active Directory password expires
Authored by: bradimmanuel on Oct 04, '06 10:17:26AM

This is a great hint. Thanks for posting it. I have been testing it out and it works fine on our 10.4.8 server, but returns a 1021 days left on our 10.3.9 server. Would there be anything different about the AD plugins?

I can see a few uses for this.

1) Our AD authenticated realm can now being to remind people when their passwords are about to expire. We can grab the user name from their login and send it to the script, have it show up in bright red of something on the landing page.
2) AD login users. OS 10.4 now reminds us our password is expiring, but that does not mean people will change it in time. We could now use this script to check the expiration date, if it is less than three days or so, take them to the online password change page. Could even run a cron job to get around those who leave their computers on at night.

Again, great hint, thanks for posting it!



[ Reply to This | # ]
Show days left until Active Directory password expires
Authored by: pmbuko on Jul 22, '08 11:58:31AM
Apologies for digging up an old thread, but I have both a AppleScript and a (leopard-only) dashboard widget that keep track of password expirations available here:

http://pmbuko.googlepages.com

[ Reply to This | # ]
Show days left until Active Directory password expires
Authored by: joelbruner on Dec 15, '10 08:57:07AM
Snow Leopard's dscl prepends dsAttrTypeNative: to lastpwdMS: this fixes the match so output is purely numeric:
lastpwdMS=`echo "$userRecord" | grep -i pwdLastSet | sed 's/dsAttrTypeNative:pwdLastSet: //'`

Although, this is better and might in some way future-proof it by using the space as a delimeter in cut :
lastpwdMS=`echo "$userRecord" | grep -i pwdLastSet | cut -d' ' -f 2`

[ Reply to This | # ]