#!/bin/bash
echo "--- 安全配置检查脚本（只读模式） ---"
echo "本脚本用于检查密码复杂度、账户锁定策略及密码过期设置。"
echo "脚本不会修改任何配置文件。"
echo
# 检查root权限（查看其他用户密码过期设置时需要）
if [ "$EUID" -ne 0 ]; then
  echo "警告：当前未以root权限运行。部分检查（如其他用户的密码过期设置）可能无法执行。"
  echo "建议使用'sudo'运行此脚本以获取完整信息。"
  echo
fi
# --- 1. 密码复杂度检查 (/etc/security/pwquality.conf) ---
echo "[1] 正在检查密码复杂度设置..."
PWQUALITY_CONF="/etc/security/pwquality.conf"
if [ -f "$PWQUALITY_CONF" ]; then
  echo "  配置文件路径: $PWQUALITY_CONF"
  
  # 辅助函数：检查并打印参数值
  check_pw_param() {
    local param_name=$1
    local file=$2
    local value=$(grep "^${param_name}=" "$file" | cut -d'=' -f2 | tr -d ' ')
    if [ -n "$value" ]; then
      echo "    - $param_name: $value"
    else
      local commented_value=$(grep "^#\s*${param_name}=" "$file" | cut -d'=' -f2 | tr -d ' ')
      if [ -n "$commented_value" ]; then
         echo "    - $param_name: 未设置（默认或已注释: $commented_value）"
      else
         echo "    - $param_name: 未设置"
      fi
    fi
  }
  
  # 辅助函数：检查布尔型参数（如dictcheck=1）
  check_pw_flag_param() {
      local param_name=$1
      local file=$2
      local line=$(grep "^${param_name}" "$file")
       if [[ -n "$line" && ! "$line" =~ ^# ]]; then
           local value=$(echo "$line" | cut -d'=' -f2 | tr -d ' ')
           if [ "$value" == "1" ]; then
                echo "    - $param_name: 已启用（值: $value）"
           else
                echo "    - $param_name: 已显式设置（值: $value）- 如需启用请确认应设为'1'"
           fi
       elif [[ -n "$line" && "$line" =~ ^# ]]; then
            echo "    - $param_name: 已禁用（已注释）"
       else
            echo "    - $param_name: 未显式设置（使用默认值）"
       fi
  }
  # 检查具体参数
  check_pw_param "minlen" "$PWQUALITY_CONF"
  check_pw_param "minclass" "$PWQUALITY_CONF"
  check_pw_flag_param "dictcheck" "$PWQUALITY_CONF"
  check_pw_flag_param "usercheck" "$PWQUALITY_CONF"
  check_pw_flag_param "palindrome" "$PWQUALITY_CONF" # 假设'palindrome=1'表示启用
  # 检查similarcheck（处理#no_similar_check的特殊逻辑）
  if grep -q "^#no_similar_check" "$PWQUALITY_CONF"; then
      echo "    - similar_check: 已启用（通过'#no_similar_check'）"
  elif grep -q "^no_similar_check" "$PWQUALITY_CONF"; then
       echo "    - similar_check: 已禁用（通过'no_similar_check'）"
  elif grep -q "^similarcheck=" "$PWQUALITY_CONF"; then
        check_pw_flag_param "similarcheck" "$PWQUALITY_CONF"
  else
       echo "    - similar_check: 未显式设置（使用默认值）"
  fi
else
  echo "  错误：未找到配置文件 $PWQUALITY_CONF"
fi
echo
# --- 2. 账户锁定策略检查 (/etc/pam.d/common-auth) ---
echo "[2] 正在检查账户锁定策略..."
PAM_FILES=("/etc/pam.d/common-auth" "/etc/pam.d/system-auth" "/etc/pam.d/password-auth")
FOUND_PAM_LOCKOUT=false
for PAM_FILE in "${PAM_FILES[@]}"; do
  if [ -f "$PAM_FILE" ]; then
    echo "  检查文件: $PAM_FILE"
    # 查找包含锁定参数的pam_unix.so
    PAM_UNIX_LINE=$(grep "pam_unix.so" "$PAM_FILE" | grep -v "^#")
    if echo "$PAM_UNIX_LINE" | grep -q "deny="; then
      echo "    发现pam_unix.so锁定设置:"
      LOCKOUT_PARAMS=$(echo "$PAM_UNIX_LINE" | grep -oE 'deny=[0-9]+|unlock_time=[0-9]+|root_unlock_time=[0-9]+')
      if [ -n "$LOCKOUT_PARAMS" ]; then
           echo "      参数: $LOCKOUT_PARAMS"
      else
           echo "      找到参数但格式不符，原始行:"
           echo "        $PAM_UNIX_LINE"
      fi
      FOUND_PAM_LOCKOUT=true
    fi
    # 检查替代锁定模块pam_faillock/pam_tally2
    PAM_FAILLOCK_LINE=$(grep "pam_faillock.so" "$PAM_FILE" | grep -v "^#")
     if [ -n "$PAM_FAILLOCK_LINE" ]; then
        echo "    发现pam_faillock.so设置（替代锁定机制）:"
        echo "      配置行: $PAM_FAILLOCK_LINE"
        FOUND_PAM_LOCKOUT=true
     fi
     PAM_TALLY2_LINE=$(grep "pam_tally2.so" "$PAM_FILE" | grep -v "^#")
     if [ -n "$PAM_TALLY2_LINE" ]; then
        echo "    发现pam_tally2.so设置（旧版锁定机制）:"
        echo "      配置行: $PAM_TALLY2_LINE"
        FOUND_PAM_LOCKOUT=true
     fi
  else
    echo "  提示：未找到文件 $PAM_FILE，跳过检查"
  fi
done
if [ "$FOUND_PAM_LOCKOUT" = false ]; then
  echo "  未在检查文件中发现常见PAM锁定设置（pam_unix.so的deny=参数、pam_faillock.so或pam_tally2.so）"
fi
echo
# --- 3. 密码过期设置检查 ---
echo "[3] 正在检查密码过期策略..."
# 3a. 新用户默认设置 (/etc/login.defs)
echo "  检查新用户默认设置 (/etc/login.defs):"
LOGIN_DEFS_FILE="/etc/login.defs"
if [ -f "$LOGIN_DEFS_FILE" ]; then
  MAX_DAYS=$(grep -E "^PASS_MAX_DAYS\s+" "$LOGIN_DEFS_FILE" | awk '{print $2}')
  MIN_DAYS=$(grep -E "^PASS_MIN_DAYS\s+" "$LOGIN_DEFS_FILE" | awk '{print $2}')
  WARN_AGE=$(grep -E "^PASS_WARN_AGE\s+" "$LOGIN_DEFS_FILE" | awk '{print $2}')
  echo "    - PASS_MAX_DAYS (最长有效期): ${MAX_DAYS:-未设置或已注释}"
  echo "    - PASS_MIN_DAYS (最短有效期): ${MIN_DAYS:-未设置或已注释}"
  echo "    - PASS_WARN_AGE (过期提醒): ${WARN_AGE:-未设置或已注释}"
else
  echo "    错误：未找到配置文件 $LOGIN_DEFS_FILE"
fi
echo
# 3b. 现有用户设置检查（使用chage命令）
echo "  检查现有用户设置（需要root/sudo权限）:"
# 检查root用户
echo "    - 用户: root"
if command -v chage &> /dev/null; then
    if [ "$EUID" -eq 0 ]; then
        MAX_DAYS_ROOT=$(sudo chage -l root | grep "Maximum number of days between password change" | cut -d: -f2 | tr -d ' ')
        echo "      密码最长有效期: ${MAX_DAYS_ROOT:-读取值失败}"
    else
        echo "      跳过root用户检查（需要sudo权限）"
    fi
else
    echo "      未找到'chage'命令，无法检查现有用户"
fi
# 检查sudo执行者（非root用户）
if [ -n "$SUDO_USER" ] && [ "$SUDO_USER" != "root" ]; then
    echo "    - 用户: $SUDO_USER (sudo执行用户)"
     if command -v chage &> /dev/null && [ "$EUID" -eq 0 ]; then
        MAX_DAYS_SUDOER=$(sudo chage -l "$SUDO_USER" | grep "Maximum number of days between password change" | cut -d: -f2 | tr -d ' ')
        echo "      密码最长有效期: ${MAX_DAYS_SUDOER:-读取值失败}"
     else
         echo "      跳过$SUDO_USER检查（需要sudo权限和chage命令）"
     fi
fi
echo
echo "--- 检查完成 ---"
exit 0