|
@@ -1,6 +1,6 @@
|
|
|
#!/usr/bin/env sh
|
|
|
|
|
|
-VER=3.0.2
|
|
|
+VER=3.0.5
|
|
|
|
|
|
PROJECT_NAME="acme.sh"
|
|
|
|
|
@@ -20,8 +20,6 @@ _SUB_FOLDER_DEPLOY="deploy"
|
|
|
|
|
|
_SUB_FOLDERS="$_SUB_FOLDER_DNSAPI $_SUB_FOLDER_DEPLOY $_SUB_FOLDER_NOTIFY"
|
|
|
|
|
|
-CA_LETSENCRYPT_V1="https://acme-v01.api.letsencrypt.org/directory"
|
|
|
-
|
|
|
CA_LETSENCRYPT_V2="https://acme-v02.api.letsencrypt.org/directory"
|
|
|
CA_LETSENCRYPT_V2_TEST="https://acme-staging-v02.api.letsencrypt.org/directory"
|
|
|
|
|
@@ -34,6 +32,9 @@ _ZERO_EAB_ENDPOINT="https://api.zerossl.com/acme/eab-credentials-email"
|
|
|
CA_SSLCOM_RSA="https://acme.ssl.com/sslcom-dv-rsa"
|
|
|
CA_SSLCOM_ECC="https://acme.ssl.com/sslcom-dv-ecc"
|
|
|
|
|
|
+CA_GOOGLE="https://dv.acme-v02.api.pki.goog/directory"
|
|
|
+CA_GOOGLE_TEST="https://dv.acme-v02.test-api.pki.goog/directory"
|
|
|
+
|
|
|
DEFAULT_CA=$CA_ZEROSSL
|
|
|
DEFAULT_STAGING_CA=$CA_LETSENCRYPT_V2_TEST
|
|
|
|
|
@@ -44,9 +45,11 @@ LetsEncrypt.org_test,letsencrypt_test,letsencrypttest
|
|
|
BuyPass.com,buypass
|
|
|
BuyPass.com_test,buypass_test,buypasstest
|
|
|
SSL.com,sslcom
|
|
|
+Google.com,google
|
|
|
+Google.com_test,googletest,google_test
|
|
|
"
|
|
|
|
|
|
-CA_SERVERS="$CA_ZEROSSL,$CA_LETSENCRYPT_V2,$CA_LETSENCRYPT_V2_TEST,$CA_BUYPASS,$CA_BUYPASS_TEST,$CA_SSLCOM_RSA"
|
|
|
+CA_SERVERS="$CA_ZEROSSL,$CA_LETSENCRYPT_V2,$CA_LETSENCRYPT_V2_TEST,$CA_BUYPASS,$CA_BUYPASS_TEST,$CA_SSLCOM_RSA,$CA_GOOGLE,$CA_GOOGLE_TEST"
|
|
|
|
|
|
DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)"
|
|
|
|
|
@@ -172,6 +175,8 @@ _SERVER_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Server"
|
|
|
|
|
|
_PREFERRED_CHAIN_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Preferred-Chain"
|
|
|
|
|
|
+_VALIDITY_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Validity"
|
|
|
+
|
|
|
_DNSCHECK_WIKI="https://github.com/acmesh-official/acme.sh/wiki/dnscheck"
|
|
|
|
|
|
_DNS_MANUAL_ERR="The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead."
|
|
@@ -976,9 +981,9 @@ _base64() {
|
|
|
#Usage: multiline
|
|
|
_dbase64() {
|
|
|
if [ "$1" ]; then
|
|
|
- ${ACME_OPENSSL_BIN:-openssl} base64 -d -A
|
|
|
- else
|
|
|
${ACME_OPENSSL_BIN:-openssl} base64 -d
|
|
|
+ else
|
|
|
+ ${ACME_OPENSSL_BIN:-openssl} base64 -d -A
|
|
|
fi
|
|
|
}
|
|
|
|
|
@@ -1141,13 +1146,19 @@ _createkey() {
|
|
|
|
|
|
_debug "Use length $length"
|
|
|
|
|
|
- if ! touch "$f" >/dev/null 2>&1; then
|
|
|
- _f_path="$(dirname "$f")"
|
|
|
- _debug _f_path "$_f_path"
|
|
|
- if ! mkdir -p "$_f_path"; then
|
|
|
- _err "Can not create path: $_f_path"
|
|
|
+ if ! [ -e "$f" ]; then
|
|
|
+ if ! touch "$f" >/dev/null 2>&1; then
|
|
|
+ _f_path="$(dirname "$f")"
|
|
|
+ _debug _f_path "$_f_path"
|
|
|
+ if ! mkdir -p "$_f_path"; then
|
|
|
+ _err "Can not create path: $_f_path"
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+ if ! touch "$f" >/dev/null 2>&1; then
|
|
|
return 1
|
|
|
fi
|
|
|
+ chmod 600 "$f"
|
|
|
fi
|
|
|
|
|
|
if _isEccKey "$length"; then
|
|
@@ -1495,7 +1506,6 @@ _create_account_key() {
|
|
|
else
|
|
|
#generate account key
|
|
|
if _createkey "$length" "$ACCOUNT_KEY_PATH"; then
|
|
|
- chmod 600 "$ACCOUNT_KEY_PATH"
|
|
|
_info "Create account key ok."
|
|
|
return 0
|
|
|
else
|
|
@@ -1593,23 +1603,22 @@ _durl_replace_base64() {
|
|
|
|
|
|
_time2str() {
|
|
|
#BSD
|
|
|
- if date -u -r "$1" 2>/dev/null; then
|
|
|
+ if date -u -r "$1" -j "+%Y-%m-%dT%H:%M:%SZ" 2>/dev/null; then
|
|
|
return
|
|
|
fi
|
|
|
|
|
|
#Linux
|
|
|
- if date -u -d@"$1" 2>/dev/null; then
|
|
|
+ if date -u --date=@"$1" "+%Y-%m-%dT%H:%M:%SZ" 2>/dev/null; then
|
|
|
return
|
|
|
fi
|
|
|
|
|
|
#Solaris
|
|
|
- if _exists adb; then
|
|
|
- _t_s_a=$(echo "0t${1}=Y" | adb)
|
|
|
- echo "$_t_s_a"
|
|
|
+ if printf "%(%Y-%m-%dT%H:%M:%SZ)T\n" $1 2>/dev/null; then
|
|
|
+ return
|
|
|
fi
|
|
|
|
|
|
#Busybox
|
|
|
- if echo "$1" | awk '{ print strftime("%c", $0); }' 2>/dev/null; then
|
|
|
+ if echo "$1" | awk '{ print strftime("%Y-%m-%dT%H:%M:%SZ", $0); }' 2>/dev/null; then
|
|
|
return
|
|
|
fi
|
|
|
}
|
|
@@ -1768,6 +1777,27 @@ _time() {
|
|
|
date -u "+%s"
|
|
|
}
|
|
|
|
|
|
+#support 2 formats:
|
|
|
+# 2022-04-01 08:10:33 to 1648800633
|
|
|
+#or 2022-04-01T08:10:33Z to 1648800633
|
|
|
+_date2time() {
|
|
|
+ #Linux
|
|
|
+ if date -u -d "$(echo "$1" | tr -d "Z" | tr "T" ' ')" +"%s" 2>/dev/null; then
|
|
|
+ return
|
|
|
+ fi
|
|
|
+
|
|
|
+ #Solaris
|
|
|
+ if gdate -u -d "$(echo "$1" | tr -d "Z" | tr "T" ' ')" +"%s" 2>/dev/null; then
|
|
|
+ return
|
|
|
+ fi
|
|
|
+ #Mac/BSD
|
|
|
+ if date -u -j -f "%Y-%m-%d %H:%M:%S" "$(echo "$1" | tr -d "Z" | tr "T" ' ')" +"%s" 2>/dev/null; then
|
|
|
+ return
|
|
|
+ fi
|
|
|
+ _err "Can not parse _date2time $1"
|
|
|
+ return 1
|
|
|
+}
|
|
|
+
|
|
|
_utc_date() {
|
|
|
date -u "+%Y-%m-%d %H:%M:%S"
|
|
|
}
|
|
@@ -1840,7 +1870,9 @@ _inithttp() {
|
|
|
_ACME_WGET="$_ACME_WGET --max-redirect 0 "
|
|
|
fi
|
|
|
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
|
|
|
- _ACME_WGET="$_ACME_WGET -d "
|
|
|
+ if [ "$_ACME_WGET" ] && _contains "$($_ACME_WGET --help 2>&1)" "--debug"; then
|
|
|
+ _ACME_WGET="$_ACME_WGET -d "
|
|
|
+ fi
|
|
|
fi
|
|
|
if [ "$CA_PATH" ]; then
|
|
|
_ACME_WGET="$_ACME_WGET --ca-directory=$CA_PATH "
|
|
@@ -2657,6 +2689,12 @@ _initAPI() {
|
|
|
return 1
|
|
|
}
|
|
|
|
|
|
+_clearCA() {
|
|
|
+ export CA_CONF=
|
|
|
+ export ACCOUNT_KEY_PATH=
|
|
|
+ export ACCOUNT_JSON_PATH=
|
|
|
+}
|
|
|
+
|
|
|
#[domain] [keylength or isEcc flag]
|
|
|
_initpath() {
|
|
|
domain="$1"
|
|
@@ -3746,7 +3784,7 @@ updateaccount() {
|
|
|
|
|
|
_email="$(_getAccountEmail)"
|
|
|
|
|
|
- if [ "$ACCOUNT_EMAIL" ]; then
|
|
|
+ if [ "$_email" ]; then
|
|
|
updjson='{"contact": ["mailto:'$_email'"]}'
|
|
|
else
|
|
|
updjson='{"contact": []}'
|
|
@@ -3756,7 +3794,7 @@ updateaccount() {
|
|
|
|
|
|
if [ "$code" = '200' ]; then
|
|
|
echo "$response" >"$ACCOUNT_JSON_PATH"
|
|
|
- _info "account update success for $_accUri."
|
|
|
+ _info "Account update success for $_accUri."
|
|
|
else
|
|
|
_info "Error. The account was not updated."
|
|
|
return 1
|
|
@@ -4195,6 +4233,40 @@ _getIdType() {
|
|
|
fi
|
|
|
}
|
|
|
|
|
|
+# beginTime dateTo
|
|
|
+# beginTime is full string format("2022-04-01T08:10:33Z"), beginTime can be empty, to use current time
|
|
|
+# dateTo can be ether in full string format("2022-04-01T08:10:33Z") or in delta format(+5d or +20h)
|
|
|
+_convertValidaty() {
|
|
|
+ _beginTime="$1"
|
|
|
+ _dateTo="$2"
|
|
|
+ _debug2 "_beginTime" "$_beginTime"
|
|
|
+ _debug2 "_dateTo" "$_dateTo"
|
|
|
+
|
|
|
+ if _startswith "$_dateTo" "+"; then
|
|
|
+ _v_begin=$(_time)
|
|
|
+ if [ "$_beginTime" ]; then
|
|
|
+ _v_begin="$(_date2time "$_beginTime")"
|
|
|
+ fi
|
|
|
+ _debug2 "_v_begin" "$_v_begin"
|
|
|
+ if _endswith "$_dateTo" "h"; then
|
|
|
+ _v_end=$(_math "$_v_begin + 60 * 60 * $(echo "$_dateTo" | tr -d '+h')")
|
|
|
+ elif _endswith "$_dateTo" "d"; then
|
|
|
+ _v_end=$(_math "$_v_begin + 60 * 60 * 24 * $(echo "$_dateTo" | tr -d '+d')")
|
|
|
+ else
|
|
|
+ _err "Not recognized format for _dateTo: $_dateTo"
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+ _debug2 "_v_end" "$_v_end"
|
|
|
+ _time2str "$_v_end"
|
|
|
+ else
|
|
|
+ if [ "$(_time)" -gt "$(_date2time "$_dateTo")" ]; then
|
|
|
+ _err "The validaty to is in the past: _dateTo = $_dateTo"
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+ echo "$_dateTo"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
#webroot, domain domainlist keylength
|
|
|
issue() {
|
|
|
if [ -z "$2" ]; then
|
|
@@ -4228,6 +4300,8 @@ issue() {
|
|
|
_local_addr="${13}"
|
|
|
_challenge_alias="${14}"
|
|
|
_preferred_chain="${15}"
|
|
|
+ _valid_from="${16}"
|
|
|
+ _valid_to="${17}"
|
|
|
|
|
|
if [ -z "$_ACME_IS_RENEW" ]; then
|
|
|
_initpath "$_main_domain" "$_key_length"
|
|
@@ -4247,11 +4321,24 @@ issue() {
|
|
|
Le_NextRenewTime=$(_readdomainconf Le_NextRenewTime)
|
|
|
_debug Le_NextRenewTime "$Le_NextRenewTime"
|
|
|
if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(_time)" -lt "$Le_NextRenewTime" ]; then
|
|
|
+ _valid_to_saved=$(_readdomainconf Le_Valid_to)
|
|
|
+ if [ "$_valid_to_saved" ] && ! _startswith "$_valid_to_saved" "+"; then
|
|
|
+ _info "The domain is set to be valid to: $_valid_to_saved"
|
|
|
+ _info "It can not be renewed automatically"
|
|
|
+ _info "See: $_VALIDITY_WIKI"
|
|
|
+ return $RENEW_SKIP
|
|
|
+ fi
|
|
|
_saved_domain=$(_readdomainconf Le_Domain)
|
|
|
_debug _saved_domain "$_saved_domain"
|
|
|
_saved_alt=$(_readdomainconf Le_Alt)
|
|
|
_debug _saved_alt "$_saved_alt"
|
|
|
- if [ "$_saved_domain,$_saved_alt" = "$_main_domain,$_alt_domains" ]; then
|
|
|
+ _normized_saved_domains="$(echo "$_saved_domain,$_saved_alt" | tr "," "\n" | sort | tr '\n' ',')"
|
|
|
+ _debug _normized_saved_domains "$_normized_saved_domains"
|
|
|
+
|
|
|
+ _normized_domains="$(echo "$_main_domain,$_alt_domains" | tr "," "\n" | sort | tr '\n' ',')"
|
|
|
+ _debug _normized_domains "$_normized_domains"
|
|
|
+
|
|
|
+ if [ "$_normized_saved_domains" = "$_normized_domains" ]; then
|
|
|
_info "Domains not changed."
|
|
|
_info "Skip, Next renewal time is: $(__green "$(_readdomainconf Le_NextRenewTimeStr)")"
|
|
|
_info "Add '$(__red '--force')' to force to renew."
|
|
@@ -4299,10 +4386,6 @@ issue() {
|
|
|
_alt_domains=""
|
|
|
fi
|
|
|
|
|
|
- if [ "$_key_length" = "$NO_VALUE" ]; then
|
|
|
- _key_length=""
|
|
|
- fi
|
|
|
-
|
|
|
if ! _on_before_issue "$_web_roots" "$_main_domain" "$_alt_domains" "$_pre_hook" "$_local_addr"; then
|
|
|
_err "_on_before_issue."
|
|
|
return 1
|
|
@@ -4323,7 +4406,13 @@ issue() {
|
|
|
if [ -f "$CSR_PATH" ] && [ ! -f "$CERT_KEY_PATH" ]; then
|
|
|
_info "Signing from existing CSR."
|
|
|
else
|
|
|
+ # When renewing from an old version, the empty Le_Keylength means 2048.
|
|
|
+ # Note, do not use DEFAULT_DOMAIN_KEY_LENGTH as that value may change over
|
|
|
+ # time but an empty value implies 2048 specifically.
|
|
|
_key=$(_readdomainconf Le_Keylength)
|
|
|
+ if [ -z "$_key" ]; then
|
|
|
+ _key=2048
|
|
|
+ fi
|
|
|
_debug "Read key length:$_key"
|
|
|
if [ ! -f "$CERT_KEY_PATH" ] || [ "$_key_length" != "$_key" ] || [ "$Le_ForceNewDomainKey" = "1" ]; then
|
|
|
if ! createDomainKey "$_main_domain" "$_key_length"; then
|
|
@@ -4363,12 +4452,52 @@ issue() {
|
|
|
_identifiers="$_identifiers,{\"type\":\"$(_getIdType "$d")\",\"value\":\"$(_idn "$d")\"}"
|
|
|
done
|
|
|
_debug2 _identifiers "$_identifiers"
|
|
|
- if ! _send_signed_request "$ACME_NEW_ORDER" "{\"identifiers\": [$_identifiers]}"; then
|
|
|
+ _notBefore=""
|
|
|
+ _notAfter=""
|
|
|
+
|
|
|
+ if [ "$_valid_from" ]; then
|
|
|
+ _savedomainconf "Le_Valid_From" "$_valid_from"
|
|
|
+ _debug2 "_valid_from" "$_valid_from"
|
|
|
+ _notBefore="$(_convertValidaty "" "$_valid_from")"
|
|
|
+ if [ "$?" != "0" ]; then
|
|
|
+ _err "Can not parse _valid_from: $_valid_from"
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+ if [ "$(_time)" -gt "$(_date2time "$_notBefore")" ]; then
|
|
|
+ _notBefore=""
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ _cleardomainconf "Le_Valid_From"
|
|
|
+ fi
|
|
|
+ _debug2 _notBefore "$_notBefore"
|
|
|
+
|
|
|
+ if [ "$_valid_to" ]; then
|
|
|
+ _debug2 "_valid_to" "$_valid_to"
|
|
|
+ _savedomainconf "Le_Valid_To" "$_valid_to"
|
|
|
+ _notAfter="$(_convertValidaty "$_notBefore" "$_valid_to")"
|
|
|
+ if [ "$?" != "0" ]; then
|
|
|
+ _err "Can not parse _valid_to: $_valid_to"
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ _cleardomainconf "Le_Valid_To"
|
|
|
+ fi
|
|
|
+ _debug2 "_notAfter" "$_notAfter"
|
|
|
+
|
|
|
+ _newOrderObj="{\"identifiers\": [$_identifiers]"
|
|
|
+ if [ "$_notBefore" ]; then
|
|
|
+ _newOrderObj="$_newOrderObj,\"notBefore\": \"$_notBefore\""
|
|
|
+ fi
|
|
|
+ if [ "$_notAfter" ]; then
|
|
|
+ _newOrderObj="$_newOrderObj,\"notAfter\": \"$_notAfter\""
|
|
|
+ fi
|
|
|
+ if ! _send_signed_request "$ACME_NEW_ORDER" "$_newOrderObj}"; then
|
|
|
_err "Create new order error."
|
|
|
_clearup
|
|
|
_on_issue_err "$_post_hook"
|
|
|
return 1
|
|
|
fi
|
|
|
+
|
|
|
Le_LinkOrder="$(echo "$responseHeaders" | grep -i '^Location.*$' | _tail_n 1 | tr -d "\r\n " | cut -d ":" -f 2-)"
|
|
|
_debug Le_LinkOrder "$Le_LinkOrder"
|
|
|
Le_OrderFinalize="$(echo "$response" | _egrep_o '"finalize" *: *"[^"]*"' | cut -d '"' -f 4)"
|
|
@@ -4407,7 +4536,7 @@ issue() {
|
|
|
|
|
|
response="$(echo "$response" | _normalizeJson)"
|
|
|
_debug2 response "$response"
|
|
|
- _d="$(echo "$response" | _egrep_o '"value" *: *"[^"]*"' | cut -d : -f 2 | tr -d ' "')"
|
|
|
+ _d="$(echo "$response" | _egrep_o '"value" *: *"[^"]*"' | cut -d : -f 2- | tr -d ' "')"
|
|
|
if _contains "$response" "\"wildcard\" *: *true"; then
|
|
|
_d="*.$_d"
|
|
|
fi
|
|
@@ -4557,6 +4686,7 @@ $_authorizations_map"
|
|
|
_dns_root_d="$(echo "$_dns_root_d" | sed 's/*.//')"
|
|
|
fi
|
|
|
_d_alias="$(_getfield "$_challenge_alias" "$_alias_index")"
|
|
|
+ test "$_d_alias" = "$NO_VALUE" && _d_alias=""
|
|
|
_alias_index="$(_math "$_alias_index" + 1)"
|
|
|
_debug "_d_alias" "$_d_alias"
|
|
|
if [ "$_d_alias" ]; then
|
|
@@ -4851,7 +4981,7 @@ $_authorizations_map"
|
|
|
return 1
|
|
|
fi
|
|
|
_debug "sleep 2 secs to verify again"
|
|
|
- sleep 2
|
|
|
+ _sleep 2
|
|
|
_debug "checking"
|
|
|
|
|
|
_send_signed_request "$uri"
|
|
@@ -5028,7 +5158,7 @@ $_authorizations_map"
|
|
|
Le_CertCreateTime=$(_time)
|
|
|
_savedomainconf "Le_CertCreateTime" "$Le_CertCreateTime"
|
|
|
|
|
|
- Le_CertCreateTimeStr=$(date -u)
|
|
|
+ Le_CertCreateTimeStr=$(_time2str "$Le_CertCreateTime")
|
|
|
_savedomainconf "Le_CertCreateTimeStr" "$Le_CertCreateTimeStr"
|
|
|
|
|
|
if [ -z "$Le_RenewalDays" ] || [ "$Le_RenewalDays" -lt "0" ]; then
|
|
@@ -5068,13 +5198,20 @@ $_authorizations_map"
|
|
|
else
|
|
|
_cleardomainconf Le_ForceNewDomainKey
|
|
|
fi
|
|
|
-
|
|
|
- Le_NextRenewTime=$(_math "$Le_CertCreateTime" + "$Le_RenewalDays" \* 24 \* 60 \* 60)
|
|
|
-
|
|
|
- Le_NextRenewTimeStr=$(_time2str "$Le_NextRenewTime")
|
|
|
+ if [ "$_notAfter" ]; then
|
|
|
+ Le_NextRenewTime=$(_date2time "$_notAfter")
|
|
|
+ Le_NextRenewTimeStr="$_notAfter"
|
|
|
+ if [ "$_valid_to" ] && ! _startswith "$_valid_to" "+"; then
|
|
|
+ _info "The domain is set to be valid to: $_valid_to"
|
|
|
+ _info "It can not be renewed automatically"
|
|
|
+ _info "See: $_VALIDITY_WIKI"
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ Le_NextRenewTime=$(_math "$Le_CertCreateTime" + "$Le_RenewalDays" \* 24 \* 60 \* 60)
|
|
|
+ Le_NextRenewTimeStr=$(_time2str "$Le_NextRenewTime")
|
|
|
+ Le_NextRenewTime=$(_math "$Le_NextRenewTime" - 86400)
|
|
|
+ fi
|
|
|
_savedomainconf "Le_NextRenewTimeStr" "$Le_NextRenewTimeStr"
|
|
|
-
|
|
|
- Le_NextRenewTime=$(_math "$Le_NextRenewTime" - 86400)
|
|
|
_savedomainconf "Le_NextRenewTime" "$Le_NextRenewTime"
|
|
|
|
|
|
if [ "$_real_cert$_real_key$_real_ca$_reload_cmd$_real_fullchain" ]; then
|
|
@@ -5110,17 +5247,20 @@ _split_cert_chain() {
|
|
|
fi
|
|
|
}
|
|
|
|
|
|
-#domain [isEcc]
|
|
|
+#domain [isEcc] [server]
|
|
|
renew() {
|
|
|
Le_Domain="$1"
|
|
|
if [ -z "$Le_Domain" ]; then
|
|
|
- _usage "Usage: $PROJECT_ENTRY --renew --domain <domain.tld> [--ecc]"
|
|
|
+ _usage "Usage: $PROJECT_ENTRY --renew --domain <domain.tld> [--ecc] [--server server]"
|
|
|
return 1
|
|
|
fi
|
|
|
|
|
|
_isEcc="$2"
|
|
|
+ _renewServer="$3"
|
|
|
+ _debug "_renewServer" "$_renewServer"
|
|
|
|
|
|
_initpath "$Le_Domain" "$_isEcc"
|
|
|
+
|
|
|
_set_level=${NOTIFY_LEVEL:-$NOTIFY_LEVEL_DEFAULT}
|
|
|
_info "$(__green "Renew: '$Le_Domain'")"
|
|
|
if [ ! -f "$DOMAIN_CONF" ]; then
|
|
@@ -5134,24 +5274,34 @@ renew() {
|
|
|
|
|
|
. "$DOMAIN_CONF"
|
|
|
_debug Le_API "$Le_API"
|
|
|
- if [ -z "$Le_API" ] || [ "$CA_LETSENCRYPT_V1" = "$Le_API" ]; then
|
|
|
- #if this is from an old version, Le_API is empty,
|
|
|
- #so, we force to use letsencrypt server
|
|
|
+
|
|
|
+ case "$Le_API" in
|
|
|
+ "$CA_LETSENCRYPT_V2_TEST")
|
|
|
+ _info "Switching back to $CA_LETSENCRYPT_V2"
|
|
|
Le_API="$CA_LETSENCRYPT_V2"
|
|
|
- fi
|
|
|
+ ;;
|
|
|
+ "$CA_BUYPASS_TEST")
|
|
|
+ _info "Switching back to $CA_BUYPASS"
|
|
|
+ Le_API="$CA_BUYPASS"
|
|
|
+ ;;
|
|
|
+ "$CA_GOOGLE_TEST")
|
|
|
+ _info "Switching back to $CA_GOOGLE"
|
|
|
+ Le_API="$CA_GOOGLE"
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
|
|
|
- if [ "$Le_API" ]; then
|
|
|
- if [ "$Le_API" != "$ACME_DIRECTORY" ]; then
|
|
|
- _clearAPI
|
|
|
- fi
|
|
|
- export ACME_DIRECTORY="$Le_API"
|
|
|
- #reload ca configs
|
|
|
- ACCOUNT_KEY_PATH=""
|
|
|
- ACCOUNT_JSON_PATH=""
|
|
|
- CA_CONF=""
|
|
|
- _debug3 "initpath again."
|
|
|
- _initpath "$Le_Domain" "$_isEcc"
|
|
|
+ if [ "$_server" ]; then
|
|
|
+ Le_API="$_server"
|
|
|
fi
|
|
|
+ _info "Renew to Le_API=$Le_API"
|
|
|
+
|
|
|
+ _clearAPI
|
|
|
+ _clearCA
|
|
|
+ export ACME_DIRECTORY="$Le_API"
|
|
|
+
|
|
|
+ #reload ca configs
|
|
|
+ _debug2 "initpath again."
|
|
|
+ _initpath "$Le_Domain" "$_isEcc"
|
|
|
|
|
|
if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(_time)" -lt "$Le_NextRenewTime" ]; then
|
|
|
_info "Skip, Next renewal time is: $(__green "$Le_NextRenewTimeStr")"
|
|
@@ -5175,7 +5325,14 @@ renew() {
|
|
|
Le_PostHook="$(_readdomainconf Le_PostHook)"
|
|
|
Le_RenewHook="$(_readdomainconf Le_RenewHook)"
|
|
|
Le_Preferred_Chain="$(_readdomainconf Le_Preferred_Chain)"
|
|
|
- issue "$Le_Webroot" "$Le_Domain" "$Le_Alt" "$Le_Keylength" "$Le_RealCertPath" "$Le_RealKeyPath" "$Le_RealCACertPath" "$Le_ReloadCmd" "$Le_RealFullChainPath" "$Le_PreHook" "$Le_PostHook" "$Le_RenewHook" "$Le_LocalAddress" "$Le_ChallengeAlias" "$Le_Preferred_Chain"
|
|
|
+ # When renewing from an old version, the empty Le_Keylength means 2048.
|
|
|
+ # Note, do not use DEFAULT_DOMAIN_KEY_LENGTH as that value may change over
|
|
|
+ # time but an empty value implies 2048 specifically.
|
|
|
+ Le_Keylength="$(_readdomainconf Le_Keylength)"
|
|
|
+ if [ -z "$Le_Keylength" ]; then
|
|
|
+ Le_Keylength=2048
|
|
|
+ fi
|
|
|
+ issue "$Le_Webroot" "$Le_Domain" "$Le_Alt" "$Le_Keylength" "$Le_RealCertPath" "$Le_RealKeyPath" "$Le_RealCACertPath" "$Le_ReloadCmd" "$Le_RealFullChainPath" "$Le_PreHook" "$Le_PostHook" "$Le_RenewHook" "$Le_LocalAddress" "$Le_ChallengeAlias" "$Le_Preferred_Chain" "$Le_Valid_From" "$Le_Valid_To"
|
|
|
res="$?"
|
|
|
if [ "$res" != "0" ]; then
|
|
|
return "$res"
|
|
@@ -5202,11 +5359,16 @@ renew() {
|
|
|
return "$res"
|
|
|
}
|
|
|
|
|
|
-#renewAll [stopRenewOnError]
|
|
|
+#renewAll [stopRenewOnError] [server]
|
|
|
renewAll() {
|
|
|
_initpath
|
|
|
+ _clearCA
|
|
|
_stopRenewOnError="$1"
|
|
|
_debug "_stopRenewOnError" "$_stopRenewOnError"
|
|
|
+
|
|
|
+ _server="$2"
|
|
|
+ _debug "_server" "$_server"
|
|
|
+
|
|
|
_ret="0"
|
|
|
_success_msg=""
|
|
|
_error_msg=""
|
|
@@ -5229,7 +5391,7 @@ renewAll() {
|
|
|
_isEcc=$(echo "$d" | cut -d "$ECC_SEP" -f 2)
|
|
|
d=$(echo "$d" | cut -d "$ECC_SEP" -f 1)
|
|
|
fi
|
|
|
- renew "$d" "$_isEcc"
|
|
|
+ renew "$d" "$_isEcc" "$_server"
|
|
|
)
|
|
|
rc="$?"
|
|
|
_debug "Return code: $rc"
|
|
@@ -5395,10 +5557,13 @@ showcsr() {
|
|
|
_initpath
|
|
|
|
|
|
_csrsubj=$(_readSubjectFromCSR "$_csrfile")
|
|
|
- if [ "$?" != "0" ] || [ -z "$_csrsubj" ]; then
|
|
|
+ if [ "$?" != "0" ]; then
|
|
|
_err "Can not read subject from csr: $_csrfile"
|
|
|
return 1
|
|
|
fi
|
|
|
+ if [ -z "$_csrsubj" ]; then
|
|
|
+ _info "The Subject is empty"
|
|
|
+ fi
|
|
|
|
|
|
_info "Subject=$_csrsubj"
|
|
|
|
|
@@ -5611,8 +5776,9 @@ _installcert() {
|
|
|
if [ -f "$_real_key" ]; then
|
|
|
cat "$CERT_KEY_PATH" >"$_real_key" || return 1
|
|
|
else
|
|
|
- cat "$CERT_KEY_PATH" >"$_real_key" || return 1
|
|
|
+ touch "$_real_key" || return 1
|
|
|
chmod 600 "$_real_key"
|
|
|
+ cat "$CERT_KEY_PATH" >"$_real_key" || return 1
|
|
|
fi
|
|
|
fi
|
|
|
|
|
@@ -6610,6 +6776,11 @@ Parameters:
|
|
|
If no match, the default offered chain will be used. (default: empty)
|
|
|
See: $_PREFERRED_CHAIN_WIKI
|
|
|
|
|
|
+ --valid-to <date-time> Request the NotAfter field of the cert.
|
|
|
+ See: $_VALIDITY_WIKI
|
|
|
+ --valid-from <date-time> Request the NotBefore field of the cert.
|
|
|
+ See: $_VALIDITY_WIKI
|
|
|
+
|
|
|
-f, --force Force install, force cert renewal or override sudo restrictions.
|
|
|
--staging, --test Use staging server, for testing.
|
|
|
--debug [0|1|2|3] Output debug info. Defaults to 1 if argument is omitted.
|
|
@@ -6801,6 +6972,10 @@ _processAccountConf() {
|
|
|
}
|
|
|
|
|
|
_checkSudo() {
|
|
|
+ if [ -z "__INTERACTIVE" ]; then
|
|
|
+ #don't check if it's not in an interactive shell
|
|
|
+ return 0
|
|
|
+ fi
|
|
|
if [ "$SUDO_GID" ] && [ "$SUDO_COMMAND" ] && [ "$SUDO_USER" ] && [ "$SUDO_UID" ]; then
|
|
|
if [ "$SUDO_USER" = "root" ] && [ "$SUDO_UID" = "0" ]; then
|
|
|
#it's root using sudo, no matter it's using sudo or not, just fine
|
|
@@ -6922,8 +7097,8 @@ _process() {
|
|
|
_altdomains="$NO_VALUE"
|
|
|
_webroot=""
|
|
|
_challenge_alias=""
|
|
|
- _keylength=""
|
|
|
- _accountkeylength=""
|
|
|
+ _keylength="$DEFAULT_DOMAIN_KEY_LENGTH"
|
|
|
+ _accountkeylength="$DEFAULT_ACCOUNT_KEY_LENGTH"
|
|
|
_cert_file=""
|
|
|
_key_file=""
|
|
|
_ca_file=""
|
|
@@ -6970,6 +7145,8 @@ _process() {
|
|
|
_eab_kid=""
|
|
|
_eab_hmac_key=""
|
|
|
_preferred_chain=""
|
|
|
+ _valid_from=""
|
|
|
+ _valid_to=""
|
|
|
while [ ${#} -gt 0 ]; do
|
|
|
case "${1}" in
|
|
|
|
|
@@ -7277,6 +7454,14 @@ _process() {
|
|
|
Le_RenewalDays="$_days"
|
|
|
shift
|
|
|
;;
|
|
|
+ --valid-from)
|
|
|
+ _valid_from="$2"
|
|
|
+ shift
|
|
|
+ ;;
|
|
|
+ --valid-to)
|
|
|
+ _valid_to="$2"
|
|
|
+ shift
|
|
|
+ ;;
|
|
|
--httpport)
|
|
|
_httpport="$2"
|
|
|
Le_HTTPPort="$_httpport"
|
|
@@ -7479,6 +7664,7 @@ _process() {
|
|
|
|
|
|
if [ "$_server" ]; then
|
|
|
_selectServer "$_server" "${_ecc:-$_keylength}"
|
|
|
+ _server="$ACME_DIRECTORY"
|
|
|
fi
|
|
|
|
|
|
if [ "${_CMD}" != "install" ]; then
|
|
@@ -7538,7 +7724,7 @@ _process() {
|
|
|
uninstall) uninstall "$_nocron" ;;
|
|
|
upgrade) upgrade ;;
|
|
|
issue)
|
|
|
- issue "$_webroot" "$_domain" "$_altdomains" "$_keylength" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" "$_preferred_chain"
|
|
|
+ issue "$_webroot" "$_domain" "$_altdomains" "$_keylength" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" "$_preferred_chain" "$_valid_from" "$_valid_to"
|
|
|
;;
|
|
|
deploy)
|
|
|
deploy "$_domain" "$_deploy_hook" "$_ecc"
|
|
@@ -7553,10 +7739,10 @@ _process() {
|
|
|
installcert "$_domain" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_ecc"
|
|
|
;;
|
|
|
renew)
|
|
|
- renew "$_domain" "$_ecc"
|
|
|
+ renew "$_domain" "$_ecc" "$_server"
|
|
|
;;
|
|
|
renewAll)
|
|
|
- renewAll "$_stopRenewOnError"
|
|
|
+ renewAll "$_stopRenewOnError" "$_server"
|
|
|
;;
|
|
|
revoke)
|
|
|
revoke "$_domain" "$_ecc" "$_revoke_reason"
|