Hidden deep in the bowels of the password server you will find some interesting, if seldom used, password policies that can be applied. Here Arek Dreyer takes a look at the weakpass_edit command and how it can help you refine your security policies.
Is it possible (but completely unsupported!) for you to prevent your users from changing their passwords to "weak or undesirable passwords". You have to supply the list of these "bad" passwords. Note that this does not affect the act of changing passwords with Workgroup Manager, and it breaks the ability to change passwords with the Kerberos application. Did I mention this is unsupported?
Step 1: In /Library/Preferences/com.apple.passwordserver.plist, for the key "ExternalCommand", change the value of "Disabled" to "weakpass". You don't even need to HUP the PasswordService daemon; it starts using weakpass right away.
Step 2: Use the weakpass_edit command to start your dictionary of weak or otherwise undesirable passwords which the password service should reject, like this:
<code>sudo weakpass_edit add -p riley</code>
That's it. There is no step three.
However, if you're interested in the details, I have some more information below.
On Mac OS X Server 10.4(.n?) or later, look at /Library/Preferences/com.apple.passwordserver.plist. By default, the key "ExternalCommand" has the value of "Disabled". Here's one way to figure out what happens when you change "Disabled":
Replace "Disabled" with "SomeOtherCommand.sh"
Watch the output of the command below while you change a password:
<code>sudo fs_usage | grep SomeOtherCommand.sh</code>
Here's my sample output from fs_usage above (with extra spaces removed)
13:39:24 stat /usr/sbin/authserver/tools/SomeExternalCommand.sh 0.000035 PasswordServ
I never specified /usr/sbin/authserver/tools, but there it is…take a look in /usr/sbin/authserver/tools, and you'll see the file "weakpass". So now we know that an "ExternalScript" script can be placed in /usr/sbin/authserver/tools. But let's check out what "weakpass" does before we try to write our own weakpass script. To continue the investigation, change SomeOtherCommand.sh to weakpass in com.apple.passwordserver.plist.
Unfortunately, there is no man page for weakpass. Good thing we have apropos.
"apropos weakpass" should lead you to weakpass_edit, which does have a man page. The "Files & Folders" section of the weakpass_edit man page references "/var/db/authserver/weakpasswords.[n]"
I thought I could simply create a file weakpasswords.0, stuff some cleartext words in there, and make it readable only by root. I was wrong.
I changed a password while watching the output of "fs_usage | grep weak", and weakpass was trying to open (seemingly random) "n"s in weakpasswords.[n]. The n isn't random, it is some hash or index, and I don't know the algorithm.
Don't create and edit random weakpasswords.[n] files like I did; use the weakpass_edit command, which places your entry in the correct file. If you have a bunch of weak passwords you want to inject, you could write a script which invokes weakpass_edit, so your weak passwords will be placed in the right file. I don't know the hashing algorithm, but weakpass_edit does.
Note that the contents of weakpasswords.[n] are clear text, AND when weakpass_edit creates them automatically, they are readable by owner, group, and others (of course, the parent directory /var/db/authserver is only readable by root).
When the weakpass executable rejects a password with the "passwd" command, the user will just see "sorry", as shown below:
balmoral:~ u1$ passwd
Changing password for u1.
Old password: [Here I typed in the good password]
New password: [Here I typed in "riley", the "bad" password I specified above]
Retype new password: [Here I typed in "riley" again]
If the user tries to change to a bad password via the Accounts pane of System Preferences, they will get a message indicating there is a problem: "You cannot change your password to the password you entered. Your system administrator may not allow you to change your password or there was some other problem with your password. Contact your system administrator for help."
If you force a user to change their password at next login, and they try to specify a bad password at their next login, the login window (change password dialog) will simply shake and the user must try again.
If the user tries to change their password at all with the Kerberos.app, they will get "Server error: Failed decrypting request", regardless of the proposed new password (if they fail to enter the correct old password, Kerberos.app replies with: "Kerberos Password Change Failed: Password incorrect").
Password changes will be logged to /Library/Logs/PasswordService/ApplePasswordServer.Server.log. Here are two examples:
Jun 18 2007 16:53:55 CHANGEPASS: external tool exit status = 1, message: rejected
Jun 18 2007 17:09:01 CHANGEPASS: external tool exit status = 0, message: approved
So, if we really wanted to write a script to process the password, it would have to exit with a status of 1 (and a "message" of rejected) to reject a password. Use the "strings" command on the weakpass executable if you're interested. The following strings got passed to my experimental external shell script, and as long as I used "exit 1", the password change was rejected; I didn't need to supply the message "rejected":
$1 the name of the account to change
$2 "standard" or "admin"
But how does the actual proposed password get sent to your script? I didn't see it; that's left for you to find and report back.
Note that using the ExternalCommand does add a few seconds to the password change process.
And finally, let me remind you: this is completely unsupported, the dictionaries are stored in cleartext (though readable only by root), and this breaks the ability to change passwords via Kerberos.app.