#!/bin/sh
#
# mailverify -- see where mail has come from, verifying host names as
# we go.
# [Check for bogons in Received headers -- davecb@nexus.yorku.ca]
#
ProgName=`basename $0`
main() {
if [ $# -lt 1 ]; then
echo "${ProgName} -- verify where mail has come from."
echo "Usage: $0 message"
exit 1
fi
for i in $*; do
echo "Traceback/verification of message $i:"
headers $i >/tmp/$$
egrep -i 'From:|Sender:|Reply-to:' /tmp/$$ | \
egrep -vi '^In' | \
while read Keyword FirstToken SecondToken ThirdToken Rest; do
echo " $Keyword $FirstToken $SecondToken $ThirdToken $Rest"
done
egrep 'Received' /tmp/$$ | \
while read Keyword FirstToken SecondToken ThirdToken Rest; do
parseReceived
done
done
rm /tmp/$$
}
#
# parseReceived -- describe semantics of a received line
#
parseReceived() {
# Deal with run-together hostname/address.
if echo $SecondToken | grep -s '[[(]' ; then
ThirdToken=`expr "$SecondToken" : '^[^[(]*\(.*\)'`
SecondToken=`expr "$SecondToken" : '^\([^[(]*\).*'`
fi
# Strip off person@ from hostnames if present (I put
# these on pop mail --dave)
if echo $SecondToken | grep -s '@' ; then
HostName=`expr "$SecondToken" : '^.*@\(.*\)'`
else
HostName=$SecondToken
fi
# See if we have an address to verify.
HostAddr=`echo $ThirdToken | tr -d "()[]"`
# echo " HostName=$HostName HostAddr=$HostAddr"
case "$HostAddr" in
[0-9]*.[0-9]*.[0-9]*.[0-9]*)
if verified $HostName $HostAddr; then
echo " Received from: $HostName at $HostAddr [verified]"
else
echo " BOGUS received from: `realName $HostAddr` at $HostAddr claiming to be $HostName"
fi
;;
*)
echo " Probably received from: $HostName $ThirdToken $Rest [unverifiable]";;
esac
}
#
# realName -- look up a name for this address
#
realName() {
addr=$1
a=`expr "$addr" : '^[0-9]*\.[0-9]*\.[0-9]*\.\([0-9]*\)'`
b=`expr "$addr" : '^[0-9]*\.[0-9]*\.\([0-9]*\)\.[0-9]*'`
c=`expr "$addr" : '^[0-9]*\.\([0-9]*\)\.[0-9]*\.[0-9]*'`
d=`expr "$addr" : '^\([0-9]*\)\.[0-9]*\.[0-9]*\.[0-9]*'`
echo "set q=ptr
$a.$b.$c.$d.in-addr.arpa " | nslookup 2>&1 | awk '
/host name/ {
print $5
}
'
}
#
# verified -- see if this really was who it claimed
#
verified() {
name=$1
addr=$2
# Do an nslookup on name and see if it matches addr or mx.
arecord=`nslookup_a $name | tr -d " "`
mxrecord=`nslookup_mx $name | tr -d " "`
if [ "$addr" = "$arecord" ]; then
return 0
elif [ "$addr" = "$mxrecord" ]; then
return 0
else
# echo "name=$name, addr=$addr, A=$arecord MX=$mxrecord"
return 1;
fi
}
#
# nslookup_a -- do an a-record ns lookup
#
nslookup_a() {
echo "$name" | nslookup 2>&1 | awk '
BEGIN {
FS = ":"
on = 0
}
/'$name'/ {
on = 1
}
/Address/ {
if (on) {
print $2
}
}
'
}
#
# nslookup_mx -- do an mx-record ns lookup
#
nslookup_mx() {
echo "set q=mx
$name" | nslookup 2>&1 | awk '
BEGIN {
on = 0
}
/'$name'/ {
on = 1
}
/inet address/ {
if (on) {
print $5
}
}
'
}
#
# headers -- select out just the headers from a message
#
headers() {
name=$1
awk <$name '
BEGIN {
on = 1
}
/.*/ {
if (length == 0) {
on = 0
}
if (on) {
print $0
}
}
'
}
main $*
syntax highlighted by Code2HTML, v. 0.9.1