#!/bin/sh

#
# Copyright 2004-2005 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
# ident "$Revision: 1.15.4.1 $ SMI"
#

OS=`uname -s`
if [ -z "${OS}" ]; then
   # No I18N at this point
   echo "Unable to determine operating system."
   exit 1
fi
if [ "${OS}" = "SunOS" ]; then
   CACAO_ROOT=/opt/SUNWcacao
   LIB_DIR=${CACAO_ROOT}/lib
elif [ "${OS}" = "AIX" ]; then
   CACAO_ROOT=/opt/SUNWcacao
   LIB_DIR=${CACAO_ROOT}/lib
elif [ "${OS}" = "Linux" ]; then
   CACAO_ROOT=/opt/sun/cacao
   LIB_DIR=${CACAO_ROOT}/private/lib
else
   # No I18N at this point
   echo "Not supported on detected OS \"${OS}\"."
   exit 1
fi

. ${LIB_DIR}/tools/helpers

LOCALHOST=`${HOSTNAME}`

# Local provide
DEFAULT_LANG=${LANG}
DEFAULT_LC_ALL=${LC_ALL}

# Root security directory
SECURITY_DIR=$1

# Temp files for command output
TMP_OUT="${SECURITY_DIR}/tmp.out"

# Sub-directories for JSSE and NSS keys and certificates
JSSE_SECDIR=${SECURITY_DIR}/jsse
NSS_SECDIR=${SECURITY_DIR}/nss
LOCALCA_SECDIR=${NSS_SECDIR}/localca
UNKNOWN_SECDIR=${NSS_SECDIR}/unknown
WELLKNOWN_SECDIR=${NSS_SECDIR}/wellknown

# Security files managed by this script
JSSE_FILES="keystore agent.cert truststore"
LOCALCA_FILES="localca.cert cert8.db key3.db secmod.db"
UNKNOWN_FILES="cert8.db key3.db secmod.db"
WELLKNOWN_FILES="wellknown.cert cert8.db key3.db secmod.db"

# Passwords
TMP_PASSWORD_FILE=${SECURITY_DIR}/password.tmp
PASSWORD_FILE=${SECURITY_DIR}/password
TRUST_PASSWORD="trustpass"
UNKNOWN_PASSWORD="unknownpass"

# Seed file for NSS key generation
TMP_NSSEED="${NSS_SECDIR}/tmp.nsseed"
NSSEED_SIZE=24

###############################################################################
#
# Sets locale parameter (LANG and LC_ALL) to a define value
# $1 locale value for LANG
# $2 locale value for LC_ALL
###############################################################################
setLocale() {
    LANG=${1}
    export LANG
    LC_ALL=${2}
    export LC_ALL
    
    return 0
}

########################################################
#
# Prints a key generation error message on stderr
# and in syslog.
#
# Parameters
# - $1: the message itself
# - $next: the optional message parameters
#
# Return 0
#
########################################################
printKGErrorMessage() {

	msg="$1"
	shift
	params="$*"
	
	printSyslogErrorMessage "${msg}" "${params}"
	printErrorMessage "${msg}" "${params}"
	
	return 0
}

########################################################
#
# Verifies that the parameters are ok before
# proceeding with key generation
#
# Return 1 if bad usage or bad security directory
#        0 if everything is ok
#
########################################################
checkParameters() {

	# Usage 
	cmd="`basename $0`"
	
	if [ -z "${SECURITY_DIR}" -o ! -d "${SECURITY_DIR}" ]; then
	    printErrorMessage "$KEYGEN_USG1" "$cmd"
		printErrorMessage "$KEYGEN_USG2"
	    return 1
	fi

	if [ ! -w "${SECURITY_DIR}" ]; then\
	   printKGErrorMessage "${INVALID_SECURITY_DIR}" "${SECURITY_DIR}"
	   return 1
	fi
	
	return 0
}

########################################################
#
# Verifies that the environment is ok before
# proceeding with key generation
#
# Return 1 if JAVA or CACAO_JAVA_HOME unset
#        0 if everything is ok
#
########################################################
checkEnvironment() {

	if [ \( -z "${JAVA}" \) -o \( -z "${CACAO_JAVA_HOME}" \) ]; then
	   printKGErrorMessage "${MISSING_JAVA_ENV}"
	   return 1
	fi
	
}
	
