在Bash脚本中正确回显变量

时间:2013-07-13 16:21:37

标签: macos bash shell

根据以下内容,我试图在脚本中混淆密码

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

但是,由于此密码中包含非字母数字字符,因此我不认为变量" $ MYPASS"在脚本的倒数第二行正确回显

我的剧本:

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

非常感谢您的想法/建议!

谢谢,Dan

1 个答案:

答案 0 :(得分:3)

首先,您需要引用参数echo以避免字符串拆分和glob扩展:

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

其次,如果您想以机器可解析的形式发出密码,请使用printf %q

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

顺便说一句,对局部变量使用全大写的名称是不好的做法(因为它会冒内置命令与环境变量的冲突)。


您的脚本的完整版本,更强烈地尝试遵循脚本编写的最佳实践(但仍然可靠地遵循任何关于安全性的良好实践),看起来像这样:

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

如果你想真正做到这一点正确的方法,而不是尝试这种混淆技术,你可以使用缓存的Kerberos票证对LDAP进行身份验证(我假设这是MacOS的开放目录 - - 它可以这样做),只能由脚本运行的用户读取,并使用sudo允许临时权限升级给只能在运行此脚本时才能读取票证的用户。