#!/bin/bash
#
# Attack Signature Auto-Updater
# Downloads latest ET Open rules and extracts HTTP-level attack patterns
#
# Usage: bash update-attack-signatures.sh
# Can be run manually or via cron (weekly recommended)

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LIB_DIR="$SCRIPT_DIR/../lib"
BACKUP_DIR="$SCRIPT_DIR/../backups/signatures"
TEMP_DIR="/tmp/et-rules-update-$$"

# ET Open ruleset URL
ET_RULES_URL="https://rules.emergingthreats.net/open/suricata-7.0.0/emerging.rules.tar.gz"

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

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

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

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

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

# Cleanup on exit
cleanup() {
    [ -d "$TEMP_DIR" ] && rm -rf "$TEMP_DIR"
}
trap cleanup EXIT

# Create directories
mkdir -p "$BACKUP_DIR" "$TEMP_DIR"

echo "========================================"
echo "Attack Signature Auto-Updater"
echo "Source: Emerging Threats Open Ruleset"
echo "========================================"
echo ""

# Step 1: Backup current signatures
log_info "Backing up current signatures..."
if [ -f "$LIB_DIR/attack-signatures.sh" ]; then
    backup_file="$BACKUP_DIR/attack-signatures-$(date +%Y%m%d_%H%M%S).sh"
    cp "$LIB_DIR/attack-signatures.sh" "$backup_file"
    log_success "Backed up to: $backup_file"
else
    log_warn "No existing signatures found (first run)"
fi

# Step 2: Download ET Open rules
log_info "Downloading ET Open ruleset..."
if wget -q --timeout=60 "$ET_RULES_URL" -O "$TEMP_DIR/rules.tar.gz"; then
    log_success "Downloaded $(du -h "$TEMP_DIR/rules.tar.gz" | cut -f1)"
else
    log_error "Failed to download ET Open rules"
    exit 1
fi

# Step 3: Extract rules
log_info "Extracting rules..."
tar -xzf "$TEMP_DIR/rules.tar.gz" -C "$TEMP_DIR" 2>/dev/null
if [ $? -eq 0 ]; then
    rule_count=$(find "$TEMP_DIR/rules" -name "*.rules" -type f 2>/dev/null | wc -l)
    log_success "Extracted $rule_count rule files"
else
    log_error "Failed to extract rules"
    exit 1
fi

# Step 4: Parse rules and generate new signature file
log_info "Parsing rules and generating signatures..."

cat > "$TEMP_DIR/attack-signatures-new.sh" << 'HEADER_EOF'
#!/bin/bash
#
# Attack Signature Database
# Auto-generated from Emerging Threats Open Ruleset (BSD License)
# Source: https://rules.emergingthreats.net/
# Generated: $(date)
#
# Copyright (c) 2003-2025, Emerging Threats
# All rights reserved.
# Redistribution and use permitted under BSD license terms.

# Initialize associative arrays for attack patterns
declare -A ATTACK_SQLI          # SQL Injection patterns
declare -A ATTACK_XSS           # Cross-Site Scripting
declare -A ATTACK_CMD           # Command Injection
declare -A ATTACK_TRAVERSAL     # Path Traversal
declare -A ATTACK_INCLUSION     # File Inclusion (LFI/RFI)
declare -A ATTACK_WEBSHELL      # Webshell detection
declare -A ATTACK_CVE           # Known CVE exploits
declare -A ATTACK_UPLOAD        # File upload attacks

HEADER_EOF

