#!/bin/bash

# this is the fake certbot bin to be used for testing and development
# edit certificate values to reflect your preferences:

# some defaults
# certificate term
if [ -z "${CERTTERM}" ] ; then
   CERTTERM=3650
fi
# country
A_COUNTRY=US
# state
A_STATE=GA
# city
A_CITY=Waynesburg
# organization
A_ORG=FBM
# division
A_DIV=Show

# overwrite the defaults
ASCEDSETCDIR="/etc/asceds"
if [ -r "${ASCEDSETCDIR}/certbot-ss.conf" ] ; then
   . ${ASCEDSETCDIR}/certbot-ss.conf
fi

####### do not edit below this line
# help
fake-certbot-usage()
{
  cat << ENDUSAGE

This is a fake version of certbot, simulating a subset of certbot
options to be used for testing and development.

Usage: certbot [-h] [SUBCOMMAND] [options] [-d DOMAIN] [-d DOMAIN] ... 

-h --> display usage and exit

Examples:
certbot certonly --cert-name ascedstest.math.cmu.edu 
                 --domain ascedstest.math.cmu.edu 
                 -d test1.math.cmu.edu,test2.math.cmu.edu
certbot revoke --cert-path /etc/letsencrypt/archive/ascedstest.math.cmu.edu/cert.pem 

How it works:
* checks if it run as root; exits otherwise;
* builds /etc/letsencrypt directory tree if it doesn't exist
* revokes the certificate if "revoke" subcommand is used; otherwise
* if "certonly" subcommand is used,
    generates a self-signed key/certificate for the specified domain
  
SUBCOMMANDS:
certonly  - simulates creating a key/certificate pair:
        --cert-name DOMAIN
        --domain DOMAIN
        -d SANs
  * checks the arguments of --cert-name and --domain:
       if only one is passed, that value is used for both;
       if they are different, exit;
  * parses SAN list if passed through the -d option
  * cleans the archive/DOMAIN and live/DOMAIN directories in /etc/letsencrypt;
    the old certificate files are removed;
    if the directories don't exist, they are created to mimic letsencrypt structure;
  * creates self signed certificates inside archive/DOMAIN;
    creates symlinks from live/DOMAIN.

revoke    - simulates revoking a certificate:
        --cert-path /etc/letsencrypt/archive/DOMAIN/cert.pem
  * if the PATH to cert.pem file is anything else, the command will just exit;
  * if directory /etc/letsencrypt/archive/DOMAIN does not exist, exit;
  * creates a backup of /etc/letsencrypt/archive/DOMAIN using .bak extension;
  * removes /etc/letsencrypt/live/DOMAIN containing symlinks to key/certificate.

ENDUSAGE
exit 0
}

# parse the arguments
ARGS=$*

FREVOKE=''
FGEN=''

for ARG in ${ARGS} ; do
   # echo "ARG=${ARG}"
   if [ "${ARG}" != "${ARG//[^-_a-zA-Z0-9.,/]/}" ] ; then
      echo "Malformed argument ${ARG}"
      exit 1
   elif [ "${ARG}" == "-h" ] ; then
      fake-certbot-usage
      exit 0
   elif [ "${ARG}" == "certonly" ] ; then
      shift
      FREVOKE=''
      FGEN='y'
   elif [ "${ARG}" == "revoke" ] ; then
      shift
      FREVOKE='y'
      FGEN=''   
   elif [ "${ARG}" == "--cert-path" ] ; then
      shift
      if [[ "$1" != -* ]] && [ -n "$1" ] ; then
         C_CERT=$( cat <<< $1 | tr '[:upper:]' '[:lower:]' )
      fi   
   elif [ "${ARG}" == "--cert-name" ] ; then
      shift
      if [[ "$1" != -* ]] && [ -n "$1" ] ; then
         CN_CERT=$( cat <<< $1 | tr '[:upper:]' '[:lower:]' )
      fi   
   elif [ "${ARG}" == "--domain" ] ; then
      shift
      if [[ "$1" != -* ]] && [ -n "$1" ] ; then
         CD_CERT=$( cat <<< $1 | tr '[:upper:]' '[:lower:]' )
      fi   
   elif [ "${ARG}" == "-d" ] ; then
      shift
      if [[ "$1" != -* ]] && [ -n "$1" ] ; then
         CSL_CERT=$( cat <<< $1 | tr '[:upper:]' '[:lower:]' )
      fi
   else
      shift
   fi
done

if [ $( id -u ) -ne 0 ] ; then
   echo "This command should run as root. Please use sudo! ... Exiting"
   exit 1
fi

# build the letsencrypt dir tree if it is not there
if [ ! -d "/etc/letsencrypt" ] ; then
   mkdir -p /etc/letsencrypt/live /etc/letsencrypt/archive
   mkdir -p /etc/letsencrypt/renewal-hooks/pre
   mkdir -p /etc/letsencrypt/renewal-hooks/deploy
   mkdir -p /etc/letsencrypt/renewal-hooks/post
   mkdir -p /etc/letsencrypt/renewal
