#!/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