#!/bin/bash
#################################################################
# Criado por: Eduardo Jonck                                     #
# Email: eduardo@eduardojonck.com                               #
# Site: https://openfw.com.br                          # 
#################################################################


#Função de Help
print_help() {
  echo "Utilize: suricata-jobs [OPTIONS]."
  echo
  echo -e "Options:"
  echo
  echo -e "   --restart - Reinicia o serviço"
  echo -e "   --reload - Recarrega as configuracões"
  echo -e "   --update - Baixa atualizações e aplica mudanças nas assinaturas"
  echo -e "   --status - Consulta se o serviço do Suricata está em execução"

              }



# Função para aplicar o arquivo modify-sid
modify_sid() {
    local input_file="/var/efw/suricata/modify-sid"
    local output_file="/etc/suricata/modify.conf"

    # Limpa o arquivo de saída apenas se houver dados para processar
    > "$output_file"

    while IFS=',' read -r action sid; do
        # Remove espaços e normaliza
        action=$(echo "$action" | tr -d '[:space:]' | tr '[:lower:]' '[:upper:]')
        sid=$(echo "$sid" | tr -d '[:space:]')

        # Ignora linhas vazias ou comentários
        [[ -z "$action" || -z "$sid" ]] && continue
        [[ "$action" =~ ^# ]] && continue

        case "$action" in
            ALERT)
                echo "modifysid $sid \"drop\" | \"alert\"" >> "$output_file"
                ;;
            DROP)
                echo "modifysid $sid \"alert\" | \"drop\"" >> "$output_file"
                ;;
            *)
                ;;
        esac
    done < "$input_file"
}

suppress_sid() {
    local input_file="/var/efw/suricata/suppress"
    local output_file="/etc/suricata/threshold.config"


    # Limpa o arquivo de saída somente se houver conteúdo
    > "$output_file"

    while IFS=',' read -r direction ip sid; do
        # Normalização
        direction=$(echo "$direction" | tr -d '[:space:]' | tr '[:lower:]' '[:upper:]')
        ip=$(echo "$ip" | tr -d '[:space:]')
        sid=$(echo "$sid" | tr -d '[:space:]')

        # Ignora linhas vazias ou comentários
        [[ -z "$direction" || -z "$ip" || -z "$sid" ]] && continue
        [[ "$direction" =~ ^# ]] && continue

        case "$direction" in
            ORIGEM)
                echo "suppress gen_id 1, sig_id $sid, track by_src, ip $ip" >> "$output_file"
                ;;
            DESTINO)
                echo "suppress gen_id 1, sig_id $sid, track by_dst, ip $ip" >> "$output_file"
                ;;
            *)
                # ignora silenciosamente
                ;;
        esac
    done < "$input_file"
}


# Função para aplicar categorias reescrevendo os arquivos de conf
apply_category_rules() {
    local input_file="/var/efw/suricata/category-rules"
    local drop_file="/etc/suricata/drop.conf"
    local enable_file="/etc/suricata/enable.conf"
    local disable_file="/etc/suricata/disable.conf"

    # Limpa os arquivos antes de gerar os novos
    > "$drop_file"
    > "$enable_file"
    > "$disable_file"

    while IFS='=' read -r category value; do
        # Ignora linhas vazias ou comentários
        [[ -z "$category" || "$category" =~ ^# ]] && continue

        # Remove espaços extras
        category=$(echo "$category" | xargs)
        value=$(echo "$value" | xargs)

        case "$value" in
            drop)
                echo "group:$category" >> "$drop_file"
                echo "group:$category" >> "$enable_file"
                ;;
            off)
                echo "group:$category" >> "$disable_file"
                ;;
            default)
                echo "group:$category" >> "$enable_file"
                ;;
            *)
                echo "Valor desconhecido '$value' para categoria $category"
                ;;
        esac
    done < "$input_file"
}


# Função para criar ou remover agendamento do Suricata
set_update_schedule() {
    local settings_file="/var/efw/suricata/settings"
    local cron_file="/etc/cron.d/suricata-update"
    local schedule enabled_rules

    # Lê as variáveis
    enabled_rules=$(grep -E '^ENABLED_RULES=' "$settings_file" | cut -d'=' -f2 | xargs)
    schedule=$(grep -E '^UPDATE_SCHEDULE=' "$settings_file" | cut -d'=' -f2 | xargs)

    # Checa ENABLED_RULES
    if [ "$enabled_rules" != "auto" ]; then
        echo "ENABLED_RULES=$enabled_rules, removendo agendamento se existir..."
        [ -f "$cron_file" ] && rm -f "$cron_file"
        /etc/init.d/fcron restart > /dev/null 2>&1
        return
    fi

    # Limpa ou cria o arquivo de cron
    > "$cron_file"

    # Define o cronjob com base na programação
    case "$schedule" in
        daily)
            # Todo dia às 23:00
            echo "0 23 * * * /usr/local/bin/suricata-jobs --update" >> "$cron_file"
            /etc/init.d/fcron restart > /dev/null 2>&1
            ;;
        weekly)
            # Todo domingo às 23:00
            echo "0 23 * * 0 /usr/local/bin/suricata-jobs --update" >> "$cron_file"
            /etc/init.d/fcron restart > /dev/null 2>&1
            ;;
        monthly)
            # Todo dia 1 às 23:00
            echo "0 23 1 * * /usr/local/bin/suricata-jobs --update" >> "$cron_file"
            /etc/init.d/fcron restart > /dev/null 2>&1
            ;;
        *)
            echo "Valor desconhecido '$schedule' para UPDATE_SCHEDULE."
            exit 1
            ;;
    esac
}

