#!/usr/bin/ksh
#
# ident "@(#)ccreds	1.4 02/04/15 SMI"
#
# Copyright 1998-2002 Sun Microsystems, Inc.  All rights reserved.
#
# Key package generation + initialization script
#

#############################################################
#
# Function definitions
#
#############################################################

################################################################
#
#	parse_config_file:
#
#		Parse configuration file for key package and
#		certificate generation
#
function parse_config_file {

	entities_type_parsed=false
	dn_suffix_parsed=false
	host_domain_parsed=false
	validity_parsed=false
	keysize_parsed=false
	password_parsed=false
	entities_file_parsed=false
	cred_dir_parsed=false
	rootca_dn_parsed=false
	rootca_username_parsed=false
	trusted_keys_file_parsed=false
	
	while read keyword value; do
		if [[ -z $keyword ]]; then
			print "$pgm: `gettext utskicat 'ERROR - Keyword missing in CA config file'`"
			return 1
		fi
		if [[ -z $value ]]; then
			print "$pgm: `gettext utskicat 'ERROR - Keyword '$keyword' has no value in CA config file'`"
			return 1
		fi
		case $keyword in
			SKI_ENTITIES_TYPE )
				if [[ $entities_type_parsed = true ]]; then
				    print "$pgm: 'gettext utskicat `ERROR - Multiple SKI_ENTITIES_TYPE lines in CA config file'`"
				    return 1
				fi
				# Remove leading blanks and ", if given
				entities_type=${value#*\"}
				# Remove trailing " and blanks, if given
				entities_type=${entities_type%\"*}
				entities_type_parsed=true ;;
			SKI_DN_SUFFIX )
				if [[ $dn_suffix_parsed = true ]]; then
				    print "$pgm: `gettext utskicat 'ERROR - Multiple SKI_DN_SUFFIX lines in CA config file'`"
				    return 1
				fi
				# Remove leading blanks and ", if given
				dn_suffix=${value#*\"}
				# Remove trailing " and blanks, if given
				dn_suffix=${dn_suffix%\"*}
				dn_suffix_parsed=true ;;
			SKI_HOST_DOMAIN )
				if [[ $host_domain_parsed = true ]]; then
				    print "$pgm: `gettext utskicat 'ERROR - Multiple SKI_HOST_DOMAIN lines in CA config file'`"
				    return 1
				fi
				# Remove leading blanks and ", if given
				host_domain=${value#*\"}
				# Remove trailing " and blanks, if given
				host_domain=${host_domain%\"*}
				host_domain_parsed=true ;;
			SKI_VALIDITY )
				if [[ $validity_parsed = true ]]; then
				    print "$pgm: `gettext utskicat 'ERROR - Multiple SKI_VALIDITY lines in CA config file'`"
				    return 1
				fi
				let validity=$value
				status=$?
				if (($status != 0)); then
					return $status
				fi
				validity_parsed=true ;;
			SKI_KEYSIZE )
				if [[ $keysize_parsed = true ]]; then
				    print -n "$pgm: `gettext utskicat 'ERROR - Multiple SKI_KEYSIZE lines in CA config file'`"
				    return 1
				fi
				let keysize=$value
				status=$?
				if (($status != 0)); then
					return $status
				fi

                    		if (($global_version == 1 && $keysize > 512)); then
				    print "$pgm: `gettext utskicat 'ERROR - RSA key size must not be greater than 512 bits - global version'`"
				    return 1
				fi
				keysize_parsed=true ;;
			SKI_PASSWORD )
				if [[ $password_parsed = true ]]; then
				    print "$pgm: `gettext utskicat 'ERROR - Multiple SKI_PASSWORD lines in CA config file'`"
				    return 1
				fi
				encrpwd=$value
				if [[ $encrpwd != RANDOM ]]; then
					pwd_mode=PWD_SAME
				fi
				password_parsed=true ;;
			SKI_ENTITIES_FILE )
				if [[ $entities_file_parsed = true ]]; then
				    print "$pgm: `gettext utskicat 'ERROR - Multiple SKI_ENTITIES_FILE lines in CA config file'`"
				    return 1
				fi
				entities_file=$value
				entities_file_parsed=true ;;
			SKI_CRED_DIR )
				if [[ $cred_dir_parsed = true ]]; then
				    print "$pgm: `gettext utskicat 'ERROR - Multiple SKI_CRED_DIR lines in CA config file'`"
				    return 1
				fi
				if [[ $value = "/etc/opt/SUNWut/http/ski" ]]; then
					print "$pgm: `gettext utskicat 'ERROR - Can not specify /etc/opt/SUNWut/http/ski as SKI_CRED_DIR'`"
					return 1
				fi
				cred_dir=$value
				cred_dir_parsed=true ;;
			SKI_ROOT_CA_DN )
				if [[ $rootca_dn_parsed = true ]]; then
				    print "$pgm: `gettext utskicat 'ERROR - Multiple SKI_ROOT_CA_DN lines in CA config file'`"
				    return 1
				fi
				# Remove leading blanks and ", if given
				rootca_dn=${value#*\"}
				# Remove trailing " and blanks, if given
				rootca_dn=${rootca_dn%\"*}
				rootca_dn_parsed=true ;;
			SKI_ROOT_CA_LOGIN )
				if [[ $rootca_username_parsed = true ]]; then
				    print -n "$pgm: `gettext utskicat 'ERROR - Multiple SKI_ROOT_CA_LOGIN lines in CA config file'`"
				    return 1
				fi
				# Remove leading blanks and ", if given
				rootca_username=${value#*\"}
				# Remove trailing " and blanks, if given
				rootca_username=${rootca_username%\"*}
				rootca_username_parsed=true ;;
			SKI_TRUSTED_KEYS )
				if [[ $trusted_keys_parsed = true ]]; then
				    print "$pgm: `getext 'ERROR - Multiple SKI_TRUSTED_KEYS lines in CA config file'`"
				    return 1
				fi
				trusted_keys_file=$value
				trusted_keys_file_parsed=true ;;
			* )
				print -n "$pgm: `gettext utskicat 'ERROR - Unrecognized keyword '` '$keyword' `gettext utskicat 'in CA config file'`"
				return 1 ;;
		esac
	done
	
	#
	# Make sure that all configuration parameters with no default
	# values have been set
	#
	
	if [[ -z $rootca_dn ]]; then
		print "$pgm: `gettext utskicat 'ERROR - No Root Certificate DN provided'`"
		return 1
	fi
	
	if [[ $pwd_mode = PWD_SAME && -z $encrpwd ]]; then
		print "$pgm: `gettext utskicat 'ERROR - No key package password provided'`"
		return 1
	fi

	if [[ $entities_type = user || $entities_type = USER ]]; then
		entities_type=USER
	elif [[ $entities_type = host || $entities_type = HOST ]]; then
		entities_type=HOST
	else
		print -n "$pgm: `gettext utskicat 'ERROR - Wrong entities type in configuration file. '`"
		print `gettext utskicat 'Type must be either \"user\" or \"host\"'`
	fi
	
}

