]> git.proxmox.com Git - mirror_acme.sh.git/blobdiff - acme.sh
fix log path
[mirror_acme.sh.git] / acme.sh
diff --git a/acme.sh b/acme.sh
index ad825435d4300baea19da60a3309642e3f248d39..e8228e3089fd9709865ad731ad914db93a1b9d35 100755 (executable)
--- a/acme.sh
+++ b/acme.sh
@@ -1,6 +1,6 @@
 #!/usr/bin/env sh
 
-VER=3.0.3
+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"
 
@@ -93,6 +91,7 @@ END_CERT="-----END CERTIFICATE-----"
 
 CONTENT_TYPE_JSON="application/jose+json"
 RENEW_SKIP=2
+CODE_DNS_MANUAL=3
 
 B64CONF_START="__ACME_BASE64__START_"
 B64CONF_END="__ACME_BASE64__END_"
@@ -438,21 +437,13 @@ _secure_debug3() {
 }
 
 _upper_case() {
-  if _is_solaris; then
-    tr '[:lower:]' '[:upper:]'
-  else
-    # shellcheck disable=SC2018,SC2019
-    tr 'a-z' 'A-Z'
-  fi
+  # shellcheck disable=SC2018,SC2019
+  tr '[a-z]' '[A-Z]'
 }
 
 _lower_case() {
-  if _is_solaris; then
-    tr '[:upper:]' '[:lower:]'
-  else
-    # shellcheck disable=SC2018,SC2019
-    tr 'A-Z' 'a-z'
-  fi
+  # shellcheck disable=SC2018,SC2019
+  tr '[A-Z]' '[a-z]'
 }
 
 _startswith() {
@@ -983,9 +974,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
 }
 
