# This source code is released into the public domain. _PROGNAME="${0##*/}" trap 'exit 1' TERM _fatal() { local _fmt=$1; shift local _msg="$(printf "$_fmt" "$@")" printf >&2 '%s: FATAL: %s\n' "$_PROGNAME" "$_msg" kill $$ } _error() { local _fmt=$1; shift local _msg="$(printf "$_fmt" "$@")" printf >&2 '%s: ERROR: %s\n' "$_PROGNAME" "$_msg" } _warn() { local _fmt=$1; shift local _msg="$(printf "$_fmt" "$@")" printf >&2 '%s: WARNING: %s\n' "$_PROGNAME" "$_msg" } _info() { local _fmt=$1; shift local _msg="$(printf "$_fmt" "$@")" printf '%s: %s\n' "$_PROGNAME" "$_msg" } _verbose() { if [ -z "$LFACME_VERBOSE" ]; then return fi local _fmt=$1; shift local _msg="$(printf "$_fmt" "$@")" printf '%s: %s\n' "$_PROGNAME" "$_msg" } # The prefix we're installed in. _BASEDIR="__PREFIX__" # Where the internal scripts are. _SHARE="${_BASEDIR}/share/lfacme" _CHALLENGE="${_SHARE}/challenge" # Our configuration directory. If $_CONFDIR is already set, then the script # wants to provide its own config directory, probably from a command line # argument. Otherwise if $LFACME_CONFDIR is set, we're running in a hook # script, so use that as the config directory. Otherwise, use the default. if [ -z "$_CONFDIR" ]; then if ! [ -z "$LFACME_CONFDIR" ]; then _CONFDIR="$LFACME_CONFDIR" else _CONFDIR="${_BASEDIR}/etc/lfacme" fi fi # Our configuration file. _CONFIG="${_CONFDIR}/acme.conf" # Read and validate the configuration file. if [ -f "$_CONFIG" ]; then . "$_CONFIG" fi if [ -z "$ACME_URL" ]; then _fatal "missing configuration setting: ACME_URL" fi if [ -z "$ACME_DATADIR" ]; then ACME_DATADIR="/var/db/lfacme" fi if [ -z "$ACME_HOOKDIR" ]; then ACME_HOOKDIR="${_CONFDIR}/hooks" fi # Create our data directory. if [ ! -d "$ACME_DATADIR" ]; then _info "creating directory %s" "$ACME_DATADIR" mkdir -p "$ACME_DATADIR" if [ "$?" -ne 0 ]; then exit 1 fi fi # The domains.conf file. _DOMAINS="${_CONFDIR}/domains.conf" # Find a program based on $PATH, or return the second argument if specified. # If the program isn't found, print an error and exit. _findbin() { local cmd="$1" local force="$2" if ! [ -z "$force" ]; then if ! [ -x "$force" ]; then _fatal "not found or not executable: %s" "$force" fi echo $force return 0 fi local oIFS="$IFS" local IFS=: for dir in $PATH; do local _bin="${dir}/${cmd}" if ! [ -x "$_bin" ]; then continue fi echo $_bin return 0 done IFS="$oIFS" _fatal "required command '%s' not found" "$cmd" } # uacme's base directory; this is where it puts certificates. _UACME_DIR="${ACME_DATADIR}/certs" # The uacme executable. _UACME="$(_findbin uacme $ACME_UACME)" _LFACME_UACME_FLAGS="" if ! [ -z "$LFACME_VERBOSE" ]; then _LFACME_UACME_FLAGS="$_LFACME_UACME_FLAGS -v" fi _uacme() { env "LFACME_CONFDIR=${_CONFDIR}" \ "LFACME_VERBOSE=${LFACME_VERBOSE}" \ "$_UACME" $_LFACME_UACME_FLAGS \ -a "$ACME_URL" -c "$_UACME_DIR" "$@" } # Find a challenge script and make sure it's valid. If the challenge name # begins with a '/' it's a full path, otherwise we search $_CHALLENGE and # $_CONFDIR/challenge. _findchallenge() { local identifier="$1" local challenge="$2" local path="" if [ "${challenge#/*}" != "$challenge" ]; then path="${challenge}" elif [ -f "${_CHALLENGE}/${challenge}" ]; then path="${_CHALLENGE}/${challenge}" elif [ -f "${_CONFDIR}/challenge/${challenge}" ]; then path="${_CONFDIR}/challenge/${challenge}" else _error "%s: could not find challenge script '%s'" \ "$identifier" "$challenge" return 1 fi if ! [ -x "$path" ]; then _error "%s: challenge is not executable: %s" \ "$identifier" "$path" return 1 fi echo "$path" } # Find a hook script and make sure it's valid. If the hook name begins with a # '/' it's a full path, otherwise it's relative to ACME_HOOKDIR. _findhook() { local identifier="$1" local hook="$2" if [ "${hook#/*}" = "$hook" ]; then hook="${ACME_HOOKDIR}/$hook" fi if ! [ -f "$hook" ]; then _error "%s: hook does not exist: %s" \ "$identifier" "$hook" return 1 fi if ! [ -x "$hook" ]; then _error "%s: hook is not executable: %s" \ "$identifier" "$hook" return 1 fi echo "$hook" }