################################################################
#
#	enter_target_name:
#
#		Enter DN and username for each target
#
function enter_target_name {

	finished=false
	while [[ $finished = false ]]; do
		# Distinguished Name
		done=false
		while [[ $done = false ]]; do
			if [[ $entities_type = USER ]]; then
				read REPLY?"$pgm: `gettext utskicat 'Enter Distinguished Name of'` $entities_type (e.g. \"`gettext utskicat 'cn=John Smith, ou=ENG, o=SUN, c=US'`\"), `gettext utskicat 'or q[uit]:'` "
			else
				print "$pgm: `gettext utskicat 'Enter hostname (format: \"cn=<host.domain-name>\")'`, "
				read REPLY?"          or q[uit]: "
			fi
			if [[ -z $REPLY ]]; then
				if [[ $entities_type = USER ]]; then
					print "$pgm: `gettext utskicat 'No Distinguished Name given - try again!'`"
				else
					print "$pgm: `gettext utskicat 'No hostname given - try again!'`"
				fi
			elif [[ "$REPLY" = "q" || "$REPLY" = "quit" ||
				      "$REPLY" = "Q" || "$REPLY" = "QUIT" ]]; then
				return
			else
				dname=$REPLY
				done=true
			fi
		done
	
		# username or IP address
		done=false
		if [[ $entities_type = USER ]]; then
			while [[ $done = false ]]; do
				read REPLY?"$pgm: `gettext utskicat 'Enter UNIX login name of'` $entities_type, `gettext utskicat 'or q[uit]:'` "
				if [[ -z $REPLY ]]; then
					print "$pgm: `gettext utskicat 'No UNIX login name given - try again!'`"
				elif [[ "$REPLY" = "q" || "$REPLY" = "quit" ||
					      "$REPLY" = "Q" || "$REPLY" = "QUIT" ]]; then
					return
				else
					name=$REPLY
					keypkg_file="$keypkgs_path/$name.KEYPKG"
					cert_file="$certs_path/$name.CERT"
					done=true
				fi
			done
		else
			while [[ $done = false ]]; do
				read REPLY?"$pgm: Enter host IP address, or q[uit]: "
				if [[ -z $REPLY ]]; then
					print "$pgm: `gettext utskicat 'No host IP address given - try again!'`"
				elif [[ "$REPLY" = "q" || "$REPLY" = "quit" ||
					      "$REPLY" = "Q" || "$REPLY" = "QUIT" ]]; then
					return
				else
					ip=$REPLY
					keypkg_file="$keypkgs_path/$ip.KEYPKG"
					cert_file="$certs_path/$ip.CERT"
					done=true
				fi
			done
		fi
	
		if [[ $pwd_mode = PWD_RANDOM ]]; then
			gen_passwd
		fi

		# Create credentials for target
		create_credentials
		status=$?
		if (($status != 0)); then
			print "$pgm: `gettext utskicat 'Failed to create credentials for target'` '$dname'"
			return $status
		else
			print "$pgm: `gettext utskicat 'Successfully created key package and certificate for target'` '$dname' ($name)"
			print
		fi
	done
}

################################################################
#
# is_domain_name:
#
# Function: check whether $host_name conatins '.'.
# Input: $host_name
# Output: $contain_domain_name
#
function is_domain_name {
	is_dn=`echo $host_name|fgrep "."`
	if [[ -z $is_dn ]]; then
		contain_domain_name=false
	else
		contain_domain_name=true
	fi
}

