Last active
January 25, 2017 21:26
-
-
Save haircut/21a74c7c7728b2d5a0f1b20035fc4fac to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
##################################### | |
# | |
# Keychain Repair | |
# | |
# Removes a User's login keychain, creates a new login keychain, sets it | |
# as the default keychain, deletes any Local Items keychain folders, | |
# then reboots the system interactively | |
# | |
# University of North Carolina Asheville ITS | |
# contact <bmwarren@unca.edu> | |
# author: Matthew Warren | |
# created: 2014-09-06 | |
# modified: 2017-01-03 | |
# | |
##################################### | |
# Location of cocoaDialog binary | |
ccd="/path/to/cocoaDialog.app/Contents/MacOS/cocoaDialog" | |
# Make sure cocoaDialog is installed; if not, attempt to fix it via policy | |
if [[ ! -f "${ccd}" ]]; then | |
echo "Keychain Repair: Attempting to install cocoaDialog via policy" | |
/usr/local/jamf/bin/jamf policy -forceNoRecon -event InstallCocoaDialog | |
if [[ ! -f "${ccd}" ]]; then | |
echo "Keychain Repair: Unable to install cocoaDialog, so we need to quit" | |
exit 1 | |
else | |
echo "Keychain Repair: cocoaDialog is now installed" | |
fi | |
fi | |
# Get the current User | |
User=`python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "\n");'` | |
# Get the current user's home directory | |
UserHomeDirectory=$(/usr/bin/dscl . -read Users/"${User}" NFSHomeDirectory | awk '{print $2}') | |
# Prompt the User about what is about to happen and confirm intent | |
confirmContinue=($("${ccd}" msgbox --icon stop --title "Keychain Repair" --text "Are you sure you want to continue?" --informative-text "This utility will close all open applications and restart this computer. If you'd like to continue, click 'Repair' below." --float --button1 "Repair" --button2 "Cancel")) | |
# If User confirms their intent we'll continue. For cases where the User | |
# cancels the policy should still complete "successfully" and | |
# be logged that way in Casper since it's not an explicit failure | |
# so we will exit successfully regardless of the choice | |
if [[ ${confirmContinue[0]} -eq "1" ]]; then | |
# Get the current User's default (login) keychain | |
CurrentKeychain=$(su "${User}" -c "security list-keychains" | grep login | sed -e 's/\"//g' | sed -e 's/\// /g' | awk '{print $NF}') | |
if [[ -z $CurrentKeychain ]]; then | |
echo "Keychain Repair: Unable to find a login keychain for User $User" | |
else | |
echo "Keychain Repair: Found $UserHomeDirectory/Library/Keychains/${CurrentKeychain} - deleting" | |
mv $UserHomeDirectory/Library/Keychains/$CurrentKeychain $UserHomeDirectory/Library/Keychains/$User.keychain.bkp | |
fi | |
# Make a new login keychain | |
# Prompt for account password | |
rv=($("${ccd}" secure-standard-inputbox --icon-file /Applications/Utilities/Keychain\ Access.app/Contents/Resources/Keychain.icns --title "Password" --no-newline --informative-text "Enter your current login password:")) | |
PASSWORD=${rv[1]} | |
# Prompt again for password to confirm | |
rv2=($("${ccd}" secure-standard-inputbox --icon-file /Applications/Utilities/Keychain\ Access.app/Contents/Resources/Keychain.icns --title "Password" --no-newline --informative-text "Verify your login password by entering it again:")) | |
PASSWORD2=${rv2[1]} | |
# Ensure passwords match | |
if [[ "${PASSWORD}" != "${PASSWORD2}" ]]; then | |
# Confirm with User that they'd like to continue | |
"${ccd}" msgbox --icon stop --title "Keychain Repair" --text "Password mismatch!" --informative-text "The two passwords you entered do not match. Please close this utility and restart from it from Self Service." --float --button1 "Close" | |
exit 0 | |
fi | |
# Create the new login keychain | |
expect <<- DONE | |
set timeout -1 | |
spawn su "${User}" -c "security create-keychain login.keychain" | |
# Look for prompt | |
expect "*?chain:*" | |
# send User entered password from CocoaDialog | |
send "$PASSWORD\n" | |
expect "*?chain:*" | |
send "$PASSWORD\r" | |
expect EOF | |
DONE | |
#Set the newly created login.keychain as the Users default keychain | |
su "${User}" -c "security default-keychain -s login.keychain" | |
#Unset timeout/lock behavior | |
su "${User}" -c "security set-keychain-settings login.keychain" | |
# Current user's Local Items keychain | |
LocalItemsKeychainHash=$(ls "${UserHomeDirectory}"/Library/Keychains/ | egrep '([A-Z0-9]{8})((-)([A-Z0-9]{4})){3}(-)([A-Z0-9]{12})') | |
if [[ -z $LocalItemsKeychainHash ]]; then | |
echo "Keychain Repair: Unable to find a Local Items keychain" | |
else | |
echo "Keychain Repair: Deleting ${UserHomeDirectory}/Library/Keychains/${LocalItemsKeychainHash}" | |
rm -rf ${UserHomeDirectory}/Library/Keychains/${LocalItemsKeychainHash} | |
fi | |
# All done, warn the user the system is rebooting, send the command and exit | |
"${ccd}" ok-msgbox --title "Keychain Repair" --text "Keychain Repair Complete" --informative-text "The Keychain Repair utility has repaired your keychain. This device must now reboot to complete the process. Please log back in with your current credentials once the system is back online." --icon sync --float --no-cancel | |
exit 0 | |
else | |
echo "Keychain Repair: User '${User}' decided to cancel" | |
exit 0 | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Requires cocoaDialog installed to a known location.
Deletes the current user's login keychain (after creating a backup – duh!), re-creates it, and removes the Local Items keychain.
Because we're deleting the Local Items keychain...and just for good measure...you should force a reboot after the completion of this script. I use the "Reboot" options in a Self Service policy to enforce the reboot.