@@ -1195,7 +1186,7 @@ _createkey() {
 _is_idn() {
   _is_idn_d="$1"
   _debug2 _is_idn_d "$_is_idn_d"
-  _idn_temp=$(printf "%s" "$_is_idn_d" | tr -d '0-9' | tr -d 'a-z' | tr -d 'A-Z' | tr -d '*.,-_')
+  _idn_temp=$(printf "%s" "$_is_idn_d" | tr -d '[0-9]' | tr -d '[a-z]' | tr -d '[A-Z]' | tr -d '*.,-_')
   _debug2 _idn_temp "$_idn_temp"
   [ "$_idn_temp" ]
 }
@@ -2691,6 +2682,12 @@ _initAPI() {
   return 1
 }
 
+_clearCA() {
+  export CA_CONF=
+  export ACCOUNT_KEY_PATH=
+  export ACCOUNT_JSON_PATH=
+}
+
 #[domain]  [keylength or isEcc flag]
 _initpath() {
   domain="$1"
@@ -4198,7 +4195,7 @@ _match_issuer() {
 _isIPv4() {
   for seg in $(echo "$1" | tr '.' ' '); do
     _debug2 seg "$seg"
-    if [ "$(echo "$seg" | tr -d [0-9])" ]; then
+    if [ "$(echo "$seg" | tr -d '[0-9]')" ]; then
       #not all number
       return 1
     fi
@@ -4382,10 +4379,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
@@ -4406,7 +4399,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
@@ -4680,6 +4679,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
@@ -4755,7 +4755,9 @@ $_authorizations_map"
       _err "Please add the TXT records to the domains, and re-run with --renew."
       _on_issue_err "$_post_hook"
       _clearup
-      return 1
+      # If asked to be in manual DNS mode, flag this exit with a separate
+      # error so it can be distinguished from other failures.
+      return $CODE_DNS_MANUAL
     fi
 
   fi
@@ -4974,7 +4976,7 @@ $_authorizations_map"
         return 1
       fi
       _debug "sleep 2 secs to verify again"
-      sleep 2
+      _sleep 2
       _debug "checking"
 
       _send_signed_request "$uri"
@@ -5240,17 +5242,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
@@ -5264,42 +5269,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
-    Le_API="$CA_LETSENCRYPT_V2"
-  fi
 
-  #revert from staging CAs back to production CAs
-  if [ -z "$ACME_DIRECTORY" ]; then
-    case "$Le_API" in
+  case "$Le_API" in
+  "$CA_LETSENCRYPT_V2_TEST")
+    _info "Switching back to $CA_LETSENCRYPT_V2"
+    Le_API="$CA_LETSENCRYPT_V2"
+    ;;
+  "$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
 
-    "$CA_LETSENCRYPT_V2_TEST")
-      _info "Switching back to $CA_LETSENCRYPT_V2"
-      Le_API="$CA_LETSENCRYPT_V2"
-      ;;
-    "$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 [ "$_server" ]; then
+    Le_API="$_server"
   fi
+  _info "Renew to Le_API=$Le_API"
 
-  if [ "$Le_API" ] && [ "$ACME_DIRECTORY" ]; then
-    if [ "$Le_API" != "$ACME_DIRECTORY" ]; then
-      _clearAPI
-    fi
-    #reload ca configs
-    ACCOUNT_KEY_PATH=""
-    ACCOUNT_JSON_PATH=""
-    CA_CONF=""
-    _debug3 "initpath again."
-    _initpath "$Le_Domain" "$_isEcc"
-  fi
+  _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")"
@@ -5323,6 +5320,13 @@ renew() {
   Le_PostHook="$(_readdomainconf Le_PostHook)"
   Le_RenewHook="$(_readdomainconf Le_RenewHook)"
   Le_Preferred_Chain="$(_readdomainconf 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
@@ -5350,11 +5354,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=""
@@ -5377,7 +5386,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"
@@ -5738,7 +5747,9 @@ _installcert() {
     if [ -f "$_real_cert" ] && [ ! "$_ACME_IS_RENEW" ]; then
       cp "$_real_cert" "$_backup_path/cert.bak"
     fi
-    cat "$CERT_PATH" >"$_real_cert" || return 1
+    if [ "$CERT_PATH" != "$_real_cert" ]; then
+      cat "$CERT_PATH" >"$_real_cert" || return 1
+    fi
   fi
 
   if [ "$_real_ca" ]; then
@@ -5750,7 +5761,9 @@ _installcert() {
       if [ -f "$_real_ca" ] && [ ! "$_ACME_IS_RENEW" ]; then
         cp "$_real_ca" "$_backup_path/ca.bak"
       fi
-      cat "$CA_CERT_PATH" >"$_real_ca" || return 1
+      if [ "$CA_CERT_PATH" != "$_real_ca" ]; then
+        cat "$CA_CERT_PATH" >"$_real_ca" || return 1
+      fi
     fi
   fi
 
@@ -5759,12 +5772,14 @@ _installcert() {
     if [ -f "$_real_key" ] && [ ! "$_ACME_IS_RENEW" ]; then
       cp "$_real_key" "$_backup_path/key.bak"
     fi
-    if [ -f "$_real_key" ]; then
-      cat "$CERT_KEY_PATH" >"$_real_key" || return 1
-    else
-      touch "$_real_key" || return 1
-      chmod 600 "$_real_key"
-      cat "$CERT_KEY_PATH" >"$_real_key" || return 1
+    if [ "$CERT_KEY_PATH" != "$_real_key" ]; then
+      if [ -f "$_real_key" ]; then
+        cat "$CERT_KEY_PATH" >"$_real_key" || return 1
+      else
+        touch "$_real_key" || return 1
+        chmod 600 "$_real_key"
+        cat "$CERT_KEY_PATH" >"$_real_key" || return 1
+      fi
     fi
   fi
 
@@ -5773,7 +5788,9 @@ _installcert() {
     if [ -f "$_real_fullchain" ] && [ ! "$_ACME_IS_RENEW" ]; then
       cp "$_real_fullchain" "$_backup_path/fullchain.bak"
     fi
-    cat "$CERT_FULLCHAIN_PATH" >"$_real_fullchain" || return 1
+    if [ "$_real_fullchain" != "$CERT_FULLCHAIN_PATH" ]; then
+      cat "$CERT_FULLCHAIN_PATH" >"$_real_fullchain" || return 1
+    fi
   fi
 
   if [ "$_reload_cmd" ]; then
@@ -6958,6 +6975,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
@@ -7079,8 +7100,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=""
@@ -7646,6 +7667,7 @@ _process() {
 
   if [ "$_server" ]; then
     _selectServer "$_server" "${_ecc:-$_keylength}"
+    _server="$ACME_DIRECTORY"
   fi
 
   if [ "${_CMD}" != "install" ]; then
@@ -7720,10 +7742,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"