
#!/bin/bash
#
# snuk-audit-systemd.sh
# Snukware systemd Runtime Audit Module
#

SNuk_SYSTEMD_VERSION="1.2"
SNuk_SYSTEMD_LIBDIR="/usr/lib64/systemd"

snuk_systemd_check()
{
    local FAILS=0
    local CORE_FILE
    local SHARED_FILE
    local VERSION
    local FILE
    local DEP
    local -a CORE_FILES=()

    mapfile -t CORE_FILES < <(
        find "$SNuk_SYSTEMD_LIBDIR" -maxdepth 1 \
            -type f -name 'libsystemd-core-*.so' -print 2>/dev/null |
            sort -V
    )

    echo
    echo "=== systemd Runtime ==="

    if (( ${#CORE_FILES[@]} == 0 )); then
        echo "[FAIL] no libsystemd-core library found"
        return 1
    fi

    # Bei mehreren installierten Versionen die höchste Version prüfen.
    CORE_FILE="${CORE_FILES[${#CORE_FILES[@]}-1]}"
    VERSION="${CORE_FILE##*-core-}"
    VERSION="${VERSION%.so}"
    SHARED_FILE="$SNuk_SYSTEMD_LIBDIR/libsystemd-shared-$VERSION.so"

    echo "[INFO] detected systemd library version: $VERSION"

    if [[ -f "$CORE_FILE" ]]; then
        echo "[OK]   $CORE_FILE"
    else
        echo "[FAIL] $CORE_FILE"
        ((FAILS++))
    fi

    if [[ -f "$SHARED_FILE" ]]; then
        echo "[OK]   $SHARED_FILE"
    else
        echo "[FAIL] missing $SHARED_FILE"
        ((FAILS++))
    fi

    # ELF-Abhängigkeiten der systemd-Privatbibliotheken prüfen.
    for FILE in "$CORE_FILE" "$SHARED_FILE"; do
        [[ -f "$FILE" ]] || continue

        while IFS= read -r DEP; do
            [[ -z "$DEP" ]] && continue
            echo "[FAIL] $(basename "$FILE") :: $DEP"
            ((FAILS++))
        done < <(
       		LD_LIBRARY_PATH="$SNuk_SYSTEMD_LIBDIR${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" \
    		ldd "$FILE" 2>/dev/null | grep 'not found' 
		)
    done

    if command -v systemctl >/dev/null 2>&1; then
        if systemctl --quiet is-system-running; then
            echo "[OK]   systemd reports a running system"
        else
            echo "[WARN] systemd is not fully running"
        fi

        if systemctl --failed --no-legend >/dev/null 2>&1; then
            local FAILED_UNITS
            FAILED_UNITS=$(
                systemctl --failed --no-legend 2>/dev/null | wc -l
            )
            if (( FAILED_UNITS == 0 )); then
                echo "[OK]   no failed units"
            else
                echo "[WARN] $FAILED_UNITS failed unit(s)"
            fi
        else
            echo "[WARN] could not query failed units"
        fi
    else
        echo "[WARN] systemctl is unavailable"
    fi

    if (( FAILS > 0 )); then
        echo "[FAIL] systemd audit: $FAILS problem(s)"
        return 1
    fi

    echo "[OK]   systemd audit"
    return 0
}

if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
    echo "Snukware systemd Runtime Audit v$SNuk_SYSTEMD_VERSION"
    snuk_systemd_check
    exit $?
fi
