#!/bin/bash

trap "do_signal" 2
do_signal()
{
    echo "\n"
    read -p "Terminate theprocess? (y/n): " input
}

do_clear()
{
	if [ -d "./demoCA" ]; then
        rm -rf ./demoCA
    fi

    if [ $1 -ne 0 ];then
	    if [ -d "./ca-middle/$2" ]; then
            rm -rf ./ca-middle/$2
        fi
	    if [ -d "./entity/$2" ]; then
            rm -rf ./entity/$2
        fi
	    if [ -d "./caroot/$2" ]; then
            rm -rf ./caroot/$2
        fi
        if [ -d "./csr/$2" ]; then
            rm -rf ./csr/$2
        fi
        exit
    fi
}

do_help()
{
    echo ""
    echo "./signssl -t type -n name -c cert -k key"
    echo "-t arg       - Sign a certificate with type(root|middle|entity)"
    echo "-n arg       - Certificate file name"
    echo "-c arg       - The CA certificate, format=base64"
    echo "-k arg       - Private key file, format=base64"
	echo "-s arg       - user alternate name"
    echo "-b arg       - Generate a new RSA key of 'bits' in size"
	echo "-d arg       - Number of days a certificate generated by -x509 is valid for"	
}

do_mkdir()
{
	if [ ! -d "./demoCA" ]; then
		mkdir demoCA
        mkdir ./demoCA/newcerts
        touch ./demoCA/index.txt
        touch ./demoCA/serial
        code_len=`date +%s%N | md5sum | head -c 24`
        echo $code_len  >> ./demoCA/serial
        #echo 01 >> ./demoCA/serial
    fi
}

do_check()
{
	if [ "$type_name" == "" ]||[ "$name" == "" ]; then
        echo "cert type is unkonw!"
		do_help
		exit
    fi

    if [ "$type_name" == "root" ]; then
        return
    fi

    if [ "$caname" == "" ] || [ "$cakey" == "" ]; then
		echo "input certificate name or key is unkonw!"
		do_help
		exit
    fi
    
    if [ "$type_name" == "entity" ];then
        if [ "$san_nam" == "" ];then
            echo "Please enter the san name!"
            do_help
            exit
        fi

    fi
}

do_middle()
{
    outpath=ca-middle/${name}

    do_csr ${outpath} ${name}
    if [ $? -ne 0  ]; then
        echo "certificate request file failed to be issued"
    fi

    csrname=${outpath}/${name}.csr
    csrkey=${outpath}/${name}.key

	openssl ca -extensions v3_ca -in ${csrname} -out ${outpath}/${name}.cer -cert ${caname} -keyfile ${cakey} -days ${days} -policy policy_anything
	openssl pkcs12 -export -in ${outpath}/${name}.cer -inkey ${csrkey} -chain -CAfile ${caname} -out ${outpath}/${name}.p12

    chain_file=${outpath}/${name}.chain.pem
    touch ${chain_file}
    cat ${outpath}/${name}.cer > ${chain_file}
    cat ${caname} >> ${chain_file}

    do_clear $? ${name} 
}

do_entity()
{
    outpath=entity/${name}
    
    do_csr ${outpath} ${name}
    if [ $? -ne 0 ]; then
        echo "certificate request file failed to be issued"
    fi

    csrname=${outpath}/${name}.csr
    csrkey=${outpath}/${name}.key

    openssl ca -in ${csrname} -keyfile ${cakey} -cert ${caname} -extensions SAN -config <(cat /etc/pki/tls/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:*.${san_nam}.com,DNS:*.${san_nam}.cn")) -out ${outpath}/${name}.cer
    openssl pkcs12 -export -in ${outpath}/${name}.cer -inkey ${csrkey} -chain -CAfile ${caname} -out ${outpath}/${name}.p12
    
    chain_file=${outpath}/${name}.chain.pem
    touch ${chain_file}
    cat ${outpath}/${name}.cer >> ${chain_file}
    cat ${caname} >> ${chain_file}

    do_clear $? ${name} 
}

do_caroot()
{
    outpath=caroot/${name}

    do_csr ${outpath} ${name}
    if [ $? -ne 0 ]; then
        echo "certificate request file failed to be issued"
    fi
    
    csrname=${outpath}/${name}.csr
    csrkey=${outpath}/${name}.key

    openssl x509 -req -days ${days} -sha256 -extfile /etc/pki/tls/openssl.cnf -extensions v3_ca -signkey ${outpath}/${name}.key -in ${csrname} -out ${outpath}/${name}.cer
    do_clear $? ${name} 
}

do_csr()
{
    outpath=$1
    name=$2

    if [ ! -d "./${outpath}" ];then
        mkdir -p ${outpath}
    fi

	openssl genrsa -out  ${outpath}/${name}.key ${bits}
	openssl req -new -key ${outpath}/${name}.key -out ${outpath}/${name}.csr
}

do_signssl()
{
	if [ "$type_name" == "middle" ]; then
		do_middle
		exit
    fi
	if [ "$type_name" == "entity" ]; then
		do_entity
		exit
    fi
	if [ "$type_name" == "root" ]; then
		do_caroot
		exit
    fi
    echo "unknow command"
}

do_parse()
{
    while getopts ":t:hn:c:k:s:d:b:" opt; do  
     case $opt in
        t) type_name=$OPTARG ;;
        n) name=$OPTARG      ;;
        c) caname=$OPTARG    ;;
        k) cakey=$OPTARG     ;;
        s) san_nam=$OPTARG   ;;
        b) bits=$OPTARG      ;;
        d) days=$OPTARG      ;;
        h)
            do_help
            exit 1
        ;;
        ?)
            echo "unkonw argument"
            do_help
            exit 1
        ;;
    esac
    done

	if [ -z "$bits" ]; then
        bits=1024
    fi
	if [ -z "$days" ]; then
        days=365
    fi
}

do_parse "$@"

do_check 
do_mkdir
do_signssl

