#!/bin/bash

# The PIG password generator
# The passGenerator function code is 
# mainly written by typedeaF and anonymous
# http://www.osix.net/modules/article/?id=570

# (C) 2009 Dennis Leeuw
# License: GPLv2

function passGenerator {
	# Needs MAXSIZE to be set

	# Sets the maximum size of the password the script will generate
	if [ -z $MAXSIZE ]; then
		MAXSIZE=8
	fi

	# Used in conjunction with modulus to keep random numbers in range of the array size
	MODNUM=${#array1[*]}

	# Keeps track of the number characters in the password we have generated
	local pwd_len=0

	# Make sure PASS is empty
	local PASS=""

	# The outer while loop starts at 0 and loops till MAXSIZE, creating a passwd char each iteration.
	# The shells $RANDOM variable creates a semi-random unsigned number. This is our entropy. =x
	# x simply holds some random unsigned int that will be used to make the character scramble.
	# 500 was choosen for speed and nothing else. Leave out the mod 500 if you want or change it.
	# The inner loop creates the password characters.
	# Mod MODNUM keeps the random number inside the size of the array so it doesnt over index.
	while [ $pwd_len -lt $MAXSIZE ]; do
		x=$(($RANDOM%500))
		y=0
	 	while [ $y -lt $x ]; do
			((y++))
			index=$(($RANDOM%$MODNUM))
		done
	  	PASS="${PASS}${array1[$index]}"
  	  	((pwd_len++))
	done

	# Output
	echo $PASS
}

function print_help {
	echo "The DAS password generator"
	echo "Syntax: das_passgen [-h|-c <class>|-t <type>|-p <password>|-l <password length>]"
	echo "	If no options are given a 8 character password is printed."
	echo "  -c character classes to be used in the password"
	echo "     1 = small caps"
	echo "     2 = big caps"
	echo "     3 = numbers"
	echo "     4 = other characters"
	echo "     Classes can be combined like 123 or 1234"
	echo "	-p needs a plain text password."
	echo "	   If -p is given then -l can not be given."
	echo "	-l needs a number to indicate the length of the password to be"
	echo "	   generated"
	echo "	-t the type of password to output, needs -p to hold the password"
	echo "	   base64            - outputs a WINDOWS base64 encoded password"
	echo "	   md5,smd5,sha,ssha - outputs a slappasswd encoded password with"
	echo "	                       the given hash"
	exit 0
}

#------#
# Main #
#------#

# Character class arrays
array_smallcaps=( q w e r t y u i o p a s d f g h j k l z x c v b n m )
array_bigcaps=( Q W E R T Y U I O P A S D F G H J K L Z X C V B N M )
array_digits=( 1 2 3 4 5 6 7 8 9 0 )
array_signs=( '!' '@' '$' '%' '#' '&' '*' '=' '+' '?' )

# Get options
while getopts  "hl:p:t:c:" flag
do
  case "$flag" in
	c) # Set character class
	   declare -a array1
	   for (( i=0; $i < ${#OPTARG}; i=$(($i+1)) )); do
		class=${OPTARG:$i:1}
		if [ $class = 1 ]; then
			array1=( "${array1[@]}" "${array_smallcaps[@]}" )
		elif [ $class = 2 ]; then
			array1=( "${array1[@]}" "${array_bigcaps[@]}" )
		elif [ $class = 3 ]; then
			array1=( "${array1[@]}" "${array_digits[@]}" )
		elif [ $class = 4 ]; then
			array1=( "${array1[@]}" "${array_signs[@]}" )
		fi
	   done
	;;
        l) # Password length
		MAXSIZE=$OPTARG
        ;;
	t) # Type of password
		TYPE=$OPTARG
	;;
	p) # Password
		PASS=$OPTARG
	;;
	h)
		print_help
	;;
	*)
		print_help
	;;

  esac
done

# Check for empty array1
if [ "x${array1[*]}" = "x" ]; then
	array1=( "${array_smallcaps[@]}" "${array_bigcaps[@]}" "${array_digits[@]}" "${array_signs[@]}" )
fi

## Check options
# Password given so we need a type to do hashing
if [ "x$PASS" = "x" ] && [ "x${TYPE}" != "x" ]; then
	echo "Error: Type given but no password"
	exit 1
elif [ "x$PASS" != "x" ] && [ "x${MAXSIZE}" != "x" ]; then
	echo "Error: Password and length given"
	exit 2
fi

# No password given
if [ "x$PASS" = "x" ]; then
	# Check if MAXSIZE is empty or only numbers
	if [ "x${MAXSIZE//[0-9]/}" != "x" ]; then
		echo "Error: -l can only be a positive number"
		exit 2
	fi
	PASS=`passGenerator`
fi

## From here on we have a password
# Output and exit
if [ "${TYPE}" = "base64" ]; then
	echo -n "\"${PASS}\"" | iconv -f UTF8 -t UTF16LE | base64 -w 0
	echo
elif [ "x${TYPE}" != "x" ]; then
	# HASH=`echo ${TYPE#*-} | tr [a-z] [A-Z]`
	/usr/sbin/slappasswd -s $PASS -h "{`echo ${TYPE} | tr [a-z] [A-Z]`}"
else
	echo $PASS
fi

exit 0

