#!/bin/sh
#############################
# Password Policy Settings ##
#############################
MAX_FAILED=5 # 5 max failed logins before locking
LOCKOUT=120 # 2min lockout
PW_EXPIRE=1 # 1 days password expiration
MIN_LENGTH=8 # at least 8 chars for password
MIN_NUMERIC=1 # at least 1 number in password
MIN_ALPHA_LOWER=1 # at least 1 lower case letter in password
MIN_UPPER_ALPHA=1 # at least 1 upper case letter in password
MIN_SPECIAL_CHAR=2 # at least 1 special character in password
PW_HISTORY=5 # remember last 5 passwords
exemptAccount1="locadmmac" #Exempt account used for remote management. CHANGE THIS TO YOUR EXEMPT ACCOUNT
if [ $PW_EXPIRE -lt "1" ];
then
echo "PW EXPIRE TIME CAN NOT BE 0 or less."
exit 1
fi
for user in $(dscl . list /Users UniqueID | awk '$2 >= 500 {print $1}'); do
if [ "$user" != "$exemptAccount1" ]; then
#Check if current plist is installed by comparing the current variables to the new ones
#PW_History
currentPwHistory=$(sudo pwpolicy -u "$user" -getaccountpolicies | grep "Does not match any of last $PW_HISTORY passwords" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' )
newPwHistory="Does not match any of last $PW_HISTORY passwords"
#MIN_SPECIAL_CHAR
currentMinSpecialChar=$(sudo pwpolicy -u "$user" -getaccountpolicies | grep "policyAttributePassword matches '(.*[^a-zA-Z0-9].*){$MIN_SPECIAL_CHAR,}+'" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' )
newMinSpecialChar="policyAttributePassword matches '(.*[^a-zA-Z0-9].*){$MIN_SPECIAL_CHAR,}+'"
#MIN_UPPER_ALPHA
currentUpperLimit=$(sudo pwpolicy -u "$user" -getaccountpolicies | grep "policyAttributePassword matches '(.*[A-Z].*){$MIN_UPPER_ALPHA,}+'" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' )
newUpperLimit="policyAttributePassword matches '(.*[A-Z].*){$MIN_UPPER_ALPHA,}+'"
#MIN_ALPHA_LOWER
currentLowerLimit=$(sudo pwpolicy -u "$user" -getaccountpolicies | grep "policyAttributePassword matches '(.*[a-z].*){$MIN_ALPHA_LOWER,}+'" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' )
newLowerLimit="policyAttributePassword matches '(.*[a-z].*){$MIN_ALPHA_LOWER,}+'"
#MIN_NUMERIC
currentNumLimit=$(sudo pwpolicy -u "$user" -getaccountpolicies | grep "policyAttributePassword matches '(.*[0-9].*){$MIN_NUMERIC,}+'" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' )
newNumLimit="policyAttributePassword matches '(.*[0-9].*){$MIN_NUMERIC,}+'"
#MIN_LENGTH
currentMinLength=$(sudo pwpolicy -u "$user" -getaccountpolicies | grep "policyAttributePassword matches '.{$MIN_LENGTH,}+'" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' )
newMinLength="policyAttributePassword matches '.{$MIN_LENGTH,}+'"
#PW_EXPIRE
currentPwExpire=$(sudo pwpolicy -u "$user" -getaccountpolicies | grep "Change every $PW_EXPIRE days" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' )
newPwExpire="Change every $PW_EXPIRE days"
#LOCKOUT
currentLockOut=$(sudo pwpolicy -u "$user" -getaccountpolicies | grep "$LOCKOUT" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' )
newLockOut="$LOCKOUT"
#MAX_FAILED
currentMaxFailed=$(sudo pwpolicy -u "$user" -getaccountpolicies | grep "$MAX_FAILED" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' )
newMaxFailed="$MAX_FAILED"
isPlistNew=0
if [ "$currentPwHistory" == "$newPwHistory" ]; then
echo "PW_History is the same"
else
echo "PW_History is NOT the same"
echo "current: $currentPwHistory"
echo "new: $newPwHistory"
isPlistNew=1
fi
if [ "$currentMinSpecialChar" == "$newMinSpecialChar" ]; then
echo "MIN_SPECIAL_CHAR is the same"
else
echo "MIN_SPECIAL_CHAR is NOT the same"
echo "current: $currentMinSpecialChar"
echo "new: $newMinSpecialChar"
isPlistNew=1
fi
if [ "$currentUpperLimit" == "$newUpperLimit" ]; then
echo "MIN_UPPER_ALPHA is the same"
else
echo "MIN_UPPER_ALPHA is NOT the same"
echo "current: $currentUpperLimit"
echo "new: $newUpperLimit"
isPlistNew=1
fi
if [ "$currentLowerLimit" == "$newLowerLimit" ]; then
echo "MIN_ALPHA_LOWER is the same"
else
echo "MIN_ALPHA_LOWER is NOT the same"
echo "current: $currentLowerLimit"
echo "new: $newLowerLimit"
isPlistNew=1
fi
if [ "$currentNumLimit" == "$newNumLimit" ]; then
echo "MIN_NUMERIC is the same"
else
echo "MIN_NUMERIC is NOT the same"
echo "current: $currentNumLimit"
echo "new: $newNumLimit"
isPlistNew=1
fi
if [ "$currentMinLength" == "$newMinLength" ]; then
echo "MIN_LENGTH is the same"
else
echo "MIN_LENGTH is NOT the same"
echo "current: $currentMinLength"
echo "new: $newMinLength"
isPlistNew=1
fi
if [ "$currentPwExpire" == "$newPwExpire" ]; then
echo "PW_Expire is the same"
else
echo "PW_Expire is NOT the same"
echo "current: $currentPwExpire"
echo "new: $newPwExpire"
isPlistNew=1
fi
if [ "$currentLockOut" == "$newLockOut" ]; then
echo "LOCKOUT is the same"
else
echo "LOCKOUT is NOT the same"
echo "current: $currentLockOut"
echo "new: $newLockOut"
isPlistNew=1
fi
if [ "$currentMaxFailed" == "$newMaxFailed" ]; then
echo "MAX_FAILED is the same"
else
echo "MAX_FAILED is NOT the same"
echo "current: $currentMaxFailed"
echo "new: $newMaxFailed"
isPlistNew=1
fi
if [ "$isPlistNew" -eq "1" ]; then
# Creates plist using variables above
echo "
policyCategoryAuthentication
policyContent
(policyAttributeFailedAuthentications < policyAttributeMaximumFailedAuthentications) OR (policyAttributeCurrentTime > (policyAttributeLastFailedAuthenticationTime + autoEnableInSeconds))
policyIdentifier
Authentication Lockout
policyParameters
autoEnableInSeconds
$LOCKOUT
policyAttributeMaximumFailedAuthentications
$MAX_FAILED
policyCategoryPasswordChange
policyContent
policyAttributeCurrentTime > policyAttributeLastPasswordChangeTime + (policyAttributeExpiresEveryNDays * 24 * 60 * 60)
policyIdentifier
Change every $PW_EXPIRE days
policyParameters
policyAttributeExpiresEveryNDays
$PW_EXPIRE
policyCategoryPasswordContent
policyContent
policyAttributePassword matches '.{$MIN_LENGTH,}+'
policyIdentifier
Has at least $MIN_LENGTH characters
policyParameters
minimumLength
$MIN_LENGTH
policyContent
policyAttributePassword matches '(.*[0-9].*){$MIN_NUMERIC,}+'
policyIdentifier
Has a number
policyParameters
minimumNumericCharacters
$MIN_NUMERIC
policyContent
policyAttributePassword matches '(.*[a-z].*){$MIN_ALPHA_LOWER,}+'
policyIdentifier
Has a lower case letter
policyParameters
minimumAlphaCharactersLowerCase
$MIN_ALPHA_LOWER
policyContent
policyAttributePassword matches '(.*[A-Z].*){$MIN_UPPER_ALPHA,}+'
policyIdentifier
Has an upper case letter
policyParameters
minimumAlphaCharacters
$MIN_UPPER_ALPHA
policyContent
policyAttributePassword matches '(.*[^a-zA-Z0-9].*){$MIN_SPECIAL_CHAR,}+'
policyIdentifier
Has a special character
policyParameters
minimumSymbols
$MIN_SPECIAL_CHAR
policyContent
none policyAttributePasswordHashes in policyAttributePasswordHistory
policyIdentifier
Does not match any of last $PW_HISTORY passwords
policyParameters
policyAttributePasswordHistoryDepth
$PW_HISTORY
" > /private/var/tmp/pwpolicy.plist #save the plist temp
chmod 777 /private/var/tmp/pwpolicy.plist
pwpolicy -u $user -clearaccountpolicies
pwpolicy -u $user -setaccountpolicies /private/var/tmp/pwpolicy.plist
fi
fi
done
rm /private/var/tmp/pwpolicy.plist
echo "Password policy successfully applied. Run \"sudo pwpolicy -u -getaccountpolicies\" to see it."
exit 0