Update Keychain Password Script

AdamCraig
Contributor III

An ongoing issue at many locations for AD bound macs is that if the users change their password incorrectly their keychain does not sync. 10.14.4 and up compounded this due to the 'update keychain' prompt not working and just creating a new keychain. For us we use User based network certs so a user getting a new keychain also means they can't get on the network or VPN.

I've written this script which is linked to a jamf Self Service policy that replaces the Login keychain with the old login-renamed-1 keychain. as well as updating the password and setting that to the default.

It prompts the user for the current and previous password and if the user gets both those right everything works great! However i'm trying to build in a test to verify that the users previous password is correct and that part is not working. Anyone know of a command line way to determine if a keychain is locked/unlocked?

Here is the entire script:

#!/bin/bash

##UPDATE KEYCHAIN PASSWORD

username=$( scutil <<< "show State:/Users/ConsoleUser" | awk -F': ' '/[[:space:]]+Name[[:space:]]:/ { if ( $2 != "loginwindow" ) { print $2 }}' )
loggedInUID=$(id -u "$username")

## Find the renamed keychains
renamed=""

for n in {1..9} ; do
    long="Users/$username/Library/Keychains/login_renamed_$n.keychain-db"
    short="login_renamed_$n.keychain-db"
    echo "$long"
    if [[ ! -f $long ]] ; then
        echo "Above Keychain not Found"
    else
        renamed="$long"
        short_renamed="$short"
        echo "renamed set to Above Keychain"
    fi
done

## If the rename keychain isn't found then exit

if [[ -z "$renamed" ]] ; then
    echo "Renamed keychain not found."
    dialog="Old keychain not found."
    cmd="Tell app "System Events" to display dialog "$dialog""
    /usr/bin/osascript -e "$cmd"
    exit 1
fi

#renamed=`echo ${renamed%???}`

## Prompt use for current password
currentPass=$(/usr/bin/osascript<<END
tell application "System Events"
activate
set the answer to text returned of (display dialog "Please enter your Current account Password:" default answer "" with hidden answer buttons {"Continue"} default button 1)
end tell
END)

previousPass=$(/usr/bin/osascript<<END
tell application "System Events"
activate
set the answer to text returned of (display dialog "Please enter your Previous account Password:" default answer "" with hidden answer buttons {"Continue"} default button 1)
end tell
END)

## Open the keychain to load it into keychain access
open "$renamed" &

sleep 2

## close keychain access
#killall Keychain Access

## unlock the previous keychain
expect -c "
spawn /bin/launchctl asuser $loggedInUID sudo -iu $username security unlock-keychain $short_renamed
expect "password to unlock $renamed"
send ${previousPass}
expect"

dialog="Testing access to old Keychain. If you are prompted for Keychain Password please press CANCEL!"
cmd="Tell app "System Events" to display dialog "$dialog""
/usr/bin/osascript -e "$cmd"

passwordTest=`/bin/launchctl asuser $loggedInUID sudo -iu "$username" security show-keychain-info "$short_renamed"`
echo "Password test = $passwordTest"

if [[ "$passwordTest" == *"User canceled the operation."* ]] ; then
    echo "Previous Password did not unlock keychain"
    dialog="Previous Account password did not unlock the old keychain."
    cmd="Tell app "System Events" to display dialog "$dialog""
    /usr/bin/osascript -e "$cmd"
    exit 1
fi

### If it gets this far the Previous Password is correct

## change the password to the previous keychain
expect -c "
spawn /bin/launchctl asuser $loggedInUID sudo -iu $username security set-keychain-password $short_renamed
expect "Old Password:"
send ${previousPass}
expect "New Password:"
send ${currentPass}
expect "Retype New Password:"
send ${currentPass}
expect"

## Make a keychain archive on the users desktop
mkdir /Users/$username/Desktop/Keychain Archive

## move the login keychain to the archive
mv /Users/$username/Library/Keychains/login.keychain-db /Users/$username/Desktop/Keychain Archive/login.keychain-db
## copy the renamed keychain to the archive
cp /Users/$username/Library/Keychains/$short_renamed /Users/$username/Desktop/Keychain Archive/$short_renamed
## wipe current keychain list
/bin/launchctl asuser $loggedInUID sudo -iu "$username" security list-keychains -s none
## rename the renamed keychain to login
mv $renamed /Users/$username/Library/Keychains/login.keychain-db
## add the login keychain to the list.
/bin/launchctl asuser $loggedInUID sudo -iu "$username" security list-keychains -s login.keychain-db

##unlock keychain
expect -c "
spawn /bin/launchctl asuser $loggedInUID sudo -iu $username security unlock-keychain login.keychain-db
expect "password to unlock $renamed"
send ${currentPass}
expect"

## set that keychain to the default keychain
result=$(/bin/launchctl asuser "$loggedInUID" sudo -iu "$username" security default-keychain -s "login.keychain-db")
if [[ -z $result ]] ; then
    dialog="Updating Old Keychain is complete. Recommended to verify keychain looks correct then reboot the computer"
