#!/bin/sh

FILE="$HOME"/.ssh/authorized_keys
FPDIR="/var/cache/openssh-blacklist"
NUID=`id -u`
LINE=0
VERSION=2.4
VERBOSE=1
DELETE=
STRONG=

if [ "$1" = "-h" ]
then
	echo "Use: $0 [-d] [-f file] [-h] [-l] [-L] [-q] [-s] [-v] [-V]"
	echo "	-d delete mode, weak keys are deleted from the file, the backup is created before deletion"
	echo "	-f file, define file to be checked"
	echo "	-h help, this help"
	echo "	-l use local database rather than system one"
	echo "	-L license, print license"
	echo "	-q quiet, do not display info about the keys"
	echo "	-s strong mode, all keys which are not 100% verifiable are considered as weak"
	echo "	-v verbose, print full key content in reports"
	echo "	-V version, print version"
	exit 0
fi

if [ "$1" = "-V" ]
then
	echo "$0 version $VERSION, (c) J.F.Ch. 2009"
	exit 0
fi

if [ "$1" = "-L" ]
then
	echo "This program is free software; you can redistribute it and/or modify"
	echo "it under the terms of the GNU General Public License as published by"
	echo "the Free Software Foundation; version 2 of the License."
	exit 0
fi

TMPFILE=`mktemp /tmp/iwak-"$NUID"-XXXXXXXXXXXX`
chmod 0700 "$TMPFILE"

while true
do
	if [ "$1" = "-f" ]
	then
		FILE="$2"
		shift 2
		continue
	fi
	if [ "$1" = "-v" ]
	then
		VERBOSE=2
		shift
		continue
	fi
	if [ "$1" = "-d" ]
	then
		DELETE=1
		shift
		continue
	fi
	if [ "$1" = "-q" ]
	then
		VERBOSE=0
		shift
		continue
	fi
	break
	if [ "$1" = "-s" ]
	then
		STRONG=1
		shift
		continue
	fi
	break
	if [ "$1" = "-l" ]
	then
		if [ -d "$HOME"/.openssh-blacklist ]
		then
			FPDIR="$HOME"/.openssh-blacklist
		fi
		shift
		continue
	fi

done

if [ -n "$1" ]
then
	echo "$0 invalid parameter $1, use $0 -h for help"
	exit 1
fi

if [ ! -f "$FILE" ]
then
	echo "$0 file $FILE does not exist"
	rm -f "$TMPFILE"
	exit 0
fi

if [ $NUID -ne `ls -lnd "$FILE" | cut -f3 -d" "` ]
then
	echo "$0 you do not own $FILE"
	exit 0
fi

if [ ! -r "$FILE" ]
then
	echo "$0 file $FILE is not readable"
	rm -f "$TMPFILE"
	exit 2
fi

if [ -n "$DELETE" ]
then
	if [ ! -w "$FILE" ]
	then
		echo "$0 file $FILE is not writable"
		rm -f "$TMPFILE"
		exit 2
	fi

	cat /dev/null > "$FILE".tmp
	chmod 0700 "$FILE".tmp
fi

cat "$FILE" | while read A B C
do
	LINE=`expr $LINE + 1`
	echo "$A $B $C" > "$TMPFILE"
	echo "$TMPFILE" | ssh-keygen -l 2>/dev/null | sed 's/://g' | (
		read LEN KEY REST
		case "$A" in
			ssh-rsa)
				grep "^$KEY\$" "$FPDIR"/fingerprint_*_rsa_"$LEN" >/dev/null 2>&1
				if [ $? -eq 0 ]
				then
					case "$VERBOSE" in
						1)
							echo  "$0 weak key found on line $LINE: $C"
							;;
						2)
							echo  "$0 weak key found on line $LINE: $A $B $C"
							;;
					esac
					RV=1
				else
					if [ -n "$STRONG" ]
					then
						KEYS=`cat "$FPDIR"/fingerprint_*_rsa_"$LEN" 2>/dev/null | wc -l`
						if [ $KEYS -ne 98301 ]
						then
							if [ $VERBOSE -ne 0 ]
							then
								echo "$0 only $KEYS from 98301 possible ones tested on line $LINE"
							fi
							RV=1
						else
							if [ -n "$DELETE" ]
							then
								echo "$A $B $C" >> "$FILE".tmp
							fi
						fi
					else
						if [ -n "$DELETE" ]
						then
							echo "$A $B $C" >> "$FILE".tmp
						fi
					fi
				fi
				;;
			ssh-dsa)
				grep "^$KEY\$" "$FPDIR"/fingerprint_*_dsa_"$LEN" >/dev/null 2>&1
				if [ $? -eq 0 ]
				then
					case "$VERBOSE" in
						1)
							echo  "$0 weak key found on line $LINE: $C"
							;;
						2)
							echo  "$0 weak key found on line $LINE: $A $B $C"
							;;
					esac
					RV=1
				else
					if [ -n "$STRONG" ]
					then
						KEYS=`cat "$FPDIR"/fingerprint_*_dsa_"$LEN" 2>/dev/null | wc -l`
						if [ $KEYS -ne 98301 ]
						then
							if [ $VERBOSE -ne 0 ]
							then
								echo "$0 only $KEYS from 98301 possible ones tested on line $LINE"
							fi
							RV=1
						else
							if [ -n "$DELETE" ]
							then
								echo "$A $B $C" >> "$FILE".tmp
							fi
						fi
					else
						if [ -n "$DELETE" ]
						then
							echo "$A $B $C" >> "$FILE".tmp
						fi
					fi
				fi
				;;
			*)
				if [ -n "$STRONG" ]
				then
					case "$VERBOSE" in
						1)
							echo "$0 on line $LINE unknown key type $A"
							;;
						2)
							echo "$0 on line $LINE unknown key $A $B $C"
							;;
					esac
					RV=1
				else
					if [ -n "$DELETE" ]
					then
						echo "$A $B $C" >> "$FILE".tmp
					fi
				fi
				;;
		esac
	)
done

rm -f "$TMPFILE"
if [ -n "$DELETE" ]
then
	if [ $RV -ne 0 ]
	then 
		cp "$FILE" "$FILE"-`date %Y%m%d%H%M%S`.bak
		cat "$FILE".tmp > "$FILE"
	fi
	rm -f "$FILE".tmp
fi
exit $RV

