blob: 9ab1a335d51217be2b76f23fe1b30ad6f0949a63 (
plain) (
tree)
|
|
#!/usr/bin/env bash
#
# nwatch(1) -- Slightly friendlier version of the suggested script in the
# manual page for ndiff(1) from the Nmap suite, implemented in Bash.
#
# Usage:
# $ nwatch HOSTLIST CACHEDIR
# Example with root privileges:
# # nwatch /etc/nwatch.mynet /var/cache/nwatch/mynet
#
# Prints the results of an ndiff(1) call against the last known scan to stdout;
# intended to be called from cron(8):
# 0 0 * * 0 nwatch /etc/nwatch.mynet /var/cache/nwatch/mynet
#
# I recommend you use Mail::Run::Crypt, so you don't leak your network
# information in plain text in your email:
# <https://metacpan.org/pod/Mail::Run::Crypt>
#
# Please also consider whether your scan actually requires root privileges, and
# could not instead be run by a dedicated user with appropriately limited
# privileges.
#
# Author: Tom Ryder <tom@sanctum.geek.nz>
# Copyright: 2014
# License: GPLv2 (same as Nmap itself)
#
# Defensive umask by default; change at your own risk!
umask 0077
# Some fixed values
self=nwatch
hostlist=${1:?}
cachedir=${2:?}
latest=$cachedir/${self}.scan.latest
# If the cachedir doesn't exist, attempt to create it, otherwise give up
if [[ ! -d "$cachedir" ]] ; then
if ! mkdir -- "$cachedir" ; then
exit 1
fi
fi
# Today's values
date=$(date +%s)
cache=$cachedir/${self}.scan.${date}
diff=$cachedir/${self}.diff.${date}
# Run the scan or give up
if ! nmap -v -T4 -sV --open -iL "$hostlist" -oA "$cache" >/dev/null ; then
exit 1
fi
# If the link to the XML file is legible, run the diff or give up
if [[ -r ${latest}.xml ]] ; then
ndiff -- "$latest".xml "$cache".xml > "$diff"
# Because we always want a report, only exit if an actual error condition
# (1 means there's a meaningful diff in the scans)
if (($? == 2)) ; then
exit 1
fi
fi
# Create or update the links
rm -f "${cache/$date/latest}".*
for cachetype in "$cache".* ; do
ln -s -- "$cachetype" "${cachetype/$date/latest}"
done
# Write diff to stdout if it exists (not an error if it doesn't)
if [[ -r $diff ]] ; then
awk '
/^[-+]Not shown: / { next }
/^[-+]/ { diff = 1 }
NF { lines[++l] = $0 }
function write() {
if (diff) {
for (n = 1; n <= l; n++)
print lines[n]
print ""
diff = 0
}
l = 0
}
!NF { write() }
END { write() }
' "$diff"
fi
|