Dan
Dan

Reputation: 951

Echoing variable properly within Bash script

Per the following, I'm trying to obfuscate a password within a script

Hide/encrypt password in bash file to stop accidentally seeing it

However, because this password has non-alpha numeric characters in it, I don't think the variable "$MYPASS" echoing out properly in the second to last line of the script

My script:

#!/bin/bash
PATH=/bin:/usr/bin:/sbin:/usr/sbin export PATH
MYENCPASS='IURv34bmNocv98RnZXQhCg=='
MYPASS=`echo "$MYENCPASS" | base64 --decode`

echo
echo Enter username you\'d like to change password for:
read USERNAME
dscl /LDAPv3/127.0.0.1 -read /Users/$USERNAME >/dev/null 2>&1

if [ "$?" != "0" ]; then

echo
echo -e "\033[31m Username $USERNAME does not exist! Exiting..."
echo -e "\033[0m"
exit 1
fi

echo
echo Enter New Password for "$USERNAME"
read PASSWORD
dscl -u diradmin -P "$MYPASS" /LDAPv3/127.0.0.1 passwd /Users/$USERNAME $PASSWORD
echo Password successfully changed for $USERNAME to $PASSWORD at `date` | tee -a /var/log/odpasswd.log

Your ideas/suggestions are most appreciated!

Thanks, Dan

Upvotes: 3

Views: 270

Answers (1)

Charles Duffy
Charles Duffy

Reputation: 295363

First, you need to quote your parameter to echo to avoid string-splitting and glob expansion:

echo "Password successfully changed for $USERNAME to $PASSWORD at `date`"

Second, if you want to emit the password in a machine-parsable form, use printf %q:

printf 'Password successfully changed for %s to %q at %s\n' \
  "$USERNAME" "$PASSWORD" "$(date)"

As an aside -- it's bad practice to use all-uppercase names for local variables (as it risks namespace conflicts with built-in and environment variables).


A complete version of your script, making a stronger attempt to follow best practices around scripting (but still failing horribly to follow any kind of good practices around security), would look something like this:

#!/bin/bash

# you probably don't need to export PATH -- if something is already exported,
# it stays exported on updates.
PATH=/bin:/usr/bin:/sbin:/usr/sbin

## this is really, _really_ horrible "security".
myencpass='IURv34bmNocv98RnZXQhCg=='
mypass=$(base64 --decode <<<"$myencpass")

echo
echo "Enter username you'd like to change password for:"
read -r username
if ! dscl /LDAPv3/127.0.0.1 -read "/Users/$username" &>/dev/null; then
  # This is bad practice -- assuming that the only error that can happen is
  # the nonexistent-user case, and hiding any other error messages, means that
  # the user can't diagnose the _actual_ cause of any other error.
  printf '\n\033[31m Username %s does not exist! Exiting...\033[0m\n' "$username"
  exit 1
fi

printf '\nEnter New Password for %s\n' "$username"
read -r password
if dscl -u diradmin -P "$mypass" /LDAPv3/127.0.0.1 passwd "/Users/$username" "$password"; then
  # previously, there was no conditional here, so we logged that this was
  # successful even if it failed.
  # And, of course, storing users' plaintext passwords in a log makes you evil.
  printf "Password successfully changed for %s to %q at %s\n" \
    "$username" "$password" "$(date)" \
    | tee -a /var/log/odpasswd.log
fi

If you wanted to actually do this The Right Way, instead of trying this kind of obfuscation technique you'd authenticate to LDAP with, say, a cached Kerberos ticket (I'm assuming this is MacOS's Open Directory -- it can do that), readable only by the user the script runs as, and use sudo to allow temporary privilege escalation to the user who can read the ticket only when running this script.

Upvotes: 3

Related Questions