#!/bin/bash
# Atomicorp, Inc
# Copyright 2024-2026
# Summary: freshclam wrapper — hub/offline and atomic CDN downloads (curl on Solaris)


# Globals
SIG_DIR="/var/lib/clamav/"
DEBUG=0
LOG_FILE="/var/ossec/logs/atomicorp-api.log"
TEMP_DIR="/tmp/clamav_downloads"
MODULE_NAME="atomicorp-api-module-freshclam"
ATOMIC_CDN="https://rule-updates.atomicorp.com/channels/rules/anti-malware"

#####################################
# Functions
#####################################
source /var/ossec/lib/atomicorp-functions.sh

# Build list of Atomicorp-* custom signature basenames from malware-detection settings.
collect_atomicorp_sig_files() {
    files_to_add=()
    EXTENSIONS="fp hdb hdu hsb hsu idb ign2 ldb ldu ndb ndu sfp"
    if [[ ${FRESHCLAM_LINUX_SIGS} == "yes" ]]; then
        for ext in $EXTENSIONS; do
            files_to_add+=("Atomicorp-Linux.${ext}")
        done
    fi
    if [[ ${FRESHCLAM_WINDOWS_SIGS} == "yes" ]]; then
        for ext in $EXTENSIONS; do
            files_to_add+=("Atomicorp-Windows.${ext}")
        done
    fi
    if [[ ${FRESHCLAM_ANDROID_SIGS} == "yes" ]]; then
        for ext in $EXTENSIONS; do
            files_to_add+=("Atomicorp-Android.${ext}")
        done
    fi
    if [[ ${FRESHCLAM_OSX_SIGS} == "yes" ]]; then
        for ext in $EXTENSIONS; do
            files_to_add+=("Atomicorp-OSX.${ext}")
        done
    fi
}

# Download Atomicorp-* signature packs from SERVER into SIG_DIR in-place
# (no full directory wipe). Does not fetch official main/daily/bytecode CVD/CLD —
# those defeat the low-memory atomic feed design (parity with Linux ExcludeDatabase).
# Args: SERVER base URL (no trailing slash required)
update_from_url() {
    local SERVER="$1"
    local file
    local dest
    local got_any=0
    local fail=0

    SERVER="${SERVER%/}"

    if [[ ${TEMP_DIR} == "/" ]] || [[ -z ${TEMP_DIR} ]]; then
        echo "TEMP_DIR is invalid, aborting"
        log_event "freshclam: TEMP_DIR is invalid, aborting"
        return 1
    fi

    if [[ ${SIG_DIR} == "/" ]] || [[ -z ${SIG_DIR} ]]; then
        echo "SIG_DIR is invalid, aborting"
        log_event "freshclam: SIG_DIR is invalid, aborting"
        return 1
    fi

    if [ -d "$TEMP_DIR" ]; then
        rm -rf "${TEMP_DIR}"
    fi
    mkdir -p "${TEMP_DIR}"
    mkdir -p "${SIG_DIR}"

    log_event "freshclam: downloading signatures from ${SERVER}"

    collect_atomicorp_sig_files
    for file in "${files_to_add[@]}"; do
        if download -k "${SERVER}/${file}" "${TEMP_DIR}/${file}"; then
            got_any=1
            cp -f "${TEMP_DIR}/${file}" "${SIG_DIR}/${file}"
            if [[ $DEBUG -ge 1 ]]; then
                log_event "DEBUG1: freshclam: installed ${file}"
            fi
        else
            log_event "freshclam: failed to download ${file} from ${SERVER}"
            fail=1
        fi
    done

    rm -rf "${TEMP_DIR}"

    if [[ -n ${CLAMAV_OWNER} ]]; then
        chown -R "${CLAMAV_OWNER}:${CLAMAV_GROUP}" "${SIG_DIR}" 2>/dev/null || \
            /usr/bin/chown -R "${CLAMAV_OWNER}:${CLAMAV_GROUP}" "${SIG_DIR}" 2>/dev/null || true
    fi

    if [[ $got_any -eq 0 ]]; then
        log_event "freshclam: no signatures downloaded from ${SERVER}"
        return 1
    fi

    if [[ $fail -ne 0 ]]; then
        log_event "freshclam: completed with some download failures from ${SERVER}"
        return 1
    fi

    log_event "freshclam: signature update completed from ${SERVER}"
    return 0
}

update_from_hub() {
    get_hub_ip
    if [[ -z ${HUB_IP} ]]; then
        log_event "freshclam: HUB_IP empty; cannot update from hub"
        return 1
    fi
    update_from_url "https://${HUB_IP}/channels/rules/anti-malware"
}

update_from_atomic_cdn() {
    update_from_url "${ATOMIC_CDN}"
}

#####################################
# Main
#####################################
dist_detection

if [ -d /var/ossec/queue/sockets/ ]; then
        AGENT_INFO_PATH=/var/ossec/queue/sockets/
elif [ -d /var/ossec/queue/ossec/ ]; then
        AGENT_INFO_PATH=/var/ossec/queue/ossec/
fi

ID=$(sed '3q;d' ${AGENT_INFO_PATH}/.agent_info)

if [ -f /var/ossec/etc/shared/${ID}.malware-detection ]; then
    CONFIG_FILE="/var/ossec/etc/shared/${ID}.malware-detection"
elif [ -f /var/ossec/etc/shared/malware-detection ]; then
    CONFIG_FILE="/var/ossec/etc/shared/malware-detection"
else
    if [[ $DEBUG -ge 1 ]]; then
        log_event "Neither ${ID}.malware-detection nor malware-detection found."
    fi
    exit 0
fi


get_freshclam_conf
if [ ! -d ${SIG_DIR} ]; then
    mkdir -p ${SIG_DIR}
    if [ $DEBUG -ge 1 ]; then
        log_event "DEBUG1: freshclam: clamav_owner and clamav_group are ${CLAMAV_OWNER}:${CLAMAV_GROUP}"
    fi
    chown ${CLAMAV_OWNER}:${CLAMAV_GROUP} ${SIG_DIR} 2>/dev/null || true
fi

# Default feed type if unset
if [[ -z ${FRESHCLAM_FEED_TYPE} ]]; then
    FRESHCLAM_FEED_TYPE="atomic"
fi

# Default linux sigs on if unset (matches typical hub malware-detection)
if [[ -z ${FRESHCLAM_LINUX_SIGS} ]]; then
    FRESHCLAM_LINUX_SIGS="yes"
fi

RET=0
if [[ $FRESHCLAM_FEED_TYPE == "hub" ]]; then
    update_from_hub
    RET=$?
elif [[ $PKG == "pkg" ]]; then
    # Solaris AWPclamav: stock freshclam cannot use HTTPS DatabaseCustomURL.
    # Honor atomic (CDN) vs hub via curl.
    if [[ $FRESHCLAM_FEED_TYPE == "official" ]]; then
        if [ -x /opt/atomicorp/bin/freshclam ]; then
            /opt/atomicorp/bin/freshclam
            RET=$?
        else
            log_event "freshclam: official feed requested but /opt/atomicorp/bin/freshclam missing"
            RET=1
        fi
    else
        # atomic (default) or any other non-hub type on Solaris → CDN curl
        update_from_atomic_cdn
        RET=$?
    fi
elif [[ $PKG == "aix" ]]; then
    if [ -x /opt/atomicorp/bin/freshclam ]; then
        /opt/atomicorp/bin/freshclam
        RET=$?
    else
        /opt/freeware/bin/freshclam
        RET=$?
    fi
else
    /usr/bin/freshclam
    RET=$?
fi

exit $RET