else
    echo "$result"
    dialog="$result"
fi
cmd="Tell app "System Events" to display dialog "$dialog""
/usr/bin/osascript -e "$cmd"

exit 0

This is the bit in the middle that I thought would test the password, however even though terminal outputs "User canceled the operation" when you cancel the keychain prompt, it the $passwordTest variable is blank.

dialog="Testing access to old Keychain. If you are prompted for Keychain Password please press CANCEL!"
cmd="Tell app "System Events" to display dialog "$dialog""
/usr/bin/osascript -e "$cmd"

passwordTest=`/bin/launchctl asuser $loggedInUID sudo -iu "$username" security show-keychain-info "$short_renamed"`
echo "Password test = $passwordTest"

if [[ "$passwordTest" == *"User canceled the operation."* ]] ; then
    echo "Previous Password did not unlock keychain"
    dialog="Previous Account password did not unlock the old keychain."
    cmd="Tell app "System Events" to display dialog "$dialog""
    /usr/bin/osascript -e "$cmd"
    exit 1
fi

### If it gets this far the Previous Password is correct
1 ACCEPTED SOLUTION

AdamCraig
Contributor III

This now works correctly and will allow users/technicians to update/recover previously used keychains after the fact and will alert the user and exit if the old password is not entered correctly.

#!/bin/bash

##UPDATE KEYCHAIN PASSWORD

username=$( scutil <<< "show State:/Users/ConsoleUser" | awk -F': ' '/[[:space:]]+Name[[:space:]]:/ { if ( $2 != "loginwindow" ) { print $2 }}' )
loggedInUID=$(id -u "$username")

## Find the renamed keychains
renamed=""

for n in {1..9} ; do
    long="Users/$username/Library/Keychains/login_renamed_$n.keychain-db"
    short="login_renamed_$n.keychain-db"
    echo "$long"
    if [[ ! -f $long ]] ; then
        echo "Above Keychain not Found"
    else
        renamed="$long"
        short_renamed="$short"
        echo "renamed set to Above Keychain"
    fi
done

## If the rename keychain isn't found then exit

if [[ -z "$renamed" ]] ; then
    echo "Renamed keychain not found."
    dialog="Old keychain not found."
    cmd="Tell app "System Events" to display dialog "$dialog""
    /usr/bin/osascript -e "$cmd"
    exit 1
fi

#renamed=`echo ${renamed%???}`

## Prompt use for current password
currentPass=$(/usr/bin/osascript<<END
tell application "System Events"
activate
set the answer to text returned of (display dialog "Please enter your Current account Password:" default answer "" with hidden answer buttons {"Continue"} default button 1)
end tell
END)

previousPass=$(/usr/bin/osascript<<END
tell application "System Events"
activate
set the answer to text returned of (display dialog "Please enter your Previous account Password:" default answer "" with hidden answer buttons {"Continue"} default button 1)
end tell
END)

## Open the keychain to load it into keychain access
open "$renamed" &

sleep 2

## close keychain access
#killall Keychain Access

## unlock the previous keychain
unlock_result=`expect -c "
spawn /bin/launchctl asuser $loggedInUID sudo -iu $username security unlock-keychain $short_renamed
expect "password to unlock $renamed"
send ${previousPass}
expect"`

if [[ "$unlock_result" == *"The user name or passphrase you entered is not correct."* ]] ; then
    echo "Previous Password did not unlock keychain"
    dialog="Previous Account password did not unlock the old keychain."
    cmd="Tell app "System Events" to display dialog "$dialog""
    /usr/bin/osascript -e "$cmd"
    exit 1
fi

### If it gets this far the Previous Password is correct

## change the password to the previous keychain
expect -c "
spawn /bin/launchctl asuser $loggedInUID sudo -iu $username security set-keychain-password $short_renamed
expect "Old Password:"
send ${previousPass}
expect "New Password:"
send ${currentPass}
expect "Retype New Password:"
send ${currentPass}
expect"

## Make a keychain archive on the users desktop
mkdir /Users/$username/Desktop/Keychain Archive

## move the login keychain to the archive
mv /Users/$username/Library/Keychains/login.keychain-db /Users/$username/Desktop/Keychain Archive/login.keychain-db
## copy the renamed keychain to the archive
cp /Users/$username/Library/Keychains/$short_renamed /Users/$username/Desktop/Keychain Archive/$short_renamed
## wipe current keychain list
/bin/launchctl asuser $loggedInUID sudo -iu "$username" security list-keychains -s none
## rename the renamed keychain to login
mv $renamed /Users/$username/Library/Keychains/login.keychain-db
## add the login keychain to the list.
/bin/launchctl asuser $loggedInUID sudo -iu "$username" security list-keychains -s login.keychain-db