########################################################
#
# Setup NSS certutil. NSS_CERTUTIL is set if certutil
# found and executable.
#
# Return 0
#
########################################################
setupNSSCertutil() {

	# set NSS_CERTUTIL if NSS was located
	if [ -n "${NSS_TOOLS_HOME}" ]; then
	    
	    certutil_file="${NSS_TOOLS_HOME}/certutil"

		if [ -x "${certutil_file}" ]; then
			NSS_CERTUTIL="${certutil_file}"
		fi
	fi
	
	# don't set LD_LIBRARY_PATH if certutil not found
	if [ -z "${NSS_CERTUTIL}" ]; then
		return 0
	fi

	# Set/export the LD_LIBRARY_PATH for NSS tools.
	if [ -n "${NSS_LIB_HOME}" ]; then
		if [ -n "${LD_LIBRARY_PATH}" ]; then
			LD_LIBRARY_PATH=${NSS_LIB_HOME}:${LD_LIBRARY_PATH}
		else
			LD_LIBRARY_PATH=${NSS_LIB_HOME}
		fi
		
		export LD_LIBRARY_PATH
	fi

	return 0
}

########################################################
#
# Function to generate the master password 
# only readable and writable by root.
#
# Return 1 if failure
#        0 if everything is ok
#
########################################################
generateMasterPassword() {

	# save current umask to restore afterwards
	curumask=`umask`

	# master password file restricted to root access
	umask 077

	# generate the master password with Java secure random service
	${JAVA} -classpath ${JAR_DIR}/cacao_cacao.jar \
		com.sun.cacao.agent.auth.SecurePassword > ${TMP_PASSWORD_FILE}
	
	if [ $? -ne 0 ]; then
		printKGErrorMessage "${MASTER_PWD_FAILED}"
		return 1
	fi
	
	# back to previous umask
	umask $curumask
	
	return 0
	
}

########################################################
#
# Remove a file.
#
# Return 1 if the file exists but cannot be removed
#        0 otherwise
#
########################################################
removeSecurityFile() {

	secfile="$1"
	
    if [ -f "${secfile}" ]; then
		${RM} "${secfile}"
		if [ $? -ne 0 ]; then
			printKGErrorMessage "${CANNOT_REMOVE_SECFILE}" "${secfile}"
			return 1
		else
			return 0
		fi
    fi

}

########################################################
#
# Remove any already existing files.
#
########################################################
cleanSecurityFiles() {

	# Remove JSSE security files
	if [ -d "${JSSE_SECDIR}" ]; then
		for file in ${JSSE_FILES}; do
			removeSecurityFile "${JSSE_SECDIR}/${file}"
		    if [ $? -ne 0 ]; then
		    	return 1
		    fi
		done

		# Remove JSSE directory if empty
		${RMDIR} ${JSSE_SECDIR} 1>&2 2> /dev/null
	fi
	
	# Remove CA security files
	if [ -d "${LOCALCA_SECDIR}" ]; then
		for file in ${LOCALCA_FILES}; do
		    removeSecurityFile "${LOCALCA_SECDIR}/${file}"
		    if [ $? -ne 0 ]; then
		    	return 1
		    fi
		done

		# Remove CA directory if empty
		${RMDIR} ${LOCALCA_SECDIR} 1>&2 2> /dev/null
	fi
		
	# Remove security files for well-known clients
	if [ -d "${WELLKNOWN_SECDIR}" ]; then
		for file in ${WELLKNOWN_FILES}; do
		    removeSecurityFile "${WELLKNOWN_SECDIR}/${file}"
		    if [ $? -ne 0 ]; then
		    	return 1
		    fi
		done
	
		# Remove wellknown directory if empty
		${RMDIR} ${WELLKNOWN_SECDIR} 1>&2 2> /dev/null
	fi
	
	# Remove security files for unknown clients 
	if [ -d "${UNKNOWN_SECDIR}" ]; then
		for file in ${UNKNOWN_FILES}; do
		    removeSecurityFile "${UNKNOWN_SECDIR}/${file}"
		    if [ $? -ne 0 ]; then
		    	return 1
		    fi
		done

		# Remove unknown directory if empty
		${RMDIR} ${UNKNOWN_SECDIR} 1>&2 2> /dev/null
	fi
	
	# Remove the NSS seed file
	if [ -f ${TMP_NSSEED} ]; then
		removeSecurityFile ${TMP_NSSEED}
	    if [ $? -ne 0 ]; then
	    	return 1
	    fi
	fi
	
	# Remove NSS directory if empty
	if [ -d "${NSS_SECDIR}" ]; then
		${RMDIR} ${NSS_SECDIR} 1>&2 2> /dev/null
	fi
	
	return 0
}

