#!/usr/bin/env bash working_dir="$(dirname $(realpath $0))" log_file=$(mktemp) backup_date="$(date +%Y-%m-%d-%H%M)" #----------------------------- # Some variables definitions #----------------------------- declare -a ovpn_cert_arr # ------------- # --- Some functions # ------------- clean_up() { # Perform program exit housekeeping rm -f "$log_file" blank_line exit $1 } blank_line() { if $terminal ; then echo "" fi } trim() { local var="$*" var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters echo -n "$var" } is_number() { return $(test ! -z "${1##*[!0-9]*}" > /dev/null 2>&1); # - also possible # - #[[ ! -z "${1##*[!0-9]*}" ]] && return 0 || return 1 #return $([[ ! -z "${1##*[!0-9]*}" ]]) } echononl(){ echo X\\c > /tmp/shprompt$$ if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then echo -e -n "$*\\c" 1>&2 else echo -e -n "$*" 1>&2 fi rm /tmp/shprompt$$ } fatal(){ echo "" if $terminal ; then echo -e "[ \033[31m\033[1mError\033[m ]: $*" echo "" echo -e " \033[31m\033[1mScript was interupted\033[m!" else echo " [ Fatal ]: $*" echo "" echo " Script was terminated...." fi echo "" clean_up 1 } error (){ echo "" if $terminal ; then echo -e " [ \033[31m\033[1mError\033[m ]: $*" else echo "[ Error ]: $*" fi echo "" } warn (){ echo "" if $terminal ; then echo -e " [ \033[33m\033[1mWarning\033[m ]: $*" else echo "[ Warning ]: $*" fi echo "" } echo_done() { echo -e "\033[80G[ \033[32mdone\033[m ]" } echo_ok() { echo -e "\033[80G[ \033[32mok\033[m ]" } echo_warning() { echo -e "\033[80G[ \033[33m\033[1mwarn\033[m ]" } echo_failed(){ echo -e "\033[80G[ \033[1;31mfailed\033[m ]" } echo_skipped() { echo -e "\033[80G[ \033[37mskipped\033[m ]" } trap clean_up SIGHUP SIGINT SIGTERM # ------------- # --- Check some prerequisites # ------------- # - Running in a terminal? # - if [[ -t 1 ]] ; then terminal=true else terminal=false fi # ------------- # --- Read Configurations from $conf_file # ------------- declare -a conf_file_arr=() declare -a conf_name_arr=() for _conf_file in `ls ${working_dir}/conf/server-*.conf 2>/dev/null` ; do conf_file_arr+=("${_conf_file}") _basename=$(basename $_conf_file) _tmp_name=${_basename%%.*} _tmp_name=${_tmp_name#*-} conf_name_arr+=("$_tmp_name") done if [[ ${#conf_file_arr[@]} -lt 1 ]] ; then fatal "NO Configuration found!" fi declare -i i=0 if [[ ${#conf_file_arr[@]} -gt 1 ]] ; then echo "" echo "Which Configuration should be loaded?" echo "" for _conf_file in ${conf_file_arr[@]} ; do echo " [${i}] ${conf_name_arr[${i}]}" (( i++ )) done _OK=false echo echononl "Eingabe: " while ! $_OK ; do read _IN if is_number "$_IN" && [[ -n ${conf_file_arr[$_IN]} ]]; then conf_file=${conf_file_arr[$_IN]} service_name="${conf_name_arr[$_IN]}" _OK=true else echo "" echo -e "\tFalsche Eingabe !" echo "" echononl "Eingabe: " fi done else conf_file=${conf_file_arr[0]} service_name="${conf_name_arr[0]}" fi echo "" echo -e "\033[32m--\033[m" echo "" echononl "Load configuration file '$conf_file'.." if [[ -f "$conf_file" ]] ; then source "$conf_file" > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fatal "$(cat $log_file)" fi else warn "No configuration file 'conf_file' for OpenVON Service '$service_name' found.\n Loading defaults.." fi # ------------- # --- Set default values # ------------- if [[ -z "$OPENVPN_BASE_DIR" ]]; then fatal "OpenVPN base diretory not given!" else if [[ ! -d "$OPENVPN_BASE_DIR" ]]; then fatal "OpenVPN base diretory not '$OPENVPN_BASE_DIR' not found!" fi fi if [[ -d "${OPENVPN_BASE_DIR}/pki" ]] ; then warn "Only available for old easyrsa layout managed accounts." clean_up 0 else blank_line fi [[ -n "$KEY_DIR" ]] || KEY_DIR="${OPENVPN_BASE_DIR}/keys" [[ -n "$CRL_PEM" ]] || CRL_PEM="${KEY_DIR}/crl.pem" # ------------- # --- Main part of script # ------------- INDEX_FILE="${KEY_DIR}/index.txt" echononl " Backup existing index file .." if [[ -f "$INDEX_FILE" ]]; then cp -a "$INDEX_FILE" "${INDEX_FILE}.${backup_date}" > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fatal "$(cat $log_file)" fi else echo_skipped fatal "No index file '${INDEX_FILE}' found!" fi blank_line while IFS= read -r -d '' cert ; do [[ "$cert" =~ dh[[:digit:]]+\.pem ]] && continue [[ "$cert" =~ crl\.pem ]] && continue ovpn_cert_arr+=("$cert") done < <(find "$KEY_DIR" -mindepth 1 -maxdepth 1 -type f -name "*.pem" -print0 | sort -z) if [[ ${#ovpn_cert_arr[@]} -lt 1 ]] ; then fatal "No Certificates (dot-pem file) found in key directory '$KEY_DIR'!" fi :> $INDEX_FILE echononl " Create new index file '$INDEX_FILE'.." for cert in "${ovpn_cert_arr[@]}" ; do enddate="$(openssl x509 -enddate -noout -in $cert | sed 's/notAfter=//' | awk '\ { year=$4-2000; months="JanFebMarAprMayJunJulAugSepOctNovDec" ; month=1+index(months, $1)/3 ; day=$2; hour=substr($3,1,2) ; minutes=substr($3,4,2); seconds=substr($3,7,2); printf "%02d%02d%02d%02d%02d%02dZ", year, month, day, hour, minutes, seconds}')" serial="$(openssl x509 -serial -noout -in $cert |sed 's/serial=//')" subject="$(openssl x509 -subject -noout -in $cert |sed 's/subject=/\//' |sed 's/, /\//g' |sed 's/ = /=/g')" echo -e "V\t$enddate\t\t$serial\tunknown\t$subject" >> "$INDEX_FILE" done echo_ok new_serial_calculated=false echononl " Calculate next (hex) serial number.." new_serial="$(echo "obase=ibase=16;$serial+1" | bc 2> $log_file)" if [[ -s "$log_file" ]]; then echo_failed error $(cat $log_file) else echo_ok [[ ${#new_serial} -eq 1 ]] && new_serial="0$new_serial" new_serial_calculated=true fi SERIAL_FILE="${KEY_DIR}/serial" if $new_serial_calculated ; then echononl " Backup existing serial file .." if [[ -f "$SERIAL_FILE" ]]; then cp -a "$SERIAL_FILE" "${SERIAL_FILE}.${backup_date}" > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fatal "$(cat $log_file)" fi else echo_skipped fatal "No serial file '${SERIAL_FILE}' found!" fi echononl " Write new serial file '${SERIAL_FILE}' .." echo "$new_serial" > ${SERIAL_FILE} 2>$log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed fatal "$(cat $log_file)" fi else error "No new serial file '${SERIAL_FILE}' is written!" fi warn "Check manually if '${INDEX_FILE}' and '${SERIAL_FILE}' seems to be ok.." clean_up 0