開發模擬 su 命令的 Shell 腳本時,核心難點在於:
/etc/shadow 中存儲的加密密文進行比對Linux 系統使用 crypt(3) 函數族進行密碼加密驗證。/etc/shadow 中的密碼條目格式為:
$id$salt$encrypted
$id$:標識加密算法($1$=MD5, $5$=SHA-256, $6$=SHA-512, $y$=yescrypt 等)$salt$:隨機鹽值$encrypted$:經過鹽值混合加密後的密文openssl passwd(推薦)#!/bin/bash
read -s -p "Password: " input_pass
echo
# 從 /etc/shadow 提取目標用戶的加密條目
stored_hash=$(sudo getent shadow "$USER" | cut -d: -f2)
# 使用 openssl 驗證(自動解析算法、鹽值)
if openssl passwd -stdin -verify "$stored_hash" <<< "$input_pass" >/dev/null; then
echo "驗證通過"
# 執行 su 或 sudo 切換用戶上下文
else
echo "密碼錯誤"
fi
# Perl 版本
perl -e 'use Authen::PAM; ...' # 需安裝模塊
# Python 版本(標準庫即可)
python3 -c "
import crypt, pwd, sys
user = pwd.getpwnam('$USER')
if crypt.crypt(sys.argv[1], user.pw_passwd) == user.pw_passwd:
sys.exit(0)
else:
sys.exit(1)
" "$input_pass"
單純驗證密碼不會自動改變進程的用戶身份。要實現真正的登錄切換,必須調用系統調用:
setuid(uid) / setgid(gid):設置進程有效 UID/GIDexecve():啟動新的 Shell 進程(如 /bin/bash)在 Shell 腳本中,通常直接調用 su - $USER 或 sudo -u $USER 由成熟工具完成上下文切換,而非自行實現。
read -s 關閉回顯unsetsu/sudo/pam 成熟機制更多實現細節可參考:CSDN 相關討論