################################################################
#
#	read_targets_from_file:
#
#		Read target from user/hosts file
#
function read_targets_from_file {

	if [[ -z $keypkgs_path || -z $certs_path ]]; then
		print "$pgm: `gettext utskicat 'ERROR - No keypkg and/or certs directory given'`"
		return 1
	fi
	
	# make sure a DN suffix or host domain name has been provided
	if [[ $entities_type = USER ]]; then
		if [[ -z $dn_suffix ]]; then
			print "$pgm: `gettext utskicat 'ERROR - No DN suffix provided'`"
			return 1
		fi
	else
		if [[ -z $host_domain ]]; then
			print "$pgm: `gettext utskicat 'ERROR - No host domain name provided'`"
			return 1
		fi
	fi

	# Go through the hosts or password file, line by line
	while read pos1 pos2 pos3 pos4 pos5 pos6 pos7; do

		if [[ $entities_type = USER ]]; then
			name=$pos1
			gecos=$pos5
			if [[ -z $name ]]; then
			    print "$pgm: `gettext utskicat 'ERROR - UNIX login name missing in user input file'`"
			    return 1
			fi
			if [[ -z $gecos ]]; then
			    print "$pgm: `gettext utskicat 'ERROR - gecos missing in user input file'`"
			    return 1
			fi

			# Check for & symbol in GECOS field, and replace it
			case $gecos in
				*\& )
					gecos=${gecos%\&}$name ;;
				\&* )
					gecos=$name${gecos#\&} ;;
			esac

			keypkg_file="$keypkgs_path/$name.KEYPKG"
			cert_file="$certs_path/$name.CERT"

			# add '\' before every ','
			gecos=`echo $gecos | sed -e 's/,/\\\\,/g'`

			# Concatenate gecos with DN suffix
			dname="CN=$gecos [$name],$dn_suffix"
		else
			ip=$pos1
			name=$pos2
			if [[ -z $ip ]]; then
			    print "$pgm: `gettext utskicat 'ERROR - IP address missing in hosts input file'`"
			    return 1
			fi
			if [[ -z $name ]]; then
			    print "$pgm: `gettext utskicat 'ERROR - Hostname missing in hosts input file'`"
			    return 1
			fi
	
			keypkg_file="$keypkgs_path/$ip.KEYPKG"
			cert_file="$certs_path/$ip.CERT"
		
			host_name=$name
			is_domain_name
			if [[ $contain_domain_name = true ]]; then
				domain_suffix=""
			else
				domain_suffix=".$host_domain"
			fi
			# Concatenate domain name with gecos
			if [[ -z $dn_suffix ]]; then
				dname="CN=$name$domain_suffix"
			else
				dname="CN=$name$domain_suffix, $dn_suffix"
			fi
		fi

		if [[ $pwd_mode = PWD_RANDOM ]]; then
			gen_passwd
		fi

		create_credentials
		status=$?
		if (($status != 0)); then
			return $status
		fi
	done
}

################################################################
#
# read string from user w/o printing on screen, store in $encrpwd
#
readpwd () {
        trap "stty echo; exit 1" 2
        stty -echo
	encrpwd=""
	print `gettext utskicat 'Enter key package password for new key packages: '`
	read encrpwd
        stty echo
        trap "exit 1" 2
}

################################################################
#
#	create_credentials:
#
#		Generate key package and certificate
#
function create_credentials {

	# Generate key package
	if (( $keysize > 0 )); then
	    keypkg -C -u "$keypkg_file" -k "$dname" -p "$encrpwd" -l $keysize $verbose
	else
	    keypkg -C -u "$keypkg_file" -k "$dname" -p "$encrpwd" $verbose
	fi
	status=$?
	if (($status != 0)); then
		return $status
	fi

	# Add the trusted keys from the file provided by the CA
	if [[ -n $trusted_keys_file ]]; then
		print "\n"
		print "`gettext utskicat '# Adding public keys from'` '$trusted_keys_file'"
		print "#\t`gettext utskicat 'into the key package trusted public key list'`"
		keypkg -A -u "$keypkg_file" -p "$encrpwd" $verbose < "$trusted_keys_file"
		status=$?
		if (($status != 0)); then
			/bin/rm -f $keypkg_file
			return $status
		fi
	else
		# Install Root CA certificate as trusted key in
		# generated key package
		print "\n"
		print `gettext utskicat '# Adding the Root CA public key into the key package trusted public key list'`
		keypkg -A -u "$keypkg_file" -p "$encrpwd" $verbose < "$root_cert_file"
		status=$?
		if (($status != 0)); then
			/bin/rm -f $keypkg_file
			return $status
		fi

		# Install this Sub CA certificate as trusted key in
		# generated key package.
		# First check to see if the subca IS the rootca
		# (root CA is running create_creds)
		/usr/bin/diff "$root_cert_file" "$subca_cert_file" > /dev/null
		status=$?
		if (($status != 0)); then
			print "\n"
			print `gettext utskicat '# Adding the current CA public key into the key package trusted public key list'`
			keypkg -A -u "$keypkg_file" -p "$encrpwd" $verbose < "$subca_cert_file"
			status=$?
			if (($status != 0)); then
				/bin/rm -f $keypkg_file
				return $status
			fi
		fi
	fi

	if [[ $keypkg_only = false ]]; then
		# Generate certification request
		certreq -u "$keypkg_file" -c "$challenge" -p "$encrpwd" \
			$verbose > /tmp/certreq
		status=$?
		if (($status != 0)); then
			/bin/rm -f $keypkg_file
			return $status
		fi

		# Certify it
		if (( $validity > 0 )); then
		    $bin_dir/certify -u "$cert_file" -t $validity $verbose < /tmp/certreq
		else
		    $bin_dir/certify -u "$cert_file" $verbose < /tmp/certreq
		fi
		status=$?
		if (($status != 0)); then
			/bin/rm -f $keypkg_file
			/bin/rm -f /tmp/certreq
			return $status
		fi
	
		# Remove the temporary certreq file
		/bin/rm -f /tmp/certreq
	fi

	# Store user/host name and user/host DN in new_cred_owners_file
	if [[ $entities_type = USER ]]; then
		print "$name\t$dname" >> $new_cred_owners_file
	else
		print "$ip\t$dname" >> $new_cred_owners_file
	fi
	status=$?
	if (($status != 0)); then
		/bin/rm -f $keypkg_file
		/bin/rm -f $cert_file
		return $status
	fi

	# Store user/host name and password in new_password_file
	if [[ $entities_type = USER ]]; then
		print "$name\t$encrpwd" >> $new_password_file
	else
		print "$ip\t$encrpwd" >> $new_password_file
	fi
	status=$?
	if (($status != 0)); then
		/bin/rm -f $keypkg_file
		/bin/rm -f $cert_file
		return $status
	fi

	print
	print "\t+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n"
}

################################################################
#
#	remove_creds:
#
#		Remove generated credentials
#
function remove_creds {
	if (( $ski_dir_created > 0 )); then
		/bin/rm -rf $ski_dir
	fi
	if (( $cred_dir_created > 0 )); then
		/bin/rm -rf $cred_dir
	else
		if (( $keypkgs_dir_created > 0 )); then
			/bin/rm -rf $keypkgs_path
		fi
		if (( $certs_dir_created > 0 )); then
			/bin/rm -rf $certs_path
		fi
	fi
	/bin/rm -f $new_cred_owners_file
	/bin/rm -f $new_password_file
}

