#!/bin/sh
# Walter Doekes, 2013-2015, Public Domain
# (2015-09-16: bugfix when test $# -ge 5, thanks Rene Santing)
this="`basename "$0"`"

# MD5 func and self-test
md5() { printf "$1" | md5sum | sed -e 's/[[:blank:]].*//'; }
if test `md5 ""` != d41d8cd98f00b204e9800998ecf8427e; then
	echo "$this: md5sum self-test failed!" >&2
	exit 1
fi

# Calculation func and self-test
calc() {
	username=$1; realm=$2; method=$3; digesturi=$4; nonce=$5
	password=$6; match=$7

	a1="$username:$realm:$password" # USERNAME:REALM:PASSWORD
	ha1=`md5 "$a1"`	         # MD5(HA1)
	a2="$method:$digesturi"	 # METHOD:DIGESTURI
	ha2=`md5 "$a2"`	         # MD5(HA2)
	resp=`md5 "$ha1:$nonce:$ha2"`   # MD5(HA1:NONCE:HA2)

	# Output and optional comparison
	echo "A1   = $a1"
	echo "HA1  = $ha1"
	echo "A2   = $a2"
	echo "HA2  = $ha2"
	echo "RESP = $resp"
	if test -n "$match" && test $match != $resp; then
		echo "$this: response mismatch" >&2
		false
	fi
}
if calc 1 2 3 4 5 6 7 >/dev/null 2>&1; then
	echo "$this: calc self-test 1 failed!" >&2
	exit 1
fi
if ! calc 1 2 3 4 5 6 22524e06d1e1b888b67ae1f1b7ed614e >/dev/null 2>&1; then
	echo "$this: calc self-test 2 failed!" >&2
	exit 1
fi

# Digest to keyword function
fromdigest() {
	source="$1"
	keyword=$2
	echo "$source" | sed -e "
		s/^/, /
		s/$/, /
		s/.*[, ]$keyword=\"\\([^\"]*\\)\".*/\1/
		s/.*[, ]$keyword=\\([^, ]\\),.*/\1/
	"
}


# Get arguments
if test $# -eq 1; then
	# echo Authorization:... | hahacalc -
	method="$1"
	echo -n "Password: " && read password </dev/tty
	# read sip headers from stdin
	sed -e '
		s/^[[:blank:]]*//
		s/^Proxy-Authorization:/Authorization:/
		/^Authorization:/!d
		s/Authorization:[[:blank:]]*Digest[[:blank:]]*//
	' | while read -r digest; do
		username=`fromdigest "$digest" username`
		realm=`fromdigest "$digest" realm`
		nonce=`fromdigest "$digest" nonce`
		digesturi=`fromdigest "$digest" uri`
		match=`fromdigest "$digest" response`
		echo 
		echo '==== OUTPUT ===='
		calc $username $realm $method $digesturi $nonce \
			"$password" $match
	done

elif test $# -ge 5; then
	# hahacalc USERNAME REALM METHOD DIGESTURI NONCE...
	password="$6"
	if test -z "$password"; then
		echo -n "Password: " && read password
	fi
	calc $1 $2 $3 $4 $5 "$password" $7

else
	printf "Usage:   $this USERNAME REALM METHOD DIGESTURI NONCE " >&2
	printf '[PASSWORD] [COMPARE]\n' >&2
	printf "Or:      $this METHOD < autorization_headers\n" >&2
	printf "Example: $this 123456789 itsp.com REGISTER " >&2
	printf 'sip:sip.itsp.com:6060 \\\n' >&2
	printf '	   4f7406a80000c2f214774a48d11cc5b ' >&2
	printf '9e533caff7a05904c MYPASSWORD \\\n'
	printf '	   f5787ba2624dfdbcf874f46425d65b53\n' >&2
	printf "Or:      echo 'Authorization:...' | $this REGISTER\n" >&2
	exit 1

fi
