#!/usr/bin/env sh
-VER=2.8.9
+VER=3.0.1
PROJECT_NAME="acme.sh"
_SUB_FOLDERS="$_SUB_FOLDER_DNSAPI $_SUB_FOLDER_DEPLOY $_SUB_FOLDER_NOTIFY"
-LETSENCRYPT_CA_V1="https://acme-v01.api.letsencrypt.org/directory"
-LETSENCRYPT_STAGING_CA_V1="https://acme-staging.api.letsencrypt.org/directory"
+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"
CA_ZEROSSL="https://acme.zerossl.com/v2/DV90"
_ZERO_EAB_ENDPOINT="http://api.zerossl.com/acme/eab-credentials-email"
-DEFAULT_CA=$CA_LETSENCRYPT_V2
+CA_SSLCOM_RSA="https://acme.ssl.com/sslcom-dv-rsa"
+CA_SSLCOM_ECC="https://acme.ssl.com/sslcom-dv-ecc"
+
+DEFAULT_CA=$CA_ZEROSSL
DEFAULT_STAGING_CA=$CA_LETSENCRYPT_V2_TEST
CA_NAMES="
+ZeroSSL.com,zerossl
LetsEncrypt.org,letsencrypt
LetsEncrypt.org_test,letsencrypt_test,letsencrypttest
BuyPass.com,buypass
BuyPass.com_test,buypass_test,buypasstest
-ZeroSSL.com,zerossl
+SSL.com,sslcom
"
-CA_SERVERS="$CA_LETSENCRYPT_V2,$CA_LETSENCRYPT_V2_TEST,$CA_BUYPASS,$CA_BUYPASS_TEST,$CA_ZEROSSL"
+CA_SERVERS="$CA_ZEROSSL,$CA_LETSENCRYPT_V2,$CA_LETSENCRYPT_V2_TEST,$CA_BUYPASS,$CA_BUYPASS_TEST,$CA_SSLCOM_RSA"
DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)"
_ZEROSSL_WIKI="https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA"
+_SSLCOM_WIKI="https://github.com/acmesh-official/acme.sh/wiki/SSL.com-CA"
+
_SERVER_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Server"
_PREFERRED_CHAIN_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Preferred-Chain"
_debug2 csr "$csr"
_debug2 csrconf "$csrconf"
- printf "[ req_distinguished_name ]\n[ req ]\ndistinguished_name = req_distinguished_name\nreq_extensions = v3_req\n[ v3_req ]\n\nkeyUsage = nonRepudiation, digitalSignature, keyEncipherment" >"$csrconf"
+ printf "[ req_distinguished_name ]\n[ req ]\ndistinguished_name = req_distinguished_name\nreq_extensions = v3_req\n[ v3_req ]\n\n" >"$csrconf"
if [ "$acmeValidationv1" ]; then
domainlist="$(_idn "$domainlist")"
if [ -z "$ACME_HTTP_NO_REDIRECTS" ]; then
_ACME_CURL="$_ACME_CURL -L "
fi
- if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
+ if [ "$DEBUG" ] && [ "$DEBUG" -ge 2 ]; then
_CURL_DUMP="$(_mktemp)"
_ACME_CURL="$_ACME_CURL --trace-ascii $_CURL_DUMP "
fi
}
+_HTTP_MAX_RETRY=8
+
# body url [needbase64] [POST|PUT|DELETE] [ContentType]
_post() {
body="$1"
needbase64="$3"
httpmethod="$4"
_postContentType="$5"
+ _sleep_retry_sec=1
+ _http_retry_times=0
+ _hcode=0
+ while [ "${_http_retry_times}" -le "$_HTTP_MAX_RETRY" ]; do
+ [ "$_http_retry_times" = "$_HTTP_MAX_RETRY" ]
+ _lastHCode="$?"
+ _debug "Retrying post"
+ _post_impl "$body" "$_post_url" "$needbase64" "$httpmethod" "$_postContentType" "$_lastHCode"
+ _hcode="$?"
+ _debug _hcode "$_hcode"
+ if [ "$_hcode" = "0" ]; then
+ break
+ fi
+ _http_retry_times=$(_math $_http_retry_times + 1)
+ _sleep $_sleep_retry_sec
+ done
+ return $_hcode
+}
+
+# body url [needbase64] [POST|PUT|DELETE] [ContentType] [displayError]
+_post_impl() {
+ body="$1"
+ _post_url="$2"
+ needbase64="$3"
+ httpmethod="$4"
+ _postContentType="$5"
+ displayError="$6"
if [ -z "$httpmethod" ]; then
httpmethod="POST"
fi
_ret="$?"
if [ "$_ret" != "0" ]; then
- _err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $_ret"
+ if [ -z "$displayError" ] || [ "$displayError" = "0" ]; then
+ _err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $_ret"
+ fi
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
_err "Here is the curl dump log:"
_err "$(cat "$_CURL_DUMP")"
_debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later."
fi
if [ "$_ret" != "0" ]; then
- _err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $_ret"
+ if [ -z "$displayError" ] || [ "$displayError" = "0" ]; then
+ _err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $_ret"
+ fi
fi
_sed_i "s/^ *//g" "$HTTP_HEADER"
else
# url getheader timeout
_get() {
+ url="$1"
+ onlyheader="$2"
+ t="$3"
+ _sleep_retry_sec=1
+ _http_retry_times=0
+ _hcode=0
+ while [ "${_http_retry_times}" -le "$_HTTP_MAX_RETRY" ]; do
+ [ "$_http_retry_times" = "$_HTTP_MAX_RETRY" ]
+ _lastHCode="$?"
+ _debug "Retrying GET"
+ _get_impl "$url" "$onlyheader" "$t" "$_lastHCode"
+ _hcode="$?"
+ _debug _hcode "$_hcode"
+ if [ "$_hcode" = "0" ]; then
+ break
+ fi
+ _http_retry_times=$(_math $_http_retry_times + 1)
+ _sleep $_sleep_retry_sec
+ done
+ return $_hcode
+}
+
+# url getheader timeout displayError
+_get_impl() {
_debug GET
url="$1"
onlyheader="$2"
t="$3"
+ displayError="$4"
_debug url "$url"
_debug "timeout=$t"
-
+ _debug "displayError" "$displayError"
_inithttp
if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then
fi
ret=$?
if [ "$ret" != "0" ]; then
- _err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $ret"
+ if [ -z "$displayError" ] || [ "$displayError" = "0" ]; then
+ _err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $ret"
+ fi
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
_err "Here is the curl dump log:"
_err "$(cat "$_CURL_DUMP")"
_debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later."
fi
if [ "$ret" != "0" ]; then
- _err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $ret"
+ if [ -z "$displayError" ] || [ "$displayError" = "0" ]; then
+ _err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $ret"
+ fi
fi
else
ret=$?
_sleep 2
continue
fi
- if [ "$ACME_VERSION" = "2" ]; then
- if [ "$url" = "$ACME_NEW_ACCOUNT" ]; then
- protected="$JWK_HEADERPLACE_PART1$nonce\", \"url\": \"${url}$JWK_HEADERPLACE_PART2, \"jwk\": $jwk"'}'
- elif [ "$url" = "$ACME_REVOKE_CERT" ] && [ "$keyfile" != "$ACCOUNT_KEY_PATH" ]; then
- protected="$JWK_HEADERPLACE_PART1$nonce\", \"url\": \"${url}$JWK_HEADERPLACE_PART2, \"jwk\": $jwk"'}'
- else
- protected="$JWK_HEADERPLACE_PART1$nonce\", \"url\": \"${url}$JWK_HEADERPLACE_PART2, \"kid\": \"${ACCOUNT_URL}\""'}'
- fi
- else
+
+ if [ "$url" = "$ACME_NEW_ACCOUNT" ]; then
+ protected="$JWK_HEADERPLACE_PART1$nonce\", \"url\": \"${url}$JWK_HEADERPLACE_PART2, \"jwk\": $jwk"'}'
+ elif [ "$url" = "$ACME_REVOKE_CERT" ] && [ "$keyfile" != "$ACCOUNT_KEY_PATH" ]; then
protected="$JWK_HEADERPLACE_PART1$nonce\", \"url\": \"${url}$JWK_HEADERPLACE_PART2, \"jwk\": $jwk"'}'
+ else
+ protected="$JWK_HEADERPLACE_PART1$nonce\", \"url\": \"${url}$JWK_HEADERPLACE_PART2, \"kid\": \"${ACCOUNT_URL}\""'}'
fi
+
_debug3 protected "$protected"
protected64="$(printf "%s" "$protected" | _base64 | _url_replace)"
fi
}
+_clearAPI() {
+ ACME_NEW_ACCOUNT=""
+ ACME_KEY_CHANGE=""
+ ACME_NEW_AUTHZ=""
+ ACME_NEW_ORDER=""
+ ACME_REVOKE_CERT=""
+ ACME_NEW_NONCE=""
+ ACME_AGREEMENT=""
+}
+
#server
_initAPI() {
_api_server="${1:-$ACME_DIRECTORY}"
_debug "_init api for server: $_api_server"
- if [ -z "$ACME_NEW_ACCOUNT" ]; then
+ MAX_API_RETRY_TIMES=10
+ _sleep_retry_sec=10
+ _request_retry_times=0
+ while [ -z "$ACME_NEW_ACCOUNT" ] && [ "${_request_retry_times}" -lt "$MAX_API_RETRY_TIMES" ]; do
+ _request_retry_times=$(_math "$_request_retry_times" + 1)
response=$(_get "$_api_server")
if [ "$?" != "0" ]; then
_debug2 "response" "$response"
- _err "Can not init api."
- return 1
+ _info "Can not init api for: $_api_server."
+ _info "Sleep $_sleep_retry_sec and retry."
+ _sleep "$_sleep_retry_sec"
+ continue
fi
response=$(echo "$response" | _json_decode)
_debug2 "response" "$response"
- ACME_KEY_CHANGE=$(echo "$response" | _egrep_o 'key-change" *: *"[^"]*"' | cut -d '"' -f 3)
- if [ -z "$ACME_KEY_CHANGE" ]; then
- ACME_KEY_CHANGE=$(echo "$response" | _egrep_o 'keyChange" *: *"[^"]*"' | cut -d '"' -f 3)
- fi
+ ACME_KEY_CHANGE=$(echo "$response" | _egrep_o 'keyChange" *: *"[^"]*"' | cut -d '"' -f 3)
export ACME_KEY_CHANGE
- ACME_NEW_AUTHZ=$(echo "$response" | _egrep_o 'new-authz" *: *"[^"]*"' | cut -d '"' -f 3)
- if [ -z "$ACME_NEW_AUTHZ" ]; then
- ACME_NEW_AUTHZ=$(echo "$response" | _egrep_o 'newAuthz" *: *"[^"]*"' | cut -d '"' -f 3)
- fi
+ ACME_NEW_AUTHZ=$(echo "$response" | _egrep_o 'newAuthz" *: *"[^"]*"' | cut -d '"' -f 3)
export ACME_NEW_AUTHZ
- ACME_NEW_ORDER=$(echo "$response" | _egrep_o 'new-cert" *: *"[^"]*"' | cut -d '"' -f 3)
- ACME_NEW_ORDER_RES="new-cert"
- if [ -z "$ACME_NEW_ORDER" ]; then
- ACME_NEW_ORDER=$(echo "$response" | _egrep_o 'new-order" *: *"[^"]*"' | cut -d '"' -f 3)
- ACME_NEW_ORDER_RES="new-order"
- if [ -z "$ACME_NEW_ORDER" ]; then
- ACME_NEW_ORDER=$(echo "$response" | _egrep_o 'newOrder" *: *"[^"]*"' | cut -d '"' -f 3)
- fi
- fi
+ ACME_NEW_ORDER=$(echo "$response" | _egrep_o 'newOrder" *: *"[^"]*"' | cut -d '"' -f 3)
export ACME_NEW_ORDER
- export ACME_NEW_ORDER_RES
-
- ACME_NEW_ACCOUNT=$(echo "$response" | _egrep_o 'new-reg" *: *"[^"]*"' | cut -d '"' -f 3)
- ACME_NEW_ACCOUNT_RES="new-reg"
- if [ -z "$ACME_NEW_ACCOUNT" ]; then
- ACME_NEW_ACCOUNT=$(echo "$response" | _egrep_o 'new-account" *: *"[^"]*"' | cut -d '"' -f 3)
- ACME_NEW_ACCOUNT_RES="new-account"
- if [ -z "$ACME_NEW_ACCOUNT" ]; then
- ACME_NEW_ACCOUNT=$(echo "$response" | _egrep_o 'newAccount" *: *"[^"]*"' | cut -d '"' -f 3)
- if [ "$ACME_NEW_ACCOUNT" ]; then
- export ACME_VERSION=2
- fi
- fi
- fi
+
+ ACME_NEW_ACCOUNT=$(echo "$response" | _egrep_o 'newAccount" *: *"[^"]*"' | cut -d '"' -f 3)
export ACME_NEW_ACCOUNT
- export ACME_NEW_ACCOUNT_RES
- ACME_REVOKE_CERT=$(echo "$response" | _egrep_o 'revoke-cert" *: *"[^"]*"' | cut -d '"' -f 3)
- if [ -z "$ACME_REVOKE_CERT" ]; then
- ACME_REVOKE_CERT=$(echo "$response" | _egrep_o 'revokeCert" *: *"[^"]*"' | cut -d '"' -f 3)
- fi
+ ACME_REVOKE_CERT=$(echo "$response" | _egrep_o 'revokeCert" *: *"[^"]*"' | cut -d '"' -f 3)
export ACME_REVOKE_CERT
- ACME_NEW_NONCE=$(echo "$response" | _egrep_o 'new-nonce" *: *"[^"]*"' | cut -d '"' -f 3)
- if [ -z "$ACME_NEW_NONCE" ]; then
- ACME_NEW_NONCE=$(echo "$response" | _egrep_o 'newNonce" *: *"[^"]*"' | cut -d '"' -f 3)
- fi
+ ACME_NEW_NONCE=$(echo "$response" | _egrep_o 'newNonce" *: *"[^"]*"' | cut -d '"' -f 3)
export ACME_NEW_NONCE
- ACME_AGREEMENT=$(echo "$response" | _egrep_o 'terms-of-service" *: *"[^"]*"' | cut -d '"' -f 3)
- if [ -z "$ACME_AGREEMENT" ]; then
- ACME_AGREEMENT=$(echo "$response" | _egrep_o 'termsOfService" *: *"[^"]*"' | cut -d '"' -f 3)
- fi
+ ACME_AGREEMENT=$(echo "$response" | _egrep_o 'termsOfService" *: *"[^"]*"' | cut -d '"' -f 3)
export ACME_AGREEMENT
_debug "ACME_KEY_CHANGE" "$ACME_KEY_CHANGE"
_debug "ACME_REVOKE_CERT" "$ACME_REVOKE_CERT"
_debug "ACME_AGREEMENT" "$ACME_AGREEMENT"
_debug "ACME_NEW_NONCE" "$ACME_NEW_NONCE"
- _debug "ACME_VERSION" "$ACME_VERSION"
-
+ if [ "$ACME_NEW_ACCOUNT" ] && [ "$ACME_NEW_ORDER" ]; then
+ return 0
+ fi
+ _info "Sleep $_sleep_retry_sec and retry."
+ _sleep "$_sleep_retry_sec"
+ done
+ if [ "$ACME_NEW_ACCOUNT" ] && [ "$ACME_NEW_ORDER" ]; then
+ return 0
fi
+ _err "Can not init api, for $_api_server"
+ return 1
}
#[domain] [keylength or isEcc flag]
_ACME_SERVER_HOST="$(echo "$ACME_DIRECTORY" | cut -d : -f 2 | tr -s / | cut -d / -f 2)"
_debug2 "_ACME_SERVER_HOST" "$_ACME_SERVER_HOST"
- CA_DIR="$CA_HOME/$_ACME_SERVER_HOST"
+ _ACME_SERVER_PATH="$(echo "$ACME_DIRECTORY" | cut -d : -f 2- | tr -s / | cut -d / -f 3-)"
+ _debug2 "_ACME_SERVER_PATH" "$_ACME_SERVER_PATH"
+ CA_DIR="$CA_HOME/$_ACME_SERVER_HOST/$_ACME_SERVER_PATH"
_DEFAULT_CA_CONF="$CA_DIR/ca.conf"
-
if [ -z "$CA_CONF" ]; then
CA_CONF="$_DEFAULT_CA_CONF"
fi
_debug3 CA_CONF "$CA_CONF"
+ _OLD_CADIR="$CA_HOME/$_ACME_SERVER_HOST"
+ _OLD_ACCOUNT_KEY="$_OLD_CADIR/account.key"
+ _OLD_ACCOUNT_JSON="$_OLD_CADIR/account.json"
+ _OLD_CA_CONF="$_OLD_CADIR/ca.conf"
+
+ _DEFAULT_ACCOUNT_KEY_PATH="$CA_DIR/account.key"
+ _DEFAULT_ACCOUNT_JSON_PATH="$CA_DIR/account.json"
+ if [ -z "$ACCOUNT_KEY_PATH" ]; then
+ ACCOUNT_KEY_PATH="$_DEFAULT_ACCOUNT_KEY_PATH"
+ if [ -f "$_OLD_ACCOUNT_KEY" ] && ! [ -f "$ACCOUNT_KEY_PATH" ]; then
+ mkdir -p "$CA_DIR"
+ mv "$_OLD_ACCOUNT_KEY" "$ACCOUNT_KEY_PATH"
+ fi
+ fi
+
+ if [ -z "$ACCOUNT_JSON_PATH" ]; then
+ ACCOUNT_JSON_PATH="$_DEFAULT_ACCOUNT_JSON_PATH"
+ if [ -f "$_OLD_ACCOUNT_JSON" ] && ! [ -f "$ACCOUNT_JSON_PATH" ]; then
+ mkdir -p "$CA_DIR"
+ mv "$_OLD_ACCOUNT_JSON" "$ACCOUNT_JSON_PATH"
+ fi
+ fi
+
+ if [ -f "$_OLD_CA_CONF" ] && ! [ -f "$CA_CONF" ]; then
+ mkdir -p "$CA_DIR"
+ mv "$_OLD_CA_CONF" "$CA_CONF"
+ fi
+
if [ -f "$CA_CONF" ]; then
. "$CA_CONF"
fi
HTTP_HEADER="$LE_CONFIG_HOME/http.header"
fi
- _OLD_ACCOUNT_KEY="$LE_WORKING_DIR/account.key"
- _OLD_ACCOUNT_JSON="$LE_WORKING_DIR/account.json"
-
- _DEFAULT_ACCOUNT_KEY_PATH="$CA_DIR/account.key"
- _DEFAULT_ACCOUNT_JSON_PATH="$CA_DIR/account.json"
- if [ -z "$ACCOUNT_KEY_PATH" ]; then
- ACCOUNT_KEY_PATH="$_DEFAULT_ACCOUNT_KEY_PATH"
- fi
-
- if [ -z "$ACCOUNT_JSON_PATH" ]; then
- ACCOUNT_JSON_PATH="$_DEFAULT_ACCOUNT_JSON_PATH"
- fi
-
_DEFAULT_CERT_HOME="$LE_CONFIG_HOME"
if [ -z "$CERT_HOME" ]; then
CERT_HOME="$_DEFAULT_CERT_HOME"
_debug "Try include files"
for included in $(cat "$2" | tr "\t" " " | grep "^ *include *.*;" | sed "s/include //" | tr -d " ;"); do
_debug "check included $included"
- if !_startswith "$included" "/" && _exists dirname; then
+ if ! _startswith "$included" "/" && _exists dirname; then
_relpath="$(dirname "$_c_file")"
_debug "_relpath" "$_relpath"
- included="$_relpath/included"
+ included="$_relpath/$included"
fi
if _checkConf "$1" "$included"; then
return 0
if [ "$_chk_pre_hook" ]; then
_info "Run pre hook:'$_chk_pre_hook'"
if ! (
+ export Le_Domain="$_chk_main_domain"
+ export Le_Alt="$_chk_alt_domains"
cd "$DOMAIN_PATH" && eval "$_chk_pre_hook"
); then
_err "Error when run pre hook."
_netprc="$(_ss "$_checkport" | grep "$_checkport")"
netprc="$(echo "$_netprc" | grep "$_checkaddr")"
if [ -z "$netprc" ]; then
- netprc="$(echo "$_netprc" | grep "$LOCAL_ANY_ADDRESS")"
+ netprc="$(echo "$_netprc" | grep "$LOCAL_ANY_ADDRESS:$_checkport")"
fi
if [ "$netprc" ]; then
_err "$netprc"
_initAPI
mkdir -p "$CA_DIR"
- if [ ! -f "$ACCOUNT_KEY_PATH" ] && [ -f "$_OLD_ACCOUNT_KEY" ]; then
- _info "mv $_OLD_ACCOUNT_KEY to $ACCOUNT_KEY_PATH"
- mv "$_OLD_ACCOUNT_KEY" "$ACCOUNT_KEY_PATH"
- fi
-
- if [ ! -f "$ACCOUNT_JSON_PATH" ] && [ -f "$_OLD_ACCOUNT_JSON" ]; then
- _info "mv $_OLD_ACCOUNT_JSON to $ACCOUNT_JSON_PATH"
- mv "$_OLD_ACCOUNT_JSON" "$ACCOUNT_JSON_PATH"
- fi
if [ ! -f "$ACCOUNT_KEY_PATH" ]; then
if ! _create_account_key "$_reg_length"; then
if [ "$_email" ]; then
_savecaconf "CA_EMAIL" "$_email"
fi
- if [ "$ACME_VERSION" = "2" ]; then
- if [ "$ACME_DIRECTORY" = "$CA_ZEROSSL" ]; then
- if [ -z "$_eab_id" ] || [ -z "$_eab_hmac_key" ]; then
- _info "No EAB credentials found for ZeroSSL, let's get one"
- if [ -z "$_email" ]; then
- _err "Please provide a email address for ZeroSSL account."
- _err "See ZeroSSL usage: $_ZEROSSL_WIKI"
- return 1
- fi
- _eabresp=$(_post "email=$_email" $_ZERO_EAB_ENDPOINT)
- if [ "$?" != "0" ]; then
- _debug2 "$_eabresp"
- _err "Can not get EAB credentials from ZeroSSL."
- return 1
- fi
- _eab_id="$(echo "$_eabresp" | tr ',}' '\n' | grep '"eab_kid"' | cut -d : -f 2 | tr -d '"')"
- if [ -z "$_eab_id" ]; then
- _err "Can not resolve _eab_id"
- return 1
- fi
- _eab_hmac_key="$(echo "$_eabresp" | tr ',}' '\n' | grep '"eab_hmac_key"' | cut -d : -f 2 | tr -d '"')"
- if [ -z "$_eab_hmac_key" ]; then
- _err "Can not resolve _eab_hmac_key"
- return 1
- fi
- _savecaconf CA_EAB_KEY_ID "$_eab_id"
- _savecaconf CA_EAB_HMAC_KEY "$_eab_hmac_key"
+
+ if [ "$ACME_DIRECTORY" = "$CA_ZEROSSL" ]; then
+ if [ -z "$_eab_id" ] || [ -z "$_eab_hmac_key" ]; then
+ _info "No EAB credentials found for ZeroSSL, let's get one"
+ if [ -z "$_email" ]; then
+ _info "$(__green "$PROJECT_NAME is using ZeroSSL as default CA now.")"
+ _info "$(__green "Please update your account with an email address first.")"
+ _info "$(__green "$PROJECT_ENTRY --register-account -m my@example.com")"
+ _info "See: $(__green "$_ZEROSSL_WIKI")"
+ return 1
+ fi
+ _eabresp=$(_post "email=$_email" $_ZERO_EAB_ENDPOINT)
+ if [ "$?" != "0" ]; then
+ _debug2 "$_eabresp"
+ _err "Can not get EAB credentials from ZeroSSL."
+ return 1
+ fi
+ _secure_debug2 _eabresp "$_eabresp"
+ _eab_id="$(echo "$_eabresp" | tr ',}' '\n\n' | grep '"eab_kid"' | cut -d : -f 2 | tr -d '"')"
+ _secure_debug2 _eab_id "$_eab_id"
+ if [ -z "$_eab_id" ]; then
+ _err "Can not resolve _eab_id"
+ return 1
fi
+ _eab_hmac_key="$(echo "$_eabresp" | tr ',}' '\n\n' | grep '"eab_hmac_key"' | cut -d : -f 2 | tr -d '"')"
+ _secure_debug2 _eab_hmac_key "$_eab_hmac_key"
+ if [ -z "$_eab_hmac_key" ]; then
+ _err "Can not resolve _eab_hmac_key"
+ return 1
+ fi
+ _savecaconf CA_EAB_KEY_ID "$_eab_id"
+ _savecaconf CA_EAB_HMAC_KEY "$_eab_hmac_key"
fi
- if [ "$_eab_id" ] && [ "$_eab_hmac_key" ]; then
- eab_protected="{\"alg\":\"HS256\",\"kid\":\"$_eab_id\",\"url\":\"${ACME_NEW_ACCOUNT}\"}"
- _debug3 eab_protected "$eab_protected"
+ fi
+ if [ "$_eab_id" ] && [ "$_eab_hmac_key" ]; then
+ eab_protected="{\"alg\":\"HS256\",\"kid\":\"$_eab_id\",\"url\":\"${ACME_NEW_ACCOUNT}\"}"
+ _debug3 eab_protected "$eab_protected"
- eab_protected64=$(printf "%s" "$eab_protected" | _base64 | _url_replace)
- _debug3 eab_protected64 "$eab_protected64"
+ eab_protected64=$(printf "%s" "$eab_protected" | _base64 | _url_replace)
+ _debug3 eab_protected64 "$eab_protected64"
- eab_payload64=$(printf "%s" "$jwk" | _base64 | _url_replace)
- _debug3 eab_payload64 "$eab_payload64"
+ eab_payload64=$(printf "%s" "$jwk" | _base64 | _url_replace)
+ _debug3 eab_payload64 "$eab_payload64"
- eab_sign_t="$eab_protected64.$eab_payload64"
- _debug3 eab_sign_t "$eab_sign_t"
+ eab_sign_t="$eab_protected64.$eab_payload64"
+ _debug3 eab_sign_t "$eab_sign_t"
- key_hex="$(_durl_replace_base64 "$_eab_hmac_key" | _dbase64 | _hex_dump | tr -d ' ')"
- _debug3 key_hex "$key_hex"
+ key_hex="$(_durl_replace_base64 "$_eab_hmac_key" | _dbase64 multi | _hex_dump | tr -d ' ')"
+ _debug3 key_hex "$key_hex"
- eab_signature=$(printf "%s" "$eab_sign_t" | _hmac sha256 $key_hex | _base64 | _url_replace)
- _debug3 eab_signature "$eab_signature"
+ eab_signature=$(printf "%s" "$eab_sign_t" | _hmac sha256 $key_hex | _base64 | _url_replace)
+ _debug3 eab_signature "$eab_signature"
- externalBinding=",\"externalAccountBinding\":{\"protected\":\"$eab_protected64\", \"payload\":\"$eab_payload64\", \"signature\":\"$eab_signature\"}"
- _debug3 externalBinding "$externalBinding"
- fi
- if [ "$_email" ]; then
- email_sg="\"contact\": [\"mailto:$_email\"], "
- fi
- regjson="{$email_sg\"termsOfServiceAgreed\": true$externalBinding}"
- else
- _reg_res="$ACME_NEW_ACCOUNT_RES"
- regjson='{"resource": "'$_reg_res'", "terms-of-service-agreed": true, "agreement": "'$ACME_AGREEMENT'"}'
- if [ "$_email" ]; then
- regjson='{"resource": "'$_reg_res'", "contact": ["mailto:'$_email'"], "terms-of-service-agreed": true, "agreement": "'$ACME_AGREEMENT'"}'
- fi
+ externalBinding=",\"externalAccountBinding\":{\"protected\":\"$eab_protected64\", \"payload\":\"$eab_payload64\", \"signature\":\"$eab_signature\"}"
+ _debug3 externalBinding "$externalBinding"
+ fi
+ if [ "$_email" ]; then
+ email_sg="\"contact\": [\"mailto:$_email\"], "
fi
+ regjson="{$email_sg\"termsOfServiceAgreed\": true$externalBinding}"
_info "Registering account: $ACME_DIRECTORY"
updateaccount() {
_initpath
- if [ ! -f "$ACCOUNT_KEY_PATH" ] && [ -f "$_OLD_ACCOUNT_KEY" ]; then
- _info "mv $_OLD_ACCOUNT_KEY to $ACCOUNT_KEY_PATH"
- mv "$_OLD_ACCOUNT_KEY" "$ACCOUNT_KEY_PATH"
- fi
-
- if [ ! -f "$ACCOUNT_JSON_PATH" ] && [ -f "$_OLD_ACCOUNT_JSON" ]; then
- _info "mv $_OLD_ACCOUNT_JSON to $ACCOUNT_JSON_PATH"
- mv "$_OLD_ACCOUNT_JSON" "$ACCOUNT_JSON_PATH"
- fi
-
if [ ! -f "$ACCOUNT_KEY_PATH" ]; then
_err "Account key is not found at: $ACCOUNT_KEY_PATH"
return 1
_initAPI
_email="$(_getAccountEmail)"
- if [ "$ACME_VERSION" = "2" ]; then
- if [ "$ACCOUNT_EMAIL" ]; then
- updjson='{"contact": ["mailto:'$_email'"]}'
- else
- updjson='{"contact": []}'
- fi
+
+ if [ "$ACCOUNT_EMAIL" ]; then
+ updjson='{"contact": ["mailto:'$_email'"]}'
else
- # ACMEv1: Updates happen the same way a registration is done.
- # https://tools.ietf.org/html/draft-ietf-acme-acme-01#section-6.3
- _regAccount
- return
+ updjson='{"contact": []}'
fi
- # this part handles ACMEv2 account updates.
_send_signed_request "$_accUri" "$updjson"
if [ "$code" = '200' ]; then
deactivateaccount() {
_initpath
- if [ ! -f "$ACCOUNT_KEY_PATH" ] && [ -f "$_OLD_ACCOUNT_KEY" ]; then
- _info "mv $_OLD_ACCOUNT_KEY to $ACCOUNT_KEY_PATH"
- mv "$_OLD_ACCOUNT_KEY" "$ACCOUNT_KEY_PATH"
- fi
-
- if [ ! -f "$ACCOUNT_JSON_PATH" ] && [ -f "$_OLD_ACCOUNT_JSON" ]; then
- _info "mv $_OLD_ACCOUNT_JSON to $ACCOUNT_JSON_PATH"
- mv "$_OLD_ACCOUNT_JSON" "$ACCOUNT_JSON_PATH"
- fi
-
if [ ! -f "$ACCOUNT_KEY_PATH" ]; then
_err "Account key is not found at: $ACCOUNT_KEY_PATH"
return 1
fi
_initAPI
- if [ "$ACME_VERSION" = "2" ]; then
- _djson="{\"status\":\"deactivated\"}"
- else
- _djson="{\"resource\": \"reg\", \"status\":\"deactivated\"}"
- fi
+ _djson="{\"status\":\"deactivated\"}"
+
if _send_signed_request "$_accUri" "$_djson" && _contains "$response" '"deactivated"'; then
_info "Deactivate account success for $_accUri."
_accid=$(echo "$response" | _egrep_o "\"id\" *: *[^,]*," | cut -d : -f 2 | tr -d ' ,')
_debug2 _t_key_authz "$_t_key_authz"
_t_vtype="$3"
_debug2 _t_vtype "$_t_vtype"
- if [ "$ACME_VERSION" = "2" ]; then
- _send_signed_request "$_t_url" "{}"
- else
- _send_signed_request "$_t_url" "{\"resource\": \"challenge\", \"type\": \"$_t_vtype\", \"keyAuthorization\": \"$_t_key_authz\"}"
- fi
+
+ _send_signed_request "$_t_url" "{}"
+
}
#endpoint domain type
}
_ns_is_available_dp() {
- if _get "https://dns.alidns.com" "" 1 >/dev/null 2>&1; then
+ if _get "https://doh.pub" "" 1 >/dev/null 2>&1; then
return 0
else
return 1
if [ -z "$_ACME_IS_RENEW" ]; then
_initpath "$_main_domain" "$_key_length"
mkdir -p "$DOMAIN_PATH"
+ elif ! _hasfield "$_web_roots" "$W_DNS"; then
+ Le_OrderFinalize=""
+ Le_LinkOrder=""
+ Le_LinkCert=""
fi
if _hasfield "$_web_roots" "$W_DNS" && [ -z "$FORCE_DNS_MANUAL" ]; then
_debug "Using ACME_DIRECTORY: $ACME_DIRECTORY"
- _initAPI
+ if ! _initAPI; then
+ return 1
+ fi
if [ -f "$DOMAIN_CONF" ]; then
Le_NextRenewTime=$(_readdomainconf Le_NextRenewTime)
sep='#'
dvsep=','
if [ -z "$vlist" ]; then
- if [ "$ACME_VERSION" = "2" ]; then
- #make new order request
- _identifiers="{\"type\":\"dns\",\"value\":\"$(_idn "$_main_domain")\"}"
- _w_index=1
- while true; do
- d="$(echo "$_alt_domains," | cut -d , -f "$_w_index")"
- _w_index="$(_math "$_w_index" + 1)"
- _debug d "$d"
- if [ -z "$d" ]; then
- break
- fi
- _identifiers="$_identifiers,{\"type\":\"dns\",\"value\":\"$(_idn "$d")\"}"
- done
- _debug2 _identifiers "$_identifiers"
- if ! _send_signed_request "$ACME_NEW_ORDER" "{\"identifiers\": [$_identifiers]}"; 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)"
- _debug Le_OrderFinalize "$Le_OrderFinalize"
- if [ -z "$Le_OrderFinalize" ]; then
- _err "Create new order error. Le_OrderFinalize not found. $response"
- _clearup
- _on_issue_err "$_post_hook"
- return 1
+ #make new order request
+ _identifiers="{\"type\":\"dns\",\"value\":\"$(_idn "$_main_domain")\"}"
+ _w_index=1
+ while true; do
+ d="$(echo "$_alt_domains," | cut -d , -f "$_w_index")"
+ _w_index="$(_math "$_w_index" + 1)"
+ _debug d "$d"
+ if [ -z "$d" ]; then
+ break
fi
+ _identifiers="$_identifiers,{\"type\":\"dns\",\"value\":\"$(_idn "$d")\"}"
+ done
+ _debug2 _identifiers "$_identifiers"
+ if ! _send_signed_request "$ACME_NEW_ORDER" "{\"identifiers\": [$_identifiers]}"; 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)"
+ _debug Le_OrderFinalize "$Le_OrderFinalize"
+ if [ -z "$Le_OrderFinalize" ]; then
+ _err "Create new order error. Le_OrderFinalize not found. $response"
+ _clearup
+ _on_issue_err "$_post_hook"
+ return 1
+ fi
- #for dns manual mode
- _savedomainconf "Le_OrderFinalize" "$Le_OrderFinalize"
+ #for dns manual mode
+ _savedomainconf "Le_OrderFinalize" "$Le_OrderFinalize"
- _authorizations_seg="$(echo "$response" | _json_decode | _egrep_o '"authorizations" *: *\[[^\[]*\]' | cut -d '[' -f 2 | tr -d ']' | tr -d '"')"
- _debug2 _authorizations_seg "$_authorizations_seg"
- if [ -z "$_authorizations_seg" ]; then
- _err "_authorizations_seg not found."
+ _authorizations_seg="$(echo "$response" | _json_decode | _egrep_o '"authorizations" *: *\[[^\[]*\]' | cut -d '[' -f 2 | tr -d ']' | tr -d '"')"
+ _debug2 _authorizations_seg "$_authorizations_seg"
+ if [ -z "$_authorizations_seg" ]; then
+ _err "_authorizations_seg not found."
+ _clearup
+ _on_issue_err "$_post_hook"
+ return 1
+ fi
+
+ #domain and authz map
+ _authorizations_map=""
+ for _authz_url in $(echo "$_authorizations_seg" | tr ',' ' '); do
+ _debug2 "_authz_url" "$_authz_url"
+ if ! _send_signed_request "$_authz_url"; then
+ _err "get to authz error."
+ _err "_authorizations_seg" "$_authorizations_seg"
+ _err "_authz_url" "$_authz_url"
_clearup
_on_issue_err "$_post_hook"
return 1
fi
- #domain and authz map
- _authorizations_map=""
- for _authz_url in $(echo "$_authorizations_seg" | tr ',' ' '); do
- _debug2 "_authz_url" "$_authz_url"
- if ! _send_signed_request "$_authz_url"; then
- _err "get to authz error."
- _err "_authorizations_seg" "$_authorizations_seg"
- _err "_authz_url" "$_authz_url"
- _clearup
- _on_issue_err "$_post_hook"
- return 1
- fi
-
- response="$(echo "$response" | _normalizeJson)"
- _debug2 response "$response"
- _d="$(echo "$response" | _egrep_o '"value" *: *"[^"]*"' | cut -d : -f 2 | tr -d ' "')"
- if _contains "$response" "\"wildcard\" *: *true"; then
- _d="*.$_d"
- fi
- _debug2 _d "$_d"
- _authorizations_map="$_d,$response
+ response="$(echo "$response" | _normalizeJson)"
+ _debug2 response "$response"
+ _d="$(echo "$response" | _egrep_o '"value" *: *"[^"]*"' | cut -d : -f 2 | tr -d ' "')"
+ if _contains "$response" "\"wildcard\" *: *true"; then
+ _d="*.$_d"
+ fi
+ _debug2 _d "$_d"
+ _authorizations_map="$_d,$response
$_authorizations_map"
- done
- _debug2 _authorizations_map "$_authorizations_map"
- fi
+ done
+ _debug2 _authorizations_map "$_authorizations_map"
_index=0
_currentRoot=""
vtype="$VTYPE_ALPN"
fi
- if [ "$ACME_VERSION" = "2" ]; then
- _idn_d="$(_idn "$d")"
- _candidates="$(echo "$_authorizations_map" | grep -i "^$_idn_d,")"
- _debug2 _candidates "$_candidates"
- if [ "$(echo "$_candidates" | wc -l)" -gt 1 ]; then
- for _can in $_candidates; do
- if _startswith "$(echo "$_can" | tr '.' '|')" "$(echo "$_idn_d" | tr '.' '|'),"; then
- _candidates="$_can"
- break
- fi
- done
- fi
- response="$(echo "$_candidates" | sed "s/$_idn_d,//")"
- _debug2 "response" "$response"
- if [ -z "$response" ]; then
- _err "get to authz error."
- _err "_authorizations_map" "$_authorizations_map"
- _clearup
- _on_issue_err "$_post_hook"
- return 1
- fi
- else
- if ! __get_domain_new_authz "$d"; then
- _clearup
- _on_issue_err "$_post_hook"
- return 1
- fi
+ _idn_d="$(_idn "$d")"
+ _candidates="$(echo "$_authorizations_map" | grep -i "^$_idn_d,")"
+ _debug2 _candidates "$_candidates"
+ if [ "$(echo "$_candidates" | wc -l)" -gt 1 ]; then
+ for _can in $_candidates; do
+ if _startswith "$(echo "$_can" | tr '.' '|')" "$(echo "$_idn_d" | tr '.' '|'),"; then
+ _candidates="$_can"
+ break
+ fi
+ done
+ fi
+ response="$(echo "$_candidates" | sed "s/$_idn_d,//")"
+ _debug2 "response" "$response"
+ if [ -z "$response" ]; then
+ _err "get to authz error."
+ _err "_authorizations_map" "$_authorizations_map"
+ _clearup
+ _on_issue_err "$_post_hook"
+ return 1
fi
if [ -z "$thumbprint" ]; then
_on_issue_err "$_post_hook"
return 1
fi
- if [ "$ACME_VERSION" = "2" ]; then
- uri="$(echo "$entry" | _egrep_o '"url":"[^"]*' | cut -d '"' -f 4 | _head_n 1)"
- else
- uri="$(echo "$entry" | _egrep_o '"uri":"[^"]*' | cut -d '"' -f 4)"
- fi
+
+ uri="$(echo "$entry" | _egrep_o '"url":"[^"]*' | cut -d '"' -f 4 | _head_n 1)"
+
_debug uri "$uri"
if [ -z "$uri" ]; then
return 1
fi
- _debug "sleep 2 secs to verify"
- sleep 2
- _debug "checking"
- if [ "$ACME_VERSION" = "2" ]; then
- _send_signed_request "$uri"
- else
- response="$(_get "$uri")"
- fi
- if [ "$?" != "0" ]; then
- _err "$d:Verify error:$response"
- _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
- _clearup
- _on_issue_err "$_post_hook" "$vlist"
- return 1
- fi
_debug2 original "$response"
response="$(echo "$response" | _normalizeJson)"
_debug2 response "$response"
status=$(echo "$response" | _egrep_o '"status":"[^"]*' | cut -d : -f 2 | tr -d '"')
- if _contains "$status" "valid"; then
- _info "$(__green Success)"
- _stopserver "$serverproc"
- serverproc=""
- _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
- break
- fi
-
- if [ "$status" = "invalid" ]; then
+ _debug2 status "$status"
+ if _contains "$status" "invalid"; then
error="$(echo "$response" | _egrep_o '"error":\{[^\}]*')"
_debug2 error "$error"
errordetail="$(echo "$error" | _egrep_o '"detail": *"[^"]*' | cut -d '"' -f 4)"
return 1
fi
+ if _contains "$status" "valid"; then
+ _info "$(__green Success)"
+ _stopserver "$serverproc"
+ serverproc=""
+ _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
+ break
+ fi
+
if [ "$status" = "pending" ]; then
- _info "Pending"
+ _info "Pending, The CA is processing your order, please just wait. ($waittimes/$MAX_RETRY_TIMES)"
elif [ "$status" = "processing" ]; then
- _info "Processing"
+ _info "Processing, The CA is processing your order, please just wait. ($waittimes/$MAX_RETRY_TIMES)"
else
_err "$d:Verify error:$response"
_clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_on_issue_err "$_post_hook" "$vlist"
return 1
fi
+ _debug "sleep 2 secs to verify again"
+ sleep 2
+ _debug "checking"
+
+ _send_signed_request "$uri"
+ if [ "$?" != "0" ]; then
+ _err "$d:Verify error:$response"
+ _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
+ _clearup
+ _on_issue_err "$_post_hook" "$vlist"
+ return 1
+ fi
done
done
_info "Verify finished, start to sign."
der="$(_getfile "${CSR_PATH}" "${BEGIN_CSR}" "${END_CSR}" | tr -d "\r\n" | _url_replace)"
- if [ "$ACME_VERSION" = "2" ]; then
- _info "Lets finalize the order."
- _info "Le_OrderFinalize" "$Le_OrderFinalize"
- if ! _send_signed_request "${Le_OrderFinalize}" "{\"csr\": \"$der\"}"; then
- _err "Sign failed."
- _on_issue_err "$_post_hook"
- return 1
- fi
- if [ "$code" != "200" ]; then
- _err "Sign failed, finalize code is not 200."
- _err "$response"
- _on_issue_err "$_post_hook"
- return 1
- fi
- if [ -z "$Le_LinkOrder" ]; then
- Le_LinkOrder="$(echo "$responseHeaders" | grep -i '^Location.*$' | _tail_n 1 | tr -d "\r\n \t" | cut -d ":" -f 2-)"
- fi
+ _info "Lets finalize the order."
+ _info "Le_OrderFinalize" "$Le_OrderFinalize"
+ if ! _send_signed_request "${Le_OrderFinalize}" "{\"csr\": \"$der\"}"; then
+ _err "Sign failed."
+ _on_issue_err "$_post_hook"
+ return 1
+ fi
+ if [ "$code" != "200" ]; then
+ _err "Sign failed, finalize code is not 200."
+ _err "$response"
+ _on_issue_err "$_post_hook"
+ return 1
+ fi
+ if [ -z "$Le_LinkOrder" ]; then
+ Le_LinkOrder="$(echo "$responseHeaders" | grep -i '^Location.*$' | _tail_n 1 | tr -d "\r\n \t" | cut -d ":" -f 2-)"
+ fi
- _savedomainconf "Le_LinkOrder" "$Le_LinkOrder"
+ _savedomainconf "Le_LinkOrder" "$Le_LinkOrder"
- _link_cert_retry=0
- _MAX_CERT_RETRY=30
- while [ "$_link_cert_retry" -lt "$_MAX_CERT_RETRY" ]; do
- if _contains "$response" "\"status\":\"valid\""; then
- _debug "Order status is valid."
- Le_LinkCert="$(echo "$response" | _egrep_o '"certificate" *: *"[^"]*"' | cut -d '"' -f 4)"
- _debug Le_LinkCert "$Le_LinkCert"
- if [ -z "$Le_LinkCert" ]; then
- _err "Sign error, can not find Le_LinkCert"
- _err "$response"
- _on_issue_err "$_post_hook"
- return 1
- fi
- break
- elif _contains "$response" "\"processing\""; then
- _info "Order status is processing, lets sleep and retry."
- _retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *:" | cut -d : -f 2 | tr -d ' ' | tr -d '\r')
- _debug "_retryafter" "$_retryafter"
- if [ "$_retryafter" ]; then
- _info "Retry after: $_retryafter"
- _sleep $_retryafter
- else
- _sleep 2
- fi
- else
- _err "Sign error, wrong status"
+ _link_cert_retry=0
+ _MAX_CERT_RETRY=30
+ while [ "$_link_cert_retry" -lt "$_MAX_CERT_RETRY" ]; do
+ if _contains "$response" "\"status\":\"valid\""; then
+ _debug "Order status is valid."
+ Le_LinkCert="$(echo "$response" | _egrep_o '"certificate" *: *"[^"]*"' | cut -d '"' -f 4)"
+ _debug Le_LinkCert "$Le_LinkCert"
+ if [ -z "$Le_LinkCert" ]; then
+ _err "Sign error, can not find Le_LinkCert"
_err "$response"
_on_issue_err "$_post_hook"
return 1
fi
- #the order is processing, so we are going to poll order status
- if [ -z "$Le_LinkOrder" ]; then
- _err "Sign error, can not get order link location header"
- _err "responseHeaders" "$responseHeaders"
- _on_issue_err "$_post_hook"
- return 1
- fi
- _info "Polling order status: $Le_LinkOrder"
- if ! _send_signed_request "$Le_LinkOrder"; then
- _err "Sign failed, can not post to Le_LinkOrder cert:$Le_LinkOrder."
- _err "$response"
- _on_issue_err "$_post_hook"
- return 1
+ break
+ elif _contains "$response" "\"processing\""; then
+ _info "Order status is processing, lets sleep and retry."
+ _retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *:" | cut -d : -f 2 | tr -d ' ' | tr -d '\r')
+ _debug "_retryafter" "$_retryafter"
+ if [ "$_retryafter" ]; then
+ _info "Retry after: $_retryafter"
+ _sleep $_retryafter
+ else
+ _sleep 2
fi
- _link_cert_retry="$(_math $_link_cert_retry + 1)"
- done
-
- if [ -z "$Le_LinkCert" ]; then
- _err "Sign failed, can not get Le_LinkCert, retry time limit."
+ else
+ _err "Sign error, wrong status"
_err "$response"
_on_issue_err "$_post_hook"
return 1
fi
- _info "Downloading cert."
- _info "Le_LinkCert" "$Le_LinkCert"
- if ! _send_signed_request "$Le_LinkCert"; then
- _err "Sign failed, can not download cert:$Le_LinkCert."
+ #the order is processing, so we are going to poll order status
+ if [ -z "$Le_LinkOrder" ]; then
+ _err "Sign error, can not get order link location header"
+ _err "responseHeaders" "$responseHeaders"
+ _on_issue_err "$_post_hook"
+ return 1
+ fi
+ _info "Polling order status: $Le_LinkOrder"
+ if ! _send_signed_request "$Le_LinkOrder"; then
+ _err "Sign failed, can not post to Le_LinkOrder cert:$Le_LinkOrder."
_err "$response"
_on_issue_err "$_post_hook"
return 1
fi
+ _link_cert_retry="$(_math $_link_cert_retry + 1)"
+ done
- echo "$response" >"$CERT_PATH"
- _split_cert_chain "$CERT_PATH" "$CERT_FULLCHAIN_PATH" "$CA_CERT_PATH"
+ if [ -z "$Le_LinkCert" ]; then
+ _err "Sign failed, can not get Le_LinkCert, retry time limit."
+ _err "$response"
+ _on_issue_err "$_post_hook"
+ return 1
+ fi
+ _info "Downloading cert."
+ _info "Le_LinkCert" "$Le_LinkCert"
+ if ! _send_signed_request "$Le_LinkCert"; then
+ _err "Sign failed, can not download cert:$Le_LinkCert."
+ _err "$response"
+ _on_issue_err "$_post_hook"
+ return 1
+ fi
- if [ "$_preferred_chain" ] && [ -f "$CERT_FULLCHAIN_PATH" ]; then
- if [ "$DEBUG" ]; then
- _debug "default chain issuers: " "$(_get_chain_issuers "$CERT_FULLCHAIN_PATH")"
- fi
- if ! _match_issuer "$CERT_FULLCHAIN_PATH" "$_preferred_chain"; then
- rels="$(echo "$responseHeaders" | tr -d ' <>' | grep -i "^link:" | grep -i 'rel="alternate"' | cut -d : -f 2- | cut -d ';' -f 1)"
- _debug2 "rels" "$rels"
- for rel in $rels; do
- _info "Try rel: $rel"
- if ! _send_signed_request "$rel"; then
- _err "Sign failed, can not download cert:$rel"
- _err "$response"
- continue
- fi
- _relcert="$CERT_PATH.alt"
- _relfullchain="$CERT_FULLCHAIN_PATH.alt"
- _relca="$CA_CERT_PATH.alt"
- echo "$response" >"$_relcert"
- _split_cert_chain "$_relcert" "$_relfullchain" "$_relca"
- if [ "$DEBUG" ]; then
- _debug "rel chain issuers: " "$(_get_chain_issuers "$_relfullchain")"
- fi
- if _match_issuer "$_relfullchain" "$_preferred_chain"; then
- _info "Matched issuer in: $rel"
- cat $_relcert >"$CERT_PATH"
- cat $_relfullchain >"$CERT_FULLCHAIN_PATH"
- cat $_relca >"$CA_CERT_PATH"
- rm -f "$_relcert"
- rm -f "$_relfullchain"
- rm -f "$_relca"
- break
- fi
+ echo "$response" >"$CERT_PATH"
+ _split_cert_chain "$CERT_PATH" "$CERT_FULLCHAIN_PATH" "$CA_CERT_PATH"
+
+ if [ "$_preferred_chain" ] && [ -f "$CERT_FULLCHAIN_PATH" ]; then
+ if [ "$DEBUG" ]; then
+ _debug "default chain issuers: " "$(_get_chain_issuers "$CERT_FULLCHAIN_PATH")"
+ fi
+ if ! _match_issuer "$CERT_FULLCHAIN_PATH" "$_preferred_chain"; then
+ rels="$(echo "$responseHeaders" | tr -d ' <>' | grep -i "^link:" | grep -i 'rel="alternate"' | cut -d : -f 2- | cut -d ';' -f 1)"
+ _debug2 "rels" "$rels"
+ for rel in $rels; do
+ _info "Try rel: $rel"
+ if ! _send_signed_request "$rel"; then
+ _err "Sign failed, can not download cert:$rel"
+ _err "$response"
+ continue
+ fi
+ _relcert="$CERT_PATH.alt"
+ _relfullchain="$CERT_FULLCHAIN_PATH.alt"
+ _relca="$CA_CERT_PATH.alt"
+ echo "$response" >"$_relcert"
+ _split_cert_chain "$_relcert" "$_relfullchain" "$_relca"
+ if [ "$DEBUG" ]; then
+ _debug "rel chain issuers: " "$(_get_chain_issuers "$_relfullchain")"
+ fi
+ if _match_issuer "$_relfullchain" "$_preferred_chain"; then
+ _info "Matched issuer in: $rel"
+ cat $_relcert >"$CERT_PATH"
+ cat $_relfullchain >"$CERT_FULLCHAIN_PATH"
+ cat $_relca >"$CA_CERT_PATH"
rm -f "$_relcert"
rm -f "$_relfullchain"
rm -f "$_relca"
- done
- fi
- fi
- else
- if ! _send_signed_request "${ACME_NEW_ORDER}" "{\"resource\": \"$ACME_NEW_ORDER_RES\", \"csr\": \"$der\"}" "needbase64"; then
- _err "Sign failed. $response"
- _on_issue_err "$_post_hook"
- return 1
- fi
- _rcert="$response"
- Le_LinkCert="$(grep -i '^Location.*$' "$HTTP_HEADER" | _tail_n 1 | tr -d "\r\n" | cut -d " " -f 2)"
- echo "$BEGIN_CERT" >"$CERT_PATH"
-
- #if ! _get "$Le_LinkCert" | _base64 "multiline" >> "$CERT_PATH" ; then
- # _debug "Get cert failed. Let's try last response."
- # printf -- "%s" "$_rcert" | _dbase64 "multiline" | _base64 "multiline" >> "$CERT_PATH"
- #fi
-
- if ! printf -- "%s" "$_rcert" | _dbase64 "multiline" | _base64 "multiline" >>"$CERT_PATH"; then
- _debug "Try cert link."
- _get "$Le_LinkCert" | _base64 "multiline" >>"$CERT_PATH"
+ break
+ fi
+ rm -f "$_relcert"
+ rm -f "$_relfullchain"
+ rm -f "$_relca"
+ done
fi
-
- echo "$END_CERT" >>"$CERT_PATH"
fi
_debug "Le_LinkCert" "$Le_LinkCert"
_info "$(__green "Cert success.")"
cat "$CERT_PATH"
- _info "Your cert is in $(__green " $CERT_PATH ")"
+ _info "Your cert is in: $(__green "$CERT_PATH")"
if [ -f "$CERT_KEY_PATH" ]; then
- _info "Your cert key is in $(__green " $CERT_KEY_PATH ")"
+ _info "Your cert key is in: $(__green "$CERT_KEY_PATH")"
fi
if [ ! "$USER_PATH" ] || [ ! "$_ACME_IN_CRON" ]; then
fi
fi
- if [ "$ACME_VERSION" = "2" ]; then
- _debug "v2 chain."
- else
- cp "$CERT_PATH" "$CERT_FULLCHAIN_PATH"
- Le_LinkIssuer=$(grep -i '^Link' "$HTTP_HEADER" | _head_n 1 | cut -d " " -f 2 | cut -d ';' -f 1 | tr -d '<>')
-
- if [ "$Le_LinkIssuer" ]; then
- if ! _contains "$Le_LinkIssuer" ":"; then
- _info "$(__red "Relative issuer link found.")"
- Le_LinkIssuer="$_ACME_SERVER_HOST$Le_LinkIssuer"
- fi
- _debug Le_LinkIssuer "$Le_LinkIssuer"
- _savedomainconf "Le_LinkIssuer" "$Le_LinkIssuer"
-
- _link_issuer_retry=0
- _MAX_ISSUER_RETRY=5
- while [ "$_link_issuer_retry" -lt "$_MAX_ISSUER_RETRY" ]; do
- _debug _link_issuer_retry "$_link_issuer_retry"
- if [ "$ACME_VERSION" = "2" ]; then
- if _send_signed_request "$Le_LinkIssuer"; then
- echo "$response" >"$CA_CERT_PATH"
- break
- fi
- else
- if _get "$Le_LinkIssuer" >"$CA_CERT_PATH.der"; then
- echo "$BEGIN_CERT" >"$CA_CERT_PATH"
- _base64 "multiline" <"$CA_CERT_PATH.der" >>"$CA_CERT_PATH"
- echo "$END_CERT" >>"$CA_CERT_PATH"
- if ! _checkcert "$CA_CERT_PATH"; then
- _err "Can not get the ca cert."
- break
- fi
- cat "$CA_CERT_PATH" >>"$CERT_FULLCHAIN_PATH"
- rm -f "$CA_CERT_PATH.der"
- break
- fi
- fi
- _link_issuer_retry=$(_math $_link_issuer_retry + 1)
- _sleep "$_link_issuer_retry"
- done
- if [ "$_link_issuer_retry" = "$_MAX_ISSUER_RETRY" ]; then
- _err "Max retry for issuer ca cert is reached."
- fi
- else
- _debug "No Le_LinkIssuer header found."
- fi
- fi
- [ -f "$CA_CERT_PATH" ] && _info "The intermediate CA cert is in $(__green " $CA_CERT_PATH ")"
- [ -f "$CERT_FULLCHAIN_PATH" ] && _info "And the full chain certs is there: $(__green " $CERT_FULLCHAIN_PATH ")"
+ [ -f "$CA_CERT_PATH" ] && _info "The intermediate CA cert is in: $(__green "$CA_CERT_PATH")"
+ [ -f "$CERT_FULLCHAIN_PATH" ] && _info "And the full chain certs is there: $(__green "$CERT_FULLCHAIN_PATH")"
Le_CertCreateTime=$(_time)
_savedomainconf "Le_CertCreateTime" "$Le_CertCreateTime"
. "$DOMAIN_CONF"
_debug Le_API "$Le_API"
-
- if [ "$Le_API" = "$LETSENCRYPT_CA_V1" ]; then
- _cleardomainconf Le_API
- Le_API="$DEFAULT_CA"
- fi
- if [ "$Le_API" = "$LETSENCRYPT_STAGING_CA_V1" ]; then
- _cleardomainconf Le_API
- Le_API="$DEFAULT_STAGING_CA"
+ 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
if [ "$Le_API" ]; then
+ if [ "$Le_API" != "$ACME_DIRECTORY" ]; then
+ _clearAPI
+ fi
export ACME_DIRECTORY="$Le_API"
#reload ca configs
ACCOUNT_KEY_PATH=""
CA_CONF=""
_debug3 "initpath again."
_initpath "$Le_Domain" "$_isEcc"
+ _initAPI
fi
if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(_time)" -lt "$Le_NextRenewTime" ]; then
return 1
fi
- if [ -z "$ACME_VERSION" ] && _contains "$_csrsubj,$_csrdomainlist" "*."; then
- export ACME_VERSION=2
- fi
_initpath "$_csrsubj" "$_csrkeylength"
mkdir -p "$DOMAIN_PATH"
mkdir -p "$_backup_path"
if [ "$_real_cert" ]; then
- _info "Installing cert to:$_real_cert"
+ _info "Installing cert to: $_real_cert"
if [ -f "$_real_cert" ] && [ ! "$_ACME_IS_RENEW" ]; then
cp "$_real_cert" "$_backup_path/cert.bak"
fi
fi
if [ "$_real_ca" ]; then
- _info "Installing CA to:$_real_ca"
+ _info "Installing CA to: $_real_ca"
if [ "$_real_ca" = "$_real_cert" ]; then
echo "" >>"$_real_ca"
cat "$CA_CERT_PATH" >>"$_real_ca" || return 1
fi
if [ "$_real_key" ]; then
- _info "Installing key to:$_real_key"
+ _info "Installing key to: $_real_key"
if [ -f "$_real_key" ] && [ ! "$_ACME_IS_RENEW" ]; then
cp "$_real_key" "$_backup_path/key.bak"
fi
fi
if [ "$_real_fullchain" ]; then
- _info "Installing full chain to:$_real_fullchain"
+ _info "Installing full chain to: $_real_fullchain"
if [ -f "$_real_fullchain" ] && [ ! "$_ACME_IS_RENEW" ]; then
cp "$_real_fullchain" "$_backup_path/fullchain.bak"
fi
_info "Removing cron job"
cr="$($_CRONTAB -l | grep "$PROJECT_ENTRY --cron")"
if [ "$cr" ]; then
- if _exists uname && uname -a | grep solaris >/dev/null; then
+ if _exists uname && uname -a | grep SunOS >/dev/null; then
$_CRONTAB -l | sed "/$PROJECT_ENTRY --cron/d" | $_CRONTAB --
else
$_CRONTAB -l | sed "/$PROJECT_ENTRY --cron/d" | $_CRONTAB -
return 1
fi
+ . "$DOMAIN_CONF"
+ _debug Le_API "$Le_API"
+
+ 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"
+ _initAPI
+ fi
+
cert="$(_getfile "${CERT_PATH}" "${BEGIN_CERT}" "${END_CERT}" | tr -d "\r\n" | _url_replace)"
if [ -z "$cert" ]; then
_initAPI
- if [ "$ACME_VERSION" = "2" ]; then
- data="{\"certificate\": \"$cert\",\"reason\":$_reason}"
- else
- data="{\"resource\": \"revoke-cert\", \"certificate\": \"$cert\"}"
- fi
+ data="{\"certificate\": \"$cert\",\"reason\":$_reason}"
+
uri="${ACME_REVOKE_CERT}"
if [ -f "$CERT_KEY_PATH" ]; then
_deactivate() {
_d_domain="$1"
_d_type="$2"
- _initpath
+ _initpath "$_d_domain" "$_d_type"
- if [ "$ACME_VERSION" = "2" ]; then
- _identifiers="{\"type\":\"dns\",\"value\":\"$_d_domain\"}"
- if ! _send_signed_request "$ACME_NEW_ORDER" "{\"identifiers\": [$_identifiers]}"; then
- _err "Can not get domain new order."
- return 1
- fi
- _authorizations_seg="$(echo "$response" | _egrep_o '"authorizations" *: *\[[^\]*\]' | cut -d '[' -f 2 | tr -d ']' | tr -d '"')"
- _debug2 _authorizations_seg "$_authorizations_seg"
- if [ -z "$_authorizations_seg" ]; then
- _err "_authorizations_seg not found."
- _clearup
- _on_issue_err "$_post_hook"
- return 1
- fi
+ . "$DOMAIN_CONF"
+ _debug Le_API "$Le_API"
- authzUri="$_authorizations_seg"
- _debug2 "authzUri" "$authzUri"
- if ! _send_signed_request "$authzUri"; then
- _err "get to authz error."
- _err "_authorizations_seg" "$_authorizations_seg"
- _err "authzUri" "$authzUri"
- _clearup
- _on_issue_err "$_post_hook"
- return 1
+ 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" "$_d_type"
+ _initAPI
+ fi
- response="$(echo "$response" | _normalizeJson)"
- _debug2 response "$response"
- _URL_NAME="url"
- else
- if ! __get_domain_new_authz "$_d_domain"; then
- _err "Can not get domain new authz token."
- return 1
- fi
+ _identifiers="{\"type\":\"dns\",\"value\":\"$_d_domain\"}"
+ if ! _send_signed_request "$ACME_NEW_ORDER" "{\"identifiers\": [$_identifiers]}"; then
+ _err "Can not get domain new order."
+ return 1
+ fi
+ _authorizations_seg="$(echo "$response" | _egrep_o '"authorizations" *: *\[[^\]*\]' | cut -d '[' -f 2 | tr -d ']' | tr -d '"')"
+ _debug2 _authorizations_seg "$_authorizations_seg"
+ if [ -z "$_authorizations_seg" ]; then
+ _err "_authorizations_seg not found."
+ _clearup
+ _on_issue_err "$_post_hook"
+ return 1
+ fi
- authzUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ':' -f 2- | tr -d "\r\n")"
- _debug "authzUri" "$authzUri"
- if [ "$code" ] && [ ! "$code" = '201' ]; then
- _err "new-authz error: $response"
- return 1
- fi
- _URL_NAME="uri"
+ authzUri="$_authorizations_seg"
+ _debug2 "authzUri" "$authzUri"
+ if ! _send_signed_request "$authzUri"; then
+ _err "get to authz error."
+ _err "_authorizations_seg" "$_authorizations_seg"
+ _err "authzUri" "$authzUri"
+ _clearup
+ _on_issue_err "$_post_hook"
+ return 1
fi
- entries="$(echo "$response" | tr '][' '==' | _egrep_o "challenges\": *=[^=]*=" | tr '}{' '\n' | grep "\"status\": *\"valid\"")"
+ response="$(echo "$response" | _normalizeJson)"
+ _debug2 response "$response"
+ _URL_NAME="url"
+
+ entries="$(echo "$response" | tr '][' '==' | _egrep_o "challenges\": *=[^=]*=" | tr '}{' '\n\n' | grep "\"status\": *\"valid\"")"
if [ -z "$entries" ]; then
_info "No valid entries found."
if [ -z "$thumbprint" ]; then
_info "Deactivate: $_vtype"
- if [ "$ACME_VERSION" = "2" ]; then
- _djson="{\"status\":\"deactivated\"}"
- else
- _djson="{\"resource\": \"authz\", \"status\":\"deactivated\"}"
- fi
+ _djson="{\"status\":\"deactivated\"}"
if _send_signed_request "$authzUri" "$_djson" && _contains "$response" '"deactivated"'; then
_info "Deactivate: $_vtype success."
_hash_path=$1
shift
_hash_url="https://api.github.com/repos/acmesh-official/$PROJECT_NAME/git/refs/$_hash_path"
- _get $_hash_url | tr -d "\r\n" | tr '{},' '\n' | grep '"sha":' | cut -d '"' -f 4
+ _get $_hash_url | tr -d "\r\n" | tr '{},' '\n\n\n' | grep '"sha":' | cut -d '"' -f 4
}
_getUpgradeHash() {
return 0
}
-#server
+#server #keylength
_selectServer() {
_server="$1"
+ _skeylength="$2"
_server_lower="$(echo "$_server" | _lower_case)"
_sindex=0
for snames in $CA_NAMES; do
if [ "$_server_lower" = "$sname" ]; then
_debug2 "_selectServer match $sname"
_serverdir="$(_getfield "$CA_SERVERS" $_sindex)"
+ if [ "$_serverdir" = "$CA_SSLCOM_RSA" ] && _isEccKey "$_skeylength"; then
+ _serverdir="$CA_SSLCOM_ECC"
+ fi
_debug "Selected server: $_serverdir"
ACME_DIRECTORY="$_serverdir"
export ACME_DIRECTORY
if [ -z "$caurl" ]; then
caurl="$DEFAULT_CA"
fi
+ if [ "$CA_SSLCOM_ECC" = "$caurl" ]; then
+ caurl="$CA_SSLCOM_RSA" #just hack to get the short name
+ fi
caurl_lower="$(echo $caurl | _lower_case)"
_sindex=0
for surl in $(echo "$CA_SERVERS" | _lower_case | tr , ' '); do
return 1
fi
- if _startswith "$_dvalue" "*."; then
- _debug "Wildcard domain"
- export ACME_VERSION=2
- fi
if [ -z "$_domain" ]; then
_domain="$_dvalue"
else
;;
--server)
_server="$2"
- _selectServer "$_server"
shift
;;
--debug)
Le_DNSSleep="$_dnssleep"
shift
;;
-
--keylength | -k)
_keylength="$2"
shift
_accountkeylength="$2"
shift
;;
-
--cert-file | --certpath)
_cert_file="$2"
shift
shift 1
done
+ if [ "$_server" ]; then
+ _selectServer "$_server" "${_ecc:-$_keylength}"
+ fi
+
if [ "${_CMD}" != "install" ]; then
if [ "$__INTERACTIVE" ] && ! _checkSudo; then
if [ -z "$FORCE" ]; then