########################################################
#
# Generates a seed file to be used by NSS
# certutil to generate keys and certificate requests.
#
# Return 0 if success, non 0 if failure
#
########################################################
seedNSS() {

	# save current umask to restore afterwards
	curumask=`umask`

	# seed file restricted to root access
	umask 077

	# generate the seed file with Java secure random service
	${JAVA} -classpath ${JAR_DIR}/cacao_cacao.jar \
		com.sun.cacao.agent.auth.SecurePassword ${NSSEED_SIZE} > ${TMP_NSSEED}
	
	# save exit code for return value
	returnval=$?
	
	# back to previous umask
	umask $curumask
	
	return $returnval
}

########################################################
#
# Starts key generation
#
# Return 0 if success, non 0 if failure
#
########################################################
startKeyGeneration() {

	# Create the JSSE sub-directory (if necessary)
	${MKDIR} -p ${JSSE_SECDIR}
	
	# Generate key pair for agent (validity -> 7304 days == 20 years)
	${CAT} ${TMP_PASSWORD_FILE} ${TMP_PASSWORD_FILE} | \
		${CACAO_JAVA_HOME}/bin/keytool \
		    -genkey \
		    -alias cacao_agent \
		    -keyalg RSA \
		    -keystore ${JSSE_SECDIR}/keystore \
		    -dname "CN=${LOCALHOST}_agent, OU=N1S, O=Sun Microsystems, L=Grenoble, ST=France, C=FR" \
		    -validity 7304 \
		    > ${TMP_OUT} 2>&1
	
	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${AGENT_KEY_FAILED}" "${DBG_OUT}"
		return 1
	fi

	return 0
}

########################################################
#
# Continues key generation w/o NSS
#
# Return 0 if success, non 0 if failure
#
########################################################
continueKeyGenerationWithoutNSS() {

	# Export the public certificate from this private key
	${CAT} ${TMP_PASSWORD_FILE} ${TMP_PASSWORD_FILE} | \
	${CACAO_JAVA_HOME}/bin/keytool \
		    -export \
		    -alias cacao_agent \
		    -keystore ${JSSE_SECDIR}/keystore \
		    -rfc \
		    -file ${JSSE_SECDIR}/agent.cert \
		    > ${TMP_OUT} 2>&1

	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${EXPORT_CERTIF_FAILED}" "${DBG_OUT}"
		return 1
	fi

	# Create the truststore from this public certificate
	setLocale "C" "C"
	echo yes | ${CACAO_JAVA_HOME}/bin/keytool \
		    -import \
		    -alias cacao_agent \
		    -keypass ${TRUST_PASSWORD} \
		    -storepass ${TRUST_PASSWORD} \
		    -file ${JSSE_SECDIR}/agent.cert \
		    -keystore ${JSSE_SECDIR}/truststore \
		    > ${TMP_OUT} 2>&1
	setLocale "${DEFAULT_LANG}" "${DEFAULT_LC_ALL}"

	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${CREATION_TRUST_STORE_FAILED}" "${DBG_OUT}"
		return 1
	fi
	
	return 0
}


