#!/bin/bash # Define constants SSH_CONFIG_FILE="/etc/ssh/sshd_config" AUTH_LINE="PasswordAuthentication" # --- Function to check the current state --- get_current_state() { # Search the file, handle lines commented out with #, and extract the effective value. # The 'yq' tool (or similar) is ideal for YAML/JSON, but 'grep' is standard for config files. # We use a pattern that handles optional whitespace and comments. # 1. Use grep to find the line, ignoring comments that start the line # 2. Use sed to remove leading/trailing whitespace and the setting name # 3. Use tr to convert to lowercase for reliable comparison CURRENT_STATE=$(grep -iP "^\s*#?\s*${AUTH_LINE}\s+" "$SSH_CONFIG_FILE" | \ sed -E "s/^\s*#?\s*${AUTH_LINE}\s*//" | \ tr '[:upper:]' '[:lower:]' | \ head -n 1) # If the line is not found, or is commented out/blank, default to 'no' (SSH default security) if [[ -z "$CURRENT_STATE" || "$CURRENT_STATE" == "no" ]]; then echo "no" elif [[ "$CURRENT_STATE" == "yes" ]]; then echo "yes" else # Handle cases where the setting is missing, which usually defaults to 'no' # but check for an explicit 'no' in the file. if grep -qP "^\s*${AUTH_LINE}\s+no" "$SSH_CONFIG_FILE"; then echo "no" else echo "no" # Defaulting to the most secure setting if not explicitly 'yes' fi fi } # --- Main Toggler Logic --- current=$(get_current_state) if [ "$current" == "yes" ]; then NEW_STATE="no" ACTION="DISABLE" WARNING="WARNING: This will DISABLE password authentication and only allow SSH keys!" elif [ "$current" == "no" ]; then NEW_STATE="yes" ACTION="ENABLE" WARNING="DANGER: This will ENABLE password authentication, increasing brute-force risk!" else echo "Error: Could not determine current state of $AUTH_LINE." exit 1 fi echo "---" echo "Current state of ${AUTH_LINE} is: **$current**" echo "$WARNING" read -r -p "Do you want to $ACTION password authentication? (y/N): " response if [[ "$response" =~ ^([yY])$ ]]; then echo "Applying changes..." # Use 'sed' for safe, idempotent change with a backup # 1. Substitute any existing line with the new one. sudo sed -i.bak -E "s/^\s*#?\s*${AUTH_LINE}\s+(yes|no)/${AUTH_LINE} ${NEW_STATE}/" "$SSH_CONFIG_FILE" # 2. If the line was missing or not matched (a rare edge case), ensure it is added if ! grep -qP "^\s*${AUTH_LINE}\s+${NEW_STATE}" "$SSH_CONFIG_FILE"; then echo "${AUTH_LINE} ${NEW_STATE}" | sudo tee -a "$SSH_CONFIG_FILE" > /dev/null fi # Restart the SSH service echo "Restarting sshd to apply the new configuration..." if command -v systemctl &> /dev/null; then sudo systemctl restart sshd || sudo systemctl restart ssh elif [ -f /etc/init.d/sshd ]; then sudo /etc/init.d/sshd restart else echo "Error: Could not find a command to restart the SSH service. Please restart it manually." exit 1 fi # Final verification new_current=$(get_current_state) echo "Verification: New state of ${AUTH_LINE} is: **$new_current**" if [ "$new_current" == "$NEW_STATE" ]; then echo "SUCCESS: Configuration changed and service restarted." else echo "FAILURE: Configuration change failed to verify." fi else echo "Action cancelled by user." fi