Tuesday, November 11, 2014

Playing with pwpolicy

I had a colleague ask me recently about the changes to Mavericks pwpolicy. Not having touched the tool in a few years, I was curious about the changes. Well, as the saying goes, I'm now one dead little kitty.

pwpolicy gets and sets the password policies for users on OS X. I believe binding to a directory service is required and these settings don't apply to local accounts, however I could be wrong about that, as Apple has now published an article on how Global policies can lock out admin accounts. Yay?

pwpolicy now has deprecated the commands we would have used in the past. In their place are multiple new Account Policy Keywords. All in all, it seems like a good move to use policy keywords as it will be much more customizable in the future. However, at the moment the pwpolciy man page makes my head hurt. I'm failing to grasp the whole picture here, and it's keeping me from grasping the new way of doing policies. I hope to learn more, but in the mean time I've played with the example plist in the man page. With a few simple modifications, I've added checking for numeric and non-numeric characters, as well as mixed case strings.

It appears that these policies use regex to check the password, where the new password is the variable "policyAttributePassword" and when the RegEx "matches" that it continues on.

Again, all conjecture as I've not been able to test or confirm. I am curious as to where the supplemental documentation is....Apple? Anyone else have some idea as to what's going on here? Perhaps willing to present it at a July conference in PA?


Test Plist...

<dict>
<key>policyCategoryPasswordAuthentication</key>
<array>
<dict>
<key>policyContent</key>
<string>policyAttributeMaximumFailedAuthentications &lt; policyAttributeFailedAuthentications</string>
<key>policyIdentifier</key>
<string>failed auths</string>
</dict>
</array>
<key>policyCategoryPasswordChange</key>
<array>
<dict>
<key>policyContent</key>
<string>policyAttributeCurrentTime &gt; policyAttributeLastPasswordChangeTime + policyAttributeExpiresEveryNDays * DAYS_TO_SECONDS</string>
<key>policyIdentifier</key>
<string>Change every 182 days</string>
<key>policyParameters</key>
<dict>
<key>policyAttributeExpiresEveryNDays</key>
<integer>182</integer>
</dict>
</dict>
</array>
<key>policyCategoryPasswordContent</key>
<array>
<dict>
<key>policyContent</key>
<string>policyAttributePassword matches '.{8,}+'</string>
<key>policyIdentifier</key>
<string>com.apple.policy.legacy.minChars</string>
<key>policyParameters</key>
<dict>
<key>minimumLength</key>
<integer>8</integer>
</dict>
</dict>
<dict>
<key>policyContent</key>
<string>policyAttributePassword matches '\D'</string>
<key>policyIdentifier</key>
<string>com.apple.policy.legacy.requiresAlpha</string>
</dict>
<dict>
<key>policyContent</key>
<string>policyAttributePassword matches '\d'</string>
<key>policyIdentifier</key>
<string>com.apple.policy.legacy.requiresNumeric</string>
</dict>
<dict>
<key>policyContent</key>
<string>policyAttributePassword matches '.*[A-Z][a-z]+'</string>
<key>policyIdentifier</key>
<string>com.apple.policy.legacy.requiresMixedCase</string>
</dict>
</array>
</dict>

Edit: Updated link to Global policies can lock out admin accounts HT.

6 comments:

pknz said...

Did you ever find get anywhere with this or find any more information?

Thanks,
Paul

Rusty Myers said...

Paul,

I believe using Profiles was the answer to accomplishing the task of password policy. Using Profile Manager or iPhone Configuration Utility, you can generate a profile for the Mac to enforce the policy.
I was not able to find additional information on pwpolicy.

Rusty

bhagaban mohanty said...

Rusty,


When I am using an array policyCatagoryPasswordContent containing the two dictionaries , one for alphabatic and other for alphanumeric, the policy is honouring to only one that is first dictionary and second is not coming into picture. Is apple designed this way or do I missing something. Below is the code snippet for pwpolicy for setaccountpolicies.

policyCategoryPasswordContent


policyContent
policyAttributePassword matches '.{3,8}+'
policyIdentifier
com.apple.policy.legacy.minChars
policyParameters

minimumLength
3



policyContent
policyAttributePassword matches "[A-Z]+"+
policyIdentifier
com.apple.policy.legacy.requiresAlpha


policyContent
policyAttributePassword matches "[0-9]+"
policyIdentifier
com.apple.policy.legacy.requiresNumeric




Here only first dictionary is honoring for password change.

Rusty Myers said...

bhagaban mohanty,

I'd suggest creating a password policy using a tool like Profile Manager or iPhone Configuration Utility.

To answer your question, it may require an array inside of a single dictionary, instead of two dictionaries.

Chad Bloch said...

There's an error in the first keyset. To be fair, the man page has the same error. The first key category should be

policyCategoryAuthentication

not

policyCategoryPasswordAuthentication

This drove me crazy for about 2 days until I discovered it. I'm not sure who wrote the new man page for pwpolicy, but it is godawful.

I have also found that you can't simply reenable account once a parameter for locking it such as failed attempts has been met. You have to clear the policies and reapply them. While this is relatively simple, I would prefer a way to simply reset the failed attempts. Hopefully Apple will provide a bit more guidance at some point.

Jeff said...

Thanks for the tip all. I got this working on Yosemite 10.10.4. Also got locked account to unlock after the declared lockout time has expired. Should be self explanatory, but the config is:

Password history depth: 5
Password expiration: 121 days
Password max auth attempts before lockout: 5
Password lockout time: 5 minutes
Password complexity: 8 chars minimum, one upper case char, one lower case char, one special symbol (non alpha/numeric)



policyCategoryAuthentication


policyContent
(policyAttributeFailedAuthentications < policyAttributeMaximumFailedAuthentications) OR (policyAttributeCurrentTime > (policyAttributeLastFailedAuthenticationTime + autoEnableInSeconds))
policyIdentifier
Authentication Lockout
policyParameters

autoEnableInSeconds
300
policyAttributeMaximumFailedAuthentications
5






policyCategoryPasswordChange


policyContent
policyAttributeCurrentTime > policyAttributeLastPasswordChangeTime + (policyAttributeExpiresEveryNDays * 24 * 60 * 60)
policyIdentifier
Change every 121 days
policyParameters

policyAttributeExpiresEveryNDays
121






policyCategoryPasswordContent


policyContent
policyAttributePassword matches '.{8,}+'
policyIdentifier
com.apple.policy.legacy.minChars
policyParameters

minimumLength
8




policyContent
policyAttributePassword matches '(.*[0-9].*){1,}+'
policyIdentifier
com.apple.policy.legacy.requiresNumeric
policyParameters

minimumNumericCharacters
1




policyContent
policyAttributePassword matches '(.*[a-z].*){1,}+'
policyIdentifier
com.apple.policy.legacy.requiresAlpha
policyParameters

minimumAlphaCharactersLowerCase
1




policyContent
policyAttributePassword matches '(.*[A-Z].*){1,}+'
policyIdentifier
com.apple.policy.legacy.requiresAlphaUpperCase
policyParameters

minimumAlphaCharacters
1




policyContent
policyAttributePassword matches '(.*[^a-zA-Z0-9].*){1,}+'
policyIdentifier
com.apple.policy.legacy.requiresSymbol
policyParameters

minimumSymbols
1




policyContent
none policyAttributePasswordHashes in policyAttributePasswordHistory
policyIdentifier
Password History
policyParameters

policyAttributePasswordHistoryDepth
5