########################################################
#
# Continue key generation with NSS
#
# Return 0 if success, non 0 if failure
#
########################################################
continueKeyGenerationWithNSS() {

	# Generate the NSS directory (if necessary)
	${MKDIR} -p ${NSS_SECDIR}
	
	# Create the CA directory (if necessary)
	${MKDIR} -p ${LOCALCA_SECDIR}

	# Generate the CA db files
	${NSS_CERTUTIL} \
		    -N \
		    -d ${LOCALCA_SECDIR} \
		    -f ${TMP_PASSWORD_FILE} \
		    > ${TMP_OUT} 2>&1

	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${LOCAL_CA_DB_FAILED}" "${DBG_OUT}"
		return 1
	fi

	# Generate the seed file for generating local CA keys
	seedNSS
			
	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${SEED_GENERATION_FOR_CA_FAILED}" "${DBG_OUT}"
		return 1
	fi
	
	# Generate the local self-signed certificate authority
	${NSS_CERTUTIL} \
		    -S \
		    -n cacao_ca \
		    -k rsa \
		    -s "CN=${LOCALHOST}_ca, OU=N1S, O=Sun Microsystems, L=Grenoble, ST=France, C=FR" \
		    -x \
		    -v 240 \
		    -t "uCT,uCT,uCT" \
		    -z ${TMP_NSSEED} \
		    -d ${LOCALCA_SECDIR} \
		    -f ${TMP_PASSWORD_FILE} \
		    > ${TMP_OUT} 2>&1

	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${GENERATION_CA_FAILED}" "${DBG_OUT}"
		return 1
	fi
	
	# Export the local CA certificate
	${NSS_CERTUTIL} \
		    -L \
		    -n cacao_ca \
		    -a \
		    -o ${LOCALCA_SECDIR}/localca.cert \
		    -d ${LOCALCA_SECDIR} \
		    -f ${TMP_PASSWORD_FILE} \
		    > ${TMP_OUT} 2>&1

	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${EXPORT_CA_CERTIF_FAILED}" "${DBG_OUT}"
		return 1
	fi
	
	
	# Create a certificate signing request for the agent
	${CAT} ${TMP_PASSWORD_FILE} ${TMP_PASSWORD_FILE} | \
	${CACAO_JAVA_HOME}/bin/keytool \
		    -certreq \
		    -alias cacao_agent \
		    -sigalg MD5withRSA \
		    -file ${JSSE_SECDIR}/agent.crq \
		    -keystore ${JSSE_SECDIR}/keystore \
		    > ${TMP_OUT} 2>&1

	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${CREATION_CSR_FAILED}" "${DBG_OUT}"
		return 1
	fi
	
	# Sign the agent certificate with the local CA
	${NSS_CERTUTIL} \
		    -C \
		    -c cacao_ca \
		    -v 240 \
		    -a \
		    -i ${JSSE_SECDIR}/agent.crq \
		    -o ${JSSE_SECDIR}/agent.cert \
		    -d ${LOCALCA_SECDIR} \
		    -f ${TMP_PASSWORD_FILE} \
		    > ${TMP_OUT} 2>&1

	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${SIGNING_CSR_FAILED}" "${DBG_OUT}"
		return 1
	fi
	
	
	# Import trusted certificate authority in the keystore
	${CAT} ${TMP_PASSWORD_FILE} | ${CACAO_JAVA_HOME}/bin/keytool \
		    -import \
		    -noprompt \
		    -alias cacao_ca \
		    -file ${LOCALCA_SECDIR}/localca.cert \
		    -keystore ${JSSE_SECDIR}/keystore \
		    > ${TMP_OUT} 2>&1

	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${IMPORT_CSR_FAILED}" "${DBG_OUT}"
		return 1
	fi
	
	# Import certificate reply
	${CAT} ${TMP_PASSWORD_FILE} ${TMP_PASSWORD_FILE} | \
	${CACAO_JAVA_HOME}/bin/keytool \
		    -import \
		    -alias cacao_agent \
		    -file ${JSSE_SECDIR}/agent.cert \
		    -keystore ${JSSE_SECDIR}/keystore \
		    > ${TMP_OUT} 2>&1

	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${IMPORT_CERTIF_FAILED}" "${DBG_OUT}"
		return 1
	fi
	
	
	# Remove the agent certificate request
	${RM} -f ${JSSE_SECDIR}/agent.crq
	
	# Create the truststore containing the local CA public certificate
	setLocale "C" "C"
	echo yes | ${CACAO_JAVA_HOME}/bin/keytool \
		    -import \
		    -alias cacao_ca \
		    -keypass ${TRUST_PASSWORD} \
		    -storepass ${TRUST_PASSWORD} \
		    -file ${LOCALCA_SECDIR}/localca.cert \
		    -keystore ${JSSE_SECDIR}/truststore \
		    > ${TMP_OUT} 2>&1

    setLocale "${DEFAULT_LANG}" "${DEFAULT_LC_ALL}"

	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${CREATION_TRUST_STORE_FAILED}" "${DBG_OUT}"
		return 1
	fi
	

	# Create the directory for well-known clients (if necessary)
	${MKDIR} -p ${WELLKNOWN_SECDIR}

	# Generate the well-known clients db files
	${NSS_CERTUTIL} \
		    -N \
		    -d ${WELLKNOWN_SECDIR} \
		    -f ${TMP_PASSWORD_FILE} \
		    > ${TMP_OUT} 2>&1

	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${CREATION_TRUST_STORE_FAILED}" "${DBG_OUT}"
		return 1
	fi

	# Generate the seed file for generating well-known client keys
	seedNSS
			
	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${SEED_GENERATION_FOR_WELLKNOWN_FAILED}" "${DBG_OUT}"
		return 1
	fi
	
	# Generate the well-known client keys and original self-signed
	# certificate 
	# Cannot use -G because it does not support -z option

	${NSS_CERTUTIL} \
		    -S \
		    -n cacao_wellknown \
		    -x \
		    -k rsa \
		    -s "CN=${LOCALHOST}_wellknown, OU=N1S, O=Sun Microsystems, L=Grenoble, ST=France, C=FR" \
		    -v 20 \
		    -t "u,u,u" \
		    -z ${TMP_NSSEED} \
		    -d ${WELLKNOWN_SECDIR} \
		    -f ${TMP_PASSWORD_FILE} \
		    > ${TMP_OUT} 2>&1

	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${GENERATION_KEY_WELLKNOWN_FAILED}" "${DBG_OUT}"
		return 1
	fi
	
	# Now delete the self-signed certificate that we didn't want
	${NSS_CERTUTIL} \
		    -D \
		    -n cacao_wellknown \
		    -d ${WELLKNOWN_SECDIR} \
		    -f ${TMP_PASSWORD_FILE} \
		    > ${TMP_OUT} 2>&1

	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${DELETION_SELF_SIGNED_FAILED}" "${DBG_OUT}"
		return 1
	fi
	
	# Generate the seed file for generating well-known CSR
	seedNSS
			
	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${SEED_GENERATION_FOR_WELLKNOWN_FAILED}" "${DBG_OUT}"
		return 1
	fi
	
	# Generate a CSR for well-known clients
	${NSS_CERTUTIL} \
		    -R \
		    -n cacao_wellknown \
		    -k rsa \
		    -s "CN=${LOCALHOST}_wellknown, OU=N1S, O=Sun Microsystems, L=Grenoble, ST=France, C=FR" \
		    -a \
		    -z ${TMP_NSSEED} \
		    -o ${WELLKNOWN_SECDIR}/wellknown.crq \
		    -d ${WELLKNOWN_SECDIR} \
		    -f ${TMP_PASSWORD_FILE} \
		    > ${TMP_OUT} 2>&1

	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${GENERATION_CSR_WELLKNOWN_FAILED}" "${DBG_OUT}"
		return 1
	fi

	# Remove the seed file the script does not need anymore
	${RM} ${TMP_NSSEED}
	
	# Sign the CSR with the local CA certificate
	${NSS_CERTUTIL} \
		    -C \
		    -c cacao_ca \
		    -v 240 \
		    -a \
		    -i ${WELLKNOWN_SECDIR}/wellknown.crq \
		    -o ${WELLKNOWN_SECDIR}/wellknown.cert \
		    -d ${LOCALCA_SECDIR} \
		    -f ${TMP_PASSWORD_FILE} \
		    > ${TMP_OUT} 2>&1

	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${SIGNING_CSR_WELLKNOWN_FAILED}" "${DBG_OUT}"
		return 1
	fi
	
	# Import the local CA certificate into the well-known security store
	${NSS_CERTUTIL} \
		    -A \
		    -n cacao_ca \
		    -t "CT,CT,CT" \
		    -a \
		    -i ${LOCALCA_SECDIR}/localca.cert \
		    -d ${WELLKNOWN_SECDIR} \
		    -f ${TMP_PASSWORD_FILE} \
		    > ${TMP_OUT} 2>&1

	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${IMPORT_CA_CERTIF_WELLKOWN}" "${DBG_OUT}"
		return 1
	fi
		
	# Promote the new certificate as the well-known client certificate
	${NSS_CERTUTIL} \
		    -A \
		    -n cacao_wellknown \
		    -t "u,u,u" \
		    -a \
		    -i ${WELLKNOWN_SECDIR}/wellknown.cert \
		    -d ${WELLKNOWN_SECDIR} \
		    -f ${TMP_PASSWORD_FILE} \
		    > ${TMP_OUT} 2>&1

	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${IMPORT_CERTIF_REPLY_WELLKNOWN_FAILED}" "${DBG_OUT}"
		return 1
	fi
		
	# Remove the wellknown CSR
	${RM} ${WELLKNOWN_SECDIR}/wellknown.crq
	
	
	# Create the directory for unknown clients (if necessary)
	${MKDIR} -p ${UNKNOWN_SECDIR}

	# Create the password file for unknown security store
	UNKNOWN_PASSWORD_FILE=${UNKNOWN_SECDIR}/password
	${ECHO} ${UNKNOWN_PASSWORD} > ${UNKNOWN_PASSWORD_FILE}
	
	# Generate the unknown clients db files
	${NSS_CERTUTIL} \
		    -N \
		    -d ${UNKNOWN_SECDIR} \
		    -f ${UNKNOWN_PASSWORD_FILE} \
		    > ${TMP_OUT} 2>&1

	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${UNKNOWN_CLIENT}" "${DBG_OUT}"
		return 1
	fi

	# Import the local CA certificate into the unknown security store
	${NSS_CERTUTIL} \
		    -A \
		    -n cacao_ca \
		    -t "CT,CT,CT" \
		    -a \
		    -i ${LOCALCA_SECDIR}/localca.cert \
		    -d ${UNKNOWN_SECDIR} \
		    -f ${UNKNOWN_PASSWORD_FILE} \
		    > ${TMP_OUT} 2>&1

	if [ $? -ne 0 ]; then
		DBG_OUT=`${CAT} ${TMP_OUT}`
		printKGErrorMessage "${IMPORT_CA_UNKNOWN}" "${DBG_OUT}"
		return 1
	fi
		
		
	# Remove the password file for unknown security store
	${RM} ${UNKNOWN_PASSWORD_FILE}
	
	# Even if the mask is correct, every file created by certutil has a 
	# restricted set of permissions. So enforce the permissions really required
	for file in ${LOCALCA_FILES}; do
		${CHMOD} 644 ${LOCALCA_SECDIR}/${file}
	done
	for file in ${UNKNOWN_FILES}; do
		${CHMOD} 644 ${UNKNOWN_SECDIR}/${file}
	done
	for file in ${WELLKNOWN_FILES}; do
		${CHMOD} 644 ${WELLKNOWN_SECDIR}/${file}
	done
	
	return 0
}

