@ -1,6 +1,6 @@
#!/usr/bin/env sh
#!/usr/bin/env sh
VER = 2.9.0
VER = 3.0.1
PROJECT_NAME = "acme.sh"
PROJECT_NAME = "acme.sh"
@ -20,6 +20,8 @@ _SUB_FOLDER_DEPLOY="deploy"
_SUB_FOLDERS = " $_SUB_FOLDER_DNSAPI $_SUB_FOLDER_DEPLOY $_SUB_FOLDER_NOTIFY "
_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 = "https://acme-v02.api.letsencrypt.org/directory"
CA_LETSENCRYPT_V2_TEST = "https://acme-staging-v02.api.letsencrypt.org/directory"
CA_LETSENCRYPT_V2_TEST = "https://acme-staging-v02.api.letsencrypt.org/directory"
@ -29,18 +31,22 @@ CA_BUYPASS_TEST="https://api.test4.buypass.no/acme/directory"
CA_ZEROSSL = "https://acme.zerossl.com/v2/DV90"
CA_ZEROSSL = "https://acme.zerossl.com/v2/DV90"
_ZERO_EAB_ENDPOINT = "http://api.zerossl.com/acme/eab-credentials-email"
_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
DEFAULT_STAGING_CA = $CA_LETSENCRYPT_V2_TEST
CA_NAMES = "
CA_NAMES = "
ZeroSSL.com,zerossl
LetsEncrypt.org,letsencrypt
LetsEncrypt.org,letsencrypt
LetsEncrypt.org_test,letsencrypt_test,letsencrypttest
LetsEncrypt.org_test,letsencrypt_test,letsencrypttest
BuyPass.com,buypass
BuyPass.com,buypass
BuyPass.com_test,buypass_test,buypasstest
BuyPass.com_test,buypass_test,buypasstest
Zero SSL.com,zero ssl
SSL.com,sslcom
"
"
CA_SERVERS = " $CA_LETSENCRYPT_V2 , $CA_LETSENCRYPT_V2_TEST , $CA_BUYPASS , $CA_BUYPASS_TEST , $CA_ZERO SSL "
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 ) "
DEFAULT_USER_AGENT = " $PROJECT_NAME / $VER ( $PROJECT ) "
@ -155,6 +161,8 @@ _REVOKE_WIKI="https://github.com/acmesh-official/acme.sh/wiki/revokecert"
_ZEROSSL_WIKI = "https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA"
_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"
_SERVER_WIKI = "https://github.com/acmesh-official/acme.sh/wiki/Server"
_PREFERRED_CHAIN_WIKI = "https://github.com/acmesh-official/acme.sh/wiki/Preferred-Chain"
_PREFERRED_CHAIN_WIKI = "https://github.com/acmesh-official/acme.sh/wiki/Preferred-Chain"
@ -1210,7 +1218,7 @@ _createcsr() {
_debug2 csr " $csr "
_debug2 csr " $csr "
_debug2 csrconf " $csrconf "
_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
if [ " $acmeValidationv1 " ] ; then
domainlist = " $( _idn " $domainlist " ) "
domainlist = " $( _idn " $domainlist " ) "
@ -1762,7 +1770,7 @@ _inithttp() {
if [ -z " $ACME_HTTP_NO_REDIRECTS " ] ; then
if [ -z " $ACME_HTTP_NO_REDIRECTS " ] ; then
_ACME_CURL = " $_ACME_CURL -L "
_ACME_CURL = " $_ACME_CURL -L "
fi
fi
if [ " $DEBUG " ] && [ " $DEBUG " -ge "2" ] ; then
if [ " $DEBUG " ] && [ " $DEBUG " -ge 2 ] ; then
_CURL_DUMP = " $( _mktemp) "
_CURL_DUMP = " $( _mktemp) "
_ACME_CURL = " $_ACME_CURL --trace-ascii $_CURL_DUMP "
_ACME_CURL = " $_ACME_CURL --trace-ascii $_CURL_DUMP "
fi
fi
@ -1802,6 +1810,8 @@ _inithttp() {
}
}
_HTTP_MAX_RETRY = 8
# body url [needbase64] [POST|PUT|DELETE] [ContentType]
# body url [needbase64] [POST|PUT|DELETE] [ContentType]
_post( ) {
_post( ) {
body = " $1 "
body = " $1 "
@ -1809,6 +1819,33 @@ _post() {
needbase64 = " $3 "
needbase64 = " $3 "
httpmethod = " $4 "
httpmethod = " $4 "
_postContentType = " $5 "
_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
if [ -z " $httpmethod " ] ; then
httpmethod = "POST"
httpmethod = "POST"
@ -1860,7 +1897,9 @@ _post() {
fi
fi
_ret = " $? "
_ret = " $? "
if [ " $_ret " != "0" ] ; then
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
if [ " $DEBUG " ] && [ " $DEBUG " -ge "2" ] ; then
_err "Here is the curl dump log:"
_err "Here is the curl dump log:"
_err " $( cat " $_CURL_DUMP " ) "
_err " $( cat " $_CURL_DUMP " ) "
@ -1916,7 +1955,9 @@ _post() {
_debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later."
_debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later."
fi
fi
if [ " $_ret " != "0" ] ; then
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
fi
_sed_i "s/^ *//g" " $HTTP_HEADER "
_sed_i "s/^ *//g" " $HTTP_HEADER "
else
else
@ -1930,13 +1971,38 @@ _post() {
# url getheader timeout
# url getheader timeout
_get( ) {
_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
_debug GET
url = " $1 "
url = " $1 "
onlyheader = " $2 "
onlyheader = " $2 "
t = " $3 "
t = " $3 "
displayError = " $4 "
_debug url " $url "
_debug url " $url "
_debug " timeout= $t "
_debug " timeout= $t "
_debug "displayError" " $displayError "
_inithttp
_inithttp
if [ " $_ACME_CURL " ] && [ " ${ ACME_USE_WGET :- 0 } " = "0" ] ; then
if [ " $_ACME_CURL " ] && [ " ${ ACME_USE_WGET :- 0 } " = "0" ] ; then
@ -1955,7 +2021,9 @@ _get() {
fi
fi
ret = $?
ret = $?
if [ " $ret " != "0" ] ; then
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
if [ " $DEBUG " ] && [ " $DEBUG " -ge "2" ] ; then
_err "Here is the curl dump log:"
_err "Here is the curl dump log:"
_err " $( cat " $_CURL_DUMP " ) "
_err " $( cat " $_CURL_DUMP " ) "
@ -1981,7 +2049,9 @@ _get() {
_debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later."
_debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later."
fi
fi
if [ " $ret " != "0" ] ; then
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
fi
else
else
ret = $?
ret = $?
@ -2529,17 +2599,33 @@ __initHome() {
fi
fi
}
}
_clearAPI( ) {
ACME_NEW_ACCOUNT = ""
ACME_KEY_CHANGE = ""
ACME_NEW_AUTHZ = ""
ACME_NEW_ORDER = ""
ACME_REVOKE_CERT = ""
ACME_NEW_NONCE = ""
ACME_AGREEMENT = ""
}
#server
#server
_initAPI( ) {
_initAPI( ) {
_api_server = " ${ 1 :- $ACME_DIRECTORY } "
_api_server = " ${ 1 :- $ACME_DIRECTORY } "
_debug " _init api for server: $_api_server "
_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 " )
response = $( _get " $_api_server " )
if [ " $? " != "0" ] ; then
if [ " $? " != "0" ] ; then
_debug2 "response" " $response "
_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
fi
response = $( echo " $response " | _json_decode)
response = $( echo " $response " | _json_decode)
_debug2 "response" " $response "
_debug2 "response" " $response "
@ -2572,8 +2658,17 @@ _initAPI() {
_debug "ACME_REVOKE_CERT" " $ACME_REVOKE_CERT "
_debug "ACME_REVOKE_CERT" " $ACME_REVOKE_CERT "
_debug "ACME_AGREEMENT" " $ACME_AGREEMENT "
_debug "ACME_AGREEMENT" " $ACME_AGREEMENT "
_debug "ACME_NEW_NONCE" " $ACME_NEW_NONCE "
_debug "ACME_NEW_NONCE" " $ACME_NEW_NONCE "
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
fi
_err " Can not init api, for $_api_server "
return 1
}
}
#[domain] [keylength or isEcc flag]
#[domain] [keylength or isEcc flag]
@ -2617,15 +2712,44 @@ _initpath() {
_ACME_SERVER_HOST = " $( echo " $ACME_DIRECTORY " | cut -d : -f 2 | tr -s / | cut -d / -f 2) "
_ACME_SERVER_HOST = " $( echo " $ACME_DIRECTORY " | cut -d : -f 2 | tr -s / | cut -d / -f 2) "
_debug2 "_ACME_SERVER_HOST" " $_ACME_SERVER_HOST "
_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 "
_DEFAULT_CA_CONF = " $CA_DIR /ca.conf "
if [ -z " $CA_CONF " ] ; then
if [ -z " $CA_CONF " ] ; then
CA_CONF = " $_DEFAULT_CA_CONF "
CA_CONF = " $_DEFAULT_CA_CONF "
fi
fi
_debug3 CA_CONF " $CA_CONF "
_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
if [ -f " $CA_CONF " ] ; then
. " $CA_CONF "
. " $CA_CONF "
fi
fi
@ -2646,19 +2770,6 @@ _initpath() {
HTTP_HEADER = " $LE_CONFIG_HOME /http.header "
HTTP_HEADER = " $LE_CONFIG_HOME /http.header "
fi
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 "
_DEFAULT_CERT_HOME = " $LE_CONFIG_HOME "
if [ -z " $CERT_HOME " ] ; then
if [ -z " $CERT_HOME " ] ; then
CERT_HOME = " $_DEFAULT_CERT_HOME "
CERT_HOME = " $_DEFAULT_CERT_HOME "
@ -3056,10 +3167,10 @@ _checkConf() {
_debug "Try include files"
_debug "Try include files"
for included in $( cat " $2 " | tr "\t" " " | grep "^ *include *.*;" | sed "s/include //" | tr -d " ;" ) ; do
for included in $( cat " $2 " | tr "\t" " " | grep "^ *include *.*;" | sed "s/include //" | tr -d " ;" ) ; do
_debug " check included $included "
_debug " check included $included "
if !_startswith " $included " "/" && _exists dirname; then
if ! _startswith " $included " "/" && _exists dirname; then
_relpath = " $( dirname " $_c_file " ) "
_relpath = " $( dirname " $_c_file " ) "
_debug "_relpath" " $_relpath "
_debug "_relpath" " $_relpath "
included = " $_relpath /included "
included = " $_relpath / $ included"
fi
fi
if _checkConf " $1 " " $included " ; then
if _checkConf " $1 " " $included " ; then
return 0
return 0
@ -3271,6 +3382,8 @@ _on_before_issue() {
if [ " $_chk_pre_hook " ] ; then
if [ " $_chk_pre_hook " ] ; then
_info " Run pre hook:' $_chk_pre_hook ' "
_info " Run pre hook:' $_chk_pre_hook ' "
if ! (
if ! (
export Le_Domain = " $_chk_main_domain "
export Le_Alt = " $_chk_alt_domains "
cd " $DOMAIN_PATH " && eval " $_chk_pre_hook "
cd " $DOMAIN_PATH " && eval " $_chk_pre_hook "
) ; then
) ; then
_err "Error when run pre hook."
_err "Error when run pre hook."
@ -3332,7 +3445,7 @@ _on_before_issue() {
_netprc = " $( _ss " $_checkport " | grep " $_checkport " ) "
_netprc = " $( _ss " $_checkport " | grep " $_checkport " ) "
netprc = " $( echo " $_netprc " | grep " $_checkaddr " ) "
netprc = " $( echo " $_netprc " | grep " $_checkaddr " ) "
if [ -z " $netprc " ] ; then
if [ -z " $netprc " ] ; then
netprc = " $( echo " $_netprc " | grep " $LOCAL_ANY_ADDRESS " ) "
netprc = " $( echo " $_netprc " | grep " $LOCAL_ANY_ADDRESS : $_checkport ") "
fi
fi
if [ " $netprc " ] ; then
if [ " $netprc " ] ; then
_err " $netprc "
_err " $netprc "
@ -3489,15 +3602,6 @@ _regAccount() {
_initAPI
_initAPI
mkdir -p " $CA_DIR "
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 [ ! -f " $ACCOUNT_KEY_PATH " ] ; then
if ! _create_account_key " $_reg_length " ; then
if ! _create_account_key " $_reg_length " ; then
@ -3526,8 +3630,10 @@ _regAccount() {
if [ -z " $_eab_id " ] || [ -z " $_eab_hmac_key " ] ; then
if [ -z " $_eab_id " ] || [ -z " $_eab_hmac_key " ] ; then
_info "No EAB credentials found for ZeroSSL, let's get one"
_info "No EAB credentials found for ZeroSSL, let's get one"
if [ -z " $_email " ] ; then
if [ -z " $_email " ] ; then
_err "Please provide a email address for ZeroSSL account."
_err " See ZeroSSL usage: $_ZEROSSL_WIKI "
_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
return 1
fi
fi
_eabresp = $( _post " email= $_email " $_ZERO_EAB_ENDPOINT )
_eabresp = $( _post " email= $_email " $_ZERO_EAB_ENDPOINT )
@ -3536,13 +3642,15 @@ _regAccount() {
_err "Can not get EAB credentials from ZeroSSL."
_err "Can not get EAB credentials from ZeroSSL."
return 1
return 1
fi
fi
_debug2 " $_eabresp "
_eab_id = " $( echo " $_eabresp " | tr ',}' '\n' | grep '"eab_kid"' | cut -d : -f 2 | tr -d '"' ) "
_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
if [ -z " $_eab_id " ] ; then
_err "Can not resolve _eab_id"
_err "Can not resolve _eab_id"
return 1
return 1
fi
fi
_eab_hmac_key = " $( echo " $_eabresp " | tr ',}' '\n' | grep '"eab_hmac_key"' | cut -d : -f 2 | tr -d '"' ) "
_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
if [ -z " $_eab_hmac_key " ] ; then
_err "Can not resolve _eab_hmac_key"
_err "Can not resolve _eab_hmac_key"
return 1
return 1
@ -3564,7 +3672,7 @@ _regAccount() {
eab_sign_t = " $eab_protected64 . $eab_payload64 "
eab_sign_t = " $eab_protected64 . $eab_payload64 "
_debug3 eab_sign_t " $eab_sign_t "
_debug3 eab_sign_t " $eab_sign_t "
key_hex = " $( _durl_replace_base64 " $_eab_hmac_key " | _dbase64 | _hex_dump | tr -d ' ' ) "
key_hex = " $( _durl_replace_base64 " $_eab_hmac_key " | _dbase64 multi | _hex_dump | tr -d ' ' ) "
_debug3 key_hex " $key_hex "
_debug3 key_hex " $key_hex "
eab_signature = $( printf "%s" " $eab_sign_t " | _hmac sha256 $key_hex | _base64 | _url_replace)
eab_signature = $( printf "%s" " $eab_sign_t " | _hmac sha256 $key_hex | _base64 | _url_replace)
@ -3631,16 +3739,6 @@ _regAccount() {
updateaccount( ) {
updateaccount( ) {
_initpath
_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
if [ ! -f " $ACCOUNT_KEY_PATH " ] ; then
_err " Account key is not found at: $ACCOUNT_KEY_PATH "
_err " Account key is not found at: $ACCOUNT_KEY_PATH "
return 1
return 1
@ -3683,16 +3781,6 @@ updateaccount() {
deactivateaccount( ) {
deactivateaccount( ) {
_initpath
_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
if [ ! -f " $ACCOUNT_KEY_PATH " ] ; then
_err " Account key is not found at: $ACCOUNT_KEY_PATH "
_err " Account key is not found at: $ACCOUNT_KEY_PATH "
return 1
return 1
@ -3903,7 +3991,7 @@ _ns_lookup_ali() {
}
}
_ns_is_available_dp( ) {
_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
return 0
else
else
return 1
return 1
@ -4123,6 +4211,10 @@ issue() {
if [ -z " $_ACME_IS_RENEW " ] ; then
if [ -z " $_ACME_IS_RENEW " ] ; then
_initpath " $_main_domain " " $_key_length "
_initpath " $_main_domain " " $_key_length "
mkdir -p " $DOMAIN_PATH "
mkdir -p " $DOMAIN_PATH "
elif ! _hasfield " $_web_roots " " $W_DNS " ; then
Le_OrderFinalize = ""
Le_LinkOrder = ""
Le_LinkCert = ""
fi
fi
if _hasfield " $_web_roots " " $W_DNS " && [ -z " $FORCE_DNS_MANUAL " ] ; then
if _hasfield " $_web_roots " " $W_DNS " && [ -z " $FORCE_DNS_MANUAL " ] ; then
@ -4132,7 +4224,9 @@ issue() {
_debug " Using ACME_DIRECTORY: $ACME_DIRECTORY "
_debug " Using ACME_DIRECTORY: $ACME_DIRECTORY "
_initAPI
if ! _initAPI; then
return 1
fi
if [ -f " $DOMAIN_CONF " ] ; then
if [ -f " $DOMAIN_CONF " ] ; then
Le_NextRenewTime = $( _readdomainconf Le_NextRenewTime)
Le_NextRenewTime = $( _readdomainconf Le_NextRenewTime)
@ -4688,26 +4782,13 @@ $_authorizations_map"
return 1
return 1
fi
fi
_debug "sleep 2 secs to verify"
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
_debug2 original " $response "
_debug2 original " $response "
response = " $( echo " $response " | _normalizeJson) "
response = " $( echo " $response " | _normalizeJson) "
_debug2 response " $response "
_debug2 response " $response "
status = $( echo " $response " | _egrep_o '"status":"[^"]*' | cut -d : -f 2 | tr -d '"' )
status = $( echo " $response " | _egrep_o '"status":"[^"]*' | cut -d : -f 2 | tr -d '"' )
_debug2 status " $status "
if _contains " $status " "invalid" ; then
if _contains " $status " "invalid" ; then
error = " $( echo " $response " | _egrep_o '"error":\{[^\}]*' ) "
error = " $( echo " $response " | _egrep_o '"error":\{[^\}]*' ) "
_debug2 error " $error "
_debug2 error " $error "
@ -4739,9 +4820,9 @@ $_authorizations_map"
fi
fi
if [ " $status " = "pending" ] ; then
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
elif [ " $status " = "processing" ] ; then
_info "Processing"
_info " Processing, The CA is processing your order, please just wait. ( $waittimes / $MAX_RETRY_TIMES ) "
else
else
_err " $d :Verify error: $response "
_err " $d :Verify error: $response "
_clearupwebbroot " $_currentRoot " " $removelevel " " $token "
_clearupwebbroot " $_currentRoot " " $removelevel " " $token "
@ -4749,7 +4830,19 @@ $_authorizations_map"
_on_issue_err " $_post_hook " " $vlist "
_on_issue_err " $_post_hook " " $vlist "
return 1
return 1
fi
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
done
done
@ -4895,10 +4988,10 @@ $_authorizations_map"
_info " $( __green "Cert success." ) "
_info " $( __green "Cert success." ) "
cat " $CERT_PATH "
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
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
fi
if [ ! " $USER_PATH " ] || [ ! " $_ACME_IN_CRON " ] ; then
if [ ! " $USER_PATH " ] || [ ! " $_ACME_IN_CRON " ] ; then
@ -4907,8 +5000,8 @@ $_authorizations_map"
fi
fi
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)
Le_CertCreateTime = $( _time)
_savedomainconf "Le_CertCreateTime" " $Le_CertCreateTime "
_savedomainconf "Le_CertCreateTime" " $Le_CertCreateTime "
@ -5019,8 +5112,16 @@ renew() {
. " $DOMAIN_CONF "
. " $DOMAIN_CONF "
_debug Le_API " $Le_API "
_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
if [ " $Le_API " ] ; then
if [ " $Le_API " ] ; then
if [ " $Le_API " != " $ACME_DIRECTORY " ] ; then
_clearAPI
fi
export ACME_DIRECTORY = " $Le_API "
export ACME_DIRECTORY = " $Le_API "
#reload ca configs
#reload ca configs
ACCOUNT_KEY_PATH = ""
ACCOUNT_KEY_PATH = ""
@ -5028,6 +5129,7 @@ renew() {
CA_CONF = ""
CA_CONF = ""
_debug3 "initpath again."
_debug3 "initpath again."
_initpath " $Le_Domain " " $_isEcc "
_initpath " $Le_Domain " " $_isEcc "
_initAPI
fi
fi
if [ -z " $FORCE " ] && [ " $Le_NextRenewTime " ] && [ " $( _time) " -lt " $Le_NextRenewTime " ] ; then
if [ -z " $FORCE " ] && [ " $Le_NextRenewTime " ] && [ " $( _time) " -lt " $Le_NextRenewTime " ] ; then
@ -5443,7 +5545,7 @@ _installcert() {
mkdir -p " $_backup_path "
mkdir -p " $_backup_path "
if [ " $_real_cert " ] ; then
if [ " $_real_cert " ] ; then
_info " Installing cert to: $_real_cert "
_info " Installing cert to: $_real_cert "
if [ -f " $_real_cert " ] && [ ! " $_ACME_IS_RENEW " ] ; then
if [ -f " $_real_cert " ] && [ ! " $_ACME_IS_RENEW " ] ; then
cp " $_real_cert " " $_backup_path /cert.bak "
cp " $_real_cert " " $_backup_path /cert.bak "
fi
fi
@ -5451,7 +5553,7 @@ _installcert() {
fi
fi
if [ " $_real_ca " ] ; then
if [ " $_real_ca " ] ; then
_info " Installing CA to: $_real_ca "
_info " Installing CA to: $_real_ca "
if [ " $_real_ca " = " $_real_cert " ] ; then
if [ " $_real_ca " = " $_real_cert " ] ; then
echo "" >>" $_real_ca "
echo "" >>" $_real_ca "
cat " $CA_CERT_PATH " >>" $_real_ca " || return 1
cat " $CA_CERT_PATH " >>" $_real_ca " || return 1
@ -5464,7 +5566,7 @@ _installcert() {
fi
fi
if [ " $_real_key " ] ; then
if [ " $_real_key " ] ; then
_info " Installing key to: $_real_key "
_info " Installing key to: $_real_key "
if [ -f " $_real_key " ] && [ ! " $_ACME_IS_RENEW " ] ; then
if [ -f " $_real_key " ] && [ ! " $_ACME_IS_RENEW " ] ; then
cp " $_real_key " " $_backup_path /key.bak "
cp " $_real_key " " $_backup_path /key.bak "
fi
fi
@ -5477,7 +5579,7 @@ _installcert() {
fi
fi
if [ " $_real_fullchain " ] ; then
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
if [ -f " $_real_fullchain " ] && [ ! " $_ACME_IS_RENEW " ] ; then
cp " $_real_fullchain " " $_backup_path /fullchain.bak "
cp " $_real_fullchain " " $_backup_path /fullchain.bak "
fi
fi
@ -5645,7 +5747,7 @@ uninstallcronjob() {
_info "Removing cron job"
_info "Removing cron job"
cr = " $( $_CRONTAB -l | grep " $PROJECT_ENTRY --cron " ) "
cr = " $( $_CRONTAB -l | grep " $PROJECT_ENTRY --cron " ) "
if [ " $cr " ] ; then
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 --
$_CRONTAB -l | sed " / $PROJECT_ENTRY --cron/d " | $_CRONTAB --
else
else
$_CRONTAB -l | sed " / $PROJECT_ENTRY --cron/d " | $_CRONTAB -
$_CRONTAB -l | sed " / $PROJECT_ENTRY --cron/d " | $_CRONTAB -
@ -5685,6 +5787,23 @@ revoke() {
return 1
return 1
fi
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) "
cert = " $( _getfile " ${ CERT_PATH } " " ${ BEGIN_CERT } " " ${ END_CERT } " | tr -d "\r\n" | _url_replace) "
if [ -z " $cert " ] ; then
if [ -z " $cert " ] ; then
@ -5764,7 +5883,24 @@ remove() {
_deactivate( ) {
_deactivate( ) {
_d_domain = " $1 "
_d_domain = " $1 "
_d_type = " $2 "
_d_type = " $2 "
_initpath
_initpath " $_d_domain " " $_d_type "
. " $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 " " $_d_type "
_initAPI
fi
_identifiers = " {\"type\":\"dns\",\"value\":\" $_d_domain \"} "
_identifiers = " {\"type\":\"dns\",\"value\":\" $_d_domain \"} "
if ! _send_signed_request " $ACME_NEW_ORDER " " {\"identifiers\": [ $_identifiers ]} " ; then
if ! _send_signed_request " $ACME_NEW_ORDER " " {\"identifiers\": [ $_identifiers ]} " ; then
@ -5795,7 +5931,7 @@ _deactivate() {
_debug2 response " $response "
_debug2 response " $response "
_URL_NAME = "url"
_URL_NAME = "url"
entries = " $( echo " $response " | tr '][' '==' | _egrep_o "challenges\": *=[^=]*=" | tr '}{' '\n' | grep "\"status\": *\"valid\"" ) "
entries = " $( echo " $response " | tr '][' '==' | _egrep_o "challenges\": *=[^=]*=" | tr '}{' '\n\n ' | grep "\"status\": *\"valid\"" ) "
if [ -z " $entries " ] ; then
if [ -z " $entries " ] ; then
_info "No valid entries found."
_info "No valid entries found."
if [ -z " $thumbprint " ] ; then
if [ -z " $thumbprint " ] ; then
@ -6559,7 +6695,7 @@ _getRepoHash() {
_hash_path = $1
_hash_path = $1
shift
shift
_hash_url = " https://api.github.com/repos/acmesh-official/ $PROJECT_NAME /git/refs/ $_hash_path "
_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( ) {
_getUpgradeHash( ) {
@ -6632,9 +6768,10 @@ _checkSudo() {
return 0
return 0
}
}
#server
#server #keylength
_selectServer( ) {
_selectServer( ) {
_server = " $1 "
_server = " $1 "
_skeylength = " $2 "
_server_lower = " $( echo " $_server " | _lower_case) "
_server_lower = " $( echo " $_server " | _lower_case) "
_sindex = 0
_sindex = 0
for snames in $CA_NAMES ; do
for snames in $CA_NAMES ; do
@ -6645,6 +6782,9 @@ _selectServer() {
if [ " $_server_lower " = " $sname " ] ; then
if [ " $_server_lower " = " $sname " ] ; then
_debug2 " _selectServer match $sname "
_debug2 " _selectServer match $sname "
_serverdir = " $( _getfield " $CA_SERVERS " $_sindex ) "
_serverdir = " $( _getfield " $CA_SERVERS " $_sindex ) "
if [ " $_serverdir " = " $CA_SSLCOM_RSA " ] && _isEccKey " $_skeylength " ; then
_serverdir = " $CA_SSLCOM_ECC "
fi
_debug " Selected server: $_serverdir "
_debug " Selected server: $_serverdir "
ACME_DIRECTORY = " $_serverdir "
ACME_DIRECTORY = " $_serverdir "
export ACME_DIRECTORY
export ACME_DIRECTORY
@ -6662,6 +6802,9 @@ _getCAShortName() {
if [ -z " $caurl " ] ; then
if [ -z " $caurl " ] ; then
caurl = " $DEFAULT_CA "
caurl = " $DEFAULT_CA "
fi
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) "
caurl_lower = " $( echo $caurl | _lower_case) "
_sindex = 0
_sindex = 0
for surl in $( echo " $CA_SERVERS " | _lower_case | tr , ' ' ) ; do
for surl in $( echo " $CA_SERVERS " | _lower_case | tr , ' ' ) ; do
@ -6876,7 +7019,6 @@ _process() {
; ;
; ;
--server)
--server)
_server = " $2 "
_server = " $2 "
_selectServer " $_server "
shift
shift
; ;
; ;
--debug)
--debug)
@ -6975,7 +7117,6 @@ _process() {
Le_DNSSleep = " $_dnssleep "
Le_DNSSleep = " $_dnssleep "
shift
shift
; ;
; ;
--keylength | -k)
--keylength | -k)
_keylength = " $2 "
_keylength = " $2 "
shift
shift
@ -6984,7 +7125,6 @@ _process() {
_accountkeylength = " $2 "
_accountkeylength = " $2 "
shift
shift
; ;
; ;
--cert-file | --certpath)
--cert-file | --certpath)
_cert_file = " $2 "
_cert_file = " $2 "
shift
shift
@ -7248,6 +7388,10 @@ _process() {
shift 1
shift 1
done
done
if [ " $_server " ] ; then
_selectServer " $_server " " ${ _ecc :- $_keylength } "
fi
if [ " ${ _CMD } " != "install" ] ; then
if [ " ${ _CMD } " != "install" ] ; then
if [ " $__INTERACTIVE " ] && ! _checkSudo; then
if [ " $__INTERACTIVE " ] && ! _checkSudo; then
if [ -z " $FORCE " ] ; then
if [ -z " $FORCE " ] ; then