#!/bin/bash

# copyright 2013, Simon Oosthoek (soosthoek@nieuwland.nl)
# License: GPL v2 or later.

# Check vhosts:
# using a file with a list of hostnames and urls to check all vhost services on a webserver
# optionally use an IP address to bypass any alternative routes for reaching the server
# I don't see any reason to produce warning codes, OK, CRITICAL (with list of failed vhosts) and UNKNOWN if 
# the file cannot be read or the wget command is not available
# vhostfile format: 
# vhostname	URL contentstring
# URL must start with a /

GETOPTSSTR="f:H:p:v:dh"
VHOSTFILE=""
HOSTIP=""
VERBOSITY=0
PORT=""
DEBUG=""
WGET=/usr/bin/wget

if [[ -x "$WGET" ]]; then
	if $WGET --version |grep '\<1\.[1-9][2-9]' >/dev/null
	then
		USEEXITCODE=true
		echo "WGET using exitcodes v >= 1.12"
	else
		USEEXITCODE=""
		echo "WGET NOT using exitcodes v < 1.12"
	fi
else
	echo "ERROR: $WGET not executable"
	exit 3
fi

function usage () {
	echo "Usage: $0 -w <warning> -c <critical>"
	# Nagios exit code 3 = status UNKNOWN = orange
	echo ""
	echo " -H IPnumber = Optional IPnumber to use instead of the hostname."
	echo " -p port     = Optional portnumber to use instead of 80."
	echo " -f file     = mandatory input file with vhost definitions."
	echo " -d          = Optional debugging, saves retrieved file for vhostname in /tmp/"
	echo " -v number   = Verbosity level (0,1 single line, 2,3 multiline. use 3 for debugging"
	echo " -h          = This help message."
	exit 3   
}

while getopts "$GETOPTSSTR" Option
do
	case "$Option" in
	f) 	if [[ -f "$OPTARG" && ! -h "$OPTARG" ]]; then
			VHOSTFILE="$OPTARG"
		else 
			echo "ERROR: argument to -f $OPTARG not a file" 
			exit 3
		fi
	;;
	H) 	if ping -q -c 1 "$OPTARG" >/dev/null 2>&1
		then
			HOSTIP="$OPTARG"
		else
			echo "ERROR: option $OPTARG to -H doesn't respond to ping"
			exit 3
		fi
	;;
	v) 	case "$OPTARG" in
			[0-9]) VERBOSITY="$OPTARG"
			;;
			*)	echo "ERROR: verbosity number outside range 0-9" 
				exit 3
			;;
		esac
	;;
	p)	case "$OPTARG" in 
			*[^0-9]*)
				echo "PORTNUMBER is not a number"
				exit 3
			;;
			[1-9]*)
				if [[ $OPTARG -gt 65535 ]]; then
					echo "PORTNUMBER out of range"
					exit 3
				fi
			;;
			*)
				echo "PORTNUMBER out of range"
				exit 3
			;;
		esac
		PORT=$OPTARG
	;;
	d)	DEBUG="true"
	;;
	h) 	usage
	;;
	*)	usage
	esac
done
shift $(($OPTIND - 1)) 

STATUS=0

tempfile=/tmp/$(basename $0)-$$
tempfile2=/tmp/$(basename $0)-2-$$

if :>$tempfile
then
	: #ok
else
	echo "ERROR: unable to open $tempfile"
	exit 3
fi

if :>$tempfile2
then
	: #ok
else
	echo "ERROR: unable to open $tempfile2"
	exit 3
fi

while read vhostname url contentstring
do
	if [[ -z "$contentstring" ]]; then
		contentstring=$vhostname
	fi
	if [[ $VERBOSITY -gt 2 ]]; then
		echo "Checking $vhostname; url=$url; string=$contentstring" 
	fi
	if [[ -n "$PORT" ]]; then
		url=":${PORT}$url"
	fi
	if [[ -z "$HOSTIP" ]]; then
		GETURL="http://${vhostname}$url"
		$WGET --quiet --server-response -O $tempfile "$GETURL"  2>$tempfile2
		WGETEXITCODE=$?
	else
		GETURL="http://${HOSTIP}$url"
		$WGET --quiet --server-response -O $tempfile --header "Host: $vhostname" "$GETURL" 2>$tempfile2
		WGETEXITCODE=$?
	fi
	httpresponse=$(grep HTTP $tempfile2)
	if [[ -n "$USEEXITCODE" ]]; then
		case "$WGETEXITCODE" in 
			0|8)	;; #in case 0 or 8, httpresponse is already set to the right value
			1)	httpresponse="wget generic error";;
			2)	httpresponse="wget argument error";;
			3)	httpresponse="wget file i/o error";;
			4)	httpresponse="wget network failure";;
			5)	httpresponse="wget SSL error";;
			6)	httpresponse="wget basic authentication failure";;
			7)	httpresponse="wget protocol errors";;
			*)	httpresponse="wget unknown exitcode $WGETEXITCODE";;
		esac
	else
		WGETEXITCODE=0
	fi

	if [[ $WGETEXITCODE -gt 0 ]]; then
		STATUS=2 #CRITICAL
		FAILEDVHOSTS="$FAILEDVHOSTS $vhostname:'$httpresponse'"
	elif [[ $WGETEXITCODE -eq 0 ]]; then
		if grep -- "$contentstring" $tempfile  >/dev/null
		then
			GOODVHOSTS="$GOODVHOSTS $vhostname"
		else
			STATUS=2 #CRITICAL
			FAILEDVHOSTS="$FAILEDVHOSTS $vhostname:CONTENTSTRING_MISMATCH"
		fi
		if [[ -n "$DEBUG" ]]; then
			cp $tempfile "/tmp/$vhostname-url.html"
			echo "$vhostname -> /tmp/$vhostname-url.html"
		fi
	fi
done < "$VHOSTFILE" 
rm -f $tempfile
rm -f $tempfile2

if [[ $STATUS == 0 ]]; then
	if [[ $VERBOSITY > 0 ]]; then
		echo "OK: $GOODVHOSTS"
		exit 0
	else 
		echo "OK: all vhosts"
	fi
elif [[ $STATUS == 2 ]]; then
	echo "CRITICAL: $FAILEDVHOSTS"
	exit $STATUS
else
	echo "UNKNOWN"
	exit $STATUS
fi
