Browse Source

date error fixed for MacOS

pull/662/head
update process 5 years ago
parent
commit
b7ce5f2181
1 changed files with 205 additions and 116 deletions
  1. +205
    -116
      getssl

+ 205
- 116
getssl View File

@ -256,7 +256,11 @@
# 2021-02-07 Allow -u --upgrade without any domain, so that one can only update the script (Benno-K)(2.34)
# 2021-02-09 Prevent listing the complete file if version tag missing (#637)(softins)
# 2021-02-12 Add PREFERRED_CHAIN
# 2021-02-15 ADD ftp explicit SSL with curl for upload the challenge
# 2021-02-15 ADD ftp explicit SSL with curl for upload the challenge (CoolMischa)
# 2021-02-18 Add FULL_CHAIN_INCLUDE_ROOT
# 2021-03-25 Fix DNS challenge completion check if CNAMEs on different NS are used (sideeffect42)(2.35)
# 2021-05-08 Merge from tlhackque/getssl: GoDaddy, split-view, tempfile permissions fixes, --version(2.36)
# 2021-05-26 Fix 'date -j' error on Mac fixed. Mac OS BigSur uses version: date (GNU coreutils) 8.32 (CooMischa)
# ----------------------------------------------------------------------------------------
case :$SHELLOPTS: in
@ -265,7 +269,7 @@ esac
PROGNAME=${0##*/}
PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)"
VERSION="2.34"
VERSION="2.36"
# defaults
ACCOUNT_KEY_LENGTH=4096
@ -283,6 +287,7 @@ DEFAULT_REVOKE_CA="https://acme-v02.api.letsencrypt.org"
DOMAIN_KEY_LENGTH=4096
DUAL_RSA_ECDSA="false"
FTP_OPTIONS=""
FULL_CHAIN_INCLUDE_ROOT="false"
GETSSL_IGNORE_CP_PRESERVE="false"
HTTP_TOKEN_CHECK_WAIT=0
IGNORE_DIRECTORY_DOMAIN="false"
@ -300,12 +305,13 @@ OCSP_MUST_STAPLE="false"
TEMP_UPGRADE_FILE=""
TOKEN_USER_ID=""
USE_SINGLE_ACL="false"
WORKING_DIR_CANDIDATES=("/etc/getssl/" "${PROGDIR}/conf" "${PROGDIR}/.getssl" "${HOME}/.getssl")
WORKING_DIR_CANDIDATES=("/etc/getssl" "${PROGDIR}/conf" "${PROGDIR}/.getssl" "${HOME}/.getssl")
# Variables used when validating using a DNS entry
VALIDATE_VIA_DNS="" # Set this to "true" to enable DNS validation
AUTH_DNS_SERVER="" # Use this DNS server to check the challenge token has been set
PUBLIC_DNS_SERVER="" # Use this DNS server to find the authoritative DNS servers for the domain
export AUTH_DNS_SERVER="" # Use this DNS server to check the challenge token has been set
export DNS_CHECK_OPTIONS="" # Options (such as TSIG file) required by DNS_CHECK_FUNC
export PUBLIC_DNS_SERVER="" # Use this DNS server to find the authoritative DNS servers for the domain
CHECK_ALL_AUTH_DNS="false" # Check the challenge token has been set on all authoritative DNS servers
CHECK_PUBLIC_DNS_SERVER="true" # Check the public DNS server as well as the authoritative DNS servers
DNS_ADD_COMMAND="" # Use this command/script to add the challenge token to the DNS entries for the domain
@ -333,7 +339,7 @@ _UPGRADE_CHECK=1
_USE_DEBUG=0
_ONLY_CHECK_CONFIG=0
config_errors="false"
LANG=C
export LANG=C
API=1
# store copy of original command in case of upgrading script and re-running
@ -516,48 +522,42 @@ check_challenge_completion() { # checks with the ACME server if our challenge is
}
check_challenge_completion_dns() { # perform validation via DNS challenge
token=$1
uri=$2
keyauthorization=$3
d=$4
primary_ns=$5
auth_key=$6
# Always use lowercase domain name when querying DNS servers
# shellcheck disable=SC2018,SC2019
lower_d=$(echo "${d##\*.}" | tr A-Z a-z)
d=${1}
rr=${2}
primary_ns=${3}
auth_key=${4}
# check for token at public dns server, waiting for a valid response.
for ns in $primary_ns; do
info "checking dns at $ns"
info "checking DNS at $ns"
ntries=0
check_dns="fail"
while [[ "$check_dns" == "fail" ]]; do
if [[ "$os" == "cygwin" ]]; then
check_result=$(nslookup -type=txt "_acme-challenge.${lower_d}" "${ns}" \
check_result=$(nslookup -type=txt "${rr}" "${ns}" \
| grep ^_acme -A2\
| grep '"'|awk -F'"' '{ print $2}')
elif [[ "$DNS_CHECK_FUNC" == "drill" ]] || [[ "$DNS_CHECK_FUNC" == "dig" ]]; then
debug "$DNS_CHECK_FUNC" TXT "_acme-challenge.${lower_d}" "@${ns}"
check_result=$($DNS_CHECK_FUNC TXT "_acme-challenge.${lower_d}" "@${ns}" \
| grep -i "^_acme-challenge.${lower_d}" \
debug "$DNS_CHECK_FUNC" TXT "${rr}" "@${ns}"
check_result=$($DNS_CHECK_FUNC TXT "${rr}" "@${ns}" \
| grep -i "^${rr}" \
| grep 'IN\WTXT'|awk -F'"' '{ print $2}')
debug "check_result=$check_result"
if [[ -z "$check_result" ]]; then
debug "$DNS_CHECK_FUNC" ANY "_acme-challenge.${lower_d}" "@${ns}"
check_result=$($DNS_CHECK_FUNC ANY "_acme-challenge.${lower_d}" "@${ns}" \
| grep -i "^_acme-challenge.${lower_d}" \
debug "$DNS_CHECK_FUNC" ANY "${rr}" "@${ns}"
check_result=$($DNS_CHECK_FUNC ANY "${rr}" "@${ns}" \
| grep -i "^${rr}" \
| grep 'IN\WTXT'|awk -F'"' '{ print $2}')
debug "check_result=$check_result"
fi
elif [[ "$DNS_CHECK_FUNC" == "host" ]]; then
check_result=$($DNS_CHECK_FUNC -t TXT "_acme-challenge.${lower_d}" "${ns}" \
check_result=$($DNS_CHECK_FUNC -t TXT "${rr}" "${ns}" \
| grep 'descriptive text'|awk -F'"' '{ print $2}')
else
check_result=$(nslookup -type=txt "_acme-challenge.${lower_d}" "${ns}" \
check_result=$(nslookup -type=txt "${rr}" "${ns}" \
| grep 'text ='|awk -F'"' '{ print $2}')
if [[ -z "$check_result" ]]; then
check_result=$(nslookup -type=any "_acme-challenge.${lower_d}" "${ns}" \
check_result=$(nslookup -type=any "${rr}" "${ns}" \
| grep 'text ='|awk -F'"' '{ print $2}')
fi
fi
@ -571,22 +571,20 @@ check_challenge_completion_dns() { # perform validation via DNS challenge
ntries=$(( ntries + 1 ))
if [[ $DNS_WAIT_RETRY_ADD == "true" && $(( ntries % 10 )) == 0 ]]; then
debug "Retrying adding dns via command: $DNS_ADD_COMMAND $lower_d $auth_key"
test_output "Retrying adding dns via command: $DNS_ADD_COMMAND"
eval "$DNS_DEL_COMMAND" "$lower_d" "$auth_key"
if ! eval "$DNS_ADD_COMMAND" "$lower_d" "$auth_key" ; then
error_exit "DNS_ADD_COMMAND failed for domain $d"
fi
test_output "Deleting DNS RR via command: ${DNS_DEL_COMMAND}"
del_dns_rr "${d}" "${auth_key}"
test_output "Retrying adding DNS via command: ${DNS_ADD_COMMAND}"
add_dns_rr "${d}" "${auth_key}" \
|| error_exit "DNS_ADD_COMMAND failed for domain ${d}"
fi
info "checking DNS at ${ns} for ${lower_d}. Attempt $ntries/${DNS_WAIT_COUNT} gave wrong result, "\
info "checking DNS at ${ns} for ${rr}. Attempt $ntries/${DNS_WAIT_COUNT} gave wrong result, "\
"waiting $DNS_WAIT secs before checking again"
sleep $DNS_WAIT
else
debug "dns check failed - removing existing value"
eval "$DNS_DEL_COMMAND" "$lower_d" "$auth_key"
del_dns_rr "${d}" "${auth_key}"
error_exit "checking _acme-challenge.${lower_d} gave $check_result not $auth_key"
error_exit "checking ${rr} gave $check_result not $auth_key"
fi
fi
done
@ -596,13 +594,6 @@ check_challenge_completion_dns() { # perform validation via DNS challenge
info "sleeping $DNS_EXTRA_WAIT seconds before asking the ACME server to check the dns"
sleep "$DNS_EXTRA_WAIT"
fi
check_challenge_completion "$uri" "$d" "$keyauthorization"
debug "remove DNS entry"
# shellcheck disable=SC2018,SC2019
lower_d=$(echo "${d##\*.}" | tr A-Z a-z)
eval "$DNS_DEL_COMMAND" "$lower_d" "$auth_key"
}
# end of ... perform validation if via DNS challenge
@ -625,7 +616,7 @@ check_config() { # check the config files for all obvious errors
rsa|prime256v1|secp384r1|secp521r1)
debug "checked PRIVATE_KEY_ALG " ;;
*)
info "${DOMAIN}: invalid PRIVATE_KEY_ALG - $PRIVATE_KEY_ALG"
info "${DOMAIN}: invalid PRIVATE_KEY_ALG - '$PRIVATE_KEY_ALG'"
config_errors=true ;;
esac
if [[ "$DUAL_RSA_ECDSA" == "true" ]] && [[ "$PRIVATE_KEY_ALG" == "rsa" ]]; then
@ -681,32 +672,32 @@ check_config() { # check the config files for all obvious errors
config_errors=true
fi
# check domain exists using all DNS utilities
# check domain exists using all DNS utilities. DNS_CHECK_OPTIONS may bind IP address or provide TSIG
found_ip=false
if [[ -n "$HAS_DIG_OR_DRILL" ]]; then
debug "DNS lookup using $HAS_DIG_OR_DRILL ${d}"
if [[ "$($HAS_DIG_OR_DRILL -t SOA "${d}" |grep -c -i "^${d}")" -ge 1 ]]; then
debug "DNS lookup using $HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS ${d}"
if [[ "$($HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS -t SOA "${d}" |grep -c -i "^${d}")" -ge 1 ]]; then
found_ip=true
elif [[ "$($HAS_DIG_OR_DRILL -t A "${d}"|grep -c -i "^${d}")" -ge 1 ]]; then
elif [[ "$($HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS -t A "${d}"|grep -c -i "^${d}")" -ge 1 ]]; then
found_ip=true
elif [[ "$($HAS_DIG_OR_DRILL -t AAAA "${d}"|grep -c -i "^${d}")" -ge 1 ]]; then
elif [[ "$($HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS -t AAAA "${d}"|grep -c -i "^${d}")" -ge 1 ]]; then
found_ip=true
fi
fi
if [[ "$HAS_HOST" == "true" ]]; then
debug "DNS lookup using host ${d}"
if [[ "$(host "${d}" |grep -c -i "^${d}")" -ge 1 ]]; then
if [[ "$(host $DNS_CHECK_OPTIONS "${d}" |grep -c -i "^${d}")" -ge 1 ]]; then
found_ip=true
fi
fi
if [[ "$HAS_NSLOOKUP" == "true" ]]; then
debug "DNS lookup using nslookup -query AAAA ${d}"
if [[ "$(nslookup -query=AAAA "${d}"|grep -c -i "^${d}.*has AAAA address")" -ge 1 ]]; then
if [[ "$(nslookup $DNS_CHECK_OPTIONS -query=AAAA "${d}"|grep -c -i "^${d}.*has AAAA address")" -ge 1 ]]; then
debug "found IPv6 record for ${d}"
found_ip=true
elif [[ "$(nslookup "${d}"| grep -c ^Name)" -ge 1 ]]; then
elif [[ "$(nslookup $DNS_CHECK_OPTIONS "${d}"| grep -c ^Name)" -ge 1 ]]; then
debug "found IPv4 record for ${d}"
found_ip=true
fi
@ -805,7 +796,7 @@ clean_up() { # Perform pre-exit housekeeping
# shellcheck source=/dev/null
. "$dnsfile"
debug "attempting to clean up DNS entry for $d"
eval "$DNS_DEL_COMMAND" "${d##\*.}" "$auth_key"
del_dns_rr "${d}" "${auth_key}"
done
shopt -u nullglob
fi
@ -1079,8 +1070,9 @@ create_order() {
date_epoc() { # convert the date into epoch time
if [[ "$os" == "bsd" ]]; then
date -j -f "%b %d %T %Y %Z" "$1" +%s
elif [[ "$os" == "mac" ]]; then
date -j -f "%b %d %T %Y %Z" "$1" +%s
# elif [[ "$os" == "mac" ]]; then
# date -j -f "%b %d %T %Y %Z" "$1" +%s
# date -d "$1" +%s
elif [[ "$os" == "busybox" ]]; then
de_ld=$(echo "$1" | awk '{print $1 " " $2 " " $3 " " $4}')
date -D "%b %d %T %Y" -d "$de_ld" +%s
@ -1091,10 +1083,11 @@ date_epoc() { # convert the date into epoch time
}
date_fmt() { # format date from epoc time to YYYY-MM-DD
if [[ "$os" == "bsd" ]]; then #uses older style date function.
date -j -f "%s" "$1" +%F
elif [[ "$os" == "mac" ]]; then # macOS uses older BSD style date.
if [[ "$os" == "bsd" ]]; then # uses older style date function.
date -j -f "%s" "$1" +%F
# elif [[ "$os" == "mac" ]]; then # macOS uses older BSD style date.
# date -j -f "%s" "$1" +%F
# date -d "@$1" +%F
else
date -d "@$1" +%F
fi
@ -1169,6 +1162,26 @@ find_ftp_command() {
}
add_dns_rr() {
d=${1}
auth_key=${2}
# shellcheck disable=SC2018,SC2019
lower_d=$(printf '%s' "${d#\*.}" | tr 'A-Z' 'a-z')
debug "adding DNS RR via command: ${DNS_ADD_COMMAND} ${lower_d} ${auth_key}"
eval "${DNS_ADD_COMMAND}" "${lower_d}" "${auth_key}"
}
del_dns_rr() {
d=${1}
auth_key=${2}
# shellcheck disable=SC2018,SC2019
lower_d=$(printf '%s' "${d#\*.}" | tr 'A-Z' 'a-z')
debug "removing DNS RR via command: ${DNS_DEL_COMMAND} ${lower_d} ${auth_key}"
eval "${DNS_DEL_COMMAND}" "${lower_d}" "${auth_key}"
}
fulfill_challenges() {
dn=0
for d in "${alldomains[@]}"; do
@ -1234,16 +1247,24 @@ for d in "${alldomains[@]}"; do
| sed -e 's:=*$::g' -e 'y:+/:-_:')
debug auth_key "$auth_key"
add_dns_rr "${d}" "${auth_key}" \
|| error_exit "DNS_ADD_COMMAND failed for domain $d"
# shellcheck disable=SC2018,SC2019
lower_d=$(echo "${d##\*.}" | tr A-Z a-z)
debug "adding dns via command: $DNS_ADD_COMMAND $lower_d $auth_key"
if ! eval "$DNS_ADD_COMMAND" "$lower_d" "$auth_key" ; then
error_exit "DNS_ADD_COMMAND failed for domain $d"
fi
rr="_acme-challenge.$(printf '%s' "${d#\*.}" | tr 'A-Z' 'a-z')"
# find a primary / authoritative DNS server for the domain
if [[ -z "$AUTH_DNS_SERVER" ]]; then
get_auth_dns "$d"
# Find authorative dns server for _acme-challenge.{domain} (for CNAMES/acme-dns)
get_auth_dns "${rr}"
if test -n "${cname}"; then
rr=${cname}
fi
# If no authorative dns server found, try again for {domain}
if [[ -z "$primary_ns" ]]; then
get_auth_dns "$d"
fi
elif [[ "$CHECK_PUBLIC_DNS_SERVER" == "true" ]]; then
primary_ns="$AUTH_DNS_SERVER $PUBLIC_DNS_SERVER"
else
@ -1251,7 +1272,13 @@ for d in "${alldomains[@]}"; do
fi
debug set primary_ns = "$primary_ns"
check_challenge_completion_dns "${token}" "${uri}" "${keyauthorization}" "${d}" "${primary_ns}" "${auth_key}"
# internal check
check_challenge_completion_dns "${d}" "${rr}" "${primary_ns}" "${auth_key}"
# let Let's Encrypt check
check_challenge_completion "${uri}" "${d}" "${keyauthorization}"
del_dns_rr "${d}" "${auth_key}"
else # set up the correct http token for verification
if [[ $API -eq 1 ]]; then
# get the token from the http component
@ -1364,45 +1391,45 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n
gad_s="@$gad_s"
fi
# Use SOA +trace to find the name server
if [[ $_TEST_SKIP_SOA_CALL == 0 ]]; then
if [[ "$HAS_DIG_OR_DRILL" == "drill" ]]; then
debug Using "$HAS_DIG_OR_DRILL -T $gad_d $gad_s" to find primary nameserver
test_output "Using $HAS_DIG_OR_DRILL SOA"
res=$($HAS_DIG_OR_DRILL -T SOA "$gad_d" $gad_s 2>/dev/null | grep "IN\WNS\W")
else
debug Using "$HAS_DIG_OR_DRILL SOA +trace +nocomments $gad_d $gad_s" to find primary nameserver
test_output "Using $HAS_DIG_OR_DRILL SOA"
res=$($HAS_DIG_OR_DRILL SOA +trace +nocomments "$gad_d" $gad_s 2>/dev/null | grep "IN\WNS\W")
fi
fi
# Check if domain is a CNAME, first
test_output "Using $HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS CNAME"
# Check if domain is a CNAME
if [[ -z "$res" ]]; then
test_output "Using $HAS_DIG_OR_DRILL CNAME"
# Two options here; either dig CNAME will return the CNAME and the NS or just the CNAME
debug Checking for CNAME using "$HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS CNAME $gad_d $gad_s"
res=$($HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS CNAME "$gad_d" $gad_s| grep "^$gad_d")
cname=$(echo "$res"| awk '$4 ~ "CNAME" {print $5}' |sed 's/\.$//g')
# Two options here; either dig CNAME will return the CNAME and the NS or just the CNAME
debug Checking for CNAME using "$HAS_DIG_OR_DRILL CNAME $gad_d $gad_s"
res=$($HAS_DIG_OR_DRILL CNAME "$gad_d" $gad_s| grep "^$gad_d")
cname=$(echo "$res"| awk '$4 ~ "CNAME" {print $5}' |sed 's/\.$//g')
if [[ $_TEST_SKIP_CNAME_CALL == 0 ]]; then
debug Checking if CNAME result contains NS records
res=$($HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS CNAME "$gad_d" $gad_s| grep -E "IN\W(NS|SOA)\W")
else
res=
fi
if [[ $_TEST_SKIP_CNAME_CALL == 0 ]]; then
debug Checking if CNAME result contains NS records
res=$($HAS_DIG_OR_DRILL CNAME "$gad_d" $gad_s| grep -E "IN\W(NS|SOA)\W")
else
res=""
fi
if [[ -n "${cname}" ]]; then
# domain is a CNAME: resolve it and continue with that
debug Domain is a CNAME, actual domain is "$cname"
gad_d=${cname}
fi
if [[ -n "$cname" ]]; then # domain is a CNAME so get main domain
debug Domain is a CNAME, actual domain is "$cname"
# Use SOA +trace to find the name server
if [[ -z "$res" ]] && [[ $_TEST_SKIP_SOA_CALL == 0 ]]; then
if [[ "$HAS_DIG_OR_DRILL" == "drill" ]]; then
debug Using "$HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS -T $gad_d $gad_s" to find primary nameserver
test_output "Using $HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS SOA"
res=$($HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS -T SOA "$gad_d" $gad_s 2>/dev/null | grep "IN\WNS\W")
else
debug Using "$HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS SOA +trace +nocomments $gad_d $gad_s" to find primary nameserver
test_output "Using $HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS SOA"
res=$($HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS SOA +trace +nocomments "$gad_d" $gad_s 2>/dev/null | grep "IN\WNS\W")
fi
fi
# Query for NS records
if [[ -z "$res" ]]; then
test_output "Using $HAS_DIG_OR_DRILL NS"
debug Using "$HAS_DIG_OR_DRILL NS $gad_d $gad_s" to find primary nameserver
res=$($HAS_DIG_OR_DRILL NS "$gad_d" $gad_s | grep -E "IN\W(NS|SOA)\W")
test_output "Using $HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS NS"
debug Using "$HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS NS $gad_d $gad_s" to find primary nameserver
res=$($HAS_DIG_OR_DRILL $DNS_CHECK_OPTIONS NS "$gad_d" $gad_s | grep -E "IN\W(NS|SOA)\W")
fi
if [[ -n "$res" ]]; then
@ -1442,10 +1469,10 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n
gad_d="$orig_gad_d"
debug Using "host -t NS" to find primary name server for "$gad_d"
if [[ -z "$gad_s" ]]; then
res=$(host -t NS "$gad_d"| grep "name server")
res=$(host $DNS_CHECK_OPTIONS -t NS "$gad_d"| grep "name server")
else
# shellcheck disable=SC2086
res=$(host -t NS "$gad_d" $gad_s| grep "name server")
res=$(host $DNS_CHECK_OPTIONS -t NS "$gad_d" $gad_s| grep "name server")
fi
if [[ -n "$res" ]]; then
all_auth_dns_servers=$(echo "$res" | awk '{print $4}' | sed 's/\.$//g'|tr '\n' ' ')
@ -1465,9 +1492,9 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n
if [[ "$HAS_NSLOOKUP" == "true" ]]; then
gad_d="$orig_gad_d"
debug Using "nslookup -debug -type=soa -type=ns $gad_d $gad_s" to find primary name server
debug Using "nslookup $DNS_CHECK_OPTIONS -debug -type=soa -type=ns $gad_d $gad_s" to find primary name server
# shellcheck disable=SC2086
res=$(nslookup -debug -type=soa -type=ns "$gad_d" ${gad_s})
res=$(nslookup $DNS_CHECK_OPTIONS -debug -type=soa -type=ns "$gad_d" ${gad_s})
if [[ "$(echo "$res" | grep -c "Non-authoritative")" -gt 0 ]]; then
# this is a Non-authoritative server, need to check for an authoritative one.
@ -1483,7 +1510,7 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n
fi
# shellcheck disable=SC2086
res=$(nslookup -debug -type=soa -type=ns "$gad_d" ${gad_s})
res=$(nslookup $DNS_CHECK_OPTIONS -debug -type=soa -type=ns "$gad_d" ${gad_s})
fi
if [[ "$(echo "$res" | grep -c "canonical name")" -gt 0 ]]; then
@ -1499,7 +1526,7 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n
# shellcheck disable=SC2086
# not quoting gad_s fixes the nslookup: couldn't get address for '': not found warning (#332)
all_auth_dns_servers=$(nslookup -debug -type=soa -type=ns "$gad_d" $gad_s \
all_auth_dns_servers=$(nslookup $DNS_CHECK_OPTIONS -debug -type=soa -type=ns "$gad_d" $gad_s \
| awk '$1 ~ "nameserver" {print $3}' \
| sed 's/\.$//g'| tr '\n' ' ')
@ -1527,6 +1554,7 @@ get_certificate() { # get certificate for csr, if all domains validated.
gc_fullchain=$4 # The filename for the fullchain
der=$(openssl req -in "$gc_csr" -outform DER | urlbase64)
if [[ $API -eq 1 ]]; then
send_signed_request "$URL_new_cert" "{\"resource\": \"new-cert\", \"csr\": \"$der\"}" "needbase64"
# convert certificate information into correct format and save to file.
@ -1580,7 +1608,7 @@ get_certificate() { # get certificate for csr, if all domains validated.
cp "$gc_fullchain" "$cert_to_check"
i=0
while [[ $i -le ${#alternate_links[@]} ]]; do
cert_issuer=$(openssl crl2pkcs7 -nocrl -certfile "$cert_to_check" | openssl pkcs7 -print_certs -text -noout | grep 'Issuer:' | tail -1 | cut -d= -f2)
cert_issuer=$(openssl crl2pkcs7 -nocrl -certfile "$cert_to_check" | openssl pkcs7 -print_certs -text -noout | grep 'Issuer:' | tail -1 | awk -F"CN=" '{ print $2 }')
debug Certificate issued by "$cert_issuer"
if [[ $cert_issuer = *${PREFERRED_CHAIN}* ]]; then
debug "Found required certificate"
@ -1598,7 +1626,27 @@ get_certificate() { # get certificate for csr, if all domains validated.
# tidy up
rm -f "$cert_to_check"
fi
awk -v CERT_FILE="$gc_certfile" -v CA_CERT="$gc_cafile" 'BEGIN {outfile=CERT_FILE} split_after==1 {outfile=CA_CERT;split_after=0} /-----END CERTIFICATE-----/ {split_after=1} {print > outfile}' "$gc_fullchain"
if [[ "$FULL_CHAIN_INCLUDE_ROOT" = "true" ]]; then
# Some of the code below was copied from zakjan/cert-chain-resolver
# Download the certificate for the issuer using the "CA Issuers" attribute from the AIA x509 extension
issuer_url=$(openssl x509 -inform pem -noout -text -in "$gc_certfile" | awk 'BEGIN {FS="CA Issuers - URI:"} NF==2 {print $2; exit}')
debug Issuer for "$gc_certfile" is "$issuer_url"
# Keep downloading issuer certficates until we find the root certificate (which doesn't have a "CA Issuers" attribure)
cp "$gc_certfile" "$gc_fullchain"
while [[ -n "$issuer_url" ]]; do
debug Fetching certificate issuer from "$issuer_url"
issuer_cert=$(curl --user-agent "$CURL_USERAGENT" --silent "$issuer_url" | openssl x509 -inform der -outform pem)
debug Fetched issuer certificate "$(echo "$issuer_cert" | openssl x509 -inform pem -noout -text | awk 'BEGIN {FS="Subject: "} NF==2 {print $2; exit}')"
echo "$issuer_cert" >> "$gc_fullchain"
# get issuer for the certificate that's just been downloaded
issuer_url=$(echo "$issuer_cert" | openssl x509 -inform pem -noout -text | awk 'BEGIN {FS="CA Issuers - URI:"} NF==2 {print $2; exit}')
done
fi
info "Certificate saved in $gc_certfile"
fi
}
@ -1715,6 +1763,7 @@ help_message() { # print out the help message
-u, --upgrade Upgrade getssl if a more recent version is available - can be used with or without domain(s)
-k, --keep "#" Maximum number of old getssl versions to keep when upgrading
-U, --nocheck Do not check if a more recent version is available
-v --version Display current version of $PROGNAME
-w working_dir "Working directory"
--preferred-chain "chain" Use an alternate chain for the certificate
@ -2051,16 +2100,18 @@ revoke_certificate() { # revoke a certificate
}
requires() { # check if required function is available
args=("${@}")
lastarg=${args[${#args[@]}-1]}
if [[ "$#" -gt 1 ]]; then # if more than 1 value, check list
for i in "$@"; do
if [[ "$i" == "${!#}" ]]; then # if on last variable then exit as not found
if [[ "$i" == "$lastarg" ]]; then # if on last variable then exit as not found
error_exit "this script requires one of: ${*:1:$(($#-1))}"
fi
res=$(command -v "$i" 2>/dev/null)
debug "checking for $i ... $res"
if [[ -n "$res" ]]; then # if function found, then set variable to function and return
debug "function $i found at $res - setting ${!#} to $i"
eval "${!#}=\$i"
debug "function $i found at $res - setting ${lastarg} to $i"
eval "${lastarg}=\$i"
return
fi
done
@ -2377,10 +2428,14 @@ write_domain_template() { # write out a template file for a domain.
# Set USE_SINGLE_ACL="true" to use a single ACL for all checks
#USE_SINGLE_ACL="false"
# Preferred Chain - use an different certificate root from the default
# Staging options are: "Fake LE Root X1" and "Fake LE Root X2"
# Production options are: "ISRG Root X1" and "ISRG Root X2"
#PREFERRED_CHAIN=""
# Preferred Chain - use an different certificate root from the default
# This uses wildcard matching so requesting "X1" returns the correct certificate - may need to escape characters
# Staging options are: "(STAGING) Doctored Durian Root CA X3" and "(STAGING) Pretend Pear X1"
# Production options are: "ISRG Root X1" and "ISRG Root X2"
#PREFERRED_CHAIN="\(STAGING\) Pretend Pear X1"
# Uncomment this if you need the full chain file to include the root certificate (Java keystores, Nutanix Prism)
#FULL_CHAIN_INCLUDE_ROOT="true"
# Location for all your certs, these can either be on the server (full path name)
# or using ssh /sftp as for the ACL
@ -2436,10 +2491,14 @@ write_getssl_template() { # write out the main template file
PRIVATE_KEY_ALG="rsa"
#REUSE_PRIVATE_KEY="true"
# Preferred Chain - use an different certificate root from the default
# Staging options are: "Fake LE Root X1" and "Fake LE Root X2"
# Production options are: "ISRG Root X1" and "ISRG Root X2"
#PREFERRED_CHAIN=""
# Preferred Chain - use an different certificate root from the default
# This uses wildcard matching so requesting "X1" returns the correct certificate - may need to escape characters
# Staging options are: "(STAGING) Doctored Durian Root CA X3" and "(STAGING) Pretend Pear X1"
# Production options are: "ISRG Root X1" and "ISRG Root X2"
#PREFERRED_CHAIN="\(STAGING\) Pretend Pear X1"
# Uncomment this if you need the full chain file to include the root certificate (Java keystores, Nutanix Prism)
#FULL_CHAIN_INCLUDE_ROOT="true"
# The command needed to reload apache / nginx or whatever you use.
# Several (ssh) commands may be given using a bash array:
@ -2463,6 +2522,19 @@ write_getssl_template() { # write out the main template file
#VALIDATE_VIA_DNS="true"
#DNS_ADD_COMMAND=
#DNS_DEL_COMMAND=
# Unusual configurations (especially split views) may require these.
# If you have a mixture, these can go in the per-domain getssl.cfg.
#
# If you must use an external DNS Server (e.g. due to split views)
# Specify it here. Otherwise, the default is to find the zone master.
# The default will usually work.
# PUBLIC_DNS_SERVER="8.8.8.8"
# If getssl is unable to determine the authoritative nameserver for a domain
# it will as you to enter AUTH_DNS_SERVER. This is a server that
# can answer queries for the zone - a master or a slave, not a recursive server.
# AUTH_DNS_SERVER="10.0.0.14"
_EOF_getssl_
}
@ -2485,6 +2557,8 @@ while [[ -n ${1+defined} ]]; do
case $1 in
-h | --help)
help_message; graceful_exit ;;
-v | --version)
echo "$PROGNAME V$VERSION"; graceful_exit ;;
-d | --debug)
_USE_DEBUG=1 ;;
-c | --create)
@ -2629,6 +2703,12 @@ if [[ -s "$WORKING_DIR/getssl.cfg" ]]; then
. "$WORKING_DIR/getssl.cfg"
fi
if [[ -n "$DNS_CHECK_FUNC" ]]; then
requires "${DNS_CHECK_FUNC}"
else
requires nslookup drill dig host DNS_CHECK_FUNC
fi
# Define defaults for variables not set in the main config.
ACCOUNT_KEY="${ACCOUNT_KEY:=$WORKING_DIR/account.key}"
DOMAIN_STORAGE="${DOMAIN_STORAGE:=$WORKING_DIR}"
@ -2719,6 +2799,7 @@ if [[ ${_CREATE_CONFIG} -eq 1 ]]; then
info "Adding SANS=$EX_SANS from certificate installed on ${DOMAIN##\*.} to new configuration file"
fi
write_domain_template "$DOMAIN_DIR/getssl.cfg"
info "created domain config file in $DOMAIN_DIR/getssl.cfg"
fi
TEMP_DIR="$DOMAIN_DIR/tmp"
# end of "-c|--create" option, so exit
@ -2825,7 +2906,7 @@ if [[ "${CHECK_REMOTE}" == "true" ]] && [[ $_FORCE_RENEW -eq 0 ]]; then
else
# check if the certificate is for the right domain
EX_CERT_DOMAIN=$(echo "$EX_CERT" | openssl x509 -text \
| sed -n -e 's/^ *Subject: .* CN=\([A-Za-z0-9.-]*\).*$/\1/p; /^ *DNS:.../ { s/ *DNS://g; y/,/\n/; p; }' \
| sed -n -e 's/^ *Subject: .*CN=\([A-Za-z0-9.-]*\).*$/\1/p; /^ *DNS:.../ { s/ *DNS://g; y/,/\n/; p; }' \
| sort -u | grep "^$DOMAIN\$")
if [[ "$EX_CERT_DOMAIN" == "$DOMAIN" ]]; then
# check renew-date on ex_cert and compare to local ( if local exists)
@ -2858,18 +2939,26 @@ if [[ "${CHECK_REMOTE}" == "true" ]] && [[ $_FORCE_RENEW -eq 0 ]]; then
copy_file_to_location "full pem" \
"$TEMP_DIR/${DOMAIN}_chain.pem" \
"$DOMAIN_CHAIN_LOCATION"
umask 077
cat "$DOMAIN_DIR/${DOMAIN}.key" "$CERT_FILE" > "$TEMP_DIR/${DOMAIN}_K_C.pem"
umask "$ORIG_UMASK"
copy_file_to_location "private key and domain cert pem" \
"$TEMP_DIR/${DOMAIN}_K_C.pem" \
"$DOMAIN_KEY_CERT_LOCATION"
umask 077
cat "$DOMAIN_DIR/${DOMAIN}.key" "$CERT_FILE" "$CA_CERT" > "$TEMP_DIR/${DOMAIN}.pem"
umask "$ORIG_UMASK"
copy_file_to_location "full pem" \
"$TEMP_DIR/${DOMAIN}.pem" \
"$DOMAIN_PEM_LOCATION"
reload_service
fi
else
info "${DOMAIN}: Certificate on remote domain does not match, ignoring remote certificate"
# Get the domain from the existing certificate for the error message
EX_CERT_DOMAIN=$(echo "$EX_CERT" | openssl x509 -text \
| sed -n -e 's/^ *Subject: .*CN=\([A-Za-z0-9.-]*\).*$/\1/p; /^ *DNS:.../ { s/ *DNS://g; y/,/\n/; p; }' \
| sort -u | head -1)
info "${DOMAIN}: Certificate on remote domain does not match, ignoring remote certificate ($EX_CERT_DOMAIN != $real_d)"
fi
fi
else


Loading…
Cancel
Save