#!/bin/sh # # Copyright 1999-2006 University of Chicago # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # printDirections () { printThis=0 if [ -f $DIRECTIONS_FILE ] ; then while read line || test ! -z "${line}" ; do if test -n "`echo $line | grep \"END $1 TEXT\"`" ; then break fi if [ "$printThis" = "1" ]; then echo "`eval echo \"$line\"`" fi if test -n "`echo $line | grep \"BEGIN $1 TEXT\"`" ; then printThis=1 fi done < $DIRECTIONS_FILE fi return $printThis } openssl="/cvmfs/dirac.egi.eu/dirac/v8.0.26/Linux-x86_64/bin/openssl" prefix="${GLOBUS_LOCATION-/cvmfs/dirac.egi.eu/dirac/v8.0.26/Linux-x86_64}" exec_prefix="${prefix}" bindir="${exec_prefix}/bin" sbindir="${exec_prefix}/sbin" datarootdir="${prefix}/share" datadir="${datarootdir}" sysconfdir="${prefix}/etc" PATH=${bindir}:${sbindir}:${PATH} if [ ! -z "${GRID_SECURITY_DIR}" ] ; then if [ -r "${GRID_SECURITY_DIR}/globus-user-ssl.conf" ] && [ -r "${GRID_SECURITY_DIR}/globus-host-ssl.conf" ] ; then secconfdir="${GRID_SECURITY_DIR}" if test ! -z "${X509_CERT_DIR}" ; then trusted_certs_dir="${X509_CERT_DIR}" elif test "X`echo ${GRID_SECURITY_DIR}| sed 's/\/\//\//'`" \ = "X`echo ${sysconfdir}|sed 's/\/\//\//'`" ; then trusted_certs_dir="${datadir}/certificates" elif test -d "${secconfdir}/certificates"; then trusted_certs_dir="${secconfdir}/certificates" else echo "ERROR: Cannot determine trusted certificate directory. Please set X509_CERT_DIR" 1>&2 exit 1 fi fi elif [ -r "/etc/grid-security/globus-user-ssl.conf" ] && [ -r "/etc/grid-security/globus-host-ssl.conf" ] ; then secconfdir="/etc/grid-security" if test ! -z "${X509_CERT_DIR}" ; then trusted_certs_dir="${X509_CERT_DIR}" else trusted_certs_dir="${secconfdir}/certificates" fi elif [ -r "${sysconfdir}/globus-user-ssl.conf" ] && [ -r "${sysconfdir}/globus-host-ssl.conf" ] ; then secconfdir="${sysconfdir}" if test ! -z "${X509_CERT_DIR}" ; then trusted_certs_dir="${X509_CERT_DIR}" else trusted_certs_dir="${datadir}/certificates" fi else secconfdir="/etc/grid-security" if test ! -z "${X509_CERT_DIR}" ; then trusted_certs_dir="${X509_CERT_DIR}" else trusted_certs_dir="${secconfdir}/certificates" fi fi # # Sample script to generate a certificate request which can be sent # to the Globus CA, who will sign it. This script uses the # globus-ssl.conf file. # # When generating a certificate request and private key for a # globus gatekeeper daemon, use the -nopw option, so the # key is not protected by pass phrase. # PROGRAM_NAME=`echo $0 | sed 's|.*/||g'` PROGRAM_VERSION="10.8" VERSION="10.8" PACKAGE="globus_gsi_cert_utils" DIRT_TIMESTAMP="1629915172" DIRT_BRANCH_ID="0" short_usage="$PROGRAM_NAME [-help] [ options ...]" ########################################################### # long_usage # Provide usage instructions to the end user ########################################################### long_usage () { cat >&2 <, : Common name of the user -commonname -service : Create certificate for a service. Requires the -host option and implies that the generated key will not be password protected (ie implies -nopw). -host : Create certificate for a host named -dns ,... : Create certificate with the dNSName extension -ip ,... : Create certificate with the iPAddress extension -dir : Changes the directory the private key and certificate request will be placed in. By default user certificates are placed in $HOME/.globus, host certificates are placed in /etc/grid-security and service certificates are place in /etc/grid-security/. -prefix : Causes the generated files to be named cert.pem, key.pem and cert_request.pem -nopw, : Create certificate without a passwd -nodes, -nopassphrase, -verbose : Don't clear the screen -int[eractive] : Prompt user for each component of the DN -force : Overwrites preexisting certifictes -ca : Will ask which CA is to be used (interactive) -ca : Will use the CA with hash value EOF } ########################################################### # set_non_default_ca # Change the CA used for generating the certificate ########################################################### set_non_default_ca() { if [ "${nondefaultca}" = "true" ]; then INSTALLED_CERTS="`echo ${trusted_certs_dir}/*.0`" if [ -z "${INSTALLED_CERTS}" ]; then echo "No CA's have been installed on this host!" echo "To run grid-cert-request, a CA must first" echo "be installed" exit 1; else echo echo "The available CA configurations installed on this host are:" echo fi index=1 for cert in ${trusted_certs_dir}/*.0; do if test -r "${cert}" ; then eval "CA${index}=${cert}" TEMP_SUBJECT=`"$openssl" x509 -in ${cert} -noout -subject -nameopt sep_multiline | sed -e '/^subject=/d' -e 's!^\s*!/!' | tr -d '\n'` eval "CA_SUBJECT${index}=\"${TEMP_SUBJECT}\"" eval "CA_HASH${index}=`"$openssl" x509 -in ${cert} -noout -hash`" eval "echo \"$index) \${CA_HASH${index}} - \${CA_SUBJECT${index}}\"" index=`expr $index + 1` fi done echo echo -n "Enter the index number of the CA you want to sign your cert request: " read CA_CHOSEN_INDEX if [ 0 -ge ${CA_CHOSEN_INDEX:-0} ] || [ $index -le ${CA_CHOSEN_INDEX:-0} ] ; then echo "${CA_CHOSEN_INDEX} is not a valid index!" exit 1 fi eval "CA_SUBJECT=\${CA_SUBJECT${CA_CHOSEN_INDEX}}" eval "CA_HASH=\${CA_HASH${CA_CHOSEN_INDEX}}" elif [ ! -z "${nondefaultca}" ] ; then CA_HASH=${nondefaultca} if test ! -r "${trusted_certs_dir}/${CA_HASH}.0" ; then echo echo "Cannot find a CA with hash ${CA_HASH}." echo "Use grid-cert-request -ca to pick a CA interactively." echo exit 1 fi TEMP_SUBJECT=`"$openssl" x509 -in ${trusted_certs_dir}/${CA_HASH}.0 -noout -subject -nameopt sep_multiline | sed -e '/^subject=/d' -e 's!^\s*!/!' | tr -d '\n'` eval "CA_SUBJECT=\"${TEMP_SUBJECT}\"" fi echo echo "Using CA: ${CA_HASH} - ${CA_SUBJECT}" echo SSL_CONFIG=${trusted_certs_dir}/globus-user-ssl.conf.${CA_HASH} SSL_USER_CONFIG=${trusted_certs_dir}/globus-user-ssl.conf.${CA_HASH} SSL_HOST_CONFIG=${trusted_certs_dir}/globus-host-ssl.conf.${CA_HASH} DIRECTIONS_FILE=${trusted_certs_dir}/directions.${CA_HASH} security_conf=${trusted_certs_dir}/grid-security.conf.${CA_HASH} } ########################################################### # abort_cleanup # Remove temp files generated by this script ########################################################### abort_cleanup () { rm -f ${CERT_FILE} ${KEY_FILE} \ ${REQUEST_FILE} ${RAND_TEMP} \ ${REQ_HEAD} ${REQ_INPUT} ${REQ_OUTPUT} ${REQ_CONF} } ########################################################### # absolute_path # Make these absolute file names if they are not ########################################################### absolute_path () { _file_name="$1" case $_file_name in /*) echo ${_file_name} ;; *) echo ${PWD}/${_file_name} esac } ########################################################### # read_command_line # Command line parsing ########################################################### globus_args_short_usage() { cat 1>&2 <&2 </dev/null || \ echo ${SERVICE_HOST}|grep "localdomain" >/dev/null; then globus_args_option_error "$1" "$2 may not contain localhost or localdomain" fi NO_DES="-nodes" shift ; shift ;; -dns | --dns) DNS_NAME_EXTENSIONS="$2" shift; shift; ;; -ip | --ip) IP_ADDRESS_EXTENSIONS="$2" shift; shift; ;; -service | --service) SERVICE="$2" SERVICE=`echo ${SERVICE}|tr 'A-Z' 'a-z'` shift ; shift ;; -dir | --dir) TARGET_DIR="$2" TARGET_DIR="`absolute_path ${TARGET_DIR}`" shift ; shift ;; -prefix | --prefix) PREFIX="$2" shift ; shift ;; -nopw|-nodes|-nopassphrase | --nopw | --nodes | --nopassphrase) NO_DES="-nodes" shift ;; -verbose | --verbose) VERBOSE="yes" shift ;; -int|-interactive | --int | --interactive) INTERACTIVE="TRUE" shift ;; -force | --force) FORCE="TRUE" shift ;; -ca | --ca) if [ ! -z "$2" ] && \ [ -z "`echo $2 | sed -e \"s|[^-]*||g\"`" ] then nondefaultca=$2 shift else echo "nondefaultca=true" nondefaultca="true" fi set_non_default_ca shift ;; *) globus_args_unrecognized_option "$1" ;; esac done if test -z "${SERVICE}"; then if test -z "${SERVICE_HOST}"; then SERVICE="user" else SERVICE="host" fi else if test -z "${SERVICE_HOST}"; then globus_args_option_error "-service" "Requires thes -host option" fi fi if test -z "${TARGET_DIR}"; then case ${SERVICE} in user) TARGET_DIR="$HOME/.globus" ;; host) TARGET_DIR="${secconfdir}" ;; *) TARGET_DIR="${secconfdir}/${SERVICE}" ;; esac fi if test -z "${PREFIX}"; then REQUEST_FILE="${TARGET_DIR}/${SERVICE}cert_request.pem" CERT_FILE="${TARGET_DIR}/${SERVICE}cert.pem" KEY_FILE="${TARGET_DIR}/${SERVICE}key.pem" else REQUEST_FILE="${TARGET_DIR}/${PREFIX}cert_request.pem" CERT_FILE="${TARGET_DIR}/${PREFIX}cert.pem" KEY_FILE="${TARGET_DIR}/${PREFIX}key.pem" fi } ########################################################### # create_input_file # Generate a inputfile to be given to SSL that fully # specifies the DN of the user # files ########################################################### create_input_file () { _common_name="$1" _config_file="$2" # Parse the ssleay configuration file, to determine the # correct default parameters awk < $_config_file ' /^\[ req_distinguished_name \]/ { start_parsing=1; next; } /^\[ .*/ { start_parsing=0; next; } /^[a-zA-Z0-9\.]*_default[ \t]*=/ && start_parsing==1 { split($0, a, "="); # default value is in a[2], but we should strip of leading ws for(i=1;substr(a[2],i,1) == " " || substr(a[2],i,1) == "\t"; i++); print substr(a[2], i); next; } ' echo ${_common_name} } create_subjectAltName() { _dns_extensions="" _ip_extensions="" if [ -n "$DNS_NAME_EXTENSIONS" ]; then _dns_extensions="`echo \"$DNS_NAME_EXTENSIONS\" | sed -e 's/^/DNS:/' -e 's/,/,DNS:/g'`" fi if [ -n "$IP_ADDRESS_EXTENSIONS" ]; then _ip_extensions="`echo \"$IP_ADDRESS_EXTENSIONS\" | sed -e 's/^/IP:/' -e 's/,/,IP:/g'`" fi if [ -n "$_dns_extensions" -a -n "$_ip_extensions" ]; then echo "subjectAltName=$_dns_extensions,$_ip_extensions" elif [ -n "$_dns_extensions" ]; then echo "subjectAltName=$_dns_extensions" else echo "subjectAltName=$_ip_extensions" fi } create_conf_file () { _config_file="$1" # Add $DNS_NAME_EXTENSIONS and $IP_ADDRESS_EXTENSIONS to the v3_req section while read line; do echo "$line" if echo "$line" | grep '\[ v3_req \]' > /dev/null 2>&1 ; then create_subjectAltName fi done < $_config_file } ########################################################### # create_request_header ########################################################### create_request_header () { if printDirections "REQUEST HEADER" ; then cat <&2 chmod u+w ${REQUEST_FILE} _exists=TRUE fi if [ -r ${CERT_FILE} ] ; then printf "\n ${CERT_FILE} already exists" 1>&2 chmod u+w ${CERT_FILE} _exists=TRUE fi if [ -r ${KEY_FILE} ] ; then printf "\n ${KEY_FILE} already exists" 1>&2 chmod u+w ${KEY_FILE} _exists=TRUE fi if [ "X$_exists" = "XTRUE" ] ; then if [ "X$FORCE" = "XTRUE" ] ; then rm -f ${CERT_FILE} ${KEY_FILE} ${REQUEST_FILE} echo echo else printf "\n\nIf you wish to overwrite, run the script again with -force.\n" 1>&2 exit 1 fi fi } ########################################################### # setup_target_dir: # Create a directory in the HOME directory of the user # to store globus related stuff. ########################################################### setup_target_dir () { if test ! -d ${TARGET_DIR} ; then mkdir ${TARGET_DIR} if [ $? -ne 0 ] ; then printf "\n\nUnable to create ${TARGET_DIR}. Please make sure that you have the right to create this directory before running this script.\n" 1>&2 exit $? fi fi if test ! -w ${TARGET_DIR} ; then printf "\n\nUnable to access ${TARGET_DIR}. Please make sure that you have the right to create files in this directory before running this script.\n" 1>&2 exit 1 fi } ########################################################### # get_user_CN # Determine the name of the user ########################################################### get_user_CN () { _common_name="${COMMON_NAME}" # 1. Command line argument # 2. Query the system # 3. Prompt the user if [ -z "${_common_name}" ] ; then finger -lm ${USERID} >/dev/null 2>&1 if [ $? -eq 0 ] ; then _common_name="`finger -lm ${USERID} |\ grep ${USERID} |\ awk -F: '{ print $3; exit }' |\ cut -c2- `" fi fi if [ -z "${_common_name}" ] || [ "${_common_name}" = "(null)" ]; then printf "Enter your name, e.g., John Smith: " 1>&2 read _common_name fi echo ${_common_name} } ########################################################### # get_host_CN # Determine the name of the host for a host certificate ########################################################### get_host_CN () { _common_name="${COMMON_NAME}" # 1. Command line -cn argument # 2. Create from -host argument if [ -z "${_common_name}" ] ; then # Check SERVICE_HOST and make sure it looks like a FQDN echo ${SERVICE_HOST} | \ grep "\." >/dev/null 2>&1 if [ $? -eq 1 ] ; then echo "The hostname ${SERVICE_HOST} does not appear to be fully qualified." 1>&2 printf "Do you wish to continue? [n] " 1>&2 read _response case X${_response} in Xy|XY|Xyes|XYES|XYes) ;; *) echo "Aborting" 1>&2 return 1 ;; esac fi _common_name="${SERVICE}/${SERVICE_HOST}" fi echo ${_common_name} return 0 } ########################################################### # create_certs # Create the certificate, key, and certificate request # files ########################################################### create_certs () { if [ -z "${NO_DES}" ] ; then echo "A certificate request and private key is being created." echo "You will be asked to enter a PEM pass phrase." echo "This pass phrase is akin to your account password, " echo "and is used to protect your key file." echo "If you forget your pass phrase, you will need to" echo "obtain a new certificate." echo fi #------------------------ # Create the Certificate File umask 022 touch ${CERT_FILE} #------------------------ # Create some semi random data for key generation umask 066 touch ${RAND_TEMP} if [ -r /dev/urandom ] ; then head -1000 /dev/urandom >> ${RAND_TEMP} 2>&1 fi date >> ${RAND_TEMP} 2>&1 netstat -in >> ${RAND_TEMP} 2>&1 ps -ef >> ${RAND_TEMP} 2>&1 ls -ln ${HOME} >> ${RAND_TEMP} 2>&1 ls -ln /tmp >> ${RAND_TEMP} 2>&1 umask 266 #------------------------ # Create the Key and Request Files if test "${SERVICE}" = "user" ; then used_config="${SSL_USER_CONFIG}" elif [ -z "$DNS_NAME_EXTENSIONS" -a -z "$IP_ADDRESS_EXTENSIONS" ]; then used_config="${SSL_HOST_CONFIG}" else used_config="${REQ_CONF}" create_conf_file "${SSL_HOST_CONFIG}" > "${REQ_CONF}" fi if test ! -z "${INTERACTIVE}" ; then "$openssl" req -new -keyout ${KEY_FILE} -out ${REQ_OUTPUT} \ -rand ${RAND_TEMP}:/var/adm/wtmp:/var/log/messages \ -config ${used_config} ${NO_DES} RET=$? rm -f ${RAND_TEMP} else create_input_file "${COMMON_NAME}" "${used_config}" > ${REQ_INPUT} "$openssl" req -new -keyout ${KEY_FILE} \ -rand ${RAND_TEMP}:/var/adm/wtmp:/var/log/messages \ -out ${REQ_OUTPUT} -config ${used_config} \ ${NO_DES} < ${REQ_INPUT} RET=$? rm -f ${RAND_TEMP} rm -f ${REQ_INPUT} # You can't separate the SSL output, it all goes to stderr # including the prompts. # Don't remove ssleay output on error as it may be useful if test ${RET} -eq 0 -a -z "${VERBOSE}" ; then clear fi fi if [ ${RET} -ne 0 ] ; then echo "Error number ${RET} was returned by " 1>&2 echo " $openssl" 1>&2 exit ${RET} fi umask 022 #------------------------ # Insert instructions into the request file SUBJECT=`"$openssl" req -in ${REQ_OUTPUT} -noout -subject -nameopt sep_multiline | sed -e '/^subject=/d' -e 's!^\s*!/!' | tr -d '\n'` create_request_header >${REQ_HEAD} # Finalize the Request file. cat ${REQ_HEAD} ${REQ_OUTPUT} >${REQUEST_FILE} rm -f ${REQ_HEAD} ${REQ_OUTPUT} ${REQ_CONF} } ########################################################### # emit_directions # Provide instructions to the end user ########################################################### emit_directions () { if test "${SERVICE}" = "user" ; then if printDirections "USER INSTRUCTIONS" ; then echo echo "A private key and a certificate request has been generated with the subject:" echo echo "${SUBJECT}" echo echo "If the CN=${COMMON_NAME} is not appropriate, rerun this" echo "script with the -force -cn \"Common Name\" options." echo echo "Your private key is stored in ${KEY_FILE}" echo "Your request is stored in ${REQUEST_FILE}" echo echo "Please e-mail the request to the ${GSI_CA_NAME} ${GSI_CA_EMAIL_ADDR}" echo "You may use a command similar to the following:" echo echo " cat ${REQUEST_FILE} | mail ${GSI_CA_EMAIL_ADDR}" echo echo "Only use the above if this machine can send AND receive e-mail. if not, please" echo "mail using some other method." echo echo "Your certificate will be mailed to you within two working days." echo "If you receive no response, contact ${GSI_CA_NAME} at ${GSI_CA_EMAIL_ADDR}" fi else if printDirections "NONUSER INSTRUCTIONS" ; then echo echo "A private ${SERVICE} key and a certificate request has been generated" echo "with the subject:" echo echo "${SUBJECT}" echo echo "----------------------------------------------------------" echo echo "The private key is stored in ${KEY_FILE}" echo "The request is stored in ${REQUEST_FILE}" echo echo "Please e-mail the request to the ${GSI_CA_NAME} ${GSI_CA_EMAIL_ADDR}" echo "You may use a command similar to the following:" echo echo " cat ${REQUEST_FILE} | mail ${GSI_CA_EMAIL_ADDR}" echo echo "Only use the above if this machine can send AND receive e-mail. if not, please" echo "mail using some other method." echo echo "Your certificate will be mailed to you within two working days." echo "If you receive no response, contact ${GSI_CA_NAME} at ${GSI_CA_EMAIL_ADDR}" fi fi } ########################################################### # MAIN ########################################################### if ! "$openssl" version > /dev/null 2> /dev/null; then echo "Unable to locate openssl binary in PATH" 1>&2 exit 1 fi SSL_CONFIG="${secconfdir}/globus-user-ssl.conf" SSL_USER_CONFIG="${secconfdir}/globus-user-ssl.conf" SSL_HOST_CONFIG="${secconfdir}/globus-host-ssl.conf" DIRECTIONS_FILE="${secconfdir}/directions" security_conf="${secconfdir}/grid-security.conf" # Info sent with the certificate SUBJECT= USERID="`whoami`" if command -v globus-hostname > /dev/null; then HOST="`globus-hostname`" elif command -v hostname > /dev/null; then HOST=`hostname` elif command -v uname > /dev/null; then HOST=`uname -n` else HOST="" fi SERVICE= SERVICE_HOST= INTERACTIVE= NO_DES= TARGET_DIR= CERT_FILE= KEY_FILE= REQUEST_FILE= CERTREQ="grid-cert-request" # Parse the command line read_command_line "$@" if test -z "$trusted_certs_dir"; then if test -n "$GRID_SECURITY_DIR"; then echo "Can't find valid CA config files in " \ "GRID_SECURITY_DIR \"${GRID_SECURITY_DIR}\"." echo "Please make sure that you have installed and " \ "setup a CA setup package." else echo "Error reading" echo " /etc/grid-security/globus-user-ssl.conf" echo " /etc/grid-security/globus-host-ssl.conf" echo " ${sysconfdir}/globus-user-ssl.conf" echo " ${sysconfdir}/globus-host-ssl.conf" echo "" echo "Can't find valid CA config files." echo "Not all CAs use this tool to generate certificate requests." echo "If your CA is using this tool, make sure that you have installed" echo "your CA's setup package." echo "If your CA is not using this tool, consult the CA documentation" echo "to find the right way to request a certificate." fi echo "" exit 1 fi # set temporary files REQ_HEAD=${TARGET_DIR}/$PROGRAM_NAME.$$.head REQ_INPUT=${TARGET_DIR}/$PROGRAM_NAME.$$.input REQ_OUTPUT=${TARGET_DIR}/$PROGRAM_NAME.$$.output RAND_TEMP=${TARGET_DIR}/$PROGRAM_NAME.$$.random REQ_CONF="${TARGET_DIR}/$PROGRAM_NAME.$$.conf" # Source the security.conf file . ${security_conf} # Check the target directory setup_target_dir # Check for preexisting credential files check4certs # Derive the Common Name if test "${SERVICE}" = "user"; then COMMON_NAME="`get_user_CN`" else COMMON_NAME="`get_host_CN`" if [ $? -ne 0 ]; then exit 1 fi fi # do clean up on abort trap abort_cleanup 1 2 3 6 9 13 15 # create the certificate request and private key create_certs RET=$? COMMON_NAME="`echo ${SUBJECT} | sed -e 's|^.*/CN=||'`" # print directions to screen emit_directions ${SERVICE} exit ${RET}