#!/usr/bin/env bash
# audit_http_headers
# ------------------
# Audita las cabeceras HTTP de seguridad de una URL: HSTS, CSP, X-Frame-Options,
# X-Content-Type-Options, Referrer-Policy, Permissions-Policy y otras.
# También muestra cabeceras que exponen información del servidor.
#
# USO (directo):
#   audit_http_headers <url>
#
# Depende de: curl

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/../shell/bash_colors.sh"
source "$SCRIPT_DIR/../shell/bash_log.sh"
bash_colors
bash_log_init

# ─── Funciones puras ──────────────────────────────────────────────────────────

_hdr_normalize_url() {
    local url="$1"
    if [[ ! "$url" =~ ^https?:// ]]; then
        echo "https://${url}"
    else
        echo "$url"
    fi
}

_hdr_header_present() {
    local headers="$1"
    local name="$2"
    echo "$headers" | grep -qi "^${name}:"
}

_hdr_extract_value() {
    local headers="$1"
    local name="$2"
    echo "$headers" | grep -i "^${name}:" | cut -d: -f2- | xargs
}

_hdr_hsts_is_strong() {
    local value="$1"
    local max_age
    max_age="$(echo "$value" | grep -oE 'max-age=[0-9]+' | cut -d= -f2 || echo 0)"
    [[ "$max_age" -ge 15768000 ]]  # 6 meses en segundos
}

# ─── Funciones de efecto ──────────────────────────────────────────────────────

_hdr_fetch() {
    local url="$1"
    curl -sI --max-time 15 --location "$url" 2>/dev/null | tr -d '\r'
}

_hdr_check_header() {
    local headers="$1"
    local name="$2"
    local description="$3"

    if _hdr_header_present "$headers" "$name"; then
        local value
        value="$(_hdr_extract_value "$headers" "$name")"
        echo -e "  ${GREEN}[ok]${NC} ${name}"
        echo -e "       ${GRAY}${value}${NC}"
    else
        echo -e "  ${RED}[x] ${NC} ${name} -- ${description}"
    fi
}

_hdr_check_hsts() {
    local headers="$1"
    local name="Strict-Transport-Security"
    if _hdr_header_present "$headers" "$name"; then
        local value
        value="$(_hdr_extract_value "$headers" "$name")"
        if _hdr_hsts_is_strong "$value"; then
            echo -e "  ${GREEN}[ok]${NC} ${name}"
        else
            echo -e "  ${YELLOW}[!] ${NC} ${name} -- max-age demasiado corto (<6 meses)"
        fi
        echo -e "       ${GRAY}${value}${NC}"
    else
        echo -e "  ${RED}[x] ${NC} ${name} -- HSTS no configurado"
    fi
}

_hdr_show_server_info() {
    local headers="$1"

    echo ""
    echo -e "${CYAN}── Información del servidor ──────────────────────${NC}"

    for h in Server X-Powered-By X-AspNet-Version X-Generator; do
        if _hdr_header_present "$headers" "$h"; then
            local val
            val="$(_hdr_extract_value "$headers" "$h")"
            echo -e "  ${YELLOW}[!]${NC} ${h}: ${val} (información expuesta)"
        fi
    done

    local status
    status="$(echo "$headers" | head -1)"
    echo -e "  ${CYAN}Status:${NC} ${status}"
}

# ─── Punto de entrada ─────────────────────────────────────────────────────────

audit_http_headers() {
    local raw_url="$1"

    if [[ -z "$raw_url" ]]; then
        error "audit_http_headers: se requiere una URL como argumento" >&2
        return 1
    fi

    if ! command -v curl &>/dev/null; then
        error "audit_http_headers: 'curl' no está instalado (sudo apt install curl)" >&2
        return 1
    fi

    local url
    url="$(_hdr_normalize_url "$raw_url")"

    info "Consultando cabeceras de: ${url}"
    local headers
    headers="$(_hdr_fetch "$url")"

    if [[ -z "$headers" ]]; then
        error "audit_http_headers: no se pudieron obtener las cabeceras. ¿El sitio está disponible?" >&2
        return 1
    fi

    echo ""
    echo -e "${PURPLE}════════ Cabeceras de Seguridad ════════════════${NC}"
    echo ""

    _hdr_check_hsts "$headers"
    _hdr_check_header "$headers" "Content-Security-Policy"      "Previene XSS e inyección de contenido"
    _hdr_check_header "$headers" "X-Frame-Options"              "Previene clickjacking"
    _hdr_check_header "$headers" "X-Content-Type-Options"       "Previene MIME sniffing"
    _hdr_check_header "$headers" "Referrer-Policy"              "Controla información del referrer"
    _hdr_check_header "$headers" "Permissions-Policy"           "Controla acceso a APIs del navegador"
    _hdr_check_header "$headers" "Cross-Origin-Opener-Policy"   "Aísla el contexto de navegación"
    _hdr_check_header "$headers" "Cross-Origin-Resource-Policy" "Controla compartición de recursos"

    _hdr_show_server_info "$headers"
    echo ""
}

# Ejecutar si se llama directamente
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    audit_http_headers "$@"
fi