# Function to extract patterns from Suricata rules
parse_et_rules() {
    local rules_dir="$1"
    local output_file="$2"

    echo "" >> "$output_file"
    echo "# ============================================================================" >> "$output_file"
    echo "# SQL INJECTION PATTERNS (auto-extracted from emerging-sql.rules)" >> "$output_file"
    echo "# ============================================================================" >> "$output_file"
    echo "" >> "$output_file"

    # Extract SQL injection patterns
    if [ -f "$rules_dir/emerging-sql.rules" ]; then
        local count=0
        while IFS= read -r line; do
            # Skip comments and empty lines
            [[ "$line" =~ ^#.*$ ]] && continue
            [[ -z "$line" ]] && continue

            # Extract content patterns from rules
            if [[ "$line" =~ content:\"([^\"]+)\" ]]; then
                local pattern="${BASH_REMATCH[1]}"

                # Clean up Suricata-specific syntax
                pattern=$(echo "$pattern" | sed 's/|20|/ /g')  # Replace |20| with space
                pattern=$(echo "$pattern" | sed 's/|0d 0a|/\\n/g')  # Replace CRLF
                pattern=$(echo "$pattern" | sed 's/|[0-9a-f][0-9a-f]|//g')  # Remove hex

                # Skip binary patterns (contain pipes)
                [[ "$pattern" =~ \| ]] && continue

                # Skip too short patterns
                [ "${#pattern}" -lt 3 ] && continue

                # Determine severity from rule priority
                local severity=80
                if [[ "$line" =~ priority:1 ]]; then
                    severity=90
                elif [[ "$line" =~ priority:2 ]]; then
                    severity=85
                elif [[ "$line" =~ priority:3 ]]; then
                    severity=75
                fi

                # Extract description from msg field
                local description="SQL Injection"
                if [[ "$line" =~ msg:\"([^\"]+)\" ]]; then
                    description="${BASH_REMATCH[1]}"
                fi

                # Generate pattern name
                local pattern_name="sqli_$(printf '%03d' $count)"

                # Output pattern
                echo "ATTACK_SQLI[\"$pattern_name\"]=\"$pattern|$severity|$description\"" >> "$output_file"

                count=$((count + 1))
                [ "$count" -ge 20 ] && break  # Limit to 20 patterns per category
            fi
        done < "$rules_dir/emerging-sql.rules"

        log_info "  Extracted $count SQL injection patterns"
    fi

    echo "" >> "$output_file"
    echo "# ============================================================================" >> "$output_file"
    echo "# XSS PATTERNS (auto-extracted from emerging-web_server.rules)" >> "$output_file"
    echo "# ============================================================================" >> "$output_file"
    echo "" >> "$output_file"

    # Extract XSS patterns
    if [ -f "$rules_dir/emerging-web_server.rules" ]; then
        local count=0
        while IFS= read -r line; do
            [[ "$line" =~ ^#.*$ ]] && continue
            [[ -z "$line" ]] && continue

            # Only process lines with XSS-related content
            if [[ "$line" =~ (script|xss|javascript|onerror|onload) ]] && [[ "$line" =~ content:\"([^\"]+)\" ]]; then
                local pattern="${BASH_REMATCH[1]}"

                # Clean up
                pattern=$(echo "$pattern" | sed 's/|20|/ /g')
                pattern=$(echo "$pattern" | sed 's/|[0-9a-f][0-9a-f]|//g')

                [[ "$pattern" =~ \| ]] && continue
                [ "${#pattern}" -lt 3 ] && continue

                local severity=75
                [[ "$line" =~ priority:1 ]] && severity=85
                [[ "$line" =~ priority:2 ]] && severity=80

                local description="Cross-Site Scripting"
                if [[ "$line" =~ msg:\"([^\"]+)\" ]]; then
                    description="${BASH_REMATCH[1]}"
                fi

                local pattern_name="xss_$(printf '%03d' $count)"
                echo "ATTACK_XSS[\"$pattern_name\"]=\"$pattern|$severity|$description\"" >> "$output_file"

                count=$((count + 1))
                [ "$count" -ge 20 ] && break
            fi
        done < "$rules_dir/emerging-web_server.rules"

        log_info "  Extracted $count XSS patterns"
    fi

    # Add fallback patterns if extraction yielded few results
    echo "" >> "$output_file"
    echo "# Fallback patterns (always included)" >> "$output_file"
    cat >> "$output_file" << 'FALLBACK_EOF'

# Critical fallback patterns (in case extraction misses common attacks)
ATTACK_SQLI["union_select"]="${ATTACK_SQLI["union_select"]:-union.*select|union.*all.*select|90|UNION SELECT injection}"
ATTACK_XSS["script_tag"]="${ATTACK_XSS["script_tag"]:-<script|</script>|80|Script tag injection}"
ATTACK_CMD["unix_cmd"]="${ATTACK_CMD["unix_cmd"]:-;cat |;ls |;wget |;curl |90|Unix command chaining}"
ATTACK_TRAVERSAL["dotdot"]="${ATTACK_TRAVERSAL["dotdot"]:-\\.\\./|\\.\\.|%2e%2e|80|Directory traversal}"
ATTACK_WEBSHELL["known_shells"]="${ATTACK_WEBSHELL["known_shells"]:-c99\\.php|r57\\.php|b374k|wso\\.php|95|Known webshell}"
ATTACK_CVE["log4shell"]="${ATTACK_CVE["log4shell"]:-jndi:ldap://|jndi:rmi://|95|CVE-2021-44228 Log4Shell}"

FALLBACK_EOF
}

# Parse the rules
parse_et_rules "$TEMP_DIR/rules" "$TEMP_DIR/attack-signatures-new.sh"

# Add helper functions (always included)
cat >> "$TEMP_DIR/attack-signatures-new.sh" << 'HELPER_EOF'

# ============================================================================
# HELPER FUNCTIONS
# ============================================================================

# Check if request matches attack pattern in specific category
check_attack_pattern() {
    local request="$1"
    local category="$2"

    local -n patterns="$category"

    for pattern_name in "${!patterns[@]}"; do
        local pattern_data="${patterns[$pattern_name]}"

        local regex="${pattern_data%%|*}"
        local temp="${pattern_data#*|}"
        local severity="${temp%%|*}"
        local description="${temp#*|}"

        if echo "$request" | grep -iEq "$regex"; then
            echo "$severity|$pattern_name|$description"
            return 0
        fi
    done

    return 1
}

# Get all matching patterns across all categories
detect_all_attacks() {
    local request="$1"
    local matches=()
    local max_severity=0

    local categories=("ATTACK_SQLI" "ATTACK_XSS" "ATTACK_CMD" "ATTACK_TRAVERSAL"
                      "ATTACK_INCLUSION" "ATTACK_WEBSHELL" "ATTACK_CVE" "ATTACK_UPLOAD")

    for category in "${categories[@]}"; do
        local result=$(check_attack_pattern "$request" "$category")
        if [ -n "$result" ]; then
            local severity="${result%%|*}"
            local temp="${result#*|}"
            local pattern_name="${temp%%|*}"
            local description="${temp#*|}"

            matches+=("$severity|${category#ATTACK_}|$pattern_name|$description")

            [ "$severity" -gt "$max_severity" ] && max_severity="$severity"
        fi
    done

    if [ ${#matches[@]} -gt 0 ]; then
        echo "$max_severity|${#matches[@]}|${matches[*]}"
        return 0
    fi

    return 1
}

# Get attack category name (human-readable)
get_category_name() {
    local category="$1"

    case "$category" in
        SQLI) echo "SQL Injection" ;;
        XSS) echo "Cross-Site Scripting" ;;
        CMD) echo "Command Injection" ;;
        TRAVERSAL) echo "Path Traversal" ;;
        INCLUSION) echo "File Inclusion" ;;
        WEBSHELL) echo "Webshell" ;;
        CVE) echo "CVE Exploit" ;;
        UPLOAD) echo "Malicious Upload" ;;
        *) echo "$category" ;;
    esac
}
HELPER_EOF

# Step 5: Validate new signature file
log_info "Validating new signature file..."
if bash -n "$TEMP_DIR/attack-signatures-new.sh" 2>/dev/null; then
    log_success "Syntax check passed"
else
    log_error "Syntax check failed - keeping old signatures"
    exit 1
fi

# Step 6: Test that patterns work
log_info "Testing pattern detection..."
test_result=$(bash -c "source $TEMP_DIR/attack-signatures-new.sh && detect_all_attacks \"union select\" 2>/dev/null")
if [ -n "$test_result" ]; then
    log_success "Pattern detection working"
else
    log_warn "Pattern detection test failed - but file is valid, installing anyway"
fi

# Step 7: Install new signature file
log_info "Installing new signatures..."
cp "$TEMP_DIR/attack-signatures-new.sh" "$LIB_DIR/attack-signatures.sh"
chmod 644 "$LIB_DIR/attack-signatures.sh"
log_success "Installed to: $LIB_DIR/attack-signatures.sh"

# Step 8: Show summary
echo ""
echo "========================================"
echo "Update Complete!"
echo "========================================"
echo ""
echo "Signature file: $LIB_DIR/attack-signatures.sh"
echo "Backup saved to: $BACKUP_DIR/"
echo "ET Rules source: $ET_RULES_URL"
echo "Last updated: $(date)"
echo ""
echo "Changes will take effect when live-attack-monitor.sh is restarted."
echo ""

# Show pattern counts
log_info "Pattern counts:"
echo "  SQL Injection:    $(grep -c 'ATTACK_SQLI\[' "$LIB_DIR/attack-signatures.sh" || echo 0)"
echo "  XSS:              $(grep -c 'ATTACK_XSS\[' "$LIB_DIR/attack-signatures.sh" || echo 0)"
echo "  Command Injection: $(grep -c 'ATTACK_CMD\[' "$LIB_DIR/attack-signatures.sh" || echo 0)"
echo "  Path Traversal:   $(grep -c 'ATTACK_TRAVERSAL\[' "$LIB_DIR/attack-signatures.sh" || echo 0)"
echo "  File Inclusion:   $(grep -c 'ATTACK_INCLUSION\[' "$LIB_DIR/attack-signatures.sh" || echo 0)"
echo "  Webshells:        $(grep -c 'ATTACK_WEBSHELL\[' "$LIB_DIR/attack-signatures.sh" || echo 0)"
echo "  CVE Exploits:     $(grep -c 'ATTACK_CVE\[' "$LIB_DIR/attack-signatures.sh" || echo 0)"
echo "  Upload Attacks:   $(grep -c 'ATTACK_UPLOAD\[' "$LIB_DIR/attack-signatures.sh" || echo 0)"
echo ""

log_success "Signature update complete!"