################################################################
#
#	usage:
#
#		print command line options
#
function usage {
	print `gettext utskicat 'usage: create_creds [-v] [-k] [-c config_file]'`
}

################################################################
#
#	create_dir:
#
function create_dir {
	if [[ ! -a $1 ]]; then
		# path does not exist
		mkdir $1
		status=$?
		if (($status != 0)); then
			print "$pgm: `gettext utskicat 'ERROR - Cannot create directory'` \"$1\""
			return $status
		fi
		# Set directory generation flag
		case $2 in
			CERTS )
				let certs_dir_created=1 ;;
			KEYPKGS )
				let keypkgs_dir_created=1 ;;
			SKI_CRED_DIR )
				let cred_dir_created=1 ;;
			ETCSKI )
				let ski_dir_created=1 ;;
			* )
				print -n "$pgm: `gettext utskicat 'ERROR - Unrecognized keyword '`"
				print "'$keyword' `gettext utskicat 'in create_dir routine'`"
				return 1 ;;
		esac
	else
		# path exists, check if it is a directory
		if [[ ! -d $1 ]]; then
			print "$pgm: 'gettext utskicat 'ERROR'` - \"$1\" `gettext utskicat 'is not a directory'`"
			return 1
		fi
	fi
	# Do we have write permission?
	if [[ ! -w $1 ]]; then
		print -n "$pgm: `gettext utskicat 'ERROR - You do not have WRITE permission on'`"
		print " \"$1\""
		return 1
	fi
}

################################################################
#
#	gen_passwd:
#
#	Generate random keypkg password
#
function gen_passwd {
	dd if=/dev/random ibs=1 count=4 2>/dev/null | od -x -N $passwd_len | read encrpwd
	encrpwd=${encrpwd#* }
}

################################################################
#
#	eval_lic_string:
#
#	Evaluate license string; exit if no more licenses available
#
function eval_lic_string {
    /usr/bin/nawk '{ input_len = length($0);
	avail_str_start = match($0, "certificates available:");
	if ( avail_str_start == 0 ) {
		print "Invalid input"
		exit -1
	}
	avail_str_len = RLENGTH;
	avail_certs_num_len = input_len - avail_str_start - avail_str_len + 1;
	avail_certs_num = substr($0, avail_str_start + avail_str_len, avail_certs_num_len);
	if ( avail_certs_num == 0 )
		exit -1 }'
}
	
#############################################################

# initialize path variables
PATH=/bin:/usr/bin:/opt/SUNWut/http/ski/bin
export PATH
def_cred_dir="/etc/opt/SUNWut/http/ski"
certs_dir="certs"
certs_path=""
keypkgs_dir="keypkgs"
keypkgs_path=""
new_cred_owners_file_name="new_cred_list"
new_password_file_name="ski_passwords"
ski_dir="/etc/opt/SUNWut/http/ski"
dev_random="/dev/random"
bin_dir="/opt/SUNWut/http/ski/bin"

# Set default values
def_validity_str="1095 days (3 years)"
let def_validity=1095
let def_passwd_len=4
def_challenge="challengePassword"
def_pwd_mode=PWD_RANDOM
def_pwd_mode_printable="random passwords"
def_op_mode=INTERACTIVE
def_entities_type=USER
let global_version=0

# initialize option-related variables
verbose=""
config_file=""

# initialize other variables
let cred_dir_created=0
let certs_dir_created=0
let keypkgs_dir_created=0
let ski_dir_created=0
let validity=$def_validity
let passwd_len=$def_passwd_len
pwd_mode=$def_pwd_mode
challenge=$def_challenge
dn_suffix=""
host_domain=""
encrpwd=""
root_cert_file=""
subca_cert_file=""
rootca_dn=""
rootca_dn_normalized=""
rootca_username=""
trusted_keys_file=""
entities_file=""
cred_dir=$def_cred_dir
keypkg_only=false

pgm_path=$0
pgm=${pgm_path##/*/}

# Determine whether we are running an global or domestic version of SecTools
skilibvers=`/usr/bin/ls -al /opt/SUNWut/http/ski/lib/libski.so 2>/dev/null`
if [[ -z $skilibvers ]]; then
	print "$pgm: `gettext utskicat 'ERROR - Cannot determine if using global or domestic version of Sectools'`"
	exit 1
fi
skilibtype=${skilibvers##*-\> }
if [[ -z $skilibtype ]]; then
	print "$pgm: `gettext utskicat 'ERROR - Cannot determine if using global or domestic version of Sectools'`"
	exit 1
fi
if [[ ! -s /opt/SUNWut/http/ski/lib/$skilibtype ]]; then
	print "$pgm: `gettext utskicat 'ERROR - Cannot determine if using global or domestic version of Sectools'`"
	exit 1
fi
ls -al /opt/SUNWut/http/ski/lib/$skilibtype 2>/dev/null | grep "global" >> /dev/null
status=$?
if (($status == 0)); then
	# global version
	let global_version=1
fi

# Set default key size
if (($global_version == 1)); then
	let def_keysize=512
else
	let def_keysize=768
fi
let keysize=$def_keysize

#
# process command-line options
#

while getopts ":kvc:" opt; do
	case $opt in
		k )
		   keypkg_only=true ;;
		v )
		    verbose="-v" ;;
		c )
		    config_file=$OPTARG ;;
		\? )
		    usage
		    exit 1 ;;
	esac
done

# Check if certificate licenses are available. If no more licenses
# are available, we exit.
if [[ $keypkg_only = false ]]; then
	$bin_dir/certify -a 
	status=$?
	if (($status != 0)); then
		print 'first'
		print `gettext utskicat 'No certificate licenses available'`
		exit $status
	fi
	$bin_dir/certify -a | eval_lic_string
	status=$?
	if (($status != 0)); then
		print 'second'
		print `gettext utskicat 'No certificate licenses available'`
		exit $status
	fi
fi

#
# Let the user select the mode in which configuration parameters
# are supplied
#

