#!/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