##unlock keychain
expect -c "
spawn /bin/launchctl asuser $loggedInUID sudo -iu $username security unlock-keychain login.keychain-db
expect "password to unlock $renamed"
send ${currentPass}
expect"

## set that keychain to the default keychain
result=$(/bin/launchctl asuser "$loggedInUID" sudo -iu "$username" security default-keychain -s "login.keychain-db")
if [[ -z $result ]] ; then
    dialog="Updating Old Keychain is complete. Recommended to verify keychain looks correct then reboot the computer"
else
    echo "$result"
    dialog="$result"
fi
cmd="Tell app "System Events" to display dialog "$dialog""
/usr/bin/osascript -e "$cmd"

exit 0

View solution in original post

1 REPLY 1

AdamCraig
Contributor III

This now works correctly and will allow users/technicians to update/recover previously used keychains after the fact and will alert the user and exit if the old password is not entered correctly.

#!/bin/bash

##UPDATE KEYCHAIN PASSWORD

username=$( scutil <<< "show State:/Users/ConsoleUser" | awk -F': ' '/[[:space:]]+Name[[:space:]]:/ { if ( $2 != "loginwindow" ) { print $2 }}' )
loggedInUID=$(id -u "$username")

## Find the renamed keychains
renamed=""

for n in {1..9} ; do
    long="Users/$username/Library/Keychains/login_renamed_$n.keychain-db"
    short="login_renamed_$n.keychain-db"
    echo "$long"
    if [[ ! -f $long ]] ; then
        echo "Above Keychain not Found"
    else
        renamed="$long"
        short_renamed="$short"
        echo "renamed set to Above Keychain"
    fi
done

## If the rename keychain isn't found then exit

if [[ -z "$renamed" ]] ; then
    echo "Renamed keychain not found."
    dialog="Old keychain not found."
    cmd="Tell app "System Events" to display dialog "$dialog""
    /usr/bin/osascript -e "$cmd"
    exit 1
fi

#renamed=`echo ${renamed%???}`

## Prompt use for current password
currentPass=$(/usr/bin/osascript<<END
tell application "System Events"
activate
set the answer to text returned of (display dialog "Please enter your Current account Password:" default answer "" with hidden answer buttons {"Continue"} default button 1)
end tell
END)

previousPass=$(/usr/bin/osascript<<END
tell application "System Events"
activate
set the answer to text returned of (display dialog "Please enter your Previous account Password:" default answer "" with hidden answer buttons {"Continue"} default button 1)
end tell
END)

## Open the keychain to load it into keychain access
open "$renamed" &

sleep 2

## close keychain access
#killall Keychain Access

## unlock the previous keychain
unlock_result=`expect -c "
spawn /bin/launchctl asuser $loggedInUID sudo -iu $username security unlock-keychain $short_renamed
expect "password to unlock $renamed"
send ${previousPass}
expect"`

if [[ "$unlock_result" == *"The user name or passphrase you entered is not correct."* ]] ; then
    echo "Previous Password did not unlock keychain"
    dialog="Previous Account password did not unlock the old keychain."
    cmd="Tell app "System Events" to display dialog "$dialog""
    /usr/bin/osascript -e "$cmd"
    exit 1
fi

### If it gets this far the Previous Password is correct

## change the password to the previous keychain
expect -c "
spawn /bin/launchctl asuser $loggedInUID sudo -iu $username security set-keychain-password $short_renamed
expect "Old Password:"
send ${previousPass}
expect "New Password:"
send ${currentPass}
expect "Retype New Password:"
send ${currentPass}
expect"

## Make a keychain archive on the users desktop
mkdir /Users/$username/Desktop/Keychain Archive

## move the login keychain to the archive
mv /Users/$username/Library/Keychains/login.keychain-db /Users/$username/Desktop/Keychain Archive/login.keychain-db
## copy the renamed keychain to the archive
cp /Users/$username/Library/Keychains/$short_renamed /Users/$username/Desktop/Keychain Archive/$short_renamed
## wipe current keychain list
/bin/launchctl asuser $loggedInUID sudo -iu "$username" security list-keychains -s none
## rename the renamed keychain to login
mv $renamed /Users/$username/Library/Keychains/login.keychain-db
## add the login keychain to the list.
/bin/launchctl asuser $loggedInUID sudo -iu "$username" security list-keychains -s login.keychain-db

##unlock keychain
expect -c "
spawn /bin/launchctl asuser $loggedInUID sudo -iu $username security unlock-keychain login.keychain-db
expect "password to unlock $renamed"
send ${currentPass}
expect"

## set that keychain to the default keychain
result=$(/bin/launchctl asuser "$loggedInUID" sudo -iu "$username" security default-keychain -s "login.keychain-db")
if [[ -z $result ]] ; then
    dialog="Updating Old Keychain is complete. Recommended to verify keychain looks correct then reboot the computer"
else
    echo "$result"
    dialog="$result"
fi
cmd="Tell app "System Events" to display dialog "$dialog""
/usr/bin/osascript -e "$cmd"

exit 0