if [[ -z $config_file ]]; then
	done=false
	while [[ $done = false ]]; do
		print `gettext utskicat '#'`
		print `gettext utskicat '# Configuration mode:'`
		print "#\n"
		print "\t $pgm `gettext utskicat 'requires certain configuration values'`"
		print "\t `gettext utskicat 'to be entered.  Some of the values include a key size,'`"
		print "\t `gettext utskicat 'validity period, and key package password.\n'`"
		print "\t `gettext utskicat 'Have you already entered these values in a configuration'`"
		print "\t `gettext utskicat 'file, or would you like to be prompted for the necessary '`"
		print "\t `gettext utskicat 'information?\n'`"
		print "\t `gettext utskicat 'Choose one of the following:\n'`"
		
		done=true	# assume user will make a valid choice
		{
			print "\t\t `gettext utskicat '1) Interactive'`"
			print "\t\t `gettext utskicat '2) Configuration file'`"
			print "\t\t `gettext utskicat '3) quit\n'`"
		} >&2

		read REPLY?"`gettext utskicat '         Configuration mode (press RETURN for default:'` $def_op_mode) ? "
		print "\n"
		if [[ -z $REPLY ]]; then
			op_mode=$def_op_mode
		else
			case $REPLY in
				1 ) op_mode=INTERACTIVE ;;
				2 ) op_mode=FILE ;;
				3 ) exit 0;;
				* ) print "\t `gettext utskicat 'Invalid selection. Try again!\n'`"
				    done=false;;
			esac
		fi
	done
else
	op_mode=FILE
fi

# Read configuration parameters from file or command line
if [[ $op_mode = FILE ]]; then
	if [[ -z $config_file ]]; then
		done=false
		while [[ $done = false ]]; do
			print "\t `gettext utskicat 'Enter configuration file name,'`"
			read config_file?"`gettext utskicat '                 or q[uit]: '`"
			print "\n"
			if [[ -z $config_file ]]; then
				print -n "\t `gettext utskicat 'No configuration file given - try again!\n'`"
			elif [[ $config_file = q ]]; then
				exit 0
			else
				done=true
			fi
		done
	fi
	# check if configuration file exists, and if it is readable
	if [[ ! -a $config_file ]]; then
		print -n "\t `gettext utskicat 'ERROR - CA configuration file'` '$config_file' "
		print `gettext utskicat 'does not exist.'`
		exit 1
	elif [[ ! -r $config_file ]]; then
		print "\t `gettext utskicat 'ERROR - You do not have read permission on CA configuration file'` '$config_file'."
		exit 1
	fi
	print "\t `gettext utskicat 'Using configuration file'` '$config_file\n'"

	# Parse the CA configuration file
	IFS=:
	grep "^[^#]" $config_file | parse_config_file
	status=$?
	if (($status != 0)); then
		exit $status
	fi

