#!/bin/sh # # check_debsecan # # Check uses debsecan to query a list of vulnerabilies which affect a particular # Debian installation. # # Copyright (c) 2017 Stefan Schörghofer # # This module is free software; you can redistribute it and/or modify it # under the terms of GNU general public license (gpl) version 3. # See the LICENSE file for details. # Functions debug() { if ${debug} ; then echo "DEBUG: ${1}" fi } error() { echo "ERROR: ${1}" exit 3 } print_help() { #### The following line is 80 characters long (helps to fit the help text in a standard terminal) ######-------------------------------------------------------------------------------- echo echo "Usage: check_debsecan [OPTIONS]" echo echo "Arguments:" echo " -f warning value for fixed packages | default = 20" echo " -F critical value for fixed packages | default = 30" echo " -o warning value for obsolete packages | default = 1" echo " -O critical value for obsolete packages | default = 1" echo " -l warning value for \"low urgency\" fixes | default = 10" echo " -L critical value for \"low urgency\" fixes | default = 20" echo " -m warning value for \"medium urgency\" fixes | default = 5" echo " -M critical value for \"medium urgency\" fixes | default = 10" echo " -u warning value for urgent \"high urgency\" fixes | default = 1" echo " -U critical value for urgent \"high urgency\" fixes | default = 1" echo " -s set the suite parameter manually" echo " -P \"[proxy-url]\" set the proxy manually" echo echo "Options:" echo " -d produces debugging output" echo " -r disables the cve/packages report" echo " -h print this help" echo exit 3 } argument_check() { debug "Runnig argument check" debug "fixed_warn is set to ${fixed_warn}, fixed_crit is set to ${fixed_crit}" if [ ${fixed_warn} -gt ${fixed_crit} ] ; then error "Value of -F needs to be bigger or equal than value of -f (Warning can't be bigger than critical)" fi debug "obsolete_warn is set to ${obsolete_warn}, obsolete_crit is set to ${obsolete_crit}" if [ ${obsolete_warn} -gt ${obsolete_crit} ] ; then error "Value of -O needs to be bigger or equal than value of -o (Warning can't be bigger than critical)" fi debug "low_urgency_warn is set to ${low_urgency_warn}, low_urgency_crit is set to ${low_urgency_crit}" if [ ${low_urgency_warn} -gt ${low_urgency_crit} ] ; then error "Value of -L needs to be bigger or equal than value of -l (Warning can't be bigger than critical)" fi debug "medium_urgency_warn is set to ${medium_urgency_warn}, medium_urgency_crit is set to ${medium_urgency_crit}" if [ ${medium_urgency_warn} -gt ${medium_urgency_crit} ] ; then error "Value of -M needs to be bigger or equal than value of -m (Warning can't be bigger than critical)" fi debug "high_urgency_warn is set to ${high_urgency_warn}, high_urgency_crit is set to ${high_urgency_crit}" if [ ${high_urgency_warn} -gt ${high_urgency_crit} ] ; then error "Value of -U needs to be bigger or equal than value of -u (Warning can't be bigger than critical)" fi } check_if_numeric() { case $1 in ''|*[!0-9]*) debug "Argument ${1} is not numeric but has to be" echo "ERROR: Argument ${1} has to be numeric" print_help exit 3 ;; *) debug "Argument ${1} checked and is numeric" ;; esac } print_perfdata() { echo "| 'fixed'=${fixed_num};${fixed_warn};${fixed_crit};0;${fixed_crit} 'obsolete'=${obsolete_num};${obsolete_warn};${obsolete_crit};0;${obsolete_crit} 'high-urgency'=${high_urgency_num};${high_urgency_warn};${high_urgency_crit};0;${high_urgency_crit} 'medium-urgency'=${medium_urgency_num};${medium_urgency_warn};${medium_urgency_crit};0;${medium_urgency_crit} 'low-urgency'=${low_urgency_num};${low_urgency_warn};${low_urgency_crit};0;${low_urgency_crit}" } print_numbers() { echo -n "(F:${fixed_num};O:${obsolete_num};H:${high_urgency_num};M:${medium_urgency_num};L:${low_urgency_num})" } print_report() { if ${critical} || ${warning} ; then if ${report} ; then cat ${debsecan_report} fi fi } cleanup() { rm ${debsecan_report} } myexit() { if ${critical} ; then cleanup exit 2 elif ${warning} ; then cleanup exit 1 else cleanup exit 0 fi } # Checks to execute before wasting CPU-Cycles # Checking for needed debsecan binary if ! [ -x /usr/bin/debsecan ] ; then echo "ERROR: debsecan not found" exit 3 fi # Vars suite=$(grep "PRETTY_NAME" /etc/os-release | cut -d "(" -f 2 | cut -d ")" -f 1) fixed_warn=20 fixed_crit=30 obsolete_warn=1 obsolete_crit=1 low_urgency_warn=10 low_urgency_crit=20 medium_urgency_warn=5 medium_urgency_crit=10 high_urgency_warn=1 high_urgency_crit=1 debug=false report=true critical=false warning=false case ${suite} in buzz|rex|bo|hamm|slink|potato) echo "ERROR: The suite you are using is to old. Please upgrade to something newer, like Woody" exit 3 ;; stretch) debug "Stretch is not supported at the moment. Switching suite to sid." suite="sid" ;; esac while getopts "dP:hf:F:o:O:l:L:m:M:u:U:s:r" opt; do case ${opt} in h) print_help ;; d) debug=true debug "-d given, enabling debug" ;; f) debug "Warning parameter for fixed triggered - setting to ${OPTARG}" check_if_numeric ${OPTARG} fixed_warn=${OPTARG} ;; F) debug "Critical parameter for fixed triggered - setting to ${OPTARG}" check_if_numeric ${OPTARG} fixed_crit=${OPTARG} ;; o) debug "Warning parameter for obsolete triggered - setting to ${OPTARG}" check_if_numeric ${OPTARG} obsolete_warn=${OPTARG} ;; O) debug "Critical parameter for obsolete triggered - setting to ${OPTARG}" check_if_numeric ${OPTARG} obsolete_crit=${OPTARG} ;; l) debug "Warning parameter for low urgency fixes triggered - setting to ${OPTARG}" check_if_numeric ${OPTARG} low_urgency_warn=${OPTARG} ;; L) debug "Critical parameter for low urgency fixes triggered - setting to ${OPTARG}" check_if_numeric ${OPTARG} low_urgency_crit=${OPTARG} ;; m) debug "Warning parameter for medium urgency fixes triggered - setting to ${OPTARG}" check_if_numeric ${OPTARG} medium_urgency_warn=${OPTARG} ;; M) debug "Critical parameter for medium urgency fixes triggered - setting to ${OPTARG}" check_if_numeric ${OPTARG} medium_urgency_crit=${OPTARG} ;; u) debug "Warning parameter for high urgency fixes triggered - setting to ${OPTARG}" check_if_numeric ${OPTARG} high_urgency_warn=${OPTARG} ;; U) debug "Critical parameter for high urgency fixes triggered - setting to ${OPTARG}" check_if_numeric ${OPTARG} high_urgency_crit=${OPTARG} ;; r) report=false debug "-r given, disabling report" ;; s) debug "Forcing suite to ${OPTARG} because parameter was given" suite=${OPTARG} ;; P) debug "Forcing proxy-setting to ${OPTARG}" export http_proxy="${OPTARG}" export https_proxy="${OPTARG}" ;; \?) echo "ERROR: Invalid option ${OPTARG}" exit 3 ;; :) echo "ERROR: Option -${OPTARG} requires an argument." exit 3 ;; esac done argument_check # Creating tempfile to store data debsecan_report=$(mktemp) # Execute debsecan debsecan --suite ${suite} --only-fixed >> ${debsecan_report} # Checking results if [ $? -ne 0 ] ; then echo "ERROR: Problem executing debsecan. Check if your host is allowed to connect to the internet." echo " If a proxy server should be used please export the http_proxy variable." exit 3 fi # Counting, printing and checking fixed_num=$(grep -E '[(, ]fixed[), ]' ${debsecan_report} | wc -l) obsolete_num=$(grep '[( ]obsolete[), ]' ${debsecan_report} | wc -l) low_urgency_num=$(grep '[( ]low urgency[), ]' ${debsecan_report} | wc -l) medium_urgency_num=$(grep '[( ]medium urgency[), ]' ${debsecan_report} | wc -l) high_urgency_num=$(grep '[( ]high urgency[), ]' ${debsecan_report} | wc -l) # Check for criticals if [ ${fixed_num} -ge ${fixed_crit} ] ; then echo "CRITICAL: $(print_numbers) - ${fixed_num} security fixes ready to install found!" critical=true elif [ ${obsolete_num} -ge ${obsolete_crit} ] ; then echo "CRITICAL: $(print_numbers) - ${obsolete_num} obsolete package(s) found!" critical=true elif [ ${high_urgency_num} -ge ${high_urgency_crit} ] ; then echo "CRITICAL: $(print_numbers) - ${high_urgency_num} high urgency fixes ready to install found!" critical=true elif [ ${medium_urgency_num} -ge ${medium_urgency_crit} ] ; then echo "CRITICAL: $(print_numbers) - ${medium_urgency_num} medium urgency fixes ready to install found!" critical=true elif [ ${low_urgency_num} -ge ${low_urgency_crit} ] ; then echo "CRITICAL: $(print_numbers) - ${low_urgency_num} low urgency fixes ready to install found!" critical=true # Check for warnings elif [ ${fixed_num} -ge ${fixed_warn} ] ; then echo "WARNING: $(print_numbers) - ${fixed_num} security fixes ready to install found!" warning=true elif [ ${obsolete_num} -ge ${obsolete_warn} ] ; then echo "WARNING: $(print_numbers) - ${obsolete_num} obsolete package(s) found!" warning=true elif [ ${high_urgency_num} -ge ${high_urgency_warn} ] ; then echo "WARNING: $(print_numbers) - ${high_urgency_num} high urgency fixes ready to install found!" warning=true elif [ ${medium_urgency_num} -ge ${medium_urgency_warn} ] ; then echo "WARNING: $(print_numbers) - ${medium_urgency_num} medium urgency fixes ready to install found!" warning=true elif [ ${low_urgency_num} -ge ${low_urgency_warn} ] ; then echo "WARNING: $(print_numbers) - ${low_urgency_num} low urgency fixes ready to install found!" warning=true else # Everything OK echo "OK: $(print_numbers) - There are ${fixed_num} security fixes to install and ${obsolete_num} obsolete packages to remove" fi print_report print_perfdata myexit