########################################################
#
# Terminates key generation
#
# Return 0
#
########################################################
terminateKeyGeneration() {

	# Enforce the right permissions for JSSE files
	for file in ${JSSE_FILES}; do
		${CHMOD} 644 ${JSSE_SECDIR}/${file}
	done
	
	# Promote the temporary password file as the new official master password
	${MV} ${TMP_PASSWORD_FILE} ${PASSWORD_FILE}
		
	# Remove the temporary output file
	${RM} ${TMP_OUT}
	
	return 0

}

########################################################
#
# Generates the keys and certificates.
#
# Parameters:
# - useNSS: 0 to use NSS, other value to forget NSS
#
# Return
# - 0 if generation successful
# - non 0 if generation failed
#
########################################################
generateKeys() {

	useNSS=$1
	
	# start key generation
	startKeyGeneration
	
	if [ $? -ne 0 ]; then
		return 1
	fi
	
	if [ $useNSS -eq 0 ]; then
		continueKeyGenerationWithNSS
	else
		continueKeyGenerationWithoutNSS
	fi
	
	if [ $? -ne 0 ]; then
		return 1
	else	
		terminateKeyGeneration
		return $?
	fi
	
}

########################################################
#
# Main
#
########################################################
###  To run properly, certutil needs to have write access to the current
###  directory where it puts temporary files (certificate requests).
###  The script completely fails if certutil has not this permission.

