#!/bin/sh
#
# Copyright  2010 by Baptiste Daroussin <bapt@FreeBSD.org>,
# Copyright  2010 by Freddy Dissaux <freddy.dsx@free.fr>,
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.


exit_msg() {
	echo $1
	exit $2
}

ask_passwd() {
	stty -echo
	echo -n "Enter password:"
	read PASSWD1
	echo
	echo -n "Confirm password:"
	read PASSWD2
	echo

	if [ "${PASSWD1}" != "${PASSWD2}" ]; then
		exit_msg "Password mismatch" 1
	fi
	PASSWORD=${PASSWD1}
	stty echo
}

usage() {
	echo "
$0 [ -c ] [ -m ] [ -D ] passwdfile username
$0 -b [ -c ] [ -m | -d | -s ] [ -D ] passwdfile username password
$0 -nb [ -m | -d | -s ] username password
"
	exit 1
}


while getopts "bcdmnsD" FLAG; do
	case "${FLAG}" in
		b) BATCH_MODE=bopt ;;
		c) CREATE_PASSWD=copt ;;
		d) ALGO=crypt;;
		n) DISPLAY_RESULT=nopt ;;
		m) ALGO=md5;;
		s) ALGO=sha;;
		D) DELETE_USER=Dopt;;
		*) usage;;
	esac
done

shift $(( ${OPTIND} - 1 ))

test -z "${ALGO}" && ALGO=crypt

case "${DISPLAY_RESULT}${BATCH_MODE}$#" in
	noptbopt2)
		USERNAME=$1
		PASSWORD=$2
		;;
	bopt3)
		FILE=$1
		USERNAME=$2
		PASSWORD=$3
		;;
	nopt1)
		USERNAME=$1
		;;
	bopt2|2)
		FILE=$1
		USERNAME=$2
		;;
	*) usage
		;;
esac

case "${DISPLAY_RESULT}${CREATE_PASSWD}" in
	noptcopt)
		echo "you cannot display the result and create the passwd file"
		exit 1
		;;
	nopt|copt)
		;;
	*)
		test -f ${FILE} || exit_msg "File ${FILE} not found, use -c option to create it" 1
		egrep -q "^${USERNAME}:" ${FILE} && REPLACEPWD=ropt
		;;
esac


if [ -z ${DELETE_USER} ]; then
	test -z ${PASSWORD} && ask_passwd

	case "${ALGO}" in
		crypt)
			GENPASSWD=$(openssl passwd -crypt ${PASSWORD})
			;;
		md5)
			GENPASSWD=$(openssl passwd -apr1 ${PASSWORD})
			;;
		sha)
			GENPASSWD="{SHA}$(echo -n ${PASSWORD} | openssl dgst -sha1 -binary | openssl base64)"
			;;
	esac
fi

test -n "${DISPLAY_RESULT}" && exit_msg "${USERNAME}:${GENPASSWD}" 0

case "${CREATE_PASSWD}${REPLACEPWD}${DELETE_USER}" in
	copt)
		echo "${USERNAME}:${GENPASSWD}" > ${FILE}
		;;
	ropt)
		echo "Updating password for user ${USERNAME}"
		#escape GENPASSWD to allow ed substitution
		GENPASSWD=$(echo ${GENPASSWD} | sed -e 's,/,\\/,g')
		echo -e ",s/^${USERNAME}:.*/${USERNAME}:${GENPASSWD}/g\nw" | ed -s ${FILE} > /dev/null
		;;
	roptDopt)
		echo "Deleting password for user ${USERNAME}"
		echo -e "/^${USERNAME}.*/\nd\nw" | ed -s ${FILE} > /dev/null
		;;
	Dopt)
		exit_msg "No such user ${USERNAME}" 1
		;;
	*)
		echo "${USERNAME}:${GENPASSWD}" >> ${FILE}
		;;
esac

exit 0
# vim:set sw=4 sts=4 ts=4 :
