#!/bin/bash
# TSID PAM setup script
# Replaces PAM configuration files for TSID PIN authentication

# UTF-8 locale settings
export LANG=C.UTF-8
export LC_ALL=C.UTF-8

set -e

# Color definitions
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# Log functions
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# Check root privileges
check_root() {
    if [ "$EUID" -ne 0 ]; then
        log_error "This script must be run as root."
        exit 1
    fi
}

# Backup function
backup_file() {
    local file="$1"
    local backup="${file}.tsid.backup.$(date +%Y%m%d_%H%M%S)"
    
    if [ -f "$file" ]; then
        cp "$file" "$backup"
        log_info "Backup created: $backup"
    fi
}

# Update SSH configuration
setup_ssh_pam() {
    local sshd_config="/etc/ssh/sshd_config"
    local sshd_pam="/etc/pam.d/sshd"
    
    log_info "Configuring SSH for TSID PIN-only authentication..."
    
    # Backup SSH config
    backup_file "$sshd_config"
    backup_file "$sshd_pam"
    
    # Replace SSH config with TSID-only config
    if [ -f "/etc/ssh/sshd_config-tsid" ]; then
        cp /etc/ssh/sshd_config-tsid "$sshd_config"
        log_success "SSH config updated to TSID PIN authentication."
    else
        log_warning "SSH TSID config file not found."
    fi
    
    # Replace SSH PAM config with TSID config
    if [ -f "/etc/pam.d/sshd-tsid" ]; then
        cp /etc/pam.d/sshd-tsid "$sshd_pam"
        log_success "SSH PAM config updated to TSID PIN authentication."
    else
        log_warning "SSH PAM TSID config file not found."
    fi
    
    # Restart SSH service
    if systemctl is-active --quiet ssh || systemctl is-active --quiet sshd; then
        log_info "Restarting SSH service..."
        systemctl restart ssh 2>/dev/null || systemctl restart sshd 2>/dev/null || true
        log_success "SSH service restarted."
    fi
}

# Update common auth (SSH PAM only, keep common-auth unchanged)
setup_common_auth() {
    # common-auth affects TTY/GUI login too, so leave it unchanged
    # Only /etc/pam.d/sshd is changed to TSID PIN
    log_info "common-auth will keep existing password authentication."
    log_info "Only SSH PAM config will be changed to TSID PIN authentication."
}

# Update login config (keep local login with existing password)
setup_login() {
    # Keep existing password auth for local TTY/GUI login
    # Do not change login PAM to prevent system lockout
    log_info "Local login (TTY/GUI) will keep existing password authentication."
    log_info "Only SSH access will be changed to TSID PIN authentication."
}

# Check PAM module installation
check_pam_module() {
    local module_path=""
    local os_config="/etc/tsid/os-config"
    
    # Read OS configuration to determine correct path
    if [ -f "$os_config" ]; then
        local display_manager=$(grep "^TSID_DISPLAY_MANAGER=" "$os_config" | cut -d= -f2)
        
        if [ "$display_manager" = "gdm" ]; then
            # Rocky Linux uses /usr/lib64/security/
            module_path="/usr/lib64/security/pam_tsid.so"
        else
            # Ubuntu/Debian uses /lib/x86_64-linux-gnu/security/
            module_path="/lib/x86_64-linux-gnu/security/pam_tsid.so"
        fi
    else
        # Fallback: try Ubuntu path first, then Rocky path
        if [ -f "/lib/x86_64-linux-gnu/security/pam_tsid.so" ]; then
            module_path="/lib/x86_64-linux-gnu/security/pam_tsid.so"
        elif [ -f "/usr/lib64/security/pam_tsid.so" ]; then
            module_path="/usr/lib64/security/pam_tsid.so"
        else
            log_error "TSID PAM module not found in either location"
            log_info "Searched: /lib/x86_64-linux-gnu/security/pam_tsid.so"
            log_info "Searched: /usr/lib64/security/pam_tsid.so"
            log_info "Please compile and install the PAM module first:"
            log_info "  cd src && make install"
            exit 1
        fi
    fi
    
    if [ ! -f "$module_path" ]; then
        log_error "TSID PAM module not found: $module_path"
        log_info "Please compile and install the PAM module first:"
        log_info "  cd src && make install"
        exit 1
    fi
    
    log_success "TSID PAM module found at: $module_path"
}

# Verify configuration
verify_setup() {
    log_info "Verifying PAM configuration..."
    
    # Verify config files
    local config_files=(
        "/etc/pam.d/common-auth"
        "/etc/pam.d/sshd"
        "/etc/pam.d/login"
    )
    
    for file in "${config_files[@]}"; do
        if [ -f "$file" ] && grep -q "pam_tsid.so" "$file"; then
            log_success "TSID authentication configured in $file."
        else
            log_warning "TSID authentication not configured in $file."
        fi
    done
}

# Rollback configuration
rollback_setup() {
    log_info "Rolling back TSID PAM configuration..."
    
    # Find backup files
    local backup_files
    backup_files=$(find /etc -name "*.tsid.backup.*" 2>/dev/null)
    
    if [ -z "$backup_files" ]; then
        log_info "No backup files found to rollback."
        return 0
    fi
    
    for backup in $backup_files; do
        local original="${backup%.tsid.backup.*}"
        original="${original%.*}"
        
        log_info "Restoring: $original"
        cp "$backup" "$original"
        rm "$backup"
    done
    
    # Restart SSH service
    if systemctl is-active --quiet ssh || systemctl is-active --quiet sshd; then
        systemctl restart ssh 2>/dev/null || systemctl restart sshd 2>/dev/null || true
    fi
    
    log_success "Configuration rollback completed."
}

# Show usage
show_usage() {
    echo "Usage: $0 [options]"
    echo
    echo "Options:"
    echo "  -h, --help     Show this help message"
    echo "  -s, --setup    Configure TSID PAM settings"
    echo "  -r, --rollback Rollback TSID PAM settings"
    echo "  -v, --verify   Verify current configuration"
    echo
    echo "Setup:"
    echo "  Adds TSID PIN authentication to SSH, login, and common-auth"
    echo
    echo "Rollback:"
    echo "  Restores previous configuration"
}

# Main function
main() {
    case "${1:-}" in
        -h|--help)
            show_usage
            ;;
        -s|--setup)
            check_root
            check_pam_module
            setup_common_auth
            setup_ssh_pam
            setup_login
            verify_setup
            log_success "TSID PAM configuration completed!"
            echo
            echo "You can now log in with PIN only:"
            echo "  SSH: ssh 192.168.1.100 (no username required)"
            echo "  Local: enter PIN at console"
            echo
            echo "After entering PIN, complete authentication on your mobile device."
            echo "You will be automatically logged in with the user info from the server."
            ;;
        -r|--rollback)
            check_root
            rollback_setup
            ;;
        -v|--verify)
            verify_setup
            ;;
        "")
            log_error "An option is required."
            echo
            show_usage
            exit 1
            ;;
        *)
            log_error "Unknown option: $1"
            echo
            show_usage
            exit 1
            ;;
    esac
}

# Call main only when script is executed directly
if [ "${BASH_SOURCE[0]}" == "${0}" ]; then
    main "$@"
fi
