@ -264,6 +264,8 @@
# 2021-07-12 Do not redirect outputs on remote commands when the debug option is used (atisne)
# 2021-07-20 Use +noidnout to enable certificates for IDN domains (#679)(2.37)
# 2021-07-22 Only pass +noidnout param to dig/drill(#682)(2.38)
# 2021-07-25 Fix copy_file_to_location failures with ssh when suffix applied to file lacking an extension (tlhackque)(#686)
# 2021-07-27 Support ftps://, FTPS_OPTIONS, remove default --insecure parameter to ftpes. Report caller(s) of error_exit in debug and test modes (tlhackque)(#687)(2.39)
# ----------------------------------------------------------------------------------------
case :$SHELLOPTS: in
@ -272,7 +274,7 @@ esac
PROGNAME=${0##*/}
PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)"
VERSION="2.38 "
VERSION="2.39 "
# defaults
ACCOUNT_KEY_LENGTH=4096
@ -290,6 +292,7 @@ DEFAULT_REVOKE_CA="https://acme-v02.api.letsencrypt.org"
DOMAIN_KEY_LENGTH=4096
DUAL_RSA_ECDSA="false"
FTP_OPTIONS=""
FTPS_OPTIONS=""
FULL_CHAIN_INCLUDE_ROOT="false"
GETSSL_IGNORE_CP_PRESERVE="false"
HTTP_TOKEN_CHECK_WAIT=0
@ -850,7 +853,12 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required.
IFS=\; read -r -a copy_locations <<<"$3"
for to in "${copy_locations[@]}"; do
if [[ -n "$suffix" ]]; then
to="${to%.*}.${suffix}.${to##*.}"
bname="$(basename "$to")"
if [[ "${bname##*.}" == "$bname" ]]; then
to="${to}.${suffix}"
else
to="${to%.*}.${suffix}.${to##*.}"
fi
fi
info "copying $cert to $to"
if [[ "${to:0:4}" == "ssh:" ]] ; then
@ -934,7 +942,7 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required.
debug "davs user=$davsuser - pass=$davspass - host=$davshost port=$davsport dir=$davsdirn file=$davsfile"
debug "from dir=$fromdir file=$fromfile"
curl -u "${davsuser}:${davspass}" -T "${fromdir}/${fromfile}" "https://${davshost}:${davsport}${davsdirn}${davsfile}"
elif [[ "${to:0:6}" == "ftpes:" ]] ; then
elif [[ "${to:0:6}" == "ftpes:" ]] || [[ "${to:0:5}" == "ftps:" ]] ; then
debug "using ftp to copy the file from $from"
ftpuser=$(echo "$to"| awk -F: '{print $2}')
ftppass=$(echo "$to"| awk -F: '{print $3}')
@ -946,7 +954,13 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required.
fromfile=$(basename "$from")
debug "ftp user=$ftpuser - pass=$ftppass - host=$ftphost dir=$ftpdirn file=$ftpfile"
debug "from dir=$fromdir file=$fromfile"
curl --insecure --ftp-ssl -u "${ftpuser}:${ftppass}" -T "${fromdir}/${fromfile}" "ftp://${ftphost}${ftpdirn}/"
if [[ "${to:0:5}" == "ftps:" ]] ; then
# shellcheck disable=SC2086
curl $FTPS_OPTIONS --ftp-ssl --ftp-ssl-reqd -u "${ftpuser}:${ftppass}" -T "${fromdir}/${fromfile}" "ftp://${ftphost}${ftpdirn}:990/"
else
# shellcheck disable=SC2086
curl $FTPS_OPTIONS --ftp-ssl --ftp-ssl-reqd -u "${ftpuser}:${ftppass}" -T "${fromdir}/${fromfile}" "ftp://${ftphost}${ftpdirn}/"
fi
else
if ! mkdir -p "$(dirname "$to")" ; then
error_exit "cannot create ACL directory $(basename "$to")"
@ -1146,6 +1160,9 @@ test_output() { # write out debug output for testing
error_exit() { # give error message on error exit
echo -e "${PROGNAME}: ${1:-"Unknown Error"}" >&2
if [[ ${_RUNNING_TEST} -eq 1 ]] || [[ ${_USE_DEBUG} -eq 1 ]] ; then
traceback
fi
clean_up
exit 1
}
@ -1357,7 +1374,10 @@ for d in "${alldomains[@]}"; do
else
sleep "$HTTP_TOKEN_CHECK_WAIT"
# check that we can reach the challenge ourselves, if not, then error
if [[ ! "$(curl --user-agent "$CURL_USERAGENT" -k --silent --location "$wellknown_url")" == "$keyauthorization" ]]; then
# ACME only allows port 80 (http), but redirects may use https. --insecure is used in case
# those certificates are being renewed. Let's Encrypt does the same. In this case, we verify
# that the correct data is returned, so this is safe.
if [[ ! "$(curl --user-agent "$CURL_USERAGENT" --insecure --silent --location "$wellknown_url")" == "$keyauthorization" ]]; then
error_exit "for some reason could not reach $wellknown_url - please check it manually"
fi
fi
@ -2393,6 +2413,16 @@ signal_exit() { # Handle trapped signals
esac
}
traceback() { # Print function traceback
local i d=1 lbl=" called"
echo "Traceback" >&2
for ((i=$((${#FUNCNAME[@]}-1)); i>0; i--)); do
if [[ ${i} -eq 1 ]] ; then lbl=" called traceback" ; fi
printf "%*s%s() line %d%s\n" "$d" '' "${FUNCNAME[$i]}" "${BASH_LINENO[$((i-1))]}" "$lbl" >&2
((d++))
done
}
urlbase64() { # urlbase64: base64 encoded string with '+' replaced with '-' and '/' replaced with '_'
openssl base64 -e | tr -d '\n\r' | os_esed -e 's:=*$::g' -e 'y:+/:-_:'
}
@ -2448,9 +2478,11 @@ write_domain_template() { # write out a template file for a domain.
# An ssh key will be needed to provide you with access to the remote server.
# Optionally, you can specify a different userid for ssh/scp to use on the remote server before the @ sign.
# If left blank, the username on the local server will be used to authenticate against the remote server.
# If these start with ftp:/ftpes: then the next variables are ftpuserid:ftppassword:servername:ACL_location
# If these start with ftp:/ftpes:/ftps: then the next variables are ftpuserid:ftppassword:servername:ACL_location
# These should be of the form "/path/to/your/website/folder/.well-known/acme-challenge"
# where "/path/to/your/website/folder/" is the path, on your web server, to the web root for your domain.
# ftp: uses regular ftp; ftpes: ftp over explicit TLS (port 21); ftps: ftp over implicit TLS (port 990).
# ftps/ftpes support FTPS_OPTIONS, e.g. to add "--insecure" to the curl command for hosts with self-signed certificates.
# You can also user WebDAV over HTTPS as transport mechanism. To do so, start with davs: followed by username,
# password, host, port (explicitly needed even if using default port 443) and path on the server.
# Multiple locations can be defined for a file by separating the locations with a semi-colon.
@ -2459,6 +2491,7 @@ write_domain_template() { # write out a template file for a domain.
# 'ssh:sshuserid@server5:/var/www/${DOMAIN}/web/.well-known/acme-challenge'
# 'ftp:ftpuserid:ftppassword:${DOMAIN}:/web/.well-known/acme-challenge'
# 'davs:davsuserid:davspassword:{DOMAIN}:443:/web/.well-known/acme-challenge'
# 'ftps:ftpuserid:ftppassword:${DOMAIN}:/web/.well-known/acme-challenge'
# 'ftpes:ftpuserid:ftppassword:${DOMAIN}:/web/.well-known/acme-challenge')
# Specify SSH options, e.g. non standard port in SSH_OPTS