else
	# Prompt for RSA key size in domestic version only
	if (($global_version == 1)); then
		print "#"
		print "# `gettext utskicat 'Key size:'`"
		print "#\n"
		print "\t `gettext utskicat 'Generated keypair(s) will have 512 bit key size (global version)\n\n'`"
	else
	    done=false
	    while [[ $done = false ]]; do
		print "#"
		print "# `gettext utskicat 'Key size:'`"
		print "#\n"
		print "\t `gettext utskicat 'How long should the key size of the generated keypairs be?\n'`"
		print "\t `gettext utskicat 'Choose one of the following:\n'`"
		done=true #assume user will make a valid choice
		{
			print "\t\t 1) 512"
			print "\t\t 2) 768"
			print "\t\t 3) 1024 `gettext utskicat '(Recommended for CAs)'`"
			print "\t\t 4) `gettext utskicat 'quit\n'`"
		} >&2
		read REPLY?"         `gettext utskicat 'Key size (press RETURN for default:'` $def_keysize) ? "
		print "\n"

		if [[ -z $REPLY ]]; then
			let keysize=$def_keysize
		else
			case $REPLY in
				1 ) let keysize=512 ;;
				2 ) let keysize=768 ;;
				3 ) let keysize=1024 ;;
				4 ) exit 0;;
				* ) print "\t `gettext utskicat 'Invalid selection. Try again!\n'`"
				    done=false;;
			esac
		fi
	    done
	fi

	# Validity
	if [[ $keypkg_only = false ]]; then
		print "#"
		print "# `gettext utskicat 'Certificate lifetime:'`"
		print "#\n"
		print "\t `gettext utskicat 'How long should the generated certificates be valid?\n'`"
		print "\t `gettext utskicat 'Enter certificate validity period in number of days,'`"
		print "\t `gettext utskicat 'or q[uit].\n'`"
		print "         `gettext utskicat 'Certificate lifetime'`"
		read REPLY?"         `gettext '(press RETURN for default:'` $def_validity_str) ? "
		print "\n"
		if [[ -z $REPLY ]]; then
			let validity=$def_validity
		else
			if [[ "$REPLY" = "q" || "$REPLY" = "quit" ||
			      "$REPLY" = "Q" || "$REPLY" = "QUIT" ]]; then
				exit 0
			fi
			let validity=$REPLY
			status=$?
			if (($status != 0)); then
				exit $status
			fi
		fi
	fi

	# Key package password mode selection
	done=false
	while [[ $done = false ]]; do
		print "#"
		print "# `gettext utskicat 'Key package password generation mode:'`"
		print "#\n"
		print "\t `gettext utskicat 'Would you like to use randomly generated passwords for each'`"
		print "\t `gettext utskicat 'individual entity,'`"
		print "\t `gettext utskicat 'or would you like to assign the same password to each entity?\n'`"
		print "\t `gettext utskicat 'Choose one of the following:\n'`"
		done=true # assume user will make a valid choice
		{
			print "\t\t 1) `gettext utskicat 'Random password'`"
			print "\t\t 2) `gettext utskicat 'Same password for every entity'`"
			print "\t\t 3) `gettext utskicat 'quit\n'`"
		} >&2
		print "\t `gettext utskicat 'Password generation mode'`"
		read REPLY?"         `gettext utskicat '(press RETURN for default:'` $def_pwd_mode_printable) ? "
		print "\n"
		if [[ -z $REPLY ]]; then
			pwd_mode=$def_pwd_mode
		else
			case $REPLY in
				1 ) pwd_mode=PWD_RANDOM ;;
				2 ) pwd_mode=PWD_SAME ;;
				3 ) exit 0;;
				* ) print "\t `gettext utskicat 'Invalid selection. Try again!\n'`"
				    done=false;;
			esac
		fi
	done

	if [[ $pwd_mode = PWD_RANDOM && ! -p $dev_random ]]; then
		print "\t `gettext utskicat '/dev/random not installed on machine.'`"
		exit 1
	fi

	# Key package password
	if [[ $pwd_mode = PWD_SAME ]]; then
		done=false
		while [[ $done = false ]]; do
			print "#"
			print "# `gettext utskicat 'Key package password for the new key packages:'`"
			print "#\n"
			print -n "\t "
			readpwd
			if [[ -z $encrpwd ]]; then
				print -n "\t `gettext utskicat 'No key package password given - try again!\n'`"
			else
				done=true
			fi
			print "\n"
		done
	fi

	# Entities type
	done=false
	while [[ $done = false ]]; do
		print "#"
		print "# `gettext utskicat 'Entity type:'`"
		print "#\n"
		print "\t `gettext utskicat 'Shall the credentials be issued to USERS or HOSTS?\n'`"
		print "\t `gettext utskicat 'Choose one of the following:\n'`"
		done=true	# assume user will make a valid choice
		{
			print "\t\t 1) `gettext utskicat 'Users'`"
			print "\t\t 2) `gettext utskicat 'Hosts'`"
			print "\t\t 3) `gettext utskicat 'quit\n'`"
		} >&2
		read REPLY?"         `gettext utskicat 'Entity type (press RETURN for default:'` $def_entities_type) ? "
		print "\n"
		if [[ -z $REPLY ]]; then
			entities_type=$def_entities_type
		else
			case $REPLY in
				1 ) entities_type=USER ;;
				2 ) entities_type=HOST ;;
				3 ) exit 0;;
				* ) print "\t `getext 'Invalid selection. Try again!\n'`"
				    done=false;;
			esac
		fi
	done

	# User or host file
	print "#"
	print "# $entities_type `gettext utskicat 'file:'`"
	print "#\n"
	print -n "\t `gettext utskicat 'Each'` $entities_type `gettext utskicat 'for'` "
	if [[ $entities_type = USER ]]; then
		print -n `gettext utskicat 'whom '`
	else
		print -n `gettext utskicat 'which '`
	fi
	print `gettext utskicat 'a key package and certificate will be created'`
	print "\t `gettext utskicat 'can be entered by hand or listed in a file.\n'`"
	print "\t `gettext utskicat 'If you have prepared a '` $entities_type `gettext 'file, you may enter its'`"
	print "\t `gettext utskicat 'filename now.\n'`"
	print "\t `gettext utskicat 'Otherwise press RETURN to list each '` $entities_type `gettext utskicat 'individually,'`"
	print "\t or q[uit].\n"
	read REPLY?"         $entities_type `gettext utskicat 'filename ? '`"
	print "\n"
	if [[ -n $REPLY ]]; then
		if [[ "$REPLY" = "q" || "$REPLY" = "quit" ||
			  "$REPLY" = "Q" || "$REPLY" = "QUIT" ]]; then
			exit 0
		else
			entities_file=$REPLY
		fi
	fi

	# DN suffix
	if [[ -n $entities_file ]]; then
		done=false
		while [[ $done = false ]]; do
			print "#"
			print "# `gettext utskicat 'Distinguished Name suffix:'`"
			print "#\n"
			print -n "\t `gettext utskicat 'Enter Distinguished Name suffix '`"
			print "(`gettext utskicat 'e.g. \"o=SUN, c=US\"'`),"
			if [[ $entities_type = HOST ]]; then
				print "\t `gettext utskicat 'or press RETURN if you do not want a suffix,'`"
			fi
			read REPLY?"         `gettext utskicat 'or q[uit]: '`"
			print "\n"
			if [[ -z $REPLY ]]; then
				if [[ $entities_type = USER ]]; then
					print -n "\t `gettext utskicat 'No Distinguished Name suffix given - try again!\n'`"
				else
					print "\t `gettext utskicat 'No DN suffix given\n'`"
					done=true
				fi
			elif [[ "$REPLY" = "q" || "$REPLY" = "quit" ||
				      "$REPLY" = "Q" || "$REPLY" = "QUIT" ]]; then
				exit 0
			else
				dn_suffix=$REPLY
				# Remove leading ", if given
				dn_suffix=${dn_suffix#\"}
				# Remove trailing ", if given
				dn_suffix=${dn_suffix%\"}
				done=true
			fi
		done
	fi

	# Host Domain
	if [[ -n $entities_file && $entities_type = HOST ]]; then
		done=false
		while [[ $done = false ]]; do
			print "#"
			print "# `gettext utskicat 'Domain name:'`"
			print "#\n"
			print "\t `gettext utskicat 'Enter domain name (e.g. \"eng.sun.com\"),'`"
			read REPLY?"                 `gettext utskicat 'or q[uit]: '`"
			print "\n"
			if [[ -z $REPLY ]]; then
				print "\t `gettext utskicat 'No domain name given - try again!\n'`"
			elif [[ "$REPLY" = "q" || "$REPLY" = "quit" ||
				"$REPLY" = "Q" || "$REPLY" = "QUIT" ]]; then
				exit 0
			else
				host_domain=$REPLY
				# Remove leading ", if given
				host_domain=${host_domain#\"}
				# Remove trailing ", if given
				host_domain=${host_domain%\"}
				done=true
			fi
		done
	fi

	# Root certificate
	done=false
	while [[ $done = false ]]; do
		print "#"
		print "# `gettext utskicat 'Root Certificate Authority:'`"
		print "#\n"
		print "\t `gettext utskicat 'Enter Root CA Distinguished Name (e.g. \"o=SUN, c=US\"),'`"
		read REPLY?"         `gettext utskicat 'or q[uit]: '`"
		print "\n"
		if [[ -z $REPLY ]]; then
			print "\t `gettext utskicat 'No Root CA Distinguished Name given - try again!\n'`"
		elif [[ "$REPLY" = "q" || "$REPLY" = "quit" ||
		      	"$REPLY" = "Q" || "$REPLY" = "QUIT" ]]; then
			exit 0
		else
			# Remove leading ", if given
			rootca_dn=${REPLY#\"}
			# Remove trailing ", if given
			rootca_dn=${rootca_dn%\"}
			done=true
		fi
	done

	# Root CA's UNIX login name
	done=false
	while [[ $done = false ]]; do
		rootca_username=`/usr/bin/id | /usr/bin/nawk \
		    '{ pos_open=match($0, "\\\\("); pos_close=match($0, "\\\\)");
		    name=substr($0, pos_open+1, pos_close-pos_open-1); print name }'`
		print "#\n"
		print "\t `gettext utskicat 'Enter Root CA UNIX login name (e.g.'` \"$rootca_username\"),"
		read REPLY?"         `gettext utskicat 'or q[uit]:'` "
		print "\n"
		if [[ -z $REPLY ]]; then
			# Use the default login name
			done=true
		elif [[ "$REPLY" = "q" || "$REPLY" = "quit" ||
		      	"$REPLY" = "Q" || "$REPLY" = "QUIT" ]]; then
			exit 0
		else
			# Remove leading ", if given
			rootca_username=${REPLY#\"}
			# Remove trailing ", if given
			rootca_username=${rootca_username%\"}
			done=true
		fi
	done

	# Trusted Keys file
	done=false
	while [[ $done = false ]]; do
		print "#"
		print "# `gettext utskicat 'Trusted Public Keys File:'`"
		print "#\n"
		print "\t `gettext utskicat 'Enter Filename containing certificates whose public'`"
		print "\t `gettext utskicat 'keys shall be added to the trusted public key list in'`"
		print "\t `gettext utskicat 'each of the newly generated key packages,'`"
		print "\t `gettext utskicat 'or enter RETURN if you have no such file,'`"
		read REPLY?"         `gettext utskicat 'or q[uit]: '`"
		print "\n"
		if [[ -z $REPLY ]]; then
			done=true
		elif [[ "$REPLY" = "q" || "$REPLY" = "quit" ||
		      	"$REPLY" = "Q" || "$REPLY" = "QUIT" ]]; then
			exit 0
		else
			# Remove leading ", if given
			trusted_keys_file=${REPLY#\"}
			# Remove trailing ", if given
			trusted_keys_file=${trusted_keys_file%\"}
			done=true
		fi
	done

	# Directory pathname
	done=false
	while [[ $done = false ]]; do
		print "#"
		print "# `gettext utskicat 'Directory for New Credentials:'`"
		print "#\n"
		print "\t `gettext utskicat 'Enter directory pathname under which the key package and'`"
		print "\t `gettext utskicat 'certificate directories will be stored,'`"
		print "\t `gettext utskicat 'or q[uit].\n'`"
		read REPLY?"         `gettext utskicat 'Directory name ? '`"
		print "\n"
		if [[ -z $REPLY ]]; then
			print "\t `gettext utskicat 'No directory pathname given - try again!\n'`"
		elif [[ "$REPLY" = "q" || "$REPLY" = "quit" ||
			"$REPLY" = "Q" || "$REPLY" = "QUIT" ]]; then
			exit 0
		else
			if [[ "$REPLY" = "/etc/opt/SUNWut/http/ski" ]]; then
				print "\t `gettext utskicat 'Not allowed to store into /etc/opt/SUNWut/http/ski - try again\n'`"
			else
				cred_dir=$REPLY
				done=true
			fi
		fi
	done
fi

# check if user/host file exists, and if it is readable
if [[ -n $entities_file ]]; then
	if [[ ! -a $entities_file ]]; then
		print "$pgm: `gettext utskicat 'ERROR - User file '` '$entities_file' `gettext utskicat 'does not exist.'`"
		exit 1
	elif [[ ! -r $entities_file ]]; then
		print -n "$pgm: `gettext utskicat 'ERROR - You do not have read permission on '`"
		print "$entities_type `gettext utskicat 'file'` '$entities_file'."
		exit 1
	fi
fi

# check if the trusted keys file exists
if [[ -n $trusted_keys_file ]]; then
	if [[ ! -a $trusted_keys_file ]]; then
		print "$pgm: `gettext utskicat 'ERROR - Public Trusted Key file'` '$trusted_keys_file' `gettext utskicat 'does not exist.'`"
		exit 1
	elif [[ ! -r $trusted_keys_file ]]; then
		print -n "$pgm: `gettext utskicat 'ERROR - You do not have read permission on '`"
		print "$trusted_keys_file `gettext utskicat 'file'` '$trusted_keys_file'."
		exit 1
	fi
fi

# Check if the directory $cred_dir exists, and make sure it's a directory.
# If it does not exist, create it.
create_dir $cred_dir SKI_CRED_DIR
status=$?
if (($status != 0)); then
	remove_creds
	exit $status
fi

# Make absolute pathname
cred_dir=`(
	cd $cred_dir 2>/dev/null
	status=$?
	if (($status != 0)); then
		echo ""
	else
		echo $PWD
	fi
	)`
if [[ -z $cred_dir ]]; then
	print "$pgm: `gettext utskicat 'Cannot establish path to credentials directory\n'`"
	remove_creds
	exit 1
fi

new_cred_owners_file="${cred_dir:-$def_cred_dir}/$new_cred_owners_file_name"
new_password_file="$ski_dir/$new_password_file_name"
certs_path="${cred_dir:-$def_cred_dir}/$certs_dir"
keypkgs_path="${cred_dir:-$def_cred_dir}/$keypkgs_dir"

#
# Determine the Root CA username
#
rootca_dn_normalized=`skicert -N -k "$rootca_dn"`
if [[ -z $rootca_dn_normalized ]]; then
	remove_creds
	exit 1
fi
#rootca_username=`fnsearch user -a "" \
#"onc_distinguished_name=='$rootca_dn_normalized'" 2>/dev/null`
if [[ -z $rootca_username ]]; then
	rootca_username=`/usr/bin/id | /usr/bin/nawk \
	    '{ pos_open=match($0, "\\\\("); pos_close=match($0, "\\\\)");
	    name=substr($0, pos_open+1, pos_close-pos_open-1); print name }'`
#    	print -n "$pgm: `gettext utskicat 'ERROR - Root CA with Distinguished Name '`"
#	print "'$rootca_dn_normalized' `gettext utskicat 'does not exist in your system'`"
#	remove_creds
#	exit 1
fi

root_cert_file="$certs_path/$rootca_username.CERT"
subca_cert_file="$certs_path/subca"
/bin/rm -f "$root_cert_file"
/bin/rm -f "$subca_cert_file"

# Check if the keypks and cert directories and new_cred_owners_file/
# new_password_file files already exist.
# If they do exist, ask the user to back them up or to quit
done=false
while [[ $done = false ]]; do
	if [[ -a $new_cred_owners_file || -a $new_password_file ||
			-a $keypkgs_path || -a $certs_path ]]; then
		print "`gettext utskicat 'The following files/directories already exist:\n'`"
		if [[ -a $new_cred_owners_file ]]; then
			print "\t$new_cred_owners_file"
		fi
		if [[ -a $new_password_file ]]; then
			print "\t$new_password_file"
		fi
		if [[ -a $keypkgs_path ]]; then
			print "\t$keypkgs_path"
		fi
		if [[ -a $certs_path ]]; then
			print "\t$certs_path"
		fi
		print "\n"
		print "`gettext utskicat 'Please archive the above files/directories.\n'`"
		print "`gettext utskicat 'You can either quit this program now, or archive the above'`"
		print "`gettext utskicat 'files/directories and then continue with this program.\n'`"
		read REPLY?"`gettext utskicat 'Do you want to quit this program now? [n]: '`"
		if [[ "$REPLY" = "y" || "$REPLY" = "Y" ]]; then
			exit 0
		else
			print "\n"
			print "`gettext utskicat 'Creating shell from where you can archive the'`"
			print "`gettext utskicat 'specified files/directories ...'`"
			print "(`gettext utskicat 'Donot forget to type \"exit\" to exit the shell.'`)\n"
			export PS1="`gettext utskicat 'Archival shell--> '`"
			/usr/bin/ksh
			print "\n"
			read REPLY?"`gettext utskicat 'Hit any key when done archiving: '`"
			print "\n"
		fi
	else
		done=true
	fi
done

# Check if the sub directories for certs and keypkgs
# create "certs" directory
create_dir $certs_path CERTS
status=$?
if (($status != 0)); then
	remove_creds
	exit $status
fi

# create "keypkgs" directory
create_dir $keypkgs_path KEYPKGS
status=$?
if (($status != 0)); then
	remove_creds
	exit $status
fi

# Check if the ski_dir directory already exists.
# If not, create it.
create_dir $ski_dir ETCSKI
status=$?
if (($status != 0)); then
	remove_creds
	exit $status
fi

#
# Summarize
#
print "# `gettext utskicat 'Generated key packages will be stored under'` '$keypkgs_path'"
if [[ $keypkg_only = false ]]; then
	print "# `gettext utskicat 'Generated certificates will be stored under'` '$certs_path'"
fi
print -n "# `gettext utskicat 'List of key package owners will be stored in file '`"
print "'$new_cred_owners_file'"
print "# `gettext utskicat 'List of key package passwords (encrypted under the CA public key) '`"
print "#\t `gettext utskicat 'will be stored in file'` '$new_password_file'"
if [[ -n $trusted_keys_file ]]; then
	print "# `gettext utskicat 'Newly generated key packages will be initialized with the'`"
	print "#\t `gettext utskicat 'trusted public keys from'` '$trusted_keys_file'\n"
else
	print "\n"
fi

#
# Register the CA's private key with the SKI server (skilogin)
# XXX: This must be done before the skicert -C -d
#      because the skicert needs to get the keypkg from the skiserv
#
skilogin $verbose
status=$?
if (($status != 0)); then
	remove_creds
	exit $status
fi

#
# Get the Root CA's and this CA's certificate
#
skicert -C -k "$rootca_username" -d $certs_path
status=$?
if (($status != 0)); then
	remove_creds
	exit $status
fi
skicert -C -d $certs_path
status=$?
if (($status != 0)); then
	remove_creds
	exit $status
fi

#
# Add the Root CA to the new_cred_owners
#
print "$rootca_username\t$rootca_dn" >> $new_cred_owners_file

#
# Read user/host file, and process each line
#

print "\n$pgm: `gettext utskicat 'Starting the credential generation process ...'` \n\n"

if [[ -z $entities_file ]]; then
	enter_target_name
else
	if [[ $entities_type = USER ]]; then
		IFS=:
	else
		IFS="	, "
	fi
	grep "^[^#]" $entities_file | read_targets_from_file
fi

# Encrypt the password file under the CA's public key
if [[ -a $new_password_file ]]; then
	skiencrypt -i $new_password_file -o $new_password_file.tmp
	status=$?
	if (($status != 0)); then
		print "`gettext utskicat 'WARNING: Password file is not encrypted!'`"
		exit $status
	fi
	/bin/mv $new_password_file.tmp $new_password_file
fi

# Logout CA private key from SKI key server
skilogout $verbose
status=$?
if (($status != 0)); then
	# remove_creds
	exit $status
fi

# success
exit 0


	
	
