#!@BASHPATH@ # # Copyright (c) 2015-2018 Red Hat, Inc. # # All rights reserved. # # Author: Jan Friesse (jfriesse@redhat.com) # # This software licensed under BSD license, the text of which follows: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # - Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # - 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. # - Neither the name of the Red Hat, Inc. nor the names of its # contributors may be used to endorse or promote products derived from this # software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. # CONFIG_DIR="@COROSYSCONFDIR@/qnetd" DB_DIR="$CONFIG_DIR/nssdb" # Validity of certificate (months) CRT_VALIDITY=1200 CA_NICKNAME="QNet CA" SERVER_NICKNAME="QNetd Cert" CA_SUBJECT="CN=QNet CA" SERVER_SUBJECT="CN=Qnetd Server" PWD_FILE="$DB_DIR/pwdfile.txt" NOISE_FILE="$DB_DIR/noise.txt" SERIAL_NO_FILE="$DB_DIR/serial.txt" CA_EXPORT_FILE="$DB_DIR/qnetd-cacert.crt" CERTDB_FILES=("cert9.db key4.db pkcs11.txt" "cert8.db key3.db secmod.db") usage() { echo "$0: [-i|-s] [-c certificate] [-G] [-n cluster_name]" echo echo " -i Initialize QNetd CA and generate server certificate" echo " -s Sign cluster certificate (needs cluster certificate)" echo " -c certificate CRQ certificate file name" echo " -G Do not set group write bit for new files" echo " -n cluster_name Name of cluster (for -s operation)" exit 0 } chown_ref_cfgdir() { if [ "$UID" == "0" ];then chown --reference="$CONFIG_DIR" "$@" 2>/dev/null || chown "$(stat -f "%u:%g" "$CONFIG_DIR")" "$@" 2>/dev/null || return $? fi } # get_perm [directory] # Return permission based on -G and directory flag get_perm() { if [ "$1" == true ];then [ "$SET_GROUP_WRITE_BIT" == true ] && echo "0770" || echo "0750" else [ "$SET_GROUP_WRITE_BIT" == true ] && echo "0660" || echo "0640" fi } create_new_noise_file() { local noise_file="$1" if [ ! -e "$noise_file" ];then echo "Creating new noise file $noise_file" (ps -elf; date; w) | sha1sum | (read sha_sum rest; echo $sha_sum) > "$noise_file" chown_ref_cfgdir "$noise_file" chmod "$(get_perm)" "$noise_file" else echo "Using existing noise file $noise_file" fi } get_serial_no() { local serial_no if ! [ -f "$SERIAL_NO_FILE" ];then echo "100" > $SERIAL_NO_FILE chown_ref_cfgdir "$SERIAL_NO_FILE" chmod "$(get_perm)" "$SERIAL_NO_FILE" fi serial_no=`cat $SERIAL_NO_FILE` serial_no=$((serial_no+1)) echo "$serial_no" > $SERIAL_NO_FILE echo "$serial_no" } find_certdb_files() { for cert_files_index in "${!CERTDB_FILES[@]}";do cert_files=${CERTDB_FILES[$cert_files_index]} test_file=${cert_files%% *} if [ -f "$DB_DIR/$test_file" ];then echo "$cert_files" return 0 fi done return 1 } init_qnetd_ca() { cert_files=`find_certdb_files` if [ "$cert_files" != "" ];then echo "Certificate database ($DB_DIR) already exists. Delete it to initialize new db" >&2 exit 1 fi if ! [ -d "$DB_DIR" ];then echo "Creating $DB_DIR" mkdir -p "$DB_DIR" chown_ref_cfgdir "$DB_DIR" chmod "$(get_perm true)" "$DB_DIR" fi echo "Creating new key and cert db" echo -n "" > "$PWD_FILE" chown_ref_cfgdir "$PWD_FILE" chmod "$(get_perm)" "$PWD_FILE" certutil -N -d "$DB_DIR" -f "$PWD_FILE" cert_files=`find_certdb_files` if [ "$cert_files" == "" ];then echo "Can't find certificate database files. Certificate database ($DB_DIR) cannot be created" >&2 exit 1 fi for fname in $cert_files;do chown_ref_cfgdir "$DB_DIR/$fname" chmod "$(get_perm)" "$DB_DIR/$fname" done create_new_noise_file "$NOISE_FILE" echo "Creating new CA" # Create self-signed certificate (CA). Asks 3 questions (is this CA, lifetime and critical extension echo -e "y\n0\ny\n" | certutil -S -n "$CA_NICKNAME" -s "$CA_SUBJECT" -x \ -t "CT,," -m "$(get_serial_no)" -v $CRT_VALIDITY -d "$DB_DIR" \ -z "$NOISE_FILE" -f "$PWD_FILE" -2 # Export CA certificate in ascii certutil -L -d "$DB_DIR" -n "$CA_NICKNAME" > "$CA_EXPORT_FILE" certutil -L -d "$DB_DIR" -n "$CA_NICKNAME" -a >> "$CA_EXPORT_FILE" chown_ref_cfgdir "$CA_EXPORT_FILE" certutil -S -n "$SERVER_NICKNAME" -s "$SERVER_SUBJECT" -c "$CA_NICKNAME" -t "u,u,u" -m "$(get_serial_no)" \ -v $CRT_VALIDITY -d "$DB_DIR" -z "$NOISE_FILE" -f "$PWD_FILE" echo "QNetd CA certificate is exported as $CA_EXPORT_FILE" } sign_cluster_cert() { cert_files=`find_certdb_files` if [ "$cert_files" == "" ];then echo "Certificate database doesn't exists. Use $0 -i to create it" >&2 exit 1 fi echo "Signing cluster certificate" certutil -C -v "$CRT_VALIDITY" -m "$(get_serial_no)" -i "$CERTIFICATE_FILE" -o "$CRT_FILE" -c "$CA_NICKNAME" -d "$DB_DIR" chown_ref_cfgdir "$CRT_FILE" echo "Certificate stored in $CRT_FILE" } OPERATION="" CERTIFICATE_FILE="" CLUSTER_NAME="" SET_GROUP_WRITE_BIT=true while getopts ":Ghisc:n:" opt; do case $opt in i) OPERATION=init_qnetd_ca ;; s) OPERATION=sign_cluster_cert ;; h) usage ;; c) CERTIFICATE_FILE="$OPTARG" ;; G) SET_GROUP_WRITE_BIT=false ;; n) CLUSTER_NAME="$OPTARG" ;; \?) echo "Invalid option: -$OPTARG" >&2 exit 1 ;; :) echo "Option -$OPTARG requires an argument." >&2 exit 1 ;; esac done [ "$OPERATION" == "" ] && usage CRT_FILE="$DB_DIR/cluster-$CLUSTER_NAME.crt" case "$OPERATION" in "init_qnetd_ca") init_qnetd_ca ;; "sign_cluster_cert") if ! [ -e "$CERTIFICATE_FILE" ];then echo "Can't open certificate file $CERTIFICATE_FILE" >&2 exit 2 fi if [ "$CLUSTER_NAME" == "" ];then echo "You have to specify cluster name" >&2 exit 2 fi sign_cluster_cert ;; *) usage ;; esac