fi

# revoke certificates
if [ -n "${FREVOKE}" ] ; then
   # back-up and remove certificate files
   CERT_DIR=$( dirname ${C_CERT} )
   REV_DOMAIN=$( basename ${CERT_DIR})
   LIVE_DIR="/etc/letsencrypt/live/${REV_DOMAIN}"
   if [ "$( dirname ${CERT_DIR})" != "/etc/letsencrypt/archive" ] ; then
      echo "The certificate to be revoked should be in /etc/letsencrypt/archive"
      echo "Certificate cannot be found ... Exiting"
      exit 1
   fi
 
   if [ -d "${CERT_DIR}" ] ; then
      if [ -d "${CERT_DIR}.bak" ] ; then
         /bin/rm -Rf ${CERT_DIR}.bak
      fi
      /bin/mv ${CERT_DIR} \
          ${CERT_DIR}.bak
   else
      echo "Certificate directory ${CERT_DIR} does not exist" 
   fi
   # remove live links
   if [ -d "${LIVE_DIR}" ] ; then
      /bin/rm -Rf ${LIVE_DIR}
   fi
   

# generate self-signed certificates
elif [ -n "${FGEN}" ] ; then
   # create directories
   if [ -n "${CN_CERT}" ] ; then
      CERT_DIR=${CN_CERT}
      if [ -n "${CD_CERT}" ] && [ "${CN_CERT}" != "${CD_CERT}" ] ; then
         echo "The arguments of --cert-name and --domain are different ... Exiting"
         exit 1
      fi
   elif [ -n "${CD_CERT}" ] ; then
      CERT_DIR=${CD_CERT}
   else
      echo "No domain name to use for certificate ... exiting"
      exit 1
   fi      
   
   
   FSL=''
   if [ -n "${CSL_CERT}" ] ; then
      FSL="subjectAltName="
      for FDOM in ${CSL_CERT//,/ } ; do
         FSL="${FSL}DNS:${FDOM},"
      done
      FSL="${FSL}DNS:${CD_CERT}"   
      #FSL=${FSL::-1}
      echo ${FSL}
   fi

   if [ -d "/etc/letsencrypt/archive/${CERT_DIR}" ] ; then
      /bin/rm -f /etc/letsencrypt/archive/${CERT_DIR}/*
   else 
      mkdir -p /etc/letsencrypt/archive/${CERT_DIR}
   fi
   if [ -d "/etc/letsencrypt/live/${CERT_DIR}" ] ; then
      /bin/rm -f /etc/letsencrypt/live/${CERT_DIR}/*
   else 
      mkdir -p /etc/letsencrypt/live/${CERT_DIR}
   fi

   # create self signed certificates in /etc/letsencrypt/archive/${CERT_DIR}:
   # cert1.pem chain1.pem fullchain1.pem privkey1.pem
   cd /etc/letsencrypt/archive/${CERT_DIR}
   if [ -z "${FSL}" ] ; then
      openssl req -newkey rsa:4096 -x509 -sha256 -days ${CERTTERM} -nodes \
         -out cert1.pem -keyout privkey1.pem \
         -subj "/C=${A_COUNTRY}/ST=${A_STATE}/L=${A_CITY}/O=${A_ORG}/OU=${A_DIV}/CN=${CERT_DIR}"
   else
      openssl req -newkey rsa:4096 -x509 -sha256 -days ${CERTTERM} -nodes \
         -out cert1.pem -keyout privkey1.pem \
         -subj "/C=${A_COUNTRY}/ST=${A_STATE}/L=${A_CITY}/O=${A_ORG}/OU=${A_DIV}/CN=${CERT_DIR}" \
         -addext "${FSL}"
   fi
   /bin/cp -a cert1.pem fullchain1.pem
   :> chain1.pem
   :> /etc/letsencrypt/renewal/${CERT_DIR}.conf
   
   # mimic letsencrypt structure
   ln -s /etc/letsencrypt/archive/${CERT_DIR}/cert1.pem \
         /etc/letsencrypt/live/${CERT_DIR}/cert.pem
   ln -s /etc/letsencrypt/archive/${CERT_DIR}/chain1.pem \
         /etc/letsencrypt/live/${CERT_DIR}/chain.pem
   ln -s /etc/letsencrypt/archive/${CERT_DIR}/fullchain1.pem \
         /etc/letsencrypt/live/${CERT_DIR}/fullchain.pem
   ln -s /etc/letsencrypt/archive/${CERT_DIR}/privkey1.pem \
         /etc/letsencrypt/live/${CERT_DIR}/privkey.pem

else
   echo "No subcommand specified. Please use 'certonly' or 'revoke'"
fi
   
