]> git.proxmox.com Git - mirror_acme.sh.git/blobdiff - acme.sh
RI
[mirror_acme.sh.git] / acme.sh
diff --git a/acme.sh b/acme.sh
index d6d8e48c6c34949c74d0060dbd7e58290e2a1ce5..7a9468fde10c005ebff2d5e65c4a97224cdd70dc 100755 (executable)
--- a/acme.sh
+++ b/acme.sh
@@ -1,6 +1,6 @@
 #!/usr/bin/env sh
 
-VER=3.0.5
+VER=3.0.7
 
 PROJECT_NAME="acme.sh"
 
@@ -53,8 +53,8 @@ CA_SERVERS="$CA_ZEROSSL,$CA_LETSENCRYPT_V2,$CA_LETSENCRYPT_V2_TEST,$CA_BUYPASS,$
 
 DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)"
 
-DEFAULT_ACCOUNT_KEY_LENGTH=2048
-DEFAULT_DOMAIN_KEY_LENGTH=2048
+DEFAULT_ACCOUNT_KEY_LENGTH=ec-256
+DEFAULT_DOMAIN_KEY_LENGTH=ec-256
 
 DEFAULT_OPENSSL_BIN="openssl"
 
@@ -1637,7 +1637,7 @@ _stat() {
 #keyfile
 _isRSA() {
   keyfile=$1
-  if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1 || ${ACME_OPENSSL_BIN:-openssl} rsa -in "$keyfile" -noout -text | grep "^publicExponent:" >/dev/null 2>&1; then
+  if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1 || ${ACME_OPENSSL_BIN:-openssl} rsa -in "$keyfile" -noout -text 2>&1 | grep "^publicExponent:" 2>&1 >/dev/null; then
     return 0
   fi
   return 1
@@ -1646,7 +1646,7 @@ _isRSA() {
 #keyfile
 _isEcc() {
   keyfile=$1
-  if grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1 || ${ACME_OPENSSL_BIN:-openssl} ec -in "$keyfile" -noout -text 2>/dev/null | grep "^NIST CURVE:" >/dev/null 2>&1; then
+  if grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1 || ${ACME_OPENSSL_BIN:-openssl} ec -in "$keyfile" -noout -text 2>/dev/null | grep "^NIST CURVE:" 2>&1 >/dev/null; then
     return 0
   fi
   return 1
@@ -1744,7 +1744,7 @@ _calcjwk() {
     _debug3 x64 "$x64"
 
     xend=$(_math "$xend" + 1)
-    y="$(printf "%s" "$pubtext" | cut -d : -f "$xend"-10000)"
+    y="$(printf "%s" "$pubtext" | cut -d : -f "$xend"-2048)"
     _debug3 y "$y"
 
     y64="$(printf "%s" "$y" | tr -d : | _h2b | _base64 | _url_replace)"
@@ -1852,9 +1852,15 @@ _inithttp() {
       _ACME_CURL="$_ACME_CURL --cacert $CA_BUNDLE "
     fi
 
-    if _contains "$(curl --help 2>&1)" "--globoff"; then
+    if _contains "$(curl --help 2>&1)" "--globoff" || _contains "$(curl --help curl 2>&1)" "--globoff"; then
       _ACME_CURL="$_ACME_CURL -g "
     fi
+
+    #don't use --fail-with-body
+    ##from curl 7.76: return fail on HTTP errors but keep the body
+    #if _contains "$(curl --help http 2>&1)" "--fail-with-body"; then
+    #  _ACME_CURL="$_ACME_CURL --fail-with-body "
+    #fi
   fi
 
   if [ -z "$_ACME_WGET" ] && _exists "wget"; then
@@ -1872,11 +1878,11 @@ _inithttp() {
     elif [ "$CA_BUNDLE" ]; then
       _ACME_WGET="$_ACME_WGET --ca-certificate=$CA_BUNDLE "
     fi
-  fi
 
-  #from wget 1.14: do not skip body on 404 error
-  if [ "$_ACME_WGET" ] && _contains "$($_ACME_WGET --help 2>&1)" "--content-on-error"; then
-    _ACME_WGET="$_ACME_WGET --content-on-error "
+    #from wget 1.14: do not skip body on 404 error
+    if _contains "$(wget --help 2>&1)" "--content-on-error"; then
+      _ACME_WGET="$_ACME_WGET --content-on-error "
+    fi
   fi
 
   __HTTP_INITIALIZED=1
@@ -2058,7 +2064,7 @@ _get() {
     fi
     _debug "_WGET" "$_WGET"
     if [ "$onlyheader" ]; then
-      _wget_out = "$($_WGET --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" -S -O /dev/null "$url" 2>&1)"
+      _wget_out="$($_WGET --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" -S -O /dev/null "$url" 2>&1)"
       if _contains "$_WGET" " -d "; then
         # Demultiplex wget debug output
         echo "$_wget_out" >&2
@@ -2110,6 +2116,7 @@ _send_signed_request() {
   if [ -z "$keyfile" ]; then
     keyfile="$ACCOUNT_KEY_PATH"
   fi
+  _debug "=======Begin Send Signed Request======="
   _debug url "$url"
   _debug payload "$payload"
 
@@ -2223,6 +2230,20 @@ _send_signed_request() {
         _debug3 _body "$_body"
       fi
 
+      _retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *: *[0-9]\+ *" | cut -d : -f 2 | tr -d ' ' | tr -d '\r')
+      if [ "$code" = '503' ]; then
+        _sleep_overload_retry_sec=$_retryafter
+        if [ -z "$_sleep_overload_retry_sec" ]; then
+          _sleep_overload_retry_sec=5
+        fi
+        if [ $_sleep_overload_retry_sec -le 600 ]; then
+          _info "It seems the CA server is currently overloaded, let's wait and retry. Sleeping $_sleep_overload_retry_sec seconds."
+          _sleep $_sleep_overload_retry_sec
+          continue
+        else
+          _info "The retryafter=$_retryafter is too large > 600, not retry anymore."
+        fi
+      fi
       if _contains "$_body" "JWS has invalid anti-replay nonce" || _contains "$_body" "JWS has an invalid anti-replay nonce"; then
         _info "It seems the CA server is busy now, let's wait and retry. Sleeping $_sleep_retry_sec seconds."
         _CACHED_NONCE=""
@@ -2257,7 +2278,7 @@ _setopt() {
   if [ ! -f "$__conf" ]; then
     touch "$__conf"
   fi
-  if [ -n "$(tail -c 1 <"$__conf")" ]; then
+  if [ -n "$(tail -c1 <"$__conf")" ]; then
     echo >>"$__conf"
   fi
 
@@ -2352,6 +2373,26 @@ _readdomainconf() {
   _read_conf "$DOMAIN_CONF" "$1"
 }
 
+#_migratedomainconf   oldkey  newkey  base64encode
+_migratedomainconf() {
+  _old_key="$1"
+  _new_key="$2"
+  _b64encode="$3"
+  _value=$(_readdomainconf "$_old_key")
+  if [ -z "$_value" ]; then
+    return 1 # oldkey is not found
+  fi
+  _savedomainconf "$_new_key" "$_value" "$_b64encode"
+  _cleardomainconf "$_old_key"
+  _debug "Domain config $_old_key has been migrated to $_new_key"
+}
+
+#_migratedeployconf   oldkey  newkey  base64encode
+_migratedeployconf() {
+  _migratedomainconf "$1" "SAVED_$2" "$3" ||
+    _migratedomainconf "SAVED_$1" "SAVED_$2" "$3" # try only when oldkey itself is not found
+}
+
 #key  value  base64encode
 _savedeployconf() {
   _savedomainconf "SAVED_$1" "$2" "$3"
@@ -2366,12 +2407,14 @@ _getdeployconf() {
   if [ "$_rac_value" ]; then
     if _startswith "$_rac_value" '"' && _endswith "$_rac_value" '"'; then
       _debug2 "trim quotation marks"
-      eval "export $_rac_key=$_rac_value"
+      eval $_rac_key=$_rac_value
+      export $_rac_key
     fi
     return 0 # do nothing
   fi
-  _saved=$(_readdomainconf "SAVED_$_rac_key")
-  eval "export $_rac_key=\"\$_saved\""
+  _saved="$(_readdomainconf "SAVED_$_rac_key")"
+  eval $_rac_key=\$_saved
+  export $_rac_key
 }
 
 #_saveaccountconf  key  value  base64encode
@@ -2835,12 +2878,14 @@ _initpath() {
 
     if _isEccKey "$_ilength"; then
       DOMAIN_PATH="$domainhomeecc"
-    else
+    elif [ -z "$__SELECTED_RSA_KEY" ]; then
       if [ ! -d "$domainhome" ] && [ -d "$domainhomeecc" ]; then
-        _info "The domain '$domain' seems to have a ECC cert already, please add '$(__red "--ecc")' parameter if you want to use that cert."
+        _info "The domain '$domain' seems to have a ECC cert already, lets use ecc cert."
+        DOMAIN_PATH="$domainhomeecc"
       fi
     fi
     _debug DOMAIN_PATH "$DOMAIN_PATH"
+    export DOMAIN_PATH
   fi
 
   if [ -z "$DOMAIN_BACKUP_PATH" ]; then
@@ -2892,22 +2937,6 @@ _initpath() {
 
 }
 
-_exec() {
-  if [ -z "$_EXEC_TEMP_ERR" ]; then
-    _EXEC_TEMP_ERR="$(_mktemp)"
-  fi
-
-  if [ "$_EXEC_TEMP_ERR" ]; then
-    eval "$@ 2>>$_EXEC_TEMP_ERR"
-  else
-    eval "$@"
-  fi
-}
-
-_exec_err() {
-  [ "$_EXEC_TEMP_ERR" ] && _err "$(cat "$_EXEC_TEMP_ERR")" && echo "" >"$_EXEC_TEMP_ERR"
-}
-
 _apachePath() {
   _APACHECTL="apachectl"
   if ! _exists apachectl; then
@@ -2920,8 +2949,7 @@ _apachePath() {
     fi
   fi
 
-  if ! _exec $_APACHECTL -V >/dev/null; then
-    _exec_err
+  if ! $_APACHECTL -V >/dev/null; then
     return 1
   fi
 
@@ -2973,8 +3001,7 @@ _restoreApache() {
 
   cat "$APACHE_CONF_BACKUP_DIR/$httpdconfname" >"$httpdconf"
   _debug "Restored: $httpdconf."
-  if ! _exec $_APACHECTL -t; then
-    _exec_err
+  if ! $_APACHECTL -t; then
     _err "Sorry, restore apache config error, please contact me."
     return 1
   fi
@@ -2992,8 +3019,7 @@ _setApache() {
   #test the conf first
   _info "Checking if there is an error in the apache config file before starting."
 
-  if ! _exec "$_APACHECTL" -t >/dev/null; then
-    _exec_err
+  if ! $_APACHECTL -t >/dev/null; then
     _err "The apache config file has error, please fix it first, then try again."
     _err "Don't worry, there is nothing changed to your system."
     return 1
@@ -3054,8 +3080,7 @@ Allow from all
     chmod 755 "$ACME_DIR"
   fi
 
-  if ! _exec "$_APACHECTL" graceful; then
-    _exec_err
+  if ! $_APACHECTL graceful; then
     _err "$_APACHECTL  graceful error, please contact me."
     _restoreApache
     return 1
@@ -3140,8 +3165,7 @@ _setNginx() {
     return 1
   fi
   _info "Check the nginx conf before setting up."
-  if ! _exec "nginx -t" >/dev/null; then
-    _exec_err
+  if ! nginx -t >/dev/null; then
     return 1
   fi
 
@@ -3168,16 +3192,14 @@ location ~ \"^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)\$\" {
   fi
   _debug3 "Modified config:$(cat $FOUND_REAL_NGINX_CONF)"
   _info "nginx conf is done, let's check it again."
-  if ! _exec "nginx -t" >/dev/null; then
-    _exec_err
+  if ! nginx -t >/dev/null; then
     _err "It seems that nginx conf was broken, let's restore."
     cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF"
     return 1
   fi
 
   _info "Reload nginx"
-  if ! _exec "nginx -s reload" >/dev/null; then
-    _exec_err
+  if ! nginx -s reload >/dev/null; then
     _err "It seems that nginx reload error, let's restore."
     cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF"
     return 1
@@ -3302,8 +3324,7 @@ _restoreNginx() {
   done
 
   _info "Reload nginx"
-  if ! _exec "nginx -s reload" >/dev/null; then
-    _exec_err
+  if ! nginx -s reload >/dev/null; then
     _err "It seems that nginx reload error, please report bug."
     return 1
   fi
@@ -3995,7 +4016,7 @@ _ns_purge_cf() {
 
 #checks if cf server is available
 _ns_is_available_cf() {
-  if _get "https://cloudflare-dns.com" "" 1 >/dev/null 2>&1; then
+  if _get "https://cloudflare-dns.com" "" 10 >/dev/null; then
     return 0
   else
     return 1
@@ -4003,7 +4024,7 @@ _ns_is_available_cf() {
 }
 
 _ns_is_available_google() {
-  if _get "https://dns.google" "" 1 >/dev/null 2>&1; then
+  if _get "https://dns.google" "" 10 >/dev/null; then
     return 0
   else
     return 1
@@ -4019,7 +4040,7 @@ _ns_lookup_google() {
 }
 
 _ns_is_available_ali() {
-  if _get "https://dns.alidns.com" "" 1 >/dev/null 2>&1; then
+  if _get "https://dns.alidns.com" "" 10 >/dev/null; then
     return 0
   else
     return 1
@@ -4035,7 +4056,7 @@ _ns_lookup_ali() {
 }
 
 _ns_is_available_dp() {
-  if _get "https://doh.pub" "" 1 >/dev/null 2>&1; then
+  if _get "https://doh.pub" "" 10 >/dev/null; then
     return 0
   else
     return 1
@@ -4582,9 +4603,10 @@ issue() {
         _d="*.$_d"
       fi
       _debug2 _d "$_d"
-      _authorizations_map="$_d,$response
+      _authorizations_map="$_d,$response#$_authz_url
 $_authorizations_map"
     done
+
     _debug2 _authorizations_map "$_authorizations_map"
 
     _index=0
@@ -4636,33 +4658,32 @@ $_authorizations_map"
         _on_issue_err "$_post_hook"
         return 1
       fi
-
+      _authz_url="$(echo "$_candidates" | sed "s/$_idn_d,//" | _egrep_o "#.*" | sed "s/^#//")"
+      _debug _authz_url "$_authz_url"
       if [ -z "$thumbprint" ]; then
         thumbprint="$(__calc_account_thumbprint)"
       fi
 
+      keyauthorization=""
+
+      if echo "$response" | grep '"status":"valid"' >/dev/null 2>&1; then
+        _debug "$d is already valid."
+        keyauthorization="$STATE_VERIFIED"
+        _debug keyauthorization "$keyauthorization"
+      fi
+
       entry="$(echo "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"
       _debug entry "$entry"
-      keyauthorization=""
-      if [ -z "$entry" ]; then
-        if ! _startswith "$d" '*.'; then
-          _debug "Not a wildcard domain, lets check whether the validation is already valid."
-          if echo "$response" | grep '"status":"valid"' >/dev/null 2>&1; then
-            _debug "$d is already valid."
-            keyauthorization="$STATE_VERIFIED"
-            _debug keyauthorization "$keyauthorization"
-          fi
-        fi
-        if [ -z "$keyauthorization" ]; then
-          _err "Error, can not get domain token entry $d for $vtype"
-          _supported_vtypes="$(echo "$response" | _egrep_o "\"challenges\":\[[^]]*]" | tr '{' "\n" | grep type | cut -d '"' -f 4 | tr "\n" ' ')"
-          if [ "$_supported_vtypes" ]; then
-            _err "The supported validation types are: $_supported_vtypes, but you specified: $vtype"
-          fi
-          _clearup
-          _on_issue_err "$_post_hook"
-          return 1
+
+      if [ -z "$keyauthorization" -a -z "$entry" ]; then
+        _err "Error, can not get domain token entry $d for $vtype"
+        _supported_vtypes="$(echo "$response" | _egrep_o "\"challenges\":\[[^]]*]" | tr '{' "\n" | grep type | cut -d '"' -f 4 | tr "\n" ' ')"
+        if [ "$_supported_vtypes" ]; then
+          _err "The supported validation types are: $_supported_vtypes, but you specified: $vtype"
         fi
+        _clearup
+        _on_issue_err "$_post_hook"
+        return 1
       fi
 
       if [ -z "$keyauthorization" ]; then
@@ -4688,15 +4709,9 @@ $_authorizations_map"
         fi
         keyauthorization="$token.$thumbprint"
         _debug keyauthorization "$keyauthorization"
-
-        if printf "%s" "$response" | grep '"status":"valid"' >/dev/null 2>&1; then
-          _debug "$d is already verified."
-          keyauthorization="$STATE_VERIFIED"
-          _debug keyauthorization "$keyauthorization"
-        fi
       fi
 
-      dvlist="$d$sep$keyauthorization$sep$uri$sep$vtype$sep$_currentRoot"
+      dvlist="$d$sep$keyauthorization$sep$uri$sep$vtype$sep$_currentRoot$sep$_authz_url"
       _debug dvlist "$dvlist"
 
       vlist="$vlist$dvlist$dvsep"
@@ -4713,6 +4728,7 @@ $_authorizations_map"
       keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2)
       vtype=$(echo "$ventry" | cut -d "$sep" -f 4)
       _currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5)
+      _authz_url=$(echo "$ventry" | cut -d "$sep" -f 6)
       _debug d "$d"
       if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then
         _debug "$d is already verified, skip $vtype."
@@ -4838,7 +4854,7 @@ $_authorizations_map"
     uri=$(echo "$ventry" | cut -d "$sep" -f 3)
     vtype=$(echo "$ventry" | cut -d "$sep" -f 4)
     _currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5)
-
+    _authz_url=$(echo "$ventry" | cut -d "$sep" -f 6)
     if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then
       _info "$d is already verified, skip $vtype."
       continue
@@ -4848,6 +4864,7 @@ $_authorizations_map"
     _debug "d" "$d"
     _debug "keyauthorization" "$keyauthorization"
     _debug "uri" "$uri"
+    _debug "_authz_url" "$_authz_url"
     removelevel=""
     token="$(printf "%s" "$keyauthorization" | cut -d '.' -f 1)"
 
@@ -4917,18 +4934,6 @@ $_authorizations_map"
         if ! chmod a+r "$wellknown_path/$token"; then
           _debug "chmod failed, but we just continue."
         fi
-        if [ ! "$usingApache" ]; then
-          if webroot_owner=$(_stat "$_currentRoot"); then
-            _debug "Changing owner/group of .well-known to $webroot_owner"
-            if ! _exec "chown -R \"$webroot_owner\" \"$_currentRoot/.well-known\""; then
-              _debug "$(cat "$_EXEC_TEMP_ERR")"
-              _exec_err >/dev/null 2>&1
-            fi
-          else
-            _debug "not changing owner/group of webroot"
-          fi
-        fi
-
       fi
     elif [ "$vtype" = "$VTYPE_ALPN" ]; then
       acmevalidationv1="$(printf "%s" "$keyauthorization" | _digest "sha256" "hex")"
@@ -4967,6 +4972,7 @@ $_authorizations_map"
       MAX_RETRY_TIMES=30
     fi
 
+    _debug "Lets check the status of the authz"
     while true; do
       waittimes=$(_math "$waittimes" + 1)
       if [ "$waittimes" -ge "$MAX_RETRY_TIMES" ]; then
@@ -5014,9 +5020,9 @@ $_authorizations_map"
         break
       fi
 
-      if [ "$status" = "pending" ]; then
+      if _contains "$status" "pending"; then
         _info "Pending, The CA is processing your order, please just wait. ($waittimes/$MAX_RETRY_TIMES)"
-      elif [ "$status" = "processing" ]; then
+      elif _contains "$status" "processing"; then
         _info "Processing, The CA is processing your order, please just wait. ($waittimes/$MAX_RETRY_TIMES)"
       else
         _err "$d:Verify error:$response"
@@ -5029,7 +5035,7 @@ $_authorizations_map"
       _sleep 2
       _debug "checking"
 
-      _send_signed_request "$uri"
+      _send_signed_request "$_authz_url"
 
       if [ "$?" != "0" ]; then
         _err "$d:Verify error:$response"
@@ -5743,6 +5749,7 @@ deploy() {
     return 1
   fi
 
+  _debug2 DOMAIN_CONF "$DOMAIN_CONF"
   . "$DOMAIN_CONF"
 
   _savedomainconf Le_DeployHook "$_hooks"
@@ -6102,8 +6109,22 @@ revoke() {
 
   uri="${ACME_REVOKE_CERT}"
 
+  _info "Try account key first."
+  if _send_signed_request "$uri" "$data" "" "$ACCOUNT_KEY_PATH"; then
+    if [ -z "$response" ]; then
+      _info "Revoke success."
+      rm -f "$CERT_PATH"
+      cat "$CERT_KEY_PATH" >"$CERT_KEY_PATH.revoked"
+      cat "$CSR_PATH" >"$CSR_PATH.revoked"
+      return 0
+    else
+      _err "Revoke error."
+      _debug "$response"
+    fi
+  fi
+
   if [ -f "$CERT_KEY_PATH" ]; then
-    _info "Try domain key first."
+    _info "Try domain key."
     if _send_signed_request "$uri" "$data" "" "$CERT_KEY_PATH"; then
       if [ -z "$response" ]; then
         _info "Revoke success."
@@ -6119,21 +6140,6 @@ revoke() {
   else
     _info "Domain key file doesn't exist."
   fi
-
-  _info "Try account key."
-
-  if _send_signed_request "$uri" "$data" "" "$ACCOUNT_KEY_PATH"; then
-    if [ -z "$response" ]; then
-      _info "Revoke success."
-      rm -f "$CERT_PATH"
-      cat "$CERT_KEY_PATH" >"$CERT_KEY_PATH.revoked"
-      cat "$CSR_PATH" >"$CSR_PATH.revoked"
-      return 0
-    else
-      _err "Revoke error."
-      _debug "$response"
-    fi
-  fi
   return 1
 }
 
@@ -6707,6 +6713,13 @@ _send_notify() {
     return 0
   fi
 
+  _nsource="$NOTIFY_SOURCE"
+  if [ -z "$_nsource" ]; then
+    _nsource="$(hostname)"
+  fi
+
+  _nsubject="$_nsubject by $_nsource"
+
   _send_err=0
   for _n_hook in $(echo "$_nhooks" | tr ',' " "); do
     _n_hook_file="$(_findHook "" $_SUB_FOLDER_NOTIFY "$_n_hook")"
@@ -6761,11 +6774,12 @@ setnotify() {
   _nhook="$1"
   _nlevel="$2"
   _nmode="$3"
+  _nsource="$4"
 
   _initpath
 
-  if [ -z "$_nhook$_nlevel$_nmode" ]; then
-    _usage "Usage: $PROJECT_ENTRY --set-notify [--notify-hook <hookname>] [--notify-level <0|1|2|3>] [--notify-mode <0|1>]"
+  if [ -z "$_nhook$_nlevel$_nmode$_nsource" ]; then
+    _usage "Usage: $PROJECT_ENTRY --set-notify [--notify-hook <hookname>] [--notify-level <0|1|2|3>] [--notify-mode <0|1>] [--notify-source <hostname>]"
     _usage "$_NOTIFY_WIKI"
     return 1
   fi
@@ -6782,6 +6796,12 @@ setnotify() {
     _saveaccountconf "NOTIFY_MODE" "$NOTIFY_MODE"
   fi
 
+  if [ "$_nsource" ]; then
+    _info "Set notify source to: $_nsource"
+    export "NOTIFY_SOURCE=$_nsource"
+    _saveaccountconf "NOTIFY_SOURCE" "$NOTIFY_SOURCE"
+  fi
+
   if [ "$_nhook" ]; then
     _info "Set notify hook to: $_nhook"
     if [ "$_nhook" = "$NO_VALUE" ]; then
@@ -6942,6 +6962,7 @@ Parameters:
                                       0: Bulk mode. Send all the domain's notifications in one message(mail).
                                       1: Cert mode. Send a message for every single cert.
   --notify-hook <hookname>          Set the notify hook
+  --notify-source <server name>     Set the server name in the notification message
   --revoke-reason <0-10>            The reason for revocation, can be used in conjunction with the '--revoke' command.
                                       See: $_REVOKE_WIKI
 
@@ -7099,7 +7120,9 @@ _selectServer() {
 _getCAShortName() {
   caurl="$1"
   if [ -z "$caurl" ]; then
-    caurl="$DEFAULT_CA"
+    #use letsencrypt as default value if the Le_API is empty
+    #this case can only come from the old upgrading.
+    caurl="$CA_LETSENCRYPT_V2"
   fi
   if [ "$CA_SSLCOM_ECC" = "$caurl" ]; then
     caurl="$CA_SSLCOM_RSA" #just hack to get the short name
@@ -7216,6 +7239,7 @@ _process() {
   _notify_hook=""
   _notify_level=""
   _notify_mode=""
+  _notify_source=""
   _revoke_reason=""
   _eab_kid=""
   _eab_hmac_key=""
@@ -7461,6 +7485,9 @@ _process() {
     --keylength | -k)
       _keylength="$2"
       shift
+      if [ "$_keylength" ] && ! _isEccKey "$_keylength"; then
+        export __SELECTED_RSA_KEY=1
+      fi
       ;;
     -ak | --accountkeylength)
       _accountkeylength="$2"
@@ -7496,7 +7523,7 @@ _process() {
       shift
       ;;
     --home)
-      export LE_WORKING_DIR="$2"
+      export LE_WORKING_DIR="$(echo "$2" | sed 's|/$||')"
       shift
       ;;
     --cert-home | --certhome)
@@ -7708,6 +7735,15 @@ _process() {
       _notify_mode="$_nmode"
       shift
       ;;
+    --notify-source)
+      _nsource="$2"
+      if _startswith "$_nsource" "-"; then
+        _err "'$_nsource' is not valid host name for '$1'"
+        return 1
+      fi
+      _notify_source="$_nsource"
+      shift
+      ;;
     --revoke-reason)
       _revoke_reason="$2"
       if _startswith "$_revoke_reason" "-"; then
@@ -7862,7 +7898,7 @@ _process() {
     createCSR "$_domain" "$_altdomains" "$_ecc"
     ;;
   setnotify)
-    setnotify "$_notify_hook" "$_notify_level" "$_notify_mode"
+    setnotify "$_notify_hook" "$_notify_level" "$_notify_mode" "$_notify_source"
     ;;
   setdefaultca)
     setdefaultca