Attention!
This page is online for historical purposes only. Everything is out of date and you should probably not use any of it.
Active Directory Password Minders for Mac OS X
Password Expiration Checker — an AppleScript for OS X Tiger & Leopard, updated 8/28/08
This script is meant to be used as a login item (but you can deploy it any way you wish) in environments where Macs are bound to AD with Apple’s Directory Services plug-in. (Sorry, no ADmitMac support yet.) I’ve taken some time to make it as universal as I can, so it should work without any modification.
When it runs, it will display a dialog box if the password expires within the number of days you specify, otherwise it exits quietly. Prior to deploying, be sure to set the warningDays variable to your desired value and — if deploying as a Login Item — save the script as an application.
8/28/08 Update
- Following a tip from reader Roel, I modified the script to properly recognize first and last names containing spaces.
Password Expiration Checker (alternate) — an AppleScript for OS X Tiger & Leopard, updated 9/28/09
Download this alternate version if the above version does not work for you. Whereas the above script attempts to discover information about your AD environment on its own, this script requires you to manually input your site’s AD information.
7/29/08 Updates
- Added ability to manually specify password expiration interval
- Added ability to enable/disable personalization of dialog box (i.e. show user’s first and last name)
- Cleaned up comments within the script
1/16/09 Update
- Added ability to manually specify password expiration age
2/10/09 Update
- Added logic to detect OS version so the script will use separate commands to determine password age on Tiger and Leopard (or greater).
9/28/09 Update
- Fixed the command that runs on Tiger machines. Many thanks to reader Raul Santos for allowing me to remotely control his machine to troubleshoot and fix this issue.
AD Password Expiration Widget, v2 — a Dashboard widget for OS X Leopard, version 2.1, updated 7/11/08
This dashboard widget displays the number of days until the user’s Active Directory password expires. The number is superimposed on a status light that is green if there are more than 30 days to go, is yellow if between 30 and 15 days are left, and is red if 14 or fewer days remain. It also provides a ‘change password now’ button, for convenience. The widget re-uses parts of the first script above, so it has the same environmental requirements.
This update brings you offline functionality — the widget will report the correct number of days even when you’re away from the domain. Also, the rear of the widget display the time and date that it last polled AD. If you’re looking for an easy way to give your mobile users an easy way to manage their own password expiration, then this is for you.
Hi Man,
Listen, I like your applescript for the password expiration.
However, when I run it, I get a negative number. For instance, it says -14 days until expiration. I’ll poke around in the script. Any suggestions, would be great. Thanks, Pete
Hi Peter,
This occurs when the script is unable to retrieve the maximum password age from your domain. (It ends up subtracting the age of your password from zero.) I just modified the script to give a more descriptive error if that’s the case. I’ll be posting a revised version of the alternate script soon that will allow you to manually supply the max password age.
YMG:
I’m also having trouble with the alternate script’s arithmetic. We have a 90 day password change policy (I have configured this into the “manualExpireAge” property of your script). I have a test account whose password was changed 2 days ago. “Additional Account Information” in ADUC shows that the password expires in 88 days. However, when I run the script, it tells the user that the password expires in -148796 days.
Instead of doing the more complex arithmetic wherein you read the date the password was last set, is it possible to simply read the Password Expires value from AD and subtract today’s date from that for the number of days until expiration? Thanks.
Scott,
Are you sure the Password Expires value is something you can directly look up? In Windows Server 2003 and earlier, the only way to get that value is to do the math I’m doing. (I’m not sure about Server 2008.) ADUC is doing a similar calculation when it displays the expiration info. I’d like to help you get this working. Email me directly and I’ll help you troubleshoot it.
I’m sorry, I stand corrected. I believe you are right in that ADUC does a similar calculation. Would love to get this working as we are in the midst of a deployment wherein we are joining all of our Macs to AD. The script currently either cannot find the expiration date at all, or returns a very large negative value.
BTW, we are on W2k3SP2 domain controllers.
I’m unable to find your email address – did you receive mine in my submission?
I’m sorry to post here, didn’t find how to contact you privately.
The date calculation itself works for me. However, I have a question about the LastName calculation.
Seems to be that LastName with more than one word comes out on a new line, so the grep function gets it wrong. It displays as “LastName”.
Here’s my output using your command. I’ve included 1 line of context for clarity.
—
GeneratedUID: 47BD2A36-14C7-4246-96B5-9A109E9DE90F
LastName: Thys
MCXFlags:
—
and for the user with 2 words in LastName
—
LastName:
De Decker
MCXFlags:
—
I thought I could resort to the RealName. At least there’s some consistency there. It’s *always* on a new line, but how do I tell grep to go fetch it there?
—
RealName:
Anne Thys
RecordName:
—
and
—
RealName:
Chiara De Decker
RecordName:
—
Maybe if grep can handle it, the Applescript can. How would I adapt this line, specifically the “second word of” function, which only works for last names with only 1 word?
set lastName to (second word of (do shell script “/usr/bin/dscl localhost read /Search/Users/$USER LastName | /usr/bin/grep Name:”) as string)
Roel, I just updated the script to fix this issue. Thanks for letting me know about the bug.
Hi Folks,
I am from Germany and I have the Same Problems. -14…
I try too merge the two scripts and it works.
Our ExpireAge is 30 days and that is what the script not get from the AD.
I Translate the Mesage and the Part for open the System Preferences in to German for the German UI
When you need it in english cpoy it from the org script
here the Script:
————–
— WARNING PERIOD —
————————————————–
— begin ENVIRONMENTAL VARIABLES
————————————————–
property discoverExpireAge : false
— controls discovery of the password expiration interval on yor domain. Set to true to have the
— script autodiscover it. Set to false if you want to specify the password expiration age manually
— (useful if the script has trouble autodiscovering it). If you set this to false, then you MUST
— supply the value below.
property manualExpireAge : 30
— set to match your domain’s password expiration interval (in days).
— (Only necessary if you set findExpireAge to false above.)
————————————————–
— end ENVIRONMENTAL VARIABLES
————————————————–
set warningDays to 3 as integer
set theError to 0
— Check for active kerberos ticket, exit quietly if none — really only needed when running script manually
try
set kerb to do shell script “/usr/bin/klist”
on error theError
display dialog theError
return
end try
— Get password expiration age from AD
try
— Get IP of AD’s DNS
set myDNS to (do shell script “/usr/sbin/scutil –dns | /usr/bin/awk ‘/nameserver\\[1\\]/ {print $3}'”) as string
— Get the distinguished name (aka search base)
set mySearchBase to (do shell script “/usr/bin/ldapsearch -LLL -Q -s base -H ldap://” & myDNS & space & “rootDomainNamingContext | /usr/bin/awk ‘/rootDomainNamingContext/ {print $2}'”) as string
if discoverExpireAge is true then
try — to get password expiration age from AD
set expireAge to ((do shell script “/usr/bin/ldapsearch -LLL -Q -s base -H ldap://” & myDNS & space & “-b” & space & mySearchBase & space & “maxPwdAge | /usr/bin/awk -F- ‘/maxPwdAge/ {print $2}'”) as integer) / 10000000
if expireAge is equal to 0 then
if debugDialogs is true then display dialog “Unable to find maximum password age.” buttons “OK” with icon 2
return
end if
on error theError
if debugDialogs is true then display dialog theError
return
end try
else — if discovery is off, use the provided value (and do some math so it fits the expected format)
set expireAge to manualExpireAge * 3600 * 24
end if
on error theError
display dialog theError
return
end try
— Get the date the password was last set, with NT–>UNIX date conversion
try
set pwdSetDate to (second word of (do shell script “/usr/bin/dscl localhost read /Search/Users/$USER pwdLastSet | /usr/bin/grep pwdLastSet:”) as integer) / 10000000 – 1.16444736E+10
— get today’s date in the required format
set today to (do shell script “date +%s”) as integer
— do the math to get the days until expiration
set daysUntilExp to round (expireAge – (today – pwdSetDate)) / 3600 / 24
on error theError
display dialog theError
return
end try
— This section generates the warning dialog box
if daysUntilExp ≤ warningDays then
set firstName to (second word of (do shell script “/usr/bin/dscl localhost read /Search/Users/$USER FirstName | /usr/bin/grep Name:”) as string)
set lastName to (second word of (do shell script “/usr/bin/dscl localhost read /Search/Users/$USER LastName | /usr/bin/grep Name:”) as string)
copy (display dialog firstName & space & lastName & “,” & space & “Ihr Passwort läuft in” & space & daysUntilExp & space & “Tagen ab. möchten Sie es jetzt ändern?” buttons [“Ja”, “Nein”] default button 1 giving up after 300 with icon 0) to response
— If user clicks Yes, try to bring up the change password dialog box
if the button returned of response is “Ja” then
tell application “System Preferences”
try — to use UI scripting
set current pane to pane “Benutzer”
tell application “System Events”
tell application process “Systemeinstellungen”
end tell
end tell
end try
activate
end tell
end if
end if
By the Way,
Big Thanks for the Original-Script!!! it solvs a Big Problem for us.
Gerald
And by the way 2…
it works with ADmitMAC 4.1
Vielen Dank, Gerald! It’s great to know this works with ADmitMAC, too.
When I run your script I get…
john
john doe doe your password will expire in
x days. Do you wnat to change it now?
What do I need to change to get the name to display right?
Jay,
Which script are you referring to, and what OS version are you running it on? It’s a strange error, in any case.
Is there any possibility your script(s) could be modified to work when the system is stand-alone?
(Not networked to AD nor to an OS X Server)
Thanks for the work you have already done.
Mike, I’m not quite sure I understand what you’re asking. My scripts and widget take the current username and query the active directory server to determine when the password expires. If your computer is a stand-alone system, then there is no password expiration to worry about. If I’m misunderstanding what you’re asking, please clarify.
I’m trying to implement the Password Expiration Checker and I was wondering, does the Mac workstation have to be bound to the AD network for this script to work? I have everyone bound to OD and not AD at the moment. Their user names on the OD system don’t necessarily line up with the AD user names, so it might be a bit of an issue to get them lined up.
Thanks – Brian
Brian,
Yes, the clients need to be bound to AD. The script needs an active Kerberos ticket in order to poll the domain for account information.
Excellent – thanks. That’s what I was thinking, but I wanted to make sure I wasn’t missing something. Of course this begs the question – is there a good way for the Mac users to then change their password once they receive the message?
Thanks,
Brian
Even if the machine is bound to AD, if the user’s are logging on to OD accounts, they won’t have a kerberos ticket. Connecting to any AD-authenticated fileshare will create a ticket, however. My solution is probably not going to work for you as it was designed for environments where Mac users are logging on with AD accounts.
Hi Peter,
I am also having the same issue as Scott in that I get a -148975 days returned. We also hook into 2003 domain servers.
Here is some debug output from Applescript:
do shell script “/usr/bin/dscl /Active\\ Directory/pcroot.com -read /Users/$USER pwdLastSet | /usr/bin/grep pwdLastSet:”
“pwdLastSet: 128719241276925789”
do shell script “date +%s”
“1232107519”
do shell script “/usr/bin/ldapsearch -LLL -Q -s base -H ldap://10.150.2.155 -b DC=pcroot,DC=com maxPwdAge | /usr/bin/awk -F- ‘/maxPwdAge/ {print $2}'”
“51840000000000”
round -1.48974506177643E+5
-148975
display dialog “expireAge5184000″
{button returned:”OK”}
display dialog “today1.232107519E+9″
{button returned:”OK”}
display dialog “pwdSetDate-1.164447381475E+10″
{button returned:”OK”}
display dialog “daysUntilExp-148975″
{button returned:”OK”}
display dialog “manualExpireAge60″
{button returned:”OK”}
do shell script “/usr/bin/dscl localhost read /Search/Users/$USER FirstName | /usr/bin/grep Name:”
“FirstName: Chris”
do shell script “/usr/bin/dscl localhost read /Search/Users/$USER LastName | /usr/bin/grep Name:”
“LastName: Hopkins”
display dialog “Chris Hopkins, your password will expire in -148975 days. Do you want to change it now?” buttons {“Yes”, “Not now”} default button 2 giving up after 300 with icon 0
{button returned:”Not now”, gave up:false}
———————————————————————————————————————————-
With this account, there are 6 days left until a required password change.
I added some display dialog lines to report on the property values.
Much appreciated Peter.
Chris
Chris, I just updated the alternate script to add the ability to supply the expiration age manually. Please download the updated script and give it a shot. It your case, you’ll need to replace the 0 in the expireAge property with 60.
Hi,
we get password will expire in -149059 days but there are 10 days left.
System is 10.4.11 with AD on Win2003.
Setting expireAge to 100 didn’t work.
Heino, I’ve updated the alternate script to work properly with Tiger. Please give it a try and let me know if it resolves your issue.
Thanks, but now I get Can’t make “such” into real.
Regards Heino
Hi Guys,
My findings may be useful:
I have had varying degrees of success with the two scripts across both Leopard and Tiger in our Win2003 AD environment.
We have a complicated setup with multiple domains as we are a large enterprise.
In testing, some AD user accounts return the correct days until expiry whereas other accounts may return errors or negative values. It seems that the user records in AD are not consistent in the information available for the dscl command line query. I have yet to take this up with our Windows admins. This is just a suspicion on my part as directly interrogating a users account with the dscl read command can return different criteria depending on the user.
There could also be an issue with a Mac having the ‘All Domains’ setting in Directory Services.
Chris
Is there any settings that need to be set for the AD passwd widget? Installed it on a 10.5.5 laptop bound to AD and the status just shows as NAN and grey.
There are no settings to adjust. It uses the same method to get the password expiration as my applescripts do. Can you download both the regular one and the alternate one and let me know if they work for you? If not, I can help you get it working.
I tried both scripts and nothing happened. I saved the script as an application in Script editor and added it to the login items in Workgrp mgr. I was wondering if I am doing something wrong. The 10.4 clients receive the password expire warning automatically. Thanks for your time.
With the alternative script, you have to supply the information it asks for in the environmental variables section. Have you done that? The regular script should return some kind of error.
I’m also getting a negative value. It seems that the script is showing me the difference between when the password was last set and today (for me it’s -40 days ago). Take a look at this script which explains a lot (for me): http://msdn.microsoft.com/en-us/library/ms974598.aspx. They calculate this number + Max Password Age. Please have a look into this.
Martin, have you tried the latest version of my alternative script? It should give you the correct number.
Hi, great script will be very useful, however I too am getting -3 as the number of days remaining whereas in fact I changed the password 3 days ago.
If I manually enter 90 instead of 0 then I get the ‘unable to find Maximum Password Age’ message
any Ideas?
Thanks
How close are you to getting this 100% working? Specifically, the ExpireAge issue.
I’m actually not actively working on this any more. I’d be happy to assist you with any troubleshooting, however. Send me an email.
What is your email address?
i keep getting “Unable to find maximum password age” how can i fix this?
I am no longer supporting these scripts. Please try the Password Monitor application available here:
http://code.google.com/p/password-expiration-monitor/
Am trying to user on tiger 10.4.11 Password Monitor Application does not work with it it only works 10.5 and up please help
Hi Thanks for this,
I wonder if it is possible to grab a users AD Group so we can use it to determine wether or not to mount a network share or not,
Thanks…
Rob,
As part of a login script, for example, you can grab the user’s AD group with the following command:
dscl /Active\ Directory/All\ Domains read /Users/$1 | awk ‘/PrimaryGroupID/ {print $2}’
We use Workgroup Manager along with Active Directory, I have tried to use this as a login item in Workgroup manager but it not running when users login to it. Any ideas?
Can you be more specific? Which file did you try as a login item? Also, does this same file work from an AD account when you double-click on it?
Broken in 10.6, and the new project’s been abandoned. :(
True, it has been abandoned, but I am currently working on a complete rewrite in XCode in my spare time. I’m not sure when I’ll be done since I’m pretty much learning as I go. (I didn’t do any of the app coding for Password Expiration Monitor, only the applescript code that gets the password expiration information from AD.) This new version will work in 10.6 and 10.7. But it’s vaporware until it gets released, right? ;)
The new version is fantastic, I’m deploying it to all our 10.6 staff Macs. Thanks for making it.