# Performs checks
checkParameters
if [ $? -ne 0 ]; then
	exit 1
fi

checkEnvironment
if [ $? -ne 0 ]; then
	exit 1
fi

# move to security directory
cd ${SECURITY_DIR}

# most security files can be read by any user
umask 022

# Setup NSS certutil
setupNSSCertutil
if [ $? -ne 0 ]; then
	exit 1
fi

# Generate the master password 
generateMasterPassword
if [ $? -ne 0 ]; then
	exit 1
fi

# Clean all the security files
cleanSecurityFiles
if [ $? -ne 0 ]; then
	exit 1
fi

# Generate the keys and certificate
# -> retry when NSS certutil used but failed
if [ -z "${NSS_CERTUTIL}" ]; then
	
	# generate keys without NSS and do not retry
	generateKeys 1
	exit $?
	
else

	# generate keys with NSS
	generateKeys 0
	
	# if it fails, try again w/o NSS
	if [ $? -ne 0 ]; then
		
		# log a specific message
		printKGErrorMessage "${RETRY_WO_NSS}"

		# clean anything previously generated first
		cleanSecurityFiles
		if [ $? -ne 0 ]; then
			exit 1
		fi
		
		# re-generate
		generateKeys 1
		exit $?
	else
		exit 0
	fi
fi
