mind the explanatory gap

many a slip ‘twixt mind and lip…

mind the explanatory gap RSS Feed

Temporarily swapping user passwords in Open Directory

So something I find that I need to do quite often is to log in as a specific user, and I don’t always want to reset their password.

While AFP has a really useful function where you can allow admins of an AFP server to masquerade as a specific user by using the admin password, no other services really offer that same kind of functionality.

What I tend to do in these situations is to swap the Authentication Authority around. I keep a test user account around that I know the password to, and I swap its Authentication Authority with the user I need to login as.

As the Authentication Authority describes which Password Server slot contains the password for a given user, by swapping them around you are effectively swapping the passwords. If you’re in a nice Kerberized environment (and if you’re not, you should be…) then you’ll notice that this doesn’t actually swap the Kerberos passwords around. This is because in a standard Open Directory setup, there are actually two password stores, one for Password Server and one for Kerberos. Apple have done some nifty stuff behind the scenes to keep the two in sync when users change their passwords, but by swapping Authentication Authorities around, you’re not modifying the Kerberos passwords at all.

Anyway, here’s the script I use to swap authentication authorities around. I tend to save it as something like “swap_auth_authorities.sh”, and then you’d use it like:

./swap_auth_authorities.sh -n /LDAPv3/my.od.domain -a diradmin -p diradminpass  testone testtwo

which would swap the Authentication Authorities for the users “testone” and “testtwo”.

As always, don’t blame me if you blow up your server, and you should definitely try this on test accounts first…. You can use the command “/usr/libexec/chkpasswd testone” to test the passwords for each user. If you get “Sorry” back, the password is wrong, if you get nothing back, the password is correct.

Love that famed Apple user friendliness :)

Script follows, or you can download it here:

#!/bin/bash
#

directorynode="/LDAPv3/127.0.0.1"
adminusername="diradmin"

export PATH="/usr/bin"

show_usage() {
echo "This script will swap the authentication authorities of two users in a directory node."
echo usage: swap_auth_authorities [-h] [-n directorynode] [-a adminusername] [-p adminpassword] username1 username2 ...
echo
echo "-h help (this output)"
echo "-n directory node name (default: /LDAPv3/127.0.0.1)"
echo "-a directory admin username (default: diradmin)"
echo "-p directory admin password"
echo "username1 and username2 are the users you wish to swap authentication authorities for"
echo
echo "Note: If the admin password is not specified, you will be prompted for it a number of times."
}

show_password_prompt() {
  if [ ${#adminpassword} -eq 0 ]; then
    echo "Enter the password for $adminusername"
  fi
}

while getopts  "hn:a:p:" flag; do
  # echo "$flag" $OPTIND $OPTARG
  case "$flag" in
    h) show_usage; exit ;;
    n) directorynode="$OPTARG" ;;
    a) adminusername="$OPTARG" ;;
    p) adminpassword="$OPTARG" ;;
    ?) echo >&2 "Illegal option '$OPTARG'"; exit 1 ;;
  esac
done
shift $(($OPTIND -1 ))

if [ $# -ne 2 ]; then
  echo >&2 "Error: You should only pass two additional parameters, the usernames whose authentication authorities are to be swapped"
  echo
  show_usage
  exit 1
fi

if [ ${#adminpassword} -eq 0 ]; then
  authstring="-u $adminusername -p"
  echo "You will now be prompted several times for the password for $adminusername"
else
  authstring="-u $adminusername -P $adminpassword"
fi

show_password_prompt
authority1=$(dscl $authstring $directorynode -read /Users/$1 AuthenticationAuthority | sed 's|^AuthenticationAuthority: ||g')

# check to see if users exist or permission denied.
if [ $? -ne 0 ]; then
  case $? in
    71 ) echo "User $1 not found in $directorynode"; exit 1 ;;
  esac
fi

# dscl really should return an error code in these cases...
if [ $(echo $authority1 | grep -c "Data source ($directorynode) is not valid.") -gt 0 ]; then
  echo "There is a problem with either your admin username/password combination, or the specified directory node"
  exit 1;
fi

show_password_prompt
authority2=$(dscl $authstring $directorynode -read /Users/$2 AuthenticationAuthority | sed 's|^AuthenticationAuthority: ||g')

# check to see if users exist or permission denied.
if [ $? -ne 0 ]; then
  case $? in
    71 ) echo "User $2 not found in $directorynode"; exit 1 ;;
  esac
fi

show_password_prompt
dscl $authstring $directorynode -create /Users/$1 AuthenticationAuthority "$authority2"

show_password_prompt
dscl $authstring $directorynode -create /Users/$2 AuthenticationAuthority "$authority1"

echo "The authentication authorities for $1 and $2 have been swapped."
echo "Note that Kerberos authentication will continue to use the old passwords."
echo "If you re-run this command, the authentication authorities will be swapped back again."

6 Responses to “Temporarily swapping user passwords in Open Directory”

  1. nigel kersten Says:

    Testing comments…

  2. Jeff McCune Says:

    This is a test of the emergency broadcast system.
    This is only a test.
    This concludes the test of the emergency broadcast system.

  3. Ed Marczak Says:

    Yeah - this is one of my favorites! I do somthing very similar…although, I haven’t gotten around to scripting it (I’ve sadly been using WGM and editing the LDAP record directly). Leaves people’s jaw agape when they see it in action, though…two factor authentication can’t become truly mainstream quickly enough.

    erm

  4. systemsboy Says:

    Neat-O! Thanks!

    -systemsboy

  5. NYC Says:

    I don’t even understand the effect you are trying to produce.

  6. Bryan Says:

    Perfect! This comes in handy when I have to set up a vacation reply or forward for a (incapable) user with Avelsieve in Squirrelmail, and I don’t want to know or change their password.

Leave a Reply