# Função para executar o suricata-update
update() {
    if pgrep -f "/usr/bin/suricata-update" > /dev/null; then
        echo "$(date "+%d/%m/%Y -- %H:%M:%S") - <Warn> -- suricata-update já está em execução" >> /var/log/suricata/suricata.log
        echo "suricata-update já está rodando."
        return 0
    fi

    echo "Executando suricata-update..."
    echo "$(date "+%d/%m/%Y -- %H:%M:%S") - <Info> -- Update das rules iniciado....." >> /var/log/suricata/suricata.log

    /usr/bin/suricata-update >> /var/log/suricata/suricata.log 2>&1
    STATUS=$?

        #Atualiza data e hora do update na dashboard
    if [ $STATUS -eq 0 ]; then
            TS_FILE="/var/efw/download/timestamps"
            KEY="SURICATA_SURICATA_RULES_URL"
            VALUE="$(date +%s)"

            if grep -q "^${KEY}=" "$TS_FILE"; then
                sed -i "s/^${KEY}=.*/${KEY}=${VALUE}/" "$TS_FILE"
            else
                echo "${KEY}=${VALUE}" >> "$TS_FILE"
            fi
        #Atualiza data e hora do update no menu de configs gerais
        touch /var/lib/suricata/rules/suricatarules.revision
        echo "$(date "+%d/%m/%Y -- %H:%M:%S") - <Info> -- suricata-update concluído com sucesso" >> /var/log/suricata/suricata.log
        echo "suricata-update executado com sucesso."
    else
        echo "$(date "+%d/%m/%Y -- %H:%M:%S") - <Error> -- Falha ao executar suricata-update" >> /var/log/suricata/suricata.log
        echo "Erro ao executar suricata-update."
        exit 1
    fi
}

# Função para gerenciar script de inicialização do Suricata
set_startup_hook() {
    local settings_file="/var/efw/suricata/settings"
    local hook_file="/var/efw/inithooks/start.local"
    local enabled

    # Lê a variável ENABLED
    enabled=$(grep -E '^ENABLED=' "$settings_file" | cut -d'=' -f2 | xargs)

    # Garante que o arquivo de hook exista
    touch "$hook_file"
    chmod +x "$hook_file"

    if [ "$enabled" = "1" ]; then
	    #Inicia serviço, ativa mo monit e atualiza as assinaturas
		/etc/init.d/suricata restart
		monit monitor suricata
		
        # Atualiza start.local
        if ! head -n 1 "$hook_file" | grep -q '^#!/bin/bash'; then
            sed -i '1i#!/bin/bash' "$hook_file"
        fi
        if ! grep -qx '/usr/local/bin/suricata-jobs --restart' "$hook_file"; then
            echo '/usr/local/bin/suricata-jobs --restart' >> "$hook_file"
        fi

    else
        echo "Suricata esta desativado!"
        sed -i '/\/usr\/local\/bin\/suricata-jobs --restart/d' "$hook_file"
		monit unmonitor suricata	
		/etc/init.d/suricata stop
    fi
}


#Função para reiniciar
restart() {
    echo "Reiniciando o Suricata..."
    set_startup_hook
    modify_sid
    suppress_sid
    apply_category_rules
    set_update_schedule
    /etc/rc.d/rc.firewall restart

    if [ $? -eq 0 ]; then
        echo "Suricata reiniciado com sucesso."
    else
        echo "Erro ao reiniciar o Suricata."
        exit 1
    fi
}

#Função para recarregar as configurações
reload() {
    echo "Recarregando as configurações do Suricata..."
    modify_sid
    suppress_sid
    apply_category_rules
    /etc/init.d/suricata reload

    if [ $? -eq 0 ]; then
        echo "Configurações recarregadas com sucesso!."
    else
        echo "Erro ao recarregar as configurações."
        exit 1
    fi
}

#Função para checar status
status() {
    echo "Verificando status do Suricata..."
    /etc/init.d/suricata status

    if [ $? -eq 0 ]; then
        echo "Suricata está ativo."
    else
        echo "Suricata não está rodando."
        exit 1
    fi
}


#Case das escolhas possíveis
case "$1" in
         --help)	
         print_help
		 exit;
         ;;
		--update)	
         update
        exit;
         ;;
		--restart)	
         restart
        exit;
         ;;
		--reload)	
         reload
        exit;
         ;;
        --update)	
         update
        exit;
         ;;
		--status)	
         status
        exit;
         ;;
         *)
		 print_help;
		 exit;
		 ;;
esac
