From 03e1c408852c50ac2ee3bc0986ce09485a02403f Mon Sep 17 00:00:00 2001 From: Bernard Spil Date: Sun, 6 Dec 2020 16:44:57 +0100 Subject: [PATCH 001/304] Make domain names available to pre hook --- acme.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/acme.sh b/acme.sh index dcbe3c9d..bb7966dd 100755 --- a/acme.sh +++ b/acme.sh @@ -3279,6 +3279,8 @@ _on_before_issue() { 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." From 57417a33494016c2385fa944d3ae1b08c4060c6b Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 7 Dec 2020 21:31:02 +0800 Subject: [PATCH 002/304] start 2.8.9 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index bb7966dd..959a6fde 100755 --- a/acme.sh +++ b/acme.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -VER=2.8.8 +VER=2.8.9 PROJECT_NAME="acme.sh" From 2af70ecb5cb69dac95cfc80813e6607192b7f444 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 7 Dec 2020 21:41:08 +0800 Subject: [PATCH 003/304] fix --- deploy/mailcow.sh | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/deploy/mailcow.sh b/deploy/mailcow.sh index 830bec04..babd5d28 100644 --- a/deploy/mailcow.sh +++ b/deploy/mailcow.sh @@ -27,11 +27,11 @@ mailcow_deploy() { return 1 fi - #Tests if _ssl_path is the mailcow root directory. + #Tests if _ssl_path is the mailcow root directory. if [ -f "${_mailcow_path}/generate_config.sh" ]; then _ssl_path="${_mailcow_path}/data/assets/ssl/" else - _ssl_path="${_mailcow_path}" + _ssl_path="${_mailcow_path}" fi if [ ! -d "$_ssl_path" ]; then @@ -41,17 +41,16 @@ mailcow_deploy() { # ECC or RSA if [ -z "${Le_Keylength}" ]; then - Le_Keylength="" + Le_Keylength="" fi if _isEccKey "${Le_Keylength}"; then - _info "ECC key type detected" - _cert_type="ecdsa" - _cert_name_prefix="ecdsa-" + _info "ECC key type detected" + _cert_type="ecdsa" + _cert_name_prefix="ecdsa-" else - _info "RSA key type detected" - _cert_type="rsa" - _cert_name_prefix="" - + _info "RSA key type detected" + _cert_type="rsa" + _cert_name_prefix="" fi _info "Copying key and cert" _real_key="$_ssl_path/${_cert_name_prefix}key.pem" From ec792b278ae37c8930c7c7f7707899c603360ebf Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 7 Dec 2020 21:42:31 +0800 Subject: [PATCH 004/304] fix --- deploy/mailcow.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/deploy/mailcow.sh b/deploy/mailcow.sh index babd5d28..932956c0 100644 --- a/deploy/mailcow.sh +++ b/deploy/mailcow.sh @@ -49,7 +49,6 @@ mailcow_deploy() { _cert_name_prefix="ecdsa-" else _info "RSA key type detected" - _cert_type="rsa" _cert_name_prefix="" fi _info "Copying key and cert" From adc6ee4621de9e4f87bf2fccf610314882eb114a Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 7 Dec 2020 22:01:30 +0800 Subject: [PATCH 005/304] fix --- deploy/mailcow.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/deploy/mailcow.sh b/deploy/mailcow.sh index 932956c0..c3535e7e 100644 --- a/deploy/mailcow.sh +++ b/deploy/mailcow.sh @@ -45,7 +45,6 @@ mailcow_deploy() { fi if _isEccKey "${Le_Keylength}"; then _info "ECC key type detected" - _cert_type="ecdsa" _cert_name_prefix="ecdsa-" else _info "RSA key type detected" From 054f4fa09954a772c275a90a97df0d9f645316bf Mon Sep 17 00:00:00 2001 From: Nate Date: Sun, 6 Dec 2020 22:45:42 +0700 Subject: [PATCH 006/304] Correct sed regex Corrects issue #3285. The '?' character after a group is not supported in POSIX Basic Regular Expressions. Replacing it with '\{0,1\}' retains the same functionality and also works on non-GNU systems. --- dnsapi/dns_duckdns.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index f0af2741..41685147 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -96,7 +96,7 @@ dns_duckdns_rm() { _duckdns_get_domain() { # We'll extract the domain/username from full domain - _duckdns_domain="$(printf "%s" "$fulldomain" | _lower_case | _egrep_o '^(_acme-challenge\.)?[a-z0-9-]*\.duckdns\.org' | sed 's/^\(_acme-challenge\.\)\?\([a-z0-9-]*\)\.duckdns\.org/\2/')" + _duckdns_domain="$(printf "%s" "$fulldomain" | _lower_case | _egrep_o '^(_acme-challenge\.)?[a-z0-9-]*\.duckdns\.org' | sed 's/^\(_acme-challenge\.\)\{0,1\}\([a-z0-9-]*\)\.duckdns\.org/\2/')" if [ -z "$_duckdns_domain" ]; then _err "Error extracting the domain." From cbf4069856d5d55a3c80b424e470f01e1a1d17a0 Mon Sep 17 00:00:00 2001 From: neil Date: Thu, 10 Dec 2020 20:21:57 +0800 Subject: [PATCH 007/304] fix https://github.com/acmesh-official/acme.sh/issues/3300 --- deploy/docker.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/deploy/docker.sh b/deploy/docker.sh index 451d5d00..3aa1b2cd 100755 --- a/deploy/docker.sh +++ b/deploy/docker.sh @@ -275,6 +275,7 @@ _check_curl_version() { if [ "$_major$_minor" -lt "740" ]; then _err "curl v$_cversion doesn't support unit socket" + _err "Please upgrade to curl 7.40 or later." return 1 fi if [ "$_major$_minor" -lt "750" ]; then From cb84ad90bc9bb8e4b669da681b29aef3022f1971 Mon Sep 17 00:00:00 2001 From: Van Hau TRAN Date: Sun, 6 Dec 2020 22:59:36 +0100 Subject: [PATCH 008/304] feat: add scaleway provider --- dnsapi/dns_scaleway.sh | 162 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100755 dnsapi/dns_scaleway.sh diff --git a/dnsapi/dns_scaleway.sh b/dnsapi/dns_scaleway.sh new file mode 100755 index 00000000..20397096 --- /dev/null +++ b/dnsapi/dns_scaleway.sh @@ -0,0 +1,162 @@ +#!/usr/bin/env sh + +# Scaleway API +# https://developers.scaleway.com/en/products/domain/dns/api/ +# +# Requires Scaleway API token set in SCALEWAY_API_TOKEN + +######## Public functions ##################### + +SCALEWAY_API="https://api.scaleway.com/domain/v2beta1" + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_scaleway_add() { + fulldomain=$1 + txtvalue=$2 + + if ! _scaleway_check_config; then + return 1 + fi + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _info "Adding record" + _scaleway_create_TXT_record "$_domain" "$_sub_domain" "$txtvalue" + _info "Record added." + + return 0 +} + +dns_scaleway_rm() { + fulldomain=$1 + txtvalue=$2 + + if ! _scaleway_check_config; then + return 1 + fi + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _info "Deleting record" + _scaleway_create_TXT_record "$_domain" "$_sub_domain" "$txtvalue" + _info "Record deleted." + + return 0 +} + +#################### Private functions below ################################## + +_scaleway_check_config() { + SCALEWAY_API_TOKEN="${SCALEWAY_API_TOKEN:-$(_readaccountconf_mutable SCALEWAY_API_TOKEN)}" + if [ -z "$SCALEWAY_API_TOKEN" ]; then + _err "No API key specified for Scaleway API." + _err "Create your key and export it as SCALEWAY_API_TOKEN" + return 1 + fi + if ! _scaleway_rest GET "dns-zones"; then + _err "Invalid API key specified for Scaleway API." + return 1 + fi + + _saveaccountconf_mutable SCALEWAY_API_TOKEN "$SCALEWAY_API_TOKEN" + + return 0 +} + +#_acme-challenge.www.domain.com +#returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +_get_root() { + domain=$1 + i=2 + p=1 + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + if [ -z "$h" ]; then + #not valid + return 1 + fi + + _scaleway_rest GET "dns-zones/$h/records" + + if ! _contains "$response" "subdomain not found" >/dev/null; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain="$h" + return 0 + fi + p=$i + i=$(_math "$i" + 1) + done + _err "Unable to retrive DNS zone matching this domain" + return 1 +} + +_scaleway_create_TXT_record() { + txt_zone=$1 + txt_name=$2 + txt_value=$3 + + _scaleway_rest PATCH "dns-zones/$txt_zone/records" "{\"return_all_records\":false,\"changes\":[{\"add\":{\"records\":[{\"name\":\"$txt_name\",\"data\":\"$txt_value\",\"type\":\"TXT\",\"ttl\":60}]}}]}" + + if [ _contains "$response" "records"; then + return 0 + else + _err "error1 $response" + return 1 + fi +} + +_scaleway_delete_TXT_record() { + txt_zone=$1 + txt_name=$2 + txt_value=$3 + + _scaleway_rest PATCH "dns-zones/$txt_zone/records" "{\"return_all_records\":false,\"changes\":[{\"delete\":{\"id_fields\":{\"name\":\"$txt_name\",\"data\":\"$txt_value\",\"type\":\"TXT\"}}}]}" + + if [ _contains "$response" "records"; then + return 0 + else + _err "error2 $response" + return 1 + fi +} + +_scaleway_rest() { + m=$1 + ep="$2" + data="$3" + _debug "$ep" + _scaleway_url="$SCALEWAY_API/$ep" + _debug2 _scaleway_url "$_scaleway_url" + export _H1="x-auth-token: $SCALEWAY_API_TOKEN" + export _H2="Accept: application/json" + export _H3="Content-Type: application/json" + + if [ "$data" ] || [ "$m" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$_scaleway_url" "" "$m")" + else + response="$(_get "$_scaleway_url")" + fi + if [ "$?" != "0" ] || _contains "$response" "denied_authentication" || _contains "$response" "Method not allowed" || _contains "$response" "json parse error: unexpected EOF"; then + _err "error $response" + return 1 + fi + _debug2 response "$response" + return 0 +} From debb4d292243ef1a3c399c1c0402068d92b90f5e Mon Sep 17 00:00:00 2001 From: Van Hau TRAN Date: Sun, 6 Dec 2020 23:14:25 +0100 Subject: [PATCH 009/304] feat: add comment and configure workflow ci test --- dnsapi/dns_scaleway.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dnsapi/dns_scaleway.sh b/dnsapi/dns_scaleway.sh index 20397096..abca5125 100755 --- a/dnsapi/dns_scaleway.sh +++ b/dnsapi/dns_scaleway.sh @@ -106,6 +106,7 @@ _get_root() { return 1 } +# this function add a TXT record _scaleway_create_TXT_record() { txt_zone=$1 txt_name=$2 @@ -121,6 +122,7 @@ _scaleway_create_TXT_record() { fi } +# this function delete a TXT record based on name and content _scaleway_delete_TXT_record() { txt_zone=$1 txt_name=$2 From 3b6f4c92600b2865ffe82fba3738056d5c7d9231 Mon Sep 17 00:00:00 2001 From: Van Hau TRAN Date: Sun, 6 Dec 2020 23:20:41 +0100 Subject: [PATCH 010/304] fix: shell if --- dnsapi/dns_scaleway.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_scaleway.sh b/dnsapi/dns_scaleway.sh index abca5125..778738f4 100755 --- a/dnsapi/dns_scaleway.sh +++ b/dnsapi/dns_scaleway.sh @@ -114,7 +114,7 @@ _scaleway_create_TXT_record() { _scaleway_rest PATCH "dns-zones/$txt_zone/records" "{\"return_all_records\":false,\"changes\":[{\"add\":{\"records\":[{\"name\":\"$txt_name\",\"data\":\"$txt_value\",\"type\":\"TXT\",\"ttl\":60}]}}]}" - if [ _contains "$response" "records"; then + if _contains "$response" "records"; then return 0 else _err "error1 $response" @@ -130,7 +130,7 @@ _scaleway_delete_TXT_record() { _scaleway_rest PATCH "dns-zones/$txt_zone/records" "{\"return_all_records\":false,\"changes\":[{\"delete\":{\"id_fields\":{\"name\":\"$txt_name\",\"data\":\"$txt_value\",\"type\":\"TXT\"}}}]}" - if [ _contains "$response" "records"; then + if _contains "$response" "records"; then return 0 else _err "error2 $response" From 47ac086d5b40c131a3d9f54ffeebe56e85f75d15 Mon Sep 17 00:00:00 2001 From: Van Hau TRAN Date: Tue, 8 Dec 2020 16:32:31 +0100 Subject: [PATCH 011/304] fix: fix delete txt record and error mngtt --- dnsapi/dns_scaleway.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_scaleway.sh b/dnsapi/dns_scaleway.sh index 778738f4..a0a0f318 100755 --- a/dnsapi/dns_scaleway.sh +++ b/dnsapi/dns_scaleway.sh @@ -29,6 +29,12 @@ dns_scaleway_add() { _info "Adding record" _scaleway_create_TXT_record "$_domain" "$_sub_domain" "$txtvalue" + if _contains "$response" "records"; then + return 0 + else + _err error "$response" + return 1 + fi _info "Record added." return 0 @@ -52,7 +58,13 @@ dns_scaleway_rm() { _debug _domain "$_domain" _info "Deleting record" - _scaleway_create_TXT_record "$_domain" "$_sub_domain" "$txtvalue" + _scaleway_delete_TXT_record "$_domain" "$_sub_domain" "$txtvalue" + if _contains "$response" "records"; then + return 0 + else + _err error "$response" + return 1 + fi _info "Record deleted." return 0 @@ -83,7 +95,7 @@ _scaleway_check_config() { # _domain=domain.com _get_root() { domain=$1 - i=2 + i=1 p=1 while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) From 877f768e01061def8f8ae3763d9b02bb784e250c Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sat, 26 Sep 2020 19:38:18 -0600 Subject: [PATCH 012/304] Use POST for login This allows us to get the cookie and the token (as it appears to be only in the body in DSM 7.) HTTP_HEADERS is only guarenteed to be output with POST for both wget and curl. --- deploy/synology_dsm.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 2ec0ceb3..53ab5dd9 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -22,7 +22,7 @@ ######## Public functions ##################### _syno_get_cookie_data() { - grep -i "\W$1=" | grep -i "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';' + grep -i "\W$1=" "$HTTP_HEADER" | grep -i "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';' } #domain keyfile certfile cafile fullchain @@ -78,8 +78,8 @@ synology_dsm_deploy() { encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)" encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)" encoded_did="$(printf "%s" "$SYNO_DID" | _url_encode)" - response=$(_get "$_base_url/webman/login.cgi?username=$encoded_username&passwd=$encoded_password&enable_syno_token=yes&device_id=$encoded_did" 1) - token=$(echo "$response" | grep -i "X-SYNO-TOKEN:" | sed -n 's/^X-SYNO-TOKEN: \(.*\)$/\1/pI' | tr -d "\r\n") + response=$(_post "username=$encoded_username&passwd=$encoded_password&device_id=$encoded_did" "$_base_url/webman/login.cgi?enable_syno_token=yes") + token=$(echo "$response" | grep "SynoToken" | sed -n 's/.*"SynoToken" *: *"\([^"]*\).*/\1/p') _debug3 response "$response" _debug token "$token" @@ -89,7 +89,7 @@ synology_dsm_deploy() { return 1 fi - _H1="Cookie: $(echo "$response" | _syno_get_cookie_data "id"); $(echo "$response" | _syno_get_cookie_data "smid")" + _H1="Cookie: $(_syno_get_cookie_data "id"); $(_syno_get_cookie_data "smid")" _H2="X-SYNO-TOKEN: $token" export _H1 export _H2 From 9109f4760c809720697d2658882519cb5598ca57 Mon Sep 17 00:00:00 2001 From: Thijn Date: Wed, 9 Dec 2020 11:45:25 +0100 Subject: [PATCH 013/304] Fix synology_dsm deployhook for DSM 7 --- deploy/synology_dsm.sh | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 53ab5dd9..bca12d8d 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -73,13 +73,25 @@ synology_dsm_deploy() { _base_url="$SYNO_Scheme://$SYNO_Hostname:$SYNO_Port" _debug _base_url "$_base_url" + _debug "Getting API version" + response=$(_get "$_base_url/webapi/query.cgi?api=SYNO.API.Info&version=1&method=query&query=SYNO.API.Auth") + api_version=$(echo "$response" | grep "SYNO.API.Auth" | sed -n 's/.*"maxVersion" *: *\([0-9]*\).*/\1/p') + _debug3 response "$response" + _debug3 api_version "$api_version" + # Login, get the token from JSON and session id from cookie _info "Logging into $SYNO_Hostname:$SYNO_Port" encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)" encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)" - encoded_did="$(printf "%s" "$SYNO_DID" | _url_encode)" - response=$(_post "username=$encoded_username&passwd=$encoded_password&device_id=$encoded_did" "$_base_url/webman/login.cgi?enable_syno_token=yes") - token=$(echo "$response" | grep "SynoToken" | sed -n 's/.*"SynoToken" *: *"\([^"]*\).*/\1/p') + + if [ ! -z "$SYNO_DID" ]; then + _H1="Cookie: did=$SYNO_DID" + export _H1 + _debug3 H1 "${_H1}" + fi + + response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&enable_device_token=yes&enable_syno_token=yes" "$_base_url/webapi/entry.cgi?api=SYNO.API.Auth&version=$api_version") + token=$(echo "$response" | grep "synotoken" | sed -n 's/.*"synotoken" *: *"\([^"]*\).*/\1/p') _debug3 response "$response" _debug token "$token" @@ -88,13 +100,11 @@ synology_dsm_deploy() { _err "Check your username and password." return 1 fi + sid=$(echo "$response" | grep "sid" | sed -n 's/.*"sid" *: *"\([^"]*\).*/\1/p') - _H1="Cookie: $(_syno_get_cookie_data "id"); $(_syno_get_cookie_data "smid")" - _H2="X-SYNO-TOKEN: $token" + _H1="X-SYNO-TOKEN: $token" export _H1 - export _H2 _debug2 H1 "${_H1}" - _debug2 H2 "${_H2}" # Now that we know the username and password are good, save them _savedeployconf SYNO_Username "$SYNO_Username" @@ -102,7 +112,7 @@ synology_dsm_deploy() { _savedeployconf SYNO_DID "$SYNO_DID" _info "Getting certificates in Synology DSM" - response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1" "$_base_url/webapi/entry.cgi") + response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1&_sid=$sid" "$_base_url/webapi/entry.cgi") _debug3 response "$response" id=$(echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\"id\":\"\([^\"]*\).*/\1/p") _debug2 id "$id" @@ -135,7 +145,7 @@ synology_dsm_deploy() { content="${content%_}" # protect trailing \n _info "Upload certificate to the Synology DSM" - response=$(_post "$content" "$_base_url/webapi/entry.cgi?api=SYNO.Core.Certificate&method=import&version=1&SynoToken=$token" "" "POST" "multipart/form-data; boundary=${delim}") + response=$(_post "$content" "$_base_url/webapi/entry.cgi?api=SYNO.Core.Certificate&method=import&version=1&SynoToken=$token&_sid=$sid" "" "POST" "multipart/form-data; boundary=${delim}") _debug3 response "$response" if ! echo "$response" | grep '"error":' >/dev/null; then From 119643475f3d4019cdaa6b3c7ea5b0b86e27017c Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Wed, 9 Dec 2020 20:35:50 -0700 Subject: [PATCH 014/304] Support DSM 6 and 7 Small changes for DSM 6: All fields (except enable_syno_token as explained below) must either be in the GET params or the POST params, you can't mix GET and POST params enable_syno_token=yes must be in both the GET and POST params. If enable_syno_token=yes is only in the POST fields, then DSM6 returns a synotoken of --------. If enable_syno_token=yes is only in the GET params, then it returns no synotoken at all. It must be in both to work. Need to use /webapi/auth.cgi instead of /webapi/entry.cgi Verified with DSM 6.2.3-25426 Update 2 and DSM 7.0-40850 --- deploy/synology_dsm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index bca12d8d..edbc1e3e 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -90,7 +90,7 @@ synology_dsm_deploy() { _debug3 H1 "${_H1}" fi - response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&enable_device_token=yes&enable_syno_token=yes" "$_base_url/webapi/entry.cgi?api=SYNO.API.Auth&version=$api_version") + response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&api=SYNO.API.Auth&version=$api_version&enable_syno_token=yes" "$_base_url/webapi/auth.cgi?enable_syno_token=yes") token=$(echo "$response" | grep "synotoken" | sed -n 's/.*"synotoken" *: *"\([^"]*\).*/\1/p') _debug3 response "$response" _debug token "$token" From 6e27d9db64f268ffcd15378da02749e1ca63e710 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Wed, 9 Dec 2020 21:01:44 -0700 Subject: [PATCH 015/304] Shellcheck linting Also removed unused code --- deploy/synology_dsm.sh | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index edbc1e3e..35d33209 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -21,10 +21,6 @@ ######## Public functions ##################### -_syno_get_cookie_data() { - grep -i "\W$1=" "$HTTP_HEADER" | grep -i "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';' -} - #domain keyfile certfile cafile fullchain synology_dsm_deploy() { @@ -84,7 +80,7 @@ synology_dsm_deploy() { encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)" encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)" - if [ ! -z "$SYNO_DID" ]; then + if [ -n "$SYNO_DID" ]; then _H1="Cookie: did=$SYNO_DID" export _H1 _debug3 H1 "${_H1}" From dc8513122ebdf85f00a47ba1d087e4f254da464f Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 20 Dec 2020 20:17:05 +0100 Subject: [PATCH 016/304] World4You Bugfix unable to parse paketnr --- dnsapi/dns_world4you.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 24b8dd68..9d36f84d 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -185,7 +185,8 @@ _get_paketnr() { fi TLD="$domain" + _debug domain "$domain" RECORD=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#TLD} - 1))") - PAKETNR=$(echo "$form" | grep "data-textfilter=\" $domain " | _head_n 1 | sed 's/^.* \([0-9]*\) .*$/\1/') + PAKETNR=$(echo "$form" | grep "data-textfilter=\".* $domain " | _head_n 1 | sed 's/^.* \([0-9]*\) .*$/\1/') return 0 } From 573c0b1951ec622c39d4db3b1b79226ba420dc92 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Mon, 21 Dec 2020 09:39:09 +0100 Subject: [PATCH 017/304] World4You code refactor --- dnsapi/dns_world4you.sh | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 9d36f84d..6baccbd0 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -52,17 +52,26 @@ AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_toke ret=$(_post "$body" "$WORLD4YOU_API/$paketnr/dns" '' POST 'application/x-www-form-urlencoded') _resethttp - if grep '302' >/dev/null <"$HTTP_HEADER"; then + if _contains "$(_head_n 3 <"$HTTP_HEADER")" '302'; then res=$(_get "$WORLD4YOU_API/$paketnr/dns") if _contains "$res" "successfully"; then return 0 else msg=$(echo "$res" | tr '\n' '\t' | sed 's/.*

[^\t]*\t *\([^\t]*\)\t.*/\1/') + if _contains "$msg" '^<\!DOCTYPE html>'; then + msg='Unknown error' + fi _err "Unable to add record: $msg" + if _contains "$msg" '^<\!DOCTYPE html>'; then + echo "$ret" > 'error-01.html' + echo "$res" > 'error-02.html' + _err "View error-01.html and error-02.html for debugging" + fi return 1 fi else - _err "$(_head_n 1 <"$HTTP_HEADER")" + _err "$(_head_n 3 <"$HTTP_HEADER")" + _err "View $HTTP_HEADER for debugging" return 1 fi } @@ -111,17 +120,26 @@ DeleteDnsRecordForm[_token]=$form_token" ret=$(_post "$body" "$WORLD4YOU_API/$paketnr/deleteRecord" '' POST 'application/x-www-form-urlencoded') _resethttp - if grep '302' >/dev/null <"$HTTP_HEADER"; then + if _contains "$(_head_n 3 <"$HTTP_HEADER")" '302'; then res=$(_get "$WORLD4YOU_API/$paketnr/dns") if _contains "$res" "successfully"; then return 0 else msg=$(echo "$res" | tr '\n' '\t' | sed 's/.*

[^\t]*\t *\([^\t]*\)\t.*/\1/') + if _contains "$msg" '^<\!DOCTYPE html>'; then + msg='Unknown error' + fi _err "Unable to remove record: $msg" + if _contains "$msg" '^<\!DOCTYPE html>'; then + echo "$ret" > 'error-01.html' + echo "$res" > 'error-02.html' + _err "View error-01.html and error-02.html for debugging" + fi return 1 fi else - _err "$(_head_n 1 <"$HTTP_HEADER")" + _err "$(_head_n 3 <"$HTTP_HEADER")" + _err "View $HTTP_HEADER for debugging" return 1 fi } @@ -175,7 +193,7 @@ _get_paketnr() { domains=$(echo "$form" | grep '^ *[A-Za-z0-9_\.-]*\.[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/') domain='' for domain in $domains; do - if echo "$fqdn" | grep "$domain\$" >/dev/null; then + if _contains "$fqdn" "$domain\$"; then break fi domain='' From de4377f3a0878adf55d34ac74ee23dc5ceb1a2d5 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Mon, 21 Dec 2020 09:41:05 +0100 Subject: [PATCH 018/304] World4You shellcheck --- dnsapi/dns_world4you.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 6baccbd0..9ab406f6 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -63,8 +63,8 @@ AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_toke fi _err "Unable to add record: $msg" if _contains "$msg" '^<\!DOCTYPE html>'; then - echo "$ret" > 'error-01.html' - echo "$res" > 'error-02.html' + echo "$ret" >'error-01.html' + echo "$res" >'error-02.html' _err "View error-01.html and error-02.html for debugging" fi return 1 @@ -131,8 +131,8 @@ DeleteDnsRecordForm[_token]=$form_token" fi _err "Unable to remove record: $msg" if _contains "$msg" '^<\!DOCTYPE html>'; then - echo "$ret" > 'error-01.html' - echo "$res" > 'error-02.html' + echo "$ret" >'error-01.html' + echo "$res" >'error-02.html' _err "View error-01.html and error-02.html for debugging" fi return 1 From a03a874f3b717d922dba266d7d834f7c04af7951 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 23 Dec 2020 20:45:43 +0800 Subject: [PATCH 019/304] add dns check wiki --- acme.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/acme.sh b/acme.sh index 959a6fde..ba52f409 100755 --- a/acme.sh +++ b/acme.sh @@ -160,6 +160,8 @@ _SERVER_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Server" _PREFERRED_CHAIN_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Preferred-Chain" +_DNSCHECK_WIKI="https://github.com/acmesh-official/acme.sh/wiki/dnscheck" + _DNS_MANUAL_ERR="The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead." _DNS_MANUAL_WARN="It seems that you are using dns manual mode. please take care: $_DNS_MANUAL_ERR" @@ -3960,6 +3962,8 @@ _check_dns_entries() { _end_time="$(_math "$_end_time" + 1200)" #let's check no more than 20 minutes. while [ "$(_time)" -le "$_end_time" ]; do + _info "You can use '--dnssleep' to disable public dns checks." + _info "See: $_DNSCHECK_WIKI" _left="" for entry in $dns_entries; do d=$(_getfield "$entry" 1) From bef7c0341bbccd12cc18c55ef2ca3361a38d4136 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 28 Dec 2020 21:10:22 +0800 Subject: [PATCH 020/304] add libidn --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 6b382242..4618efaf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,6 +12,7 @@ RUN apk update -f \ tzdata \ oath-toolkit-oathtool \ tar \ + libidn \ && rm -rf /var/cache/apk/* ENV LE_CONFIG_HOME /acme.sh From 177493ef44b77b2054f6a1b96335206b951f8ac7 Mon Sep 17 00:00:00 2001 From: jimp100 <35727302+jimp100@users.noreply.github.com> Date: Wed, 16 Dec 2020 10:11:43 +0000 Subject: [PATCH 021/304] Corrected regex for subdomains A fix to handle subdomains of a duckdns domain. I.e. subdomain.mydomain.duckdns.org Handles n number of subdomains --- dnsapi/dns_duckdns.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index 41685147..618e12c6 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -96,7 +96,7 @@ dns_duckdns_rm() { _duckdns_get_domain() { # We'll extract the domain/username from full domain - _duckdns_domain="$(printf "%s" "$fulldomain" | _lower_case | _egrep_o '^(_acme-challenge\.)?[a-z0-9-]*\.duckdns\.org' | sed 's/^\(_acme-challenge\.\)\{0,1\}\([a-z0-9-]*\)\.duckdns\.org/\2/')" + _duckdns_domain="$(printf "%s" "$fulldomain" | _lower_case | _egrep_o '^(_acme-challenge\.)?([a-z0-9-]+\.)+duckdns\.org' | sed -n 's/^\([^.]\{1,\}\.\)*\([a-z0-9-]\{1,\}\)\.duckdns\.org$/\2/p;')" if [ -z "$_duckdns_domain" ]; then _err "Error extracting the domain." From dfddffd194890b7a053e98b21c0552b3507a758a Mon Sep 17 00:00:00 2001 From: James Edington Date: Fri, 8 Jan 2021 11:14:39 -0700 Subject: [PATCH 022/304] This is a general-purpose ACME client. We should be proud of this. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index cd747666..f53578d4 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,7 @@ https://github.com/acmesh-official/acmetest - [ZeroSSL.com CA](https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA) - [BuyPass.com CA](https://github.com/acmesh-official/acme.sh/wiki/BuyPass.com-CA) - [Pebble strict Mode](https://github.com/letsencrypt/pebble) +- Any other [RFC8555](https://tools.ietf.org/html/rfc8555)-compliant CA # Supported modes From 54dca4b5fa85f17fb21398e70f9845f79d6dd2c8 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 10 Jan 2021 11:47:54 +0800 Subject: [PATCH 023/304] fix https://github.com/acmesh-official/acme.sh/issues/3156 --- dnsapi/dns_linode_v4.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_linode_v4.sh b/dnsapi/dns_linode_v4.sh index c2bebc57..9504afbf 100755 --- a/dnsapi/dns_linode_v4.sh +++ b/dnsapi/dns_linode_v4.sh @@ -106,6 +106,7 @@ dns_linode_v4_rm() { #################### Private functions below ################################## _Linode_API() { + LINODE_V4_API_KEY="${LINODE_V4_API_KEY:-$(_readaccountconf_mutable LINODE_V4_API_KEY)}" if [ -z "$LINODE_V4_API_KEY" ]; then LINODE_V4_API_KEY="" @@ -115,7 +116,7 @@ _Linode_API() { return 1 fi - _saveaccountconf LINODE_V4_API_KEY "$LINODE_V4_API_KEY" + _saveaccountconf_mutable LINODE_V4_API_KEY "$LINODE_V4_API_KEY" } #################### Private functions below ################################## From 2629140d880603cbf04c95ae7ff168742bfb3233 Mon Sep 17 00:00:00 2001 From: Stephen Dendtler Date: Sun, 10 Jan 2021 11:19:16 +0000 Subject: [PATCH 024/304] Added RackCorp API Integration --- dnsapi/dns_rackcorp.sh | 156 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 dnsapi/dns_rackcorp.sh diff --git a/dnsapi/dns_rackcorp.sh b/dnsapi/dns_rackcorp.sh new file mode 100644 index 00000000..7323473d --- /dev/null +++ b/dnsapi/dns_rackcorp.sh @@ -0,0 +1,156 @@ +#!/usr/bin/env sh + +# Provider: RackCorp (www.rackcorp.com) +# Author: Stephen Dendtler (sdendtler@rackcorp.com) +# Report Bugs here: https://github.com/senjoo/acme.sh +# Alternate email contact: support@rackcorp.com +# +# You'll need an API key (Portal: ADMINISTRATION -> API) +# Set the environment variables as below: +# +# export RACKCORP_APIUUID="UUIDHERE" +# export RACKCORP_APISECRET="SECRETHERE" +# + +RACKCORP_API_ENDPOINT="https://api.rackcorp.net/api/rest/v2.4/json.php" + +######## Public functions ##################### + +dns_rackcorp_add() { + fulldomain="$1" + txtvalue="$2" + + _debug fulldomain="$fulldomain" + _debug txtvalue="$txtvalue" + + if ! _rackcorp_validate; then + return 1 + fi + + _debug "Searching for root zone" + if ! _get_root "$fulldomain"; then + return 1 + fi + _debug _lookup "$_lookup" + _debug _domain "$_domain" + + _info "Creating TXT record." + + if ! _rackcorp_api dns.record.create "\"name\":\"$_domain\",\"type\":\"TXT\",\"lookup\":\"$_lookup\",\"data\":\"$txtvalue\",\"ttl\":300"; then + return 1 + fi + + return 0 +} + +#Usage: fulldomain txtvalue +#Remove the txt record after validation. +dns_rackcorp_rm() { + fulldomain=$1 + txtvalue=$2 + + _debug fulldomain="$fulldomain" + _debug txtvalue="$txtvalue" + + if ! _rackcorp_validate; then + return 1 + fi + + _debug "Searching for root zone" + if ! _get_root "$fulldomain"; then + return 1 + fi + _debug _lookup "$_lookup" + _debug _domain "$_domain" + + _info "Creating TXT record." + + if ! _rackcorp_api dns.record.delete "\"name\":\"$_domain\",\"type\":\"TXT\",\"lookup\":\"$_lookup\",\"data\":\"$txtvalue\""; then + return 1 + fi + + return 0 +} + +#################### Private functions below ################################## +#_acme-challenge.domain.com +#returns +# _lookup=_acme-challenge +# _domain=domain.com +_get_root() { + domain=$1 + i=2 + p=1 + if ! _rackcorp_api dns.domain.getall "\"name\":\"$domain\""; then + return 1 + fi + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug searchhost "$h" + if [ -z "$h" ]; then + _err "Could not find domain for record $domain in RackCorp using the provided credentials" + #not valid + return 1 + fi + + _rackcorp_api dns.domain.getall "\"exactName\":\"$h\"" + + if _contains "$response" "\"matches\":1"; then + if _contains "$response" "\"name\":\"$h\""; then + _lookup=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain="$h" + return 0 + fi + fi + p=$i + i=$(_math "$i" + 1) + done + + return 1 +} + +_rackcorp_validate() { + RACKCORP_APIUUID="${RACKCORP_APIUUID:-$(_readaccountconf_mutable RACKCORP_APIUUID)}" + if [ -z "$RACKCORP_APIUUID" ]; then + RACKCORP_APIUUID="" + _err "You require a RackCorp API UUID (export RACKCORP_APIUUID=\"\")" + _err "Please login to the portal and create an API key and try again." + return 1 + fi + + _saveaccountconf_mutable RACKCORP_APIUUID "$RACKCORP_APIUUID" + + RACKCORP_APISECRET="${RACKCORP_APISECRET:-$(_readaccountconf_mutable RACKCORP_APISECRET)}" + if [ -z "$RACKCORP_APISECRET" ]; then + RACKCORP_APISECRET="" + _err "You require a RackCorp API secret (export RACKCORP_APISECRET=\"\")" + _err "Please login to the portal and create an API key and try again." + return 1 + fi + + _saveaccountconf_mutable RACKCORP_APISECRET "$RACKCORP_APISECRET" + + return 0 +} +_rackcorp_api() { + _rackcorpcmd=$1 + _rackcorpinputdata=$2 + _debug cmd "$_rackcorpcmd $_rackcorpinputdata" + + export _H1="Accept: application/json" + response="$(_post "{\"APIUUID\":\"$RACKCORP_APIUUID\",\"APISECRET\":\"$RACKCORP_APISECRET\",\"cmd\":\"$_rackcorpcmd\",$_rackcorpinputdata}" "$RACKCORP_API_ENDPOINT" "" "POST")" + + if [ "$?" != "0" ]; then + _err "error $response" + return 1 + fi + _debug2 response "$response" + if _contains "$response" "\"code\":\"OK\""; then + _debug code "OK" + else + _debug code "FAILED" + response="" + return 1 + fi + return 0 +} From 1ef3efe7937a492b41cd02d53d85851526501db7 Mon Sep 17 00:00:00 2001 From: Stephen Dendtler Date: Mon, 11 Jan 2021 13:03:42 +0000 Subject: [PATCH 025/304] _get_root now does not skip the first label of the domain --- dnsapi/dns_rackcorp.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_rackcorp.sh b/dnsapi/dns_rackcorp.sh index 7323473d..6aabfddc 100644 --- a/dnsapi/dns_rackcorp.sh +++ b/dnsapi/dns_rackcorp.sh @@ -79,7 +79,7 @@ dns_rackcorp_rm() { # _domain=domain.com _get_root() { domain=$1 - i=2 + i=1 p=1 if ! _rackcorp_api dns.domain.getall "\"name\":\"$domain\""; then return 1 From 9cccf5e7cffde1d553fce953f84fac1977b17fdd Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Mon, 4 Jan 2021 18:41:02 +1300 Subject: [PATCH 026/304] Add Telegram notification script Requires: - API Token for a bot created with the Telegram Bot Father. - A Chat ID for a user/group that the bot has permission to post to. --- notify/telegram.sh | 49 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 notify/telegram.sh diff --git a/notify/telegram.sh b/notify/telegram.sh new file mode 100644 index 00000000..ee2d93e2 --- /dev/null +++ b/notify/telegram.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +#Support Telegram Bots + +#TELEGRAM_BOT_APITOKEN="" +#TELEGRAM_BOT_CHATID="" + +telegram_send() { + _subject="$1" + _content="$2" + _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped + _debug "_statusCode" "$_statusCode" + + TELEGRAM_BOT_APITOKEN="${TELEGRAM_BOT_APITOKEN:-$(_readaccountconf_mutable TELEGRAM_BOT_APITOKEN)}" + if [ -z "$TELEGRAM_BOT_APITOKEN" ]; then + TELEGRAM_BOT_APITOKEN="" + _err "You didn't specify a Telegram BOT API Token TELEGRAM_BOT_APITOKEN yet." + return 1 + fi + _saveaccountconf_mutable TELEGRAM_BOT_APITOKEN "$TELEGRAM_BOT_APITOKEN" + + TELEGRAM_BOT_CHATID="${TELEGRAM_BOT_CHATID:-$(_readaccountconf_mutable TELEGRAM_BOT_CHATID)}" + if [ -z "$TELEGRAM_BOT_CHATID" ]; then + TELEGRAM_BOT_CHATID="" + _err "You didn't specify a Telegram Chat id TELEGRAM_BOT_CHATID yet." + return 1 + fi + _saveaccountconf_mutable TELEGRAM_BOT_CHATID "$TELEGRAM_BOT_CHATID" + + _content="$(printf "*%s*\n%s" "$_subject" "$_content" | _json_encode)" + _data="{\"text\": \"$_content\", " + _data="$_data\"chat_id\": \"$TELEGRAM_BOT_CHATID\", " + _data="$_data\"parse_mode\": \"markdown\", " + _data="$_data\"disable_web_page_preview\": \"1\"}" + + export _H1="Content-Type: application/json" + _telegram_bot_url="https://api.telegram.org/bot${TELEGRAM_BOT_APITOKEN}/sendMessage" + if _post "$_data" "$_telegram_bot_url"; then + # shellcheck disable=SC2154 + _message=$(printf "%s\n" "$response" | sed -ne 's/.*"ok":\([^,]*\).*/\1/p') + if [ "$_message" = "true" ]; then + _info "telegram send success." + return 0 + fi + fi + _err "telegram send error." + _err "$response" + return 1 +} From f6f9f74a14058cb8efc34c0c89b766a0c47299d9 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Mon, 11 Jan 2021 11:21:46 +1300 Subject: [PATCH 027/304] Correct shebang --- notify/telegram.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notify/telegram.sh b/notify/telegram.sh index ee2d93e2..2806206d 100644 --- a/notify/telegram.sh +++ b/notify/telegram.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env sh #Support Telegram Bots From 6bdbc1639461abec5ae937045faef41ee7bd4d1d Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Mon, 11 Jan 2021 11:27:39 +1300 Subject: [PATCH 028/304] Avoid usage of sed -e --- notify/telegram.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notify/telegram.sh b/notify/telegram.sh index 2806206d..b1306ee1 100644 --- a/notify/telegram.sh +++ b/notify/telegram.sh @@ -37,7 +37,7 @@ telegram_send() { _telegram_bot_url="https://api.telegram.org/bot${TELEGRAM_BOT_APITOKEN}/sendMessage" if _post "$_data" "$_telegram_bot_url"; then # shellcheck disable=SC2154 - _message=$(printf "%s\n" "$response" | sed -ne 's/.*"ok":\([^,]*\).*/\1/p') + _message=$(printf "%s\n" "$response" | sed -n 's/.*"ok":\([^,]*\).*/\1/p') if [ "$_message" = "true" ]; then _info "telegram send success." return 0 From d871767a01e43458a26045091cf9cdbded1e467d Mon Sep 17 00:00:00 2001 From: Mark Challoner Date: Wed, 6 Jan 2021 20:20:21 +0000 Subject: [PATCH 029/304] Add Peplink deploy hook --- deploy/peplink.sh | 123 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 deploy/peplink.sh diff --git a/deploy/peplink.sh b/deploy/peplink.sh new file mode 100644 index 00000000..c4bd6242 --- /dev/null +++ b/deploy/peplink.sh @@ -0,0 +1,123 @@ +#!/usr/bin/env sh + +# Script to deploy cert to Peplink Routers +# +# The following environment variables must be set: +# +# PEPLINK_Hostname - Peplink hostname +# PEPLINK_Username - Peplink username to login +# PEPLINK_Password - Peplink password to login +# +# The following environmental variables may be set if you don't like their +# default values: +# +# PEPLINK_Certtype - Certificate type to target for replacement +# defaults to "webadmin", can be one of: +# * "chub" (ContentHub) +# * "openvpn" (OpenVPN CA) +# * "portal" (Captive Portal SSL) +# * "webadmin" (Web Admin SSL) +# * "webproxy" (Proxy Root CA) +# * "wwan_ca" (Wi-Fi WAN CA) +# * "wwan_client" (Wi-Fi WAN Client) +# PEPLINK_Scheme - defaults to "https" +# PEPLINK_Port - defaults to "443" +# +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +_peplink_get_cookie_data() { + grep -i "\W$1=" | grep -i "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';' +} + +#domain keyfile certfile cafile fullchain +peplink_deploy() { + + _cdomain="$1" + _ckey="$2" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug _cfullchain "$_cfullchain" + _debug _ckey "$_ckey" + + # Get Hostname, Username and Password, but don't save until we successfully authenticate + _getdeployconf PEPLINK_Hostname + _getdeployconf PEPLINK_Username + _getdeployconf PEPLINK_Password + if [ -z "${PEPLINK_Hostname:-}" ] || [ -z "${PEPLINK_Username:-}" ] || [ -z "${PEPLINK_Password:-}" ]; then + _err "PEPLINK_Hostname & PEPLINK_Username & PEPLINK_Password must be set" + return 1 + fi + _debug2 PEPLINK_Hostname "$PEPLINK_Hostname" + _debug2 PEPLINK_Username "$PEPLINK_Username" + _secure_debug2 PEPLINK_Password "$PEPLINK_Password" + + # Optional certificate type, scheme, and port for Peplink + _getdeployconf PEPLINK_Certtype + _getdeployconf PEPLINK_Scheme + _getdeployconf PEPLINK_Port + + # Don't save the certificate type until we verify it exists and is supported + _savedeployconf PEPLINK_Scheme "$PEPLINK_Scheme" + _savedeployconf PEPLINK_Port "$PEPLINK_Port" + + # Default vaules for certificate type, scheme, and port + [ -n "${PEPLINK_Certtype}" ] || PEPLINK_Certtype="webadmin" + [ -n "${PEPLINK_Scheme}" ] || PEPLINK_Scheme="https" + [ -n "${PEPLINK_Port}" ] || PEPLINK_Port="443" + + _debug2 PEPLINK_Certtype "$PEPLINK_Certtype" + _debug2 PEPLINK_Scheme "$PEPLINK_Scheme" + _debug2 PEPLINK_Port "$PEPLINK_Port" + + _base_url="$PEPLINK_Scheme://$PEPLINK_Hostname:$PEPLINK_Port" + _debug _base_url "$_base_url" + + # Login, get the auth token from the cookie + _info "Logging into $PEPLINK_Hostname:$PEPLINK_Port" + encoded_username="$(printf "%s" "$PEPLINK_Username" | _url_encode)" + encoded_password="$(printf "%s" "$PEPLINK_Password" | _url_encode)" + response=$(_post "func=login&username=$encoded_username&password=$encoded_password" "$_base_url/cgi-bin/MANGA/api.cgi") + auth_token=$(_peplink_get_cookie_data "bauth" <"$HTTP_HEADER") + _debug3 response "$response" + _debug auth_token "$auth_token" + + if [ -z "$auth_token" ]; then + _err "Unable to authenticate to $PEPLINK_Hostname:$PEPLINK_Port using $PEPLINK_Scheme." + _err "Check your username and password." + return 1 + fi + + _H1="Cookie: $auth_token" + export _H1 + _debug2 H1 "${_H1}" + + # Now that we know the hostnameusername and password are good, save them + _savedeployconf PEPLINK_Hostname "$PEPLINK_Hostname" + _savedeployconf PEPLINK_Username "$PEPLINK_Username" + _savedeployconf PEPLINK_Password "$PEPLINK_Password" + + _info "Generate form POST request" + + encoded_key="$(_url_encode <"$_ckey")" + encoded_fullchain="$(_url_encode <"$_cfullchain")" + body="cert_type=$PEPLINK_Certtype&cert_uid=§ion=CERT_modify&key_pem=$encoded_key&key_pem_passphrase=&key_pem_passphrase_confirm=&cert_pem=$encoded_fullchain" + _debug3 body "$body" + + _info "Upload $PEPLINK_Certtype certificate to the Peplink" + + response=$(_post "$body" "$_base_url/cgi-bin/MANGA/admin.cgi") + _debug3 response "$response" + + if echo "$response" | grep 'Success' >/dev/null; then + # We've verified this certificate type is valid, so save it + _savedeployconf PEPLINK_Certtype "$PEPLINK_Certtype" + _info "Certificate was updated" + return 0 + else + _err "Unable to update certificate, error code $response" + return 1 + fi +} From fa7dfde08f42ea0452d8dae8df749a614ea90f12 Mon Sep 17 00:00:00 2001 From: pssara Date: Fri, 15 Jan 2021 15:12:53 +0100 Subject: [PATCH 030/304] Fixed issue with ISP config where the Client ID was asumed to be the same as the SYS User ID --- dnsapi/dns_ispconfig.sh | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/dnsapi/dns_ispconfig.sh b/dnsapi/dns_ispconfig.sh index bd1e0391..8be47f60 100755 --- a/dnsapi/dns_ispconfig.sh +++ b/dnsapi/dns_ispconfig.sh @@ -75,7 +75,7 @@ _ISPC_getZoneInfo() { # suffix . needed for zone -> domain.tld. curData="{\"session_id\":\"${sessionID}\",\"primary_id\":{\"origin\":\"${curZone}.\"}}" curResult="$(_post "${curData}" "${ISPC_Api}?dns_zone_get")" - _debug "Calling _ISPC_getZoneInfo: '${curData}' '${ISPC_Api}?login'" + _debug "Calling _ISPC_getZoneInfo: '${curData}' '${ISPC_Api}?dns_zone_get'" _debug "Result of _ISPC_getZoneInfo: '$curResult'" if _contains "${curResult}" '"id":"'; then zoneFound=true @@ -110,18 +110,32 @@ _ISPC_getZoneInfo() { ;; *) _info "Retrieved Zone ID" ;; esac - client_id=$(echo "${curResult}" | _egrep_o "sys_userid.*" | cut -d ':' -f 2 | cut -d '"' -f 2) - _debug "Client ID: '${client_id}'" - case "${client_id}" in + sys_userid=$(echo "${curResult}" | _egrep_o "sys_userid.*" | cut -d ':' -f 2 | cut -d '"' -f 2) + _debug "SYS User ID: '${sys_userid}'" + case "${sys_userid}" in '' | *[!0-9]*) - _err "Client ID is not numeric." + _err "SYS User ID is not numeric." return 1 ;; - *) _info "Retrieved Client ID." ;; + *) _info "Retrieved SYS User ID." ;; esac zoneFound="" zoneEnd="" fi + # Need to get client_id as it is different from sys_userid + curData="{\"session_id\":\"${sessionID}\",\"sys_userid\":\"${sys_userid}\"}" + curResult="$(_post "${curData}" "${ISPC_Api}?client_get_id")" + _debug "Calling _ISPC_ClientGetID: '${curData}' '${ISPC_Api}?client_get_id'" + _debug "Result of _ISPC_ClientGetID: '$curResult'" + client_id=$(echo "${curResult}" | _egrep_o "response.*" | cut -d ':' -f 2 | cut -d '"' -f 2 | tr -d '{}') + _debug "Client ID: '${client_id}'" + case "${client_id}" in + '' | *[!0-9]*) + _err "Client ID is not numeric." + return 1 + ;; + *) _info "Retrieved Client ID." ;; + esac } _ISPC_addTxt() { From 488fc094331cfe1c1e8f0b8dff94a56e10d3dad7 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 16 Jan 2021 23:50:57 +0800 Subject: [PATCH 031/304] fix format --- dnsapi/dns_ispconfig.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_ispconfig.sh b/dnsapi/dns_ispconfig.sh index 8be47f60..e68ddd49 100755 --- a/dnsapi/dns_ispconfig.sh +++ b/dnsapi/dns_ispconfig.sh @@ -130,11 +130,11 @@ _ISPC_getZoneInfo() { client_id=$(echo "${curResult}" | _egrep_o "response.*" | cut -d ':' -f 2 | cut -d '"' -f 2 | tr -d '{}') _debug "Client ID: '${client_id}'" case "${client_id}" in - '' | *[!0-9]*) + '' | *[!0-9]*) _err "Client ID is not numeric." return 1 ;; - *) _info "Retrieved Client ID." ;; + *) _info "Retrieved Client ID." ;; esac } From 1191ba44ca83ee31719fd61716657f8d422c012a Mon Sep 17 00:00:00 2001 From: Lukas Brocke Date: Thu, 24 Dec 2020 11:03:25 +0100 Subject: [PATCH 032/304] dnsapi/ionos: Add API support for IONOS DNS API The IONOS DNS API is in beta state, please read [1] on how to get started. PLEASE NOTE: The v2 wildcard certification creation [2] is not yet supported as the IONOS API doesn't allow the creation of multiple TXT records with the same domain name. [1] https://beta.developer.hosting.ionos.de/docs/getstarted [2] https://github.com/acmesh-official/acme.sh/issues/1261 --- dnsapi/dns_ionos.sh | 157 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100755 dnsapi/dns_ionos.sh diff --git a/dnsapi/dns_ionos.sh b/dnsapi/dns_ionos.sh new file mode 100755 index 00000000..4d33e019 --- /dev/null +++ b/dnsapi/dns_ionos.sh @@ -0,0 +1,157 @@ +#!/usr/bin/env sh + +# Supports IONOS DNS API Beta v1.0.0 +# +# Usage: +# Export IONOS_PREFIX and IONOS_SECRET before calling acme.sh: +# +# $ export IONOS_PREFIX="..." +# $ export IONOS_SECRET="..." +# +# $ acme.sh --issue --dns dns_ionos ... + +IONOS_API="https://api.hosting.ionos.com/dns" +IONOS_ROUTE_ZONES="/v1/zones" + +IONOS_TXT_TTL=60 # minumum accepted by API +IONOS_TXT_PRIO=10 + +dns_ionos_add() { + fulldomain=$1 + txtvalue=$2 + + _ionos_init + + _body="{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}" + + if _ionos_rest PATCH "$IONOS_ROUTE_ZONES/$_zone_id" "$_body" && [ -z "$response" ]; then + _info "TXT record for _sub_domain.$_domain has been created successfully." + return 0 + fi + + return 1 +} + +dns_ionos_rm() { + fulldomain=$1 + txtvalue=$2 + + _ionos_init + + if ! _ionos_get_record "$fulldomain" "$_zone_id"; then + _err "Could not find _acme-challenge TXT record." + return 1 + fi + + if _ionos_rest DELETE "$IONOS_ROUTE_ZONES/$_zone_id/records/$_record_id" && [ -z "$response" ]; then + _info "TXT record for _sub_domain.$_domain has been deleted successfully." + return 0 + fi + + return 1 +} + +_ionos_init() { + IONOS_PREFIX="${IONOS_PREFIX:-$(_readaccountconf_mutable IONOS_PREFIX)}" + IONOS_SECRET="${IONOS_SECRET:-$(_readaccountconf_mutable IONOS_SECRET)}" + + if [ -z "$IONOS_PREFIX" ] || [ -z "$IONOS_SECRET" ]; then + _err "You didn't specify an IONOS api prefix and secret yet." + _err "Read https://beta.developer.hosting.ionos.de/docs/getstarted to learn how to get a prefix and secret." + _err "" + _err "Then set them before calling acme.sh:" + _err "\$ export IONOS_PREFIX=\"...\"" + _err "\$ export IONOS_SECRET=\"...\"" + _err "\$ acme.sh --issue -d ... --dns dns_ionos" + return 1 + fi + + _saveaccountconf_mutable IONOS_PREFIX "$IONOS_PREFIX" + _saveaccountconf_mutable IONOS_SECRET "$IONOS_SECRET" + + if ! _get_root "$fulldomain"; then + _err "Cannot find this domain in your IONOS account." + return 1 + fi +} + +_get_root() { + domain=$1 + i=2 + p=1 + + if _ionos_rest GET "$IONOS_ROUTE_ZONES"; then + response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" + + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + if [ -z "$h" ]; then + return 1 + fi + + _zone="$(echo "$response" | _egrep_o "{.*\"name\":\s*\"$h\".*}")" + if [ "$_zone" ]; then + _zone_id=$(printf "%s\n" "$_zone" | _egrep_o "\"id\":\s*\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"' ) + if [ "$_zone_id" ]; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain=$h + + return 0 + fi + + return 1 + fi + + p=$i + i=$(_math "$i" + 1) + done + fi + + return 1 +} + +_ionos_get_record() { + fulldomain=$1 + zone_id=$2 + + if _ionos_rest GET "$IONOS_ROUTE_ZONES/$zone_id?recordName=$fulldomain&recordType=TXT"; then + response="$(echo "$response" | tr -d "\n" )" + + _record="$(echo "$response" | _egrep_o "{\"name\":\s*\"$fulldomain\".*}")" + if [ "$_record" ]; then + _record_id=$(printf "%s\n" "$_record" | _egrep_o "\"id\":\s*\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"' ) + + return 0 + fi + fi + + return 1 +} + +_ionos_rest() { + method="$1" + route="$2" + data="$3" + + IONOS_API_KEY="$(printf "%s.%s" "$IONOS_PREFIX" "$IONOS_SECRET")" + + export _H1="X-API-Key: $IONOS_API_KEY" + + if [ "$method" != "GET" ]; then + export _H2="Accept: application/json" + export _H3="Content-Type: application/json" + + response="$(_post "$data" "$IONOS_API$route" "" "$method")" + else + export _H2="Accept: */*" + + response="$(_get "$IONOS_API$route")" + fi + + if [ "$?" != "0" ]; then + _err "Error $route" + return 1 + fi + + return 0 +} From 2b7c99191905b1ba0037bfabf5a4c23d8544c55d Mon Sep 17 00:00:00 2001 From: Lukas Brocke Date: Thu, 24 Dec 2020 13:06:07 +0100 Subject: [PATCH 033/304] dnsapi/ionos: Run shfmt --- dnsapi/dns_ionos.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/dnsapi/dns_ionos.sh b/dnsapi/dns_ionos.sh index 4d33e019..fb6ba3f8 100755 --- a/dnsapi/dns_ionos.sh +++ b/dnsapi/dns_ionos.sh @@ -13,7 +13,7 @@ IONOS_API="https://api.hosting.ionos.com/dns" IONOS_ROUTE_ZONES="/v1/zones" -IONOS_TXT_TTL=60 # minumum accepted by API +IONOS_TXT_TTL=60 # minimum accepted by API IONOS_TXT_PRIO=10 dns_ionos_add() { @@ -25,7 +25,7 @@ dns_ionos_add() { _body="{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}" if _ionos_rest PATCH "$IONOS_ROUTE_ZONES/$_zone_id" "$_body" && [ -z "$response" ]; then - _info "TXT record for _sub_domain.$_domain has been created successfully." + _info "TXT record has been created successfully." return 0 fi @@ -44,7 +44,7 @@ dns_ionos_rm() { fi if _ionos_rest DELETE "$IONOS_ROUTE_ZONES/$_zone_id/records/$_record_id" && [ -z "$response" ]; then - _info "TXT record for _sub_domain.$_domain has been deleted successfully." + _info "TXT record has been deleted successfully." return 0 fi @@ -54,7 +54,7 @@ dns_ionos_rm() { _ionos_init() { IONOS_PREFIX="${IONOS_PREFIX:-$(_readaccountconf_mutable IONOS_PREFIX)}" IONOS_SECRET="${IONOS_SECRET:-$(_readaccountconf_mutable IONOS_SECRET)}" - + if [ -z "$IONOS_PREFIX" ] || [ -z "$IONOS_SECRET" ]; then _err "You didn't specify an IONOS api prefix and secret yet." _err "Read https://beta.developer.hosting.ionos.de/docs/getstarted to learn how to get a prefix and secret." @@ -91,7 +91,7 @@ _get_root() { _zone="$(echo "$response" | _egrep_o "{.*\"name\":\s*\"$h\".*}")" if [ "$_zone" ]; then - _zone_id=$(printf "%s\n" "$_zone" | _egrep_o "\"id\":\s*\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"' ) + _zone_id=$(printf "%s\n" "$_zone" | _egrep_o "\"id\":\s*\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') if [ "$_zone_id" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain=$h @@ -115,13 +115,13 @@ _ionos_get_record() { zone_id=$2 if _ionos_rest GET "$IONOS_ROUTE_ZONES/$zone_id?recordName=$fulldomain&recordType=TXT"; then - response="$(echo "$response" | tr -d "\n" )" + response="$(echo "$response" | tr -d "\n")" _record="$(echo "$response" | _egrep_o "{\"name\":\s*\"$fulldomain\".*}")" if [ "$_record" ]; then - _record_id=$(printf "%s\n" "$_record" | _egrep_o "\"id\":\s*\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"' ) - - return 0 + _record_id=$(printf "%s\n" "$_record" | _egrep_o "\"id\":\s*\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') + + return 0 fi fi From 24599f69daedc57a730016f9575874f928c09798 Mon Sep 17 00:00:00 2001 From: Lukas Brocke Date: Mon, 18 Jan 2021 14:35:08 +0100 Subject: [PATCH 034/304] dnsapi/ionos: Add support for v2 wildcard certificates --- dnsapi/dns_ionos.sh | 45 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/dnsapi/dns_ionos.sh b/dnsapi/dns_ionos.sh index fb6ba3f8..a8cc36cf 100755 --- a/dnsapi/dns_ionos.sh +++ b/dnsapi/dns_ionos.sh @@ -20,9 +20,22 @@ dns_ionos_add() { fulldomain=$1 txtvalue=$2 - _ionos_init + if ! _ionos_init; then + return 1 + fi + + _new_record="{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}" + + # As no POST route is supported by the API, check for existing records and include them in the PATCH request in order not delete them. + # This is required to support ACME v2 wildcard certificate creation, where two TXT records for the same domain name are created. + + _ionos_get_existing_records "$fulldomain" "$_zone_id" - _body="{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}" + if [ "$_existing_records" ]; then + _body="[$_new_record,$_existing_records]" + else + _body="[$_new_record]" + fi if _ionos_rest PATCH "$IONOS_ROUTE_ZONES/$_zone_id" "$_body" && [ -z "$response" ]; then _info "TXT record has been created successfully." @@ -36,9 +49,11 @@ dns_ionos_rm() { fulldomain=$1 txtvalue=$2 - _ionos_init + if ! _ionos_init; then + return 1 + fi - if ! _ionos_get_record "$fulldomain" "$_zone_id"; then + if ! _ionos_get_record "$fulldomain" "$_zone_id" "$txtvalue"; then _err "Could not find _acme-challenge TXT record." return 1 fi @@ -81,7 +96,7 @@ _get_root() { p=1 if _ionos_rest GET "$IONOS_ROUTE_ZONES"; then - response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" + response="$(echo "$response" | tr -d "\n")" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) @@ -89,9 +104,9 @@ _get_root() { return 1 fi - _zone="$(echo "$response" | _egrep_o "{.*\"name\":\s*\"$h\".*}")" + _zone="$(echo "$response" | _egrep_o "\"name\":\"$h\".*?}")" if [ "$_zone" ]; then - _zone_id=$(printf "%s\n" "$_zone" | _egrep_o "\"id\":\s*\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') + _zone_id=$(printf "%s\n" "$_zone" | _egrep_o "\"id\":\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') if [ "$_zone_id" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain=$h @@ -110,16 +125,28 @@ _get_root() { return 1 } +_ionos_get_existing_records() { + fulldomain=$1 + zone_id=$2 + + if _ionos_rest GET "$IONOS_ROUTE_ZONES/$zone_id?recordName=$fulldomain&recordType=TXT"; then + response="$(echo "$response" | tr -d "\n")" + + _existing_records="$(printf "%s\n" "$response" | _egrep_o "\"records\":\[.*?\]" | _head_n 1 | cut -d '[' -f 2 | sed 's/]//')" + fi +} + _ionos_get_record() { fulldomain=$1 zone_id=$2 + txtrecord=$3 if _ionos_rest GET "$IONOS_ROUTE_ZONES/$zone_id?recordName=$fulldomain&recordType=TXT"; then response="$(echo "$response" | tr -d "\n")" - _record="$(echo "$response" | _egrep_o "{\"name\":\s*\"$fulldomain\".*}")" + _record="$(echo "$response" | _egrep_o "\{\"name\":\"$fulldomain\"[^\}]*?\"type\":\"TXT\"[^\}]*?\"content\":\"\\\\\"$txtrecord\\\\\"\".*?\}")" if [ "$_record" ]; then - _record_id=$(printf "%s\n" "$_record" | _egrep_o "\"id\":\s*\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') + _record_id=$(printf "%s\n" "$_record" | _egrep_o "\"id\":\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') return 0 fi From 34af4bae6b271f9744db8f9e5812688494f508f9 Mon Sep 17 00:00:00 2001 From: Lukas Brocke Date: Wed, 20 Jan 2021 21:08:58 +0100 Subject: [PATCH 035/304] dnsapi/ionos: Fixes for Solaris --- dnsapi/dns_ionos.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dnsapi/dns_ionos.sh b/dnsapi/dns_ionos.sh index a8cc36cf..54696d5d 100755 --- a/dnsapi/dns_ionos.sh +++ b/dnsapi/dns_ionos.sh @@ -104,9 +104,9 @@ _get_root() { return 1 fi - _zone="$(echo "$response" | _egrep_o "\"name\":\"$h\".*?}")" + _zone="$(echo "$response" | _egrep_o "\"name\":\"$h\".*\}")" if [ "$_zone" ]; then - _zone_id=$(printf "%s\n" "$_zone" | _egrep_o "\"id\":\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') + _zone_id=$(printf "%s\n" "$_zone" | _egrep_o "\"id\":\"[a-fA-F0-9\-]*\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') if [ "$_zone_id" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain=$h @@ -132,7 +132,7 @@ _ionos_get_existing_records() { if _ionos_rest GET "$IONOS_ROUTE_ZONES/$zone_id?recordName=$fulldomain&recordType=TXT"; then response="$(echo "$response" | tr -d "\n")" - _existing_records="$(printf "%s\n" "$response" | _egrep_o "\"records\":\[.*?\]" | _head_n 1 | cut -d '[' -f 2 | sed 's/]//')" + _existing_records="$(printf "%s\n" "$response" | _egrep_o "\"records\":\[.*\]" | _head_n 1 | cut -d '[' -f 2 | sed 's/]//')" fi } @@ -144,9 +144,9 @@ _ionos_get_record() { if _ionos_rest GET "$IONOS_ROUTE_ZONES/$zone_id?recordName=$fulldomain&recordType=TXT"; then response="$(echo "$response" | tr -d "\n")" - _record="$(echo "$response" | _egrep_o "\{\"name\":\"$fulldomain\"[^\}]*?\"type\":\"TXT\"[^\}]*?\"content\":\"\\\\\"$txtrecord\\\\\"\".*?\}")" + _record="$(echo "$response" | _egrep_o "\"name\":\"$fulldomain\"[^\}]*\"type\":\"TXT\"[^\}]*\"content\":\"\\\\\"$txtrecord\\\\\"\".*\}")" if [ "$_record" ]; then - _record_id=$(printf "%s\n" "$_record" | _egrep_o "\"id\":\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') + _record_id=$(printf "%s\n" "$_record" | _egrep_o "\"id\":\"[a-fA-F0-9\-]*\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') return 0 fi From f2dd9fd28bb4a330239d7b390c41136dc809b501 Mon Sep 17 00:00:00 2001 From: Lukas Brocke Date: Thu, 21 Jan 2021 16:10:10 +0100 Subject: [PATCH 036/304] dnsapi/ionos: Change to root zone finding algorithm --- dnsapi/dns_ionos.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_ionos.sh b/dnsapi/dns_ionos.sh index 54696d5d..e6bd5000 100755 --- a/dnsapi/dns_ionos.sh +++ b/dnsapi/dns_ionos.sh @@ -92,7 +92,7 @@ _ionos_init() { _get_root() { domain=$1 - i=2 + i=1 p=1 if _ionos_rest GET "$IONOS_ROUTE_ZONES"; then From 51d31d82cbd6f6bf08315286e82a05d67f8f5e92 Mon Sep 17 00:00:00 2001 From: MaysWind Date: Thu, 21 Jan 2021 22:15:23 +0800 Subject: [PATCH 037/304] update dnspod.com api --- dnsapi/dns_dpi.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dnsapi/dns_dpi.sh b/dnsapi/dns_dpi.sh index 9cbf4d51..2955effd 100755 --- a/dnsapi/dns_dpi.sh +++ b/dnsapi/dns_dpi.sh @@ -53,7 +53,7 @@ dns_dpi_rm() { return 1 fi - if ! _rest POST "Record.List" "user_token=$DPI_Id,$DPI_Key&format=json&domain_id=$_domain_id&sub_domain=$_sub_domain"; then + if ! _rest POST "Record.List" "login_token=$DPI_Id,$DPI_Key&format=json&domain_id=$_domain_id&sub_domain=$_sub_domain"; then _err "Record.Lis error." return 1 fi @@ -63,14 +63,14 @@ dns_dpi_rm() { return 0 fi - record_id=$(echo "$response" | _egrep_o '{[^{]*"value":"'"$txtvalue"'"' | cut -d , -f 1 | cut -d : -f 2 | tr -d \") + record_id=$(echo "$response" | tr "{" "\n" | grep -- "$txtvalue" | grep '^"id"' | cut -d : -f 2 | cut -d '"' -f 2) _debug record_id "$record_id" if [ -z "$record_id" ]; then _err "Can not get record id." return 1 fi - if ! _rest POST "Record.Remove" "user_token=$DPI_Id,$DPI_Key&format=json&domain_id=$_domain_id&record_id=$record_id"; then + if ! _rest POST "Record.Remove" "login_token=$DPI_Id,$DPI_Key&format=json&domain_id=$_domain_id&record_id=$record_id"; then _err "Record.Remove error." return 1 fi @@ -89,7 +89,7 @@ add_record() { _info "Adding record" - if ! _rest POST "Record.Create" "user_token=$DPI_Id,$DPI_Key&format=json&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=default"; then + if ! _rest POST "Record.Create" "login_token=$DPI_Id,$DPI_Key&format=json&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=default"; then return 1 fi @@ -113,7 +113,7 @@ _get_root() { return 1 fi - if ! _rest POST "Domain.Info" "user_token=$DPI_Id,$DPI_Key&format=json&domain=$h"; then + if ! _rest POST "Domain.Info" "login_token=$DPI_Id,$DPI_Key&format=json&domain=$h"; then return 1 fi From ae670315f65e24a3c69ae73faa0d40631c521e3d Mon Sep 17 00:00:00 2001 From: dgasaway Date: Mon, 25 Jan 2021 11:46:52 -0800 Subject: [PATCH 038/304] Change ipconfig.co to ifconfig.co URL https://ipconfig.co/ip does not currently work, and since https://ifconfig.co/ip is mentioned on the DNS API wiki page, I assume these messages were a typo. --- dnsapi/dns_namecheap.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index 2e389265..7ce39fa9 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -157,7 +157,7 @@ _namecheap_set_publicip() { if [ -z "$NAMECHEAP_SOURCEIP" ]; then _err "No Source IP specified for Namecheap API." - _err "Use your public ip address or an url to retrieve it (e.g. https://ipconfig.co/ip) and export it as NAMECHEAP_SOURCEIP" + _err "Use your public ip address or an url to retrieve it (e.g. https://ifconfig.co/ip) and export it as NAMECHEAP_SOURCEIP" return 1 else _saveaccountconf NAMECHEAP_SOURCEIP "$NAMECHEAP_SOURCEIP" @@ -175,7 +175,7 @@ _namecheap_set_publicip() { _publicip=$(_get "$addr") else _err "No Source IP specified for Namecheap API." - _err "Use your public ip address or an url to retrieve it (e.g. https://ipconfig.co/ip) and export it as NAMECHEAP_SOURCEIP" + _err "Use your public ip address or an url to retrieve it (e.g. https://ifconfig.co/ip) and export it as NAMECHEAP_SOURCEIP" return 1 fi fi From bbb8c133efee596c37836c90ab0573a4d4745c8e Mon Sep 17 00:00:00 2001 From: neil Date: Tue, 26 Jan 2021 22:10:53 +0800 Subject: [PATCH 039/304] fix docker build (#3383) * fix dockerhub * fix Co-authored-by: neil --- .github/workflows/dockerhub.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/dockerhub.yml b/.github/workflows/dockerhub.yml index 89915af7..238fde3a 100644 --- a/.github/workflows/dockerhub.yml +++ b/.github/workflows/dockerhub.yml @@ -33,12 +33,10 @@ jobs: steps: - name: checkout code uses: actions/checkout@v2 - - name: install buildx - id: buildx - uses: crazy-max/ghaction-docker-buildx@v3 - with: - buildx-version: latest - qemu-version: latest + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 - name: login to docker hub run: | echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin From 8d035858ffb5f648fb70a93d9e3bfd7f30f17553 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 30 Jan 2021 11:27:18 +0800 Subject: [PATCH 040/304] fix online install (#3385) --- acme.sh | 59 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/acme.sh b/acme.sh index ba52f409..4cedc28b 100755 --- a/acme.sh +++ b/acme.sh @@ -6107,7 +6107,7 @@ _installalias() { } -# nocron confighome noprofile +# nocron confighome noprofile accountemail install() { if [ -z "$LE_WORKING_DIR" ]; then @@ -6117,6 +6117,8 @@ install() { _nocron="$1" _c_home="$2" _noprofile="$3" + _accountemail="$4" + if ! _initpath; then _err "Install failed." return 1 @@ -6235,6 +6237,10 @@ install() { fi fi + if [ "$_accountemail" ]; then + _saveaccountconf "ACCOUNT_EMAIL" "$_accountemail" + fi + _info OK } @@ -6513,7 +6519,7 @@ Parameters: --cert-home Specifies the home dir to save all the certs, only valid for '--install' command. --config-home Specifies the home dir to save all the configurations. --useragent Specifies the user agent string. it will be saved for future use too. - -m, --accountemail Specifies the account email, only valid for the '--install' and '--update-account' command. + -m, --email Specifies the account email, only valid for the '--install' and '--update-account' command. --accountkey Specifies the account key path, only valid for the '--install' command. --days Specifies the days to renew the cert when using '--issue' command. The default value is $DEFAULT_RENEW days. --httpport Specifies the standalone listening port. Only valid if the server is behind a reverse proxy or load balancer. @@ -6524,9 +6530,9 @@ Parameters: --insecure Do not check the server certificate, in some devices, the api server's certificate may not be trusted. --ca-bundle Specifies the path to the CA certificate bundle to verify api server's certificate. --ca-path Specifies directory containing CA certificates in PEM format, used by wget or curl. - --nocron Only valid for '--install' command, which means: do not install the default cron job. + --no-cron Only valid for '--install' command, which means: do not install the default cron job. In this case, the certs will not be renewed automatically. - --noprofile Only valid for '--install' command, which means: do not install aliases to user profile. + --no-profile Only valid for '--install' command, which means: do not install aliases to user profile. --no-color Do not output color text. --force-color Force output of color text. Useful for non-interactive use with the aha tool for HTML E-Mails. --ecc Specifies to use the ECC cert. Valid for '--install-cert', '--renew', '--revoke', '--to-pkcs12' and '--create-csr' @@ -6564,18 +6570,18 @@ Parameters: " } -# nocron noprofile -_installOnline() { + +installOnline() { _info "Installing from online archive." - _nocron="$1" - _noprofile="$2" - if [ ! "$BRANCH" ]; then - BRANCH="master" + + _branch="$BRANCH" + if [ -z "$_branch" ]; then + _branch="master" fi - target="$PROJECT/archive/$BRANCH.tar.gz" + target="$PROJECT/archive/$_branch.tar.gz" _info "Downloading $target" - localname="$BRANCH.tar.gz" + localname="$_branch.tar.gz" if ! _get "$target" >$localname; then _err "Download error." return 1 @@ -6587,9 +6593,9 @@ _installOnline() { exit 1 fi - cd "$PROJECT_NAME-$BRANCH" + cd "$PROJECT_NAME-$_branch" chmod +x $PROJECT_ENTRY - if ./$PROJECT_ENTRY install "$_nocron" "" "$_noprofile"; then + if ./$PROJECT_ENTRY --install "$@"; then _info "Install success!" _initpath _saveaccountconf "UPGRADE_HASH" "$(_getUpgradeHash)" @@ -6597,7 +6603,7 @@ _installOnline() { cd .. - rm -rf "$PROJECT_NAME-$BRANCH" + rm -rf "$PROJECT_NAME-$_branch" rm -f "$localname" ) } @@ -6625,7 +6631,7 @@ upgrade() { [ -z "$FORCE" ] && [ "$(_getUpgradeHash)" = "$(_readaccountconf "UPGRADE_HASH")" ] && _info "Already uptodate!" && exit 0 export LE_WORKING_DIR cd "$LE_WORKING_DIR" - _installOnline "nocron" "noprofile" + installOnline "--nocron" "--noprofile" ); then _info "Upgrade success!" exit 0 @@ -6805,6 +6811,11 @@ _process() { --install) _CMD="install" ;; + --install-online) + shift + installOnline "$@" + return + ;; --uninstall) _CMD="uninstall" ;; @@ -7079,9 +7090,9 @@ _process() { USER_AGENT="$_useragent" shift ;; - -m | --accountemail) + -m | --email | --accountemail) _accountemail="$2" - ACCOUNT_EMAIL="$_accountemail" + export ACCOUNT_EMAIL="$_accountemail" shift ;; --accountkey) @@ -7124,10 +7135,10 @@ _process() { CA_PATH="$_ca_path" shift ;; - --nocron) + --no-cron | --nocron) _nocron="1" ;; - --noprofile) + --no-profile | --noprofile) _noprofile="1" ;; --no-color) @@ -7347,7 +7358,7 @@ _process() { fi _debug "Running cmd: ${_CMD}" case "${_CMD}" in - install) install "$_nocron" "$_confighome" "$_noprofile" ;; + install) install "$_nocron" "$_confighome" "$_noprofile" "$_accountemail" ;; uninstall) uninstall "$_nocron" ;; upgrade) upgrade ;; issue) @@ -7460,12 +7471,6 @@ _process() { } -if [ "$INSTALLONLINE" ]; then - INSTALLONLINE="" - _installOnline - exit -fi - main() { [ -z "$1" ] && showhelp && return if _startswith "$1" '-'; then _process "$@"; else "$@"; fi From 5651d4da6262f98b962ad3d3c01755c4a4ea537b Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 30 Jan 2021 11:44:42 +0800 Subject: [PATCH 041/304] update readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f53578d4..edd6442f 100644 --- a/README.md +++ b/README.md @@ -110,13 +110,13 @@ https://github.com/acmesh-official/acmetest Check this project: https://github.com/acmesh-official/get.acme.sh ```bash -curl https://get.acme.sh | sh +curl https://get.acme.sh | sh -s email=my@example.com ``` Or: ```bash -wget -O - https://get.acme.sh | sh +wget -O - https://get.acme.sh | sh -s email=my@example.com ``` @@ -127,7 +127,7 @@ Clone this project and launch installation: ```bash git clone https://github.com/acmesh-official/acme.sh.git cd ./acme.sh -./acme.sh --install +./acme.sh --install -m my@example.com ``` You `don't have to be root` then, although `it is recommended`. From ce661b100c91cd380aad012f5ef007ec354856e6 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 30 Jan 2021 12:05:23 +0800 Subject: [PATCH 042/304] fix format --- acme.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/acme.sh b/acme.sh index 4cedc28b..21fd6a8f 100755 --- a/acme.sh +++ b/acme.sh @@ -6570,7 +6570,6 @@ Parameters: " } - installOnline() { _info "Installing from online archive." From 88997ef84960ead310206ce5c4480d64bfe861f2 Mon Sep 17 00:00:00 2001 From: Vahid Fardi Date: Tue, 5 Jan 2021 15:29:08 +0330 Subject: [PATCH 043/304] change arvan api script --- dnsapi/dns_arvan.sh | 43 +++++++++++++++---------------------------- 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/dnsapi/dns_arvan.sh b/dnsapi/dns_arvan.sh index ca1f56c7..3c4ced15 100644 --- a/dnsapi/dns_arvan.sh +++ b/dnsapi/dns_arvan.sh @@ -3,7 +3,6 @@ #Arvan_Token="xxxx" ARVAN_API_URL="https://napi.arvancloud.com/cdn/4.0/domains" - #Author: Ehsan Aliakbar #Report Bugs here: https://github.com/Neilpang/acme.sh # @@ -38,6 +37,7 @@ dns_arvan_add() { _info "Adding record" if _arvan_rest POST "$_domain/dns-records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":{\"text\":\"$txtvalue\"},\"ttl\":120}"; then if _contains "$response" "$txtvalue"; then + _info "response id is $response" _info "Added, OK" return 0 elif _contains "$response" "Record Data is Duplicated"; then @@ -49,7 +49,7 @@ dns_arvan_add() { fi fi _err "Add txt record error." - return 1 + return 0 } #Usage: fulldomain txtvalue @@ -73,33 +73,21 @@ dns_arvan_rm() { _debug _domain "$_domain" _debug "Getting txt records" - shorted_txtvalue=$(printf "%s" "$txtvalue" | cut -d "-" -d "_" -f1) - _arvan_rest GET "${_domain}/dns-records?search=$shorted_txtvalue" - + _arvan_rest GET "${_domain}/dns-records" if ! printf "%s" "$response" | grep \"current_page\":1 >/dev/null; then _err "Error on Arvan Api" _err "Please create a github issue with debbug log" return 1 fi - count=$(printf "%s\n" "$response" | _egrep_o "\"total\":[^,]*" | cut -d : -f 2) - _debug count "$count" - if [ "$count" = "0" ]; then - _info "Don't need to remove." - else - record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1) - _debug "record_id" "$record_id" - if [ -z "$record_id" ]; then - _err "Can not get record id to remove." - return 1 - fi - if ! _arvan_rest "DELETE" "${_domain}/dns-records/$record_id"; then - _err "Delete record error." - return 1 - fi - _debug "$response" - _contains "$response" 'dns record deleted' + _record_id=$(echo "$response" | _egrep_o ".\"id\":\"[^\"]*\",\"type\":\"txt\",\"name\":\"_acme-challenge\",\"value\":{\"text\":\"$txtvalue\"}" | cut -d : -f 2 | cut -d , -f 1 | tr -d \") + if ! _arvan_rest "DELETE" "${_domain}/dns-records/${_record_id}"; then + _err "Error on Arvan Api" + return 1 fi + _debug "$response" + _contains "$response" 'dns record deleted' + return 0 } #################### Private functions below ################################## @@ -111,7 +99,7 @@ dns_arvan_rm() { # _domain_id=sdjkglgdfewsdfg _get_root() { domain=$1 - i=1 + i=2 p=1 while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) @@ -121,12 +109,11 @@ _get_root() { return 1 fi - if ! _arvan_rest GET "?search=$h"; then + if ! _arvan_rest GET "$h"; then return 1 fi - - if _contains "$response" "\"domain\":\"$h\"" || _contains "$response" '"total":1'; then - _domain_id=$(echo "$response" | _egrep_o "\[.\"id\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \") + if _contains "$response" "\"domain\":\"$h\""; then + _domain_id=$(echo "$response" | cut -d : -f 3 | cut -d , -f 1 | tr -d \") if [ "$_domain_id" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain=$h @@ -146,7 +133,6 @@ _arvan_rest() { data="$3" token_trimmed=$(echo "$Arvan_Token" | tr -d '"') - export _H1="Authorization: $token_trimmed" if [ "$mtd" = "DELETE" ]; then @@ -160,4 +146,5 @@ _arvan_rest() { else response="$(_get "$ARVAN_API_URL/$ep$data")" fi + return 0 } From dcf466695c36167b67bf96deb88e2f81ae60bce4 Mon Sep 17 00:00:00 2001 From: Vahid Fardi Date: Tue, 5 Jan 2021 17:10:41 +0330 Subject: [PATCH 044/304] change Author name --- dnsapi/dns_arvan.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_arvan.sh b/dnsapi/dns_arvan.sh index 3c4ced15..a33504d0 100644 --- a/dnsapi/dns_arvan.sh +++ b/dnsapi/dns_arvan.sh @@ -1,10 +1,10 @@ #!/usr/bin/env sh -#Arvan_Token="xxxx" +#Arvan_Token="Apikey xxxx" ARVAN_API_URL="https://napi.arvancloud.com/cdn/4.0/domains" -#Author: Ehsan Aliakbar -#Report Bugs here: https://github.com/Neilpang/acme.sh +#Author: Vahid Fardi +#Report Bugs here: https://github.com/fvahid/acme.sh # ######## Public functions ##################### From ad87b4b0c013a932bc389e9f4ca5ada224972175 Mon Sep 17 00:00:00 2001 From: Vahid Fardi Date: Tue, 5 Jan 2021 21:31:31 +0330 Subject: [PATCH 045/304] change name actor --- dnsapi/dns_arvan.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_arvan.sh b/dnsapi/dns_arvan.sh index a33504d0..4c9217e5 100644 --- a/dnsapi/dns_arvan.sh +++ b/dnsapi/dns_arvan.sh @@ -4,7 +4,7 @@ ARVAN_API_URL="https://napi.arvancloud.com/cdn/4.0/domains" #Author: Vahid Fardi -#Report Bugs here: https://github.com/fvahid/acme.sh +#Report Bugs here: https://github.com/Neilpang/acme.sh # ######## Public functions ##################### From f27ddc9c408743d5e9b1b3e55ed62f0930511684 Mon Sep 17 00:00:00 2001 From: manuel Date: Thu, 11 Feb 2021 11:20:18 +0100 Subject: [PATCH 046/304] dnsapi/pdns: also normalize json response in detecting root zone --- dnsapi/dns_pdns.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_pdns.sh b/dnsapi/dns_pdns.sh index 8f07e8c4..28b35492 100755 --- a/dnsapi/dns_pdns.sh +++ b/dnsapi/dns_pdns.sh @@ -175,13 +175,13 @@ _get_root() { i=1 if _pdns_rest "GET" "/api/v1/servers/$PDNS_ServerId/zones"; then - _zones_response="$response" + _zones_response=$(echo "$response" | _normalizeJson) fi while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) - if _contains "$_zones_response" "\"name\": \"$h.\""; then + if _contains "$_zones_response" "\"name\":\"$h.\""; then _domain="$h." if [ -z "$h" ]; then _domain="=2E" From 1c2e031153ee2dc3ceaf17e0f5c661aff5a45bc5 Mon Sep 17 00:00:00 2001 From: Gnought <1684105+gnought@users.noreply.github.com> Date: Thu, 11 Feb 2021 01:08:08 +0800 Subject: [PATCH 047/304] Updated --preferred-chain to issue ISRG properly To support different openssl crl2pkcs7 help cli format --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 21fd6a8f..47603e3b 100755 --- a/acme.sh +++ b/acme.sh @@ -4013,7 +4013,7 @@ _check_dns_entries() { #file _get_cert_issuers() { _cfile="$1" - if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then + if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -help 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 else ${ACME_OPENSSL_BIN:-openssl} x509 -in $_cfile -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 From b80d8f4d2d6323b5f6e2f02431820cdb724a3323 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 13 Feb 2021 16:22:31 +0800 Subject: [PATCH 048/304] Chain (#3408) * fix https://github.com/acmesh-official/acme.sh/issues/3384 match the issuer to the root CA cert subject * fix format * fix https://github.com/acmesh-official/acme.sh/issues/3384 * remove the alt files. https://github.com/acmesh-official/acme.sh/issues/3384 --- acme.sh | 58 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/acme.sh b/acme.sh index 47603e3b..c76fabb8 100755 --- a/acme.sh +++ b/acme.sh @@ -4011,12 +4011,42 @@ _check_dns_entries() { } #file -_get_cert_issuers() { +_get_chain_issuers() { _cfile="$1" if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -help 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then - ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 + ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep -i 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 else - ${ACME_OPENSSL_BIN:-openssl} x509 -in $_cfile -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 + _cindex=1 + for _startn in $(grep -n -- "$BEGIN_CERT" "$_cfile" | cut -d : -f 1); do + _endn="$(grep -n -- "$END_CERT" "$_cfile" | cut -d : -f 1 | _head_n $_cindex | _tail_n 1)" + _debug2 "_startn" "$_startn" + _debug2 "_endn" "$_endn" + if [ "$DEBUG" ]; then + _debug2 "cert$_cindex" "$(sed -n "$_startn,${_endn}p" "$_cfile")" + fi + sed -n "$_startn,${_endn}p" "$_cfile" | ${ACME_OPENSSL_BIN:-openssl} x509 -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 | sed "s/ *\(.*\)/\1/" + _cindex=$(_math $_cindex + 1) + done + fi +} + +# +_get_chain_subjects() { + _cfile="$1" + if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -help 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then + ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep -i 'Subject:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 + else + _cindex=1 + for _startn in $(grep -n -- "$BEGIN_CERT" "$_cfile" | cut -d : -f 1); do + _endn="$(grep -n -- "$END_CERT" "$_cfile" | cut -d : -f 1 | _head_n $_cindex | _tail_n 1)" + _debug2 "_startn" "$_startn" + _debug2 "_endn" "$_endn" + if [ "$DEBUG" ]; then + _debug2 "cert$_cindex" "$(sed -n "$_startn,${_endn}p" "$_cfile")" + fi + sed -n "$_startn,${_endn}p" "$_cfile" | ${ACME_OPENSSL_BIN:-openssl} x509 -text -noout | grep -i 'Subject:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 | sed "s/ *\(.*\)/\1/" + _cindex=$(_math $_cindex + 1) + done fi } @@ -4024,14 +4054,12 @@ _get_cert_issuers() { _match_issuer() { _cfile="$1" _missuer="$2" - _fissuers="$(_get_cert_issuers $_cfile)" + _fissuers="$(_get_chain_issuers $_cfile)" _debug2 _fissuers "$_fissuers" - if _contains "$_fissuers" "$_missuer"; then - return 0 - fi - _fissuers="$(echo "$_fissuers" | _lower_case)" + _rootissuer="$(echo "$_fissuers" | _lower_case | _tail_n 1)" + _debug2 _rootissuer "$_rootissuer" _missuer="$(echo "$_missuer" | _lower_case)" - _contains "$_fissuers" "$_missuer" + _contains "$_rootissuer" "$_missuer" } #webroot, domain domainlist keylength @@ -4805,6 +4833,9 @@ $_authorizations_map" _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" @@ -4820,13 +4851,22 @@ $_authorizations_map" _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 + rm -f "$_relcert" + rm -f "$_relfullchain" + rm -f "$_relca" done fi fi From bb10f748b1803adaf66c4a06471157e7fdfae60b Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 13 Feb 2021 17:27:22 +0800 Subject: [PATCH 049/304] upgrade freebsd and solaris --- .github/workflows/LetsEncrypt.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 8d0c4eb0..7c398c09 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -111,7 +111,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.0.7 + - uses: vmactions/freebsd-vm@v0.1.2 with: envs: 'NGROK_TOKEN TEST_LOCAL' prepare: pkg install -y socat curl @@ -136,7 +136,7 @@ jobs: run: echo "TestingDomain=${{steps.ngrok.outputs.server}}" >> $GITHUB_ENV - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/solaris-vm@v0.0.1 + - uses: vmactions/solaris-vm@v0.0.3 with: envs: 'TEST_LOCAL TestingDomain' nat: | From b6211858674c3545e57a428a9f0d193437e2f9d5 Mon Sep 17 00:00:00 2001 From: jerrm Date: Sat, 13 Feb 2021 05:58:44 -0500 Subject: [PATCH 050/304] duckdns - fix "integer expression expected" errors (#3397) * fix "integer expression expected" errors * duckdns fix * Update dns_duckdns.sh * Update dns_duckdns.sh --- dnsapi/dns_duckdns.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index 618e12c6..d6e1dbdc 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -12,7 +12,7 @@ DuckDNS_API="https://www.duckdns.org/update" -######## Public functions ##################### +######## Public functions ###################### #Usage: dns_duckdns_add _acme-challenge.domain.duckdns.org "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_duckdns_add() { @@ -112,7 +112,7 @@ _duckdns_rest() { param="$2" _debug param "$param" url="$DuckDNS_API?$param" - if [ "$DEBUG" -gt 0 ]; then + if [ -n "$DEBUG" ] && [ "$DEBUG" -gt 0 ]; then url="$url&verbose=true" fi _debug url "$url" @@ -121,7 +121,7 @@ _duckdns_rest() { if [ "$method" = "GET" ]; then response="$(_get "$url")" _debug2 response "$response" - if [ "$DEBUG" -gt 0 ] && _contains "$response" "UPDATED" && _contains "$response" "OK"; then + if [ -n "$DEBUG" ] && [ "$DEBUG" -gt 0 ] && _contains "$response" "UPDATED" && _contains "$response" "OK"; then response="OK" fi else From 81751c0aa91a30eeb404eeab360c69792a000dd7 Mon Sep 17 00:00:00 2001 From: Mike Edmunds Date: Sun, 14 Feb 2021 23:01:21 -0800 Subject: [PATCH 051/304] Fix: Unifi deploy hook support Unifi Cloud Key (#3327) * fix: unifi deploy hook also update Cloud Key nginx certs When running on a Unifi Cloud Key device, also deploy to /etc/ssl/private/cloudkey.{crt,key} and reload nginx. This makes the new cert available for the Cloud Key management app running via nginx on port 443 (as well as the port 8443 Unifi Controller app the deploy hook already supported). Fixes #3326 * Improve settings documentation comments * Improve Cloud Key pre-flight error messaging * Fix typo * Add support for UnifiOS (Cloud Key Gen2) Since UnifiOS does not use the Java keystore (like a Unifi Controller or Cloud Key Gen1 deploy), this also reworks the settings validation and error messaging somewhat. * PR review fixes * Detect unsupported Cloud Key java keystore location * Don't try to restart inactive services (and remove extra spaces from reload command) * Clean up error messages and internal variables * Change to _getdeployconf/_savedeployconf * Switch from cp to cat to preserve file permissions --- deploy/unifi.sh | 220 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 167 insertions(+), 53 deletions(-) diff --git a/deploy/unifi.sh b/deploy/unifi.sh index 184aa62e..a864135e 100644 --- a/deploy/unifi.sh +++ b/deploy/unifi.sh @@ -1,12 +1,43 @@ #!/usr/bin/env sh -#Here is a script to deploy cert to unifi server. +# Here is a script to deploy cert on a Unifi Controller or Cloud Key device. +# It supports: +# - self-hosted Unifi Controller +# - Unifi Cloud Key (Gen1/2/2+) +# - Unifi Cloud Key running UnifiOS (v2.0.0+, Gen2/2+ only) +# Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3359 #returns 0 means success, otherwise error. +# The deploy-hook automatically detects standard Unifi installations +# for each of the supported environments. Most users should not need +# to set any of these variables, but if you are running a self-hosted +# Controller with custom locations, set these as necessary before running +# the deploy hook. (Defaults shown below.) +# +# Settings for Unifi Controller: +# Location of Java keystore or unifi.keystore.jks file: #DEPLOY_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore" +# Keystore password (built into Unifi Controller, not a user-set password): #DEPLOY_UNIFI_KEYPASS="aircontrolenterprise" +# Command to restart Unifi Controller: #DEPLOY_UNIFI_RELOAD="service unifi restart" +# +# Settings for Unifi Cloud Key Gen1 (nginx admin pages): +# Directory where cloudkey.crt and cloudkey.key live: +#DEPLOY_UNIFI_CLOUDKEY_CERTDIR="/etc/ssl/private" +# Command to restart maintenance pages and Controller +# (same setting as above, default is updated when running on Cloud Key Gen1): +#DEPLOY_UNIFI_RELOAD="service nginx restart && service unifi restart" +# +# Settings for UnifiOS (Cloud Key Gen2): +# Directory where unifi-core.crt and unifi-core.key live: +#DEPLOY_UNIFI_CORE_CONFIG="/data/unifi-core/config/" +# Command to restart unifi-core: +#DEPLOY_UNIFI_RELOAD="systemctl restart unifi-core" +# +# At least one of DEPLOY_UNIFI_KEYSTORE, DEPLOY_UNIFI_CLOUDKEY_CERTDIR, +# or DEPLOY_UNIFI_CORE_CONFIG must exist to receive the deployed certs. ######## Public functions ##################### @@ -24,77 +55,160 @@ unifi_deploy() { _debug _cca "$_cca" _debug _cfullchain "$_cfullchain" - if ! _exists keytool; then - _err "keytool not found" - return 1 - fi + _getdeployconf DEPLOY_UNIFI_KEYSTORE + _getdeployconf DEPLOY_UNIFI_KEYPASS + _getdeployconf DEPLOY_UNIFI_CLOUDKEY_CERTDIR + _getdeployconf DEPLOY_UNIFI_CORE_CONFIG + _getdeployconf DEPLOY_UNIFI_RELOAD + + _debug2 DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" + _debug2 DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" + _debug2 DEPLOY_UNIFI_CLOUDKEY_CERTDIR "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" + _debug2 DEPLOY_UNIFI_CORE_CONFIG "$DEPLOY_UNIFI_CORE_CONFIG" + _debug2 DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" + + # Space-separated list of environments detected and installed: + _services_updated="" + + # Default reload commands accumulated as we auto-detect environments: + _reload_cmd="" + + # Unifi Controller environment (self hosted or any Cloud Key) -- + # auto-detect by file /usr/lib/unifi/data/keystore: + _unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-/usr/lib/unifi/data/keystore}" + if [ -f "$_unifi_keystore" ]; then + _info "Installing certificate for Unifi Controller (Java keystore)" + _debug _unifi_keystore "$_unifi_keystore" + if ! _exists keytool; then + _err "keytool not found" + return 1 + fi + if [ ! -w "$_unifi_keystore" ]; then + _err "The file $_unifi_keystore is not writable, please change the permission." + return 1 + fi + + _unifi_keypass="${DEPLOY_UNIFI_KEYPASS:-aircontrolenterprise}" - DEFAULT_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore" - _unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-$DEFAULT_UNIFI_KEYSTORE}" - DEFAULT_UNIFI_KEYPASS="aircontrolenterprise" - _unifi_keypass="${DEPLOY_UNIFI_KEYPASS:-$DEFAULT_UNIFI_KEYPASS}" - DEFAULT_UNIFI_RELOAD="service unifi restart" - _reload="${DEPLOY_UNIFI_RELOAD:-$DEFAULT_UNIFI_RELOAD}" - - _debug _unifi_keystore "$_unifi_keystore" - if [ ! -f "$_unifi_keystore" ]; then - if [ -z "$DEPLOY_UNIFI_KEYSTORE" ]; then - _err "unifi keystore is not found, please define DEPLOY_UNIFI_KEYSTORE" + _debug "Generate import pkcs12" + _import_pkcs12="$(_mktemp)" + _toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root + # shellcheck disable=SC2181 + if [ "$?" != "0" ]; then + _err "Error generating pkcs12. Please re-run with --debug and report a bug." return 1 + fi + + _debug "Import into keystore: $_unifi_keystore" + if keytool -importkeystore \ + -deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \ + -srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \ + -alias unifi -noprompt; then + _debug "Import keystore success!" + rm "$_import_pkcs12" else - _err "It seems that the specified unifi keystore is not valid, please check." + _err "Error importing into Unifi Java keystore." + _err "Please re-run with --debug and report a bug." + rm "$_import_pkcs12" return 1 fi + + if systemctl -q is-active unifi; then + _reload_cmd="${_reload_cmd:+$_reload_cmd && }service unifi restart" + fi + _services_updated="${_services_updated} unifi" + _info "Install Unifi Controller certificate success!" + elif [ "$DEPLOY_UNIFI_KEYSTORE" ]; then + _err "The specified DEPLOY_UNIFI_KEYSTORE='$DEPLOY_UNIFI_KEYSTORE' is not valid, please check." + return 1 fi - if [ ! -w "$_unifi_keystore" ]; then - _err "The file $_unifi_keystore is not writable, please change the permission." + + # Cloud Key environment (non-UnifiOS -- nginx serves admin pages) -- + # auto-detect by file /etc/ssl/private/cloudkey.key: + _cloudkey_certdir="${DEPLOY_UNIFI_CLOUDKEY_CERTDIR:-/etc/ssl/private}" + if [ -f "${_cloudkey_certdir}/cloudkey.key" ]; then + _info "Installing certificate for Cloud Key Gen1 (nginx admin pages)" + _debug _cloudkey_certdir "$_cloudkey_certdir" + if [ ! -w "$_cloudkey_certdir" ]; then + _err "The directory $_cloudkey_certdir is not writable; please check permissions." + return 1 + fi + # Cloud Key expects to load the keystore from /etc/ssl/private/unifi.keystore.jks. + # Normally /usr/lib/unifi/data/keystore is a symlink there (so the keystore was + # updated above), but if not, we don't know how to handle this installation: + if ! cmp -s "$_unifi_keystore" "${_cloudkey_certdir}/unifi.keystore.jks"; then + _err "Unsupported Cloud Key configuration: keystore not found at '${_cloudkey_certdir}/unifi.keystore.jks'" + return 1 + fi + + cat "$_cfullchain" >"${_cloudkey_certdir}/cloudkey.crt" + cat "$_ckey" >"${_cloudkey_certdir}/cloudkey.key" + (cd "$_cloudkey_certdir" && tar -cf cert.tar cloudkey.crt cloudkey.key unifi.keystore.jks) + + if systemctl -q is-active nginx; then + _reload_cmd="${_reload_cmd:+$_reload_cmd && }service nginx restart" + fi + _info "Install Cloud Key Gen1 certificate success!" + _services_updated="${_services_updated} nginx" + elif [ "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" ]; then + _err "The specified DEPLOY_UNIFI_CLOUDKEY_CERTDIR='$DEPLOY_UNIFI_CLOUDKEY_CERTDIR' is not valid, please check." return 1 fi - _info "Generate import pkcs12" - _import_pkcs12="$(_mktemp)" - _toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root - if [ "$?" != "0" ]; then - _err "Oops, error creating import pkcs12, please report bug to us." + # UnifiOS environment -- auto-detect by /data/unifi-core/config/unifi-core.key: + _unifi_core_config="${DEPLOY_UNIFI_CORE_CONFIG:-/data/unifi-core/config}" + if [ -f "${_unifi_core_config}/unifi-core.key" ]; then + _info "Installing certificate for UnifiOS" + _debug _unifi_core_config "$_unifi_core_config" + if [ ! -w "$_unifi_core_config" ]; then + _err "The directory $_unifi_core_config is not writable; please check permissions." + return 1 + fi + + cat "$_cfullchain" >"${_unifi_core_config}/unifi-core.crt" + cat "$_ckey" >"${_unifi_core_config}/unifi-core.key" + + if systemctl -q is-active unifi-core; then + _reload_cmd="${_reload_cmd:+$_reload_cmd && }systemctl restart unifi-core" + fi + _info "Install UnifiOS certificate success!" + _services_updated="${_services_updated} unifi-core" + elif [ "$DEPLOY_UNIFI_CORE_CONFIG" ]; then + _err "The specified DEPLOY_UNIFI_CORE_CONFIG='$DEPLOY_UNIFI_CORE_CONFIG' is not valid, please check." return 1 fi - _info "Modify unifi keystore: $_unifi_keystore" - if keytool -importkeystore \ - -deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \ - -srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \ - -alias unifi -noprompt; then - _info "Import keystore success!" - rm "$_import_pkcs12" - else - _err "Import unifi keystore error, please report bug to us." - rm "$_import_pkcs12" + if [ -z "$_services_updated" ]; then + # None of the Unifi environments were auto-detected, so no deployment has occurred + # (and none of DEPLOY_UNIFI_{KEYSTORE,CLOUDKEY_CERTDIR,CORE_CONFIG} were set). + _err "Unable to detect Unifi environment in standard location." + _err "(This deploy hook must be run on the Unifi device, not a remote machine.)" + _err "For non-standard Unifi installations, set DEPLOY_UNIFI_KEYSTORE," + _err "DEPLOY_UNIFI_CLOUDKEY_CERTDIR, and/or DEPLOY_UNIFI_CORE_CONFIG as appropriate." return 1 fi - _info "Run reload: $_reload" - if eval "$_reload"; then + _reload_cmd="${DEPLOY_UNIFI_RELOAD:-$_reload_cmd}" + if [ -z "$_reload_cmd" ]; then + _err "Certificates were installed for services:${_services_updated}," + _err "but none appear to be active. Please set DEPLOY_UNIFI_RELOAD" + _err "to a command that will restart the necessary services." + return 1 + fi + _info "Reload services (this may take some time): $_reload_cmd" + if eval "$_reload_cmd"; then _info "Reload success!" - if [ "$DEPLOY_UNIFI_KEYSTORE" ]; then - _savedomainconf DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" - else - _cleardomainconf DEPLOY_UNIFI_KEYSTORE - fi - if [ "$DEPLOY_UNIFI_KEYPASS" ]; then - _savedomainconf DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" - else - _cleardomainconf DEPLOY_UNIFI_KEYPASS - fi - if [ "$DEPLOY_UNIFI_RELOAD" ]; then - _savedomainconf DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" - else - _cleardomainconf DEPLOY_UNIFI_RELOAD - fi - return 0 else _err "Reload error" return 1 fi - return 0 + # Successful, so save all (non-default) config: + _savedeployconf DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" + _savedeployconf DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" + _savedeployconf DEPLOY_UNIFI_CLOUDKEY_CERTDIR "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" + _savedeployconf DEPLOY_UNIFI_CORE_CONFIG "$DEPLOY_UNIFI_CORE_CONFIG" + _savedeployconf DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" + + return 0 } From 2413baef557b9419f2e8154280e9c8f290f3fbc4 Mon Sep 17 00:00:00 2001 From: Easton Man Date: Mon, 15 Feb 2021 15:18:49 +0800 Subject: [PATCH 052/304] feat: add huaweicloud error handling --- dnsapi/dns_huaweicloud.sh | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_huaweicloud.sh b/dnsapi/dns_huaweicloud.sh index 74fec2a9..f7192725 100644 --- a/dnsapi/dns_huaweicloud.sh +++ b/dnsapi/dns_huaweicloud.sh @@ -5,7 +5,7 @@ # HUAWEICLOUD_ProjectID iam_api="https://iam.myhuaweicloud.com" -dns_api="https://dns.ap-southeast-1.myhuaweicloud.com" +dns_api="https://dns.ap-southeast-1.myhuaweicloud.com" # Should work ######## Public functions ##################### @@ -29,16 +29,27 @@ dns_huaweicloud_add() { return 1 fi + unset token # Clear token token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_ProjectID}")" - _debug2 "${token}" + if [ -z "${token}" ]; then # Check token + _err "dns_api(dns_huaweicloud): Error getting token." + return 1 + fi + _debug "Access token is: ${token}" + + unset zoneid zoneid="$(_get_zoneid "${token}" "${fulldomain}")" - _debug "${zoneid}" + if [ -z "${zoneid}" ]; then + _err "dns_api(dns_huaweicloud): Error getting zone id." + return 1 + fi + _debug "Zone ID is: ${zoneid}" _debug "Adding Record" _add_record "${token}" "${fulldomain}" "${txtvalue}" ret="$?" if [ "${ret}" != "0" ]; then - _err "dns_huaweicloud: Error adding record." + _err "dns_api(dns_huaweicloud): Error adding record." return 1 fi @@ -69,12 +80,21 @@ dns_huaweicloud_rm() { return 1 fi + unset token # Clear token token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_ProjectID}")" - _debug2 "${token}" + if [ -z "${token}" ]; then # Check token + _err "dns_api(dns_huaweicloud): Error getting token." + return 1 + fi + _debug "Access token is: ${token}" + + unset zoneid zoneid="$(_get_zoneid "${token}" "${fulldomain}")" - _debug "${zoneid}" - record_id="$(_get_recordset_id "${token}" "${fulldomain}" "${zoneid}")" - _debug "Record Set ID is: ${record_id}" + if [ -z "${zoneid}" ]; then + _err "dns_api(dns_huaweicloud): Error getting zone id." + return 1 + fi + _debug "Zone ID is: ${zoneid}" # Remove all records # Therotically HuaweiCloud does not allow more than one record set From 5a6f672a6f10afb4c1ad6027a2556f0da664656a Mon Sep 17 00:00:00 2001 From: Easton Man Date: Mon, 15 Feb 2021 15:19:18 +0800 Subject: [PATCH 053/304] fix: fix freebsd and solaris --- .github/workflows/DNS.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 5dc2d453..ed0426ad 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -184,7 +184,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.0.7 + - uses: vmactions/freebsd-vm@v0.1.2 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkg install -y socat curl @@ -223,7 +223,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/solaris-vm@v0.0.1 + - uses: vmactions/solaris-vm@v0.0.3 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkgutil -y -i socat curl From 2b14a17c85442708bd8ffa3238892dbf07d056eb Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 15 Feb 2021 21:25:27 +0800 Subject: [PATCH 054/304] support openssl 3.0 fix https://github.com/acmesh-official/acme.sh/issues/3399 --- acme.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index c76fabb8..dbf13e95 100755 --- a/acme.sh +++ b/acme.sh @@ -1122,9 +1122,14 @@ _createkey() { fi fi + __traditional="" + if _contains "$(${ACME_OPENSSL_BIN:-openssl} help genrsa 2>&1)" "-traditional"; then + __traditional="-traditional" + fi + if _isEccKey "$length"; then _debug "Using ec name: $eccname" - if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -genkey 2>/dev/null)"; then + if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam $__traditional -name "$eccname" -genkey 2>/dev/null)"; then echo "$_opkey" >"$f" else _err "error ecc key name: $eccname" @@ -1132,7 +1137,7 @@ _createkey() { fi else _debug "Using RSA: $length" - if _opkey="$(${ACME_OPENSSL_BIN:-openssl} genrsa "$length" 2>/dev/null)"; then + if _opkey="$(${ACME_OPENSSL_BIN:-openssl} genrsa $__traditional "$length" 2>/dev/null)"; then echo "$_opkey" >"$f" else _err "error rsa key: $length" From 7597fb0566fdd53a0bd47db022bc6b55e5770470 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 15 Feb 2021 21:35:59 +0800 Subject: [PATCH 055/304] make the fix for rsa key only --- acme.sh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/acme.sh b/acme.sh index dbf13e95..920e21d4 100755 --- a/acme.sh +++ b/acme.sh @@ -1122,14 +1122,9 @@ _createkey() { fi fi - __traditional="" - if _contains "$(${ACME_OPENSSL_BIN:-openssl} help genrsa 2>&1)" "-traditional"; then - __traditional="-traditional" - fi - if _isEccKey "$length"; then _debug "Using ec name: $eccname" - if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam $__traditional -name "$eccname" -genkey 2>/dev/null)"; then + if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -genkey 2>/dev/null)"; then echo "$_opkey" >"$f" else _err "error ecc key name: $eccname" @@ -1137,6 +1132,10 @@ _createkey() { fi else _debug "Using RSA: $length" + __traditional="" + if _contains "$(${ACME_OPENSSL_BIN:-openssl} help genrsa 2>&1)" "-traditional"; then + __traditional="-traditional" + fi if _opkey="$(${ACME_OPENSSL_BIN:-openssl} genrsa $__traditional "$length" 2>/dev/null)"; then echo "$_opkey" >"$f" else From e770250bb934c0c591c78ce5ac86cd7c21d9c4e2 Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 29 Dec 2020 16:28:38 -0800 Subject: [PATCH 056/304] Implement smtp notify hook Support notifications via direct SMTP server connection. Uses Python (2.7.x or 3.4+) to communicate with SMTP server. --- notify/smtp.sh | 185 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 183 insertions(+), 2 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 6aa37ca3..367021c8 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -2,7 +2,103 @@ # support smtp +# This implementation uses Python (2 or 3), which is available in many environments. +# If you don't have Python, try "mail" notification instead of "smtp". + +# SMTP_FROM="from@example.com" # required +# SMTP_TO="to@example.com" # required +# SMTP_HOST="smtp.example.com" # required +# SMTP_PORT="25" # defaults to 25, 465 or 587 depending on SMTP_SECURE +# SMTP_SECURE="none" # one of "none", "ssl" (implicit TLS, TLS Wrapper), "tls" (explicit TLS, STARTTLS) +# SMTP_USERNAME="" # set if SMTP server requires login +# SMTP_PASSWORD="" # set if SMTP server requires login +# SMTP_TIMEOUT="15" # seconds for SMTP operations to timeout +# SMTP_PYTHON="/path/to/python" # defaults to system python3 or python + smtp_send() { + # Find a Python interpreter: + SMTP_PYTHON="${SMTP_PYTHON:-$(_readaccountconf_mutable SMTP_PYTHON)}" + if [ "$SMTP_PYTHON" ]; then + if _exists "$SMTP_PYTHON"; then + _saveaccountconf_mutable SMTP_PYTHON "$SMTP_PYTHON" + else + _err "SMTP_PYTHON '$SMTP_PYTHON' does not exist." + return 1 + fi + else + # No SMTP_PYTHON setting; try to run default Python. + # (This is not saved with the conf.) + if _exists python3; then + SMTP_PYTHON="python3" + elif _exists python; then + SMTP_PYTHON="python" + else + _err "Can't locate Python interpreter; please define SMTP_PYTHON." + return 1 + fi + fi + _debug "SMTP_PYTHON" "$SMTP_PYTHON" + _debug "Python version" "$($SMTP_PYTHON --version 2>&1)" + + # Validate other settings: + SMTP_FROM="${SMTP_FROM:-$(_readaccountconf_mutable SMTP_FROM)}" + if [ -z "$SMTP_FROM" ]; then + _err "You must define SMTP_FROM as the sender email address." + return 1 + fi + + SMTP_TO="${SMTP_TO:-$(_readaccountconf_mutable SMTP_TO)}" + if [ -z "$SMTP_TO" ]; then + _err "You must define SMTP_TO as the recipient email address." + return 1 + fi + + SMTP_HOST="${SMTP_HOST:-$(_readaccountconf_mutable SMTP_HOST)}" + if [ -z "$SMTP_HOST" ]; then + _err "You must define SMTP_HOST as the SMTP server hostname." + return 1 + fi + SMTP_PORT="${SMTP_PORT:-$(_readaccountconf_mutable SMTP_PORT)}" + + SMTP_SECURE="${SMTP_SECURE:-$(_readaccountconf_mutable SMTP_SECURE)}" + SMTP_SECURE="${SMTP_SECURE:-none}" + case "$SMTP_SECURE" in + "none") SMTP_DEFAULT_PORT="25";; + "ssl") SMTP_DEFAULT_PORT="465";; + "tls") SMTP_DEFAULT_PORT="587";; + *) + _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." + return 1 + ;; + esac + + SMTP_USERNAME="${SMTP_USERNAME:-$(_readaccountconf_mutable SMTP_USERNAME)}" + SMTP_PASSWORD="${SMTP_PASSWORD:-$(_readaccountconf_mutable SMTP_PASSWORD)}" + + SMTP_TIMEOUT="${SMTP_TIMEOUT:-$(_readaccountconf_mutable SMTP_TIMEOUT)}" + SMTP_DEFAULT_TIMEOUT="15" + + _saveaccountconf_mutable SMTP_FROM "$SMTP_FROM" + _saveaccountconf_mutable SMTP_TO "$SMTP_TO" + _saveaccountconf_mutable SMTP_HOST "$SMTP_HOST" + _saveaccountconf_mutable SMTP_PORT "$SMTP_PORT" + _saveaccountconf_mutable SMTP_SECURE "$SMTP_SECURE" + _saveaccountconf_mutable SMTP_USERNAME "$SMTP_USERNAME" + _saveaccountconf_mutable SMTP_PASSWORD "$SMTP_PASSWORD" + _saveaccountconf_mutable SMTP_TIMEOUT "$SMTP_TIMEOUT" + + # Send the message: + if ! _smtp_send "$@"; then + _err "$smtp_send_output" + return 1 + fi + + return 0 +} + +# _send subject content statuscode +# Send the message via Python using SMTP_* settings +_smtp_send() { _subject="$1" _content="$2" _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped @@ -10,6 +106,91 @@ smtp_send() { _debug "_content" "$_content" _debug "_statusCode" "$_statusCode" - _err "Not implemented yet." - return 1 + _debug "SMTP_FROM" "$SMTP_FROM" + _debug "SMTP_TO" "$SMTP_TO" + _debug "SMTP_HOST" "$SMTP_HOST" + _debug "SMTP_PORT" "$SMTP_PORT" + _debug "SMTP_DEFAULT_PORT" "$SMTP_DEFAULT_PORT" + _debug "SMTP_SECURE" "$SMTP_SECURE" + _debug "SMTP_USERNAME" "$SMTP_USERNAME" + _secure_debug "SMTP_PASSWORD" "$SMTP_PASSWORD" + _debug "SMTP_TIMEOUT" "$SMTP_TIMEOUT" + _debug "SMTP_DEFAULT_TIMEOUT" "$SMTP_DEFAULT_TIMEOUT" + + if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then + # Output the SMTP server dialogue. (Note this will include SMTP_PASSWORD!) + smtp_debug="True" + else + smtp_debug="" + fi + + # language=Python + smtp_send_output="$($SMTP_PYTHON < Date: Tue, 29 Dec 2020 17:10:36 -0800 Subject: [PATCH 057/304] Make shfmt happy (I'm open to better ways of formatting the heredoc that embeds the Python script.) --- notify/smtp.sh | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 367021c8..6171cb9b 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -63,13 +63,13 @@ smtp_send() { SMTP_SECURE="${SMTP_SECURE:-$(_readaccountconf_mutable SMTP_SECURE)}" SMTP_SECURE="${SMTP_SECURE:-none}" case "$SMTP_SECURE" in - "none") SMTP_DEFAULT_PORT="25";; - "ssl") SMTP_DEFAULT_PORT="465";; - "tls") SMTP_DEFAULT_PORT="587";; - *) - _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." - return 1 - ;; + "none") SMTP_DEFAULT_PORT="25" ;; + "ssl") SMTP_DEFAULT_PORT="465" ;; + "tls") SMTP_DEFAULT_PORT="587" ;; + *) + _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." + return 1 + ;; esac SMTP_USERNAME="${SMTP_USERNAME:-$(_readaccountconf_mutable SMTP_USERNAME)}" @@ -125,7 +125,8 @@ _smtp_send() { fi # language=Python - smtp_send_output="$($SMTP_PYTHON < Date: Mon, 11 Jan 2021 11:46:26 -0800 Subject: [PATCH 058/304] Only save config if send is successful --- notify/smtp.sh | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 6171cb9b..092bb2b9 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -78,6 +78,13 @@ smtp_send() { SMTP_TIMEOUT="${SMTP_TIMEOUT:-$(_readaccountconf_mutable SMTP_TIMEOUT)}" SMTP_DEFAULT_TIMEOUT="15" + # Send the message: + if ! _smtp_send "$@"; then + _err "$smtp_send_output" + return 1 + fi + + # Save remaining config if successful. (SMTP_PYTHON is saved earlier.) _saveaccountconf_mutable SMTP_FROM "$SMTP_FROM" _saveaccountconf_mutable SMTP_TO "$SMTP_TO" _saveaccountconf_mutable SMTP_HOST "$SMTP_HOST" @@ -87,12 +94,6 @@ smtp_send() { _saveaccountconf_mutable SMTP_PASSWORD "$SMTP_PASSWORD" _saveaccountconf_mutable SMTP_TIMEOUT "$SMTP_TIMEOUT" - # Send the message: - if ! _smtp_send "$@"; then - _err "$smtp_send_output" - return 1 - fi - return 0 } From 3aec3fc436a402f7b2ca4f90615b295997e8fd61 Mon Sep 17 00:00:00 2001 From: medmunds Date: Mon, 11 Jan 2021 12:59:51 -0800 Subject: [PATCH 059/304] Add instructions for reporting bugs --- notify/smtp.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/notify/smtp.sh b/notify/smtp.sh index 092bb2b9..a74ce092 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -2,6 +2,8 @@ # support smtp +# Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3358 + # This implementation uses Python (2 or 3), which is available in many environments. # If you don't have Python, try "mail" notification instead of "smtp". From 03c8cacb67817fcad88bdc10b6744734ba7f844c Mon Sep 17 00:00:00 2001 From: medmunds Date: Sun, 14 Feb 2021 15:47:51 -0800 Subject: [PATCH 060/304] Prep for curl or Python; clean up SMTP_* variable usage --- notify/smtp.sh | 203 ++++++++++++++++++++++++++++--------------------- 1 file changed, 118 insertions(+), 85 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index a74ce092..cb29d0f7 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -4,8 +4,8 @@ # Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3358 -# This implementation uses Python (2 or 3), which is available in many environments. -# If you don't have Python, try "mail" notification instead of "smtp". +# This implementation uses either curl or Python (3 or 2.7). +# (See also the "mail" notify hook, which supports other ways to send mail.) # SMTP_FROM="from@example.com" # required # SMTP_TO="to@example.com" # required @@ -14,79 +14,132 @@ # SMTP_SECURE="none" # one of "none", "ssl" (implicit TLS, TLS Wrapper), "tls" (explicit TLS, STARTTLS) # SMTP_USERNAME="" # set if SMTP server requires login # SMTP_PASSWORD="" # set if SMTP server requires login -# SMTP_TIMEOUT="15" # seconds for SMTP operations to timeout -# SMTP_PYTHON="/path/to/python" # defaults to system python3 or python +# SMTP_TIMEOUT="30" # seconds for SMTP operations to timeout +# SMTP_BIN="/path/to/curl_or_python" # default finds first of curl, python3, or python on PATH +# subject content statuscode smtp_send() { - # Find a Python interpreter: - SMTP_PYTHON="${SMTP_PYTHON:-$(_readaccountconf_mutable SMTP_PYTHON)}" - if [ "$SMTP_PYTHON" ]; then - if _exists "$SMTP_PYTHON"; then - _saveaccountconf_mutable SMTP_PYTHON "$SMTP_PYTHON" - else - _err "SMTP_PYTHON '$SMTP_PYTHON' does not exist." - return 1 - fi - else - # No SMTP_PYTHON setting; try to run default Python. - # (This is not saved with the conf.) - if _exists python3; then - SMTP_PYTHON="python3" - elif _exists python; then - SMTP_PYTHON="python" - else - _err "Can't locate Python interpreter; please define SMTP_PYTHON." + _SMTP_SUBJECT="$1" + _SMTP_CONTENT="$2" + # UNUSED: _statusCode="$3" # 0: success, 1: error 2($RENEW_SKIP): skipped + + # Load config: + SMTP_FROM="${SMTP_FROM:-$(_readaccountconf_mutable SMTP_FROM)}" + SMTP_TO="${SMTP_TO:-$(_readaccountconf_mutable SMTP_TO)}" + SMTP_HOST="${SMTP_HOST:-$(_readaccountconf_mutable SMTP_HOST)}" + SMTP_PORT="${SMTP_PORT:-$(_readaccountconf_mutable SMTP_PORT)}" + SMTP_SECURE="${SMTP_SECURE:-$(_readaccountconf_mutable SMTP_SECURE)}" + SMTP_USERNAME="${SMTP_USERNAME:-$(_readaccountconf_mutable SMTP_USERNAME)}" + SMTP_PASSWORD="${SMTP_PASSWORD:-$(_readaccountconf_mutable SMTP_PASSWORD)}" + SMTP_TIMEOUT="${SMTP_TIMEOUT:-$(_readaccountconf_mutable SMTP_TIMEOUT)}" + SMTP_BIN="${SMTP_BIN:-$(_readaccountconf_mutable SMTP_BIN)}" + + _debug "SMTP_FROM" "$SMTP_FROM" + _debug "SMTP_TO" "$SMTP_TO" + _debug "SMTP_HOST" "$SMTP_HOST" + _debug "SMTP_PORT" "$SMTP_PORT" + _debug "SMTP_SECURE" "$SMTP_SECURE" + _debug "SMTP_USERNAME" "$SMTP_USERNAME" + _secure_debug "SMTP_PASSWORD" "$SMTP_PASSWORD" + _debug "SMTP_TIMEOUT" "$SMTP_TIMEOUT" + _debug "SMTP_BIN" "$SMTP_BIN" + + _debug "_SMTP_SUBJECT" "$_SMTP_SUBJECT" + _debug "_SMTP_CONTENT" "$_SMTP_CONTENT" + + # Validate config and apply defaults: + # _SMTP_* variables are the resolved (with defaults) versions of SMTP_*. + # (The _SMTP_* versions will not be stored in account conf.) + + if [ -n "$SMTP_BIN" ] && ! _exists "$SMTP_BIN"; then + _err "SMTP_BIN '$SMTP_BIN' does not exist." + return 1 + fi + _SMTP_BIN="$SMTP_BIN" + if [ -z "$_SMTP_BIN" ]; then + # Look for a command that can communicate with an SMTP server. + # (Please don't add sendmail, ssmtp, mutt, mail, or msmtp here. + # Those are already handled by the "mail" notify hook.) + for cmd in curl python3 python2.7 python pypy3 pypy; do + if _exists "$cmd"; then + _SMTP_BIN="$cmd" + break + fi + done + if [ -z "$_SMTP_BIN" ]; then + _err "The smtp notify-hook requires curl or Python, but can't find any." + _err 'If you have one of them, define SMTP_BIN="/path/to/curl_or_python".' + _err 'Otherwise, see if you can use the "mail" notify-hook instead.' return 1 fi + _debug "_SMTP_BIN" "$_SMTP_BIN" fi - _debug "SMTP_PYTHON" "$SMTP_PYTHON" - _debug "Python version" "$($SMTP_PYTHON --version 2>&1)" - # Validate other settings: - SMTP_FROM="${SMTP_FROM:-$(_readaccountconf_mutable SMTP_FROM)}" if [ -z "$SMTP_FROM" ]; then _err "You must define SMTP_FROM as the sender email address." return 1 fi + _SMTP_FROM="$SMTP_FROM" - SMTP_TO="${SMTP_TO:-$(_readaccountconf_mutable SMTP_TO)}" if [ -z "$SMTP_TO" ]; then _err "You must define SMTP_TO as the recipient email address." return 1 fi + _SMTP_TO="$SMTP_TO" - SMTP_HOST="${SMTP_HOST:-$(_readaccountconf_mutable SMTP_HOST)}" if [ -z "$SMTP_HOST" ]; then _err "You must define SMTP_HOST as the SMTP server hostname." return 1 fi - SMTP_PORT="${SMTP_PORT:-$(_readaccountconf_mutable SMTP_PORT)}" + _SMTP_HOST="$SMTP_HOST" - SMTP_SECURE="${SMTP_SECURE:-$(_readaccountconf_mutable SMTP_SECURE)}" - SMTP_SECURE="${SMTP_SECURE:-none}" - case "$SMTP_SECURE" in - "none") SMTP_DEFAULT_PORT="25" ;; - "ssl") SMTP_DEFAULT_PORT="465" ;; - "tls") SMTP_DEFAULT_PORT="587" ;; + _SMTP_SECURE="${SMTP_SECURE:-none}" + case "$_SMTP_SECURE" in + "none") smtp_default_port="25" ;; + "ssl") smtp_default_port="465" ;; + "tls") smtp_default_port="587" ;; *) _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." return 1 ;; esac - SMTP_USERNAME="${SMTP_USERNAME:-$(_readaccountconf_mutable SMTP_USERNAME)}" - SMTP_PASSWORD="${SMTP_PASSWORD:-$(_readaccountconf_mutable SMTP_PASSWORD)}" + _SMTP_PORT="${SMTP_PORT:-$smtp_default_port}" + if [ -z "$SMTP_PORT" ]; then + _debug "_SMTP_PORT" "$_SMTP_PORT" + fi - SMTP_TIMEOUT="${SMTP_TIMEOUT:-$(_readaccountconf_mutable SMTP_TIMEOUT)}" - SMTP_DEFAULT_TIMEOUT="15" + _SMTP_USERNAME="$SMTP_USERNAME" + _SMTP_PASSWORD="$SMTP_PASSWORD" + _SMTP_TIMEOUT="${SMTP_TIMEOUT:-30}" + + # Run with --debug 2 (or above) to echo the transcript of the SMTP session. + # Careful: this may include SMTP_PASSWORD in plaintext! + if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then + _SMTP_SHOW_TRANSCRIPT="True" + else + _SMTP_SHOW_TRANSCRIPT="" + fi # Send the message: - if ! _smtp_send "$@"; then - _err "$smtp_send_output" + case "$(basename "$_SMTP_BIN")" in + curl) _smtp_send=_smtp_send_curl ;; + py*) _smtp_send=_smtp_send_python ;; + *) + _err "Can't figure out how to invoke $_SMTP_BIN." + _err "Please re-run with --debug and report a bug." + return 1 + ;; + esac + + if ! smtp_output="$($_smtp_send)"; then + _err "Error sending message with $_SMTP_BIN." + _err "${smtp_output:-(No additional details; try --debug or --debug 2)}" return 1 fi - # Save remaining config if successful. (SMTP_PYTHON is saved earlier.) + # Save config only if send was successful: + _saveaccountconf_mutable SMTP_BIN "$SMTP_BIN" _saveaccountconf_mutable SMTP_FROM "$SMTP_FROM" _saveaccountconf_mutable SMTP_TO "$SMTP_TO" _saveaccountconf_mutable SMTP_HOST "$SMTP_HOST" @@ -99,37 +152,21 @@ smtp_send() { return 0 } -# _send subject content statuscode -# Send the message via Python using SMTP_* settings -_smtp_send() { - _subject="$1" - _content="$2" - _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped - _debug "_subject" "$_subject" - _debug "_content" "$_content" - _debug "_statusCode" "$_statusCode" - _debug "SMTP_FROM" "$SMTP_FROM" - _debug "SMTP_TO" "$SMTP_TO" - _debug "SMTP_HOST" "$SMTP_HOST" - _debug "SMTP_PORT" "$SMTP_PORT" - _debug "SMTP_DEFAULT_PORT" "$SMTP_DEFAULT_PORT" - _debug "SMTP_SECURE" "$SMTP_SECURE" - _debug "SMTP_USERNAME" "$SMTP_USERNAME" - _secure_debug "SMTP_PASSWORD" "$SMTP_PASSWORD" - _debug "SMTP_TIMEOUT" "$SMTP_TIMEOUT" - _debug "SMTP_DEFAULT_TIMEOUT" "$SMTP_DEFAULT_TIMEOUT" +# Send the message via curl using _SMTP_* variables +_smtp_send_curl() { + # TODO: implement + echo "_smtp_send_curl not implemented" + return 1 +} - if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then - # Output the SMTP server dialogue. (Note this will include SMTP_PASSWORD!) - smtp_debug="True" - else - smtp_debug="" - fi + +# Send the message via Python using _SMTP_* variables +_smtp_send_python() { + _debug "Python version" "$("$_SMTP_BIN" --version 2>&1)" # language=Python - smtp_send_output="$( - $SMTP_PYTHON < Date: Sun, 14 Feb 2021 19:56:23 -0800 Subject: [PATCH 061/304] Implement curl version of smtp notify-hook --- notify/smtp.sh | 111 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 105 insertions(+), 6 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index cb29d0f7..44a5821f 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -127,14 +127,16 @@ smtp_send() { py*) _smtp_send=_smtp_send_python ;; *) _err "Can't figure out how to invoke $_SMTP_BIN." - _err "Please re-run with --debug and report a bug." + _err "Check your SMTP_BIN setting." return 1 ;; esac if ! smtp_output="$($_smtp_send)"; then _err "Error sending message with $_SMTP_BIN." - _err "${smtp_output:-(No additional details; try --debug or --debug 2)}" + if [ -n "$smtp_output" ]; then + _err "$smtp_output" + fi return 1 fi @@ -152,12 +154,109 @@ smtp_send() { return 0 } - # Send the message via curl using _SMTP_* variables _smtp_send_curl() { - # TODO: implement - echo "_smtp_send_curl not implemented" - return 1 + # curl passes --mail-from and --mail-rcpt directly to the SMTP protocol without + # additional parsing, and SMTP requires addr-spec only (no display names). + # In the future, maybe try to parse the addr-spec out for curl args (non-trivial). + if _email_has_display_name "$_SMTP_FROM"; then + _err "curl smtp only allows a simple email address in SMTP_FROM." + _err "Change your SMTP_FROM='$SMTP_FROM' to remove the display name." + return 1 + fi + if _email_has_display_name "$_SMTP_TO"; then + _err "curl smtp only allows simple email addresses in SMTP_TO." + _err "Change your SMTP_TO='$SMTP_TO' to remove the display name(s)." + return 1 + fi + + # Build curl args in $@ + + case "$_SMTP_SECURE" in + none) + set -- --url "smtp://${_SMTP_HOST}:${_SMTP_PORT}" + ;; + ssl) + set -- --url "smtps://${_SMTP_HOST}:${_SMTP_PORT}" + ;; + tls) + set -- --url "smtp://${_SMTP_HOST}:${_SMTP_PORT}" --ssl-reqd + ;; + *) + # This will only occur if someone adds a new SMTP_SECURE option above + # without updating this code for it. + _err "Unhandled _SMTP_SECURE='$_SMTP_SECURE' in _smtp_send_curl" + _err "Please re-run with --debug and report a bug." + return 1 + ;; + esac + + set -- "$@" \ + --upload-file - \ + --mail-from "$_SMTP_FROM" \ + --max-time "$_SMTP_TIMEOUT" + + # Burst comma-separated $_SMTP_TO into individual --mail-rcpt args. + _to="${_SMTP_TO}," + while [ -n "$_to" ]; do + _rcpt="${_to%%,*}" + _to="${_to#*,}" + set -- "$@" --mail-rcpt "$_rcpt" + done + + _smtp_login="${_SMTP_USERNAME}:${_SMTP_PASSWORD}" + if [ "$_smtp_login" != ":" ]; then + set -- "$@" --user "$_smtp_login" + fi + + if [ "$_SMTP_SHOW_TRANSCRIPT" = "True" ]; then + set -- "$@" --verbose + else + set -- "$@" --silent --show-error + fi + + raw_message="$(_smtp_raw_message)" + + _debug2 "curl command:" "$_SMTP_BIN" "$*" + _debug2 "raw_message:\n$raw_message" + + echo "$raw_message" | "$_SMTP_BIN" "$@" +} + +# Output an RFC-822 / RFC-5322 email message using _SMTP_* variables +_smtp_raw_message() { + echo "From: $_SMTP_FROM" + echo "To: $_SMTP_TO" + echo "Subject: $(_mime_encoded_word "$_SMTP_SUBJECT")" + if _exists date; then + echo "Date: $(date +'%a, %-d %b %Y %H:%M:%S %z')" + fi + echo "Content-Type: text/plain; charset=utf-8" + echo "X-Mailer: acme.sh --notify-hook smtp" + echo + echo "$_SMTP_CONTENT" +} + +# Convert text to RFC-2047 MIME "encoded word" format if it contains non-ASCII chars +# text +_mime_encoded_word() { + _text="$1" + # (regex character ranges like [a-z] can be locale-dependent; enumerate ASCII chars to avoid that) + _ascii='] $`"'"[!#%&'()*+,./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ~^_abcdefghijklmnopqrstuvwxyz{|}~-" + if expr "$_text" : "^.*[^$_ascii]" >/dev/null; then + # At least one non-ASCII char; convert entire thing to encoded word + printf "%s" "=?UTF-8?B?$(printf "%s" "$_text" | _base64)?=" + else + # Just printable ASCII, no conversion needed + printf "%s" "$_text" + fi +} + +# Simple check for display name in an email address (< > or ") +# email +_email_has_display_name() { + _email="$1" + expr "$_email" : '^.*[<>"]' > /dev/null } From 7f1586678c41d06d5f2c0269ba44dafc3c24e6f5 Mon Sep 17 00:00:00 2001 From: medmunds Date: Sun, 14 Feb 2021 20:06:07 -0800 Subject: [PATCH 062/304] More than one blank line is an abomination, apparently I will not try to use whitespace to group code visually --- notify/smtp.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 44a5821f..c9927e3e 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -256,10 +256,9 @@ _mime_encoded_word() { # email _email_has_display_name() { _email="$1" - expr "$_email" : '^.*[<>"]' > /dev/null + expr "$_email" : '^.*[<>"]' >/dev/null } - # Send the message via Python using _SMTP_* variables _smtp_send_python() { _debug "Python version" "$("$_SMTP_BIN" --version 2>&1)" From 362bd62152264eabce861154a82b8a81dfdcb142 Mon Sep 17 00:00:00 2001 From: medmunds Date: Mon, 15 Feb 2021 12:23:48 -0800 Subject: [PATCH 063/304] Use PROJECT_NAME and VER for X-Mailer header Also add X-Mailer header to Python version --- notify/smtp.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index c9927e3e..bb71a563 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -112,6 +112,7 @@ smtp_send() { _SMTP_USERNAME="$SMTP_USERNAME" _SMTP_PASSWORD="$SMTP_PASSWORD" _SMTP_TIMEOUT="${SMTP_TIMEOUT:-30}" + _SMTP_X_MAILER="${PROJECT_NAME} ${VER} --notify-hook smtp" # Run with --debug 2 (or above) to echo the transcript of the SMTP session. # Careful: this may include SMTP_PASSWORD in plaintext! @@ -232,7 +233,7 @@ _smtp_raw_message() { echo "Date: $(date +'%a, %-d %b %Y %H:%M:%S %z')" fi echo "Content-Type: text/plain; charset=utf-8" - echo "X-Mailer: acme.sh --notify-hook smtp" + echo "X-Mailer: $_SMTP_X_MAILER" echo echo "$_SMTP_CONTENT" } @@ -286,6 +287,7 @@ smtp_secure = """$_SMTP_SECURE""" username = """$_SMTP_USERNAME""" password = """$_SMTP_PASSWORD""" timeout=int("""$_SMTP_TIMEOUT""") # seconds +x_mailer="""$_SMTP_X_MAILER""" from_email="""$_SMTP_FROM""" to_emails="""$_SMTP_TO""" # can be comma-separated @@ -301,6 +303,7 @@ except (AttributeError, TypeError): msg["Subject"] = subject msg["From"] = from_email msg["To"] = to_emails +msg["X-Mailer"] = x_mailer smtp = None try: From c2a4f31368fd0f757c771b3cdf11c3b1d2151499 Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 16 Feb 2021 09:33:39 -0800 Subject: [PATCH 064/304] Add _clearaccountconf_mutable() --- acme.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/acme.sh b/acme.sh index 920e21d4..5f7a1642 100755 --- a/acme.sh +++ b/acme.sh @@ -2283,6 +2283,13 @@ _clearaccountconf() { _clear_conf "$ACCOUNT_CONF_PATH" "$1" } +#key +_clearaccountconf_mutable() { + _clearaccountconf "SAVED_$1" + #remove later + _clearaccountconf "$1" +} + #_savecaconf key value _savecaconf() { _save_conf "$CA_CONF" "$1" "$2" From a4590b97072f06143590eafc44bd083cf2d1a136 Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 16 Feb 2021 12:49:27 -0800 Subject: [PATCH 065/304] Rework read/save config to not save default values Add and use _readaccountconf_mutable_default and _saveaccountconf_mutable_default helpers to capture common default value handling. New approach also eliminates need for separate underscore-prefixed version of each conf var. --- notify/smtp.sh | 255 +++++++++++++++++++++++++++++-------------------- 1 file changed, 149 insertions(+), 106 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index bb71a563..85801604 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -17,155 +17,150 @@ # SMTP_TIMEOUT="30" # seconds for SMTP operations to timeout # SMTP_BIN="/path/to/curl_or_python" # default finds first of curl, python3, or python on PATH +SMTP_SECURE_DEFAULT="none" +SMTP_TIMEOUT_DEFAULT="30" + # subject content statuscode smtp_send() { - _SMTP_SUBJECT="$1" - _SMTP_CONTENT="$2" + SMTP_SUBJECT="$1" + SMTP_CONTENT="$2" # UNUSED: _statusCode="$3" # 0: success, 1: error 2($RENEW_SKIP): skipped - # Load config: - SMTP_FROM="${SMTP_FROM:-$(_readaccountconf_mutable SMTP_FROM)}" - SMTP_TO="${SMTP_TO:-$(_readaccountconf_mutable SMTP_TO)}" - SMTP_HOST="${SMTP_HOST:-$(_readaccountconf_mutable SMTP_HOST)}" - SMTP_PORT="${SMTP_PORT:-$(_readaccountconf_mutable SMTP_PORT)}" - SMTP_SECURE="${SMTP_SECURE:-$(_readaccountconf_mutable SMTP_SECURE)}" - SMTP_USERNAME="${SMTP_USERNAME:-$(_readaccountconf_mutable SMTP_USERNAME)}" - SMTP_PASSWORD="${SMTP_PASSWORD:-$(_readaccountconf_mutable SMTP_PASSWORD)}" - SMTP_TIMEOUT="${SMTP_TIMEOUT:-$(_readaccountconf_mutable SMTP_TIMEOUT)}" - SMTP_BIN="${SMTP_BIN:-$(_readaccountconf_mutable SMTP_BIN)}" - - _debug "SMTP_FROM" "$SMTP_FROM" - _debug "SMTP_TO" "$SMTP_TO" - _debug "SMTP_HOST" "$SMTP_HOST" - _debug "SMTP_PORT" "$SMTP_PORT" - _debug "SMTP_SECURE" "$SMTP_SECURE" - _debug "SMTP_USERNAME" "$SMTP_USERNAME" - _secure_debug "SMTP_PASSWORD" "$SMTP_PASSWORD" - _debug "SMTP_TIMEOUT" "$SMTP_TIMEOUT" - _debug "SMTP_BIN" "$SMTP_BIN" - - _debug "_SMTP_SUBJECT" "$_SMTP_SUBJECT" - _debug "_SMTP_CONTENT" "$_SMTP_CONTENT" - - # Validate config and apply defaults: - # _SMTP_* variables are the resolved (with defaults) versions of SMTP_*. - # (The _SMTP_* versions will not be stored in account conf.) - + # Load and validate config: + SMTP_BIN="$(_readaccountconf_mutable_default SMTP_BIN)" if [ -n "$SMTP_BIN" ] && ! _exists "$SMTP_BIN"; then _err "SMTP_BIN '$SMTP_BIN' does not exist." return 1 fi - _SMTP_BIN="$SMTP_BIN" - if [ -z "$_SMTP_BIN" ]; then + if [ -z "$SMTP_BIN" ]; then # Look for a command that can communicate with an SMTP server. # (Please don't add sendmail, ssmtp, mutt, mail, or msmtp here. # Those are already handled by the "mail" notify hook.) for cmd in curl python3 python2.7 python pypy3 pypy; do if _exists "$cmd"; then - _SMTP_BIN="$cmd" + SMTP_BIN="$cmd" break fi done - if [ -z "$_SMTP_BIN" ]; then + if [ -z "$SMTP_BIN" ]; then _err "The smtp notify-hook requires curl or Python, but can't find any." _err 'If you have one of them, define SMTP_BIN="/path/to/curl_or_python".' _err 'Otherwise, see if you can use the "mail" notify-hook instead.' return 1 fi - _debug "_SMTP_BIN" "$_SMTP_BIN" fi + _debug SMTP_BIN "$SMTP_BIN" + _saveaccountconf_mutable_default SMTP_BIN "$SMTP_BIN" + SMTP_FROM="$(_readaccountconf_mutable_default SMTP_FROM)" if [ -z "$SMTP_FROM" ]; then _err "You must define SMTP_FROM as the sender email address." return 1 fi - _SMTP_FROM="$SMTP_FROM" + _debug SMTP_FROM "$SMTP_FROM" + _saveaccountconf_mutable_default SMTP_FROM "$SMTP_FROM" + SMTP_TO="$(_readaccountconf_mutable_default SMTP_TO)" if [ -z "$SMTP_TO" ]; then _err "You must define SMTP_TO as the recipient email address." return 1 fi - _SMTP_TO="$SMTP_TO" + _debug SMTP_TO "$SMTP_TO" + _saveaccountconf_mutable_default SMTP_TO "$SMTP_TO" + SMTP_HOST="$(_readaccountconf_mutable_default SMTP_HOST)" if [ -z "$SMTP_HOST" ]; then _err "You must define SMTP_HOST as the SMTP server hostname." return 1 fi - _SMTP_HOST="$SMTP_HOST" - - _SMTP_SECURE="${SMTP_SECURE:-none}" - case "$_SMTP_SECURE" in - "none") smtp_default_port="25" ;; - "ssl") smtp_default_port="465" ;; - "tls") smtp_default_port="587" ;; + _debug SMTP_HOST "$SMTP_HOST" + _saveaccountconf_mutable_default SMTP_HOST "$SMTP_HOST" + + SMTP_SECURE="$(_readaccountconf_mutable_default SMTP_SECURE "$SMTP_SECURE_DEFAULT")" + case "$SMTP_SECURE" in + "none") smtp_port_default="25" ;; + "ssl") smtp_port_default="465" ;; + "tls") smtp_port_default="587" ;; *) _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." return 1 ;; esac + _debug SMTP_SECURE "$SMTP_SECURE" + _saveaccountconf_mutable_default SMTP_SECURE "$SMTP_SECURE" "$SMTP_SECURE_DEFAULT" - _SMTP_PORT="${SMTP_PORT:-$smtp_default_port}" - if [ -z "$SMTP_PORT" ]; then - _debug "_SMTP_PORT" "$_SMTP_PORT" - fi + SMTP_PORT="$(_readaccountconf_mutable_default SMTP_PORT "$smtp_port_default")" + case "$SMTP_PORT" in + *[!0-9]*) + _err "Invalid SMTP_PORT='$SMTP_PORT'. It must be a port number." + return 1 + ;; + esac + _debug SMTP_PORT "$SMTP_PORT" + _saveaccountconf_mutable_default SMTP_PORT "$SMTP_PORT" "$smtp_port_default" + + SMTP_USERNAME="$(_readaccountconf_mutable_default SMTP_USERNAME)" + _debug SMTP_USERNAME "$SMTP_USERNAME" + _saveaccountconf_mutable_default SMTP_USERNAME "$SMTP_USERNAME" + + SMTP_PASSWORD="$(_readaccountconf_mutable_default SMTP_PASSWORD)" + _secure_debug SMTP_PASSWORD "$SMTP_PASSWORD" + _saveaccountconf_mutable_default SMTP_PASSWORD "$SMTP_PASSWORD" - _SMTP_USERNAME="$SMTP_USERNAME" - _SMTP_PASSWORD="$SMTP_PASSWORD" - _SMTP_TIMEOUT="${SMTP_TIMEOUT:-30}" - _SMTP_X_MAILER="${PROJECT_NAME} ${VER} --notify-hook smtp" + SMTP_TIMEOUT="$(_readaccountconf_mutable_default SMTP_TIMEOUT "$SMTP_TIMEOUT_DEFAULT")" + _debug SMTP_TIMEOUT "$SMTP_TIMEOUT" + _saveaccountconf_mutable_default SMTP_TIMEOUT "$SMTP_TIMEOUT" "$SMTP_TIMEOUT_DEFAULT" + + SMTP_X_MAILER="${PROJECT_NAME} ${VER} --notify-hook smtp" # Run with --debug 2 (or above) to echo the transcript of the SMTP session. # Careful: this may include SMTP_PASSWORD in plaintext! if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then - _SMTP_SHOW_TRANSCRIPT="True" + SMTP_SHOW_TRANSCRIPT="True" else - _SMTP_SHOW_TRANSCRIPT="" + SMTP_SHOW_TRANSCRIPT="" fi + _debug SMTP_SUBJECT "$SMTP_SUBJECT" + _debug SMTP_CONTENT "$SMTP_CONTENT" + # Send the message: - case "$(basename "$_SMTP_BIN")" in + case "$(basename "$SMTP_BIN")" in curl) _smtp_send=_smtp_send_curl ;; py*) _smtp_send=_smtp_send_python ;; *) - _err "Can't figure out how to invoke $_SMTP_BIN." + _err "Can't figure out how to invoke '$SMTP_BIN'." _err "Check your SMTP_BIN setting." return 1 ;; esac if ! smtp_output="$($_smtp_send)"; then - _err "Error sending message with $_SMTP_BIN." + _err "Error sending message with $SMTP_BIN." if [ -n "$smtp_output" ]; then _err "$smtp_output" fi return 1 fi - # Save config only if send was successful: - _saveaccountconf_mutable SMTP_BIN "$SMTP_BIN" - _saveaccountconf_mutable SMTP_FROM "$SMTP_FROM" - _saveaccountconf_mutable SMTP_TO "$SMTP_TO" - _saveaccountconf_mutable SMTP_HOST "$SMTP_HOST" - _saveaccountconf_mutable SMTP_PORT "$SMTP_PORT" - _saveaccountconf_mutable SMTP_SECURE "$SMTP_SECURE" - _saveaccountconf_mutable SMTP_USERNAME "$SMTP_USERNAME" - _saveaccountconf_mutable SMTP_PASSWORD "$SMTP_PASSWORD" - _saveaccountconf_mutable SMTP_TIMEOUT "$SMTP_TIMEOUT" - return 0 } -# Send the message via curl using _SMTP_* variables +## +## curl smtp sending +## + +# Send the message via curl using SMTP_* variables _smtp_send_curl() { # curl passes --mail-from and --mail-rcpt directly to the SMTP protocol without # additional parsing, and SMTP requires addr-spec only (no display names). # In the future, maybe try to parse the addr-spec out for curl args (non-trivial). - if _email_has_display_name "$_SMTP_FROM"; then + if _email_has_display_name "$SMTP_FROM"; then _err "curl smtp only allows a simple email address in SMTP_FROM." _err "Change your SMTP_FROM='$SMTP_FROM' to remove the display name." return 1 fi - if _email_has_display_name "$_SMTP_TO"; then + if _email_has_display_name "$SMTP_TO"; then _err "curl smtp only allows simple email addresses in SMTP_TO." _err "Change your SMTP_TO='$SMTP_TO' to remove the display name(s)." return 1 @@ -173,20 +168,20 @@ _smtp_send_curl() { # Build curl args in $@ - case "$_SMTP_SECURE" in + case "$SMTP_SECURE" in none) - set -- --url "smtp://${_SMTP_HOST}:${_SMTP_PORT}" + set -- --url "smtp://${SMTP_HOST}:${SMTP_PORT}" ;; ssl) - set -- --url "smtps://${_SMTP_HOST}:${_SMTP_PORT}" + set -- --url "smtps://${SMTP_HOST}:${SMTP_PORT}" ;; tls) - set -- --url "smtp://${_SMTP_HOST}:${_SMTP_PORT}" --ssl-reqd + set -- --url "smtp://${SMTP_HOST}:${SMTP_PORT}" --ssl-reqd ;; *) # This will only occur if someone adds a new SMTP_SECURE option above # without updating this code for it. - _err "Unhandled _SMTP_SECURE='$_SMTP_SECURE' in _smtp_send_curl" + _err "Unhandled SMTP_SECURE='$SMTP_SECURE' in _smtp_send_curl" _err "Please re-run with --debug and report a bug." return 1 ;; @@ -194,23 +189,23 @@ _smtp_send_curl() { set -- "$@" \ --upload-file - \ - --mail-from "$_SMTP_FROM" \ - --max-time "$_SMTP_TIMEOUT" + --mail-from "$SMTP_FROM" \ + --max-time "$SMTP_TIMEOUT" - # Burst comma-separated $_SMTP_TO into individual --mail-rcpt args. - _to="${_SMTP_TO}," + # Burst comma-separated $SMTP_TO into individual --mail-rcpt args. + _to="${SMTP_TO}," while [ -n "$_to" ]; do _rcpt="${_to%%,*}" _to="${_to#*,}" set -- "$@" --mail-rcpt "$_rcpt" done - _smtp_login="${_SMTP_USERNAME}:${_SMTP_PASSWORD}" + _smtp_login="${SMTP_USERNAME}:${SMTP_PASSWORD}" if [ "$_smtp_login" != ":" ]; then set -- "$@" --user "$_smtp_login" fi - if [ "$_SMTP_SHOW_TRANSCRIPT" = "True" ]; then + if [ "$SMTP_SHOW_TRANSCRIPT" = "True" ]; then set -- "$@" --verbose else set -- "$@" --silent --show-error @@ -218,24 +213,24 @@ _smtp_send_curl() { raw_message="$(_smtp_raw_message)" - _debug2 "curl command:" "$_SMTP_BIN" "$*" + _debug2 "curl command:" "$SMTP_BIN" "$*" _debug2 "raw_message:\n$raw_message" - echo "$raw_message" | "$_SMTP_BIN" "$@" + echo "$raw_message" | "$SMTP_BIN" "$@" } -# Output an RFC-822 / RFC-5322 email message using _SMTP_* variables +# Output an RFC-822 / RFC-5322 email message using SMTP_* variables _smtp_raw_message() { - echo "From: $_SMTP_FROM" - echo "To: $_SMTP_TO" - echo "Subject: $(_mime_encoded_word "$_SMTP_SUBJECT")" + echo "From: $SMTP_FROM" + echo "To: $SMTP_TO" + echo "Subject: $(_mime_encoded_word "$SMTP_SUBJECT")" if _exists date; then echo "Date: $(date +'%a, %-d %b %Y %H:%M:%S %z')" fi echo "Content-Type: text/plain; charset=utf-8" - echo "X-Mailer: $_SMTP_X_MAILER" + echo "X-Mailer: $SMTP_X_MAILER" echo - echo "$_SMTP_CONTENT" + echo "$SMTP_CONTENT" } # Convert text to RFC-2047 MIME "encoded word" format if it contains non-ASCII chars @@ -260,12 +255,16 @@ _email_has_display_name() { expr "$_email" : '^.*[<>"]' >/dev/null } -# Send the message via Python using _SMTP_* variables +## +## Python smtp sending +## + +# Send the message via Python using SMTP_* variables _smtp_send_python() { - _debug "Python version" "$("$_SMTP_BIN" --version 2>&1)" + _debug "Python version" "$("$SMTP_BIN" --version 2>&1)" # language=Python - "$_SMTP_BIN" < Date: Tue, 16 Feb 2021 13:13:26 -0800 Subject: [PATCH 066/304] Implement _rfc2822_date helper --- notify/smtp.sh | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 85801604..43536cd2 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -224,9 +224,7 @@ _smtp_raw_message() { echo "From: $SMTP_FROM" echo "To: $SMTP_TO" echo "Subject: $(_mime_encoded_word "$SMTP_SUBJECT")" - if _exists date; then - echo "Date: $(date +'%a, %-d %b %Y %H:%M:%S %z')" - fi + echo "Date: $(_rfc2822_date)" echo "Content-Type: text/plain; charset=utf-8" echo "X-Mailer: $SMTP_X_MAILER" echo @@ -248,6 +246,19 @@ _mime_encoded_word() { fi } +# Output current date in RFC-2822 Section 3.3 format as required in email headers +# (e.g., "Mon, 15 Feb 2021 14:22:01 -0800") +_rfc2822_date() { + # Notes: + # - this is deliberately not UTC, because it "SHOULD express local time" per spec + # - the spec requires weekday and month in the C locale (English), not localized + # - this date format specifier has been tested on Linux, Mac, Solaris and FreeBSD + _old_lc_time="$LC_TIME" + LC_TIME=C + date +'%a, %-d %b %Y %H:%M:%S %z' + LC_TIME="$_old_lc_time" +} + # Simple check for display name in an email address (< > or ") # email _email_has_display_name() { From c7ce0fd7809ac54795b35c21c017561ed2a2bd24 Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 16 Feb 2021 14:02:09 -0800 Subject: [PATCH 067/304] Clean email headers and warn on unsupported address format Just in case, make sure CR or NL don't end up in an email header. --- notify/smtp.sh | 55 +++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 43536cd2..42c1487c 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -53,16 +53,28 @@ smtp_send() { _saveaccountconf_mutable_default SMTP_BIN "$SMTP_BIN" SMTP_FROM="$(_readaccountconf_mutable_default SMTP_FROM)" + SMTP_FROM="$(_clean_email_header "$SMTP_FROM")" if [ -z "$SMTP_FROM" ]; then _err "You must define SMTP_FROM as the sender email address." return 1 fi + if _email_has_display_name "$SMTP_FROM"; then + _err "SMTP_FROM must be only a simple email address (sender@example.com)." + _err "Change your SMTP_FROM='$SMTP_FROM' to remove the display name." + return 1 + fi _debug SMTP_FROM "$SMTP_FROM" _saveaccountconf_mutable_default SMTP_FROM "$SMTP_FROM" SMTP_TO="$(_readaccountconf_mutable_default SMTP_TO)" + SMTP_TO="$(_clean_email_header "$SMTP_TO")" if [ -z "$SMTP_TO" ]; then - _err "You must define SMTP_TO as the recipient email address." + _err "You must define SMTP_TO as the recipient email address(es)." + return 1 + fi + if _email_has_display_name "$SMTP_TO"; then + _err "SMTP_TO must be only simple email addresses (to@example.com,to2@example.com)." + _err "Change your SMTP_TO='$SMTP_TO' to remove the display name(s)." return 1 fi _debug SMTP_TO "$SMTP_TO" @@ -111,7 +123,7 @@ smtp_send() { _debug SMTP_TIMEOUT "$SMTP_TIMEOUT" _saveaccountconf_mutable_default SMTP_TIMEOUT "$SMTP_TIMEOUT" "$SMTP_TIMEOUT_DEFAULT" - SMTP_X_MAILER="${PROJECT_NAME} ${VER} --notify-hook smtp" + SMTP_X_MAILER="$(_clean_email_header "$PROJECT_NAME $VER --notify-hook smtp")" # Run with --debug 2 (or above) to echo the transcript of the SMTP session. # Careful: this may include SMTP_PASSWORD in plaintext! @@ -121,6 +133,7 @@ smtp_send() { SMTP_SHOW_TRANSCRIPT="" fi + SMTP_SUBJECT=$(_clean_email_header "$SMTP_SUBJECT") _debug SMTP_SUBJECT "$SMTP_SUBJECT" _debug SMTP_CONTENT "$SMTP_CONTENT" @@ -146,28 +159,26 @@ smtp_send() { return 0 } +# Strip CR and NL from text to prevent MIME header injection +# text +_clean_email_header() { + printf "%s" "$(echo "$1" | tr -d "\r\n")" +} + +# Simple check for display name in an email address (< > or ") +# email +_email_has_display_name() { + _email="$1" + expr "$_email" : '^.*[<>"]' >/dev/null +} + ## ## curl smtp sending ## # Send the message via curl using SMTP_* variables _smtp_send_curl() { - # curl passes --mail-from and --mail-rcpt directly to the SMTP protocol without - # additional parsing, and SMTP requires addr-spec only (no display names). - # In the future, maybe try to parse the addr-spec out for curl args (non-trivial). - if _email_has_display_name "$SMTP_FROM"; then - _err "curl smtp only allows a simple email address in SMTP_FROM." - _err "Change your SMTP_FROM='$SMTP_FROM' to remove the display name." - return 1 - fi - if _email_has_display_name "$SMTP_TO"; then - _err "curl smtp only allows simple email addresses in SMTP_TO." - _err "Change your SMTP_TO='$SMTP_TO' to remove the display name(s)." - return 1 - fi - # Build curl args in $@ - case "$SMTP_SECURE" in none) set -- --url "smtp://${SMTP_HOST}:${SMTP_PORT}" @@ -219,7 +230,8 @@ _smtp_send_curl() { echo "$raw_message" | "$SMTP_BIN" "$@" } -# Output an RFC-822 / RFC-5322 email message using SMTP_* variables +# Output an RFC-822 / RFC-5322 email message using SMTP_* variables. +# (This assumes variables have already been cleaned for use in email headers.) _smtp_raw_message() { echo "From: $SMTP_FROM" echo "To: $SMTP_TO" @@ -259,13 +271,6 @@ _rfc2822_date() { LC_TIME="$_old_lc_time" } -# Simple check for display name in an email address (< > or ") -# email -_email_has_display_name() { - _email="$1" - expr "$_email" : '^.*[<>"]' >/dev/null -} - ## ## Python smtp sending ## From d4fde8dad313af35255f01033888868dfd416157 Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 16 Feb 2021 14:41:21 -0800 Subject: [PATCH 068/304] Clarify _readaccountconf_mutable_default --- notify/smtp.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 42c1487c..fabde79b 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -358,7 +358,7 @@ PYTHON # - if MY_CONF is set _empty_, output $default_value # (lets user `export MY_CONF=` to clear previous saved value # and return to default, without user having to know default) -# - otherwise if _readaccountconf_mutable $name is non-empty, return that +# - otherwise if _readaccountconf_mutable MY_CONF is non-empty, return that # (value of SAVED_MY_CONF from account.conf) # - otherwise output $default_value _readaccountconf_mutable_default() { @@ -366,8 +366,9 @@ _readaccountconf_mutable_default() { _default_value="$2" eval "_value=\"\$$_name\"" - eval "_explicit_empty_value=\"\${${_name}+empty}\"" - if [ -z "${_value}" ] && [ "${_explicit_empty_value:-}" != "empty" ]; then + eval "_name_is_set=\"\${${_name}+true}\"" + # ($_name_is_set is "true" if $$_name is set to anything, including empty) + if [ -z "${_value}" ] && [ "${_name_is_set:-}" != "true" ]; then _value="$(_readaccountconf_mutable "$_name")" fi if [ -z "${_value}" ]; then From 9570cce7e33385e99e1ef8e9983f86ed6bb1330f Mon Sep 17 00:00:00 2001 From: medmunds Date: Wed, 17 Feb 2021 09:46:13 -0800 Subject: [PATCH 069/304] Add Date email header in Python implementation --- notify/smtp.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/notify/smtp.sh b/notify/smtp.sh index fabde79b..0c698631 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -287,6 +287,7 @@ try: from email.message import EmailMessage except ImportError: from email.mime.text import MIMEText as EmailMessage # Python 2 + from email.utils import formatdate as rfc2822_date from smtplib import SMTP, SMTP_SSL, SMTPException from socket import error as SocketError except ImportError as err: @@ -318,6 +319,7 @@ except (AttributeError, TypeError): msg["Subject"] = subject msg["From"] = from_email msg["To"] = to_emails +msg["Date"] = rfc2822_date(localtime=True) msg["X-Mailer"] = x_mailer smtp = None From 3cfb423e89f39a4f0d15700c27bf55c7feb8d2ae Mon Sep 17 00:00:00 2001 From: medmunds Date: Wed, 17 Feb 2021 09:57:44 -0800 Subject: [PATCH 070/304] Use email.policy.default in Python 3 implementation Improves standards compatibility and utf-8 handling in Python 3.3-3.8. (email.policy.default becomes the default in Python 3.9.) --- notify/smtp.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 0c698631..69863206 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -285,8 +285,11 @@ _smtp_send_python() { try: try: from email.message import EmailMessage + from email.policy import default as email_policy_default except ImportError: - from email.mime.text import MIMEText as EmailMessage # Python 2 + # Python 2 (or < 3.3) + from email.mime.text import MIMEText as EmailMessage + email_policy_default = None from email.utils import formatdate as rfc2822_date from smtplib import SMTP, SMTP_SSL, SMTPException from socket import error as SocketError @@ -311,7 +314,7 @@ subject="""$SMTP_SUBJECT""" content="""$SMTP_CONTENT""" try: - msg = EmailMessage() + msg = EmailMessage(policy=email_policy_default) msg.set_content(content) except (AttributeError, TypeError): # Python 2 MIMEText From f8ee124742ea240be8456cb0bb762bc22bf1da57 Mon Sep 17 00:00:00 2001 From: medmunds Date: Wed, 17 Feb 2021 10:02:14 -0800 Subject: [PATCH 071/304] Prefer Python to curl when both available --- notify/smtp.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 69863206..71020818 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -15,7 +15,7 @@ # SMTP_USERNAME="" # set if SMTP server requires login # SMTP_PASSWORD="" # set if SMTP server requires login # SMTP_TIMEOUT="30" # seconds for SMTP operations to timeout -# SMTP_BIN="/path/to/curl_or_python" # default finds first of curl, python3, or python on PATH +# SMTP_BIN="/path/to/python_or_curl" # default finds first of python3, python2.7, python, pypy3, pypy, curl on PATH SMTP_SECURE_DEFAULT="none" SMTP_TIMEOUT_DEFAULT="30" @@ -36,7 +36,7 @@ smtp_send() { # Look for a command that can communicate with an SMTP server. # (Please don't add sendmail, ssmtp, mutt, mail, or msmtp here. # Those are already handled by the "mail" notify hook.) - for cmd in curl python3 python2.7 python pypy3 pypy; do + for cmd in python3 python2.7 python pypy3 pypy curl; do if _exists "$cmd"; then SMTP_BIN="$cmd" break From 60027ca7fed4befab4aaca044ffd01ae3f1fc02a Mon Sep 17 00:00:00 2001 From: medmunds Date: Wed, 17 Feb 2021 11:39:16 -0800 Subject: [PATCH 072/304] Change default SMTP_SECURE to "tls" Secure by default. Also try to minimize configuration errors. (Many ESPs/ISPs require STARTTLS, and most support it.) --- notify/smtp.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 71020818..293c665e 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -11,13 +11,13 @@ # SMTP_TO="to@example.com" # required # SMTP_HOST="smtp.example.com" # required # SMTP_PORT="25" # defaults to 25, 465 or 587 depending on SMTP_SECURE -# SMTP_SECURE="none" # one of "none", "ssl" (implicit TLS, TLS Wrapper), "tls" (explicit TLS, STARTTLS) +# SMTP_SECURE="tls" # one of "none", "ssl" (implicit TLS, TLS Wrapper), "tls" (explicit TLS, STARTTLS) # SMTP_USERNAME="" # set if SMTP server requires login # SMTP_PASSWORD="" # set if SMTP server requires login # SMTP_TIMEOUT="30" # seconds for SMTP operations to timeout # SMTP_BIN="/path/to/python_or_curl" # default finds first of python3, python2.7, python, pypy3, pypy, curl on PATH -SMTP_SECURE_DEFAULT="none" +SMTP_SECURE_DEFAULT="tls" SMTP_TIMEOUT_DEFAULT="30" # subject content statuscode From 817ccba687e4015b4e21a2a14d5b79c8a58249f2 Mon Sep 17 00:00:00 2001 From: czeming Date: Sat, 20 Feb 2021 17:16:33 +0800 Subject: [PATCH 073/304] Update dns_dp.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 没有encode中文字符会导致提交失败 --- dnsapi/dns_dp.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_dp.sh b/dnsapi/dns_dp.sh index 033fa5aa..9b8b7a8b 100755 --- a/dnsapi/dns_dp.sh +++ b/dnsapi/dns_dp.sh @@ -89,7 +89,7 @@ add_record() { _info "Adding record" - if ! _rest POST "Record.Create" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=默认"; then + if ! _rest POST "Record.Create" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=%E9%BB%98%E8%AE%A4"; then return 1 fi From 3bb1986bb525e191e2d5cb2eb30eff12c6875ae8 Mon Sep 17 00:00:00 2001 From: Geert Hendrickx Date: Tue, 23 Feb 2021 10:28:17 +0100 Subject: [PATCH 074/304] No need to include EC parameters explicitly with the private key. (they are embedded) --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 5f7a1642..3b27e7db 100755 --- a/acme.sh +++ b/acme.sh @@ -1124,7 +1124,7 @@ _createkey() { if _isEccKey "$length"; then _debug "Using ec name: $eccname" - if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -genkey 2>/dev/null)"; then + if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -noout -genkey 2>/dev/null)"; then echo "$_opkey" >"$f" else _err "error ecc key name: $eccname" From e0946b822debf2b16f46cf4a1ebdab89b73270ac Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 25 Feb 2021 07:45:22 +0800 Subject: [PATCH 075/304] fix https://github.com/acmesh-official/acme.sh/issues/3402 --- acme.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 3b27e7db..e643e327 100755 --- a/acme.sh +++ b/acme.sh @@ -562,8 +562,16 @@ if _exists xargs && [ "$(printf %s '\\x41' | xargs printf)" = 'A' ]; then fi _h2b() { - if _exists xxd && xxd -r -p 2>/dev/null; then - return + if _exists xxd; then + if _contains "$(xxd --help 2>&1)" "assumes -c30"; then + if xxd -r -p -c 9999 2>/dev/null; then + return + fi + else + if xxd -r -p 2>/dev/null; then + return + fi + fi fi hex=$(cat) From 56f032ee82555ae5e56edc58b86bcae5a8040b7d Mon Sep 17 00:00:00 2001 From: Kristian Johansson Date: Wed, 24 Feb 2021 08:53:35 +0100 Subject: [PATCH 076/304] Fixes response handling and thereby allow issuing of subdomain certs --- dnsapi/dns_simply.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index d053dcf6..b38d0ed3 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -6,7 +6,7 @@ #SIMPLY_ApiKey="apikey" # #SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]" - +SIMPLY_SUCCESS_CODE='"status": 200' SIMPLY_Api_Default="https://api.simply.com/1" ######## Public functions ##################### @@ -171,7 +171,7 @@ _get_root() { return 1 fi - if _contains "$response" '"code":"NOT_FOUND"'; then + if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then _debug "$h not found" else _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) @@ -196,6 +196,12 @@ _simply_add_record() { return 1 fi + if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then + _err "Call to API not sucessfull, see below message for more details" + _err "$response" + return 1 + fi + return 0 } @@ -211,6 +217,12 @@ _simply_delete_record() { return 1 fi + if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then + _err "Call to API not sucessfull, see below message for more details" + _err "$response" + return 1 + fi + return 0 } From c705c5e77894e7c88edd27aa089b44f9e6fc9dd7 Mon Sep 17 00:00:00 2001 From: Kristian Johansson Date: Wed, 24 Feb 2021 17:34:28 +0100 Subject: [PATCH 077/304] Adds comment --- dnsapi/dns_simply.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index b38d0ed3..e0e05017 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -6,9 +6,11 @@ #SIMPLY_ApiKey="apikey" # #SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]" -SIMPLY_SUCCESS_CODE='"status": 200' SIMPLY_Api_Default="https://api.simply.com/1" +#This is used for determining success of REST call +SIMPLY_SUCCESS_CODE='"status": 200' + ######## Public functions ##################### #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_simply_add() { From 06b04cb60c872d6a68b88645256866e474a85c8d Mon Sep 17 00:00:00 2001 From: Lukas Brocke Date: Tue, 23 Feb 2021 19:49:58 +0100 Subject: [PATCH 078/304] dnsapi/ionos: Use POST instead of PATCH for adding TXT record The API now supports a POST route for adding records. Therefore checking for already existing records and including them in a PATCH request is no longer necessary. --- dnsapi/dns_ionos.sh | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/dnsapi/dns_ionos.sh b/dnsapi/dns_ionos.sh index e6bd5000..aaf8580f 100755 --- a/dnsapi/dns_ionos.sh +++ b/dnsapi/dns_ionos.sh @@ -24,20 +24,9 @@ dns_ionos_add() { return 1 fi - _new_record="{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}" + _body="[{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}]" - # As no POST route is supported by the API, check for existing records and include them in the PATCH request in order not delete them. - # This is required to support ACME v2 wildcard certificate creation, where two TXT records for the same domain name are created. - - _ionos_get_existing_records "$fulldomain" "$_zone_id" - - if [ "$_existing_records" ]; then - _body="[$_new_record,$_existing_records]" - else - _body="[$_new_record]" - fi - - if _ionos_rest PATCH "$IONOS_ROUTE_ZONES/$_zone_id" "$_body" && [ -z "$response" ]; then + if _ionos_rest POST "$IONOS_ROUTE_ZONES/$_zone_id/records" "$_body" && [ -z "$response" ]; then _info "TXT record has been created successfully." return 0 fi @@ -125,17 +114,6 @@ _get_root() { return 1 } -_ionos_get_existing_records() { - fulldomain=$1 - zone_id=$2 - - if _ionos_rest GET "$IONOS_ROUTE_ZONES/$zone_id?recordName=$fulldomain&recordType=TXT"; then - response="$(echo "$response" | tr -d "\n")" - - _existing_records="$(printf "%s\n" "$response" | _egrep_o "\"records\":\[.*\]" | _head_n 1 | cut -d '[' -f 2 | sed 's/]//')" - fi -} - _ionos_get_record() { fulldomain=$1 zone_id=$2 @@ -168,7 +146,7 @@ _ionos_rest() { export _H2="Accept: application/json" export _H3="Content-Type: application/json" - response="$(_post "$data" "$IONOS_API$route" "" "$method")" + response="$(_post "$data" "$IONOS_API$route" "" "$method" "application/json")" else export _H2="Accept: */*" From 22a377f04abe44197edc1d2fe1c31db857b67f3b Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 1 Mar 2021 18:13:50 +0800 Subject: [PATCH 079/304] fix https://github.com/acmesh-official/acme.sh/issues/3433 --- acme.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/acme.sh b/acme.sh index e643e327..de77aee0 100755 --- a/acme.sh +++ b/acme.sh @@ -2133,6 +2133,12 @@ _send_signed_request() { _sleep $_sleep_retry_sec continue fi + if _contains "$_body" "The Replay Nonce is not recognized"; then + _info "The replay Nonce is not valid, let's get a new one, Sleeping $_sleep_retry_sec seconds." + _CACHED_NONCE="" + _sleep $_sleep_retry_sec + continue + fi fi return 0 done From a95bf7d3745b2c12057653e44d4b1694880efe82 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 4 Mar 2021 21:38:51 +0800 Subject: [PATCH 080/304] fix https://github.com/acmesh-official/acme.sh/issues/3019 --- dnsapi/dns_namecheap.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index 7ce39fa9..5e1f4791 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -208,7 +208,7 @@ _namecheap_parse_host() { _hostid=$(echo "$_host" | _egrep_o ' HostId="[^"]*' | cut -d '"' -f 2) _hostname=$(echo "$_host" | _egrep_o ' Name="[^"]*' | cut -d '"' -f 2) _hosttype=$(echo "$_host" | _egrep_o ' Type="[^"]*' | cut -d '"' -f 2) - _hostaddress=$(echo "$_host" | _egrep_o ' Address="[^"]*' | cut -d '"' -f 2) + _hostaddress=$(echo "$_host" | _egrep_o ' Address="[^"]*' | cut -d '"' -f 2 | _xml_decode) _hostmxpref=$(echo "$_host" | _egrep_o ' MXPref="[^"]*' | cut -d '"' -f 2) _hostttl=$(echo "$_host" | _egrep_o ' TTL="[^"]*' | cut -d '"' -f 2) @@ -405,3 +405,11 @@ _namecheap_set_tld_sld() { done } + +_xml_decode() { + sed 's/"/"/g' +} + + + + From 282269885eeb1aa3e4c01e0837d9f8649b830164 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 4 Mar 2021 21:50:54 +0800 Subject: [PATCH 081/304] fix format --- dnsapi/dns_namecheap.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index 5e1f4791..e3dc7997 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -410,6 +410,3 @@ _xml_decode() { sed 's/"/"/g' } - - - From 27725bb2d3c29667e1a763a3897198cfa8ddb612 Mon Sep 17 00:00:00 2001 From: anom-human <80478363+anom-human@users.noreply.github.com> Date: Thu, 11 Mar 2021 19:11:02 +0100 Subject: [PATCH 082/304] Update dns_servercow.sh to support wildcard certs Updated dns_servercow.sh to support txt records with multiple entries. This supports wildcard certificates that require txt records with the same name and different contents. --- dnsapi/dns_servercow.sh | 42 +++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_servercow.sh b/dnsapi/dns_servercow.sh index e73d85b0..39f16396 100755 --- a/dnsapi/dns_servercow.sh +++ b/dnsapi/dns_servercow.sh @@ -48,18 +48,44 @@ dns_servercow_add() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - - if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then - if printf -- "%s" "$response" | grep "ok" >/dev/null; then - _info "Added, OK" - return 0 + + # check whether a txt record already exists for the subdomain + if printf -- "%s" "$response" | grep "{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\"" >/dev/null; then + _info "A txt record with the same name already exists." + # trim the string on the left + txtvalue_old=${response#*{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\",\"content\":\"} + # trim the string on the right + txtvalue_old=${txtvalue_old%%\"*} + + _debug txtvalue_old "$txtvalue_old" + + _info "Add the new txtvalue to the existing txt record." + if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":[\"$txtvalue\",\"$txtvalue_old\"],\"ttl\":20}"; then + if printf -- "%s" "$response" | grep "ok" >/dev/null; then + _info "Added additional txtvalue, OK" + return 0 + else + _err "add txt record error." + return 1 + fi + fi + _err "add txt record error." + return 1 else + _info "There is no txt record with the name yet." + if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then + if printf -- "%s" "$response" | grep "ok" >/dev/null; then + _info "Added, OK" + return 0 + else + _err "add txt record error." + return 1 + fi + fi _err "add txt record error." return 1 - fi fi - _err "add txt record error." - + return 1 } From b3b347769e1e00deb4300b5a35621ac1d4bf9e55 Mon Sep 17 00:00:00 2001 From: anom-human <80478363+anom-human@users.noreply.github.com> Date: Thu, 11 Mar 2021 20:25:49 +0100 Subject: [PATCH 083/304] Update dns_servercow.sh to support wildcard certs Updated dns_servercow.sh to support txt records with multiple entries. This supports wildcard certificates that require txt records with the same name and different contents. --- dnsapi/dns_servercow.sh | 64 ++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/dnsapi/dns_servercow.sh b/dnsapi/dns_servercow.sh index 39f16396..f70a2294 100755 --- a/dnsapi/dns_servercow.sh +++ b/dnsapi/dns_servercow.sh @@ -48,44 +48,44 @@ dns_servercow_add() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - - # check whether a txt record already exists for the subdomain + + # check whether a txt record already exists for the subdomain if printf -- "%s" "$response" | grep "{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\"" >/dev/null; then - _info "A txt record with the same name already exists." - # trim the string on the left - txtvalue_old=${response#*{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\",\"content\":\"} - # trim the string on the right - txtvalue_old=${txtvalue_old%%\"*} - - _debug txtvalue_old "$txtvalue_old" - - _info "Add the new txtvalue to the existing txt record." - if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":[\"$txtvalue\",\"$txtvalue_old\"],\"ttl\":20}"; then - if printf -- "%s" "$response" | grep "ok" >/dev/null; then - _info "Added additional txtvalue, OK" - return 0 - else - _err "add txt record error." + _info "A txt record with the same name already exists." + # trim the string on the left + txtvalue_old=${response#*{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\",\"content\":\"} + # trim the string on the right + txtvalue_old=${txtvalue_old%%\"*} + + _debug txtvalue_old "$txtvalue_old" + + _info "Add the new txtvalue to the existing txt record." + if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":[\"$txtvalue\",\"$txtvalue_old\"],\"ttl\":20}"; then + if printf -- "%s" "$response" | grep "ok" >/dev/null; then + _info "Added additional txtvalue, OK" + return 0 + else + _err "add txt record error." return 1 - fi fi - _err "add txt record error." - return 1 - else - _info "There is no txt record with the name yet." - if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then - if printf -- "%s" "$response" | grep "ok" >/dev/null; then - _info "Added, OK" - return 0 - else - _err "add txt record error." + fi + _err "add txt record error." + return 1 + else + _info "There is no txt record with the name yet." + if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then + if printf -- "%s" "$response" | grep "ok" >/dev/null; then + _info "Added, OK" + return 0 + else + _err "add txt record error." return 1 - fi fi - _err "add txt record error." - return 1 + fi + _err "add txt record error." + return 1 fi - + return 1 } From 88e758df0d906e2590023afdfc552a64326f7f4d Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 13 Mar 2021 20:43:25 +0800 Subject: [PATCH 084/304] fix https://github.com/acmesh-official/acme.sh/issues/3312 --- acme.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index de77aee0..3eebdbc7 100755 --- a/acme.sh +++ b/acme.sh @@ -5289,6 +5289,7 @@ signcsr() { _renew_hook="${10}" _local_addr="${11}" _challenge_alias="${12}" + _preferred_chain="${13}" _csrsubj=$(_readSubjectFromCSR "$_csrfile") if [ "$?" != "0" ]; then @@ -5335,7 +5336,7 @@ signcsr() { _info "Copy csr to: $CSR_PATH" cp "$_csrfile" "$CSR_PATH" - issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_addr" "$_challenge_alias" + issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_addr" "$_challenge_alias" "$_preferred_chain" } @@ -7432,7 +7433,7 @@ _process() { deploy "$_domain" "$_deploy_hook" "$_ecc" ;; signcsr) - signcsr "$_csr" "$_webroot" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" + signcsr "$_csr" "$_webroot" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" "$_preferred_chain" ;; showcsr) showcsr "$_csr" "$_domain" From 07809a4e6e1f5b586f94d001c72a1951243ca9d4 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 13 Mar 2021 20:46:12 +0800 Subject: [PATCH 085/304] fix format --- dnsapi/dns_namecheap.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index e3dc7997..d15d6b0e 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -409,4 +409,3 @@ _namecheap_set_tld_sld() { _xml_decode() { sed 's/"/"/g' } - From d15a53b809539c959ef4a792db3e08564ca5b6a2 Mon Sep 17 00:00:00 2001 From: Quentin Dreyer Date: Fri, 12 Mar 2021 12:03:36 +0100 Subject: [PATCH 086/304] feat: add dns_porkbun --- dnsapi/dns_porkbun.sh | 171 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 dnsapi/dns_porkbun.sh diff --git a/dnsapi/dns_porkbun.sh b/dnsapi/dns_porkbun.sh new file mode 100644 index 00000000..05ecb781 --- /dev/null +++ b/dnsapi/dns_porkbun.sh @@ -0,0 +1,171 @@ +#!/usr/bin/env sh + +# +#PORKBUN_API_KEY="pk1_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" +#PORKBUN_SECRET_API_KEY="sk1_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + +PORKBUN_Api="https://porkbun.com/api/json/v3" + +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_porkbun_add() { + fulldomain=$1 + txtvalue=$2 + + PORKBUN_API_KEY="${PORKBUN_API_KEY:-$(_readaccountconf_mutable PORKBUN_API_KEY)}" + PORKBUN_SECRET_API_KEY="${PORKBUN_SECRET_API_KEY:-$(_readaccountconf_mutable PORKBUN_SECRET_API_KEY)}" + + if [ -z "$PORKBUN_API_KEY" ] || [ -z "$PORKBUN_SECRET_API_KEY" ]; then + PORKBUN_API_KEY='' + PORKBUN_SECRET_API_KEY='' + _err "You didn't specify a Porkbun api key and secret api key yet." + _err "You can get yours from here https://porkbun.com/account/api." + return 1 + fi + + #save the credentials to the account conf file. + _saveaccountconf_mutable PORKBUN_API_KEY "$PORKBUN_API_KEY" + _saveaccountconf_mutable PORKBUN_SECRET_API_KEY "$PORKBUN_SECRET_API_KEY" + + _debug 'First detect the root zone' + if ! _get_root "$fulldomain"; then + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting txt records" + _porkbun_rest POST "dns/retrieve/$_domain" + + if ! echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null; then + _err "Error $response" + return 1 + fi + + # For wildcard cert, the main root domain and the wildcard domain have the same txt subdomain name, so + # we can not use updating anymore. + # count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2) + # _debug count "$count" + # if [ "$count" = "0" ]; then + _info "Adding record" + if _porkbun_rest POST "dns/create/$_domain" "{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":120}"; then + if _contains "$response" '\"status\":"SUCCESS"'; then + _info "Added, OK" + return 0 + elif _contains "$response" "The record already exists"; then + _info "Already exists, OK" + return 0 + else + _err "Add txt record error. ($response)" + return 1 + fi + fi + _err "Add txt record error." + return 1 + +} + +#fulldomain txtvalue +dns_porkbun_rm() { + fulldomain=$1 + txtvalue=$2 + + PORKBUN_API_KEY="${PORKBUN_API_KEY:-$(_readaccountconf_mutable PORKBUN_API_KEY)}" + PORKBUN_SECRET_API_KEY="${PORKBUN_SECRET_API_KEY:-$(_readaccountconf_mutable PORKBUN_SECRET_API_KEY)}" + + _debug 'First detect the root zone' + if ! _get_root "$fulldomain"; then + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting txt records" + _porkbun_rest POST "dns/retrieve/$_domain" + + if ! echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null; then + _err "Error: $response" + return 1 + fi + + count=$(echo "$response" | _egrep_o "\"count\": *[^,]*" | cut -d : -f 2 | tr -d " ") + _debug count "$count" + if [ "$count" = "0" ]; then + _info "Don't need to remove." + else + record_id=$(echo "$response" | tr '{' '\n' | grep "$txtvalue" | cut -d, -f1 | cut -d: -f2 | tr -d \") + _debug "record_id" "$record_id" + if [ -z "$record_id" ]; then + _err "Can not get record id to remove." + return 1 + fi + if ! _porkbun_rest POST "dns/delete/$_domain/$record_id"; then + _err "Delete record error." + return 1 + fi + echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null + fi + +} + +#################### Private functions below ################################## +#_acme-challenge.www.domain.com +#returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +_get_root() { + domain=$1 + i=1 + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug h "$h" + if [ -z "$h" ]; then + return 1 + fi + + if _porkbun_rest POST "dns/retrieve/$h"; then + if _contains "$response" "\"status\":\"SUCCESS\""; then + _sub_domain="$(echo "$fulldomain" | sed "s/\\.$_domain\$//")" + _domain=$h + return 0 + else + _debug "Go to next level of $_domain" + fi + else + _debug "Go to next level of $_domain" + fi + i=$(_math "$i" + 1) + done + + return 1 +} + +_porkbun_rest() { + m=$1 + ep="$2" + data="$3" + _debug "$ep" + + api_key_trimmed=$(echo "$PORKBUN_API_KEY" | tr -d '"') + secret_api_key_trimmed=$(echo "$PORKBUN_SECRET_API_KEY" | tr -d '"') + + test -z "$data" && data="{" || data="$(echo $data | cut -d'}' -f1)," + data="$data\"apikey\":\"$api_key_trimmed\",\"secretapikey\":\"$secret_api_key_trimmed\"}" + + export _H1="Content-Type: application/json" + + if [ "$m" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$PORKBUN_Api/$ep" "" "$m")" + else + response="$(_get "$PORKBUN_Api/$ep")" + fi + + if [ "$?" != "0" ]; then + _err "error $ep" + return 1 + fi + _debug2 response "$response" + return 0 +} From 0c76959b5ad302df917c6de3be2c1d80764612db Mon Sep 17 00:00:00 2001 From: qkdreyer Date: Sat, 13 Mar 2021 14:53:43 +0100 Subject: [PATCH 087/304] fix: prevent rate limit --- dnsapi/dns_porkbun.sh | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/dnsapi/dns_porkbun.sh b/dnsapi/dns_porkbun.sh index 05ecb781..18da6b2f 100644 --- a/dnsapi/dns_porkbun.sh +++ b/dnsapi/dns_porkbun.sh @@ -35,14 +35,6 @@ dns_porkbun_add() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - _debug "Getting txt records" - _porkbun_rest POST "dns/retrieve/$_domain" - - if ! echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null; then - _err "Error $response" - return 1 - fi - # For wildcard cert, the main root domain and the wildcard domain have the same txt subdomain name, so # we can not use updating anymore. # count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2) @@ -81,14 +73,6 @@ dns_porkbun_rm() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - _debug "Getting txt records" - _porkbun_rest POST "dns/retrieve/$_domain" - - if ! echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null; then - _err "Error: $response" - return 1 - fi - count=$(echo "$response" | _egrep_o "\"count\": *[^,]*" | cut -d : -f 2 | tr -d " ") _debug count "$count" if [ "$count" = "0" ]; then @@ -162,6 +146,8 @@ _porkbun_rest() { response="$(_get "$PORKBUN_Api/$ep")" fi + _sleep 3 # prevent rate limit + if [ "$?" != "0" ]; then _err "error $ep" return 1 From 3428fe9b345f71665448c09ec15e8a77394594d4 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 21 Mar 2021 22:46:35 +0800 Subject: [PATCH 088/304] fix freebsd --- .github/workflows/DNS.yml | 2 +- .github/workflows/LetsEncrypt.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index ed0426ad..5ff1f8ab 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -184,7 +184,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.1.2 + - uses: vmactions/freebsd-vm@v0.1.3 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkg install -y socat curl diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 7c398c09..7193d88d 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -111,7 +111,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.1.2 + - uses: vmactions/freebsd-vm@v0.1.3 with: envs: 'NGROK_TOKEN TEST_LOCAL' prepare: pkg install -y socat curl From 64e41a8056c396159a97754bcdb8210a25d3c2c1 Mon Sep 17 00:00:00 2001 From: wout Date: Wed, 10 Mar 2021 16:18:07 +0100 Subject: [PATCH 089/304] Add wildcard certificate support for dns_constellix --- dnsapi/dns_constellix.sh | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_constellix.sh b/dnsapi/dns_constellix.sh index 42df710d..d0d3132a 100644 --- a/dnsapi/dns_constellix.sh +++ b/dnsapi/dns_constellix.sh @@ -30,16 +30,38 @@ dns_constellix_add() { return 1 fi - _info "Adding TXT record" - if _constellix_rest POST "domains/${_domain_id}/records" "[{\"type\":\"txt\",\"add\":true,\"set\":{\"name\":\"${_sub_domain}\",\"ttl\":120,\"roundRobin\":[{\"value\":\"${txtvalue}\"}]}}]"; then - if printf -- "%s" "$response" | grep "{\"success\":\"1 record(s) added, 0 record(s) updated, 0 record(s) deleted\"}" >/dev/null; then - _info "Added" - return 0 + # To support wildcard certificates, try to find existig TXT record and update it. + _info "Search existing TXT record" + if _constellix_rest GET "domains/${_domain_id}/records/TXT/search?exact=${_sub_domain}"; then + if printf -- "%s" "$response" | grep "{\"errors\":\[\"Requested record was not found\"\]}" >/dev/null; then + _info "Adding TXT record" + if _constellix_rest POST "domains/${_domain_id}/records" "[{\"type\":\"txt\",\"add\":true,\"set\":{\"name\":\"${_sub_domain}\",\"ttl\":60,\"roundRobin\":[{\"value\":\"${txtvalue}\"}]}}]"; then + if printf -- "%s" "$response" | grep "{\"success\":\"1 record(s) added, 0 record(s) updated, 0 record(s) deleted\"}" >/dev/null; then + _info "Added" + return 0 + else + _err "Error adding TXT record" + fi + fi else - _err "Error adding TXT record" - return 1 + _record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]+" | cut -d ':' -f 2) + if _constellix_rest GET "domains/${_domain_id}/records/TXT/${_record_id}"; then + _new_rr_values=$(printf "%s\n" "$response" | _egrep_o "\"roundRobin\":\[.*?\]" | sed "s/\]$/,{\"value\":\"${txtvalue}\"}]/") + _debug _new_rr_values $_new_rr_values + _info "Updating TXT record" + if _constellix_rest PUT "domains/${_domain_id}/records/TXT/${_record_id}" "{\"name\":\"${_sub_domain}\",\"ttl\":60,${_new_rr_values}}"; then + if printf -- "%s" "$response" | grep "{\"success\":\"Record.*updated successfully\"}" >/dev/null; then + _info "Updated" + return 0 + else + _err "Error updating TXT record" + fi + fi + fi fi fi + + return 1 } # Usage: fulldomain txtvalue @@ -68,9 +90,10 @@ dns_constellix_rm() { return 0 else _err "Error removing TXT record" - return 1 fi fi + + return 1 } #################### Private functions below ################################## From ae74ec7557a101496c9f4f796229c88d0b2a962d Mon Sep 17 00:00:00 2001 From: wout Date: Wed, 10 Mar 2021 16:32:09 +0100 Subject: [PATCH 090/304] Fix checks --- dnsapi/dns_constellix.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_constellix.sh b/dnsapi/dns_constellix.sh index d0d3132a..5c20a917 100644 --- a/dnsapi/dns_constellix.sh +++ b/dnsapi/dns_constellix.sh @@ -38,7 +38,7 @@ dns_constellix_add() { if _constellix_rest POST "domains/${_domain_id}/records" "[{\"type\":\"txt\",\"add\":true,\"set\":{\"name\":\"${_sub_domain}\",\"ttl\":60,\"roundRobin\":[{\"value\":\"${txtvalue}\"}]}}]"; then if printf -- "%s" "$response" | grep "{\"success\":\"1 record(s) added, 0 record(s) updated, 0 record(s) deleted\"}" >/dev/null; then _info "Added" - return 0 + return 0 else _err "Error adding TXT record" fi @@ -47,7 +47,7 @@ dns_constellix_add() { _record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]+" | cut -d ':' -f 2) if _constellix_rest GET "domains/${_domain_id}/records/TXT/${_record_id}"; then _new_rr_values=$(printf "%s\n" "$response" | _egrep_o "\"roundRobin\":\[.*?\]" | sed "s/\]$/,{\"value\":\"${txtvalue}\"}]/") - _debug _new_rr_values $_new_rr_values + _debug _new_rr_values "$_new_rr_values" _info "Updating TXT record" if _constellix_rest PUT "domains/${_domain_id}/records/TXT/${_record_id}" "{\"name\":\"${_sub_domain}\",\"ttl\":60,${_new_rr_values}}"; then if printf -- "%s" "$response" | grep "{\"success\":\"Record.*updated successfully\"}" >/dev/null; then From 7a010a2b8ce69ca3a1e580130f1c9f258eeb21b9 Mon Sep 17 00:00:00 2001 From: wout Date: Wed, 10 Mar 2021 23:34:21 +0100 Subject: [PATCH 091/304] Improve the remove handling so it does not print errors --- dnsapi/dns_constellix.sh | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/dnsapi/dns_constellix.sh b/dnsapi/dns_constellix.sh index 5c20a917..fb4e278e 100644 --- a/dnsapi/dns_constellix.sh +++ b/dnsapi/dns_constellix.sh @@ -30,8 +30,8 @@ dns_constellix_add() { return 1 fi - # To support wildcard certificates, try to find existig TXT record and update it. - _info "Search existing TXT record" + # The TXT record might already exist when working with wilcard certificates. In that case, update the record by adding the new value. + _debug "Search TXT record" if _constellix_rest GET "domains/${_domain_id}/records/TXT/search?exact=${_sub_domain}"; then if printf -- "%s" "$response" | grep "{\"errors\":\[\"Requested record was not found\"\]}" >/dev/null; then _info "Adding TXT record" @@ -83,13 +83,22 @@ dns_constellix_rm() { return 1 fi - _info "Removing TXT record" - if _constellix_rest POST "domains/${_domain_id}/records" "[{\"type\":\"txt\",\"delete\":true,\"filter\":{\"field\":\"name\",\"op\":\"eq\",\"value\":\"${_sub_domain}\"}}]"; then - if printf -- "%s" "$response" | grep "{\"success\":\"0 record(s) added, 0 record(s) updated, 1 record(s) deleted\"}" >/dev/null; then + # The TXT record might have been removed already when working with some wildcard certificates. + _debug "Search TXT record" + if _constellix_rest GET "domains/${_domain_id}/records/TXT/search?exact=${_sub_domain}"; then + if printf -- "%s" "$response" | grep "{\"errors\":\[\"Requested record was not found\"\]}" >/dev/null; then _info "Removed" return 0 else - _err "Error removing TXT record" + _info "Removing TXT record" + if _constellix_rest POST "domains/${_domain_id}/records" "[{\"type\":\"txt\",\"delete\":true,\"filter\":{\"field\":\"name\",\"op\":\"eq\",\"value\":\"${_sub_domain}\"}}]"; then + if printf -- "%s" "$response" | grep "{\"success\":\"0 record(s) added, 0 record(s) updated, 1 record(s) deleted\"}" >/dev/null; then + _info "Removed" + return 0 + else + _err "Error removing TXT record" + fi + fi fi fi From 2899d696861fd1e47f547a2307a36a5e521593de Mon Sep 17 00:00:00 2001 From: wout Date: Wed, 10 Mar 2021 23:36:34 +0100 Subject: [PATCH 092/304] Fix typo --- dnsapi/dns_constellix.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_constellix.sh b/dnsapi/dns_constellix.sh index fb4e278e..75211a6f 100644 --- a/dnsapi/dns_constellix.sh +++ b/dnsapi/dns_constellix.sh @@ -30,7 +30,7 @@ dns_constellix_add() { return 1 fi - # The TXT record might already exist when working with wilcard certificates. In that case, update the record by adding the new value. + # The TXT record might already exist when working with wildcard certificates. In that case, update the record by adding the new value. _debug "Search TXT record" if _constellix_rest GET "domains/${_domain_id}/records/TXT/search?exact=${_sub_domain}"; then if printf -- "%s" "$response" | grep "{\"errors\":\[\"Requested record was not found\"\]}" >/dev/null; then From 2ef8705b4ff2f30261a760585c9995626b89cdb6 Mon Sep 17 00:00:00 2001 From: wout Date: Tue, 23 Mar 2021 21:20:27 +0100 Subject: [PATCH 095/304] While [0-9]+ is a bit more correct than [0-9]*, the former does not seem to work on Solaris. --- dnsapi/dns_constellix.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_constellix.sh b/dnsapi/dns_constellix.sh index 75211a6f..2c3b3265 100644 --- a/dnsapi/dns_constellix.sh +++ b/dnsapi/dns_constellix.sh @@ -44,7 +44,7 @@ dns_constellix_add() { fi fi else - _record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]+" | cut -d ':' -f 2) + _record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]*" | cut -d ':' -f 2) if _constellix_rest GET "domains/${_domain_id}/records/TXT/${_record_id}"; then _new_rr_values=$(printf "%s\n" "$response" | _egrep_o "\"roundRobin\":\[.*?\]" | sed "s/\]$/,{\"value\":\"${txtvalue}\"}]/") _debug _new_rr_values "$_new_rr_values" @@ -123,7 +123,7 @@ _get_root() { fi if _contains "$response" "\"name\":\"$h\""; then - _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]+" | cut -d ':' -f 2) + _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]*" | cut -d ':' -f 2) if [ "$_domain_id" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d '.' -f 1-$p) _domain="$h" From ee73d4e583e2d8d86658afba876fb3691f179c65 Mon Sep 17 00:00:00 2001 From: wout Date: Wed, 24 Mar 2021 09:01:54 +0100 Subject: [PATCH 096/304] Catch the situation when the TXT record is updated with the same value --- dnsapi/dns_constellix.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dnsapi/dns_constellix.sh b/dnsapi/dns_constellix.sh index 2c3b3265..914f79df 100644 --- a/dnsapi/dns_constellix.sh +++ b/dnsapi/dns_constellix.sh @@ -53,6 +53,9 @@ dns_constellix_add() { if printf -- "%s" "$response" | grep "{\"success\":\"Record.*updated successfully\"}" >/dev/null; then _info "Updated" return 0 + elif printf -- "%s" "$response" | grep "{\"errors\":\[\"Contents are identical\"\]}" >/dev/null; then + _info "Already exists, no need to update" + return 0 else _err "Error updating TXT record" fi From 78769ed8945b137be5dc279baf3df496d98d6cb1 Mon Sep 17 00:00:00 2001 From: wout Date: Wed, 24 Mar 2021 13:56:14 +0100 Subject: [PATCH 097/304] Workaround for Solaris, as it does not support non-greedy regex --- dnsapi/dns_constellix.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_constellix.sh b/dnsapi/dns_constellix.sh index 914f79df..69d216f0 100644 --- a/dnsapi/dns_constellix.sh +++ b/dnsapi/dns_constellix.sh @@ -46,7 +46,7 @@ dns_constellix_add() { else _record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]*" | cut -d ':' -f 2) if _constellix_rest GET "domains/${_domain_id}/records/TXT/${_record_id}"; then - _new_rr_values=$(printf "%s\n" "$response" | _egrep_o "\"roundRobin\":\[.*?\]" | sed "s/\]$/,{\"value\":\"${txtvalue}\"}]/") + _new_rr_values=$(printf "%s\n" "$response" | _egrep_o '"roundRobin":\[[^]]*\]' | sed "s/\]$/,{\"value\":\"${txtvalue}\"}]/") _debug _new_rr_values "$_new_rr_values" _info "Updating TXT record" if _constellix_rest PUT "domains/${_domain_id}/records/TXT/${_record_id}" "{\"name\":\"${_sub_domain}\",\"ttl\":60,${_new_rr_values}}"; then From 392de503cdf51dcab4bbc37597968033d05a3d56 Mon Sep 17 00:00:00 2001 From: Christophe Le Guern Date: Mon, 29 Mar 2021 15:10:14 +0200 Subject: [PATCH 098/304] Use 'vault kv put' instead of 'vault write' When using vault_cli with a kv2 path, it isn't working. I have the following error: ``` WARNING! The following warnings were returned from Vault: * Invalid path for a versioned K/V secrets engine. See the API docs for the appropriate API endpoints to use. If using the Vault CLI, use 'vault kv put' for this operation. ``` The new way to write data is to use `vault kv put`, it is compatible with kv1 and kv2. Ref: https://www.vaultproject.io/docs/commands#reading-and-writing-data ``` The original version of K/V used the common read and write operations. A more advanced K/V Version 2 engine was released in Vault 0.10 and introduced the kv get and kv put commands. ``` --- deploy/vault_cli.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/deploy/vault_cli.sh b/deploy/vault_cli.sh index 8b854137..cbb8cc59 100644 --- a/deploy/vault_cli.sh +++ b/deploy/vault_cli.sh @@ -50,12 +50,12 @@ vault_cli_deploy() { fi if [ -n "$FABIO" ]; then - $VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}" cert=@"$_cfullchain" key=@"$_ckey" || return 1 + $VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}" cert=@"$_cfullchain" key=@"$_ckey" || return 1 else - $VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/cert.pem" value=@"$_ccert" || return 1 - $VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/cert.key" value=@"$_ckey" || return 1 - $VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/chain.pem" value=@"$_cca" || return 1 - $VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/fullchain.pem" value=@"$_cfullchain" || return 1 + $VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/cert.pem" value=@"$_ccert" || return 1 + $VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/cert.key" value=@"$_ckey" || return 1 + $VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/chain.pem" value=@"$_cca" || return 1 + $VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/fullchain.pem" value=@"$_cfullchain" || return 1 fi } From fea67cf2ec91cf7f2c4dc8112cd9e8a013549944 Mon Sep 17 00:00:00 2001 From: Jan-Philipp Benecke Date: Fri, 26 Mar 2021 15:37:12 +0100 Subject: [PATCH 099/304] Make uploading cert to subaccount possible --- deploy/cleverreach.sh | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/deploy/cleverreach.sh b/deploy/cleverreach.sh index 552d8149..10670f34 100644 --- a/deploy/cleverreach.sh +++ b/deploy/cleverreach.sh @@ -25,6 +25,7 @@ cleverreach_deploy() { _getdeployconf DEPLOY_CLEVERREACH_CLIENT_ID _getdeployconf DEPLOY_CLEVERREACH_CLIENT_SECRET + _getdeployconf DEPLOY_CLEVERREACH_SUBCLIENT_ID if [ -z "${DEPLOY_CLEVERREACH_CLIENT_ID}" ]; then _err "CleverReach Client ID is not found, please define DEPLOY_CLEVERREACH_CLIENT_ID." @@ -37,6 +38,7 @@ cleverreach_deploy() { _savedeployconf DEPLOY_CLEVERREACH_CLIENT_ID "${DEPLOY_CLEVERREACH_CLIENT_ID}" _savedeployconf DEPLOY_CLEVERREACH_CLIENT_SECRET "${DEPLOY_CLEVERREACH_CLIENT_SECRET}" + _savedeployconf DEPLOY_CLEVERREACH_SUBCLIENT_ID "${DEPLOY_CLEVERREACH_SUBCLIENT_ID}" _info "Obtaining a CleverReach access token" @@ -50,14 +52,26 @@ cleverreach_deploy() { _debug _regex "$_regex" _access_token=$(echo "$_auth_result" | _json_decode | sed -n "s/$_regex/\1/p") + if ${DEPLOY_CLEVERREACH_SUBCLIENT_ID}; then + _info "Obtaining token for sub-client" + export _H1="Authorization: Bearer ${_access_token}" + _subclient_token_result="$(_get "https://rest.cleverreach.com/v3/clients/$DEPLOY_CLEVERREACH_SUBCLIENT_ID}/token")" + _access_token=$(echo "$_subclient_token_result" | _json_decode | sed -n "s/$_regex/\1/p") + + _debug "Destroying parent token at CleverReach" + _post "" "https://rest.cleverreach.com/v3/oauth/token.json" "" "DELETE" "application/json" + fi + _info "Uploading certificate and key to CleverReach" _certData="{\"cert\":\"$(_json_encode <"$_cfullchain")\", \"key\":\"$(_json_encode <"$_ckey")\"}" export _H1="Authorization: Bearer ${_access_token}" _add_cert_result="$(_post "$_certData" "https://rest.cleverreach.com/v3/ssl" "" "POST" "application/json")" - _debug "Destroying token at CleverReach" - _post "" "https://rest.cleverreach.com/v3/oauth/token.json" "" "DELETE" "application/json" + if ! ${DEPLOY_CLEVERREACH_SUBCLIENT_ID}; then + _debug "Destroying token at CleverReach" + _post "" "https://rest.cleverreach.com/v3/oauth/token.json" "" "DELETE" "application/json" + fi if ! echo "$_add_cert_result" | grep '"error":' >/dev/null; then _info "Uploaded certificate successfully" From b37aa1985a28ec999c9681e2be75d7feba5e3391 Mon Sep 17 00:00:00 2001 From: Jan-Philipp Benecke Date: Tue, 30 Mar 2021 09:13:32 +0200 Subject: [PATCH 100/304] Make uploading cert to subaccount possible --- deploy/cleverreach.sh | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/deploy/cleverreach.sh b/deploy/cleverreach.sh index 10670f34..03fccc74 100644 --- a/deploy/cleverreach.sh +++ b/deploy/cleverreach.sh @@ -17,6 +17,8 @@ cleverreach_deploy() { _cca="$4" _cfullchain="$5" + _rest_endpoint="https://rest.cleverreach.com" + _debug _cdomain "$_cdomain" _debug _ckey "$_ckey" _debug _ccert "$_ccert" @@ -43,7 +45,7 @@ cleverreach_deploy() { _info "Obtaining a CleverReach access token" _data="{\"grant_type\": \"client_credentials\", \"client_id\": \"${DEPLOY_CLEVERREACH_CLIENT_ID}\", \"client_secret\": \"${DEPLOY_CLEVERREACH_CLIENT_SECRET}\"}" - _auth_result="$(_post "$_data" "https://rest.cleverreach.com/oauth/token.php" "" "POST" "application/json")" + _auth_result="$(_post "$_data" "$_rest_endpoint/oauth/token.php" "" "POST" "application/json")" _debug _data "$_data" _debug _auth_result "$_auth_result" @@ -52,25 +54,31 @@ cleverreach_deploy() { _debug _regex "$_regex" _access_token=$(echo "$_auth_result" | _json_decode | sed -n "s/$_regex/\1/p") - if ${DEPLOY_CLEVERREACH_SUBCLIENT_ID}; then - _info "Obtaining token for sub-client" + _debug _subclient "${DEPLOY_CLEVERREACH_SUBCLIENT_ID}" + + if ! [ -z "${DEPLOY_CLEVERREACH_SUBCLIENT_ID}" ]; then + _info "Obtaining token for sub-client ${DEPLOY_CLEVERREACH_SUBCLIENT_ID}" export _H1="Authorization: Bearer ${_access_token}" - _subclient_token_result="$(_get "https://rest.cleverreach.com/v3/clients/$DEPLOY_CLEVERREACH_SUBCLIENT_ID}/token")" - _access_token=$(echo "$_subclient_token_result" | _json_decode | sed -n "s/$_regex/\1/p") + _subclient_token_result="$(_get "$_rest_endpoint/v3/clients/$DEPLOY_CLEVERREACH_SUBCLIENT_ID/token")" + _access_token=$(echo "$_subclient_token_result" | sed -n "s/\"//p") + + _debug _subclient_token_result "$_access_token" - _debug "Destroying parent token at CleverReach" - _post "" "https://rest.cleverreach.com/v3/oauth/token.json" "" "DELETE" "application/json" + _info "Destroying parent token at CleverReach, as it not needed anymore" + _destroy_result="$(_post "" "$_rest_endpoint/v3/oauth/token.json" "" "DELETE" "application/json")" + _debug _destroy_result "$_destroy_result" fi _info "Uploading certificate and key to CleverReach" _certData="{\"cert\":\"$(_json_encode <"$_cfullchain")\", \"key\":\"$(_json_encode <"$_ckey")\"}" export _H1="Authorization: Bearer ${_access_token}" - _add_cert_result="$(_post "$_certData" "https://rest.cleverreach.com/v3/ssl" "" "POST" "application/json")" + _add_cert_result="$(_post "$_certData" "$_rest_endpoint/v3/ssl" "" "POST" "application/json")" - if ! ${DEPLOY_CLEVERREACH_SUBCLIENT_ID}; then - _debug "Destroying token at CleverReach" - _post "" "https://rest.cleverreach.com/v3/oauth/token.json" "" "DELETE" "application/json" + if [ -z "${DEPLOY_CLEVERREACH_SUBCLIENT_ID}" ]; then + _info "Destroying token at CleverReach, as it not needed anymore" + _destroy_result="$(_post "" "$_rest_endpoint/v3/oauth/token.json" "" "DELETE" "application/json")" + _debug _destroy_result "$_destroy_result" fi if ! echo "$_add_cert_result" | grep '"error":' >/dev/null; then From b065544fbe2042ee78f776b3e19642f82df1f72d Mon Sep 17 00:00:00 2001 From: Jan-Philipp Benecke Date: Tue, 30 Mar 2021 09:18:33 +0200 Subject: [PATCH 101/304] Make CI happy --- deploy/cleverreach.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/cleverreach.sh b/deploy/cleverreach.sh index 03fccc74..a460a139 100644 --- a/deploy/cleverreach.sh +++ b/deploy/cleverreach.sh @@ -56,7 +56,7 @@ cleverreach_deploy() { _debug _subclient "${DEPLOY_CLEVERREACH_SUBCLIENT_ID}" - if ! [ -z "${DEPLOY_CLEVERREACH_SUBCLIENT_ID}" ]; then + if [ -n "${DEPLOY_CLEVERREACH_SUBCLIENT_ID}" ]; then _info "Obtaining token for sub-client ${DEPLOY_CLEVERREACH_SUBCLIENT_ID}" export _H1="Authorization: Bearer ${_access_token}" _subclient_token_result="$(_get "$_rest_endpoint/v3/clients/$DEPLOY_CLEVERREACH_SUBCLIENT_ID/token")" From bae08da4325fc775e1dd5faec57c5787efe5dffb Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Thu, 8 Apr 2021 16:36:42 +1200 Subject: [PATCH 102/304] Escape asterisks in notification content This messes with markdown parsing Signed-off-by: Mike Beattie --- notify/telegram.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/notify/telegram.sh b/notify/telegram.sh index b1306ee1..d9b375d0 100644 --- a/notify/telegram.sh +++ b/notify/telegram.sh @@ -27,6 +27,7 @@ telegram_send() { fi _saveaccountconf_mutable TELEGRAM_BOT_CHATID "$TELEGRAM_BOT_CHATID" + _content="$(printf "%s" "$_content" | sed -e 's/*/\\\\*/')" _content="$(printf "*%s*\n%s" "$_subject" "$_content" | _json_encode)" _data="{\"text\": \"$_content\", " _data="$_data\"chat_id\": \"$TELEGRAM_BOT_CHATID\", " From bc455f2b54b6c63716c25a3e4cc44616efbaa191 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Thu, 8 Apr 2021 16:37:27 +1200 Subject: [PATCH 103/304] Add debug output of $_data variable to aid diagnosis Signed-off-by: Mike Beattie --- notify/telegram.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/notify/telegram.sh b/notify/telegram.sh index d9b375d0..3e266040 100644 --- a/notify/telegram.sh +++ b/notify/telegram.sh @@ -34,6 +34,8 @@ telegram_send() { _data="$_data\"parse_mode\": \"markdown\", " _data="$_data\"disable_web_page_preview\": \"1\"}" + _debug "$_data" + export _H1="Content-Type: application/json" _telegram_bot_url="https://api.telegram.org/bot${TELEGRAM_BOT_APITOKEN}/sendMessage" if _post "$_data" "$_telegram_bot_url"; then From cfec2872723fe7b5c07ea19972bf29be58ccda9e Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Thu, 8 Apr 2021 16:38:00 +1200 Subject: [PATCH 104/304] Dump _post() call output to /dev/null Signed-off-by: Mike Beattie --- notify/telegram.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notify/telegram.sh b/notify/telegram.sh index 3e266040..c46bc1e2 100644 --- a/notify/telegram.sh +++ b/notify/telegram.sh @@ -38,7 +38,7 @@ telegram_send() { export _H1="Content-Type: application/json" _telegram_bot_url="https://api.telegram.org/bot${TELEGRAM_BOT_APITOKEN}/sendMessage" - if _post "$_data" "$_telegram_bot_url"; then + if _post "$_data" "$_telegram_bot_url" > /dev/null; then # shellcheck disable=SC2154 _message=$(printf "%s\n" "$response" | sed -n 's/.*"ok":\([^,]*\).*/\1/p') if [ "$_message" = "true" ]; then From 595196cdbe871bafa44683f6b2bf6b0234303a2a Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Thu, 8 Apr 2021 16:44:22 +1200 Subject: [PATCH 105/304] Update telegram.sh (fix shellcheck failure) --- notify/telegram.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notify/telegram.sh b/notify/telegram.sh index c46bc1e2..d16f3a98 100644 --- a/notify/telegram.sh +++ b/notify/telegram.sh @@ -38,7 +38,7 @@ telegram_send() { export _H1="Content-Type: application/json" _telegram_bot_url="https://api.telegram.org/bot${TELEGRAM_BOT_APITOKEN}/sendMessage" - if _post "$_data" "$_telegram_bot_url" > /dev/null; then + if _post "$_data" "$_telegram_bot_url" >/dev/null; then # shellcheck disable=SC2154 _message=$(printf "%s\n" "$response" | sed -n 's/.*"ok":\([^,]*\).*/\1/p') if [ "$_message" = "true" ]; then From fbf04e1d37b86d9925cd0cda18292c32a31a3a82 Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 14 Apr 2021 22:18:01 +0800 Subject: [PATCH 106/304] fix onecom api --- dnsapi/dns_one.sh | 55 +++-------------------------------------------- 1 file changed, 3 insertions(+), 52 deletions(-) diff --git a/dnsapi/dns_one.sh b/dnsapi/dns_one.sh index 890cc804..0a4b2a14 100644 --- a/dnsapi/dns_one.sh +++ b/dnsapi/dns_one.sh @@ -1,22 +1,10 @@ #!/usr/bin/env sh -# -*- mode: sh; tab-width: 2; indent-tabs-mode: s; coding: utf-8 -*- - # one.com ui wrapper for acme.sh -# Author: github: @diseq -# Created: 2019-02-17 -# Fixed by: @der-berni -# Modified: 2020-04-07 -# -# Use ONECOM_KeepCnameProxy to keep the CNAME DNS record -# export ONECOM_KeepCnameProxy="1" + # # export ONECOM_User="username" # export ONECOM_Password="password" -# -# Usage: -# acme.sh --issue --dns dns_one -d example.com -# -# only single domain supported atm + dns_one_add() { fulldomain=$1 @@ -36,26 +24,10 @@ dns_one_add() { subdomain="${_sub_domain}" maindomain=${_domain} - useProxy=0 - if [ "${_sub_domain}" = "_acme-challenge" ]; then - subdomain="proxy${_sub_domain}" - useProxy=1 - fi _debug subdomain "$subdomain" _debug maindomain "$maindomain" - if [ $useProxy -eq 1 ]; then - #Check if the CNAME exists - _dns_one_getrecord "CNAME" "$_sub_domain" "$subdomain.$maindomain" - if [ -z "$id" ]; then - _info "$(__red "Add CNAME Proxy record: '$(__green "\"$_sub_domain\" => \"$subdomain.$maindomain\"")'")" - _dns_one_addrecord "CNAME" "$_sub_domain" "$subdomain.$maindomain" - - _info "Not valid yet, let's wait 1 hour to take effect." - _sleep 3600 - fi - fi #Check if the TXT exists _dns_one_getrecord "TXT" "$subdomain" "$txtvalue" @@ -92,26 +64,8 @@ dns_one_rm() { subdomain="${_sub_domain}" maindomain=${_domain} - useProxy=0 - if [ "${_sub_domain}" = "_acme-challenge" ]; then - subdomain="proxy${_sub_domain}" - useProxy=1 - fi - _debug subdomain "$subdomain" _debug maindomain "$maindomain" - if [ $useProxy -eq 1 ]; then - if [ "$ONECOM_KeepCnameProxy" = "1" ]; then - _info "$(__red "Keeping CNAME Proxy record: '$(__green "\"$_sub_domain\" => \"$subdomain.$maindomain\"")'")" - else - #Check if the CNAME exists - _dns_one_getrecord "CNAME" "$_sub_domain" "$subdomain.$maindomain" - if [ -n "$id" ]; then - _info "$(__red "Removing CNAME Proxy record: '$(__green "\"$_sub_domain\" => \"$subdomain.$maindomain\"")'")" - _dns_one_delrecord "$id" - fi - fi - fi #Check if the TXT exists _dns_one_getrecord "TXT" "$subdomain" "$txtvalue" @@ -136,7 +90,7 @@ dns_one_rm() { # _domain=domain.com _get_root() { domain="$1" - i=2 + i=1 p=1 while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) @@ -163,8 +117,6 @@ _get_root() { _dns_one_login() { # get credentials - ONECOM_KeepCnameProxy="${ONECOM_KeepCnameProxy:-$(_readaccountconf_mutable ONECOM_KeepCnameProxy)}" - ONECOM_KeepCnameProxy="${ONECOM_KeepCnameProxy:-0}" ONECOM_User="${ONECOM_User:-$(_readaccountconf_mutable ONECOM_User)}" ONECOM_Password="${ONECOM_Password:-$(_readaccountconf_mutable ONECOM_Password)}" if [ -z "$ONECOM_User" ] || [ -z "$ONECOM_Password" ]; then @@ -176,7 +128,6 @@ _dns_one_login() { fi #save the api key and email to the account conf file. - _saveaccountconf_mutable ONECOM_KeepCnameProxy "$ONECOM_KeepCnameProxy" _saveaccountconf_mutable ONECOM_User "$ONECOM_User" _saveaccountconf_mutable ONECOM_Password "$ONECOM_Password" From 957c3187faaac77d91486de698ae6a74ded4fd3a Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 17 Apr 2021 22:09:59 +0800 Subject: [PATCH 107/304] fix format --- dnsapi/dns_one.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/dnsapi/dns_one.sh b/dnsapi/dns_one.sh index 0a4b2a14..1565b767 100644 --- a/dnsapi/dns_one.sh +++ b/dnsapi/dns_one.sh @@ -5,7 +5,6 @@ # export ONECOM_User="username" # export ONECOM_Password="password" - dns_one_add() { fulldomain=$1 txtvalue=$2 @@ -24,11 +23,9 @@ dns_one_add() { subdomain="${_sub_domain}" maindomain=${_domain} - _debug subdomain "$subdomain" _debug maindomain "$maindomain" - #Check if the TXT exists _dns_one_getrecord "TXT" "$subdomain" "$txtvalue" if [ -n "$id" ]; then From dd42da818f65dff649e2b936fc8b5dc3a4683b78 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 2 May 2021 22:20:04 +0800 Subject: [PATCH 108/304] upgrade freebsd --- .github/workflows/DNS.yml | 2 +- .github/workflows/LetsEncrypt.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 5ff1f8ab..f8e501ed 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -184,7 +184,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.1.3 + - uses: vmactions/freebsd-vm@v0.1.4 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkg install -y socat curl diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 7193d88d..ba9a5317 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -111,7 +111,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.1.3 + - uses: vmactions/freebsd-vm@v0.1.4 with: envs: 'NGROK_TOKEN TEST_LOCAL' prepare: pkg install -y socat curl From e508fb82f2c30e2d31c632a0149413b3fac4f25c Mon Sep 17 00:00:00 2001 From: Jasper Zonneveld Date: Fri, 26 Mar 2021 14:59:13 +0100 Subject: [PATCH 109/304] Add Aurora DNS API --- dnsapi/dns_aurora.sh | 171 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 dnsapi/dns_aurora.sh diff --git a/dnsapi/dns_aurora.sh b/dnsapi/dns_aurora.sh new file mode 100644 index 00000000..00f44739 --- /dev/null +++ b/dnsapi/dns_aurora.sh @@ -0,0 +1,171 @@ +#!/usr/bin/env sh + +# +#AURORA_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" +# +#AURORA_Secret="sdfsdfsdfljlbjkljlkjsdfoiwje" + +AURORA_Api="https://api.auroradns.eu" + +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_aurora_add() { + fulldomain=$1 + txtvalue=$2 + + AURORA_Key="${AURORA_Key:-$(_readaccountconf_mutable AURORA_Key)}" + AURORA_Secret="${AURORA_Secret:-$(_readaccountconf_mutable AURORA_Secret)}" + + if [ -z "$AURORA_Key" ] || [ -z "$AURORA_Secret" ]; then + AURORA_Key="" + AURORA_Secret="" + _err "You didn't specify an Aurora api key and secret yet." + _err "You can get yours from here https://cp.pcextreme.nl/auroradns/users." + return 1 + fi + + #save the api key and secret to the account conf file. + _saveaccountconf_mutable AURORA_Key "$AURORA_Key" + _saveaccountconf_mutable AURORA_Secret "$AURORA_Secret" + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _domain_id "$_domain_id" + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _info "Adding record" + if _aurora_rest POST "zones/$_domain_id/records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":300}"; then + if _contains "$response" "$txtvalue"; then + _info "Added, OK" + return 0 + elif _contains "$response" "RecordExistsError"; then + _info "Already exists, OK" + return 0 + else + _err "Add txt record error." + return 1 + fi + fi + _err "Add txt record error." + return 1 + +} + +#fulldomain txtvalue +dns_aurora_rm() { + fulldomain=$1 + txtvalue=$2 + + AURORA_Key="${AURORA_Key:-$(_readaccountconf_mutable AURORA_Key)}" + AURORA_Secret="${AURORA_Secret:-$(_readaccountconf_mutable AURORA_Secret)}" + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _domain_id "$_domain_id" + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting records" + _aurora_rest GET "zones/${_domain_id}/records" + + if ! _contains "$response" "$txtvalue"; then + _info "Don't need to remove." + else + records=$(echo "$response" | _normalizeJson | tr -d "[]" | sed "s/},{/}|{/g" | tr "|" "\n") + if [ "$(echo "$records" | wc -l)" -le 2 ]; then + _err "Can not parse records." + return 1 + fi + record_id=$(echo "$records" | grep "\"type\": *\"TXT\"" | grep "\"name\": *\"$_sub_domain\"" | grep "\"content\": *\"$txtvalue\"" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | _head_n 1 | tr -d " ") + _debug "record_id" "$record_id" + if [ -z "$record_id" ]; then + _err "Can not get record id to remove." + return 1 + fi + if ! _aurora_rest DELETE "zones/$_domain_id/records/$record_id"; then + _err "Delete record error." + return 1 + fi + fi + return 0 + +} + +#################### Private functions below ################################## +#_acme-challenge.www.domain.com +#returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +# _domain_id=sdjkglgdfewsdfg +_get_root() { + domain=$1 + i=1 + p=1 + + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug h "$h" + if [ -z "$h" ]; then + #not valid + return 1 + fi + + if ! _aurora_rest GET "zones/$h"; then + return 1 + fi + + if _contains "$response" "\"name\": \"$h\""; then + _domain_id=$(echo "$response" | _normalizeJson | tr -d "{}" | tr "," "\n" | grep "\"id\": *\"" | cut -d : -f 2 | tr -d \" | _head_n 1 | tr -d " ") + _debug _domain_id "$_domain_id" + if [ "$_domain_id" ]; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain=$h + return 0 + fi + return 1 + fi + p=$i + i=$(_math "$i" + 1) + done + return 1 +} + +_aurora_rest() { + m=$1 + ep="$2" + data="$3" + _debug "$ep" + + key_trimmed=$(echo "$AURORA_Key" | tr -d '"') + secret_trimmed=$(echo "$AURORA_Secret" | tr -d '"') + + timestamp=$(date -u +"%Y%m%dT%H%M%SZ") + signature=$(printf "%s/%s%s" "$m" "$ep" "$timestamp" | _hmac sha256 "$(printf "%s" "$secret_trimmed" | _hex_dump | tr -d " ")" | _base64) + authorization=$(printf "AuroraDNSv1 %s" "$(printf "%s:%s" "$key_trimmed" "$signature" | _base64)") + + export _H1="Content-Type: application/json; charset=UTF-8" + export _H2="X-AuroraDNS-Date: $timestamp" + export _H3="Authorization: $authorization" + + if [ "$m" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$AURORA_Api/$ep" "" "$m")" + else + response="$(_get "$AURORA_Api/$ep")" + fi + + if [ "$?" != "0" ]; then + _err "error $ep" + return 1 + fi + _debug2 response "$response" + return 0 +} From e0eeca34c7d3556a678e049325bca0846654626b Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Mon, 25 Jan 2021 21:55:07 +0100 Subject: [PATCH 110/304] Test original implementation by trgosk --- dnsapi/dns_websupport.sh | 208 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 dnsapi/dns_websupport.sh diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh new file mode 100644 index 00000000..1332a0aa --- /dev/null +++ b/dnsapi/dns_websupport.sh @@ -0,0 +1,208 @@ +#!/usr/bin/env sh + +#This is the websupport.sk api wrapper for acme.sh +# +#Author: trgo.sk +#Report Bugs here: https://github.com/trgosk/acme.sh + +#WS_ApiKey="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +#WS_ApiSecret="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + +WS_Api="https://rest.websupport.sk" + +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_websupport_add() { + fulldomain=$1 + txtvalue=$2 + + WS_ApiKey="${WS_ApiKey:-$(_readaccountconf_mutable WS_ApiKey)}" + WS_ApiSecret="${WS_ApiSecret:-$(_readaccountconf_mutable WS_ApiSecret)}" + + if [ "$WS_ApiKey" ] && [ "$WS_ApiSecret" ]; then + _saveaccountconf_mutable WS_ApiKey "$WS_ApiKey" + _saveaccountconf_mutable WS_ApiSecret "$WS_ApiSecret" + else + WS_ApiKey="" + WS_ApiSecret="" + _err "You didn't specify a api key and/or api secret yet." + _err "You can get yours from here https://admin.websupport.sk/en/auth/apiKey" + return 1 + fi + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + # For wildcard cert, the main root domain and the wildcard domain have the same txt subdomain name, so + # we can not use updating anymore. + # count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2) + # _debug count "$count" + # if [ "$count" = "0" ]; then + _info "Adding record" + if _ws_rest POST "/v1/user/self/zone/$_domain/record" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then + if _contains "$response" "$txtvalue"; then + _info "Added, OK" + return 0 + elif _contains "$response" "The record already exists"; then + _info "Already exists, OK" + return 0 + else + _err "Add txt record error." + return 1 + fi + fi + _err "Add txt record error." + return 1 + +} + +#fulldomain txtvalue +dns_websupport_rm() { + fulldomain=$1 + txtvalue=$2 + + _debug2 fulldomain "$fulldomain" + _debug2 txtvalue "$txtvalue" + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting txt records" + _ws_rest GET "/v1/user/self/zone/$_domain/record" + + if [ "$(printf "%s" "$response" | tr -d " " | grep -c \"items\")" -lt "1" ]; then + _err "Error: $response" + return 1 + fi + + record_line="$(_get_from_array "$response" "$txtvalue")" + _debug record_line "$record_line" + if [ -z "$record_line" ]; then + _info "Don't need to remove." + else + record_id=$(echo "$record_line" | _egrep_o "\"id\": *[^,]*" | _head_n 1 | cut -d : -f 2 | tr -d \" | tr -d " ") + _debug "record_id" "$record_id" + if [ -z "$record_id" ]; then + _err "Can not get record id to remove." + return 1 + fi + if ! _ws_rest DELETE "/v1/user/self/zone/$_domain/record/$record_id"; then + _err "Delete record error." + return 1 + fi + if [ "$(printf "%s" "$response" | tr -d " " | grep -c \"success\")" -lt "1" ]; then + return 1 + else + return 0 + fi + fi + +} + +#################### Private functions below ################################## +#_acme-challenge.www.domain.com +#returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +_get_root() { + domain=$1 + i=1 + p=1 + + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug h "$h" + if [ -z "$h" ]; then + #not valid + return 1 + fi + + if ! _ws_rest GET "/v1/user/self/zone"; then + return 1 + fi + + if _contains "$response" "\"name\":\"$h\""; then + _domain_id=$(echo "$response" | _egrep_o "\[.\"id\": *[^,]*" | _head_n 1 | cut -d : -f 2 | tr -d \" | tr -d " ") + if [ "$_domain_id" ]; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain=$h + return 0 + fi + return 1 + fi + p=$i + i=$(_math "$i" + 1) + done + return 1 +} + +_ws_rest() { + me=$1 + pa="$2" + da="$3" + + _debug2 api_key "$WS_ApiKey" + _debug2 api_secret "$WS_ApiSecret" + + timestamp="$(date +%s)" + datez=$(date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || date -u -d@"$timestamp" +%Y-%m-%dT%H:%M:%S%z) + canonical_request="${me} ${pa} ${timestamp}" + alg="sha1" + signature_hash=$( (printf "%s" "$canonical_request" | ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -mac HMAC -macopt "key:$WS_ApiSecret" 2>/dev/null || printf "%s" "$canonical_request" | ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -hmac "$(printf "%s" "$WS_ApiSecret" | _h2b)") | cut -d = -f 2 | tr -d ' ') + basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" + + _debug2 method "$me" + _debug2 path "$pa" + _debug2 data "$da" + _debug2 timestamp "$timestamp" + _debug2 datez "$datez" + _debug2 canonical_request "$canonical_request" + _debug2 alg "$alg" + _debug2 signature_hash "$signature_hash" + _debug2 basicauth "$basicauth" + + export _H1="Accept: application/json" + export _H2="Content-Type: application/json" + export _H3="Authorization: Basic ${basicauth}" + export _H4="Date: ${datez}" + + _debug2 H1 "$_H1" + _debug2 H2 "$_H2" + _debug2 H3 "$_H3" + _debug2 H4 "$_H4" + + if [ "$me" != "GET" ]; then + _debug2 "${me} $WS_Api${pa}" + _debug data "$da" + response="$(_post "$da" "${WS_Api}${pa}" "" "$me")" + else + _debug2 "GET $WS_Api${pa}" + response="$(_get "$WS_Api${pa}")" + fi + + _debug2 response "$response" + return "$?" +} + +_get_from_array() { + va="$1" + fi="$2" + for i in $(echo "$va" | sed "s/{/ /g"); do + if _contains "$i" "$fi"; then + echo "$i" + break + fi + done +} From 00eba97511b154b7d20031bf52ae469c791fef92 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Mon, 25 Jan 2021 22:01:41 +0100 Subject: [PATCH 111/304] Update dns_websupport.sh --- dnsapi/dns_websupport.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 1332a0aa..407e3485 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -206,3 +206,4 @@ _get_from_array() { fi done } + From 1d36e880b18a8c7a64784ed86de71bae17e3a836 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Mon, 25 Jan 2021 22:10:27 +0100 Subject: [PATCH 112/304] Update dns_websupport.sh --- dnsapi/dns_websupport.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 407e3485..1332a0aa 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -206,4 +206,3 @@ _get_from_array() { fi done } - From f02dccb6483b9dba4e555049d58ee472a35a9e3e Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Sun, 31 Jan 2021 22:02:11 +0100 Subject: [PATCH 113/304] Testing HMAC --- dnsapi/dns_websupport.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 1332a0aa..5136a8e1 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -156,11 +156,11 @@ _ws_rest() { _debug2 api_key "$WS_ApiKey" _debug2 api_secret "$WS_ApiSecret" - timestamp="$(date +%s)" + timestamp=$(_time) datez=$(date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || date -u -d@"$timestamp" +%Y-%m-%dT%H:%M:%S%z) canonical_request="${me} ${pa} ${timestamp}" alg="sha1" - signature_hash=$( (printf "%s" "$canonical_request" | ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -mac HMAC -macopt "key:$WS_ApiSecret" 2>/dev/null || printf "%s" "$canonical_request" | ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -hmac "$(printf "%s" "$WS_ApiSecret" | _h2b)") | cut -d = -f 2 | tr -d ' ') + signature_hash=$( (printf "%s" "$canonical_request" | _hmac "$alg" "$WS_ApiSecret" 2>/dev/null || printf "%s" "$canonical_request" | _hmac "$alg" "$WS_ApiSecret") basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" _debug2 method "$me" From 7e34de8b26d812e7300ab1ad16a158c404931e14 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Sun, 31 Jan 2021 22:04:53 +0100 Subject: [PATCH 114/304] Added a forgotten ")" --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 5136a8e1..ca6b8a06 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -160,7 +160,7 @@ _ws_rest() { datez=$(date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || date -u -d@"$timestamp" +%Y-%m-%dT%H:%M:%S%z) canonical_request="${me} ${pa} ${timestamp}" alg="sha1" - signature_hash=$( (printf "%s" "$canonical_request" | _hmac "$alg" "$WS_ApiSecret" 2>/dev/null || printf "%s" "$canonical_request" | _hmac "$alg" "$WS_ApiSecret") + signature_hash=$( (printf "%s" "$canonical_request" | _hmac "$alg" "$WS_ApiSecret" 2>/dev/null || printf "%s" "$canonical_request" | _hmac "$alg" "$WS_ApiSecret")) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" _debug2 method "$me" From f6e5ab4da251748b8bd835c34ba9b51002a68471 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Sun, 31 Jan 2021 22:16:00 +0100 Subject: [PATCH 115/304] Simplified approach for the HMAC method --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index ca6b8a06..2ff93a5d 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -160,7 +160,7 @@ _ws_rest() { datez=$(date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || date -u -d@"$timestamp" +%Y-%m-%dT%H:%M:%S%z) canonical_request="${me} ${pa} ${timestamp}" alg="sha1" - signature_hash=$( (printf "%s" "$canonical_request" | _hmac "$alg" "$WS_ApiSecret" 2>/dev/null || printf "%s" "$canonical_request" | _hmac "$alg" "$WS_ApiSecret")) + signature_hash=$(printf "%s" "$canonical_request" | _hmac "$alg" "$WS_ApiSecret") basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" _debug2 method "$me" From a263390a07a7612eaefb3369243d633c32a5871a Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Sun, 31 Jan 2021 22:25:13 +0100 Subject: [PATCH 116/304] Update dns_websupport.sh --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 2ff93a5d..4b0026f8 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -160,7 +160,7 @@ _ws_rest() { datez=$(date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || date -u -d@"$timestamp" +%Y-%m-%dT%H:%M:%S%z) canonical_request="${me} ${pa} ${timestamp}" alg="sha1" - signature_hash=$(printf "%s" "$canonical_request" | _hmac "$alg" "$WS_ApiSecret") + signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" _debug2 method "$me" From 5b87f05cb29bc702d2767b4e8a2611111d83a41f Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Mon, 1 Feb 2021 00:30:36 +0100 Subject: [PATCH 117/304] "datez" var and comments --- dnsapi/dns_websupport.sh | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 4b0026f8..731da0a6 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -1,18 +1,24 @@ #!/usr/bin/env sh -#This is the websupport.sk api wrapper for acme.sh +# This is the websupport.sk api wrapper for acme.sh # -#Author: trgo.sk -#Report Bugs here: https://github.com/trgosk/acme.sh - -#WS_ApiKey="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -#WS_ApiSecret="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +# Original author: trgo.sk (https://github.com/trgosk) +# Tweaks by: akulumbeg (https://github.com/akulumbeg) +# +# Report Bugs here: https://github.com/akulumbeg/acme.sh +# +# Requirements: API Key and Secret from https://admin.websupport.sk/en/auth/apiKey +# +# WS_ApiKey="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +# (called "Identifier" in the WS Admin) +# +# WS_ApiSecret="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +# (called "Secret key" in the WS Admin) WS_Api="https://rest.websupport.sk" ######## Public functions ##################### -#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_websupport_add() { fulldomain=$1 txtvalue=$2 @@ -26,7 +32,7 @@ dns_websupport_add() { else WS_ApiKey="" WS_ApiSecret="" - _err "You didn't specify a api key and/or api secret yet." + _err "You did not specify the API Key and/or API Secret" _err "You can get yours from here https://admin.websupport.sk/en/auth/apiKey" return 1 fi @@ -62,7 +68,6 @@ dns_websupport_add() { } -#fulldomain txtvalue dns_websupport_rm() { fulldomain=$1 txtvalue=$2 @@ -111,11 +116,8 @@ dns_websupport_rm() { } -#################### Private functions below ################################## -#_acme-challenge.www.domain.com -#returns -# _sub_domain=_acme-challenge.www -# _domain=domain.com +#################### Private Functions ################################## + _get_root() { domain=$1 i=1 @@ -157,9 +159,8 @@ _ws_rest() { _debug2 api_secret "$WS_ApiSecret" timestamp=$(_time) - datez=$(date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || date -u -d@"$timestamp" +%Y-%m-%dT%H:%M:%S%z) + datez=$(printf "%s" "$(date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || date -u -d@"$timestamp" +%Y-%m-%dT%H:%M:%S%z)") canonical_request="${me} ${pa} ${timestamp}" - alg="sha1" signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" @@ -169,7 +170,6 @@ _ws_rest() { _debug2 timestamp "$timestamp" _debug2 datez "$datez" _debug2 canonical_request "$canonical_request" - _debug2 alg "$alg" _debug2 signature_hash "$signature_hash" _debug2 basicauth "$basicauth" From 817d0472b688efe7b3852d26508476576e9a1136 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Mon, 1 Feb 2021 18:16:15 +0100 Subject: [PATCH 118/304] Fix comments, error msg and time formatting --- dnsapi/dns_websupport.sh | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 731da0a6..8950970b 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -1,12 +1,11 @@ #!/usr/bin/env sh -# This is the websupport.sk api wrapper for acme.sh +# Acme.sh DNS API wrapper for websupport.sk # # Original author: trgo.sk (https://github.com/trgosk) # Tweaks by: akulumbeg (https://github.com/akulumbeg) -# # Report Bugs here: https://github.com/akulumbeg/acme.sh -# + # Requirements: API Key and Secret from https://admin.websupport.sk/en/auth/apiKey # # WS_ApiKey="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" @@ -33,7 +32,7 @@ dns_websupport_add() { WS_ApiKey="" WS_ApiSecret="" _err "You did not specify the API Key and/or API Secret" - _err "You can get yours from here https://admin.websupport.sk/en/auth/apiKey" + _err "You can get the credentials from here https://admin.websupport.sk/en/auth/apiKey" return 1 fi @@ -159,7 +158,7 @@ _ws_rest() { _debug2 api_secret "$WS_ApiSecret" timestamp=$(_time) - datez=$(printf "%s" "$(date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || date -u -d@"$timestamp" +%Y-%m-%dT%H:%M:%S%z)") + datez=$(printf "%s" "$(date -u -r "$timestamp" "+%Y-%m-%dT%H:%M:%S%z" 2>/dev/null || date -u -d@"$timestamp" "+%Y-%m-%dT%H:%M:%S%z")") canonical_request="${me} ${pa} ${timestamp}" signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" From 2745324b5a3542ce7711cc017beed4225d01689e Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Mon, 1 Feb 2021 18:37:17 +0100 Subject: [PATCH 119/304] Testing datez change for Solaris --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 8950970b..c3a43f1e 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -158,7 +158,7 @@ _ws_rest() { _debug2 api_secret "$WS_ApiSecret" timestamp=$(_time) - datez=$(printf "%s" "$(date -u -r "$timestamp" "+%Y-%m-%dT%H:%M:%S%z" 2>/dev/null || date -u -d@"$timestamp" "+%Y-%m-%dT%H:%M:%S%z")") + datez=$(printf "%s" "$(date -u -d@"$timestamp" "+%Y-%m-%dT%H:%M:%S%z" 2>/dev/null || date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z)") canonical_request="${me} ${pa} ${timestamp}" signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" From 4495e83ee08f59b988448fe26f011119c3e0a277 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Mon, 1 Feb 2021 20:31:05 +0100 Subject: [PATCH 120/304] Yet another Solaris test --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index c3a43f1e..73543ea5 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -158,7 +158,7 @@ _ws_rest() { _debug2 api_secret "$WS_ApiSecret" timestamp=$(_time) - datez=$(printf "%s" "$(date -u -d@"$timestamp" "+%Y-%m-%dT%H:%M:%S%z" 2>/dev/null || date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z)") + datez=$(date -u -d@"$timestamp" "+%Y-%m-%dT%H:%M:%S%z" 1>/dev/null 2>&1 || date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z) canonical_request="${me} ${pa} ${timestamp}" signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" From 9948a889d97fd11208433037a31e75ce234c1095 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Mon, 1 Feb 2021 20:43:22 +0100 Subject: [PATCH 121/304] And again --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 73543ea5..b145dc3e 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -158,7 +158,7 @@ _ws_rest() { _debug2 api_secret "$WS_ApiSecret" timestamp=$(_time) - datez=$(date -u -d@"$timestamp" "+%Y-%m-%dT%H:%M:%S%z" 1>/dev/null 2>&1 || date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z) + datez=$(date -u -d@"$timestamp" "+%Y-%m-%dT%H:%M:%S%z" 2>/dev/null || date -u -r "$timestamp" "+%Y-%m-%dT%H:%M:%S%z") canonical_request="${me} ${pa} ${timestamp}" signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" From 41abe01ee15983842909c8397aa42c922ca5bb3d Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 00:21:08 +0100 Subject: [PATCH 122/304] sed workaround for "datez" --- dnsapi/dns_websupport.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index b145dc3e..b30ac994 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -1,3 +1,4 @@ + #!/usr/bin/env sh # Acme.sh DNS API wrapper for websupport.sk @@ -158,7 +159,7 @@ _ws_rest() { _debug2 api_secret "$WS_ApiSecret" timestamp=$(_time) - datez=$(date -u -d@"$timestamp" "+%Y-%m-%dT%H:%M:%S%z" 2>/dev/null || date -u -r "$timestamp" "+%Y-%m-%dT%H:%M:%S%z") + datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/")" canonical_request="${me} ${pa} ${timestamp}" signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" From 103800de26e40a0dc0caf5f8926e91604a63ae12 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 00:31:46 +0100 Subject: [PATCH 123/304] Fixing the shebang accident --- dnsapi/dns_websupport.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index b30ac994..922e6819 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -1,4 +1,3 @@ - #!/usr/bin/env sh # Acme.sh DNS API wrapper for websupport.sk From 70b17d1a61171e002cf29643d6d4b9f4f0c058de Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 10:13:36 +0100 Subject: [PATCH 124/304] Extra test - adding date -u -d Adding this to at least partially prevent the virtually nonexistent possibility of timestamp and _utc_date() mismatch. If the normal date -u -d does not get converted (looking at you Solaris!), the poor man's method with manipulating the _utc_date() string output kicks in. --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 922e6819..d69a6c00 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -158,7 +158,7 @@ _ws_rest() { _debug2 api_secret "$WS_ApiSecret" timestamp=$(_time) - datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/")" + datez="$(date -u -d @"$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null/ || _utc_date | sed "s/ /T/" | sed "s/$/+0000/")" canonical_request="${me} ${pa} ${timestamp}" signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" From f13718b1994e77e94f2950e8321409f569ce08e6 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 11:15:13 +0100 Subject: [PATCH 125/304] 2>/dev/null/ to 2>/dev/null Silly mistake with a "/" -.- --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index d69a6c00..143b07b2 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -158,7 +158,7 @@ _ws_rest() { _debug2 api_secret "$WS_ApiSecret" timestamp=$(_time) - datez="$(date -u -d @"$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null/ || _utc_date | sed "s/ /T/" | sed "s/$/+0000/")" + datez="$(date -u -d @"$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || _utc_date | sed "s/ /T/" | sed "s/$/+0000/")" canonical_request="${me} ${pa} ${timestamp}" signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" From 803aa99decd3e8af3d5d9ab47c1a20e619f8636f Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 11:18:22 +0100 Subject: [PATCH 126/304] Testing double 2>/dev/null into _utc_date with sed --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 143b07b2..797c1b57 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -158,7 +158,7 @@ _ws_rest() { _debug2 api_secret "$WS_ApiSecret" timestamp=$(_time) - datez="$(date -u -d @"$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || _utc_date | sed "s/ /T/" | sed "s/$/+0000/")" + datez="$(date -u -d @"$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || _utc_date | sed "s/ /T/" | sed "s/$/+0000/")" canonical_request="${me} ${pa} ${timestamp}" signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" From 20da70a4abcf897d74d1d9cfccc1290a558ee4b3 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 15:11:53 +0100 Subject: [PATCH 127/304] Implementing/testing Neil's suggestions --- dnsapi/dns_websupport.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 797c1b57..5089d7c3 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -158,9 +158,9 @@ _ws_rest() { _debug2 api_secret "$WS_ApiSecret" timestamp=$(_time) - datez="$(date -u -d @"$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || _utc_date | sed "s/ /T/" | sed "s/$/+0000/")" + datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/") canonical_request="${me} ${pa} ${timestamp}" - signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) + signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$WS_ApiSecret") basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" _debug2 method "$me" From 1b12aebe58844004726b1c7d30ae66b29f24ce72 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 15:15:17 +0100 Subject: [PATCH 128/304] Typo Forgot a quotation mark on line 161 --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 5089d7c3..de3d8b71 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -158,7 +158,7 @@ _ws_rest() { _debug2 api_secret "$WS_ApiSecret" timestamp=$(_time) - datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/") + datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/")" canonical_request="${me} ${pa} ${timestamp}" signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$WS_ApiSecret") basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" From c0821cb648b1dd26aee2426c342b8eb22e6d0c23 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 15:18:39 +0100 Subject: [PATCH 129/304] adding the hex parameter to _hmac call --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index de3d8b71..e40a3729 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -160,7 +160,7 @@ _ws_rest() { timestamp=$(_time) datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/")" canonical_request="${me} ${pa} ${timestamp}" - signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$WS_ApiSecret") + signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$WS_ApiSecret" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" _debug2 method "$me" From bc1488ae9086b15507c0c30ac10e17b3ab4d2e73 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 15:22:53 +0100 Subject: [PATCH 130/304] Trying the original solution _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index e40a3729..922e6819 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -160,7 +160,7 @@ _ws_rest() { timestamp=$(_time) datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/")" canonical_request="${me} ${pa} ${timestamp}" - signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$WS_ApiSecret" hex) + signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" _debug2 method "$me" From 5d03106cd22bd25ade1211a2336d70ef54734c22 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 15:32:51 +0100 Subject: [PATCH 131/304] Changing the _hmac call into Neil's suggestion --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 922e6819..06ed9c78 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -160,7 +160,7 @@ _ws_rest() { timestamp=$(_time) datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/")" canonical_request="${me} ${pa} ${timestamp}" - signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) + signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$WS_ApiSecret" | _hex_dump | tr -d " ") basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" _debug2 method "$me" From debf06fff8d8b79ba18086584b82afe92cbcb79f Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 17:15:22 +0100 Subject: [PATCH 132/304] Update dns_websupport.sh --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 06ed9c78..ed14a279 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -160,7 +160,7 @@ _ws_rest() { timestamp=$(_time) datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/")" canonical_request="${me} ${pa} ${timestamp}" - signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$WS_ApiSecret" | _hex_dump | tr -d " ") + signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$("$WS_ApiSecret" | _hex_dump | tr -d " ")") basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" _debug2 method "$me" From 8363853208361c2f4d8ade3b1115195d972f978c Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 17:21:33 +0100 Subject: [PATCH 133/304] added hex param to _hmac but removed "printf "s%" ... --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index ed14a279..773d693d 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -160,7 +160,7 @@ _ws_rest() { timestamp=$(_time) datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/")" canonical_request="${me} ${pa} ${timestamp}" - signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$("$WS_ApiSecret" | _hex_dump | tr -d " ")") + signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$("$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" _debug2 method "$me" From 4770115be6fa2c66affdedeab1f2e2b3ecb6b50f Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 17:27:39 +0100 Subject: [PATCH 134/304] Changing the _hmac auth back It only works this way, apparently --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 773d693d..922e6819 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -160,7 +160,7 @@ _ws_rest() { timestamp=$(_time) datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/")" canonical_request="${me} ${pa} ${timestamp}" - signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$("$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) + signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" _debug2 method "$me" From 4dd333c4e13eec7e98c02e4fb16a7626adc922c1 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Sat, 20 Mar 2021 15:26:32 +0100 Subject: [PATCH 137/304] String change --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 922e6819..3b5a8847 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -32,7 +32,7 @@ dns_websupport_add() { WS_ApiKey="" WS_ApiSecret="" _err "You did not specify the API Key and/or API Secret" - _err "You can get the credentials from here https://admin.websupport.sk/en/auth/apiKey" + _err "You can get the API credentials from here https://admin.websupport.sk/en/auth/apiKey" return 1 fi From 58ff7722cde3b7bc42cc17ed0d0f1dfdcdd560aa Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Sun, 21 Mar 2021 16:16:38 +0100 Subject: [PATCH 138/304] Revert "Syncing with the original repo (#2)" This reverts commit c384ed960c138f4449e79293644c4d0ec937cef1. --- .github/workflows/DNS.yml | 2 +- .github/workflows/LetsEncrypt.yml | 2 +- acme.sh | 98 ++------ deploy/unifi.sh | 220 ++++------------ dnsapi/dns_arvan.sh | 47 ++-- dnsapi/dns_dp.sh | 2 +- dnsapi/dns_duckdns.sh | 6 +- dnsapi/dns_huaweicloud.sh | 36 +-- dnsapi/dns_ionos.sh | 28 ++- dnsapi/dns_namecheap.sh | 6 +- dnsapi/dns_pdns.sh | 4 +- dnsapi/dns_porkbun.sh | 157 ------------ dnsapi/dns_servercow.sh | 42 +--- dnsapi/dns_simply.sh | 18 +- notify/smtp.sh | 402 +----------------------------- 15 files changed, 160 insertions(+), 910 deletions(-) delete mode 100644 dnsapi/dns_porkbun.sh diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index f8e501ed..b9e34ba4 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -223,7 +223,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/solaris-vm@v0.0.3 + - uses: vmactions/solaris-vm@v0.0.1 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkgutil -y -i socat curl diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index ba9a5317..da46b962 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -136,7 +136,7 @@ jobs: run: echo "TestingDomain=${{steps.ngrok.outputs.server}}" >> $GITHUB_ENV - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/solaris-vm@v0.0.3 + - uses: vmactions/solaris-vm@v0.0.1 with: envs: 'TEST_LOCAL TestingDomain' nat: | diff --git a/acme.sh b/acme.sh index 3eebdbc7..21fd6a8f 100755 --- a/acme.sh +++ b/acme.sh @@ -562,16 +562,8 @@ if _exists xargs && [ "$(printf %s '\\x41' | xargs printf)" = 'A' ]; then fi _h2b() { - if _exists xxd; then - if _contains "$(xxd --help 2>&1)" "assumes -c30"; then - if xxd -r -p -c 9999 2>/dev/null; then - return - fi - else - if xxd -r -p 2>/dev/null; then - return - fi - fi + if _exists xxd && xxd -r -p 2>/dev/null; then + return fi hex=$(cat) @@ -1132,7 +1124,7 @@ _createkey() { if _isEccKey "$length"; then _debug "Using ec name: $eccname" - if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -noout -genkey 2>/dev/null)"; then + if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -genkey 2>/dev/null)"; then echo "$_opkey" >"$f" else _err "error ecc key name: $eccname" @@ -1140,11 +1132,7 @@ _createkey() { fi else _debug "Using RSA: $length" - __traditional="" - if _contains "$(${ACME_OPENSSL_BIN:-openssl} help genrsa 2>&1)" "-traditional"; then - __traditional="-traditional" - fi - if _opkey="$(${ACME_OPENSSL_BIN:-openssl} genrsa $__traditional "$length" 2>/dev/null)"; then + if _opkey="$(${ACME_OPENSSL_BIN:-openssl} genrsa "$length" 2>/dev/null)"; then echo "$_opkey" >"$f" else _err "error rsa key: $length" @@ -2133,12 +2121,6 @@ _send_signed_request() { _sleep $_sleep_retry_sec continue fi - if _contains "$_body" "The Replay Nonce is not recognized"; then - _info "The replay Nonce is not valid, let's get a new one, Sleeping $_sleep_retry_sec seconds." - _CACHED_NONCE="" - _sleep $_sleep_retry_sec - continue - fi fi return 0 done @@ -2297,13 +2279,6 @@ _clearaccountconf() { _clear_conf "$ACCOUNT_CONF_PATH" "$1" } -#key -_clearaccountconf_mutable() { - _clearaccountconf "SAVED_$1" - #remove later - _clearaccountconf "$1" -} - #_savecaconf key value _savecaconf() { _save_conf "$CA_CONF" "$1" "$2" @@ -4036,42 +4011,12 @@ _check_dns_entries() { } #file -_get_chain_issuers() { +_get_cert_issuers() { _cfile="$1" - if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -help 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then - ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep -i 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 + if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then + ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 else - _cindex=1 - for _startn in $(grep -n -- "$BEGIN_CERT" "$_cfile" | cut -d : -f 1); do - _endn="$(grep -n -- "$END_CERT" "$_cfile" | cut -d : -f 1 | _head_n $_cindex | _tail_n 1)" - _debug2 "_startn" "$_startn" - _debug2 "_endn" "$_endn" - if [ "$DEBUG" ]; then - _debug2 "cert$_cindex" "$(sed -n "$_startn,${_endn}p" "$_cfile")" - fi - sed -n "$_startn,${_endn}p" "$_cfile" | ${ACME_OPENSSL_BIN:-openssl} x509 -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 | sed "s/ *\(.*\)/\1/" - _cindex=$(_math $_cindex + 1) - done - fi -} - -# -_get_chain_subjects() { - _cfile="$1" - if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -help 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then - ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep -i 'Subject:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 - else - _cindex=1 - for _startn in $(grep -n -- "$BEGIN_CERT" "$_cfile" | cut -d : -f 1); do - _endn="$(grep -n -- "$END_CERT" "$_cfile" | cut -d : -f 1 | _head_n $_cindex | _tail_n 1)" - _debug2 "_startn" "$_startn" - _debug2 "_endn" "$_endn" - if [ "$DEBUG" ]; then - _debug2 "cert$_cindex" "$(sed -n "$_startn,${_endn}p" "$_cfile")" - fi - sed -n "$_startn,${_endn}p" "$_cfile" | ${ACME_OPENSSL_BIN:-openssl} x509 -text -noout | grep -i 'Subject:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 | sed "s/ *\(.*\)/\1/" - _cindex=$(_math $_cindex + 1) - done + ${ACME_OPENSSL_BIN:-openssl} x509 -in $_cfile -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 fi } @@ -4079,12 +4024,14 @@ _get_chain_subjects() { _match_issuer() { _cfile="$1" _missuer="$2" - _fissuers="$(_get_chain_issuers $_cfile)" + _fissuers="$(_get_cert_issuers $_cfile)" _debug2 _fissuers "$_fissuers" - _rootissuer="$(echo "$_fissuers" | _lower_case | _tail_n 1)" - _debug2 _rootissuer "$_rootissuer" + if _contains "$_fissuers" "$_missuer"; then + return 0 + fi + _fissuers="$(echo "$_fissuers" | _lower_case)" _missuer="$(echo "$_missuer" | _lower_case)" - _contains "$_rootissuer" "$_missuer" + _contains "$_fissuers" "$_missuer" } #webroot, domain domainlist keylength @@ -4858,9 +4805,6 @@ $_authorizations_map" _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" @@ -4876,22 +4820,13 @@ $_authorizations_map" _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 - rm -f "$_relcert" - rm -f "$_relfullchain" - rm -f "$_relca" done fi fi @@ -5289,7 +5224,6 @@ signcsr() { _renew_hook="${10}" _local_addr="${11}" _challenge_alias="${12}" - _preferred_chain="${13}" _csrsubj=$(_readSubjectFromCSR "$_csrfile") if [ "$?" != "0" ]; then @@ -5336,7 +5270,7 @@ signcsr() { _info "Copy csr to: $CSR_PATH" cp "$_csrfile" "$CSR_PATH" - issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_addr" "$_challenge_alias" "$_preferred_chain" + issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_addr" "$_challenge_alias" } @@ -7433,7 +7367,7 @@ _process() { deploy "$_domain" "$_deploy_hook" "$_ecc" ;; signcsr) - signcsr "$_csr" "$_webroot" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" "$_preferred_chain" + signcsr "$_csr" "$_webroot" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" ;; showcsr) showcsr "$_csr" "$_domain" diff --git a/deploy/unifi.sh b/deploy/unifi.sh index a864135e..184aa62e 100644 --- a/deploy/unifi.sh +++ b/deploy/unifi.sh @@ -1,43 +1,12 @@ #!/usr/bin/env sh -# Here is a script to deploy cert on a Unifi Controller or Cloud Key device. -# It supports: -# - self-hosted Unifi Controller -# - Unifi Cloud Key (Gen1/2/2+) -# - Unifi Cloud Key running UnifiOS (v2.0.0+, Gen2/2+ only) -# Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3359 +#Here is a script to deploy cert to unifi server. #returns 0 means success, otherwise error. -# The deploy-hook automatically detects standard Unifi installations -# for each of the supported environments. Most users should not need -# to set any of these variables, but if you are running a self-hosted -# Controller with custom locations, set these as necessary before running -# the deploy hook. (Defaults shown below.) -# -# Settings for Unifi Controller: -# Location of Java keystore or unifi.keystore.jks file: #DEPLOY_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore" -# Keystore password (built into Unifi Controller, not a user-set password): #DEPLOY_UNIFI_KEYPASS="aircontrolenterprise" -# Command to restart Unifi Controller: #DEPLOY_UNIFI_RELOAD="service unifi restart" -# -# Settings for Unifi Cloud Key Gen1 (nginx admin pages): -# Directory where cloudkey.crt and cloudkey.key live: -#DEPLOY_UNIFI_CLOUDKEY_CERTDIR="/etc/ssl/private" -# Command to restart maintenance pages and Controller -# (same setting as above, default is updated when running on Cloud Key Gen1): -#DEPLOY_UNIFI_RELOAD="service nginx restart && service unifi restart" -# -# Settings for UnifiOS (Cloud Key Gen2): -# Directory where unifi-core.crt and unifi-core.key live: -#DEPLOY_UNIFI_CORE_CONFIG="/data/unifi-core/config/" -# Command to restart unifi-core: -#DEPLOY_UNIFI_RELOAD="systemctl restart unifi-core" -# -# At least one of DEPLOY_UNIFI_KEYSTORE, DEPLOY_UNIFI_CLOUDKEY_CERTDIR, -# or DEPLOY_UNIFI_CORE_CONFIG must exist to receive the deployed certs. ######## Public functions ##################### @@ -55,160 +24,77 @@ unifi_deploy() { _debug _cca "$_cca" _debug _cfullchain "$_cfullchain" - _getdeployconf DEPLOY_UNIFI_KEYSTORE - _getdeployconf DEPLOY_UNIFI_KEYPASS - _getdeployconf DEPLOY_UNIFI_CLOUDKEY_CERTDIR - _getdeployconf DEPLOY_UNIFI_CORE_CONFIG - _getdeployconf DEPLOY_UNIFI_RELOAD - - _debug2 DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" - _debug2 DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" - _debug2 DEPLOY_UNIFI_CLOUDKEY_CERTDIR "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" - _debug2 DEPLOY_UNIFI_CORE_CONFIG "$DEPLOY_UNIFI_CORE_CONFIG" - _debug2 DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" - - # Space-separated list of environments detected and installed: - _services_updated="" - - # Default reload commands accumulated as we auto-detect environments: - _reload_cmd="" - - # Unifi Controller environment (self hosted or any Cloud Key) -- - # auto-detect by file /usr/lib/unifi/data/keystore: - _unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-/usr/lib/unifi/data/keystore}" - if [ -f "$_unifi_keystore" ]; then - _info "Installing certificate for Unifi Controller (Java keystore)" - _debug _unifi_keystore "$_unifi_keystore" - if ! _exists keytool; then - _err "keytool not found" - return 1 - fi - if [ ! -w "$_unifi_keystore" ]; then - _err "The file $_unifi_keystore is not writable, please change the permission." - return 1 - fi - - _unifi_keypass="${DEPLOY_UNIFI_KEYPASS:-aircontrolenterprise}" - - _debug "Generate import pkcs12" - _import_pkcs12="$(_mktemp)" - _toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root - # shellcheck disable=SC2181 - if [ "$?" != "0" ]; then - _err "Error generating pkcs12. Please re-run with --debug and report a bug." - return 1 - fi - - _debug "Import into keystore: $_unifi_keystore" - if keytool -importkeystore \ - -deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \ - -srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \ - -alias unifi -noprompt; then - _debug "Import keystore success!" - rm "$_import_pkcs12" - else - _err "Error importing into Unifi Java keystore." - _err "Please re-run with --debug and report a bug." - rm "$_import_pkcs12" - return 1 - fi - - if systemctl -q is-active unifi; then - _reload_cmd="${_reload_cmd:+$_reload_cmd && }service unifi restart" - fi - _services_updated="${_services_updated} unifi" - _info "Install Unifi Controller certificate success!" - elif [ "$DEPLOY_UNIFI_KEYSTORE" ]; then - _err "The specified DEPLOY_UNIFI_KEYSTORE='$DEPLOY_UNIFI_KEYSTORE' is not valid, please check." + if ! _exists keytool; then + _err "keytool not found" return 1 fi - # Cloud Key environment (non-UnifiOS -- nginx serves admin pages) -- - # auto-detect by file /etc/ssl/private/cloudkey.key: - _cloudkey_certdir="${DEPLOY_UNIFI_CLOUDKEY_CERTDIR:-/etc/ssl/private}" - if [ -f "${_cloudkey_certdir}/cloudkey.key" ]; then - _info "Installing certificate for Cloud Key Gen1 (nginx admin pages)" - _debug _cloudkey_certdir "$_cloudkey_certdir" - if [ ! -w "$_cloudkey_certdir" ]; then - _err "The directory $_cloudkey_certdir is not writable; please check permissions." + DEFAULT_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore" + _unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-$DEFAULT_UNIFI_KEYSTORE}" + DEFAULT_UNIFI_KEYPASS="aircontrolenterprise" + _unifi_keypass="${DEPLOY_UNIFI_KEYPASS:-$DEFAULT_UNIFI_KEYPASS}" + DEFAULT_UNIFI_RELOAD="service unifi restart" + _reload="${DEPLOY_UNIFI_RELOAD:-$DEFAULT_UNIFI_RELOAD}" + + _debug _unifi_keystore "$_unifi_keystore" + if [ ! -f "$_unifi_keystore" ]; then + if [ -z "$DEPLOY_UNIFI_KEYSTORE" ]; then + _err "unifi keystore is not found, please define DEPLOY_UNIFI_KEYSTORE" return 1 - fi - # Cloud Key expects to load the keystore from /etc/ssl/private/unifi.keystore.jks. - # Normally /usr/lib/unifi/data/keystore is a symlink there (so the keystore was - # updated above), but if not, we don't know how to handle this installation: - if ! cmp -s "$_unifi_keystore" "${_cloudkey_certdir}/unifi.keystore.jks"; then - _err "Unsupported Cloud Key configuration: keystore not found at '${_cloudkey_certdir}/unifi.keystore.jks'" + else + _err "It seems that the specified unifi keystore is not valid, please check." return 1 fi - - cat "$_cfullchain" >"${_cloudkey_certdir}/cloudkey.crt" - cat "$_ckey" >"${_cloudkey_certdir}/cloudkey.key" - (cd "$_cloudkey_certdir" && tar -cf cert.tar cloudkey.crt cloudkey.key unifi.keystore.jks) - - if systemctl -q is-active nginx; then - _reload_cmd="${_reload_cmd:+$_reload_cmd && }service nginx restart" - fi - _info "Install Cloud Key Gen1 certificate success!" - _services_updated="${_services_updated} nginx" - elif [ "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" ]; then - _err "The specified DEPLOY_UNIFI_CLOUDKEY_CERTDIR='$DEPLOY_UNIFI_CLOUDKEY_CERTDIR' is not valid, please check." - return 1 fi - - # UnifiOS environment -- auto-detect by /data/unifi-core/config/unifi-core.key: - _unifi_core_config="${DEPLOY_UNIFI_CORE_CONFIG:-/data/unifi-core/config}" - if [ -f "${_unifi_core_config}/unifi-core.key" ]; then - _info "Installing certificate for UnifiOS" - _debug _unifi_core_config "$_unifi_core_config" - if [ ! -w "$_unifi_core_config" ]; then - _err "The directory $_unifi_core_config is not writable; please check permissions." - return 1 - fi - - cat "$_cfullchain" >"${_unifi_core_config}/unifi-core.crt" - cat "$_ckey" >"${_unifi_core_config}/unifi-core.key" - - if systemctl -q is-active unifi-core; then - _reload_cmd="${_reload_cmd:+$_reload_cmd && }systemctl restart unifi-core" - fi - _info "Install UnifiOS certificate success!" - _services_updated="${_services_updated} unifi-core" - elif [ "$DEPLOY_UNIFI_CORE_CONFIG" ]; then - _err "The specified DEPLOY_UNIFI_CORE_CONFIG='$DEPLOY_UNIFI_CORE_CONFIG' is not valid, please check." + if [ ! -w "$_unifi_keystore" ]; then + _err "The file $_unifi_keystore is not writable, please change the permission." return 1 fi - if [ -z "$_services_updated" ]; then - # None of the Unifi environments were auto-detected, so no deployment has occurred - # (and none of DEPLOY_UNIFI_{KEYSTORE,CLOUDKEY_CERTDIR,CORE_CONFIG} were set). - _err "Unable to detect Unifi environment in standard location." - _err "(This deploy hook must be run on the Unifi device, not a remote machine.)" - _err "For non-standard Unifi installations, set DEPLOY_UNIFI_KEYSTORE," - _err "DEPLOY_UNIFI_CLOUDKEY_CERTDIR, and/or DEPLOY_UNIFI_CORE_CONFIG as appropriate." + _info "Generate import pkcs12" + _import_pkcs12="$(_mktemp)" + _toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root + if [ "$?" != "0" ]; then + _err "Oops, error creating import pkcs12, please report bug to us." return 1 fi - _reload_cmd="${DEPLOY_UNIFI_RELOAD:-$_reload_cmd}" - if [ -z "$_reload_cmd" ]; then - _err "Certificates were installed for services:${_services_updated}," - _err "but none appear to be active. Please set DEPLOY_UNIFI_RELOAD" - _err "to a command that will restart the necessary services." + _info "Modify unifi keystore: $_unifi_keystore" + if keytool -importkeystore \ + -deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \ + -srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \ + -alias unifi -noprompt; then + _info "Import keystore success!" + rm "$_import_pkcs12" + else + _err "Import unifi keystore error, please report bug to us." + rm "$_import_pkcs12" return 1 fi - _info "Reload services (this may take some time): $_reload_cmd" - if eval "$_reload_cmd"; then + + _info "Run reload: $_reload" + if eval "$_reload"; then _info "Reload success!" + if [ "$DEPLOY_UNIFI_KEYSTORE" ]; then + _savedomainconf DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" + else + _cleardomainconf DEPLOY_UNIFI_KEYSTORE + fi + if [ "$DEPLOY_UNIFI_KEYPASS" ]; then + _savedomainconf DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" + else + _cleardomainconf DEPLOY_UNIFI_KEYPASS + fi + if [ "$DEPLOY_UNIFI_RELOAD" ]; then + _savedomainconf DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" + else + _cleardomainconf DEPLOY_UNIFI_RELOAD + fi + return 0 else _err "Reload error" return 1 fi - - # Successful, so save all (non-default) config: - _savedeployconf DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" - _savedeployconf DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" - _savedeployconf DEPLOY_UNIFI_CLOUDKEY_CERTDIR "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" - _savedeployconf DEPLOY_UNIFI_CORE_CONFIG "$DEPLOY_UNIFI_CORE_CONFIG" - _savedeployconf DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" - return 0 + } diff --git a/dnsapi/dns_arvan.sh b/dnsapi/dns_arvan.sh index 4c9217e5..ca1f56c7 100644 --- a/dnsapi/dns_arvan.sh +++ b/dnsapi/dns_arvan.sh @@ -1,9 +1,10 @@ #!/usr/bin/env sh -#Arvan_Token="Apikey xxxx" +#Arvan_Token="xxxx" ARVAN_API_URL="https://napi.arvancloud.com/cdn/4.0/domains" -#Author: Vahid Fardi + +#Author: Ehsan Aliakbar #Report Bugs here: https://github.com/Neilpang/acme.sh # ######## Public functions ##################### @@ -37,7 +38,6 @@ dns_arvan_add() { _info "Adding record" if _arvan_rest POST "$_domain/dns-records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":{\"text\":\"$txtvalue\"},\"ttl\":120}"; then if _contains "$response" "$txtvalue"; then - _info "response id is $response" _info "Added, OK" return 0 elif _contains "$response" "Record Data is Duplicated"; then @@ -49,7 +49,7 @@ dns_arvan_add() { fi fi _err "Add txt record error." - return 0 + return 1 } #Usage: fulldomain txtvalue @@ -73,21 +73,33 @@ dns_arvan_rm() { _debug _domain "$_domain" _debug "Getting txt records" - _arvan_rest GET "${_domain}/dns-records" + shorted_txtvalue=$(printf "%s" "$txtvalue" | cut -d "-" -d "_" -f1) + _arvan_rest GET "${_domain}/dns-records?search=$shorted_txtvalue" + if ! printf "%s" "$response" | grep \"current_page\":1 >/dev/null; then _err "Error on Arvan Api" _err "Please create a github issue with debbug log" return 1 fi - _record_id=$(echo "$response" | _egrep_o ".\"id\":\"[^\"]*\",\"type\":\"txt\",\"name\":\"_acme-challenge\",\"value\":{\"text\":\"$txtvalue\"}" | cut -d : -f 2 | cut -d , -f 1 | tr -d \") - if ! _arvan_rest "DELETE" "${_domain}/dns-records/${_record_id}"; then - _err "Error on Arvan Api" - return 1 + count=$(printf "%s\n" "$response" | _egrep_o "\"total\":[^,]*" | cut -d : -f 2) + _debug count "$count" + if [ "$count" = "0" ]; then + _info "Don't need to remove." + else + record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1) + _debug "record_id" "$record_id" + if [ -z "$record_id" ]; then + _err "Can not get record id to remove." + return 1 + fi + if ! _arvan_rest "DELETE" "${_domain}/dns-records/$record_id"; then + _err "Delete record error." + return 1 + fi + _debug "$response" + _contains "$response" 'dns record deleted' fi - _debug "$response" - _contains "$response" 'dns record deleted' - return 0 } #################### Private functions below ################################## @@ -99,7 +111,7 @@ dns_arvan_rm() { # _domain_id=sdjkglgdfewsdfg _get_root() { domain=$1 - i=2 + i=1 p=1 while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) @@ -109,11 +121,12 @@ _get_root() { return 1 fi - if ! _arvan_rest GET "$h"; then + if ! _arvan_rest GET "?search=$h"; then return 1 fi - if _contains "$response" "\"domain\":\"$h\""; then - _domain_id=$(echo "$response" | cut -d : -f 3 | cut -d , -f 1 | tr -d \") + + if _contains "$response" "\"domain\":\"$h\"" || _contains "$response" '"total":1'; then + _domain_id=$(echo "$response" | _egrep_o "\[.\"id\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \") if [ "$_domain_id" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain=$h @@ -133,6 +146,7 @@ _arvan_rest() { data="$3" token_trimmed=$(echo "$Arvan_Token" | tr -d '"') + export _H1="Authorization: $token_trimmed" if [ "$mtd" = "DELETE" ]; then @@ -146,5 +160,4 @@ _arvan_rest() { else response="$(_get "$ARVAN_API_URL/$ep$data")" fi - return 0 } diff --git a/dnsapi/dns_dp.sh b/dnsapi/dns_dp.sh index 9b8b7a8b..033fa5aa 100755 --- a/dnsapi/dns_dp.sh +++ b/dnsapi/dns_dp.sh @@ -89,7 +89,7 @@ add_record() { _info "Adding record" - if ! _rest POST "Record.Create" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=%E9%BB%98%E8%AE%A4"; then + if ! _rest POST "Record.Create" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=默认"; then return 1 fi diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index d6e1dbdc..618e12c6 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -12,7 +12,7 @@ DuckDNS_API="https://www.duckdns.org/update" -######## Public functions ###################### +######## Public functions ##################### #Usage: dns_duckdns_add _acme-challenge.domain.duckdns.org "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_duckdns_add() { @@ -112,7 +112,7 @@ _duckdns_rest() { param="$2" _debug param "$param" url="$DuckDNS_API?$param" - if [ -n "$DEBUG" ] && [ "$DEBUG" -gt 0 ]; then + if [ "$DEBUG" -gt 0 ]; then url="$url&verbose=true" fi _debug url "$url" @@ -121,7 +121,7 @@ _duckdns_rest() { if [ "$method" = "GET" ]; then response="$(_get "$url")" _debug2 response "$response" - if [ -n "$DEBUG" ] && [ "$DEBUG" -gt 0 ] && _contains "$response" "UPDATED" && _contains "$response" "OK"; then + if [ "$DEBUG" -gt 0 ] && _contains "$response" "UPDATED" && _contains "$response" "OK"; then response="OK" fi else diff --git a/dnsapi/dns_huaweicloud.sh b/dnsapi/dns_huaweicloud.sh index f7192725..74fec2a9 100644 --- a/dnsapi/dns_huaweicloud.sh +++ b/dnsapi/dns_huaweicloud.sh @@ -5,7 +5,7 @@ # HUAWEICLOUD_ProjectID iam_api="https://iam.myhuaweicloud.com" -dns_api="https://dns.ap-southeast-1.myhuaweicloud.com" # Should work +dns_api="https://dns.ap-southeast-1.myhuaweicloud.com" ######## Public functions ##################### @@ -29,27 +29,16 @@ dns_huaweicloud_add() { return 1 fi - unset token # Clear token token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_ProjectID}")" - if [ -z "${token}" ]; then # Check token - _err "dns_api(dns_huaweicloud): Error getting token." - return 1 - fi - _debug "Access token is: ${token}" - - unset zoneid + _debug2 "${token}" zoneid="$(_get_zoneid "${token}" "${fulldomain}")" - if [ -z "${zoneid}" ]; then - _err "dns_api(dns_huaweicloud): Error getting zone id." - return 1 - fi - _debug "Zone ID is: ${zoneid}" + _debug "${zoneid}" _debug "Adding Record" _add_record "${token}" "${fulldomain}" "${txtvalue}" ret="$?" if [ "${ret}" != "0" ]; then - _err "dns_api(dns_huaweicloud): Error adding record." + _err "dns_huaweicloud: Error adding record." return 1 fi @@ -80,21 +69,12 @@ dns_huaweicloud_rm() { return 1 fi - unset token # Clear token token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_ProjectID}")" - if [ -z "${token}" ]; then # Check token - _err "dns_api(dns_huaweicloud): Error getting token." - return 1 - fi - _debug "Access token is: ${token}" - - unset zoneid + _debug2 "${token}" zoneid="$(_get_zoneid "${token}" "${fulldomain}")" - if [ -z "${zoneid}" ]; then - _err "dns_api(dns_huaweicloud): Error getting zone id." - return 1 - fi - _debug "Zone ID is: ${zoneid}" + _debug "${zoneid}" + record_id="$(_get_recordset_id "${token}" "${fulldomain}" "${zoneid}")" + _debug "Record Set ID is: ${record_id}" # Remove all records # Therotically HuaweiCloud does not allow more than one record set diff --git a/dnsapi/dns_ionos.sh b/dnsapi/dns_ionos.sh index aaf8580f..e6bd5000 100755 --- a/dnsapi/dns_ionos.sh +++ b/dnsapi/dns_ionos.sh @@ -24,9 +24,20 @@ dns_ionos_add() { return 1 fi - _body="[{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}]" + _new_record="{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}" - if _ionos_rest POST "$IONOS_ROUTE_ZONES/$_zone_id/records" "$_body" && [ -z "$response" ]; then + # As no POST route is supported by the API, check for existing records and include them in the PATCH request in order not delete them. + # This is required to support ACME v2 wildcard certificate creation, where two TXT records for the same domain name are created. + + _ionos_get_existing_records "$fulldomain" "$_zone_id" + + if [ "$_existing_records" ]; then + _body="[$_new_record,$_existing_records]" + else + _body="[$_new_record]" + fi + + if _ionos_rest PATCH "$IONOS_ROUTE_ZONES/$_zone_id" "$_body" && [ -z "$response" ]; then _info "TXT record has been created successfully." return 0 fi @@ -114,6 +125,17 @@ _get_root() { return 1 } +_ionos_get_existing_records() { + fulldomain=$1 + zone_id=$2 + + if _ionos_rest GET "$IONOS_ROUTE_ZONES/$zone_id?recordName=$fulldomain&recordType=TXT"; then + response="$(echo "$response" | tr -d "\n")" + + _existing_records="$(printf "%s\n" "$response" | _egrep_o "\"records\":\[.*\]" | _head_n 1 | cut -d '[' -f 2 | sed 's/]//')" + fi +} + _ionos_get_record() { fulldomain=$1 zone_id=$2 @@ -146,7 +168,7 @@ _ionos_rest() { export _H2="Accept: application/json" export _H3="Content-Type: application/json" - response="$(_post "$data" "$IONOS_API$route" "" "$method" "application/json")" + response="$(_post "$data" "$IONOS_API$route" "" "$method")" else export _H2="Accept: */*" diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index d15d6b0e..7ce39fa9 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -208,7 +208,7 @@ _namecheap_parse_host() { _hostid=$(echo "$_host" | _egrep_o ' HostId="[^"]*' | cut -d '"' -f 2) _hostname=$(echo "$_host" | _egrep_o ' Name="[^"]*' | cut -d '"' -f 2) _hosttype=$(echo "$_host" | _egrep_o ' Type="[^"]*' | cut -d '"' -f 2) - _hostaddress=$(echo "$_host" | _egrep_o ' Address="[^"]*' | cut -d '"' -f 2 | _xml_decode) + _hostaddress=$(echo "$_host" | _egrep_o ' Address="[^"]*' | cut -d '"' -f 2) _hostmxpref=$(echo "$_host" | _egrep_o ' MXPref="[^"]*' | cut -d '"' -f 2) _hostttl=$(echo "$_host" | _egrep_o ' TTL="[^"]*' | cut -d '"' -f 2) @@ -405,7 +405,3 @@ _namecheap_set_tld_sld() { done } - -_xml_decode() { - sed 's/"/"/g' -} diff --git a/dnsapi/dns_pdns.sh b/dnsapi/dns_pdns.sh index 28b35492..8f07e8c4 100755 --- a/dnsapi/dns_pdns.sh +++ b/dnsapi/dns_pdns.sh @@ -175,13 +175,13 @@ _get_root() { i=1 if _pdns_rest "GET" "/api/v1/servers/$PDNS_ServerId/zones"; then - _zones_response=$(echo "$response" | _normalizeJson) + _zones_response="$response" fi while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) - if _contains "$_zones_response" "\"name\":\"$h.\""; then + if _contains "$_zones_response" "\"name\": \"$h.\""; then _domain="$h." if [ -z "$h" ]; then _domain="=2E" diff --git a/dnsapi/dns_porkbun.sh b/dnsapi/dns_porkbun.sh deleted file mode 100644 index 18da6b2f..00000000 --- a/dnsapi/dns_porkbun.sh +++ /dev/null @@ -1,157 +0,0 @@ -#!/usr/bin/env sh - -# -#PORKBUN_API_KEY="pk1_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" -#PORKBUN_SECRET_API_KEY="sk1_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" - -PORKBUN_Api="https://porkbun.com/api/json/v3" - -######## Public functions ##################### - -#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" -dns_porkbun_add() { - fulldomain=$1 - txtvalue=$2 - - PORKBUN_API_KEY="${PORKBUN_API_KEY:-$(_readaccountconf_mutable PORKBUN_API_KEY)}" - PORKBUN_SECRET_API_KEY="${PORKBUN_SECRET_API_KEY:-$(_readaccountconf_mutable PORKBUN_SECRET_API_KEY)}" - - if [ -z "$PORKBUN_API_KEY" ] || [ -z "$PORKBUN_SECRET_API_KEY" ]; then - PORKBUN_API_KEY='' - PORKBUN_SECRET_API_KEY='' - _err "You didn't specify a Porkbun api key and secret api key yet." - _err "You can get yours from here https://porkbun.com/account/api." - return 1 - fi - - #save the credentials to the account conf file. - _saveaccountconf_mutable PORKBUN_API_KEY "$PORKBUN_API_KEY" - _saveaccountconf_mutable PORKBUN_SECRET_API_KEY "$PORKBUN_SECRET_API_KEY" - - _debug 'First detect the root zone' - if ! _get_root "$fulldomain"; then - return 1 - fi - _debug _sub_domain "$_sub_domain" - _debug _domain "$_domain" - - # For wildcard cert, the main root domain and the wildcard domain have the same txt subdomain name, so - # we can not use updating anymore. - # count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2) - # _debug count "$count" - # if [ "$count" = "0" ]; then - _info "Adding record" - if _porkbun_rest POST "dns/create/$_domain" "{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":120}"; then - if _contains "$response" '\"status\":"SUCCESS"'; then - _info "Added, OK" - return 0 - elif _contains "$response" "The record already exists"; then - _info "Already exists, OK" - return 0 - else - _err "Add txt record error. ($response)" - return 1 - fi - fi - _err "Add txt record error." - return 1 - -} - -#fulldomain txtvalue -dns_porkbun_rm() { - fulldomain=$1 - txtvalue=$2 - - PORKBUN_API_KEY="${PORKBUN_API_KEY:-$(_readaccountconf_mutable PORKBUN_API_KEY)}" - PORKBUN_SECRET_API_KEY="${PORKBUN_SECRET_API_KEY:-$(_readaccountconf_mutable PORKBUN_SECRET_API_KEY)}" - - _debug 'First detect the root zone' - if ! _get_root "$fulldomain"; then - return 1 - fi - _debug _sub_domain "$_sub_domain" - _debug _domain "$_domain" - - count=$(echo "$response" | _egrep_o "\"count\": *[^,]*" | cut -d : -f 2 | tr -d " ") - _debug count "$count" - if [ "$count" = "0" ]; then - _info "Don't need to remove." - else - record_id=$(echo "$response" | tr '{' '\n' | grep "$txtvalue" | cut -d, -f1 | cut -d: -f2 | tr -d \") - _debug "record_id" "$record_id" - if [ -z "$record_id" ]; then - _err "Can not get record id to remove." - return 1 - fi - if ! _porkbun_rest POST "dns/delete/$_domain/$record_id"; then - _err "Delete record error." - return 1 - fi - echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null - fi - -} - -#################### Private functions below ################################## -#_acme-challenge.www.domain.com -#returns -# _sub_domain=_acme-challenge.www -# _domain=domain.com -_get_root() { - domain=$1 - i=1 - while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) - _debug h "$h" - if [ -z "$h" ]; then - return 1 - fi - - if _porkbun_rest POST "dns/retrieve/$h"; then - if _contains "$response" "\"status\":\"SUCCESS\""; then - _sub_domain="$(echo "$fulldomain" | sed "s/\\.$_domain\$//")" - _domain=$h - return 0 - else - _debug "Go to next level of $_domain" - fi - else - _debug "Go to next level of $_domain" - fi - i=$(_math "$i" + 1) - done - - return 1 -} - -_porkbun_rest() { - m=$1 - ep="$2" - data="$3" - _debug "$ep" - - api_key_trimmed=$(echo "$PORKBUN_API_KEY" | tr -d '"') - secret_api_key_trimmed=$(echo "$PORKBUN_SECRET_API_KEY" | tr -d '"') - - test -z "$data" && data="{" || data="$(echo $data | cut -d'}' -f1)," - data="$data\"apikey\":\"$api_key_trimmed\",\"secretapikey\":\"$secret_api_key_trimmed\"}" - - export _H1="Content-Type: application/json" - - if [ "$m" != "GET" ]; then - _debug data "$data" - response="$(_post "$data" "$PORKBUN_Api/$ep" "" "$m")" - else - response="$(_get "$PORKBUN_Api/$ep")" - fi - - _sleep 3 # prevent rate limit - - if [ "$?" != "0" ]; then - _err "error $ep" - return 1 - fi - _debug2 response "$response" - return 0 -} diff --git a/dnsapi/dns_servercow.sh b/dnsapi/dns_servercow.sh index f70a2294..e73d85b0 100755 --- a/dnsapi/dns_servercow.sh +++ b/dnsapi/dns_servercow.sh @@ -49,42 +49,16 @@ dns_servercow_add() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - # check whether a txt record already exists for the subdomain - if printf -- "%s" "$response" | grep "{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\"" >/dev/null; then - _info "A txt record with the same name already exists." - # trim the string on the left - txtvalue_old=${response#*{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\",\"content\":\"} - # trim the string on the right - txtvalue_old=${txtvalue_old%%\"*} - - _debug txtvalue_old "$txtvalue_old" - - _info "Add the new txtvalue to the existing txt record." - if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":[\"$txtvalue\",\"$txtvalue_old\"],\"ttl\":20}"; then - if printf -- "%s" "$response" | grep "ok" >/dev/null; then - _info "Added additional txtvalue, OK" - return 0 - else - _err "add txt record error." - return 1 - fi - fi - _err "add txt record error." - return 1 - else - _info "There is no txt record with the name yet." - if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then - if printf -- "%s" "$response" | grep "ok" >/dev/null; then - _info "Added, OK" - return 0 - else - _err "add txt record error." - return 1 - fi + if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then + if printf -- "%s" "$response" | grep "ok" >/dev/null; then + _info "Added, OK" + return 0 + else + _err "add txt record error." + return 1 fi - _err "add txt record error." - return 1 fi + _err "add txt record error." return 1 } diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index e0e05017..d053dcf6 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -6,10 +6,8 @@ #SIMPLY_ApiKey="apikey" # #SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]" -SIMPLY_Api_Default="https://api.simply.com/1" -#This is used for determining success of REST call -SIMPLY_SUCCESS_CODE='"status": 200' +SIMPLY_Api_Default="https://api.simply.com/1" ######## Public functions ##################### #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" @@ -173,7 +171,7 @@ _get_root() { return 1 fi - if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then + if _contains "$response" '"code":"NOT_FOUND"'; then _debug "$h not found" else _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) @@ -198,12 +196,6 @@ _simply_add_record() { return 1 fi - if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then - _err "Call to API not sucessfull, see below message for more details" - _err "$response" - return 1 - fi - return 0 } @@ -219,12 +211,6 @@ _simply_delete_record() { return 1 fi - if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then - _err "Call to API not sucessfull, see below message for more details" - _err "$response" - return 1 - fi - return 0 } diff --git a/notify/smtp.sh b/notify/smtp.sh index 293c665e..6aa37ca3 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -2,398 +2,14 @@ # support smtp -# Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3358 - -# This implementation uses either curl or Python (3 or 2.7). -# (See also the "mail" notify hook, which supports other ways to send mail.) - -# SMTP_FROM="from@example.com" # required -# SMTP_TO="to@example.com" # required -# SMTP_HOST="smtp.example.com" # required -# SMTP_PORT="25" # defaults to 25, 465 or 587 depending on SMTP_SECURE -# SMTP_SECURE="tls" # one of "none", "ssl" (implicit TLS, TLS Wrapper), "tls" (explicit TLS, STARTTLS) -# SMTP_USERNAME="" # set if SMTP server requires login -# SMTP_PASSWORD="" # set if SMTP server requires login -# SMTP_TIMEOUT="30" # seconds for SMTP operations to timeout -# SMTP_BIN="/path/to/python_or_curl" # default finds first of python3, python2.7, python, pypy3, pypy, curl on PATH - -SMTP_SECURE_DEFAULT="tls" -SMTP_TIMEOUT_DEFAULT="30" - -# subject content statuscode smtp_send() { - SMTP_SUBJECT="$1" - SMTP_CONTENT="$2" - # UNUSED: _statusCode="$3" # 0: success, 1: error 2($RENEW_SKIP): skipped - - # Load and validate config: - SMTP_BIN="$(_readaccountconf_mutable_default SMTP_BIN)" - if [ -n "$SMTP_BIN" ] && ! _exists "$SMTP_BIN"; then - _err "SMTP_BIN '$SMTP_BIN' does not exist." - return 1 - fi - if [ -z "$SMTP_BIN" ]; then - # Look for a command that can communicate with an SMTP server. - # (Please don't add sendmail, ssmtp, mutt, mail, or msmtp here. - # Those are already handled by the "mail" notify hook.) - for cmd in python3 python2.7 python pypy3 pypy curl; do - if _exists "$cmd"; then - SMTP_BIN="$cmd" - break - fi - done - if [ -z "$SMTP_BIN" ]; then - _err "The smtp notify-hook requires curl or Python, but can't find any." - _err 'If you have one of them, define SMTP_BIN="/path/to/curl_or_python".' - _err 'Otherwise, see if you can use the "mail" notify-hook instead.' - return 1 - fi - fi - _debug SMTP_BIN "$SMTP_BIN" - _saveaccountconf_mutable_default SMTP_BIN "$SMTP_BIN" - - SMTP_FROM="$(_readaccountconf_mutable_default SMTP_FROM)" - SMTP_FROM="$(_clean_email_header "$SMTP_FROM")" - if [ -z "$SMTP_FROM" ]; then - _err "You must define SMTP_FROM as the sender email address." - return 1 - fi - if _email_has_display_name "$SMTP_FROM"; then - _err "SMTP_FROM must be only a simple email address (sender@example.com)." - _err "Change your SMTP_FROM='$SMTP_FROM' to remove the display name." - return 1 - fi - _debug SMTP_FROM "$SMTP_FROM" - _saveaccountconf_mutable_default SMTP_FROM "$SMTP_FROM" - - SMTP_TO="$(_readaccountconf_mutable_default SMTP_TO)" - SMTP_TO="$(_clean_email_header "$SMTP_TO")" - if [ -z "$SMTP_TO" ]; then - _err "You must define SMTP_TO as the recipient email address(es)." - return 1 - fi - if _email_has_display_name "$SMTP_TO"; then - _err "SMTP_TO must be only simple email addresses (to@example.com,to2@example.com)." - _err "Change your SMTP_TO='$SMTP_TO' to remove the display name(s)." - return 1 - fi - _debug SMTP_TO "$SMTP_TO" - _saveaccountconf_mutable_default SMTP_TO "$SMTP_TO" - - SMTP_HOST="$(_readaccountconf_mutable_default SMTP_HOST)" - if [ -z "$SMTP_HOST" ]; then - _err "You must define SMTP_HOST as the SMTP server hostname." - return 1 - fi - _debug SMTP_HOST "$SMTP_HOST" - _saveaccountconf_mutable_default SMTP_HOST "$SMTP_HOST" - - SMTP_SECURE="$(_readaccountconf_mutable_default SMTP_SECURE "$SMTP_SECURE_DEFAULT")" - case "$SMTP_SECURE" in - "none") smtp_port_default="25" ;; - "ssl") smtp_port_default="465" ;; - "tls") smtp_port_default="587" ;; - *) - _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." - return 1 - ;; - esac - _debug SMTP_SECURE "$SMTP_SECURE" - _saveaccountconf_mutable_default SMTP_SECURE "$SMTP_SECURE" "$SMTP_SECURE_DEFAULT" - - SMTP_PORT="$(_readaccountconf_mutable_default SMTP_PORT "$smtp_port_default")" - case "$SMTP_PORT" in - *[!0-9]*) - _err "Invalid SMTP_PORT='$SMTP_PORT'. It must be a port number." - return 1 - ;; - esac - _debug SMTP_PORT "$SMTP_PORT" - _saveaccountconf_mutable_default SMTP_PORT "$SMTP_PORT" "$smtp_port_default" - - SMTP_USERNAME="$(_readaccountconf_mutable_default SMTP_USERNAME)" - _debug SMTP_USERNAME "$SMTP_USERNAME" - _saveaccountconf_mutable_default SMTP_USERNAME "$SMTP_USERNAME" - - SMTP_PASSWORD="$(_readaccountconf_mutable_default SMTP_PASSWORD)" - _secure_debug SMTP_PASSWORD "$SMTP_PASSWORD" - _saveaccountconf_mutable_default SMTP_PASSWORD "$SMTP_PASSWORD" - - SMTP_TIMEOUT="$(_readaccountconf_mutable_default SMTP_TIMEOUT "$SMTP_TIMEOUT_DEFAULT")" - _debug SMTP_TIMEOUT "$SMTP_TIMEOUT" - _saveaccountconf_mutable_default SMTP_TIMEOUT "$SMTP_TIMEOUT" "$SMTP_TIMEOUT_DEFAULT" - - SMTP_X_MAILER="$(_clean_email_header "$PROJECT_NAME $VER --notify-hook smtp")" - - # Run with --debug 2 (or above) to echo the transcript of the SMTP session. - # Careful: this may include SMTP_PASSWORD in plaintext! - if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then - SMTP_SHOW_TRANSCRIPT="True" - else - SMTP_SHOW_TRANSCRIPT="" - fi - - SMTP_SUBJECT=$(_clean_email_header "$SMTP_SUBJECT") - _debug SMTP_SUBJECT "$SMTP_SUBJECT" - _debug SMTP_CONTENT "$SMTP_CONTENT" - - # Send the message: - case "$(basename "$SMTP_BIN")" in - curl) _smtp_send=_smtp_send_curl ;; - py*) _smtp_send=_smtp_send_python ;; - *) - _err "Can't figure out how to invoke '$SMTP_BIN'." - _err "Check your SMTP_BIN setting." - return 1 - ;; - esac - - if ! smtp_output="$($_smtp_send)"; then - _err "Error sending message with $SMTP_BIN." - if [ -n "$smtp_output" ]; then - _err "$smtp_output" - fi - return 1 - fi - - return 0 -} - -# Strip CR and NL from text to prevent MIME header injection -# text -_clean_email_header() { - printf "%s" "$(echo "$1" | tr -d "\r\n")" -} - -# Simple check for display name in an email address (< > or ") -# email -_email_has_display_name() { - _email="$1" - expr "$_email" : '^.*[<>"]' >/dev/null -} - -## -## curl smtp sending -## - -# Send the message via curl using SMTP_* variables -_smtp_send_curl() { - # Build curl args in $@ - case "$SMTP_SECURE" in - none) - set -- --url "smtp://${SMTP_HOST}:${SMTP_PORT}" - ;; - ssl) - set -- --url "smtps://${SMTP_HOST}:${SMTP_PORT}" - ;; - tls) - set -- --url "smtp://${SMTP_HOST}:${SMTP_PORT}" --ssl-reqd - ;; - *) - # This will only occur if someone adds a new SMTP_SECURE option above - # without updating this code for it. - _err "Unhandled SMTP_SECURE='$SMTP_SECURE' in _smtp_send_curl" - _err "Please re-run with --debug and report a bug." - return 1 - ;; - esac - - set -- "$@" \ - --upload-file - \ - --mail-from "$SMTP_FROM" \ - --max-time "$SMTP_TIMEOUT" - - # Burst comma-separated $SMTP_TO into individual --mail-rcpt args. - _to="${SMTP_TO}," - while [ -n "$_to" ]; do - _rcpt="${_to%%,*}" - _to="${_to#*,}" - set -- "$@" --mail-rcpt "$_rcpt" - done - - _smtp_login="${SMTP_USERNAME}:${SMTP_PASSWORD}" - if [ "$_smtp_login" != ":" ]; then - set -- "$@" --user "$_smtp_login" - fi - - if [ "$SMTP_SHOW_TRANSCRIPT" = "True" ]; then - set -- "$@" --verbose - else - set -- "$@" --silent --show-error - fi - - raw_message="$(_smtp_raw_message)" - - _debug2 "curl command:" "$SMTP_BIN" "$*" - _debug2 "raw_message:\n$raw_message" - - echo "$raw_message" | "$SMTP_BIN" "$@" -} - -# Output an RFC-822 / RFC-5322 email message using SMTP_* variables. -# (This assumes variables have already been cleaned for use in email headers.) -_smtp_raw_message() { - echo "From: $SMTP_FROM" - echo "To: $SMTP_TO" - echo "Subject: $(_mime_encoded_word "$SMTP_SUBJECT")" - echo "Date: $(_rfc2822_date)" - echo "Content-Type: text/plain; charset=utf-8" - echo "X-Mailer: $SMTP_X_MAILER" - echo - echo "$SMTP_CONTENT" -} - -# Convert text to RFC-2047 MIME "encoded word" format if it contains non-ASCII chars -# text -_mime_encoded_word() { - _text="$1" - # (regex character ranges like [a-z] can be locale-dependent; enumerate ASCII chars to avoid that) - _ascii='] $`"'"[!#%&'()*+,./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ~^_abcdefghijklmnopqrstuvwxyz{|}~-" - if expr "$_text" : "^.*[^$_ascii]" >/dev/null; then - # At least one non-ASCII char; convert entire thing to encoded word - printf "%s" "=?UTF-8?B?$(printf "%s" "$_text" | _base64)?=" - else - # Just printable ASCII, no conversion needed - printf "%s" "$_text" - fi -} - -# Output current date in RFC-2822 Section 3.3 format as required in email headers -# (e.g., "Mon, 15 Feb 2021 14:22:01 -0800") -_rfc2822_date() { - # Notes: - # - this is deliberately not UTC, because it "SHOULD express local time" per spec - # - the spec requires weekday and month in the C locale (English), not localized - # - this date format specifier has been tested on Linux, Mac, Solaris and FreeBSD - _old_lc_time="$LC_TIME" - LC_TIME=C - date +'%a, %-d %b %Y %H:%M:%S %z' - LC_TIME="$_old_lc_time" -} - -## -## Python smtp sending -## - -# Send the message via Python using SMTP_* variables -_smtp_send_python() { - _debug "Python version" "$("$SMTP_BIN" --version 2>&1)" - - # language=Python - "$SMTP_BIN" < Date: Tue, 5 Jan 2021 15:29:08 +0330 Subject: [PATCH 139/304] change arvan api script --- dnsapi/dns_arvan.sh | 43 +++++++++++++++---------------------------- 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/dnsapi/dns_arvan.sh b/dnsapi/dns_arvan.sh index ca1f56c7..3c4ced15 100644 --- a/dnsapi/dns_arvan.sh +++ b/dnsapi/dns_arvan.sh @@ -3,7 +3,6 @@ #Arvan_Token="xxxx" ARVAN_API_URL="https://napi.arvancloud.com/cdn/4.0/domains" - #Author: Ehsan Aliakbar #Report Bugs here: https://github.com/Neilpang/acme.sh # @@ -38,6 +37,7 @@ dns_arvan_add() { _info "Adding record" if _arvan_rest POST "$_domain/dns-records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":{\"text\":\"$txtvalue\"},\"ttl\":120}"; then if _contains "$response" "$txtvalue"; then + _info "response id is $response" _info "Added, OK" return 0 elif _contains "$response" "Record Data is Duplicated"; then @@ -49,7 +49,7 @@ dns_arvan_add() { fi fi _err "Add txt record error." - return 1 + return 0 } #Usage: fulldomain txtvalue @@ -73,33 +73,21 @@ dns_arvan_rm() { _debug _domain "$_domain" _debug "Getting txt records" - shorted_txtvalue=$(printf "%s" "$txtvalue" | cut -d "-" -d "_" -f1) - _arvan_rest GET "${_domain}/dns-records?search=$shorted_txtvalue" - + _arvan_rest GET "${_domain}/dns-records" if ! printf "%s" "$response" | grep \"current_page\":1 >/dev/null; then _err "Error on Arvan Api" _err "Please create a github issue with debbug log" return 1 fi - count=$(printf "%s\n" "$response" | _egrep_o "\"total\":[^,]*" | cut -d : -f 2) - _debug count "$count" - if [ "$count" = "0" ]; then - _info "Don't need to remove." - else - record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1) - _debug "record_id" "$record_id" - if [ -z "$record_id" ]; then - _err "Can not get record id to remove." - return 1 - fi - if ! _arvan_rest "DELETE" "${_domain}/dns-records/$record_id"; then - _err "Delete record error." - return 1 - fi - _debug "$response" - _contains "$response" 'dns record deleted' + _record_id=$(echo "$response" | _egrep_o ".\"id\":\"[^\"]*\",\"type\":\"txt\",\"name\":\"_acme-challenge\",\"value\":{\"text\":\"$txtvalue\"}" | cut -d : -f 2 | cut -d , -f 1 | tr -d \") + if ! _arvan_rest "DELETE" "${_domain}/dns-records/${_record_id}"; then + _err "Error on Arvan Api" + return 1 fi + _debug "$response" + _contains "$response" 'dns record deleted' + return 0 } #################### Private functions below ################################## @@ -111,7 +99,7 @@ dns_arvan_rm() { # _domain_id=sdjkglgdfewsdfg _get_root() { domain=$1 - i=1 + i=2 p=1 while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) @@ -121,12 +109,11 @@ _get_root() { return 1 fi - if ! _arvan_rest GET "?search=$h"; then + if ! _arvan_rest GET "$h"; then return 1 fi - - if _contains "$response" "\"domain\":\"$h\"" || _contains "$response" '"total":1'; then - _domain_id=$(echo "$response" | _egrep_o "\[.\"id\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \") + if _contains "$response" "\"domain\":\"$h\""; then + _domain_id=$(echo "$response" | cut -d : -f 3 | cut -d , -f 1 | tr -d \") if [ "$_domain_id" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain=$h @@ -146,7 +133,6 @@ _arvan_rest() { data="$3" token_trimmed=$(echo "$Arvan_Token" | tr -d '"') - export _H1="Authorization: $token_trimmed" if [ "$mtd" = "DELETE" ]; then @@ -160,4 +146,5 @@ _arvan_rest() { else response="$(_get "$ARVAN_API_URL/$ep$data")" fi + return 0 } From 1d70b989414f10e0ff97b446b42fa21c271d4280 Mon Sep 17 00:00:00 2001 From: Vahid Fardi Date: Tue, 5 Jan 2021 17:10:41 +0330 Subject: [PATCH 140/304] change Author name --- dnsapi/dns_arvan.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_arvan.sh b/dnsapi/dns_arvan.sh index 3c4ced15..a33504d0 100644 --- a/dnsapi/dns_arvan.sh +++ b/dnsapi/dns_arvan.sh @@ -1,10 +1,10 @@ #!/usr/bin/env sh -#Arvan_Token="xxxx" +#Arvan_Token="Apikey xxxx" ARVAN_API_URL="https://napi.arvancloud.com/cdn/4.0/domains" -#Author: Ehsan Aliakbar -#Report Bugs here: https://github.com/Neilpang/acme.sh +#Author: Vahid Fardi +#Report Bugs here: https://github.com/fvahid/acme.sh # ######## Public functions ##################### From 4a86e71442bac1d5c822f2e329f4ef31c24ff2a4 Mon Sep 17 00:00:00 2001 From: Vahid Fardi Date: Tue, 5 Jan 2021 21:31:31 +0330 Subject: [PATCH 141/304] change name actor --- dnsapi/dns_arvan.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_arvan.sh b/dnsapi/dns_arvan.sh index a33504d0..4c9217e5 100644 --- a/dnsapi/dns_arvan.sh +++ b/dnsapi/dns_arvan.sh @@ -4,7 +4,7 @@ ARVAN_API_URL="https://napi.arvancloud.com/cdn/4.0/domains" #Author: Vahid Fardi -#Report Bugs here: https://github.com/fvahid/acme.sh +#Report Bugs here: https://github.com/Neilpang/acme.sh # ######## Public functions ##################### From 6cea1cbb574cf2fdfddca040816d5edcddf1de83 Mon Sep 17 00:00:00 2001 From: Gnought <1684105+gnought@users.noreply.github.com> Date: Thu, 11 Feb 2021 01:08:08 +0800 Subject: [PATCH 142/304] Updated --preferred-chain to issue ISRG properly To support different openssl crl2pkcs7 help cli format --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 21fd6a8f..47603e3b 100755 --- a/acme.sh +++ b/acme.sh @@ -4013,7 +4013,7 @@ _check_dns_entries() { #file _get_cert_issuers() { _cfile="$1" - if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then + if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -help 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 else ${ACME_OPENSSL_BIN:-openssl} x509 -in $_cfile -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 From b822da93f488675e65798de14c852cac7dd0dba7 Mon Sep 17 00:00:00 2001 From: manuel Date: Thu, 11 Feb 2021 11:20:18 +0100 Subject: [PATCH 143/304] dnsapi/pdns: also normalize json response in detecting root zone --- dnsapi/dns_pdns.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_pdns.sh b/dnsapi/dns_pdns.sh index 8f07e8c4..28b35492 100755 --- a/dnsapi/dns_pdns.sh +++ b/dnsapi/dns_pdns.sh @@ -175,13 +175,13 @@ _get_root() { i=1 if _pdns_rest "GET" "/api/v1/servers/$PDNS_ServerId/zones"; then - _zones_response="$response" + _zones_response=$(echo "$response" | _normalizeJson) fi while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) - if _contains "$_zones_response" "\"name\": \"$h.\""; then + if _contains "$_zones_response" "\"name\":\"$h.\""; then _domain="$h." if [ -z "$h" ]; then _domain="=2E" From 1b2b4af3cc943e0278e0d932b49900228860be11 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 13 Feb 2021 16:22:31 +0800 Subject: [PATCH 144/304] Chain (#3408) * fix https://github.com/acmesh-official/acme.sh/issues/3384 match the issuer to the root CA cert subject * fix format * fix https://github.com/acmesh-official/acme.sh/issues/3384 * remove the alt files. https://github.com/acmesh-official/acme.sh/issues/3384 --- acme.sh | 58 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/acme.sh b/acme.sh index 47603e3b..c76fabb8 100755 --- a/acme.sh +++ b/acme.sh @@ -4011,12 +4011,42 @@ _check_dns_entries() { } #file -_get_cert_issuers() { +_get_chain_issuers() { _cfile="$1" if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -help 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then - ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 + ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep -i 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 else - ${ACME_OPENSSL_BIN:-openssl} x509 -in $_cfile -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 + _cindex=1 + for _startn in $(grep -n -- "$BEGIN_CERT" "$_cfile" | cut -d : -f 1); do + _endn="$(grep -n -- "$END_CERT" "$_cfile" | cut -d : -f 1 | _head_n $_cindex | _tail_n 1)" + _debug2 "_startn" "$_startn" + _debug2 "_endn" "$_endn" + if [ "$DEBUG" ]; then + _debug2 "cert$_cindex" "$(sed -n "$_startn,${_endn}p" "$_cfile")" + fi + sed -n "$_startn,${_endn}p" "$_cfile" | ${ACME_OPENSSL_BIN:-openssl} x509 -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 | sed "s/ *\(.*\)/\1/" + _cindex=$(_math $_cindex + 1) + done + fi +} + +# +_get_chain_subjects() { + _cfile="$1" + if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -help 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then + ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep -i 'Subject:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 + else + _cindex=1 + for _startn in $(grep -n -- "$BEGIN_CERT" "$_cfile" | cut -d : -f 1); do + _endn="$(grep -n -- "$END_CERT" "$_cfile" | cut -d : -f 1 | _head_n $_cindex | _tail_n 1)" + _debug2 "_startn" "$_startn" + _debug2 "_endn" "$_endn" + if [ "$DEBUG" ]; then + _debug2 "cert$_cindex" "$(sed -n "$_startn,${_endn}p" "$_cfile")" + fi + sed -n "$_startn,${_endn}p" "$_cfile" | ${ACME_OPENSSL_BIN:-openssl} x509 -text -noout | grep -i 'Subject:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 | sed "s/ *\(.*\)/\1/" + _cindex=$(_math $_cindex + 1) + done fi } @@ -4024,14 +4054,12 @@ _get_cert_issuers() { _match_issuer() { _cfile="$1" _missuer="$2" - _fissuers="$(_get_cert_issuers $_cfile)" + _fissuers="$(_get_chain_issuers $_cfile)" _debug2 _fissuers "$_fissuers" - if _contains "$_fissuers" "$_missuer"; then - return 0 - fi - _fissuers="$(echo "$_fissuers" | _lower_case)" + _rootissuer="$(echo "$_fissuers" | _lower_case | _tail_n 1)" + _debug2 _rootissuer "$_rootissuer" _missuer="$(echo "$_missuer" | _lower_case)" - _contains "$_fissuers" "$_missuer" + _contains "$_rootissuer" "$_missuer" } #webroot, domain domainlist keylength @@ -4805,6 +4833,9 @@ $_authorizations_map" _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" @@ -4820,13 +4851,22 @@ $_authorizations_map" _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 + rm -f "$_relcert" + rm -f "$_relfullchain" + rm -f "$_relca" done fi fi From 45a5f24d6414933d4b6a65fe0415c3b9b2381b15 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 13 Feb 2021 17:27:22 +0800 Subject: [PATCH 145/304] upgrade freebsd and solaris --- .github/workflows/LetsEncrypt.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index da46b962..ba9a5317 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -136,7 +136,7 @@ jobs: run: echo "TestingDomain=${{steps.ngrok.outputs.server}}" >> $GITHUB_ENV - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/solaris-vm@v0.0.1 + - uses: vmactions/solaris-vm@v0.0.3 with: envs: 'TEST_LOCAL TestingDomain' nat: | From e1229d4c02b2d89559d194d2b2efe9d7dde345ad Mon Sep 17 00:00:00 2001 From: jerrm Date: Sat, 13 Feb 2021 05:58:44 -0500 Subject: [PATCH 146/304] duckdns - fix "integer expression expected" errors (#3397) * fix "integer expression expected" errors * duckdns fix * Update dns_duckdns.sh * Update dns_duckdns.sh --- dnsapi/dns_duckdns.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index 618e12c6..d6e1dbdc 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -12,7 +12,7 @@ DuckDNS_API="https://www.duckdns.org/update" -######## Public functions ##################### +######## Public functions ###################### #Usage: dns_duckdns_add _acme-challenge.domain.duckdns.org "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_duckdns_add() { @@ -112,7 +112,7 @@ _duckdns_rest() { param="$2" _debug param "$param" url="$DuckDNS_API?$param" - if [ "$DEBUG" -gt 0 ]; then + if [ -n "$DEBUG" ] && [ "$DEBUG" -gt 0 ]; then url="$url&verbose=true" fi _debug url "$url" @@ -121,7 +121,7 @@ _duckdns_rest() { if [ "$method" = "GET" ]; then response="$(_get "$url")" _debug2 response "$response" - if [ "$DEBUG" -gt 0 ] && _contains "$response" "UPDATED" && _contains "$response" "OK"; then + if [ -n "$DEBUG" ] && [ "$DEBUG" -gt 0 ] && _contains "$response" "UPDATED" && _contains "$response" "OK"; then response="OK" fi else From 2000240aa6492536fb2e97eb6669e33f1165fb93 Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 29 Dec 2020 16:28:38 -0800 Subject: [PATCH 147/304] Implement smtp notify hook Support notifications via direct SMTP server connection. Uses Python (2.7.x or 3.4+) to communicate with SMTP server. --- notify/smtp.sh | 185 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 183 insertions(+), 2 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 6aa37ca3..367021c8 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -2,7 +2,103 @@ # support smtp +# This implementation uses Python (2 or 3), which is available in many environments. +# If you don't have Python, try "mail" notification instead of "smtp". + +# SMTP_FROM="from@example.com" # required +# SMTP_TO="to@example.com" # required +# SMTP_HOST="smtp.example.com" # required +# SMTP_PORT="25" # defaults to 25, 465 or 587 depending on SMTP_SECURE +# SMTP_SECURE="none" # one of "none", "ssl" (implicit TLS, TLS Wrapper), "tls" (explicit TLS, STARTTLS) +# SMTP_USERNAME="" # set if SMTP server requires login +# SMTP_PASSWORD="" # set if SMTP server requires login +# SMTP_TIMEOUT="15" # seconds for SMTP operations to timeout +# SMTP_PYTHON="/path/to/python" # defaults to system python3 or python + smtp_send() { + # Find a Python interpreter: + SMTP_PYTHON="${SMTP_PYTHON:-$(_readaccountconf_mutable SMTP_PYTHON)}" + if [ "$SMTP_PYTHON" ]; then + if _exists "$SMTP_PYTHON"; then + _saveaccountconf_mutable SMTP_PYTHON "$SMTP_PYTHON" + else + _err "SMTP_PYTHON '$SMTP_PYTHON' does not exist." + return 1 + fi + else + # No SMTP_PYTHON setting; try to run default Python. + # (This is not saved with the conf.) + if _exists python3; then + SMTP_PYTHON="python3" + elif _exists python; then + SMTP_PYTHON="python" + else + _err "Can't locate Python interpreter; please define SMTP_PYTHON." + return 1 + fi + fi + _debug "SMTP_PYTHON" "$SMTP_PYTHON" + _debug "Python version" "$($SMTP_PYTHON --version 2>&1)" + + # Validate other settings: + SMTP_FROM="${SMTP_FROM:-$(_readaccountconf_mutable SMTP_FROM)}" + if [ -z "$SMTP_FROM" ]; then + _err "You must define SMTP_FROM as the sender email address." + return 1 + fi + + SMTP_TO="${SMTP_TO:-$(_readaccountconf_mutable SMTP_TO)}" + if [ -z "$SMTP_TO" ]; then + _err "You must define SMTP_TO as the recipient email address." + return 1 + fi + + SMTP_HOST="${SMTP_HOST:-$(_readaccountconf_mutable SMTP_HOST)}" + if [ -z "$SMTP_HOST" ]; then + _err "You must define SMTP_HOST as the SMTP server hostname." + return 1 + fi + SMTP_PORT="${SMTP_PORT:-$(_readaccountconf_mutable SMTP_PORT)}" + + SMTP_SECURE="${SMTP_SECURE:-$(_readaccountconf_mutable SMTP_SECURE)}" + SMTP_SECURE="${SMTP_SECURE:-none}" + case "$SMTP_SECURE" in + "none") SMTP_DEFAULT_PORT="25";; + "ssl") SMTP_DEFAULT_PORT="465";; + "tls") SMTP_DEFAULT_PORT="587";; + *) + _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." + return 1 + ;; + esac + + SMTP_USERNAME="${SMTP_USERNAME:-$(_readaccountconf_mutable SMTP_USERNAME)}" + SMTP_PASSWORD="${SMTP_PASSWORD:-$(_readaccountconf_mutable SMTP_PASSWORD)}" + + SMTP_TIMEOUT="${SMTP_TIMEOUT:-$(_readaccountconf_mutable SMTP_TIMEOUT)}" + SMTP_DEFAULT_TIMEOUT="15" + + _saveaccountconf_mutable SMTP_FROM "$SMTP_FROM" + _saveaccountconf_mutable SMTP_TO "$SMTP_TO" + _saveaccountconf_mutable SMTP_HOST "$SMTP_HOST" + _saveaccountconf_mutable SMTP_PORT "$SMTP_PORT" + _saveaccountconf_mutable SMTP_SECURE "$SMTP_SECURE" + _saveaccountconf_mutable SMTP_USERNAME "$SMTP_USERNAME" + _saveaccountconf_mutable SMTP_PASSWORD "$SMTP_PASSWORD" + _saveaccountconf_mutable SMTP_TIMEOUT "$SMTP_TIMEOUT" + + # Send the message: + if ! _smtp_send "$@"; then + _err "$smtp_send_output" + return 1 + fi + + return 0 +} + +# _send subject content statuscode +# Send the message via Python using SMTP_* settings +_smtp_send() { _subject="$1" _content="$2" _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped @@ -10,6 +106,91 @@ smtp_send() { _debug "_content" "$_content" _debug "_statusCode" "$_statusCode" - _err "Not implemented yet." - return 1 + _debug "SMTP_FROM" "$SMTP_FROM" + _debug "SMTP_TO" "$SMTP_TO" + _debug "SMTP_HOST" "$SMTP_HOST" + _debug "SMTP_PORT" "$SMTP_PORT" + _debug "SMTP_DEFAULT_PORT" "$SMTP_DEFAULT_PORT" + _debug "SMTP_SECURE" "$SMTP_SECURE" + _debug "SMTP_USERNAME" "$SMTP_USERNAME" + _secure_debug "SMTP_PASSWORD" "$SMTP_PASSWORD" + _debug "SMTP_TIMEOUT" "$SMTP_TIMEOUT" + _debug "SMTP_DEFAULT_TIMEOUT" "$SMTP_DEFAULT_TIMEOUT" + + if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then + # Output the SMTP server dialogue. (Note this will include SMTP_PASSWORD!) + smtp_debug="True" + else + smtp_debug="" + fi + + # language=Python + smtp_send_output="$($SMTP_PYTHON < Date: Tue, 29 Dec 2020 17:10:36 -0800 Subject: [PATCH 148/304] Make shfmt happy (I'm open to better ways of formatting the heredoc that embeds the Python script.) --- notify/smtp.sh | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 367021c8..6171cb9b 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -63,13 +63,13 @@ smtp_send() { SMTP_SECURE="${SMTP_SECURE:-$(_readaccountconf_mutable SMTP_SECURE)}" SMTP_SECURE="${SMTP_SECURE:-none}" case "$SMTP_SECURE" in - "none") SMTP_DEFAULT_PORT="25";; - "ssl") SMTP_DEFAULT_PORT="465";; - "tls") SMTP_DEFAULT_PORT="587";; - *) - _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." - return 1 - ;; + "none") SMTP_DEFAULT_PORT="25" ;; + "ssl") SMTP_DEFAULT_PORT="465" ;; + "tls") SMTP_DEFAULT_PORT="587" ;; + *) + _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." + return 1 + ;; esac SMTP_USERNAME="${SMTP_USERNAME:-$(_readaccountconf_mutable SMTP_USERNAME)}" @@ -125,7 +125,8 @@ _smtp_send() { fi # language=Python - smtp_send_output="$($SMTP_PYTHON < Date: Mon, 11 Jan 2021 11:46:26 -0800 Subject: [PATCH 149/304] Only save config if send is successful --- notify/smtp.sh | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 6171cb9b..092bb2b9 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -78,6 +78,13 @@ smtp_send() { SMTP_TIMEOUT="${SMTP_TIMEOUT:-$(_readaccountconf_mutable SMTP_TIMEOUT)}" SMTP_DEFAULT_TIMEOUT="15" + # Send the message: + if ! _smtp_send "$@"; then + _err "$smtp_send_output" + return 1 + fi + + # Save remaining config if successful. (SMTP_PYTHON is saved earlier.) _saveaccountconf_mutable SMTP_FROM "$SMTP_FROM" _saveaccountconf_mutable SMTP_TO "$SMTP_TO" _saveaccountconf_mutable SMTP_HOST "$SMTP_HOST" @@ -87,12 +94,6 @@ smtp_send() { _saveaccountconf_mutable SMTP_PASSWORD "$SMTP_PASSWORD" _saveaccountconf_mutable SMTP_TIMEOUT "$SMTP_TIMEOUT" - # Send the message: - if ! _smtp_send "$@"; then - _err "$smtp_send_output" - return 1 - fi - return 0 } From 0fc1654fafec61bc1a24935db2438e929f0cd4ff Mon Sep 17 00:00:00 2001 From: medmunds Date: Mon, 11 Jan 2021 12:59:51 -0800 Subject: [PATCH 150/304] Add instructions for reporting bugs --- notify/smtp.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/notify/smtp.sh b/notify/smtp.sh index 092bb2b9..a74ce092 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -2,6 +2,8 @@ # support smtp +# Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3358 + # This implementation uses Python (2 or 3), which is available in many environments. # If you don't have Python, try "mail" notification instead of "smtp". From 30b54b8d0ffcac2b0f25629b2976eb484b881113 Mon Sep 17 00:00:00 2001 From: medmunds Date: Sun, 14 Feb 2021 15:47:51 -0800 Subject: [PATCH 151/304] Prep for curl or Python; clean up SMTP_* variable usage --- notify/smtp.sh | 203 ++++++++++++++++++++++++++++--------------------- 1 file changed, 118 insertions(+), 85 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index a74ce092..cb29d0f7 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -4,8 +4,8 @@ # Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3358 -# This implementation uses Python (2 or 3), which is available in many environments. -# If you don't have Python, try "mail" notification instead of "smtp". +# This implementation uses either curl or Python (3 or 2.7). +# (See also the "mail" notify hook, which supports other ways to send mail.) # SMTP_FROM="from@example.com" # required # SMTP_TO="to@example.com" # required @@ -14,79 +14,132 @@ # SMTP_SECURE="none" # one of "none", "ssl" (implicit TLS, TLS Wrapper), "tls" (explicit TLS, STARTTLS) # SMTP_USERNAME="" # set if SMTP server requires login # SMTP_PASSWORD="" # set if SMTP server requires login -# SMTP_TIMEOUT="15" # seconds for SMTP operations to timeout -# SMTP_PYTHON="/path/to/python" # defaults to system python3 or python +# SMTP_TIMEOUT="30" # seconds for SMTP operations to timeout +# SMTP_BIN="/path/to/curl_or_python" # default finds first of curl, python3, or python on PATH +# subject content statuscode smtp_send() { - # Find a Python interpreter: - SMTP_PYTHON="${SMTP_PYTHON:-$(_readaccountconf_mutable SMTP_PYTHON)}" - if [ "$SMTP_PYTHON" ]; then - if _exists "$SMTP_PYTHON"; then - _saveaccountconf_mutable SMTP_PYTHON "$SMTP_PYTHON" - else - _err "SMTP_PYTHON '$SMTP_PYTHON' does not exist." - return 1 - fi - else - # No SMTP_PYTHON setting; try to run default Python. - # (This is not saved with the conf.) - if _exists python3; then - SMTP_PYTHON="python3" - elif _exists python; then - SMTP_PYTHON="python" - else - _err "Can't locate Python interpreter; please define SMTP_PYTHON." + _SMTP_SUBJECT="$1" + _SMTP_CONTENT="$2" + # UNUSED: _statusCode="$3" # 0: success, 1: error 2($RENEW_SKIP): skipped + + # Load config: + SMTP_FROM="${SMTP_FROM:-$(_readaccountconf_mutable SMTP_FROM)}" + SMTP_TO="${SMTP_TO:-$(_readaccountconf_mutable SMTP_TO)}" + SMTP_HOST="${SMTP_HOST:-$(_readaccountconf_mutable SMTP_HOST)}" + SMTP_PORT="${SMTP_PORT:-$(_readaccountconf_mutable SMTP_PORT)}" + SMTP_SECURE="${SMTP_SECURE:-$(_readaccountconf_mutable SMTP_SECURE)}" + SMTP_USERNAME="${SMTP_USERNAME:-$(_readaccountconf_mutable SMTP_USERNAME)}" + SMTP_PASSWORD="${SMTP_PASSWORD:-$(_readaccountconf_mutable SMTP_PASSWORD)}" + SMTP_TIMEOUT="${SMTP_TIMEOUT:-$(_readaccountconf_mutable SMTP_TIMEOUT)}" + SMTP_BIN="${SMTP_BIN:-$(_readaccountconf_mutable SMTP_BIN)}" + + _debug "SMTP_FROM" "$SMTP_FROM" + _debug "SMTP_TO" "$SMTP_TO" + _debug "SMTP_HOST" "$SMTP_HOST" + _debug "SMTP_PORT" "$SMTP_PORT" + _debug "SMTP_SECURE" "$SMTP_SECURE" + _debug "SMTP_USERNAME" "$SMTP_USERNAME" + _secure_debug "SMTP_PASSWORD" "$SMTP_PASSWORD" + _debug "SMTP_TIMEOUT" "$SMTP_TIMEOUT" + _debug "SMTP_BIN" "$SMTP_BIN" + + _debug "_SMTP_SUBJECT" "$_SMTP_SUBJECT" + _debug "_SMTP_CONTENT" "$_SMTP_CONTENT" + + # Validate config and apply defaults: + # _SMTP_* variables are the resolved (with defaults) versions of SMTP_*. + # (The _SMTP_* versions will not be stored in account conf.) + + if [ -n "$SMTP_BIN" ] && ! _exists "$SMTP_BIN"; then + _err "SMTP_BIN '$SMTP_BIN' does not exist." + return 1 + fi + _SMTP_BIN="$SMTP_BIN" + if [ -z "$_SMTP_BIN" ]; then + # Look for a command that can communicate with an SMTP server. + # (Please don't add sendmail, ssmtp, mutt, mail, or msmtp here. + # Those are already handled by the "mail" notify hook.) + for cmd in curl python3 python2.7 python pypy3 pypy; do + if _exists "$cmd"; then + _SMTP_BIN="$cmd" + break + fi + done + if [ -z "$_SMTP_BIN" ]; then + _err "The smtp notify-hook requires curl or Python, but can't find any." + _err 'If you have one of them, define SMTP_BIN="/path/to/curl_or_python".' + _err 'Otherwise, see if you can use the "mail" notify-hook instead.' return 1 fi + _debug "_SMTP_BIN" "$_SMTP_BIN" fi - _debug "SMTP_PYTHON" "$SMTP_PYTHON" - _debug "Python version" "$($SMTP_PYTHON --version 2>&1)" - # Validate other settings: - SMTP_FROM="${SMTP_FROM:-$(_readaccountconf_mutable SMTP_FROM)}" if [ -z "$SMTP_FROM" ]; then _err "You must define SMTP_FROM as the sender email address." return 1 fi + _SMTP_FROM="$SMTP_FROM" - SMTP_TO="${SMTP_TO:-$(_readaccountconf_mutable SMTP_TO)}" if [ -z "$SMTP_TO" ]; then _err "You must define SMTP_TO as the recipient email address." return 1 fi + _SMTP_TO="$SMTP_TO" - SMTP_HOST="${SMTP_HOST:-$(_readaccountconf_mutable SMTP_HOST)}" if [ -z "$SMTP_HOST" ]; then _err "You must define SMTP_HOST as the SMTP server hostname." return 1 fi - SMTP_PORT="${SMTP_PORT:-$(_readaccountconf_mutable SMTP_PORT)}" + _SMTP_HOST="$SMTP_HOST" - SMTP_SECURE="${SMTP_SECURE:-$(_readaccountconf_mutable SMTP_SECURE)}" - SMTP_SECURE="${SMTP_SECURE:-none}" - case "$SMTP_SECURE" in - "none") SMTP_DEFAULT_PORT="25" ;; - "ssl") SMTP_DEFAULT_PORT="465" ;; - "tls") SMTP_DEFAULT_PORT="587" ;; + _SMTP_SECURE="${SMTP_SECURE:-none}" + case "$_SMTP_SECURE" in + "none") smtp_default_port="25" ;; + "ssl") smtp_default_port="465" ;; + "tls") smtp_default_port="587" ;; *) _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." return 1 ;; esac - SMTP_USERNAME="${SMTP_USERNAME:-$(_readaccountconf_mutable SMTP_USERNAME)}" - SMTP_PASSWORD="${SMTP_PASSWORD:-$(_readaccountconf_mutable SMTP_PASSWORD)}" + _SMTP_PORT="${SMTP_PORT:-$smtp_default_port}" + if [ -z "$SMTP_PORT" ]; then + _debug "_SMTP_PORT" "$_SMTP_PORT" + fi - SMTP_TIMEOUT="${SMTP_TIMEOUT:-$(_readaccountconf_mutable SMTP_TIMEOUT)}" - SMTP_DEFAULT_TIMEOUT="15" + _SMTP_USERNAME="$SMTP_USERNAME" + _SMTP_PASSWORD="$SMTP_PASSWORD" + _SMTP_TIMEOUT="${SMTP_TIMEOUT:-30}" + + # Run with --debug 2 (or above) to echo the transcript of the SMTP session. + # Careful: this may include SMTP_PASSWORD in plaintext! + if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then + _SMTP_SHOW_TRANSCRIPT="True" + else + _SMTP_SHOW_TRANSCRIPT="" + fi # Send the message: - if ! _smtp_send "$@"; then - _err "$smtp_send_output" + case "$(basename "$_SMTP_BIN")" in + curl) _smtp_send=_smtp_send_curl ;; + py*) _smtp_send=_smtp_send_python ;; + *) + _err "Can't figure out how to invoke $_SMTP_BIN." + _err "Please re-run with --debug and report a bug." + return 1 + ;; + esac + + if ! smtp_output="$($_smtp_send)"; then + _err "Error sending message with $_SMTP_BIN." + _err "${smtp_output:-(No additional details; try --debug or --debug 2)}" return 1 fi - # Save remaining config if successful. (SMTP_PYTHON is saved earlier.) + # Save config only if send was successful: + _saveaccountconf_mutable SMTP_BIN "$SMTP_BIN" _saveaccountconf_mutable SMTP_FROM "$SMTP_FROM" _saveaccountconf_mutable SMTP_TO "$SMTP_TO" _saveaccountconf_mutable SMTP_HOST "$SMTP_HOST" @@ -99,37 +152,21 @@ smtp_send() { return 0 } -# _send subject content statuscode -# Send the message via Python using SMTP_* settings -_smtp_send() { - _subject="$1" - _content="$2" - _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped - _debug "_subject" "$_subject" - _debug "_content" "$_content" - _debug "_statusCode" "$_statusCode" - _debug "SMTP_FROM" "$SMTP_FROM" - _debug "SMTP_TO" "$SMTP_TO" - _debug "SMTP_HOST" "$SMTP_HOST" - _debug "SMTP_PORT" "$SMTP_PORT" - _debug "SMTP_DEFAULT_PORT" "$SMTP_DEFAULT_PORT" - _debug "SMTP_SECURE" "$SMTP_SECURE" - _debug "SMTP_USERNAME" "$SMTP_USERNAME" - _secure_debug "SMTP_PASSWORD" "$SMTP_PASSWORD" - _debug "SMTP_TIMEOUT" "$SMTP_TIMEOUT" - _debug "SMTP_DEFAULT_TIMEOUT" "$SMTP_DEFAULT_TIMEOUT" +# Send the message via curl using _SMTP_* variables +_smtp_send_curl() { + # TODO: implement + echo "_smtp_send_curl not implemented" + return 1 +} - if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then - # Output the SMTP server dialogue. (Note this will include SMTP_PASSWORD!) - smtp_debug="True" - else - smtp_debug="" - fi + +# Send the message via Python using _SMTP_* variables +_smtp_send_python() { + _debug "Python version" "$("$_SMTP_BIN" --version 2>&1)" # language=Python - smtp_send_output="$( - $SMTP_PYTHON < Date: Sun, 14 Feb 2021 19:56:23 -0800 Subject: [PATCH 152/304] Implement curl version of smtp notify-hook --- notify/smtp.sh | 111 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 105 insertions(+), 6 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index cb29d0f7..44a5821f 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -127,14 +127,16 @@ smtp_send() { py*) _smtp_send=_smtp_send_python ;; *) _err "Can't figure out how to invoke $_SMTP_BIN." - _err "Please re-run with --debug and report a bug." + _err "Check your SMTP_BIN setting." return 1 ;; esac if ! smtp_output="$($_smtp_send)"; then _err "Error sending message with $_SMTP_BIN." - _err "${smtp_output:-(No additional details; try --debug or --debug 2)}" + if [ -n "$smtp_output" ]; then + _err "$smtp_output" + fi return 1 fi @@ -152,12 +154,109 @@ smtp_send() { return 0 } - # Send the message via curl using _SMTP_* variables _smtp_send_curl() { - # TODO: implement - echo "_smtp_send_curl not implemented" - return 1 + # curl passes --mail-from and --mail-rcpt directly to the SMTP protocol without + # additional parsing, and SMTP requires addr-spec only (no display names). + # In the future, maybe try to parse the addr-spec out for curl args (non-trivial). + if _email_has_display_name "$_SMTP_FROM"; then + _err "curl smtp only allows a simple email address in SMTP_FROM." + _err "Change your SMTP_FROM='$SMTP_FROM' to remove the display name." + return 1 + fi + if _email_has_display_name "$_SMTP_TO"; then + _err "curl smtp only allows simple email addresses in SMTP_TO." + _err "Change your SMTP_TO='$SMTP_TO' to remove the display name(s)." + return 1 + fi + + # Build curl args in $@ + + case "$_SMTP_SECURE" in + none) + set -- --url "smtp://${_SMTP_HOST}:${_SMTP_PORT}" + ;; + ssl) + set -- --url "smtps://${_SMTP_HOST}:${_SMTP_PORT}" + ;; + tls) + set -- --url "smtp://${_SMTP_HOST}:${_SMTP_PORT}" --ssl-reqd + ;; + *) + # This will only occur if someone adds a new SMTP_SECURE option above + # without updating this code for it. + _err "Unhandled _SMTP_SECURE='$_SMTP_SECURE' in _smtp_send_curl" + _err "Please re-run with --debug and report a bug." + return 1 + ;; + esac + + set -- "$@" \ + --upload-file - \ + --mail-from "$_SMTP_FROM" \ + --max-time "$_SMTP_TIMEOUT" + + # Burst comma-separated $_SMTP_TO into individual --mail-rcpt args. + _to="${_SMTP_TO}," + while [ -n "$_to" ]; do + _rcpt="${_to%%,*}" + _to="${_to#*,}" + set -- "$@" --mail-rcpt "$_rcpt" + done + + _smtp_login="${_SMTP_USERNAME}:${_SMTP_PASSWORD}" + if [ "$_smtp_login" != ":" ]; then + set -- "$@" --user "$_smtp_login" + fi + + if [ "$_SMTP_SHOW_TRANSCRIPT" = "True" ]; then + set -- "$@" --verbose + else + set -- "$@" --silent --show-error + fi + + raw_message="$(_smtp_raw_message)" + + _debug2 "curl command:" "$_SMTP_BIN" "$*" + _debug2 "raw_message:\n$raw_message" + + echo "$raw_message" | "$_SMTP_BIN" "$@" +} + +# Output an RFC-822 / RFC-5322 email message using _SMTP_* variables +_smtp_raw_message() { + echo "From: $_SMTP_FROM" + echo "To: $_SMTP_TO" + echo "Subject: $(_mime_encoded_word "$_SMTP_SUBJECT")" + if _exists date; then + echo "Date: $(date +'%a, %-d %b %Y %H:%M:%S %z')" + fi + echo "Content-Type: text/plain; charset=utf-8" + echo "X-Mailer: acme.sh --notify-hook smtp" + echo + echo "$_SMTP_CONTENT" +} + +# Convert text to RFC-2047 MIME "encoded word" format if it contains non-ASCII chars +# text +_mime_encoded_word() { + _text="$1" + # (regex character ranges like [a-z] can be locale-dependent; enumerate ASCII chars to avoid that) + _ascii='] $`"'"[!#%&'()*+,./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ~^_abcdefghijklmnopqrstuvwxyz{|}~-" + if expr "$_text" : "^.*[^$_ascii]" >/dev/null; then + # At least one non-ASCII char; convert entire thing to encoded word + printf "%s" "=?UTF-8?B?$(printf "%s" "$_text" | _base64)?=" + else + # Just printable ASCII, no conversion needed + printf "%s" "$_text" + fi +} + +# Simple check for display name in an email address (< > or ") +# email +_email_has_display_name() { + _email="$1" + expr "$_email" : '^.*[<>"]' > /dev/null } From f4a2dc1fcc01ea2dd18313d1b7416297d14fbc5b Mon Sep 17 00:00:00 2001 From: medmunds Date: Sun, 14 Feb 2021 20:06:07 -0800 Subject: [PATCH 153/304] More than one blank line is an abomination, apparently I will not try to use whitespace to group code visually --- notify/smtp.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 44a5821f..c9927e3e 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -256,10 +256,9 @@ _mime_encoded_word() { # email _email_has_display_name() { _email="$1" - expr "$_email" : '^.*[<>"]' > /dev/null + expr "$_email" : '^.*[<>"]' >/dev/null } - # Send the message via Python using _SMTP_* variables _smtp_send_python() { _debug "Python version" "$("$_SMTP_BIN" --version 2>&1)" From 4137df2a512f254135d490e9bf9649de2a587076 Mon Sep 17 00:00:00 2001 From: Mike Edmunds Date: Sun, 14 Feb 2021 23:01:21 -0800 Subject: [PATCH 154/304] Fix: Unifi deploy hook support Unifi Cloud Key (#3327) * fix: unifi deploy hook also update Cloud Key nginx certs When running on a Unifi Cloud Key device, also deploy to /etc/ssl/private/cloudkey.{crt,key} and reload nginx. This makes the new cert available for the Cloud Key management app running via nginx on port 443 (as well as the port 8443 Unifi Controller app the deploy hook already supported). Fixes #3326 * Improve settings documentation comments * Improve Cloud Key pre-flight error messaging * Fix typo * Add support for UnifiOS (Cloud Key Gen2) Since UnifiOS does not use the Java keystore (like a Unifi Controller or Cloud Key Gen1 deploy), this also reworks the settings validation and error messaging somewhat. * PR review fixes * Detect unsupported Cloud Key java keystore location * Don't try to restart inactive services (and remove extra spaces from reload command) * Clean up error messages and internal variables * Change to _getdeployconf/_savedeployconf * Switch from cp to cat to preserve file permissions --- deploy/unifi.sh | 220 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 167 insertions(+), 53 deletions(-) diff --git a/deploy/unifi.sh b/deploy/unifi.sh index 184aa62e..a864135e 100644 --- a/deploy/unifi.sh +++ b/deploy/unifi.sh @@ -1,12 +1,43 @@ #!/usr/bin/env sh -#Here is a script to deploy cert to unifi server. +# Here is a script to deploy cert on a Unifi Controller or Cloud Key device. +# It supports: +# - self-hosted Unifi Controller +# - Unifi Cloud Key (Gen1/2/2+) +# - Unifi Cloud Key running UnifiOS (v2.0.0+, Gen2/2+ only) +# Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3359 #returns 0 means success, otherwise error. +# The deploy-hook automatically detects standard Unifi installations +# for each of the supported environments. Most users should not need +# to set any of these variables, but if you are running a self-hosted +# Controller with custom locations, set these as necessary before running +# the deploy hook. (Defaults shown below.) +# +# Settings for Unifi Controller: +# Location of Java keystore or unifi.keystore.jks file: #DEPLOY_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore" +# Keystore password (built into Unifi Controller, not a user-set password): #DEPLOY_UNIFI_KEYPASS="aircontrolenterprise" +# Command to restart Unifi Controller: #DEPLOY_UNIFI_RELOAD="service unifi restart" +# +# Settings for Unifi Cloud Key Gen1 (nginx admin pages): +# Directory where cloudkey.crt and cloudkey.key live: +#DEPLOY_UNIFI_CLOUDKEY_CERTDIR="/etc/ssl/private" +# Command to restart maintenance pages and Controller +# (same setting as above, default is updated when running on Cloud Key Gen1): +#DEPLOY_UNIFI_RELOAD="service nginx restart && service unifi restart" +# +# Settings for UnifiOS (Cloud Key Gen2): +# Directory where unifi-core.crt and unifi-core.key live: +#DEPLOY_UNIFI_CORE_CONFIG="/data/unifi-core/config/" +# Command to restart unifi-core: +#DEPLOY_UNIFI_RELOAD="systemctl restart unifi-core" +# +# At least one of DEPLOY_UNIFI_KEYSTORE, DEPLOY_UNIFI_CLOUDKEY_CERTDIR, +# or DEPLOY_UNIFI_CORE_CONFIG must exist to receive the deployed certs. ######## Public functions ##################### @@ -24,77 +55,160 @@ unifi_deploy() { _debug _cca "$_cca" _debug _cfullchain "$_cfullchain" - if ! _exists keytool; then - _err "keytool not found" - return 1 - fi + _getdeployconf DEPLOY_UNIFI_KEYSTORE + _getdeployconf DEPLOY_UNIFI_KEYPASS + _getdeployconf DEPLOY_UNIFI_CLOUDKEY_CERTDIR + _getdeployconf DEPLOY_UNIFI_CORE_CONFIG + _getdeployconf DEPLOY_UNIFI_RELOAD + + _debug2 DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" + _debug2 DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" + _debug2 DEPLOY_UNIFI_CLOUDKEY_CERTDIR "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" + _debug2 DEPLOY_UNIFI_CORE_CONFIG "$DEPLOY_UNIFI_CORE_CONFIG" + _debug2 DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" + + # Space-separated list of environments detected and installed: + _services_updated="" + + # Default reload commands accumulated as we auto-detect environments: + _reload_cmd="" + + # Unifi Controller environment (self hosted or any Cloud Key) -- + # auto-detect by file /usr/lib/unifi/data/keystore: + _unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-/usr/lib/unifi/data/keystore}" + if [ -f "$_unifi_keystore" ]; then + _info "Installing certificate for Unifi Controller (Java keystore)" + _debug _unifi_keystore "$_unifi_keystore" + if ! _exists keytool; then + _err "keytool not found" + return 1 + fi + if [ ! -w "$_unifi_keystore" ]; then + _err "The file $_unifi_keystore is not writable, please change the permission." + return 1 + fi + + _unifi_keypass="${DEPLOY_UNIFI_KEYPASS:-aircontrolenterprise}" - DEFAULT_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore" - _unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-$DEFAULT_UNIFI_KEYSTORE}" - DEFAULT_UNIFI_KEYPASS="aircontrolenterprise" - _unifi_keypass="${DEPLOY_UNIFI_KEYPASS:-$DEFAULT_UNIFI_KEYPASS}" - DEFAULT_UNIFI_RELOAD="service unifi restart" - _reload="${DEPLOY_UNIFI_RELOAD:-$DEFAULT_UNIFI_RELOAD}" - - _debug _unifi_keystore "$_unifi_keystore" - if [ ! -f "$_unifi_keystore" ]; then - if [ -z "$DEPLOY_UNIFI_KEYSTORE" ]; then - _err "unifi keystore is not found, please define DEPLOY_UNIFI_KEYSTORE" + _debug "Generate import pkcs12" + _import_pkcs12="$(_mktemp)" + _toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root + # shellcheck disable=SC2181 + if [ "$?" != "0" ]; then + _err "Error generating pkcs12. Please re-run with --debug and report a bug." return 1 + fi + + _debug "Import into keystore: $_unifi_keystore" + if keytool -importkeystore \ + -deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \ + -srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \ + -alias unifi -noprompt; then + _debug "Import keystore success!" + rm "$_import_pkcs12" else - _err "It seems that the specified unifi keystore is not valid, please check." + _err "Error importing into Unifi Java keystore." + _err "Please re-run with --debug and report a bug." + rm "$_import_pkcs12" return 1 fi + + if systemctl -q is-active unifi; then + _reload_cmd="${_reload_cmd:+$_reload_cmd && }service unifi restart" + fi + _services_updated="${_services_updated} unifi" + _info "Install Unifi Controller certificate success!" + elif [ "$DEPLOY_UNIFI_KEYSTORE" ]; then + _err "The specified DEPLOY_UNIFI_KEYSTORE='$DEPLOY_UNIFI_KEYSTORE' is not valid, please check." + return 1 fi - if [ ! -w "$_unifi_keystore" ]; then - _err "The file $_unifi_keystore is not writable, please change the permission." + + # Cloud Key environment (non-UnifiOS -- nginx serves admin pages) -- + # auto-detect by file /etc/ssl/private/cloudkey.key: + _cloudkey_certdir="${DEPLOY_UNIFI_CLOUDKEY_CERTDIR:-/etc/ssl/private}" + if [ -f "${_cloudkey_certdir}/cloudkey.key" ]; then + _info "Installing certificate for Cloud Key Gen1 (nginx admin pages)" + _debug _cloudkey_certdir "$_cloudkey_certdir" + if [ ! -w "$_cloudkey_certdir" ]; then + _err "The directory $_cloudkey_certdir is not writable; please check permissions." + return 1 + fi + # Cloud Key expects to load the keystore from /etc/ssl/private/unifi.keystore.jks. + # Normally /usr/lib/unifi/data/keystore is a symlink there (so the keystore was + # updated above), but if not, we don't know how to handle this installation: + if ! cmp -s "$_unifi_keystore" "${_cloudkey_certdir}/unifi.keystore.jks"; then + _err "Unsupported Cloud Key configuration: keystore not found at '${_cloudkey_certdir}/unifi.keystore.jks'" + return 1 + fi + + cat "$_cfullchain" >"${_cloudkey_certdir}/cloudkey.crt" + cat "$_ckey" >"${_cloudkey_certdir}/cloudkey.key" + (cd "$_cloudkey_certdir" && tar -cf cert.tar cloudkey.crt cloudkey.key unifi.keystore.jks) + + if systemctl -q is-active nginx; then + _reload_cmd="${_reload_cmd:+$_reload_cmd && }service nginx restart" + fi + _info "Install Cloud Key Gen1 certificate success!" + _services_updated="${_services_updated} nginx" + elif [ "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" ]; then + _err "The specified DEPLOY_UNIFI_CLOUDKEY_CERTDIR='$DEPLOY_UNIFI_CLOUDKEY_CERTDIR' is not valid, please check." return 1 fi - _info "Generate import pkcs12" - _import_pkcs12="$(_mktemp)" - _toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root - if [ "$?" != "0" ]; then - _err "Oops, error creating import pkcs12, please report bug to us." + # UnifiOS environment -- auto-detect by /data/unifi-core/config/unifi-core.key: + _unifi_core_config="${DEPLOY_UNIFI_CORE_CONFIG:-/data/unifi-core/config}" + if [ -f "${_unifi_core_config}/unifi-core.key" ]; then + _info "Installing certificate for UnifiOS" + _debug _unifi_core_config "$_unifi_core_config" + if [ ! -w "$_unifi_core_config" ]; then + _err "The directory $_unifi_core_config is not writable; please check permissions." + return 1 + fi + + cat "$_cfullchain" >"${_unifi_core_config}/unifi-core.crt" + cat "$_ckey" >"${_unifi_core_config}/unifi-core.key" + + if systemctl -q is-active unifi-core; then + _reload_cmd="${_reload_cmd:+$_reload_cmd && }systemctl restart unifi-core" + fi + _info "Install UnifiOS certificate success!" + _services_updated="${_services_updated} unifi-core" + elif [ "$DEPLOY_UNIFI_CORE_CONFIG" ]; then + _err "The specified DEPLOY_UNIFI_CORE_CONFIG='$DEPLOY_UNIFI_CORE_CONFIG' is not valid, please check." return 1 fi - _info "Modify unifi keystore: $_unifi_keystore" - if keytool -importkeystore \ - -deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \ - -srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \ - -alias unifi -noprompt; then - _info "Import keystore success!" - rm "$_import_pkcs12" - else - _err "Import unifi keystore error, please report bug to us." - rm "$_import_pkcs12" + if [ -z "$_services_updated" ]; then + # None of the Unifi environments were auto-detected, so no deployment has occurred + # (and none of DEPLOY_UNIFI_{KEYSTORE,CLOUDKEY_CERTDIR,CORE_CONFIG} were set). + _err "Unable to detect Unifi environment in standard location." + _err "(This deploy hook must be run on the Unifi device, not a remote machine.)" + _err "For non-standard Unifi installations, set DEPLOY_UNIFI_KEYSTORE," + _err "DEPLOY_UNIFI_CLOUDKEY_CERTDIR, and/or DEPLOY_UNIFI_CORE_CONFIG as appropriate." return 1 fi - _info "Run reload: $_reload" - if eval "$_reload"; then + _reload_cmd="${DEPLOY_UNIFI_RELOAD:-$_reload_cmd}" + if [ -z "$_reload_cmd" ]; then + _err "Certificates were installed for services:${_services_updated}," + _err "but none appear to be active. Please set DEPLOY_UNIFI_RELOAD" + _err "to a command that will restart the necessary services." + return 1 + fi + _info "Reload services (this may take some time): $_reload_cmd" + if eval "$_reload_cmd"; then _info "Reload success!" - if [ "$DEPLOY_UNIFI_KEYSTORE" ]; then - _savedomainconf DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" - else - _cleardomainconf DEPLOY_UNIFI_KEYSTORE - fi - if [ "$DEPLOY_UNIFI_KEYPASS" ]; then - _savedomainconf DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" - else - _cleardomainconf DEPLOY_UNIFI_KEYPASS - fi - if [ "$DEPLOY_UNIFI_RELOAD" ]; then - _savedomainconf DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" - else - _cleardomainconf DEPLOY_UNIFI_RELOAD - fi - return 0 else _err "Reload error" return 1 fi - return 0 + # Successful, so save all (non-default) config: + _savedeployconf DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" + _savedeployconf DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" + _savedeployconf DEPLOY_UNIFI_CLOUDKEY_CERTDIR "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" + _savedeployconf DEPLOY_UNIFI_CORE_CONFIG "$DEPLOY_UNIFI_CORE_CONFIG" + _savedeployconf DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" + + return 0 } From 4ccfa1a79459b176dd127d4f5cb08f0e4fa36dfb Mon Sep 17 00:00:00 2001 From: Easton Man Date: Mon, 15 Feb 2021 15:18:49 +0800 Subject: [PATCH 155/304] feat: add huaweicloud error handling --- dnsapi/dns_huaweicloud.sh | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_huaweicloud.sh b/dnsapi/dns_huaweicloud.sh index 74fec2a9..f7192725 100644 --- a/dnsapi/dns_huaweicloud.sh +++ b/dnsapi/dns_huaweicloud.sh @@ -5,7 +5,7 @@ # HUAWEICLOUD_ProjectID iam_api="https://iam.myhuaweicloud.com" -dns_api="https://dns.ap-southeast-1.myhuaweicloud.com" +dns_api="https://dns.ap-southeast-1.myhuaweicloud.com" # Should work ######## Public functions ##################### @@ -29,16 +29,27 @@ dns_huaweicloud_add() { return 1 fi + unset token # Clear token token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_ProjectID}")" - _debug2 "${token}" + if [ -z "${token}" ]; then # Check token + _err "dns_api(dns_huaweicloud): Error getting token." + return 1 + fi + _debug "Access token is: ${token}" + + unset zoneid zoneid="$(_get_zoneid "${token}" "${fulldomain}")" - _debug "${zoneid}" + if [ -z "${zoneid}" ]; then + _err "dns_api(dns_huaweicloud): Error getting zone id." + return 1 + fi + _debug "Zone ID is: ${zoneid}" _debug "Adding Record" _add_record "${token}" "${fulldomain}" "${txtvalue}" ret="$?" if [ "${ret}" != "0" ]; then - _err "dns_huaweicloud: Error adding record." + _err "dns_api(dns_huaweicloud): Error adding record." return 1 fi @@ -69,12 +80,21 @@ dns_huaweicloud_rm() { return 1 fi + unset token # Clear token token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_ProjectID}")" - _debug2 "${token}" + if [ -z "${token}" ]; then # Check token + _err "dns_api(dns_huaweicloud): Error getting token." + return 1 + fi + _debug "Access token is: ${token}" + + unset zoneid zoneid="$(_get_zoneid "${token}" "${fulldomain}")" - _debug "${zoneid}" - record_id="$(_get_recordset_id "${token}" "${fulldomain}" "${zoneid}")" - _debug "Record Set ID is: ${record_id}" + if [ -z "${zoneid}" ]; then + _err "dns_api(dns_huaweicloud): Error getting zone id." + return 1 + fi + _debug "Zone ID is: ${zoneid}" # Remove all records # Therotically HuaweiCloud does not allow more than one record set From ad8fd9743341a5427b22ee3037578616427506f2 Mon Sep 17 00:00:00 2001 From: Easton Man Date: Mon, 15 Feb 2021 15:19:18 +0800 Subject: [PATCH 156/304] fix: fix freebsd and solaris --- .github/workflows/DNS.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index b9e34ba4..f8e501ed 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -223,7 +223,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/solaris-vm@v0.0.1 + - uses: vmactions/solaris-vm@v0.0.3 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkgutil -y -i socat curl From 307951fabf181523ed95f3f7f454511cea52cd86 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 15 Feb 2021 21:25:27 +0800 Subject: [PATCH 157/304] support openssl 3.0 fix https://github.com/acmesh-official/acme.sh/issues/3399 --- acme.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index c76fabb8..dbf13e95 100755 --- a/acme.sh +++ b/acme.sh @@ -1122,9 +1122,14 @@ _createkey() { fi fi + __traditional="" + if _contains "$(${ACME_OPENSSL_BIN:-openssl} help genrsa 2>&1)" "-traditional"; then + __traditional="-traditional" + fi + if _isEccKey "$length"; then _debug "Using ec name: $eccname" - if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -genkey 2>/dev/null)"; then + if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam $__traditional -name "$eccname" -genkey 2>/dev/null)"; then echo "$_opkey" >"$f" else _err "error ecc key name: $eccname" @@ -1132,7 +1137,7 @@ _createkey() { fi else _debug "Using RSA: $length" - if _opkey="$(${ACME_OPENSSL_BIN:-openssl} genrsa "$length" 2>/dev/null)"; then + if _opkey="$(${ACME_OPENSSL_BIN:-openssl} genrsa $__traditional "$length" 2>/dev/null)"; then echo "$_opkey" >"$f" else _err "error rsa key: $length" From 3086ade5435fa6557ed6e58d9a616d48d7ac757d Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 15 Feb 2021 21:35:59 +0800 Subject: [PATCH 158/304] make the fix for rsa key only --- acme.sh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/acme.sh b/acme.sh index dbf13e95..920e21d4 100755 --- a/acme.sh +++ b/acme.sh @@ -1122,14 +1122,9 @@ _createkey() { fi fi - __traditional="" - if _contains "$(${ACME_OPENSSL_BIN:-openssl} help genrsa 2>&1)" "-traditional"; then - __traditional="-traditional" - fi - if _isEccKey "$length"; then _debug "Using ec name: $eccname" - if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam $__traditional -name "$eccname" -genkey 2>/dev/null)"; then + if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -genkey 2>/dev/null)"; then echo "$_opkey" >"$f" else _err "error ecc key name: $eccname" @@ -1137,6 +1132,10 @@ _createkey() { fi else _debug "Using RSA: $length" + __traditional="" + if _contains "$(${ACME_OPENSSL_BIN:-openssl} help genrsa 2>&1)" "-traditional"; then + __traditional="-traditional" + fi if _opkey="$(${ACME_OPENSSL_BIN:-openssl} genrsa $__traditional "$length" 2>/dev/null)"; then echo "$_opkey" >"$f" else From ff009f4c2fb0523e4de17ff231954442963a2b58 Mon Sep 17 00:00:00 2001 From: medmunds Date: Mon, 15 Feb 2021 12:23:48 -0800 Subject: [PATCH 159/304] Use PROJECT_NAME and VER for X-Mailer header Also add X-Mailer header to Python version --- notify/smtp.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index c9927e3e..bb71a563 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -112,6 +112,7 @@ smtp_send() { _SMTP_USERNAME="$SMTP_USERNAME" _SMTP_PASSWORD="$SMTP_PASSWORD" _SMTP_TIMEOUT="${SMTP_TIMEOUT:-30}" + _SMTP_X_MAILER="${PROJECT_NAME} ${VER} --notify-hook smtp" # Run with --debug 2 (or above) to echo the transcript of the SMTP session. # Careful: this may include SMTP_PASSWORD in plaintext! @@ -232,7 +233,7 @@ _smtp_raw_message() { echo "Date: $(date +'%a, %-d %b %Y %H:%M:%S %z')" fi echo "Content-Type: text/plain; charset=utf-8" - echo "X-Mailer: acme.sh --notify-hook smtp" + echo "X-Mailer: $_SMTP_X_MAILER" echo echo "$_SMTP_CONTENT" } @@ -286,6 +287,7 @@ smtp_secure = """$_SMTP_SECURE""" username = """$_SMTP_USERNAME""" password = """$_SMTP_PASSWORD""" timeout=int("""$_SMTP_TIMEOUT""") # seconds +x_mailer="""$_SMTP_X_MAILER""" from_email="""$_SMTP_FROM""" to_emails="""$_SMTP_TO""" # can be comma-separated @@ -301,6 +303,7 @@ except (AttributeError, TypeError): msg["Subject"] = subject msg["From"] = from_email msg["To"] = to_emails +msg["X-Mailer"] = x_mailer smtp = None try: From f73034cc77716a68fa7bf502cd55f6d972e88f45 Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 16 Feb 2021 09:33:39 -0800 Subject: [PATCH 160/304] Add _clearaccountconf_mutable() --- acme.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/acme.sh b/acme.sh index 920e21d4..5f7a1642 100755 --- a/acme.sh +++ b/acme.sh @@ -2283,6 +2283,13 @@ _clearaccountconf() { _clear_conf "$ACCOUNT_CONF_PATH" "$1" } +#key +_clearaccountconf_mutable() { + _clearaccountconf "SAVED_$1" + #remove later + _clearaccountconf "$1" +} + #_savecaconf key value _savecaconf() { _save_conf "$CA_CONF" "$1" "$2" From 3ed3e3095c1eb32b2508fa1ad22f2e7c7d9a5c24 Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 16 Feb 2021 12:49:27 -0800 Subject: [PATCH 161/304] Rework read/save config to not save default values Add and use _readaccountconf_mutable_default and _saveaccountconf_mutable_default helpers to capture common default value handling. New approach also eliminates need for separate underscore-prefixed version of each conf var. --- notify/smtp.sh | 255 +++++++++++++++++++++++++++++-------------------- 1 file changed, 149 insertions(+), 106 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index bb71a563..85801604 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -17,155 +17,150 @@ # SMTP_TIMEOUT="30" # seconds for SMTP operations to timeout # SMTP_BIN="/path/to/curl_or_python" # default finds first of curl, python3, or python on PATH +SMTP_SECURE_DEFAULT="none" +SMTP_TIMEOUT_DEFAULT="30" + # subject content statuscode smtp_send() { - _SMTP_SUBJECT="$1" - _SMTP_CONTENT="$2" + SMTP_SUBJECT="$1" + SMTP_CONTENT="$2" # UNUSED: _statusCode="$3" # 0: success, 1: error 2($RENEW_SKIP): skipped - # Load config: - SMTP_FROM="${SMTP_FROM:-$(_readaccountconf_mutable SMTP_FROM)}" - SMTP_TO="${SMTP_TO:-$(_readaccountconf_mutable SMTP_TO)}" - SMTP_HOST="${SMTP_HOST:-$(_readaccountconf_mutable SMTP_HOST)}" - SMTP_PORT="${SMTP_PORT:-$(_readaccountconf_mutable SMTP_PORT)}" - SMTP_SECURE="${SMTP_SECURE:-$(_readaccountconf_mutable SMTP_SECURE)}" - SMTP_USERNAME="${SMTP_USERNAME:-$(_readaccountconf_mutable SMTP_USERNAME)}" - SMTP_PASSWORD="${SMTP_PASSWORD:-$(_readaccountconf_mutable SMTP_PASSWORD)}" - SMTP_TIMEOUT="${SMTP_TIMEOUT:-$(_readaccountconf_mutable SMTP_TIMEOUT)}" - SMTP_BIN="${SMTP_BIN:-$(_readaccountconf_mutable SMTP_BIN)}" - - _debug "SMTP_FROM" "$SMTP_FROM" - _debug "SMTP_TO" "$SMTP_TO" - _debug "SMTP_HOST" "$SMTP_HOST" - _debug "SMTP_PORT" "$SMTP_PORT" - _debug "SMTP_SECURE" "$SMTP_SECURE" - _debug "SMTP_USERNAME" "$SMTP_USERNAME" - _secure_debug "SMTP_PASSWORD" "$SMTP_PASSWORD" - _debug "SMTP_TIMEOUT" "$SMTP_TIMEOUT" - _debug "SMTP_BIN" "$SMTP_BIN" - - _debug "_SMTP_SUBJECT" "$_SMTP_SUBJECT" - _debug "_SMTP_CONTENT" "$_SMTP_CONTENT" - - # Validate config and apply defaults: - # _SMTP_* variables are the resolved (with defaults) versions of SMTP_*. - # (The _SMTP_* versions will not be stored in account conf.) - + # Load and validate config: + SMTP_BIN="$(_readaccountconf_mutable_default SMTP_BIN)" if [ -n "$SMTP_BIN" ] && ! _exists "$SMTP_BIN"; then _err "SMTP_BIN '$SMTP_BIN' does not exist." return 1 fi - _SMTP_BIN="$SMTP_BIN" - if [ -z "$_SMTP_BIN" ]; then + if [ -z "$SMTP_BIN" ]; then # Look for a command that can communicate with an SMTP server. # (Please don't add sendmail, ssmtp, mutt, mail, or msmtp here. # Those are already handled by the "mail" notify hook.) for cmd in curl python3 python2.7 python pypy3 pypy; do if _exists "$cmd"; then - _SMTP_BIN="$cmd" + SMTP_BIN="$cmd" break fi done - if [ -z "$_SMTP_BIN" ]; then + if [ -z "$SMTP_BIN" ]; then _err "The smtp notify-hook requires curl or Python, but can't find any." _err 'If you have one of them, define SMTP_BIN="/path/to/curl_or_python".' _err 'Otherwise, see if you can use the "mail" notify-hook instead.' return 1 fi - _debug "_SMTP_BIN" "$_SMTP_BIN" fi + _debug SMTP_BIN "$SMTP_BIN" + _saveaccountconf_mutable_default SMTP_BIN "$SMTP_BIN" + SMTP_FROM="$(_readaccountconf_mutable_default SMTP_FROM)" if [ -z "$SMTP_FROM" ]; then _err "You must define SMTP_FROM as the sender email address." return 1 fi - _SMTP_FROM="$SMTP_FROM" + _debug SMTP_FROM "$SMTP_FROM" + _saveaccountconf_mutable_default SMTP_FROM "$SMTP_FROM" + SMTP_TO="$(_readaccountconf_mutable_default SMTP_TO)" if [ -z "$SMTP_TO" ]; then _err "You must define SMTP_TO as the recipient email address." return 1 fi - _SMTP_TO="$SMTP_TO" + _debug SMTP_TO "$SMTP_TO" + _saveaccountconf_mutable_default SMTP_TO "$SMTP_TO" + SMTP_HOST="$(_readaccountconf_mutable_default SMTP_HOST)" if [ -z "$SMTP_HOST" ]; then _err "You must define SMTP_HOST as the SMTP server hostname." return 1 fi - _SMTP_HOST="$SMTP_HOST" - - _SMTP_SECURE="${SMTP_SECURE:-none}" - case "$_SMTP_SECURE" in - "none") smtp_default_port="25" ;; - "ssl") smtp_default_port="465" ;; - "tls") smtp_default_port="587" ;; + _debug SMTP_HOST "$SMTP_HOST" + _saveaccountconf_mutable_default SMTP_HOST "$SMTP_HOST" + + SMTP_SECURE="$(_readaccountconf_mutable_default SMTP_SECURE "$SMTP_SECURE_DEFAULT")" + case "$SMTP_SECURE" in + "none") smtp_port_default="25" ;; + "ssl") smtp_port_default="465" ;; + "tls") smtp_port_default="587" ;; *) _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." return 1 ;; esac + _debug SMTP_SECURE "$SMTP_SECURE" + _saveaccountconf_mutable_default SMTP_SECURE "$SMTP_SECURE" "$SMTP_SECURE_DEFAULT" - _SMTP_PORT="${SMTP_PORT:-$smtp_default_port}" - if [ -z "$SMTP_PORT" ]; then - _debug "_SMTP_PORT" "$_SMTP_PORT" - fi + SMTP_PORT="$(_readaccountconf_mutable_default SMTP_PORT "$smtp_port_default")" + case "$SMTP_PORT" in + *[!0-9]*) + _err "Invalid SMTP_PORT='$SMTP_PORT'. It must be a port number." + return 1 + ;; + esac + _debug SMTP_PORT "$SMTP_PORT" + _saveaccountconf_mutable_default SMTP_PORT "$SMTP_PORT" "$smtp_port_default" + + SMTP_USERNAME="$(_readaccountconf_mutable_default SMTP_USERNAME)" + _debug SMTP_USERNAME "$SMTP_USERNAME" + _saveaccountconf_mutable_default SMTP_USERNAME "$SMTP_USERNAME" + + SMTP_PASSWORD="$(_readaccountconf_mutable_default SMTP_PASSWORD)" + _secure_debug SMTP_PASSWORD "$SMTP_PASSWORD" + _saveaccountconf_mutable_default SMTP_PASSWORD "$SMTP_PASSWORD" - _SMTP_USERNAME="$SMTP_USERNAME" - _SMTP_PASSWORD="$SMTP_PASSWORD" - _SMTP_TIMEOUT="${SMTP_TIMEOUT:-30}" - _SMTP_X_MAILER="${PROJECT_NAME} ${VER} --notify-hook smtp" + SMTP_TIMEOUT="$(_readaccountconf_mutable_default SMTP_TIMEOUT "$SMTP_TIMEOUT_DEFAULT")" + _debug SMTP_TIMEOUT "$SMTP_TIMEOUT" + _saveaccountconf_mutable_default SMTP_TIMEOUT "$SMTP_TIMEOUT" "$SMTP_TIMEOUT_DEFAULT" + + SMTP_X_MAILER="${PROJECT_NAME} ${VER} --notify-hook smtp" # Run with --debug 2 (or above) to echo the transcript of the SMTP session. # Careful: this may include SMTP_PASSWORD in plaintext! if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then - _SMTP_SHOW_TRANSCRIPT="True" + SMTP_SHOW_TRANSCRIPT="True" else - _SMTP_SHOW_TRANSCRIPT="" + SMTP_SHOW_TRANSCRIPT="" fi + _debug SMTP_SUBJECT "$SMTP_SUBJECT" + _debug SMTP_CONTENT "$SMTP_CONTENT" + # Send the message: - case "$(basename "$_SMTP_BIN")" in + case "$(basename "$SMTP_BIN")" in curl) _smtp_send=_smtp_send_curl ;; py*) _smtp_send=_smtp_send_python ;; *) - _err "Can't figure out how to invoke $_SMTP_BIN." + _err "Can't figure out how to invoke '$SMTP_BIN'." _err "Check your SMTP_BIN setting." return 1 ;; esac if ! smtp_output="$($_smtp_send)"; then - _err "Error sending message with $_SMTP_BIN." + _err "Error sending message with $SMTP_BIN." if [ -n "$smtp_output" ]; then _err "$smtp_output" fi return 1 fi - # Save config only if send was successful: - _saveaccountconf_mutable SMTP_BIN "$SMTP_BIN" - _saveaccountconf_mutable SMTP_FROM "$SMTP_FROM" - _saveaccountconf_mutable SMTP_TO "$SMTP_TO" - _saveaccountconf_mutable SMTP_HOST "$SMTP_HOST" - _saveaccountconf_mutable SMTP_PORT "$SMTP_PORT" - _saveaccountconf_mutable SMTP_SECURE "$SMTP_SECURE" - _saveaccountconf_mutable SMTP_USERNAME "$SMTP_USERNAME" - _saveaccountconf_mutable SMTP_PASSWORD "$SMTP_PASSWORD" - _saveaccountconf_mutable SMTP_TIMEOUT "$SMTP_TIMEOUT" - return 0 } -# Send the message via curl using _SMTP_* variables +## +## curl smtp sending +## + +# Send the message via curl using SMTP_* variables _smtp_send_curl() { # curl passes --mail-from and --mail-rcpt directly to the SMTP protocol without # additional parsing, and SMTP requires addr-spec only (no display names). # In the future, maybe try to parse the addr-spec out for curl args (non-trivial). - if _email_has_display_name "$_SMTP_FROM"; then + if _email_has_display_name "$SMTP_FROM"; then _err "curl smtp only allows a simple email address in SMTP_FROM." _err "Change your SMTP_FROM='$SMTP_FROM' to remove the display name." return 1 fi - if _email_has_display_name "$_SMTP_TO"; then + if _email_has_display_name "$SMTP_TO"; then _err "curl smtp only allows simple email addresses in SMTP_TO." _err "Change your SMTP_TO='$SMTP_TO' to remove the display name(s)." return 1 @@ -173,20 +168,20 @@ _smtp_send_curl() { # Build curl args in $@ - case "$_SMTP_SECURE" in + case "$SMTP_SECURE" in none) - set -- --url "smtp://${_SMTP_HOST}:${_SMTP_PORT}" + set -- --url "smtp://${SMTP_HOST}:${SMTP_PORT}" ;; ssl) - set -- --url "smtps://${_SMTP_HOST}:${_SMTP_PORT}" + set -- --url "smtps://${SMTP_HOST}:${SMTP_PORT}" ;; tls) - set -- --url "smtp://${_SMTP_HOST}:${_SMTP_PORT}" --ssl-reqd + set -- --url "smtp://${SMTP_HOST}:${SMTP_PORT}" --ssl-reqd ;; *) # This will only occur if someone adds a new SMTP_SECURE option above # without updating this code for it. - _err "Unhandled _SMTP_SECURE='$_SMTP_SECURE' in _smtp_send_curl" + _err "Unhandled SMTP_SECURE='$SMTP_SECURE' in _smtp_send_curl" _err "Please re-run with --debug and report a bug." return 1 ;; @@ -194,23 +189,23 @@ _smtp_send_curl() { set -- "$@" \ --upload-file - \ - --mail-from "$_SMTP_FROM" \ - --max-time "$_SMTP_TIMEOUT" + --mail-from "$SMTP_FROM" \ + --max-time "$SMTP_TIMEOUT" - # Burst comma-separated $_SMTP_TO into individual --mail-rcpt args. - _to="${_SMTP_TO}," + # Burst comma-separated $SMTP_TO into individual --mail-rcpt args. + _to="${SMTP_TO}," while [ -n "$_to" ]; do _rcpt="${_to%%,*}" _to="${_to#*,}" set -- "$@" --mail-rcpt "$_rcpt" done - _smtp_login="${_SMTP_USERNAME}:${_SMTP_PASSWORD}" + _smtp_login="${SMTP_USERNAME}:${SMTP_PASSWORD}" if [ "$_smtp_login" != ":" ]; then set -- "$@" --user "$_smtp_login" fi - if [ "$_SMTP_SHOW_TRANSCRIPT" = "True" ]; then + if [ "$SMTP_SHOW_TRANSCRIPT" = "True" ]; then set -- "$@" --verbose else set -- "$@" --silent --show-error @@ -218,24 +213,24 @@ _smtp_send_curl() { raw_message="$(_smtp_raw_message)" - _debug2 "curl command:" "$_SMTP_BIN" "$*" + _debug2 "curl command:" "$SMTP_BIN" "$*" _debug2 "raw_message:\n$raw_message" - echo "$raw_message" | "$_SMTP_BIN" "$@" + echo "$raw_message" | "$SMTP_BIN" "$@" } -# Output an RFC-822 / RFC-5322 email message using _SMTP_* variables +# Output an RFC-822 / RFC-5322 email message using SMTP_* variables _smtp_raw_message() { - echo "From: $_SMTP_FROM" - echo "To: $_SMTP_TO" - echo "Subject: $(_mime_encoded_word "$_SMTP_SUBJECT")" + echo "From: $SMTP_FROM" + echo "To: $SMTP_TO" + echo "Subject: $(_mime_encoded_word "$SMTP_SUBJECT")" if _exists date; then echo "Date: $(date +'%a, %-d %b %Y %H:%M:%S %z')" fi echo "Content-Type: text/plain; charset=utf-8" - echo "X-Mailer: $_SMTP_X_MAILER" + echo "X-Mailer: $SMTP_X_MAILER" echo - echo "$_SMTP_CONTENT" + echo "$SMTP_CONTENT" } # Convert text to RFC-2047 MIME "encoded word" format if it contains non-ASCII chars @@ -260,12 +255,16 @@ _email_has_display_name() { expr "$_email" : '^.*[<>"]' >/dev/null } -# Send the message via Python using _SMTP_* variables +## +## Python smtp sending +## + +# Send the message via Python using SMTP_* variables _smtp_send_python() { - _debug "Python version" "$("$_SMTP_BIN" --version 2>&1)" + _debug "Python version" "$("$SMTP_BIN" --version 2>&1)" # language=Python - "$_SMTP_BIN" < Date: Tue, 16 Feb 2021 13:13:26 -0800 Subject: [PATCH 162/304] Implement _rfc2822_date helper --- notify/smtp.sh | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 85801604..43536cd2 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -224,9 +224,7 @@ _smtp_raw_message() { echo "From: $SMTP_FROM" echo "To: $SMTP_TO" echo "Subject: $(_mime_encoded_word "$SMTP_SUBJECT")" - if _exists date; then - echo "Date: $(date +'%a, %-d %b %Y %H:%M:%S %z')" - fi + echo "Date: $(_rfc2822_date)" echo "Content-Type: text/plain; charset=utf-8" echo "X-Mailer: $SMTP_X_MAILER" echo @@ -248,6 +246,19 @@ _mime_encoded_word() { fi } +# Output current date in RFC-2822 Section 3.3 format as required in email headers +# (e.g., "Mon, 15 Feb 2021 14:22:01 -0800") +_rfc2822_date() { + # Notes: + # - this is deliberately not UTC, because it "SHOULD express local time" per spec + # - the spec requires weekday and month in the C locale (English), not localized + # - this date format specifier has been tested on Linux, Mac, Solaris and FreeBSD + _old_lc_time="$LC_TIME" + LC_TIME=C + date +'%a, %-d %b %Y %H:%M:%S %z' + LC_TIME="$_old_lc_time" +} + # Simple check for display name in an email address (< > or ") # email _email_has_display_name() { From 86818463f16960fbc32a33885f58cce1fb4664e0 Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 16 Feb 2021 14:02:09 -0800 Subject: [PATCH 163/304] Clean email headers and warn on unsupported address format Just in case, make sure CR or NL don't end up in an email header. --- notify/smtp.sh | 55 +++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 43536cd2..42c1487c 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -53,16 +53,28 @@ smtp_send() { _saveaccountconf_mutable_default SMTP_BIN "$SMTP_BIN" SMTP_FROM="$(_readaccountconf_mutable_default SMTP_FROM)" + SMTP_FROM="$(_clean_email_header "$SMTP_FROM")" if [ -z "$SMTP_FROM" ]; then _err "You must define SMTP_FROM as the sender email address." return 1 fi + if _email_has_display_name "$SMTP_FROM"; then + _err "SMTP_FROM must be only a simple email address (sender@example.com)." + _err "Change your SMTP_FROM='$SMTP_FROM' to remove the display name." + return 1 + fi _debug SMTP_FROM "$SMTP_FROM" _saveaccountconf_mutable_default SMTP_FROM "$SMTP_FROM" SMTP_TO="$(_readaccountconf_mutable_default SMTP_TO)" + SMTP_TO="$(_clean_email_header "$SMTP_TO")" if [ -z "$SMTP_TO" ]; then - _err "You must define SMTP_TO as the recipient email address." + _err "You must define SMTP_TO as the recipient email address(es)." + return 1 + fi + if _email_has_display_name "$SMTP_TO"; then + _err "SMTP_TO must be only simple email addresses (to@example.com,to2@example.com)." + _err "Change your SMTP_TO='$SMTP_TO' to remove the display name(s)." return 1 fi _debug SMTP_TO "$SMTP_TO" @@ -111,7 +123,7 @@ smtp_send() { _debug SMTP_TIMEOUT "$SMTP_TIMEOUT" _saveaccountconf_mutable_default SMTP_TIMEOUT "$SMTP_TIMEOUT" "$SMTP_TIMEOUT_DEFAULT" - SMTP_X_MAILER="${PROJECT_NAME} ${VER} --notify-hook smtp" + SMTP_X_MAILER="$(_clean_email_header "$PROJECT_NAME $VER --notify-hook smtp")" # Run with --debug 2 (or above) to echo the transcript of the SMTP session. # Careful: this may include SMTP_PASSWORD in plaintext! @@ -121,6 +133,7 @@ smtp_send() { SMTP_SHOW_TRANSCRIPT="" fi + SMTP_SUBJECT=$(_clean_email_header "$SMTP_SUBJECT") _debug SMTP_SUBJECT "$SMTP_SUBJECT" _debug SMTP_CONTENT "$SMTP_CONTENT" @@ -146,28 +159,26 @@ smtp_send() { return 0 } +# Strip CR and NL from text to prevent MIME header injection +# text +_clean_email_header() { + printf "%s" "$(echo "$1" | tr -d "\r\n")" +} + +# Simple check for display name in an email address (< > or ") +# email +_email_has_display_name() { + _email="$1" + expr "$_email" : '^.*[<>"]' >/dev/null +} + ## ## curl smtp sending ## # Send the message via curl using SMTP_* variables _smtp_send_curl() { - # curl passes --mail-from and --mail-rcpt directly to the SMTP protocol without - # additional parsing, and SMTP requires addr-spec only (no display names). - # In the future, maybe try to parse the addr-spec out for curl args (non-trivial). - if _email_has_display_name "$SMTP_FROM"; then - _err "curl smtp only allows a simple email address in SMTP_FROM." - _err "Change your SMTP_FROM='$SMTP_FROM' to remove the display name." - return 1 - fi - if _email_has_display_name "$SMTP_TO"; then - _err "curl smtp only allows simple email addresses in SMTP_TO." - _err "Change your SMTP_TO='$SMTP_TO' to remove the display name(s)." - return 1 - fi - # Build curl args in $@ - case "$SMTP_SECURE" in none) set -- --url "smtp://${SMTP_HOST}:${SMTP_PORT}" @@ -219,7 +230,8 @@ _smtp_send_curl() { echo "$raw_message" | "$SMTP_BIN" "$@" } -# Output an RFC-822 / RFC-5322 email message using SMTP_* variables +# Output an RFC-822 / RFC-5322 email message using SMTP_* variables. +# (This assumes variables have already been cleaned for use in email headers.) _smtp_raw_message() { echo "From: $SMTP_FROM" echo "To: $SMTP_TO" @@ -259,13 +271,6 @@ _rfc2822_date() { LC_TIME="$_old_lc_time" } -# Simple check for display name in an email address (< > or ") -# email -_email_has_display_name() { - _email="$1" - expr "$_email" : '^.*[<>"]' >/dev/null -} - ## ## Python smtp sending ## From a236b3cfc0c0a72b45e9d20d15442c9022929ffe Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 16 Feb 2021 14:41:21 -0800 Subject: [PATCH 164/304] Clarify _readaccountconf_mutable_default --- notify/smtp.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 42c1487c..fabde79b 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -358,7 +358,7 @@ PYTHON # - if MY_CONF is set _empty_, output $default_value # (lets user `export MY_CONF=` to clear previous saved value # and return to default, without user having to know default) -# - otherwise if _readaccountconf_mutable $name is non-empty, return that +# - otherwise if _readaccountconf_mutable MY_CONF is non-empty, return that # (value of SAVED_MY_CONF from account.conf) # - otherwise output $default_value _readaccountconf_mutable_default() { @@ -366,8 +366,9 @@ _readaccountconf_mutable_default() { _default_value="$2" eval "_value=\"\$$_name\"" - eval "_explicit_empty_value=\"\${${_name}+empty}\"" - if [ -z "${_value}" ] && [ "${_explicit_empty_value:-}" != "empty" ]; then + eval "_name_is_set=\"\${${_name}+true}\"" + # ($_name_is_set is "true" if $$_name is set to anything, including empty) + if [ -z "${_value}" ] && [ "${_name_is_set:-}" != "true" ]; then _value="$(_readaccountconf_mutable "$_name")" fi if [ -z "${_value}" ]; then From 1864109b8292c90abadf310000fa5eae058c5de1 Mon Sep 17 00:00:00 2001 From: medmunds Date: Wed, 17 Feb 2021 09:46:13 -0800 Subject: [PATCH 165/304] Add Date email header in Python implementation --- notify/smtp.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/notify/smtp.sh b/notify/smtp.sh index fabde79b..0c698631 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -287,6 +287,7 @@ try: from email.message import EmailMessage except ImportError: from email.mime.text import MIMEText as EmailMessage # Python 2 + from email.utils import formatdate as rfc2822_date from smtplib import SMTP, SMTP_SSL, SMTPException from socket import error as SocketError except ImportError as err: @@ -318,6 +319,7 @@ except (AttributeError, TypeError): msg["Subject"] = subject msg["From"] = from_email msg["To"] = to_emails +msg["Date"] = rfc2822_date(localtime=True) msg["X-Mailer"] = x_mailer smtp = None From f59cd16bfd58880e85a66264667b1b3d84f1b5e5 Mon Sep 17 00:00:00 2001 From: medmunds Date: Wed, 17 Feb 2021 09:57:44 -0800 Subject: [PATCH 166/304] Use email.policy.default in Python 3 implementation Improves standards compatibility and utf-8 handling in Python 3.3-3.8. (email.policy.default becomes the default in Python 3.9.) --- notify/smtp.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 0c698631..69863206 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -285,8 +285,11 @@ _smtp_send_python() { try: try: from email.message import EmailMessage + from email.policy import default as email_policy_default except ImportError: - from email.mime.text import MIMEText as EmailMessage # Python 2 + # Python 2 (or < 3.3) + from email.mime.text import MIMEText as EmailMessage + email_policy_default = None from email.utils import formatdate as rfc2822_date from smtplib import SMTP, SMTP_SSL, SMTPException from socket import error as SocketError @@ -311,7 +314,7 @@ subject="""$SMTP_SUBJECT""" content="""$SMTP_CONTENT""" try: - msg = EmailMessage() + msg = EmailMessage(policy=email_policy_default) msg.set_content(content) except (AttributeError, TypeError): # Python 2 MIMEText From 0f4aadfc922b43643f88422f90173990f36a73c5 Mon Sep 17 00:00:00 2001 From: medmunds Date: Wed, 17 Feb 2021 10:02:14 -0800 Subject: [PATCH 167/304] Prefer Python to curl when both available --- notify/smtp.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 69863206..71020818 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -15,7 +15,7 @@ # SMTP_USERNAME="" # set if SMTP server requires login # SMTP_PASSWORD="" # set if SMTP server requires login # SMTP_TIMEOUT="30" # seconds for SMTP operations to timeout -# SMTP_BIN="/path/to/curl_or_python" # default finds first of curl, python3, or python on PATH +# SMTP_BIN="/path/to/python_or_curl" # default finds first of python3, python2.7, python, pypy3, pypy, curl on PATH SMTP_SECURE_DEFAULT="none" SMTP_TIMEOUT_DEFAULT="30" @@ -36,7 +36,7 @@ smtp_send() { # Look for a command that can communicate with an SMTP server. # (Please don't add sendmail, ssmtp, mutt, mail, or msmtp here. # Those are already handled by the "mail" notify hook.) - for cmd in curl python3 python2.7 python pypy3 pypy; do + for cmd in python3 python2.7 python pypy3 pypy curl; do if _exists "$cmd"; then SMTP_BIN="$cmd" break From 5822e1e54c55a505ffa96a67ac46b7d34cc0561e Mon Sep 17 00:00:00 2001 From: medmunds Date: Wed, 17 Feb 2021 11:39:16 -0800 Subject: [PATCH 168/304] Change default SMTP_SECURE to "tls" Secure by default. Also try to minimize configuration errors. (Many ESPs/ISPs require STARTTLS, and most support it.) --- notify/smtp.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 71020818..293c665e 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -11,13 +11,13 @@ # SMTP_TO="to@example.com" # required # SMTP_HOST="smtp.example.com" # required # SMTP_PORT="25" # defaults to 25, 465 or 587 depending on SMTP_SECURE -# SMTP_SECURE="none" # one of "none", "ssl" (implicit TLS, TLS Wrapper), "tls" (explicit TLS, STARTTLS) +# SMTP_SECURE="tls" # one of "none", "ssl" (implicit TLS, TLS Wrapper), "tls" (explicit TLS, STARTTLS) # SMTP_USERNAME="" # set if SMTP server requires login # SMTP_PASSWORD="" # set if SMTP server requires login # SMTP_TIMEOUT="30" # seconds for SMTP operations to timeout # SMTP_BIN="/path/to/python_or_curl" # default finds first of python3, python2.7, python, pypy3, pypy, curl on PATH -SMTP_SECURE_DEFAULT="none" +SMTP_SECURE_DEFAULT="tls" SMTP_TIMEOUT_DEFAULT="30" # subject content statuscode From 89ee620f5daba8f7dbe36b4dcf7cfd667164883d Mon Sep 17 00:00:00 2001 From: czeming Date: Sat, 20 Feb 2021 17:16:33 +0800 Subject: [PATCH 169/304] Update dns_dp.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 没有encode中文字符会导致提交失败 --- dnsapi/dns_dp.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_dp.sh b/dnsapi/dns_dp.sh index 033fa5aa..9b8b7a8b 100755 --- a/dnsapi/dns_dp.sh +++ b/dnsapi/dns_dp.sh @@ -89,7 +89,7 @@ add_record() { _info "Adding record" - if ! _rest POST "Record.Create" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=默认"; then + if ! _rest POST "Record.Create" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=%E9%BB%98%E8%AE%A4"; then return 1 fi From 1d3bf4332862d2c3272b66be250f733b074bece7 Mon Sep 17 00:00:00 2001 From: Geert Hendrickx Date: Tue, 23 Feb 2021 10:28:17 +0100 Subject: [PATCH 170/304] No need to include EC parameters explicitly with the private key. (they are embedded) --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 5f7a1642..3b27e7db 100755 --- a/acme.sh +++ b/acme.sh @@ -1124,7 +1124,7 @@ _createkey() { if _isEccKey "$length"; then _debug "Using ec name: $eccname" - if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -genkey 2>/dev/null)"; then + if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -noout -genkey 2>/dev/null)"; then echo "$_opkey" >"$f" else _err "error ecc key name: $eccname" From e8d3984f11f38d01402206ab902b2563557ff1ef Mon Sep 17 00:00:00 2001 From: Kristian Johansson Date: Wed, 24 Feb 2021 08:53:35 +0100 Subject: [PATCH 171/304] Fixes response handling and thereby allow issuing of subdomain certs --- dnsapi/dns_simply.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index d053dcf6..b38d0ed3 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -6,7 +6,7 @@ #SIMPLY_ApiKey="apikey" # #SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]" - +SIMPLY_SUCCESS_CODE='"status": 200' SIMPLY_Api_Default="https://api.simply.com/1" ######## Public functions ##################### @@ -171,7 +171,7 @@ _get_root() { return 1 fi - if _contains "$response" '"code":"NOT_FOUND"'; then + if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then _debug "$h not found" else _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) @@ -196,6 +196,12 @@ _simply_add_record() { return 1 fi + if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then + _err "Call to API not sucessfull, see below message for more details" + _err "$response" + return 1 + fi + return 0 } @@ -211,6 +217,12 @@ _simply_delete_record() { return 1 fi + if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then + _err "Call to API not sucessfull, see below message for more details" + _err "$response" + return 1 + fi + return 0 } From 9838b792ed37ae1ba0ad79f9792899d30a52dceb Mon Sep 17 00:00:00 2001 From: Kristian Johansson Date: Wed, 24 Feb 2021 17:34:28 +0100 Subject: [PATCH 172/304] Adds comment --- dnsapi/dns_simply.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index b38d0ed3..e0e05017 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -6,9 +6,11 @@ #SIMPLY_ApiKey="apikey" # #SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]" -SIMPLY_SUCCESS_CODE='"status": 200' SIMPLY_Api_Default="https://api.simply.com/1" +#This is used for determining success of REST call +SIMPLY_SUCCESS_CODE='"status": 200' + ######## Public functions ##################### #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_simply_add() { From 2c253c9446f8c3dca4293d2717b6acf4c735f821 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 25 Feb 2021 07:45:22 +0800 Subject: [PATCH 173/304] fix https://github.com/acmesh-official/acme.sh/issues/3402 --- acme.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 3b27e7db..e643e327 100755 --- a/acme.sh +++ b/acme.sh @@ -562,8 +562,16 @@ if _exists xargs && [ "$(printf %s '\\x41' | xargs printf)" = 'A' ]; then fi _h2b() { - if _exists xxd && xxd -r -p 2>/dev/null; then - return + if _exists xxd; then + if _contains "$(xxd --help 2>&1)" "assumes -c30"; then + if xxd -r -p -c 9999 2>/dev/null; then + return + fi + else + if xxd -r -p 2>/dev/null; then + return + fi + fi fi hex=$(cat) From a73fdbbb5b2806e71ace29573c839ee224c08275 Mon Sep 17 00:00:00 2001 From: Lukas Brocke Date: Tue, 23 Feb 2021 19:49:58 +0100 Subject: [PATCH 174/304] dnsapi/ionos: Use POST instead of PATCH for adding TXT record The API now supports a POST route for adding records. Therefore checking for already existing records and including them in a PATCH request is no longer necessary. --- dnsapi/dns_ionos.sh | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/dnsapi/dns_ionos.sh b/dnsapi/dns_ionos.sh index e6bd5000..aaf8580f 100755 --- a/dnsapi/dns_ionos.sh +++ b/dnsapi/dns_ionos.sh @@ -24,20 +24,9 @@ dns_ionos_add() { return 1 fi - _new_record="{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}" + _body="[{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}]" - # As no POST route is supported by the API, check for existing records and include them in the PATCH request in order not delete them. - # This is required to support ACME v2 wildcard certificate creation, where two TXT records for the same domain name are created. - - _ionos_get_existing_records "$fulldomain" "$_zone_id" - - if [ "$_existing_records" ]; then - _body="[$_new_record,$_existing_records]" - else - _body="[$_new_record]" - fi - - if _ionos_rest PATCH "$IONOS_ROUTE_ZONES/$_zone_id" "$_body" && [ -z "$response" ]; then + if _ionos_rest POST "$IONOS_ROUTE_ZONES/$_zone_id/records" "$_body" && [ -z "$response" ]; then _info "TXT record has been created successfully." return 0 fi @@ -125,17 +114,6 @@ _get_root() { return 1 } -_ionos_get_existing_records() { - fulldomain=$1 - zone_id=$2 - - if _ionos_rest GET "$IONOS_ROUTE_ZONES/$zone_id?recordName=$fulldomain&recordType=TXT"; then - response="$(echo "$response" | tr -d "\n")" - - _existing_records="$(printf "%s\n" "$response" | _egrep_o "\"records\":\[.*\]" | _head_n 1 | cut -d '[' -f 2 | sed 's/]//')" - fi -} - _ionos_get_record() { fulldomain=$1 zone_id=$2 @@ -168,7 +146,7 @@ _ionos_rest() { export _H2="Accept: application/json" export _H3="Content-Type: application/json" - response="$(_post "$data" "$IONOS_API$route" "" "$method")" + response="$(_post "$data" "$IONOS_API$route" "" "$method" "application/json")" else export _H2="Accept: */*" From 86807162625007d7914a41b92ebb0417dca5eb70 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 1 Mar 2021 18:13:50 +0800 Subject: [PATCH 175/304] fix https://github.com/acmesh-official/acme.sh/issues/3433 --- acme.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/acme.sh b/acme.sh index e643e327..de77aee0 100755 --- a/acme.sh +++ b/acme.sh @@ -2133,6 +2133,12 @@ _send_signed_request() { _sleep $_sleep_retry_sec continue fi + if _contains "$_body" "The Replay Nonce is not recognized"; then + _info "The replay Nonce is not valid, let's get a new one, Sleeping $_sleep_retry_sec seconds." + _CACHED_NONCE="" + _sleep $_sleep_retry_sec + continue + fi fi return 0 done From 72a8e8ff0c0c1e71976067efddfa6ed3edb19df0 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 4 Mar 2021 21:38:51 +0800 Subject: [PATCH 176/304] fix https://github.com/acmesh-official/acme.sh/issues/3019 --- dnsapi/dns_namecheap.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index 7ce39fa9..5e1f4791 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -208,7 +208,7 @@ _namecheap_parse_host() { _hostid=$(echo "$_host" | _egrep_o ' HostId="[^"]*' | cut -d '"' -f 2) _hostname=$(echo "$_host" | _egrep_o ' Name="[^"]*' | cut -d '"' -f 2) _hosttype=$(echo "$_host" | _egrep_o ' Type="[^"]*' | cut -d '"' -f 2) - _hostaddress=$(echo "$_host" | _egrep_o ' Address="[^"]*' | cut -d '"' -f 2) + _hostaddress=$(echo "$_host" | _egrep_o ' Address="[^"]*' | cut -d '"' -f 2 | _xml_decode) _hostmxpref=$(echo "$_host" | _egrep_o ' MXPref="[^"]*' | cut -d '"' -f 2) _hostttl=$(echo "$_host" | _egrep_o ' TTL="[^"]*' | cut -d '"' -f 2) @@ -405,3 +405,11 @@ _namecheap_set_tld_sld() { done } + +_xml_decode() { + sed 's/"/"/g' +} + + + + From 79a8fb677ad6a681c4e9e4cee265192bebcd1486 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 4 Mar 2021 21:50:54 +0800 Subject: [PATCH 177/304] fix format --- dnsapi/dns_namecheap.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index 5e1f4791..e3dc7997 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -410,6 +410,3 @@ _xml_decode() { sed 's/"/"/g' } - - - From 5ab52c8eab0a78ada4d2af33e3e66b145eab7f8d Mon Sep 17 00:00:00 2001 From: anom-human <80478363+anom-human@users.noreply.github.com> Date: Thu, 11 Mar 2021 19:11:02 +0100 Subject: [PATCH 178/304] Update dns_servercow.sh to support wildcard certs Updated dns_servercow.sh to support txt records with multiple entries. This supports wildcard certificates that require txt records with the same name and different contents. --- dnsapi/dns_servercow.sh | 42 +++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_servercow.sh b/dnsapi/dns_servercow.sh index e73d85b0..39f16396 100755 --- a/dnsapi/dns_servercow.sh +++ b/dnsapi/dns_servercow.sh @@ -48,18 +48,44 @@ dns_servercow_add() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - - if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then - if printf -- "%s" "$response" | grep "ok" >/dev/null; then - _info "Added, OK" - return 0 + + # check whether a txt record already exists for the subdomain + if printf -- "%s" "$response" | grep "{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\"" >/dev/null; then + _info "A txt record with the same name already exists." + # trim the string on the left + txtvalue_old=${response#*{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\",\"content\":\"} + # trim the string on the right + txtvalue_old=${txtvalue_old%%\"*} + + _debug txtvalue_old "$txtvalue_old" + + _info "Add the new txtvalue to the existing txt record." + if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":[\"$txtvalue\",\"$txtvalue_old\"],\"ttl\":20}"; then + if printf -- "%s" "$response" | grep "ok" >/dev/null; then + _info "Added additional txtvalue, OK" + return 0 + else + _err "add txt record error." + return 1 + fi + fi + _err "add txt record error." + return 1 else + _info "There is no txt record with the name yet." + if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then + if printf -- "%s" "$response" | grep "ok" >/dev/null; then + _info "Added, OK" + return 0 + else + _err "add txt record error." + return 1 + fi + fi _err "add txt record error." return 1 - fi fi - _err "add txt record error." - + return 1 } From 39e12ec65fc66a337f92d70a802077878fc1ea78 Mon Sep 17 00:00:00 2001 From: anom-human <80478363+anom-human@users.noreply.github.com> Date: Thu, 11 Mar 2021 20:25:49 +0100 Subject: [PATCH 179/304] Update dns_servercow.sh to support wildcard certs Updated dns_servercow.sh to support txt records with multiple entries. This supports wildcard certificates that require txt records with the same name and different contents. --- dnsapi/dns_servercow.sh | 64 ++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/dnsapi/dns_servercow.sh b/dnsapi/dns_servercow.sh index 39f16396..f70a2294 100755 --- a/dnsapi/dns_servercow.sh +++ b/dnsapi/dns_servercow.sh @@ -48,44 +48,44 @@ dns_servercow_add() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - - # check whether a txt record already exists for the subdomain + + # check whether a txt record already exists for the subdomain if printf -- "%s" "$response" | grep "{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\"" >/dev/null; then - _info "A txt record with the same name already exists." - # trim the string on the left - txtvalue_old=${response#*{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\",\"content\":\"} - # trim the string on the right - txtvalue_old=${txtvalue_old%%\"*} - - _debug txtvalue_old "$txtvalue_old" - - _info "Add the new txtvalue to the existing txt record." - if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":[\"$txtvalue\",\"$txtvalue_old\"],\"ttl\":20}"; then - if printf -- "%s" "$response" | grep "ok" >/dev/null; then - _info "Added additional txtvalue, OK" - return 0 - else - _err "add txt record error." + _info "A txt record with the same name already exists." + # trim the string on the left + txtvalue_old=${response#*{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\",\"content\":\"} + # trim the string on the right + txtvalue_old=${txtvalue_old%%\"*} + + _debug txtvalue_old "$txtvalue_old" + + _info "Add the new txtvalue to the existing txt record." + if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":[\"$txtvalue\",\"$txtvalue_old\"],\"ttl\":20}"; then + if printf -- "%s" "$response" | grep "ok" >/dev/null; then + _info "Added additional txtvalue, OK" + return 0 + else + _err "add txt record error." return 1 - fi fi - _err "add txt record error." - return 1 - else - _info "There is no txt record with the name yet." - if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then - if printf -- "%s" "$response" | grep "ok" >/dev/null; then - _info "Added, OK" - return 0 - else - _err "add txt record error." + fi + _err "add txt record error." + return 1 + else + _info "There is no txt record with the name yet." + if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then + if printf -- "%s" "$response" | grep "ok" >/dev/null; then + _info "Added, OK" + return 0 + else + _err "add txt record error." return 1 - fi fi - _err "add txt record error." - return 1 + fi + _err "add txt record error." + return 1 fi - + return 1 } From c9cae6ad02bbfa8325f4eba5a99bbf7a048c55f2 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 13 Mar 2021 20:43:25 +0800 Subject: [PATCH 180/304] fix https://github.com/acmesh-official/acme.sh/issues/3312 --- acme.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index de77aee0..3eebdbc7 100755 --- a/acme.sh +++ b/acme.sh @@ -5289,6 +5289,7 @@ signcsr() { _renew_hook="${10}" _local_addr="${11}" _challenge_alias="${12}" + _preferred_chain="${13}" _csrsubj=$(_readSubjectFromCSR "$_csrfile") if [ "$?" != "0" ]; then @@ -5335,7 +5336,7 @@ signcsr() { _info "Copy csr to: $CSR_PATH" cp "$_csrfile" "$CSR_PATH" - issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_addr" "$_challenge_alias" + issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_addr" "$_challenge_alias" "$_preferred_chain" } @@ -7432,7 +7433,7 @@ _process() { deploy "$_domain" "$_deploy_hook" "$_ecc" ;; signcsr) - signcsr "$_csr" "$_webroot" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" + signcsr "$_csr" "$_webroot" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" "$_preferred_chain" ;; showcsr) showcsr "$_csr" "$_domain" From f33f463b3b5959757d0b43b244d1599cfd61ed35 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 13 Mar 2021 20:46:12 +0800 Subject: [PATCH 181/304] fix format --- dnsapi/dns_namecheap.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index e3dc7997..d15d6b0e 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -409,4 +409,3 @@ _namecheap_set_tld_sld() { _xml_decode() { sed 's/"/"/g' } - From 5529dc99f42d23f0863e8c49a77e2ef290a0afa8 Mon Sep 17 00:00:00 2001 From: Quentin Dreyer Date: Fri, 12 Mar 2021 12:03:36 +0100 Subject: [PATCH 182/304] feat: add dns_porkbun --- dnsapi/dns_porkbun.sh | 171 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 dnsapi/dns_porkbun.sh diff --git a/dnsapi/dns_porkbun.sh b/dnsapi/dns_porkbun.sh new file mode 100644 index 00000000..05ecb781 --- /dev/null +++ b/dnsapi/dns_porkbun.sh @@ -0,0 +1,171 @@ +#!/usr/bin/env sh + +# +#PORKBUN_API_KEY="pk1_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" +#PORKBUN_SECRET_API_KEY="sk1_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + +PORKBUN_Api="https://porkbun.com/api/json/v3" + +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_porkbun_add() { + fulldomain=$1 + txtvalue=$2 + + PORKBUN_API_KEY="${PORKBUN_API_KEY:-$(_readaccountconf_mutable PORKBUN_API_KEY)}" + PORKBUN_SECRET_API_KEY="${PORKBUN_SECRET_API_KEY:-$(_readaccountconf_mutable PORKBUN_SECRET_API_KEY)}" + + if [ -z "$PORKBUN_API_KEY" ] || [ -z "$PORKBUN_SECRET_API_KEY" ]; then + PORKBUN_API_KEY='' + PORKBUN_SECRET_API_KEY='' + _err "You didn't specify a Porkbun api key and secret api key yet." + _err "You can get yours from here https://porkbun.com/account/api." + return 1 + fi + + #save the credentials to the account conf file. + _saveaccountconf_mutable PORKBUN_API_KEY "$PORKBUN_API_KEY" + _saveaccountconf_mutable PORKBUN_SECRET_API_KEY "$PORKBUN_SECRET_API_KEY" + + _debug 'First detect the root zone' + if ! _get_root "$fulldomain"; then + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting txt records" + _porkbun_rest POST "dns/retrieve/$_domain" + + if ! echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null; then + _err "Error $response" + return 1 + fi + + # For wildcard cert, the main root domain and the wildcard domain have the same txt subdomain name, so + # we can not use updating anymore. + # count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2) + # _debug count "$count" + # if [ "$count" = "0" ]; then + _info "Adding record" + if _porkbun_rest POST "dns/create/$_domain" "{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":120}"; then + if _contains "$response" '\"status\":"SUCCESS"'; then + _info "Added, OK" + return 0 + elif _contains "$response" "The record already exists"; then + _info "Already exists, OK" + return 0 + else + _err "Add txt record error. ($response)" + return 1 + fi + fi + _err "Add txt record error." + return 1 + +} + +#fulldomain txtvalue +dns_porkbun_rm() { + fulldomain=$1 + txtvalue=$2 + + PORKBUN_API_KEY="${PORKBUN_API_KEY:-$(_readaccountconf_mutable PORKBUN_API_KEY)}" + PORKBUN_SECRET_API_KEY="${PORKBUN_SECRET_API_KEY:-$(_readaccountconf_mutable PORKBUN_SECRET_API_KEY)}" + + _debug 'First detect the root zone' + if ! _get_root "$fulldomain"; then + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting txt records" + _porkbun_rest POST "dns/retrieve/$_domain" + + if ! echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null; then + _err "Error: $response" + return 1 + fi + + count=$(echo "$response" | _egrep_o "\"count\": *[^,]*" | cut -d : -f 2 | tr -d " ") + _debug count "$count" + if [ "$count" = "0" ]; then + _info "Don't need to remove." + else + record_id=$(echo "$response" | tr '{' '\n' | grep "$txtvalue" | cut -d, -f1 | cut -d: -f2 | tr -d \") + _debug "record_id" "$record_id" + if [ -z "$record_id" ]; then + _err "Can not get record id to remove." + return 1 + fi + if ! _porkbun_rest POST "dns/delete/$_domain/$record_id"; then + _err "Delete record error." + return 1 + fi + echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null + fi + +} + +#################### Private functions below ################################## +#_acme-challenge.www.domain.com +#returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +_get_root() { + domain=$1 + i=1 + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug h "$h" + if [ -z "$h" ]; then + return 1 + fi + + if _porkbun_rest POST "dns/retrieve/$h"; then + if _contains "$response" "\"status\":\"SUCCESS\""; then + _sub_domain="$(echo "$fulldomain" | sed "s/\\.$_domain\$//")" + _domain=$h + return 0 + else + _debug "Go to next level of $_domain" + fi + else + _debug "Go to next level of $_domain" + fi + i=$(_math "$i" + 1) + done + + return 1 +} + +_porkbun_rest() { + m=$1 + ep="$2" + data="$3" + _debug "$ep" + + api_key_trimmed=$(echo "$PORKBUN_API_KEY" | tr -d '"') + secret_api_key_trimmed=$(echo "$PORKBUN_SECRET_API_KEY" | tr -d '"') + + test -z "$data" && data="{" || data="$(echo $data | cut -d'}' -f1)," + data="$data\"apikey\":\"$api_key_trimmed\",\"secretapikey\":\"$secret_api_key_trimmed\"}" + + export _H1="Content-Type: application/json" + + if [ "$m" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$PORKBUN_Api/$ep" "" "$m")" + else + response="$(_get "$PORKBUN_Api/$ep")" + fi + + if [ "$?" != "0" ]; then + _err "error $ep" + return 1 + fi + _debug2 response "$response" + return 0 +} From 0b5fd6718ed5bd1379ca5bed0a3f9eb762006f53 Mon Sep 17 00:00:00 2001 From: qkdreyer Date: Sat, 13 Mar 2021 14:53:43 +0100 Subject: [PATCH 183/304] fix: prevent rate limit --- dnsapi/dns_porkbun.sh | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/dnsapi/dns_porkbun.sh b/dnsapi/dns_porkbun.sh index 05ecb781..18da6b2f 100644 --- a/dnsapi/dns_porkbun.sh +++ b/dnsapi/dns_porkbun.sh @@ -35,14 +35,6 @@ dns_porkbun_add() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - _debug "Getting txt records" - _porkbun_rest POST "dns/retrieve/$_domain" - - if ! echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null; then - _err "Error $response" - return 1 - fi - # For wildcard cert, the main root domain and the wildcard domain have the same txt subdomain name, so # we can not use updating anymore. # count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2) @@ -81,14 +73,6 @@ dns_porkbun_rm() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - _debug "Getting txt records" - _porkbun_rest POST "dns/retrieve/$_domain" - - if ! echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null; then - _err "Error: $response" - return 1 - fi - count=$(echo "$response" | _egrep_o "\"count\": *[^,]*" | cut -d : -f 2 | tr -d " ") _debug count "$count" if [ "$count" = "0" ]; then @@ -162,6 +146,8 @@ _porkbun_rest() { response="$(_get "$PORKBUN_Api/$ep")" fi + _sleep 3 # prevent rate limit + if [ "$?" != "0" ]; then _err "error $ep" return 1 From 333d5ad72f479d1765e46ba38abdf017d96185d2 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Sun, 21 Mar 2021 16:25:04 +0100 Subject: [PATCH 184/304] String update Hopefully the last one --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 3b5a8847..e824c9c0 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -32,7 +32,7 @@ dns_websupport_add() { WS_ApiKey="" WS_ApiSecret="" _err "You did not specify the API Key and/or API Secret" - _err "You can get the API credentials from here https://admin.websupport.sk/en/auth/apiKey" + _err "You can get the API login credentials from https://admin.websupport.sk/en/auth/apiKey" return 1 fi From 212be3d7bd98f9f95f6b8f2fcab887fafe20df33 Mon Sep 17 00:00:00 2001 From: emueller Date: Mon, 22 Mar 2021 15:12:27 +0100 Subject: [PATCH 185/304] fix _exists error message when MAIL_BIN env variable is not set --- notify/mail.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/notify/mail.sh b/notify/mail.sh index d33fd0d2..10e93f9a 100644 --- a/notify/mail.sh +++ b/notify/mail.sh @@ -78,8 +78,13 @@ mail_send() { _mail_bin() { _MAIL_BIN="" + _MAIL_BINS="sendmail ssmtp mutt mail msmtp" - for b in "$MAIL_BIN" sendmail ssmtp mutt mail msmtp; do + if [ -n "$MAIL_BIN" ]; then + _MAIL_BINS="$MAIL_BIN $_MAIL_BINS" + fi + + for b in $_MAIL_BINS; do if _exists "$b"; then _MAIL_BIN="$b" break From 1996d52578bf99e4e2f287936d4ce6aab6abe793 Mon Sep 17 00:00:00 2001 From: emueller Date: Mon, 22 Mar 2021 15:32:02 +0100 Subject: [PATCH 186/304] fixed formating --- notify/mail.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notify/mail.sh b/notify/mail.sh index 10e93f9a..2be93cd8 100644 --- a/notify/mail.sh +++ b/notify/mail.sh @@ -78,7 +78,7 @@ mail_send() { _mail_bin() { _MAIL_BIN="" - _MAIL_BINS="sendmail ssmtp mutt mail msmtp" + _MAIL_BINS="sendmail ssmtp mutt mail msmtp" if [ -n "$MAIL_BIN" ]; then _MAIL_BINS="$MAIL_BIN $_MAIL_BINS" From 1b2e3e07ef2981bb44f83a7ffcf85abdd320fc0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eike-Christian=20M=C3=BCller?= Date: Thu, 29 Apr 2021 12:53:13 +0200 Subject: [PATCH 187/304] more simple mail.sh fix Reverted the original patch and changed it to the obvious simple solution provided by @Neilpang. --- notify/mail.sh | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/notify/mail.sh b/notify/mail.sh index 2be93cd8..2cbddb63 100644 --- a/notify/mail.sh +++ b/notify/mail.sh @@ -78,13 +78,8 @@ mail_send() { _mail_bin() { _MAIL_BIN="" - _MAIL_BINS="sendmail ssmtp mutt mail msmtp" - if [ -n "$MAIL_BIN" ]; then - _MAIL_BINS="$MAIL_BIN $_MAIL_BINS" - fi - - for b in $_MAIL_BINS; do + for b in $MAIL_BIN sendmail ssmtp mutt mail msmtp; do if _exists "$b"; then _MAIL_BIN="$b" break From d8a41a3a2df591f8994f0ab56078f4da0d31dfe1 Mon Sep 17 00:00:00 2001 From: Jeff Goeke-Smith Date: Thu, 29 Apr 2021 16:46:32 -0400 Subject: [PATCH 188/304] arguments passed to printf are more generic On systems that /bin/sh is served by shells other than bash, or shells that don't implement the same syntax as the bash printf builtin, printf -- fails to produce the output necessary for standalone operation. The test case for this was SmartOS, which uses ksh93 as its /bin/sh. This change uses the more generic method of passing a format parameter of a single string, and then the argument to replace it with. --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 3eebdbc7..0fb138d9 100755 --- a/acme.sh +++ b/acme.sh @@ -2357,7 +2357,7 @@ _startserver() { echo 'HTTP/1.0 200 OK'; \ echo 'Content-Length\: $_content_len'; \ echo ''; \ -printf -- '$content';" & +printf '%s' '$content';" & serverproc="$!" } From 9952d92b5fa768fe8a42bfe114f6793dea372db9 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 1 May 2021 22:32:44 +0800 Subject: [PATCH 189/304] fix compatibility issue --- acme.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index 0fb138d9..2712a904 100755 --- a/acme.sh +++ b/acme.sh @@ -2038,7 +2038,7 @@ _send_signed_request() { if _post "" "$nonceurl" "" "HEAD" "$__request_conent_type" >/dev/null; then _headers="$(cat "$HTTP_HEADER")" _debug2 _headers "$_headers" - _CACHED_NONCE="$(echo "$_headers" | grep -i "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)" + _CACHED_NONCE="$(echo "$_headers" | grep -i "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2 | cut -d , -f 1)" fi fi if [ -z "$_CACHED_NONCE" ]; then @@ -2118,7 +2118,7 @@ _send_signed_request() { fi _debug2 response "$response" - _CACHED_NONCE="$(echo "$responseHeaders" | grep -i "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)" + _CACHED_NONCE="$(echo "$responseHeaders" | grep -i "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2 | cut -d , -f 1)" if ! _startswith "$code" "2"; then _body="$response" @@ -4722,7 +4722,7 @@ $_authorizations_map" _debug2 response "$response" status=$(echo "$response" | _egrep_o '"status":"[^"]*' | cut -d : -f 2 | tr -d '"') - if [ "$status" = "valid" ]; then + if _contains "$status" "valid"; then _info "$(__green Success)" _stopserver "$serverproc" serverproc="" From dc1526130fee187337ab8b929732d9c89f5cbb12 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 3 May 2021 15:52:56 +0800 Subject: [PATCH 190/304] fix https://github.com/acmesh-official/acme.sh/issues/3421 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 2712a904..993fd758 100755 --- a/acme.sh +++ b/acme.sh @@ -2266,7 +2266,7 @@ _getdeployconf() { return 0 # do nothing fi _saved=$(_readdomainconf "SAVED_$_rac_key") - eval "export $_rac_key=\"$_saved\"" + eval "export $_rac_key=\"\$_saved\"" } #_saveaccountconf key value base64encode From 12558414d4fd7c7cbe88f2b16bada5a7fef1cf92 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sun, 2 May 2021 13:37:59 -0600 Subject: [PATCH 191/304] FIX: Synology sets "default" on wrong certificate For some DSM installs, it appears that setting the "default" flag to the string "false" actually sets it to true. This causes Synology to set the last updated certificate to be the default certificate. Using an empty string appears to still be accepted as a false-y value for DSMs where this isn't happening and corrects the behavior in the cases that it was. Credit to @Run-King for identifying the fix and @buxm for reporting. --- deploy/synology_dsm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 35d33209..25d43efb 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -121,7 +121,7 @@ synology_dsm_deploy() { # we've verified this certificate description is a thing, so save it _savedeployconf SYNO_Certificate "$SYNO_Certificate" - default=false + default="" if echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\([^{]*\).*/\1/p" | grep -- 'is_default":true' >/dev/null; then default=true fi From cd06f8478fb116a5fbf9486e9c03e2a05361b38b Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 3 May 2021 16:35:42 +0800 Subject: [PATCH 192/304] fix https://github.com/acmesh-official/acme.sh/issues/3487 suppor Ali doh and dnspod doh. --- acme.sh | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/acme.sh b/acme.sh index 993fd758..051c57b7 100755 --- a/acme.sh +++ b/acme.sh @@ -102,6 +102,8 @@ DEBUG_LEVEL_NONE=0 DOH_CLOUDFLARE=1 DOH_GOOGLE=2 +DOH_ALI=3 +DOH_DP=4 HIDDEN_VALUE="[hidden](please add '--output-insecure' to see this value)" @@ -3918,7 +3920,15 @@ _ns_purge_cf() { #checks if cf server is available _ns_is_available_cf() { - if _get "https://cloudflare-dns.com" >/dev/null 2>&1; then + if _get "https://cloudflare-dns.com" "" 1 >/dev/null 2>&1; then + return 0 + else + return 1 + fi +} + +_ns_is_available_google() { + if _get "https://dns.google" "" 1 >/dev/null 2>&1; then return 0 else return 1 @@ -3933,6 +3943,38 @@ _ns_lookup_google() { _ns_lookup_impl "$_cf_ep" "$_cf_ld" "$_cf_ld_type" } +_ns_is_available_ali() { + if _get "https://dns.alidns.com" "" 1 >/dev/null 2>&1; then + return 0 + else + return 1 + fi +} + +#domain, type +_ns_lookup_ali() { + _cf_ld="$1" + _cf_ld_type="$2" + _cf_ep="https://dns.alidns.com/resolve" + _ns_lookup_impl "$_cf_ep" "$_cf_ld" "$_cf_ld_type" +} + +_ns_is_available_dp() { + if _get "https://dns.alidns.com" "" 1 >/dev/null 2>&1; then + return 0 + else + return 1 + fi +} + +#dnspod +_ns_lookup_dp() { + _cf_ld="$1" + _cf_ld_type="$2" + _cf_ep="https://doh.pub/dns-query" + _ns_lookup_impl "$_cf_ep" "$_cf_ld" "$_cf_ld_type" +} + #domain, type _ns_lookup() { if [ -z "$DOH_USE" ]; then @@ -3940,16 +3982,28 @@ _ns_lookup() { if _ns_is_available_cf; then _debug "Use cloudflare doh server" export DOH_USE=$DOH_CLOUDFLARE - else + elif _ns_is_available_google; then _debug "Use google doh server" export DOH_USE=$DOH_GOOGLE + elif _ns_is_available_ali; then + _debug "Use aliyun doh server" + export DOH_USE=$DOH_ALI + else _ns_is_available_dp; + _debug "Use dns pod doh server" + export DOH_USE=$DOH_DP fi fi if [ "$DOH_USE" = "$DOH_CLOUDFLARE" ] || [ -z "$DOH_USE" ]; then _ns_lookup_cf "$@" - else + elif [ "$DOH_USE" = "$DOH_GOOGLE" ]; then _ns_lookup_google "$@" + elif [ "$DOH_USE" = "$DOH_ALI" ]; then + _ns_lookup_ali "$@" + elif [ "$DOH_USE" = "$DOH_DP" ]; then + _ns_lookup_dp "$@" + else + _err "Unknown doh provider: DOH_USE=$DOH_USE" fi } @@ -3974,7 +4028,7 @@ __purge_txt() { if [ "$DOH_USE" = "$DOH_CLOUDFLARE" ] || [ -z "$DOH_USE" ]; then _ns_purge_cf "$_p_txtdomain" "TXT" else - _debug "no purge api for google dns api, just sleep 5 secs" + _debug "no purge api for this doh api, just sleep 5 secs" _sleep 5 fi From 4bd0872322c0f3987c117fdce9b24378d16b4076 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 3 May 2021 16:42:09 +0800 Subject: [PATCH 193/304] minor --- acme.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 051c57b7..933a4d17 100755 --- a/acme.sh +++ b/acme.sh @@ -3988,9 +3988,11 @@ _ns_lookup() { elif _ns_is_available_ali; then _debug "Use aliyun doh server" export DOH_USE=$DOH_ALI - else _ns_is_available_dp; + elif _ns_is_available_dp; _debug "Use dns pod doh server" export DOH_USE=$DOH_DP + else + _err "No doh" fi fi From 5a9ff8228757726d0c7f50225710b3d855325e53 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 3 May 2021 17:11:02 +0800 Subject: [PATCH 194/304] fix nginx relative path issue: https://github.com/acmesh-official/acme.sh/issues/1743 https://github.com/acmesh-official/acme.sh/issues/1914 --- acme.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/acme.sh b/acme.sh index 933a4d17..cf092659 100755 --- a/acme.sh +++ b/acme.sh @@ -3098,6 +3098,11 @@ _checkConf() { _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 + _relpath="$(dirname "$_c_file")" + _debug "_relpath" "$_relpath" + included="$_relpath/included" + fi if _checkConf "$1" "$included"; then return 0 fi From 514e3de871a622cc53392a10e8c0eb4f02f0c392 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 3 May 2021 17:14:54 +0800 Subject: [PATCH 195/304] minor --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index cf092659..de6dc7a3 100755 --- a/acme.sh +++ b/acme.sh @@ -3993,7 +3993,7 @@ _ns_lookup() { elif _ns_is_available_ali; then _debug "Use aliyun doh server" export DOH_USE=$DOH_ALI - elif _ns_is_available_dp; + elif _ns_is_available_dp; then _debug "Use dns pod doh server" export DOH_USE=$DOH_DP else From 2824db27580265f07db544d77ec92decb490c7cf Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 4 May 2021 13:32:59 +0800 Subject: [PATCH 196/304] start 2.9.0 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index de6dc7a3..e4909e4d 100755 --- a/acme.sh +++ b/acme.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -VER=2.8.9 +VER=2.9.0 PROJECT_NAME="acme.sh" From 65c0db2158f2be7321eb20fa5f9060826410e045 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 7 May 2021 21:49:47 +0800 Subject: [PATCH 197/304] fix https://github.com/acmesh-official/acme.sh/issues/3504 --- acme.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index e4909e4d..e4b707e9 100755 --- a/acme.sh +++ b/acme.sh @@ -3580,6 +3580,7 @@ _regAccount() { _err "Can not get EAB credentials from ZeroSSL." return 1 fi + _debug2 "$_eabresp" _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" @@ -4783,7 +4784,7 @@ $_authorizations_map" _debug2 response "$response" status=$(echo "$response" | _egrep_o '"status":"[^"]*' | cut -d : -f 2 | tr -d '"') - if _contains "$status" "valid"; then + if _contains "$status" '"valid"'; then _info "$(__green Success)" _stopserver "$serverproc" serverproc="" From 929d7bbd1dce67701a72c7b581ca980dbc8933a2 Mon Sep 17 00:00:00 2001 From: tyahin Date: Sun, 10 Jan 2021 12:39:12 +0300 Subject: [PATCH 198/304] deploy gcore_cdn fix auth --- deploy/gcore_cdn.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/gcore_cdn.sh b/deploy/gcore_cdn.sh index a2a35f7b..738f8561 100644 --- a/deploy/gcore_cdn.sh +++ b/deploy/gcore_cdn.sh @@ -56,9 +56,9 @@ gcore_cdn_deploy() { _request="{\"username\":\"$Le_Deploy_gcore_cdn_username\",\"password\":\"$Le_Deploy_gcore_cdn_password\"}" _debug _request "$_request" export _H1="Content-Type:application/json" - _response=$(_post "$_request" "https://api.gcdn.co/auth/signin") + _response=$(_post "$_request" "https://api.gcdn.co/auth/jwt/login") _debug _response "$_response" - _regex=".*\"token\":\"\([-._0-9A-Za-z]*\)\".*$" + _regex=".*\"access\":\"\([-._0-9A-Za-z]*\)\".*$" _debug _regex "$_regex" _token=$(echo "$_response" | sed -n "s/$_regex/\1/p") _debug _token "$_token" From 5838ee221bb69af120ba9e59459441cc1ea6b9bf Mon Sep 17 00:00:00 2001 From: tyahin Date: Sun, 10 Jan 2021 12:39:20 +0300 Subject: [PATCH 199/304] deploy gcore_cdn fix api --- deploy/gcore_cdn.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/deploy/gcore_cdn.sh b/deploy/gcore_cdn.sh index 738f8561..929a4d53 100644 --- a/deploy/gcore_cdn.sh +++ b/deploy/gcore_cdn.sh @@ -72,12 +72,15 @@ gcore_cdn_deploy() { export _H2="Authorization:Token $_token" _response=$(_get "https://api.gcdn.co/resources") _debug _response "$_response" - _regex=".*(\"id\".*?\"cname\":\"$_cdomain\".*?})" + _regex="\"primary_resource\":null}," + _debug _regex "$_regex" + _response=$(echo "$_response" | sed 's/$_regex/$_regex\n/g') + _debug _response "$_response" _regex="^.*\"cname\":\"$_cdomain\".*$" _debug _regex "$_regex" - _resource=$(echo "$_response" | sed 's/},{/},\n{/g' | _egrep_o "$_regex") + _resource=$(echo "$_response" | _egrep_o "$_regex") _debug _resource "$_resource" - _regex=".*\"id\":\([0-9]*\).*\"rules\".*$" + _regex=".*\"id\":\([0-9]*\).*$" _debug _regex "$_regex" _resourceId=$(echo "$_resource" | sed -n "s/$_regex/\1/p") _debug _resourceId "$_resourceId" From 0dc619ecdcc98fa62c53c33deb8e2c8e50364816 Mon Sep 17 00:00:00 2001 From: tyahin Date: Sun, 10 Jan 2021 12:44:56 +0300 Subject: [PATCH 200/304] deploy gcore_cdn fix syntax --- deploy/gcore_cdn.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/gcore_cdn.sh b/deploy/gcore_cdn.sh index 929a4d53..f573a3aa 100644 --- a/deploy/gcore_cdn.sh +++ b/deploy/gcore_cdn.sh @@ -74,7 +74,7 @@ gcore_cdn_deploy() { _debug _response "$_response" _regex="\"primary_resource\":null}," _debug _regex "$_regex" - _response=$(echo "$_response" | sed 's/$_regex/$_regex\n/g') + _response=$(echo "$_response" | sed "s/$_regex/$_regex\n/g") _debug _response "$_response" _regex="^.*\"cname\":\"$_cdomain\".*$" _debug _regex "$_regex" From f6d190d15e5d0d60b69543fd02d37bd4973680bf Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 7 May 2021 22:02:40 +0800 Subject: [PATCH 201/304] fix https://github.com/acmesh-official/acme.sh/issues/3504 check invalid status first. --- acme.sh | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/acme.sh b/acme.sh index e4b707e9..c2a0dbc2 100755 --- a/acme.sh +++ b/acme.sh @@ -4784,15 +4784,8 @@ $_authorizations_map" _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 + if _contains "$status" "invalid"; then error="$(echo "$response" | _egrep_o '"error":\{[^\}]*')" _debug2 error "$error" errordetail="$(echo "$error" | _egrep_o '"detail": *"[^"]*' | cut -d '"' -f 4)" @@ -4814,6 +4807,14 @@ $_authorizations_map" 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" elif [ "$status" = "processing" ]; then From 484c3293c9c8c6f690ff7972493f9e5f6be1eaa3 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 8 May 2021 21:09:56 +0800 Subject: [PATCH 202/304] minor --- dnsapi/dns_porkbun.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_porkbun.sh b/dnsapi/dns_porkbun.sh index 18da6b2f..90caec4a 100644 --- a/dnsapi/dns_porkbun.sh +++ b/dnsapi/dns_porkbun.sh @@ -78,7 +78,7 @@ dns_porkbun_rm() { if [ "$count" = "0" ]; then _info "Don't need to remove." else - record_id=$(echo "$response" | tr '{' '\n' | grep "$txtvalue" | cut -d, -f1 | cut -d: -f2 | tr -d \") + record_id=$(echo "$response" | tr '{' '\n' | grep -- "$txtvalue" | cut -d, -f1 | cut -d: -f2 | tr -d \") _debug "record_id" "$record_id" if [ -z "$record_id" ]; then _err "Can not get record id to remove." From bbe338db748420fa8d8d648dda5d21614cd2ee0f Mon Sep 17 00:00:00 2001 From: Will Browning <20662079+willbrowningme@users.noreply.github.com> Date: Thu, 6 May 2021 16:51:43 +0100 Subject: [PATCH 203/304] Remove DEDYN_NAME variable from dns_desec.sh --- dnsapi/dns_desec.sh | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/dnsapi/dns_desec.sh b/dnsapi/dns_desec.sh index f64660a8..495a6780 100644 --- a/dnsapi/dns_desec.sh +++ b/dnsapi/dns_desec.sh @@ -20,21 +20,17 @@ dns_desec_add() { _debug txtvalue "$txtvalue" DEDYN_TOKEN="${DEDYN_TOKEN:-$(_readaccountconf_mutable DEDYN_TOKEN)}" - DEDYN_NAME="${DEDYN_NAME:-$(_readaccountconf_mutable DEDYN_NAME)}" - if [ -z "$DEDYN_TOKEN" ] || [ -z "$DEDYN_NAME" ]; then + if [ -z "$DEDYN_TOKEN" ]; then DEDYN_TOKEN="" - DEDYN_NAME="" - _err "You did not specify DEDYN_TOKEN and DEDYN_NAME yet." + _err "You did not specify DEDYN_TOKEN yet." _err "Please create your key and try again." _err "e.g." _err "export DEDYN_TOKEN=d41d8cd98f00b204e9800998ecf8427e" - _err "export DEDYN_NAME=foobar.dedyn.io" return 1 fi - #save the api token and name to the account conf file. + #save the api token to the account conf file. _saveaccountconf_mutable DEDYN_TOKEN "$DEDYN_TOKEN" - _saveaccountconf_mutable DEDYN_NAME "$DEDYN_NAME" _debug "First detect the root zone" if ! _get_root "$fulldomain" "$REST_API/"; then @@ -47,7 +43,7 @@ dns_desec_add() { # Get existing TXT record _debug "Getting txt records" txtvalues="\"\\\"$txtvalue\\\"\"" - _desec_rest GET "$REST_API/$DEDYN_NAME/rrsets/$_sub_domain/TXT/" + _desec_rest GET "$REST_API/$_domain/rrsets/$_sub_domain/TXT/" if [ "$_code" = "200" ]; then oldtxtvalues="$(echo "$response" | _egrep_o "\"records\":\\[\"\\S*\"\\]" | cut -d : -f 2 | tr -d "[]\\\\\"" | sed "s/,/ /g")" @@ -63,7 +59,7 @@ dns_desec_add() { _info "Adding record" body="[{\"subname\":\"$_sub_domain\", \"type\":\"TXT\", \"records\":[$txtvalues], \"ttl\":3600}]" - if _desec_rest PUT "$REST_API/$DEDYN_NAME/rrsets/" "$body"; then + if _desec_rest PUT "$REST_API/$_domain/rrsets/" "$body"; then if _contains "$response" "$txtvalue"; then _info "Added, OK" return 0 @@ -87,16 +83,13 @@ dns_desec_rm() { _debug txtvalue "$txtvalue" DEDYN_TOKEN="${DEDYN_TOKEN:-$(_readaccountconf_mutable DEDYN_TOKEN)}" - DEDYN_NAME="${DEDYN_NAME:-$(_readaccountconf_mutable DEDYN_NAME)}" - if [ -z "$DEDYN_TOKEN" ] || [ -z "$DEDYN_NAME" ]; then + if [ -z "$DEDYN_TOKEN" ]; then DEDYN_TOKEN="" - DEDYN_NAME="" - _err "You did not specify DEDYN_TOKEN and DEDYN_NAME yet." + _err "You did not specify DEDYN_TOKEN yet." _err "Please create your key and try again." _err "e.g." _err "export DEDYN_TOKEN=d41d8cd98f00b204e9800998ecf8427e" - _err "export DEDYN_NAME=foobar.dedyn.io" return 1 fi @@ -112,7 +105,7 @@ dns_desec_rm() { # Get existing TXT record _debug "Getting txt records" txtvalues="" - _desec_rest GET "$REST_API/$DEDYN_NAME/rrsets/$_sub_domain/TXT/" + _desec_rest GET "$REST_API/$_domain/rrsets/$_sub_domain/TXT/" if [ "$_code" = "200" ]; then oldtxtvalues="$(echo "$response" | _egrep_o "\"records\":\\[\"\\S*\"\\]" | cut -d : -f 2 | tr -d "[]\\\\\"" | sed "s/,/ /g")" @@ -131,7 +124,7 @@ dns_desec_rm() { _info "Deleting record" body="[{\"subname\":\"$_sub_domain\", \"type\":\"TXT\", \"records\":[$txtvalues], \"ttl\":3600}]" - _desec_rest PUT "$REST_API/$DEDYN_NAME/rrsets/" "$body" + _desec_rest PUT "$REST_API/$_domain/rrsets/" "$body" if [ "$_code" = "200" ]; then _info "Deleted, OK" return 0 From 2d5597c53492887a5635fd5318bbc8fb9d8db761 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Wed, 19 May 2021 13:21:34 -0600 Subject: [PATCH 204/304] Better fix for Synology DSM setting wrong default As noted by @buxm, previous fix didn't work for all versions of DSM 6. The better fix appears to be simply not outputting the "as_default" parameter unless we are doing something with the default certificate. --- deploy/synology_dsm.sh | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 25d43efb..d7e8ace8 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -121,12 +121,6 @@ synology_dsm_deploy() { # we've verified this certificate description is a thing, so save it _savedeployconf SYNO_Certificate "$SYNO_Certificate" - default="" - if echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\([^{]*\).*/\1/p" | grep -- 'is_default":true' >/dev/null; then - default=true - fi - _debug2 default "$default" - _info "Generate form POST request" nl="\0015\0012" delim="--------------------------$(_utc_date | tr -d -- '-: ')" @@ -135,7 +129,12 @@ synology_dsm_deploy() { content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"inter_cert\"; filename=\"$(basename "$_cca")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cca")\0012" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"id\"${nl}${nl}$id" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"desc\"${nl}${nl}${SYNO_Certificate}" - content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"as_default\"${nl}${nl}${default}" + if echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\([^{]*\).*/\1/p" | grep -- 'is_default":true' >/dev/null; then + _debug2 default "this is the default certificate" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"as_default\"${nl}${nl}true" + else + _debug2 default "this is NOT the default certificate" + fi content="$content${nl}--$delim--${nl}" content="$(printf "%b_" "$content")" content="${content%_}" # protect trailing \n From 67917940d8d16adcd499caf282276b80213ddece Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 22 May 2021 23:45:50 +0800 Subject: [PATCH 205/304] remove ACME v1 support --- acme.sh | 746 +++++++++++++++++++++----------------------------------- 1 file changed, 282 insertions(+), 464 deletions(-) diff --git a/acme.sh b/acme.sh index c2a0dbc2..0f117bf8 100755 --- a/acme.sh +++ b/acme.sh @@ -20,9 +20,6 @@ _SUB_FOLDER_DEPLOY="deploy" _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_V2="https://acme-v02.api.letsencrypt.org/directory" CA_LETSENCRYPT_V2_TEST="https://acme-staging-v02.api.letsencrypt.org/directory" @@ -2072,17 +2069,15 @@ _send_signed_request() { _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)" @@ -2549,61 +2544,25 @@ _initAPI() { 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" @@ -2613,7 +2572,6 @@ _initAPI() { _debug "ACME_REVOKE_CERT" "$ACME_REVOKE_CERT" _debug "ACME_AGREEMENT" "$ACME_AGREEMENT" _debug "ACME_NEW_NONCE" "$ACME_NEW_NONCE" - _debug "ACME_VERSION" "$ACME_VERSION" fi } @@ -3565,69 +3523,62 @@ _regAccount() { 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 + + 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" - _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" + _err "Can not get EAB credentials from ZeroSSL." + return 1 fi + _debug2 "$_eabresp" + _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" 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 | _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" @@ -3712,20 +3663,13 @@ updateaccount() { _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 @@ -3770,11 +3714,8 @@ deactivateaccount() { 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 ' ,') @@ -3879,11 +3820,9 @@ __trigger_validation() { _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 @@ -4299,74 +4238,72 @@ issue() { 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="" @@ -4397,33 +4334,25 @@ $_authorizations_map" 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 @@ -4464,11 +4393,9 @@ $_authorizations_map" _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 @@ -4766,11 +4693,9 @@ $_authorizations_map" _debug "sleep 2 secs to verify" sleep 2 _debug "checking" - if [ "$ACME_VERSION" = "2" ]; then - _send_signed_request "$uri" - else - response="$(_get "$uri")" - fi + + _send_signed_request "$uri" + if [ "$?" != "0" ]; then _err "$d:Verify error:$response" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" @@ -4835,150 +4760,128 @@ $_authorizations_map" _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 - _savedomainconf "Le_LinkOrder" "$Le_LinkOrder" + _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 - _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" + _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 - #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" @@ -5007,53 +4910,6 @@ $_authorizations_map" 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 ")" @@ -5167,15 +5023,6 @@ renew() { . "$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" - fi - if [ "$Le_API" ]; then export ACME_DIRECTORY="$Le_API" #reload ca configs @@ -5390,9 +5237,6 @@ signcsr() { return 1 fi - if [ -z "$ACME_VERSION" ] && _contains "$_csrsubj,$_csrdomainlist" "*."; then - export ACME_VERSION=2 - fi _initpath "$_csrsubj" "$_csrkeylength" mkdir -p "$DOMAIN_PATH" @@ -5853,11 +5697,8 @@ revoke() { _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 @@ -5928,50 +5769,35 @@ _deactivate() { _d_type="$2" _initpath - 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 - - 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 - - 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 + response="$(echo "$response" | _normalizeJson)" + _debug2 response "$response" + _URL_NAME="url" + entries="$(echo "$response" | tr '][' '==' | _egrep_o "challenges\": *=[^=]*=" | tr '}{' '\n' | grep "\"status\": *\"valid\"")" if [ -z "$entries" ]; then _info "No valid entries found." @@ -6025,11 +5851,7 @@ _deactivate() { _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." @@ -7035,10 +6857,6 @@ _process() { return 1 fi - if _startswith "$_dvalue" "*."; then - _debug "Wildcard domain" - export ACME_VERSION=2 - fi if [ -z "$_domain" ]; then _domain="$_dvalue" else From dfdca2f94f9177db22cbe24ce47853dbcfb13431 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 22 May 2021 23:48:39 +0800 Subject: [PATCH 206/304] fix format --- acme.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/acme.sh b/acme.sh index 0f117bf8..7774ea41 100755 --- a/acme.sh +++ b/acme.sh @@ -4760,7 +4760,6 @@ $_authorizations_map" _info "Verify finished, start to sign." der="$(_getfile "${CSR_PATH}" "${BEGIN_CSR}" "${END_CSR}" | tr -d "\r\n" | _url_replace)" - _info "Lets finalize the order." _info "Le_OrderFinalize" "$Le_OrderFinalize" if ! _send_signed_request "${Le_OrderFinalize}" "{\"csr\": \"$der\"}"; then From 2cd7fc40b6f35dd2be49f3a2a57bbd319c99fc0a Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 23 May 2021 23:12:46 +0800 Subject: [PATCH 207/304] use cloudflare tunnel to test --- .github/workflows/LetsEncrypt.yml | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index ba9a5317..715f9db1 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -109,11 +109,20 @@ jobs: TEST_LOCAL: 1 steps: - uses: actions/checkout@v2 + - uses: vmactions/cf-tunnel@v0.0.1 + id: tunnel + with: + protocol: http + port: 8080 + - name: Set envs + run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/freebsd-vm@v0.1.4 with: - envs: 'NGROK_TOKEN TEST_LOCAL' + envs: 'NGROK_TOKEN TEST_LOCAL TestingDomain' + nat: | + "8080": "80" prepare: pkg install -y socat curl usesh: true run: | @@ -127,13 +136,13 @@ jobs: TEST_LOCAL: 1 steps: - uses: actions/checkout@v2 - - uses: vmactions/ngrok-tunnel@v0.0.1 - id: ngrok + - uses: vmactions/cf-tunnel@v0.0.1 + id: tunnel with: protocol: http port: 8080 - name: Set envs - run: echo "TestingDomain=${{steps.ngrok.outputs.server}}" >> $GITHUB_ENV + run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/solaris-vm@v0.0.3 From 4687e4d8fce30c216205b86a6db03749ee78d1c0 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 23 May 2021 23:16:04 +0800 Subject: [PATCH 208/304] remove ngrok token --- .github/workflows/LetsEncrypt.yml | 33 ++----------------------------- 1 file changed, 2 insertions(+), 31 deletions(-) diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 715f9db1..fd79125f 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -15,30 +15,9 @@ on: jobs: - CheckToken: - runs-on: ubuntu-latest - outputs: - hasToken: ${{ steps.step_one.outputs.hasToken }} - env: - NGROK_TOKEN : ${{ secrets.NGROK_TOKEN }} - steps: - - name: Set the value - id: step_one - run: | - if [ "$NGROK_TOKEN" ] ; then - echo "::set-output name=hasToken::true" - else - echo "::set-output name=hasToken::false" - fi - - name: Check the value - run: echo ${{ steps.step_one.outputs.hasToken }} - Ubuntu: runs-on: ubuntu-latest - needs: CheckToken - if: "contains(needs.CheckToken.outputs.hasToken, 'true')" env: - NGROK_TOKEN : ${{ secrets.NGROK_TOKEN }} TEST_LOCAL: 1 steps: - uses: actions/checkout@v2 @@ -51,9 +30,7 @@ jobs: MacOS: runs-on: macos-latest - needs: Ubuntu env: - NGROK_TOKEN : ${{ secrets.NGROK_TOKEN }} TEST_LOCAL: 1 steps: - uses: actions/checkout@v2 @@ -66,11 +43,9 @@ jobs: Windows: runs-on: windows-latest - needs: MacOS env: - NGROK_TOKEN : ${{ secrets.NGROK_TOKEN }} TEST_LOCAL: 1 - #The 80 port is used by Windows server, we have to use a custom port, ngrok will also use this port. + #The 80 port is used by Windows server, we have to use a custom port, tunnel will also use this port. Le_HTTPPort: 8888 steps: - name: Set git to use LF @@ -103,9 +78,7 @@ jobs: FreeBSD: runs-on: macos-latest - needs: Windows env: - NGROK_TOKEN : ${{ secrets.NGROK_TOKEN }} TEST_LOCAL: 1 steps: - uses: actions/checkout@v2 @@ -120,7 +93,7 @@ jobs: run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/freebsd-vm@v0.1.4 with: - envs: 'NGROK_TOKEN TEST_LOCAL TestingDomain' + envs: 'TEST_LOCAL TestingDomain' nat: | "8080": "80" prepare: pkg install -y socat curl @@ -130,9 +103,7 @@ jobs: Solaris: runs-on: macos-latest - needs: FreeBSD env: - NGROK_TOKEN : ${{ secrets.NGROK_TOKEN }} TEST_LOCAL: 1 steps: - uses: actions/checkout@v2 From ac73e78554bae78623fc527f76f1d0cacece9bc7 Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 25 May 2021 21:57:15 +0800 Subject: [PATCH 209/304] add debug info --- dnsapi/dns_ionos.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_ionos.sh b/dnsapi/dns_ionos.sh index aaf8580f..c2c431bb 100755 --- a/dnsapi/dns_ionos.sh +++ b/dnsapi/dns_ionos.sh @@ -149,14 +149,15 @@ _ionos_rest() { response="$(_post "$data" "$IONOS_API$route" "" "$method" "application/json")" else export _H2="Accept: */*" - + export _H3= response="$(_get "$IONOS_API$route")" fi if [ "$?" != "0" ]; then - _err "Error $route" + _err "Error $route: $response" return 1 fi + _debug2 "response" "$response" return 0 } From 1dff1c3cc7f13bcbb08e3748e000d4cd22f43192 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Wed, 26 May 2021 15:07:23 -0600 Subject: [PATCH 210/304] Make certificate descriptions sed safe This escapes special characters used in POSIX sed to prevent mismatches. e.g. `SYNO_Certficiate=*.example.com` would not match a description of "*.example.com" and would look to match any number of double quotes (the last character in the sed regex prior to certificate description), followed by any single character, followed by "example", followed by any character, followed by "com". After this change, it will properly match `*.example.com` and not `""zexamplefcom`. Additionally we now store the certificate description as base64 encoded to prevent issues with single quotes. Tested on DSM 7.0-41222 (VDSM) and DSM 6.2.4-25556 (DS1515+). --- deploy/synology_dsm.sh | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index d7e8ace8..649a48da 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -66,6 +66,11 @@ synology_dsm_deploy() { _getdeployconf SYNO_Certificate _debug SYNO_Certificate "${SYNO_Certificate:-}" + if printf "%s" "$SYNO_Certificate" | grep '\\'; then + _err "Do not use a backslash (\) in your certificate description" + return 1 + fi + _base_url="$SYNO_Scheme://$SYNO_Hostname:$SYNO_Port" _debug _base_url "$_base_url" @@ -110,7 +115,9 @@ synology_dsm_deploy() { _info "Getting certificates in Synology DSM" response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1&_sid=$sid" "$_base_url/webapi/entry.cgi") _debug3 response "$response" - id=$(echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\"id\":\"\([^\"]*\).*/\1/p") + escaped_certificate="$(printf "%s" "$SYNO_Certificate" | sed 's/\([].*^$[]\)/\\\1/g;s/"/\\\\"/g')" + _debug escaped_certificate "$escaped_certificate" + id=$(echo "$response" | sed -n "s/.*\"desc\":\"$escaped_certificate\",\"id\":\"\([^\"]*\).*/\1/p") _debug2 id "$id" if [ -z "$id" ] && [ -z "${SYNO_Create:-}" ]; then @@ -119,7 +126,7 @@ synology_dsm_deploy() { fi # we've verified this certificate description is a thing, so save it - _savedeployconf SYNO_Certificate "$SYNO_Certificate" + _savedeployconf SYNO_Certificate "$SYNO_Certificate" "base64" _info "Generate form POST request" nl="\0015\0012" @@ -129,7 +136,7 @@ synology_dsm_deploy() { content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"inter_cert\"; filename=\"$(basename "$_cca")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cca")\0012" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"id\"${nl}${nl}$id" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"desc\"${nl}${nl}${SYNO_Certificate}" - if echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\([^{]*\).*/\1/p" | grep -- 'is_default":true' >/dev/null; then + if echo "$response" | sed -n "s/.*\"desc\":\"$escaped_certificate\",\([^{]*\).*/\1/p" | grep -- 'is_default":true' >/dev/null; then _debug2 default "this is the default certificate" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"as_default\"${nl}${nl}true" else From 4cc4f5e907dd7a6d54de405a3c24861fcb394ee5 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Wed, 26 May 2021 15:24:50 -0600 Subject: [PATCH 211/304] shellcheck cleanup shellcheck sees '\\' as trying to escape the trailing quote (see koalaman/shellcheck#1548 ). --- deploy/synology_dsm.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 649a48da..5a70c74e 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -66,6 +66,7 @@ synology_dsm_deploy() { _getdeployconf SYNO_Certificate _debug SYNO_Certificate "${SYNO_Certificate:-}" + # shellcheck disable=SC1003 # We are not trying to escape a single quote if printf "%s" "$SYNO_Certificate" | grep '\\'; then _err "Do not use a backslash (\) in your certificate description" return 1 From 95036e346e93d05a6f536f16041efecdf4af278e Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 29 May 2021 15:17:11 +0800 Subject: [PATCH 212/304] upgrade cf-tunnel --- .github/workflows/LetsEncrypt.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index fd79125f..bdc9072e 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -82,7 +82,7 @@ jobs: TEST_LOCAL: 1 steps: - uses: actions/checkout@v2 - - uses: vmactions/cf-tunnel@v0.0.1 + - uses: vmactions/cf-tunnel@v0.0.2 id: tunnel with: protocol: http @@ -107,7 +107,7 @@ jobs: TEST_LOCAL: 1 steps: - uses: actions/checkout@v2 - - uses: vmactions/cf-tunnel@v0.0.1 + - uses: vmactions/cf-tunnel@v0.0.2 id: tunnel with: protocol: http From f0b9532f07a358bd922674e560223457fb0d8713 Mon Sep 17 00:00:00 2001 From: Christophe B Billheimer Date: Mon, 31 May 2021 15:12:11 -0400 Subject: [PATCH 213/304] change "$url" -> $url so the value of $url gets passed by reference, and the string "$url" does not erroneously get passed as a variable into _post() --- dnsapi/dns_1984hosting.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_1984hosting.sh b/dnsapi/dns_1984hosting.sh index d720c1c5..d7e558a1 100755 --- a/dnsapi/dns_1984hosting.sh +++ b/dnsapi/dns_1984hosting.sh @@ -145,7 +145,7 @@ _1984hosting_login() { password=$(printf '%s' "$One984HOSTING_Password" | _url_encode) url="https://management.1984hosting.com/accounts/checkuserauth/" - response="$(_post "username=$username&password=$password&otpkey=" "$url")" + response="$(_post "username=$username&password=$password&otpkey=" $url)" response="$(echo "$response" | _normalizeJson)" _debug2 response "$response" From bcd2dab4a397150fe966a889a77f40340d184eef Mon Sep 17 00:00:00 2001 From: neil Date: Tue, 1 Jun 2021 21:23:00 +0800 Subject: [PATCH 214/304] check initAPI error --- acme.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 7774ea41..9dece202 100755 --- a/acme.sh +++ b/acme.sh @@ -4134,7 +4134,9 @@ issue() { _debug "Using ACME_DIRECTORY: $ACME_DIRECTORY" - _initAPI + if ! _initAPI; then + return 1 + fi if [ -f "$DOMAIN_CONF" ]; then Le_NextRenewTime=$(_readdomainconf Le_NextRenewTime) From 3512b15badcc458596a6f50385634c12c24bf3fa Mon Sep 17 00:00:00 2001 From: neil Date: Tue, 1 Jun 2021 21:24:37 +0800 Subject: [PATCH 215/304] add error message --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 9dece202..dcb1710c 100755 --- a/acme.sh +++ b/acme.sh @@ -2538,7 +2538,7 @@ _initAPI() { response=$(_get "$_api_server") if [ "$?" != "0" ]; then _debug2 "response" "$response" - _err "Can not init api." + _err "Can not init api for: $_api_server." return 1 fi response=$(echo "$response" | _json_decode) From c3099e7ac783c50eafec84dbd2651daf7dc9a389 Mon Sep 17 00:00:00 2001 From: Roman Zabaluev Date: Sun, 30 May 2021 18:17:39 +0300 Subject: [PATCH 216/304] Fix porkbun issues See gh-3450 --- dnsapi/dns_porkbun.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_porkbun.sh b/dnsapi/dns_porkbun.sh index 90caec4a..ad4455b6 100644 --- a/dnsapi/dns_porkbun.sh +++ b/dnsapi/dns_porkbun.sh @@ -110,8 +110,8 @@ _get_root() { if _porkbun_rest POST "dns/retrieve/$h"; then if _contains "$response" "\"status\":\"SUCCESS\""; then - _sub_domain="$(echo "$fulldomain" | sed "s/\\.$_domain\$//")" _domain=$h + _sub_domain="$(echo "$fulldomain" | sed "s/\\.$_domain\$//")" return 0 else _debug "Go to next level of $_domain" From 3315c71947467a2aec55e90f6cdd64a516613069 Mon Sep 17 00:00:00 2001 From: neil Date: Tue, 1 Jun 2021 22:15:41 +0800 Subject: [PATCH 217/304] add debug info --- dnsapi/dns_1984hosting.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_1984hosting.sh b/dnsapi/dns_1984hosting.sh index d7e558a1..fee59127 100755 --- a/dnsapi/dns_1984hosting.sh +++ b/dnsapi/dns_1984hosting.sh @@ -194,7 +194,7 @@ _check_cookie() { # _domain=domain.com _get_root() { domain="$1" - i=2 + i=1 p=1 while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) @@ -220,6 +220,7 @@ _get_root() { _authget() { export _H1="Cookie: $One984HOSTING_COOKIE" _response=$(_get "$1") + _debug2 _response "$_response" } # truncate huge HTML response From 3580cdc87f42b906f9a3ee378e97b9b31035626b Mon Sep 17 00:00:00 2001 From: neil Date: Tue, 1 Jun 2021 22:21:17 +0800 Subject: [PATCH 218/304] fix bug --- dnsapi/dns_1984hosting.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_1984hosting.sh b/dnsapi/dns_1984hosting.sh index fee59127..f371f2c1 100755 --- a/dnsapi/dns_1984hosting.sh +++ b/dnsapi/dns_1984hosting.sh @@ -177,7 +177,6 @@ _check_cookie() { fi _authget "https://management.1984hosting.com/accounts/loginstatus/" - response="$(echo "$_response" | _normalizeJson)" if _contains "$response" '"ok": true'; then _debug "Cached cookie still valid" return 0 @@ -205,7 +204,7 @@ _get_root() { fi _authget "https://management.1984hosting.com/domains/soacheck/?zone=$h&nameserver=ns0.1984.is." - if _contains "$_response" "serial"; then + if _contains "$_response" "serial" && ! _contains "$_response" 'null}'; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain="$h" return 0 @@ -219,7 +218,7 @@ _get_root() { # add extra headers to request _authget() { export _H1="Cookie: $One984HOSTING_COOKIE" - _response=$(_get "$1") + _response=$(_get "$1" | _normalizeJson) _debug2 _response "$_response" } From d419112ff8d2ae92a756c8730131a3645f55a72b Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 2 Jun 2021 23:06:12 +0800 Subject: [PATCH 219/304] start 3.0.0 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index dcb1710c..c1cb4ea0 100755 --- a/acme.sh +++ b/acme.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -VER=2.9.0 +VER=3.0.0 PROJECT_NAME="acme.sh" From f24601bef79fad443ba7828af11e8a1dc52c4a95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Parunakian?= Date: Wed, 2 Jun 2021 16:06:08 +0200 Subject: [PATCH 220/304] Fix typo --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index c1cb4ea0..9a3e1642 100755 --- a/acme.sh +++ b/acme.sh @@ -3056,7 +3056,7 @@ _checkConf() { _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" From dd805d6850a3dc19fba7706a643aac258b9e3fdc Mon Sep 17 00:00:00 2001 From: Christophe B Billheimer Date: Sat, 5 Jun 2021 22:38:45 -0400 Subject: [PATCH 221/304] fix dns_1984hosting_add() so checks for HTML responses are actually find HTML responses --- dnsapi/dns_1984hosting.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_1984hosting.sh b/dnsapi/dns_1984hosting.sh index f371f2c1..6708f890 100755 --- a/dnsapi/dns_1984hosting.sh +++ b/dnsapi/dns_1984hosting.sh @@ -59,7 +59,7 @@ dns_1984hosting_add() { if _contains "$response" '"haserrors": true'; then _err "1984Hosting failed to add TXT record for $_sub_domain bad RC from _post" return 1 - elif _contains "$response" ""; then + elif _contains "$response" "html>"; then _err "1984Hosting failed to add TXT record for $_sub_domain. Check $HTTP_HEADER file" return 1 elif _contains "$response" '"auth": false'; then From 0ce63c79fcc8fed65b8861d351500f6c0a46a4fd Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 6 Jun 2021 22:53:39 +0800 Subject: [PATCH 222/304] fix bug --- dnsapi/dns_vultr.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_vultr.sh b/dnsapi/dns_vultr.sh index c7b52e84..84857966 100644 --- a/dnsapi/dns_vultr.sh +++ b/dnsapi/dns_vultr.sh @@ -33,7 +33,7 @@ dns_vultr_add() { _debug 'Getting txt records' _vultr_rest GET "dns/records?domain=$_domain" - if printf "%s\n" "$response" | grep "\"type\":\"TXT\",\"name\":\"$fulldomain\"" >/dev/null; then + if printf "%s\n" "$response" | grep -- "\"type\":\"TXT\",\"name\":\"$fulldomain\"" >/dev/null; then _err 'Error' return 1 fi @@ -73,12 +73,12 @@ dns_vultr_rm() { _debug 'Getting txt records' _vultr_rest GET "dns/records?domain=$_domain" - if printf "%s\n" "$response" | grep "\"type\":\"TXT\",\"name\":\"$fulldomain\"" >/dev/null; then + if printf "%s\n" "$response" | grep -- "\"type\":\"TXT\",\"name\":\"$fulldomain\"" >/dev/null; then _err 'Error' return 1 fi - _record_id="$(echo "$response" | tr '{}' '\n' | grep '"TXT"' | grep "$txtvalue" | tr ',' '\n' | grep -i 'RECORDID' | cut -d : -f 2)" + _record_id="$(echo "$response" | tr '{}' '\n' | grep '"TXT"' | grep -- "$txtvalue" | tr ',' '\n' | grep -i 'RECORDID' | cut -d : -f 2)" _debug _record_id "$_record_id" if [ "$_record_id" ]; then _info "Successfully retrieved the record id for ACME challenge." From d18ffdb675a45e3af277e4b082569ed3241fc04c Mon Sep 17 00:00:00 2001 From: Marcus Grando Date: Thu, 10 Jun 2021 11:45:53 -0300 Subject: [PATCH 223/304] Added Azion DNS API --- dnsapi/dns_azion.sh | 258 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 dnsapi/dns_azion.sh diff --git a/dnsapi/dns_azion.sh b/dnsapi/dns_azion.sh new file mode 100644 index 00000000..2c5e8fda --- /dev/null +++ b/dnsapi/dns_azion.sh @@ -0,0 +1,258 @@ +#!/usr/bin/env sh + +# +#AZION_Username="" +#AZION_Password="" +#AZION_Token="" +#AZION_ZoneID="" +# + +AZION_Api="https://api.azionapi.net" + +######## Public functions ######## + +# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +# Used to add txt record +dns_azion_add() { + fulldomain=$1 + txtvalue=$2 + + AZION_Username="${AZION_Username:-$(_readaccountconf_mutable AZION_Username)}" + AZION_Password="${AZION_Password:-$(_readaccountconf_mutable AZION_Password)}" + AZION_Token="${AZION_Token:-$(_readaccountconf_mutable AZION_Token)}" + AZION_ZoneID="${AZION_ZoneID:-$(_readaccountconf_mutable AZION_ZoneID)}" + + if ! _contains "$AZION_Username" "@"; then + _err "It seems that the AZION_Username is not a valid email address. Revalidate your environments." + return 1 + fi + + if [ -z "$AZION_Token" ]; then + if [ -z "$AZION_Username" ] || [ -z "$AZION_Password" ]; then + _err "You didn't specified a AZION_Username/AZION_Password to generate Azion token." + return 1 + fi + _get_token + AZION_Token="${AZION_Token:-$(_readaccountconf_mutable AZION_Token)}" + fi + + _saveaccountconf_mutable AZION_Username "$AZION_Username" + _saveaccountconf_mutable AZION_Password "$AZION_Password" + _saveaccountconf_mutable AZION_Token "$AZION_Token" + _saveaccountconf_mutable AZION_ZoneID "$AZION_ZoneID" + + _debug "Detect the root zone" + if ! _get_root "$fulldomain"; then + _err "Domain not found" + return 1 + fi + + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + _debug _domain_id "$_domain_id" + + _info "Add or update record" + _get_record "$_sub_domain" + if [ "$record_id" ]; then + _payload="{\"record_type\": \"TXT\", \"entry\": \"$_sub_domain\", \"answers_list\": [$answers_list, \"$txtvalue\"], \"ttl\": 20}" + if _azion_rest PUT "intelligent_dns/$_domain_id/records/$record_id" "$_payload"; then + if _contains "$response" "$txtvalue"; then + _info "Record updated." + return 0 + fi + fi + else + _payload="{\"record_type\": \"TXT\", \"entry\": \"$_sub_domain\", \"answers_list\": [\"$txtvalue\"], \"ttl\": 20}" + if _azion_rest POST "intelligent_dns/$_domain_id/records" "$_payload"; then + if _contains "$response" "$txtvalue"; then + _info "Record added." + return 0 + fi + fi + fi + _err "Failed to add or update record." + return 1 +} + +# Usage: fulldomain txtvalue +# Used to remove the txt record after validation +dns_azion_rm() { + fulldomain=$1 + txtvalue=$2 + + AZION_Username="${AZION_Username:-$(_readaccountconf_mutable AZION_Username)}" + AZION_Password="${AZION_Password:-$(_readaccountconf_mutable AZION_Password)}" + AZION_Token="${AZION_Token:-$(_readaccountconf_mutable AZION_Token)}" + AZION_ZoneID="${AZION_ZoneID:-$(_readaccountconf_mutable AZION_ZoneID)}" + + if ! _contains "$AZION_Username" "@"; then + _err "It seems that the AZION_Username is not a valid email address. Revalidate your environments." + return 1 + fi + + if [ -z "$AZION_Token" ]; then + if [ -z "$AZION_Username" ] || [ -z "$AZION_Password" ]; then + _err "You didn't specified a AZION_Username/AZION_Password to generate Azion token." + return 1 + fi + _get_token + AZION_Token="${AZION_Token:-$(_readaccountconf_mutable AZION_Token)}" + fi + + _debug "Detect the root zone" + if ! _get_root "$fulldomain"; then + _err "Domain not found" + return 1 + fi + + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + _debug _domain_id "$_domain_id" + + _info "Removing record" + _get_record "$_sub_domain" + if [ "$record_id" ]; then + if _azion_rest DELETE "intelligent_dns/$_domain_id/records/$record_id"; then + _info "Record removed." + return 0 + else + _err "Failed to remove record." + return 1 + fi + else + _info "Record not found or already removed." + return 0 + fi +} + +#################### Private functions below ################################## +# Usage: _acme-challenge.www.domain.com +# returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +# _domain_id=sdjkglgdfewsdfg +_get_root() { + domain=$1 + i=1 + p=1 + + # Use Zone ID directly if provided + if [ "$AZION_ZoneID" ]; then + if ! _azion_rest GET "intelligent_dns/$AZION_ZoneID"; then + return 1 + else + if _contains "$response" "\"domain\":\"" >/dev/null; then + _domain=$(echo "$response" | _egrep_o "\"domain\":\"[^\"]*\"" | cut -d : -f 2 | _head_n 1 | tr -d \") + if [ "$_domain" ]; then + _cutlength=$((${#domain} - ${#_domain} - 1)) + _sub_domain=$(printf "%s" "$domain" | cut -c "1-$_cutlength") + _domain_id=$AZION_ZoneID + return 0 + else + return 1 + fi + else + return 1 + fi + fi + fi + + if ! _azion_rest GET "intelligent_dns"; then + return 1 + fi + + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug h "$h" + if [ -z "$h" ]; then + # not valid + return 1 + fi + + if _contains "$response" "\"domain\":\"$h\""; then + _domain_id=$(echo "$response" | tr '{' "\n" | grep "\"domain\":\"$h\"" | _egrep_o "\"id\":[0-9]*" | _head_n 1 | cut -d : -f 2 | tr -d \") + _debug _domain_id "$_domain_id" + if [ "$_domain_id" ]; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain=$h + _saveaccountconf_mutable AZION_ZoneID "$_domain_id" + return 0 + fi + return 1 + fi + p=$i + i=$(_math "$i" + 1) + done + return 1 +} + +_get_record() { + _record=$1 + + AZION_ZoneID="${AZION_ZoneID:-$(_readaccountconf_mutable AZION_ZoneID)}" + + if ! _azion_rest GET "intelligent_dns/$AZION_ZoneID/records"; then + return 1 + fi + + if _contains "$response" "\"entry\":\"$_record\""; then + _json_record=$(echo "$response" | tr '{}' "\n" | grep "\"entry\":\"$_record\"") + if [ "$_json_record" ]; then + record_id=$(echo "$_json_record" | _egrep_o "\"record_id\":[0-9]*" | _head_n 1 | cut -d : -f 2 | tr -d \") + answers_list=$(echo "$_json_record" | _egrep_o "\"answers_list\":\[.*\]" | _head_n 1 | cut -d : -f 2 | tr -d \[\]) + return 0 + fi + return 1 + fi + return 1 +} + +_get_token() { + AZION_Username="${AZION_Username:-$(_readaccountconf_mutable AZION_Username)}" + AZION_Password="${AZION_Password:-$(_readaccountconf_mutable AZION_Password)}" + + _basic_auth=$(printf "%s:%s" "$AZION_Username" "$AZION_Password" | _base64) + _debug _basic_auth "$_basic_auth" + + export _H1="Accept: application/json; version=3" + export _H2="Content-Type: application/json" + export _H3="Authorization: Basic $_basic_auth" + + response="$(_post "" "$AZION_Api/tokens" "" "POST")" + _debug2 response "$response" + if _contains "$response" "\"token\":\"" >/dev/null; then + _azion_token=$(echo "$response" | _egrep_o "\"token\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \") + _debug _azion_token "$_azion_token" + _saveaccountconf_mutable AZION_Token "$_azion_token" + else + _err "Failed to generate Azion token" + return 1 + fi +} + +_azion_rest() { + _method=$1 + _uri="$2" + _data="$3" + + AZION_Token="${AZION_Token:-$(_readaccountconf_mutable AZION_Token)}" + + export _H1="Accept: application/json; version=3" + export _H2="Content-Type: application/json" + export _H3="Authorization: token $AZION_Token" + + if [ "$_method" != "GET" ]; then + _debug _data "$_data" + response="$(_post "$_data" "$AZION_Api/$_uri" "" "$_method")" + else + response="$(_get "$AZION_Api/$_uri")" + fi + + _debug2 response "$response" + + if [ "$?" != "0" ]; then + _err "error $_method $_uri $_data" + return 1 + fi + return 0 +} From 4b7ce1c3c188d82c5e0932d45129dedde004ab41 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 13 Jun 2021 14:29:26 +0800 Subject: [PATCH 224/304] change default ca to zerossl --- acme.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/acme.sh b/acme.sh index 9a3e1642..9ebc94f4 100755 --- a/acme.sh +++ b/acme.sh @@ -29,7 +29,7 @@ CA_BUYPASS_TEST="https://api.test4.buypass.no/acme/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 +DEFAULT_CA=$CA_ZEROSSL DEFAULT_STAGING_CA=$CA_LETSENCRYPT_V2_TEST CA_NAMES=" @@ -3528,8 +3528,10 @@ _regAccount() { 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" + _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) @@ -3540,11 +3542,13 @@ _regAccount() { fi _debug2 "$_eabresp" _eab_id="$(echo "$_eabresp" | tr ',}' '\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' | 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 @@ -3566,7 +3570,7 @@ _regAccount() { 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 ' ')" + 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) From f31c7e5350c9e7dc6ad1bc84c313d6aa1b7b236b Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 13 Jun 2021 15:00:30 +0800 Subject: [PATCH 225/304] add zerossl --- .github/workflows/LetsEncrypt.yml | 48 ++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index bdc9072e..11137388 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -16,6 +16,9 @@ on: jobs: Ubuntu: + strategy: + matrix: + TEST_ACME_Server: ["", "https://acme.zerossl.com/v2/DV90"] runs-on: ubuntu-latest env: TEST_LOCAL: 1 @@ -24,11 +27,20 @@ jobs: - name: Install tools run: sudo apt-get install -y socat - name: Clone acmetest - run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ + run: | + cd .. \ + && git clone https://github.com/acmesh-official/acmetest.git \ + && cp -r acme.sh acmetest/ - name: Run acmetest - run: cd ../acmetest && sudo --preserve-env ./letest.sh + run: | + cd ../acmetest \ + && export ACME_DIRECTORY=${{ matrix.TEST_ACME_Server }} \ + && sudo --preserve-env ./letest.sh MacOS: + strategy: + matrix: + TEST_ACME_Server: ["", "https://acme.zerossl.com/v2/DV90"] runs-on: macos-latest env: TEST_LOCAL: 1 @@ -37,11 +49,20 @@ jobs: - name: Install tools run: brew install socat - name: Clone acmetest - run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ + run: | + cd .. \ + && git clone https://github.com/acmesh-official/acmetest.git \ + && cp -r acme.sh acmetest/ - name: Run acmetest - run: cd ../acmetest && sudo --preserve-env ./letest.sh + run: | + cd ../acmetest \ + && export ACME_DIRECTORY=${{ matrix.TEST_ACME_Server }} \ + && sudo --preserve-env ./letest.sh Windows: + strategy: + matrix: + TEST_ACME_Server: ["", "https://acme.zerossl.com/v2/DV90"] runs-on: windows-latest env: TEST_LOCAL: 1 @@ -74,9 +95,15 @@ jobs: run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - name: Run acmetest shell: cmd - run: cd ../acmetest && bash.exe -c ./letest.sh + run: | + cd ../acmetest \ + set ACME_DIRECTORY=${{ matrix.TEST_ACME_Server }} \ + && bash.exe -c ./letest.sh FreeBSD: + strategy: + matrix: + TEST_ACME_Server: ["", "https://acme.zerossl.com/v2/DV90"] runs-on: macos-latest env: TEST_LOCAL: 1 @@ -99,9 +126,14 @@ jobs: prepare: pkg install -y socat curl usesh: true run: | - cd ../acmetest && ./letest.sh + cd ../acmetest \ + && export ACME_DIRECTORY=${{ matrix.TEST_ACME_Server }} \ + && ./letest.sh Solaris: + strategy: + matrix: + TEST_ACME_Server: ["", "https://acme.zerossl.com/v2/DV90"] runs-on: macos-latest env: TEST_LOCAL: 1 @@ -123,5 +155,7 @@ jobs: "8080": "80" prepare: pkgutil -y -i socat curl run: | - cd ../acmetest && ./letest.sh + cd ../acmetest \ + && export ACME_DIRECTORY=${{ matrix.TEST_ACME_Server }} \ + && ./letest.sh From 838bf2684b79ed293d9fd8705c327a9e085a87f9 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 13 Jun 2021 15:30:51 +0800 Subject: [PATCH 226/304] fix windows --- .github/workflows/LetsEncrypt.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 11137388..e7c5e2d1 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -97,7 +97,7 @@ jobs: shell: cmd run: | cd ../acmetest \ - set ACME_DIRECTORY=${{ matrix.TEST_ACME_Server }} \ + && set ACME_DIRECTORY=${{ matrix.TEST_ACME_Server }} \ && bash.exe -c ./letest.sh FreeBSD: From c701bf3e376e812e0a63a9e823e702d7a1f43cbb Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 13 Jun 2021 15:45:33 +0800 Subject: [PATCH 227/304] set ca names in the env --- .github/workflows/LetsEncrypt.yml | 58 +++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index e7c5e2d1..b95334d7 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -18,10 +18,17 @@ jobs: Ubuntu: strategy: matrix: - TEST_ACME_Server: ["", "https://acme.zerossl.com/v2/DV90"] + include: + - TEST_ACME_Server: "" + CA_ECDSA: "" + CA: "" + - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" + CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" + CA: "ZeroSSL RSA Domain Secure Site CA" runs-on: ubuntu-latest env: TEST_LOCAL: 1 + ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} steps: - uses: actions/checkout@v2 - name: Install tools @@ -34,16 +41,22 @@ jobs: - name: Run acmetest run: | cd ../acmetest \ - && export ACME_DIRECTORY=${{ matrix.TEST_ACME_Server }} \ && sudo --preserve-env ./letest.sh MacOS: strategy: matrix: - TEST_ACME_Server: ["", "https://acme.zerossl.com/v2/DV90"] + include: + - TEST_ACME_Server: "" + CA_ECDSA: "" + CA: "" + - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" + CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" + CA: "ZeroSSL RSA Domain Secure Site CA" runs-on: macos-latest env: TEST_LOCAL: 1 + ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} steps: - uses: actions/checkout@v2 - name: Install tools @@ -56,15 +69,21 @@ jobs: - name: Run acmetest run: | cd ../acmetest \ - && export ACME_DIRECTORY=${{ matrix.TEST_ACME_Server }} \ && sudo --preserve-env ./letest.sh Windows: strategy: matrix: - TEST_ACME_Server: ["", "https://acme.zerossl.com/v2/DV90"] + include: + - TEST_ACME_Server: "" + CA_ECDSA: "" + CA: "" + - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" + CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" + CA: "ZeroSSL RSA Domain Secure Site CA" runs-on: windows-latest env: + ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} TEST_LOCAL: 1 #The 80 port is used by Windows server, we have to use a custom port, tunnel will also use this port. Le_HTTPPort: 8888 @@ -95,18 +114,22 @@ jobs: run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - name: Run acmetest shell: cmd - run: | - cd ../acmetest \ - && set ACME_DIRECTORY=${{ matrix.TEST_ACME_Server }} \ - && bash.exe -c ./letest.sh + run: cd ../acmetest && bash.exe -c ./letest.sh FreeBSD: strategy: matrix: - TEST_ACME_Server: ["", "https://acme.zerossl.com/v2/DV90"] + include: + - TEST_ACME_Server: "" + CA_ECDSA: "" + CA: "" + - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" + CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" + CA: "ZeroSSL RSA Domain Secure Site CA" runs-on: macos-latest env: TEST_LOCAL: 1 + ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} steps: - uses: actions/checkout@v2 - uses: vmactions/cf-tunnel@v0.0.2 @@ -120,23 +143,29 @@ jobs: run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/freebsd-vm@v0.1.4 with: - envs: 'TEST_LOCAL TestingDomain' + envs: 'TEST_LOCAL TestingDomain ACME_DIRECTORY CA_ECDSA CA' nat: | "8080": "80" prepare: pkg install -y socat curl usesh: true run: | cd ../acmetest \ - && export ACME_DIRECTORY=${{ matrix.TEST_ACME_Server }} \ && ./letest.sh Solaris: strategy: matrix: - TEST_ACME_Server: ["", "https://acme.zerossl.com/v2/DV90"] + include: + - TEST_ACME_Server: "" + CA_ECDSA: "" + CA: "" + - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" + CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" + CA: "ZeroSSL RSA Domain Secure Site CA" runs-on: macos-latest env: TEST_LOCAL: 1 + ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} steps: - uses: actions/checkout@v2 - uses: vmactions/cf-tunnel@v0.0.2 @@ -150,12 +179,11 @@ jobs: run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/solaris-vm@v0.0.3 with: - envs: 'TEST_LOCAL TestingDomain' + envs: 'TEST_LOCAL TestingDomain ACME_DIRECTORY CA_ECDSA CA' nat: | "8080": "80" prepare: pkgutil -y -i socat curl run: | cd ../acmetest \ - && export ACME_DIRECTORY=${{ matrix.TEST_ACME_Server }} \ && ./letest.sh From eec0442db60014b1d0ab9143129e18184928116d Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 13 Jun 2021 15:52:38 +0800 Subject: [PATCH 228/304] fix env --- .github/workflows/LetsEncrypt.yml | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index b95334d7..84fe61ad 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -22,13 +22,18 @@ jobs: - TEST_ACME_Server: "" CA_ECDSA: "" CA: "" + CA_EMAIL: "" - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" CA: "ZeroSSL RSA Domain Secure Site CA" + CA_EMAIL: "githubtest@acme.sh" runs-on: ubuntu-latest env: TEST_LOCAL: 1 ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} + CA_ECDSA: ${{ matrix.CA_ECDSA }} + CA: ${{ matrix.CA }} + CA_EMAIL: ${{ matrix.CA_EMAIL }} steps: - uses: actions/checkout@v2 - name: Install tools @@ -50,13 +55,18 @@ jobs: - TEST_ACME_Server: "" CA_ECDSA: "" CA: "" + CA_EMAIL: "" - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" CA: "ZeroSSL RSA Domain Secure Site CA" + CA_EMAIL: "githubtest@acme.sh" runs-on: macos-latest env: TEST_LOCAL: 1 ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} + CA_ECDSA: ${{ matrix.CA_ECDSA }} + CA: ${{ matrix.CA }} + CA_EMAIL: ${{ matrix.CA_EMAIL }} steps: - uses: actions/checkout@v2 - name: Install tools @@ -78,12 +88,17 @@ jobs: - TEST_ACME_Server: "" CA_ECDSA: "" CA: "" + CA_EMAIL: "" - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" CA: "ZeroSSL RSA Domain Secure Site CA" + CA_EMAIL: "githubtest@acme.sh" runs-on: windows-latest env: ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} + CA_ECDSA: ${{ matrix.CA_ECDSA }} + CA: ${{ matrix.CA }} + CA_EMAIL: ${{ matrix.CA_EMAIL }} TEST_LOCAL: 1 #The 80 port is used by Windows server, we have to use a custom port, tunnel will also use this port. Le_HTTPPort: 8888 @@ -123,13 +138,18 @@ jobs: - TEST_ACME_Server: "" CA_ECDSA: "" CA: "" + CA_EMAIL: "" - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" CA: "ZeroSSL RSA Domain Secure Site CA" + CA_EMAIL: "githubtest@acme.sh" runs-on: macos-latest env: TEST_LOCAL: 1 ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} + CA_ECDSA: ${{ matrix.CA_ECDSA }} + CA: ${{ matrix.CA }} + CA_EMAIL: ${{ matrix.CA_EMAIL }} steps: - uses: actions/checkout@v2 - uses: vmactions/cf-tunnel@v0.0.2 @@ -143,7 +163,7 @@ jobs: run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/freebsd-vm@v0.1.4 with: - envs: 'TEST_LOCAL TestingDomain ACME_DIRECTORY CA_ECDSA CA' + envs: 'TEST_LOCAL TestingDomain ACME_DIRECTORY CA_ECDSA CA CA_EMAIL' nat: | "8080": "80" prepare: pkg install -y socat curl @@ -159,13 +179,18 @@ jobs: - TEST_ACME_Server: "" CA_ECDSA: "" CA: "" + CA_EMAIL: "" - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" CA: "ZeroSSL RSA Domain Secure Site CA" + CA_EMAIL: "githubtest@acme.sh" runs-on: macos-latest env: TEST_LOCAL: 1 ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} + CA_ECDSA: ${{ matrix.CA_ECDSA }} + CA: ${{ matrix.CA }} + CA_EMAIL: ${{ matrix.CA_EMAIL }} steps: - uses: actions/checkout@v2 - uses: vmactions/cf-tunnel@v0.0.2 @@ -179,7 +204,7 @@ jobs: run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/solaris-vm@v0.0.3 with: - envs: 'TEST_LOCAL TestingDomain ACME_DIRECTORY CA_ECDSA CA' + envs: 'TEST_LOCAL TestingDomain ACME_DIRECTORY CA_ECDSA CA CA_EMAIL' nat: | "8080": "80" prepare: pkgutil -y -i socat curl From 20b60eaa9a5195dd2be99dbaf424cec1dca71f6f Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 13 Jun 2021 21:37:26 +0800 Subject: [PATCH 229/304] fix for solaris --- README.md | 4 ++-- acme.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index edd6442f..4b705751 100644 --- a/README.md +++ b/README.md @@ -85,8 +85,8 @@ https://github.com/acmesh-official/acmetest # Supported CA -- Letsencrypt.org CA(default) -- [ZeroSSL.com CA](https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA) +- [ZeroSSL.com CA](https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA)(default) +- Letsencrypt.org CA - [BuyPass.com CA](https://github.com/acmesh-official/acme.sh/wiki/BuyPass.com-CA) - [Pebble strict Mode](https://github.com/letsencrypt/pebble) - Any other [RFC8555](https://tools.ietf.org/html/rfc8555)-compliant CA diff --git a/acme.sh b/acme.sh index 9ebc94f4..6cea6648 100755 --- a/acme.sh +++ b/acme.sh @@ -3540,14 +3540,14 @@ _regAccount() { _err "Can not get EAB credentials from ZeroSSL." return 1 fi - _debug2 "$_eabresp" + _secure_debug2 _eabresp "$_eabresp" _eab_id="$(echo "$_eabresp" | tr ',}' '\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' | 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 _err "Can not resolve _eab_hmac_key" From cd00f00eed50914ba7193e04dbb10df93d35eb09 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 14 Jun 2021 11:50:19 +0800 Subject: [PATCH 230/304] add all Linux --- .github/workflows/Linux.yml | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .github/workflows/Linux.yml diff --git a/.github/workflows/Linux.yml b/.github/workflows/Linux.yml new file mode 100644 index 00000000..9ebc4779 --- /dev/null +++ b/.github/workflows/Linux.yml @@ -0,0 +1,38 @@ +name: Linux +on: + push: + branches: + - '*' + paths: + - '**.sh' + - '**.yml' + pull_request: + branches: + - dev + paths: + - '**.sh' + - '**.yml' + + +jobs: + Linux: + strategy: + matrix: + os: ["ubuntu:latest", "debian:latest", "almalinux:latest", "fedora:latest", "centos:latest", "opensuse/leap:latest", "alpine:latest", "oraclelinux:8", "kalilinux/kali", "archlinux:latest", "mageia", "gentoo/stage3-amd64", "clearlinux:latest"] + runs-on: ubuntu-latest + env: + TEST_LOCAL: 1 + steps: + - uses: actions/checkout@v2 + - name: Clone acmetest + run: | + cd .. \ + && git clone https://github.com/acmesh-official/acmetest.git \ + && cp -r acme.sh acmetest/ + - name: Run acmetest + run: | + cd ../acmetest \ + && ./rundocker.sh testplat {{ matrix.os }} + + + From e938a2cdc90fe649dc25d77448c1398251e01325 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 14 Jun 2021 11:52:45 +0800 Subject: [PATCH 231/304] fix --- .github/workflows/Linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Linux.yml b/.github/workflows/Linux.yml index 9ebc4779..f5f74351 100644 --- a/.github/workflows/Linux.yml +++ b/.github/workflows/Linux.yml @@ -32,7 +32,7 @@ jobs: - name: Run acmetest run: | cd ../acmetest \ - && ./rundocker.sh testplat {{ matrix.os }} + && ./rundocker.sh testplat ${{ matrix.os }} From 47bf8f959c197acf24b59cc3f3c0681e27b4aee4 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 14 Jun 2021 12:00:42 +0800 Subject: [PATCH 232/304] update status --- README.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 4b705751..07dc5d59 100644 --- a/README.md +++ b/README.md @@ -62,24 +62,24 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa) |3|[![FreeBSD](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|FreeBSD |4|[![Solaris](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|Solaris |5|[![Ubuntu](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)| Ubuntu -|6|[![](https://acmesh-official.github.io/acmetest/status/pfsense.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|pfsense -|7|[![](https://acmesh-official.github.io/acmetest/status/openbsd.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|OpenBSD -|8|[![](https://acmesh-official.github.io/acmetest/status/debian-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)| Debian -|9|[![](https://acmesh-official.github.io/acmetest/status/centos-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|CentOS -|10|[![](https://acmesh-official.github.io/acmetest/status/opensuse-leap-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|openSUSE -|11|[![](https://acmesh-official.github.io/acmetest/status/alpine-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Alpine Linux (with curl) -|12|[![](https://acmesh-official.github.io/acmetest/status/archlinux-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Archlinux -|13|[![](https://acmesh-official.github.io/acmetest/status/fedora-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|fedora -|14|[![](https://acmesh-official.github.io/acmetest/status/kalilinux-kali.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Kali Linux -|15|[![](https://acmesh-official.github.io/acmetest/status/oraclelinux-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Oracle Linux +|6|NA|pfsense +|7|NA|OpenBSD +|8|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)| Debian +|9|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|CentOS +|10|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|openSUSE +|11|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Alpine Linux (with curl) +|12|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Archlinux +|13|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|fedora +|14|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Kali Linux +|15|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Oracle Linux |16|[![](https://acmesh-official.github.io/acmetest/status/proxmox.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Proxmox: See Proxmox VE Wiki. Version [4.x, 5.0, 5.1](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x,_5.0_and_5.1)#Let.27s_Encrypt_using_acme.sh), version [5.2 and up](https://pve.proxmox.com/wiki/Certificate_Management) |17|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111 -|18|[![](https://acmesh-official.github.io/acmetest/status/mageia.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Mageia +|18|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Mageia |19|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT) -|20|[![](https://acmesh-official.github.io/acmetest/status/gentoo-stage3-amd64.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Gentoo Linux -|21|[![](https://acmesh-official.github.io/acmetest/status/clearlinux-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|ClearLinux +|20|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Gentoo Linux +|21|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|ClearLinux -For all build statuses, check our [weekly build project](https://github.com/acmesh-official/acmetest): +Check our [testing project](https://github.com/acmesh-official/acmetest): https://github.com/acmesh-official/acmetest From 91d26f6037f8ec72e1ed079632e0465be4110b14 Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Sat, 5 Oct 2019 21:28:25 +0800 Subject: [PATCH 233/304] Remove invalid "Contribute" link in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 07dc5d59..c1c3a3c4 100644 --- a/README.md +++ b/README.md @@ -469,7 +469,7 @@ TODO: ### Code Contributors -This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. +This project exists thanks to all the people who contribute. ### Financial Contributors From ed5e93f5a145554519b774333b3de3e83ebf80e5 Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Sat, 5 Oct 2019 20:49:51 +0800 Subject: [PATCH 234/304] Simplify apk command in Dockerfile With apk `--no-cache` parameter, there is no need to run `apk update` and manually clean up the cache, apk will update automatically without leaving local cache files to be cleaned up. --- Dockerfile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 4618efaf..4d8f219f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,6 @@ FROM alpine:3.12 -RUN apk update -f \ - && apk --no-cache add -f \ +RUN apk --no-cache add -f \ openssl \ openssh-client \ coreutils \ @@ -12,8 +11,7 @@ RUN apk update -f \ tzdata \ oath-toolkit-oathtool \ tar \ - libidn \ - && rm -rf /var/cache/apk/* + libidn ENV LE_CONFIG_HOME /acme.sh From 941a94587c36c696aa1fbe3493fafb4cabd9b0e8 Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Sat, 5 Oct 2019 20:51:51 +0800 Subject: [PATCH 235/304] Use `COPY` instead of `ADD` in Dockerfile for folder Ref: https://docs.docker.com/develop/develop-images/#add-or-copy --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 4d8f219f..c42f4f39 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,7 +20,7 @@ ARG AUTO_UPGRADE=1 ENV AUTO_UPGRADE $AUTO_UPGRADE #Install -ADD ./ /install_acme.sh/ +COPY ./ /install_acme.sh/ RUN cd /install_acme.sh && ([ -f /install_acme.sh/acme.sh ] && /install_acme.sh/acme.sh --install || curl https://get.acme.sh | sh) && rm -rf /install_acme.sh/ From 6e05ad4e7124bcdd2fb50873485479dd6e4cdb92 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 19 Jun 2021 11:52:11 +0800 Subject: [PATCH 236/304] fix https://github.com/acmesh-official/acme.sh/issues/3563 --- dnsapi/dns_nsd.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_nsd.sh b/dnsapi/dns_nsd.sh index 83cc4cac..0d29a485 100644 --- a/dnsapi/dns_nsd.sh +++ b/dnsapi/dns_nsd.sh @@ -51,7 +51,7 @@ dns_nsd_rm() { Nsd_ZoneFile="${Nsd_ZoneFile:-$(_readdomainconf Nsd_ZoneFile)}" Nsd_Command="${Nsd_Command:-$(_readdomainconf Nsd_Command)}" - sed -i "/$fulldomain. $ttlvalue IN TXT \"$txtvalue\"/d" "$Nsd_ZoneFile" + _sed_i "/$fulldomain. $ttlvalue IN TXT \"$txtvalue\"/d" "$Nsd_ZoneFile" _info "Removed TXT record for $fulldomain" _debug "Running $Nsd_Command" if eval "$Nsd_Command"; then From e3ae12c7a7c7c46a5ecdf6b2b788a1ca0e781307 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 20 Jun 2021 12:26:12 +0800 Subject: [PATCH 237/304] exclude test for dns api changes --- .github/workflows/LetsEncrypt.yml | 6 ++++++ .github/workflows/Linux.yml | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 84fe61ad..b579d6e9 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -6,12 +6,18 @@ on: paths: - '**.sh' - '**.yml' + - '!dnsapi/**' + - '!deploy/**' + - '!notify/**' pull_request: branches: - dev paths: - '**.sh' - '**.yml' + - '!dnsapi/**' + - '!deploy/**' + - '!notify/**' jobs: diff --git a/.github/workflows/Linux.yml b/.github/workflows/Linux.yml index f5f74351..3e1d3cf8 100644 --- a/.github/workflows/Linux.yml +++ b/.github/workflows/Linux.yml @@ -6,12 +6,18 @@ on: paths: - '**.sh' - '**.yml' + - '!dnsapi/**' + - '!deploy/**' + - '!notify/**' pull_request: branches: - dev paths: - '**.sh' - '**.yml' + - '!dnsapi/**' + - '!deploy/**' + - '!notify/**' jobs: From eee53419881667f2990354c793e502617536965c Mon Sep 17 00:00:00 2001 From: Avi Miller Date: Fri, 4 Jun 2021 19:20:23 +1000 Subject: [PATCH 238/304] Add DNS API plugin for Oracle Cloud Infrastructure DNS Service This plugin is has noticeably more required fields than most other plugins due to the requirement that all requests to the OCI REST API must be cryptographically signed by the client using the draft standard proposed in draft-cavage-http-signatures-08[1]. The OCI specific implementation details of the draft standard are documented in the Developer Guide[2]. NOTE: there is maximum allowed clock skew of five minutes between the client and the API endpoint. Requests will be denied if the skew is greater. This PR also includes a minor tweak to the Solaris job in the DNS workflow so that it uses the pre-installed GNU tools, curl and OpenSSL 1.1.1. Without these changes, the signature generation function does not work on Solaris. [1]: https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-08 [2]: https://docs.oracle.com/en-us/iaas/Content/API/Concepts/signingrequests.htm#five Signed-off-by: Avi Miller --- .github/workflows/DNS.yml | 10 +- dnsapi/dns_oci.sh | 246 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 251 insertions(+), 5 deletions(-) create mode 100644 dnsapi/dns_oci.sh diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index f8e501ed..b00ef263 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -59,7 +59,7 @@ jobs: run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - name: Set env file run: | - cd ../acmetest + cd ../acmetest if [ "${{ secrets.TokenName1}}" ] ; then echo "${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}" >> env.list fi @@ -75,7 +75,7 @@ jobs: if [ "${{ secrets.TokenName5}}" ] ; then echo "${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}" >> env.list fi - echo "TEST_DNS_NO_WILDCARD" >> env.list + echo "TEST_DNS_NO_WILDCARD" >> env.list echo "TEST_DNS_SLEEP" >> env.list - name: Run acmetest run: cd ../acmetest && ./rundocker.sh testall @@ -226,8 +226,10 @@ jobs: - uses: vmactions/solaris-vm@v0.0.3 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' - prepare: pkgutil -y -i socat curl + prepare: pkgutil -y -i socat run: | + pkg set-mediator -v -I default@1.1 openssl + export PATH=/usr/gnu/bin:$PATH if [ "${{ secrets.TokenName1}}" ] ; then export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}} fi @@ -245,5 +247,3 @@ jobs: fi cd ../acmetest ./letest.sh - - diff --git a/dnsapi/dns_oci.sh b/dnsapi/dns_oci.sh new file mode 100644 index 00000000..2843a8ca --- /dev/null +++ b/dnsapi/dns_oci.sh @@ -0,0 +1,246 @@ +#!/usr/bin/env sh +# +# Acme.sh DNS API plugin for Oracle Cloud Infrastructure +# Copyright (c) 2021, Oracle and/or its affiliates +# +# Required environment variables: +# - OCI_TENANCY : OCID of tenancy that contains the target DNS zone +# - OCI_USER : OCID of user with permission to add/remove records from zones +# - OCI_FINGERPRINT: fingerprint of the public key for the user +# - OCI_PRIVATE_KEY: Path to private API signing key file in PEM format +# +# Optional environment variables: +# - OCI_KEY_PASSPHRASE: if the private key above s encrypted, the passphrase is required +# - OCI_REGION: Your home region will probably response the fastest +# + +dns_oci_add() { + _fqdn="$1" + _rdata="$2" + + if _oci_config; then + + if ! _get_zone "$_fqdn"; then + _err "Error: DNS Zone not found for $_fqdn." + return 1 + fi + + if [ "$_sub_domain" ] && [ "$_domain" ]; then + _add_record_body="{\"items\":[{\"domain\":\"${_sub_domain}.${_domain}\",\"rdata\":\"$_rdata\",\"rtype\":\"TXT\",\"ttl\": 30,\"operation\":\"ADD\"}]}" + response=$(_signed_request "PATCH" "/20180115/zones/${_domain}/records" "$_add_record_body") + if [ "$response" ]; then + _info "Success: added TXT record for ${_sub_domain}.${_domain}." + else + _err "Error: failed to add TXT record for ${_sub_domain}.${_domain}." + return 1 + fi + fi + + else + return 1 + fi + +} + +dns_oci_rm() { + _fqdn="$1" + _rdata="$2" + + if _oci_config; then + + if ! _get_zone "$_fqdn"; then + _err "Error: DNS Zone not found for $_fqdn." + return 1 + fi + + if [ "$_sub_domain" ] && [ "$_domain" ]; then + _remove_record_body="{\"items\":[{\"domain\":\"${_sub_domain}.${_domain}\",\"rdata\":\"$_rdata\",\"rtype\":\"TXT\",\"operation\":\"REMOVE\"}]}" + response=$(_signed_request "PATCH" "/20180115/zones/${_domain}/records" "$_remove_record_body") + if [ "$response" ]; then + _info "Success: removed TXT record for ${_sub_domain}.${_domain}." + else + _err "Error: failed to remove TXT record for ${_sub_domain}.${_domain}." + return 1 + fi + fi + + else + return 1 + fi + +} + +#################### Private functions below ################################## +_oci_config() { + + OCI_TENANCY="${OCI_TENANCY:-$(_readaccountconf_mutable OCI_TENANCY)}" + OCI_USER="${OCI_USER:-$(_readaccountconf_mutable OCI_USER)}" + OCI_FINGERPRINT="${OCI_FINGERPRINT:-$(_readaccountconf_mutable OCI_FINGERPRINT)}" + OCI_PRIVATE_KEY="${OCI_PRIVATE_KEY:-$(_readaccountconf_mutable OCI_PRIVATE_KEY)}" + OCI_KEY_PASSPHRASE="${OCI_KEY_PASSPHRASE:-$(_readaccountconf_mutable OCI_KEY_PASSPHRASE)}" + OCI_REGION="${OCI_REGION:-$(_readaccountconf_mutable OCI_REGION)}" + + _not_set="" + _ret=0 + + if [ -f "$OCI_PRIVATE_KEY" ]; then + OCI_PRIVATE_KEY="$(openssl enc -a -A <"$OCI_PRIVATE_KEY")" + fi + + if [ -z "$OCI_TENANCY" ]; then + _not_set="OCI_TENANCY " + fi + + if [ -z "$OCI_USER" ]; then + _not_set="${_not_set}OCI_USER " + fi + + if [ -z "$OCI_FINGERPRINT" ]; then + _not_set="${_not_set}OCI_FINGERPRINT " + fi + + if [ -z "$OCI_PRIVATE_KEY" ]; then + _not_set="${_not_set}OCI_PRIVATE_KEY" + fi + + if [ "$_not_set" ]; then + _err "Fatal: environment variable(s): ${_not_set} not set." + _ret=1 + else + _saveaccountconf_mutable OCI_TENANCY "$OCI_TENANCY" + _saveaccountconf_mutable OCI_USER "$OCI_USER" + _saveaccountconf_mutable OCI_FINGERPRINT "$OCI_FINGERPRINT" + _saveaccountconf_mutable OCI_PRIVATE_KEY "$OCI_PRIVATE_KEY" + fi + + if [ "$OCI_PRIVATE_KEY" ] && [ "$(printf "%s\n" "$OCI_PRIVATE_KEY" | wc -l)" -eq 1 ]; then + OCI_PRIVATE_KEY="$(echo "$OCI_PRIVATE_KEY" | openssl enc -d -a -A)" + _secure_debug3 OCI_PRIVATE_KEY "$OCI_PRIVATE_KEY" + fi + + if [ "$OCI_KEY_PASSPHRASE" ]; then + _saveaccountconf_mutable OCI_KEY_PASSPHRASE "$OCI_KEY_PASSPHRASE" + fi + + if [ "$OCI_REGION" ]; then + _saveaccountconf_mutable OCI_REGION "$OCI_REGION" + else + OCI_REGION="us-ashburn-1" + fi + + return $_ret + +} + +# _get_zone(): retrieves the Zone name and OCID +# +# _sub_domain=_acme-challenge.www +# _domain=domain.com +# _domain_ociid=ocid1.dns-zone.oc1.. +_get_zone() { + domain=$1 + i=1 + p=1 + + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug h "$h" + if [ -z "$h" ]; then + # not valid + return 1 + fi + + _domain_id=$(_signed_request "GET" "/20180115/zones/$h" "" "id") + if [ "$_domain_id" ]; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain=$h + + _debug _domain_id "$_domain_id" + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + return 0 + fi + + p=$i + i=$(_math "$i" + 1) + done + return 1 + +} + +_signed_request() { + + _sig_method="$1" + _sig_target="$2" + _sig_body="$3" + _return_field="$4" + + _sig_host="dns.$OCI_REGION.oraclecloud.com" + _sig_keyId="$OCI_TENANCY/$OCI_USER/$OCI_FINGERPRINT" + _sig_alg="rsa-sha256" + _sig_version="1" + _sig_now="$(LC_ALL=C \date -u "+%a, %d %h %Y %H:%M:%S GMT")" + + if [ "$OCI_KEY_PASSPHRASE" ]; then + export OCI_KEY_PASSPHRASE="$OCI_KEY_PASSPHRASE" + _sig_passinArg="-passin env:OCI_KEY_PASSPHRASE" + fi + + _request_method=$(printf %s "$_sig_method" | _lower_case) + _curl_method=$(printf %s "$_sig_method" | _upper_case) + + _request_target="(request-target): $_request_method $_sig_target" + _date_header="date: $_sig_now" + _host_header="host: $_sig_host" + + _string_to_sign="$_request_target\n$_date_header\n$_host_header" + _sig_headers="(request-target) date host" + + if [ "$_sig_body" ]; then + _secure_debug3 _sig_body "$_sig_body" + _sig_body_sha256="x-content-sha256: $(printf %s "$_sig_body" | openssl dgst -binary -sha256 | openssl enc -e -base64)" + _sig_body_type="content-type: application/json" + _sig_body_length="content-length: ${#_sig_body}" + _string_to_sign="$_string_to_sign\n$_sig_body_sha256\n$_sig_body_type\n$_sig_body_length" + _sig_headers="$_sig_headers x-content-sha256 content-type content-length" + fi + + _tmp_file=$(_mktemp) + if [ -f "$_tmp_file" ]; then + printf '%s' "$OCI_PRIVATE_KEY" >"$_tmp_file" + # Double quoting the file and passphrase breaks openssl + # shellcheck disable=SC2086 + _signature=$(printf '%b' "$_string_to_sign" | openssl dgst -sha256 -sign $_tmp_file $_sig_passinArg | openssl enc -e -base64 | tr -d '\r\n') + rm -f "$_tmp_file" + fi + + _signed_header="Authorization: Signature version=\"$_sig_version\",keyId=\"$_sig_keyId\",algorithm=\"$_sig_alg\",headers=\"$_sig_headers\",signature=\"$_signature\"" + _secure_debug3 _signed_header "$_signed_header" + + if [ "$_curl_method" = "GET" ]; then + export _H1="$_date_header" + export _H2="$_signed_header" + _response="$(_get "https://${_sig_host}${_sig_target}")" + elif [ "$_curl_method" = "PATCH" ]; then + export _H1="$_date_header" + export _H2="$_sig_body_sha256" + export _H3="$_sig_body_type" + export _H4="$_sig_body_length" + export _H5="$_signed_header" + _response="$(_post "$_sig_body" "https://${_sig_host}${_sig_target}" "" "PATCH")" + else + _err "Unable to process method: $_curl_method." + fi + + _ret="$?" + if [ "$_return_field" ]; then + _response="$(echo "$_response" | sed 's/\\\"//g'))" + _return=$(echo "${_response}" | _egrep_o "\"$_return_field\"\\s*:\\s*\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d "\"") + else + _return="$_response" + fi + + printf "%s" "$_return" + return $_ret + +} From a41cf825e7bce9df1c2c5b0e1e84cffa9de4acbc Mon Sep 17 00:00:00 2001 From: Avi Miller Date: Fri, 18 Jun 2021 10:16:32 +1000 Subject: [PATCH 239/304] fix: switch to using functions instead of calling OpenSSL directly Also reduced the number of environment variables which simplifies the documentation and requirements. The variable names now match those used by the OCI CLI. Signed-off-by: Avi Miller --- dnsapi/dns_oci.sh | 120 ++++++++++++++++++++++------------------------ 1 file changed, 58 insertions(+), 62 deletions(-) diff --git a/dnsapi/dns_oci.sh b/dnsapi/dns_oci.sh index 2843a8ca..1c75b99f 100644 --- a/dnsapi/dns_oci.sh +++ b/dnsapi/dns_oci.sh @@ -3,15 +3,16 @@ # Acme.sh DNS API plugin for Oracle Cloud Infrastructure # Copyright (c) 2021, Oracle and/or its affiliates # -# Required environment variables: -# - OCI_TENANCY : OCID of tenancy that contains the target DNS zone -# - OCI_USER : OCID of user with permission to add/remove records from zones -# - OCI_FINGERPRINT: fingerprint of the public key for the user -# - OCI_PRIVATE_KEY: Path to private API signing key file in PEM format +# Required OCI CLI environment variables: +# - OCI_CLI_TENANCY : OCID of tenancy that contains the target DNS zone +# - OCI_CLI_USER : OCID of user with permission to add/remove records from zones +# - OCI_CLI_REGION : Should point to the tenancy home region # -# Optional environment variables: -# - OCI_KEY_PASSPHRASE: if the private key above s encrypted, the passphrase is required -# - OCI_REGION: Your home region will probably response the fastest +# One of the following two variables is required: +# - OCI_CLI_KEY_FILE: Path to private API signing key file in PEM format; or +# - OCI_CLI_KEY : The private API signing key in PEM format +# +# NOTE: using an encrypted private key that needs a passphrase is not supported. # dns_oci_add() { @@ -20,11 +21,6 @@ dns_oci_add() { if _oci_config; then - if ! _get_zone "$_fqdn"; then - _err "Error: DNS Zone not found for $_fqdn." - return 1 - fi - if [ "$_sub_domain" ] && [ "$_domain" ]; then _add_record_body="{\"items\":[{\"domain\":\"${_sub_domain}.${_domain}\",\"rdata\":\"$_rdata\",\"rtype\":\"TXT\",\"ttl\": 30,\"operation\":\"ADD\"}]}" response=$(_signed_request "PATCH" "/20180115/zones/${_domain}/records" "$_add_record_body") @@ -48,11 +44,6 @@ dns_oci_rm() { if _oci_config; then - if ! _get_zone "$_fqdn"; then - _err "Error: DNS Zone not found for $_fqdn." - return 1 - fi - if [ "$_sub_domain" ] && [ "$_domain" ]; then _remove_record_body="{\"items\":[{\"domain\":\"${_sub_domain}.${_domain}\",\"rdata\":\"$_rdata\",\"rtype\":\"TXT\",\"operation\":\"REMOVE\"}]}" response=$(_signed_request "PATCH" "/20180115/zones/${_domain}/records" "$_remove_record_body") @@ -73,59 +64,57 @@ dns_oci_rm() { #################### Private functions below ################################## _oci_config() { - OCI_TENANCY="${OCI_TENANCY:-$(_readaccountconf_mutable OCI_TENANCY)}" - OCI_USER="${OCI_USER:-$(_readaccountconf_mutable OCI_USER)}" - OCI_FINGERPRINT="${OCI_FINGERPRINT:-$(_readaccountconf_mutable OCI_FINGERPRINT)}" - OCI_PRIVATE_KEY="${OCI_PRIVATE_KEY:-$(_readaccountconf_mutable OCI_PRIVATE_KEY)}" - OCI_KEY_PASSPHRASE="${OCI_KEY_PASSPHRASE:-$(_readaccountconf_mutable OCI_KEY_PASSPHRASE)}" - OCI_REGION="${OCI_REGION:-$(_readaccountconf_mutable OCI_REGION)}" + OCI_CLI_TENANCY="${OCI_CLI_TENANCY:-$(_readaccountconf_mutable OCI_CLI_TENANCY)}" + OCI_CLI_USER="${OCI_CLI_USER:-$(_readaccountconf_mutable OCI_CLI_USER)}" + OCI_CLI_KEY="${OCI_CLI_KEY:-$(_readaccountconf_mutable OCI_CLI_KEY)}" + OCI_CLI_REGION="${OCI_CLI_REGION:-$(_readaccountconf_mutable OCI_CLI_REGION)}" _not_set="" _ret=0 - if [ -f "$OCI_PRIVATE_KEY" ]; then - OCI_PRIVATE_KEY="$(openssl enc -a -A <"$OCI_PRIVATE_KEY")" + if [ -z "$OCI_CLI_KEY_FILE" ] && [ -z "$OCI_CLI_KEY" ]; then + _err "Fatal: you must provide a value for either OCI_CLI_KEY_FILE or OCI_CLI_KEY." + return 1 fi - if [ -z "$OCI_TENANCY" ]; then - _not_set="OCI_TENANCY " + if [ "$OCI_CLI_KEY_FILE" ] && [ -z "$OCI_CLI_KEY" ]; then + if [ -f "$OCI_CLI_KEY_FILE" ]; then + OCI_CLI_KEY=$(_base64 <"$OCI_CLI_KEY_FILE") + else + _err "Fatal: unable to read $OCI_CLI_KEY_FILE." + return 1 + fi fi - if [ -z "$OCI_USER" ]; then - _not_set="${_not_set}OCI_USER " + if [ -z "$OCI_CLI_TENANCY" ]; then + _not_set="${_not_set}OCI_CLI_TENANCY " fi - if [ -z "$OCI_FINGERPRINT" ]; then - _not_set="${_not_set}OCI_FINGERPRINT " + if [ -z "$OCI_CLI_USER" ]; then + _not_set="${_not_set}OCI_CLI_USER " fi - if [ -z "$OCI_PRIVATE_KEY" ]; then - _not_set="${_not_set}OCI_PRIVATE_KEY" + if [ -z "$OCI_CLI_REGION" ]; then + _not_set="${_not_set}OCI_CLI_REGION " fi if [ "$_not_set" ]; then - _err "Fatal: environment variable(s): ${_not_set} not set." + _err "Fatal: required environment variable(s): ${_not_set} not set." _ret=1 else - _saveaccountconf_mutable OCI_TENANCY "$OCI_TENANCY" - _saveaccountconf_mutable OCI_USER "$OCI_USER" - _saveaccountconf_mutable OCI_FINGERPRINT "$OCI_FINGERPRINT" - _saveaccountconf_mutable OCI_PRIVATE_KEY "$OCI_PRIVATE_KEY" - fi - - if [ "$OCI_PRIVATE_KEY" ] && [ "$(printf "%s\n" "$OCI_PRIVATE_KEY" | wc -l)" -eq 1 ]; then - OCI_PRIVATE_KEY="$(echo "$OCI_PRIVATE_KEY" | openssl enc -d -a -A)" - _secure_debug3 OCI_PRIVATE_KEY "$OCI_PRIVATE_KEY" + _saveaccountconf_mutable OCI_CLI_TENANCY "$OCI_CLI_TENANCY" + _saveaccountconf_mutable OCI_CLI_USER "$OCI_CLI_USER" + _saveaccountconf_mutable OCI_CLI_KEY "$OCI_CLI_KEY" + _saveaccountconf_mutable OCI_CLI_REGION "$OCI_CLI_REGION" fi - if [ "$OCI_KEY_PASSPHRASE" ]; then - _saveaccountconf_mutable OCI_KEY_PASSPHRASE "$OCI_KEY_PASSPHRASE" + if ! _contains "PRIVATE KEY" "$OCI_CLI_KEY"; then + OCI_CLI_KEY=$(printf "%s" "$OCI_CLI_KEY" | _dbase64 multiline) fi - if [ "$OCI_REGION" ]; then - _saveaccountconf_mutable OCI_REGION "$OCI_REGION" - else - OCI_REGION="us-ashburn-1" + if ! _get_zone "$_fqdn"; then + _err "Error: DNS Zone not found for $_fqdn." + _ret=1 fi return $_ret @@ -168,6 +157,19 @@ _get_zone() { } +#Usage: privatekey +#Output MD5 fingerprint +_fingerprint() { + pkey="$1" + if [ -z "$pkey" ]; then + _usage "Usage: _fingerprint privkey" + return 1 + fi + + printf "%s" "$pkey" | ${ACME_OPENSSL_BIN:-openssl} rsa -pubout -outform DER 2>/dev/null | ${ACME_OPENSSL_BIN:-openssl} md5 -c | cut -d = -f 2 | tr -d ' ' + +} + _signed_request() { _sig_method="$1" @@ -175,17 +177,13 @@ _signed_request() { _sig_body="$3" _return_field="$4" - _sig_host="dns.$OCI_REGION.oraclecloud.com" - _sig_keyId="$OCI_TENANCY/$OCI_USER/$OCI_FINGERPRINT" + _key_fingerprint=$(_fingerprint "$OCI_CLI_KEY") + _sig_host="dns.$OCI_CLI_REGION.oraclecloud.com" + _sig_keyId="$OCI_CLI_TENANCY/$OCI_CLI_USER/$_key_fingerprint" _sig_alg="rsa-sha256" _sig_version="1" _sig_now="$(LC_ALL=C \date -u "+%a, %d %h %Y %H:%M:%S GMT")" - if [ "$OCI_KEY_PASSPHRASE" ]; then - export OCI_KEY_PASSPHRASE="$OCI_KEY_PASSPHRASE" - _sig_passinArg="-passin env:OCI_KEY_PASSPHRASE" - fi - _request_method=$(printf %s "$_sig_method" | _lower_case) _curl_method=$(printf %s "$_sig_method" | _upper_case) @@ -198,7 +196,7 @@ _signed_request() { if [ "$_sig_body" ]; then _secure_debug3 _sig_body "$_sig_body" - _sig_body_sha256="x-content-sha256: $(printf %s "$_sig_body" | openssl dgst -binary -sha256 | openssl enc -e -base64)" + _sig_body_sha256="x-content-sha256: $(printf %s "$_sig_body" | _digest sha256)" _sig_body_type="content-type: application/json" _sig_body_length="content-length: ${#_sig_body}" _string_to_sign="$_string_to_sign\n$_sig_body_sha256\n$_sig_body_type\n$_sig_body_length" @@ -207,10 +205,8 @@ _signed_request() { _tmp_file=$(_mktemp) if [ -f "$_tmp_file" ]; then - printf '%s' "$OCI_PRIVATE_KEY" >"$_tmp_file" - # Double quoting the file and passphrase breaks openssl - # shellcheck disable=SC2086 - _signature=$(printf '%b' "$_string_to_sign" | openssl dgst -sha256 -sign $_tmp_file $_sig_passinArg | openssl enc -e -base64 | tr -d '\r\n') + printf '%s' "$OCI_CLI_KEY" >"$_tmp_file" + _signature=$(printf '%b' "$_string_to_sign" | _sign "$_tmp_file" sha256 | tr -d '\r\n') rm -f "$_tmp_file" fi From bdc0f74d006455040f27f4ee55ca22aaef7e041a Mon Sep 17 00:00:00 2001 From: Avi Miller Date: Sat, 19 Jun 2021 15:41:34 +1000 Subject: [PATCH 240/304] fix: add missing else/return 1 to if block Signed-off-by: Avi Miller --- dnsapi/dns_oci.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dnsapi/dns_oci.sh b/dnsapi/dns_oci.sh index 1c75b99f..1380f4d4 100644 --- a/dnsapi/dns_oci.sh +++ b/dnsapi/dns_oci.sh @@ -30,6 +30,8 @@ dns_oci_add() { _err "Error: failed to add TXT record for ${_sub_domain}.${_domain}." return 1 fi + else + return 1 fi else @@ -53,6 +55,8 @@ dns_oci_rm() { _err "Error: failed to remove TXT record for ${_sub_domain}.${_domain}." return 1 fi + else + return 1 fi else From 55681f9fdd4a1adf46f9e01fb5a791be5ffd3fd7 Mon Sep 17 00:00:00 2001 From: Avi Miller Date: Sun, 20 Jun 2021 09:06:21 +1000 Subject: [PATCH 241/304] feat: enable automatic configuration from an OCI configuration file The individual parameters can still be overridden via the corresponding OCI_CLI environment variable. Signed-off-by: Avi Miller --- dnsapi/dns_oci.sh | 133 +++++++++++++++++++++++++++++++++------------- 1 file changed, 96 insertions(+), 37 deletions(-) diff --git a/dnsapi/dns_oci.sh b/dnsapi/dns_oci.sh index 1380f4d4..4d013578 100644 --- a/dnsapi/dns_oci.sh +++ b/dnsapi/dns_oci.sh @@ -3,7 +3,10 @@ # Acme.sh DNS API plugin for Oracle Cloud Infrastructure # Copyright (c) 2021, Oracle and/or its affiliates # -# Required OCI CLI environment variables: +# The plugin will automatically use the default profile from an OCI SDK and CLI +# configuration file, if it exists. +# +# Alternatively, set the following environment variables: # - OCI_CLI_TENANCY : OCID of tenancy that contains the target DNS zone # - OCI_CLI_USER : OCID of user with permission to add/remove records from zones # - OCI_CLI_REGION : Should point to the tenancy home region @@ -19,18 +22,15 @@ dns_oci_add() { _fqdn="$1" _rdata="$2" - if _oci_config; then - - if [ "$_sub_domain" ] && [ "$_domain" ]; then - _add_record_body="{\"items\":[{\"domain\":\"${_sub_domain}.${_domain}\",\"rdata\":\"$_rdata\",\"rtype\":\"TXT\",\"ttl\": 30,\"operation\":\"ADD\"}]}" - response=$(_signed_request "PATCH" "/20180115/zones/${_domain}/records" "$_add_record_body") - if [ "$response" ]; then - _info "Success: added TXT record for ${_sub_domain}.${_domain}." - else - _err "Error: failed to add TXT record for ${_sub_domain}.${_domain}." - return 1 - fi + if _get_oci_zone; then + + _add_record_body="{\"items\":[{\"domain\":\"${_sub_domain}.${_domain}\",\"rdata\":\"$_rdata\",\"rtype\":\"TXT\",\"ttl\": 30,\"operation\":\"ADD\"}]}" + response=$(_signed_request "PATCH" "/20180115/zones/${_domain}/records" "$_add_record_body") + if [ "$response" ]; then + _info "Success: added TXT record for ${_sub_domain}.${_domain}." else + _err "Error: failed to add TXT record for ${_sub_domain}.${_domain}." + _err "Check that the user has permission to add records to this zone." return 1 fi @@ -44,18 +44,15 @@ dns_oci_rm() { _fqdn="$1" _rdata="$2" - if _oci_config; then - - if [ "$_sub_domain" ] && [ "$_domain" ]; then - _remove_record_body="{\"items\":[{\"domain\":\"${_sub_domain}.${_domain}\",\"rdata\":\"$_rdata\",\"rtype\":\"TXT\",\"operation\":\"REMOVE\"}]}" - response=$(_signed_request "PATCH" "/20180115/zones/${_domain}/records" "$_remove_record_body") - if [ "$response" ]; then - _info "Success: removed TXT record for ${_sub_domain}.${_domain}." - else - _err "Error: failed to remove TXT record for ${_sub_domain}.${_domain}." - return 1 - fi + if _get_oci_zone; then + + _remove_record_body="{\"items\":[{\"domain\":\"${_sub_domain}.${_domain}\",\"rdata\":\"$_rdata\",\"rtype\":\"TXT\",\"operation\":\"REMOVE\"}]}" + response=$(_signed_request "PATCH" "/20180115/zones/${_domain}/records" "$_remove_record_body") + if [ "$response" ]; then + _info "Success: removed TXT record for ${_sub_domain}.${_domain}." else + _err "Error: failed to remove TXT record for ${_sub_domain}.${_domain}." + _err "Check that the user has permission to remove records from this zone." return 1 fi @@ -66,12 +63,41 @@ dns_oci_rm() { } #################### Private functions below ################################## +_get_oci_zone() { + + if ! _oci_config; then + return 1 + fi + + if ! _get_zone "$_fqdn"; then + _err "Error: DNS Zone not found for $_fqdn in $OCI_CLI_TENANCY" + return 1 + fi + + return 0 + +} + _oci_config() { - OCI_CLI_TENANCY="${OCI_CLI_TENANCY:-$(_readaccountconf_mutable OCI_CLI_TENANCY)}" - OCI_CLI_USER="${OCI_CLI_USER:-$(_readaccountconf_mutable OCI_CLI_USER)}" - OCI_CLI_KEY="${OCI_CLI_KEY:-$(_readaccountconf_mutable OCI_CLI_KEY)}" - OCI_CLI_REGION="${OCI_CLI_REGION:-$(_readaccountconf_mutable OCI_CLI_REGION)}" + OCI_CLI_CONFIG_FILE="${OCI_CLI_CONFIG_FILE:-$HOME/.oci/config}" + OCI_CLI_PROFILE="${OCI_CLI_PROFILE:-DEFAULT}" + + # Let's try and find the values automagically first + # But still let any environment variables take precendence + if [ -f "$OCI_CLI_CONFIG_FILE" ]; then + _info "Reading OCI configuration file: $(_green "$OCI_CLI_CONFIG_FILE")" + OCI_CLI_TENANCY="${OCI_CLI_TENANCY:-$(_read_oci_config tenancy)}" + OCI_CLI_USER="${OCI_CLI_USER:-$(_read_oci_config user)}" + OCI_CLI_KEY_FILE="${OCI_CLI_KEY_FILE:-$(_read_oci_config key_file)}" + OCI_CLI_REGION="${OCI_CLI_REGION:-$(_read_oci_config region)}" + else + OCI_CLI_TENANCY="${OCI_CLI_TENANCY:-$(_readaccountconf_mutable OCI_CLI_TENANCY)}" + OCI_CLI_USER="${OCI_CLI_USER:-$(_readaccountconf_mutable OCI_CLI_USER)}" + OCI_CLI_KEY="${OCI_CLI_KEY:-$(_readaccountconf_mutable OCI_CLI_KEY)}" + OCI_CLI_REGION="${OCI_CLI_REGION:-$(_readaccountconf_mutable OCI_CLI_REGION)}" + _save_config="true" + fi _not_set="" _ret=0 @@ -85,7 +111,7 @@ _oci_config() { if [ -f "$OCI_CLI_KEY_FILE" ]; then OCI_CLI_KEY=$(_base64 <"$OCI_CLI_KEY_FILE") else - _err "Fatal: unable to read $OCI_CLI_KEY_FILE." + _err "Fatal: unable to read key file: $OCI_CLI_KEY_FILE" return 1 fi fi @@ -106,21 +132,20 @@ _oci_config() { _err "Fatal: required environment variable(s): ${_not_set} not set." _ret=1 else - _saveaccountconf_mutable OCI_CLI_TENANCY "$OCI_CLI_TENANCY" - _saveaccountconf_mutable OCI_CLI_USER "$OCI_CLI_USER" - _saveaccountconf_mutable OCI_CLI_KEY "$OCI_CLI_KEY" - _saveaccountconf_mutable OCI_CLI_REGION "$OCI_CLI_REGION" + if [ "$_save_config" ]; then + _saveaccountconf_mutable OCI_CLI_TENANCY "$OCI_CLI_TENANCY" + _saveaccountconf_mutable OCI_CLI_USER "$OCI_CLI_USER" + _saveaccountconf_mutable OCI_CLI_KEY "$OCI_CLI_KEY" + _saveaccountconf_mutable OCI_CLI_REGION "$OCI_CLI_REGION" + else + _info "Success: OCI configuration retrieved from $OCI_CLI_CONFIG_FILE." + fi fi if ! _contains "PRIVATE KEY" "$OCI_CLI_KEY"; then OCI_CLI_KEY=$(printf "%s" "$OCI_CLI_KEY" | _dbase64 multiline) fi - if ! _get_zone "$_fqdn"; then - _err "Error: DNS Zone not found for $_fqdn." - _ret=1 - fi - return $_ret } @@ -244,3 +269,37 @@ _signed_request() { return $_ret } + +# file key [section] +_read_oci_config() { + _key="$1" + + _start_n=$(grep -n '\['"$OCI_CLI_PROFILE"']' "$OCI_CLI_CONFIG_FILE" | cut -d : -f 1) + _debug2 _start_n "$_start_n" + if [ -z "$_start_n" ]; then + _err "Can not find section: $OCI_CLI_PROFILE" + return 1 + fi + + _start_nn=$(_math "$_start_n" + 1) + _debug2 "_start_nn" "$_start_nn" + + _left="$(sed -n "${_start_nn},99999p" "$OCI_CLI_CONFIG_FILE")" + _debug2 _left "$_left" + _end="$(echo "$_left" | grep -n "^\[" | _head_n 1)" + _debug2 "_end" "$_end" + if [ "$_end" ]; then + _end_n=$(echo "$_end" | cut -d : -f 1) + _debug "_end_n" "$_end_n" + _seg_n=$(echo "$_left" | sed -n "1,${_end_n}p") + else + _seg_n="$_left" + fi + + _debug2 "_seg_n" "$_seg_n" + _lineini="$(echo "$_seg_n" | grep "^ *$_key *= *")" + + _debug2 "_lineini" "$_lineini" + printf "%b" "$(eval "echo $_lineini | sed -e \"s/${_key}[[:space:]]*=[[:space:]]*//g\"")" + +} From 35d4617009c4842a640e84c8b1fc36c646ed40a4 Mon Sep 17 00:00:00 2001 From: Avi Miller Date: Sun, 20 Jun 2021 13:12:14 +1000 Subject: [PATCH 242/304] fix: revert _readini() function to be more generic Also switched [::space::] with a literal space for better cross-platform compatibility. Signed-off-by: Avi Miller --- dnsapi/dns_oci.sh | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/dnsapi/dns_oci.sh b/dnsapi/dns_oci.sh index 4d013578..1666c5a7 100644 --- a/dnsapi/dns_oci.sh +++ b/dnsapi/dns_oci.sh @@ -83,14 +83,14 @@ _oci_config() { OCI_CLI_CONFIG_FILE="${OCI_CLI_CONFIG_FILE:-$HOME/.oci/config}" OCI_CLI_PROFILE="${OCI_CLI_PROFILE:-DEFAULT}" - # Let's try and find the values automagically first - # But still let any environment variables take precendence + # Read the configuration from either the default or specified config file + # Override the config file value with the environment variable value (if set) if [ -f "$OCI_CLI_CONFIG_FILE" ]; then - _info "Reading OCI configuration file: $(_green "$OCI_CLI_CONFIG_FILE")" - OCI_CLI_TENANCY="${OCI_CLI_TENANCY:-$(_read_oci_config tenancy)}" - OCI_CLI_USER="${OCI_CLI_USER:-$(_read_oci_config user)}" - OCI_CLI_KEY_FILE="${OCI_CLI_KEY_FILE:-$(_read_oci_config key_file)}" - OCI_CLI_REGION="${OCI_CLI_REGION:-$(_read_oci_config region)}" + _info "Reading OCI configuration file: $OCI_CLI_CONFIG_FILE" + OCI_CLI_TENANCY="${OCI_CLI_TENANCY:-$(_readini tenancy "$OCI_CLI_CONFIG_FILE" "$OCI_CLI_PROFILE")}" + OCI_CLI_USER="${OCI_CLI_USER:-$(_readini user "$OCI_CLI_CONFIG_FILE" "$OCI_CLI_PROFILE")}" + OCI_CLI_KEY_FILE="${OCI_CLI_KEY_FILE:-$(_readini key_file "$OCI_CLI_CONFIG_FILE" "$OCI_CLI_PROFILE")}" + OCI_CLI_REGION="${OCI_CLI_REGION:-$(_readini region "$OCI_CLI_CONFIG_FILE" "$OCI_CLI_PROFILE")}" else OCI_CLI_TENANCY="${OCI_CLI_TENANCY:-$(_readaccountconf_mutable OCI_CLI_TENANCY)}" OCI_CLI_USER="${OCI_CLI_USER:-$(_readaccountconf_mutable OCI_CLI_USER)}" @@ -271,20 +271,22 @@ _signed_request() { } # file key [section] -_read_oci_config() { +_readini() { _key="$1" + _file="$2" + _section="${3:-DEFAULT}" - _start_n=$(grep -n '\['"$OCI_CLI_PROFILE"']' "$OCI_CLI_CONFIG_FILE" | cut -d : -f 1) + _start_n=$(grep -n '\['"$_section"']' "$_file" | cut -d : -f 1) _debug2 _start_n "$_start_n" if [ -z "$_start_n" ]; then - _err "Can not find section: $OCI_CLI_PROFILE" + _err "Can not find section: $_section" return 1 fi _start_nn=$(_math "$_start_n" + 1) _debug2 "_start_nn" "$_start_nn" - _left="$(sed -n "${_start_nn},99999p" "$OCI_CLI_CONFIG_FILE")" + _left="$(sed -n "${_start_nn},99999p" "$_file")" _debug2 _left "$_left" _end="$(echo "$_left" | grep -n "^\[" | _head_n 1)" _debug2 "_end" "$_end" @@ -300,6 +302,6 @@ _read_oci_config() { _lineini="$(echo "$_seg_n" | grep "^ *$_key *= *")" _debug2 "_lineini" "$_lineini" - printf "%b" "$(eval "echo $_lineini | sed -e \"s/${_key}[[:space:]]*=[[:space:]]*//g\"")" + printf "%b" "$(eval "echo $_lineini | sed -e \"s/^ *${_key} *= *//g\"")" } From 38bf164979fad2951c3f73438d310b7a929325ef Mon Sep 17 00:00:00 2001 From: Avi Miller Date: Sun, 20 Jun 2021 14:38:24 +1000 Subject: [PATCH 243/304] fix: refactor the way the config is read from file and envvars The plugin will use the following order of precedence: environment value > file value > default value See the wiki for details on environment variable names. Signed-off-by: Avi Miller --- dnsapi/dns_oci.sh | 127 ++++++++++++++++++++++++++-------------------- 1 file changed, 73 insertions(+), 54 deletions(-) diff --git a/dnsapi/dns_oci.sh b/dnsapi/dns_oci.sh index 1666c5a7..c27023e2 100644 --- a/dnsapi/dns_oci.sh +++ b/dnsapi/dns_oci.sh @@ -80,76 +80,93 @@ _get_oci_zone() { _oci_config() { - OCI_CLI_CONFIG_FILE="${OCI_CLI_CONFIG_FILE:-$HOME/.oci/config}" - OCI_CLI_PROFILE="${OCI_CLI_PROFILE:-DEFAULT}" - - # Read the configuration from either the default or specified config file - # Override the config file value with the environment variable value (if set) - if [ -f "$OCI_CLI_CONFIG_FILE" ]; then - _info "Reading OCI configuration file: $OCI_CLI_CONFIG_FILE" - OCI_CLI_TENANCY="${OCI_CLI_TENANCY:-$(_readini tenancy "$OCI_CLI_CONFIG_FILE" "$OCI_CLI_PROFILE")}" - OCI_CLI_USER="${OCI_CLI_USER:-$(_readini user "$OCI_CLI_CONFIG_FILE" "$OCI_CLI_PROFILE")}" - OCI_CLI_KEY_FILE="${OCI_CLI_KEY_FILE:-$(_readini key_file "$OCI_CLI_CONFIG_FILE" "$OCI_CLI_PROFILE")}" - OCI_CLI_REGION="${OCI_CLI_REGION:-$(_readini region "$OCI_CLI_CONFIG_FILE" "$OCI_CLI_PROFILE")}" - else - OCI_CLI_TENANCY="${OCI_CLI_TENANCY:-$(_readaccountconf_mutable OCI_CLI_TENANCY)}" - OCI_CLI_USER="${OCI_CLI_USER:-$(_readaccountconf_mutable OCI_CLI_USER)}" - OCI_CLI_KEY="${OCI_CLI_KEY:-$(_readaccountconf_mutable OCI_CLI_KEY)}" - OCI_CLI_REGION="${OCI_CLI_REGION:-$(_readaccountconf_mutable OCI_CLI_REGION)}" - _save_config="true" + _DEFAULT_OCI_CLI_CONFIG_FILE="$HOME/.oci/config" + OCI_CLI_CONFIG_FILE="${OCI_CLI_CONFIG_FILE:-$(_readaccountconf_mutable OCI_CLI_CONFIG_FILE)}" + + if [ -z "$OCI_CLI_CONFIG_FILE" ]; then + OCI_CLI_CONFIG_FILE="$_DEFAULT_OCI_CLI_CONFIG_FILE" fi - _not_set="" - _ret=0 + if [ "$_DEFAULT_OCI_CLI_CONFIG_FILE" != "$OCI_CLI_CONFIG_FILE" ]; then + _saveaccountconf_mutable OCI_CLI_CONFIG_FILE "$OCI_CLI_CONFIG_FILE" + else + _clearaccountconf_mutable OCI_CLI_CONFIG_FILE + fi - if [ -z "$OCI_CLI_KEY_FILE" ] && [ -z "$OCI_CLI_KEY" ]; then - _err "Fatal: you must provide a value for either OCI_CLI_KEY_FILE or OCI_CLI_KEY." - return 1 + _DEFAULT_OCI_CLI_PROFILE="DEFAULT" + OCI_CLI_PROFILE="${OCI_CLI_PROFILE:-$(_readaccountconf_mutable OCI_CLI_PROFILE)}" + if [ "$_DEFAULT_OCI_CLI_PROFILE" != "$OCI_CLI_PROFILE" ]; then + _saveaccountconf_mutable OCI_CLI_PROFILE "$OCI_CLI_PROFILE" + else + OCI_CLI_PROFILE="$_DEFAULT_OCI_CLI_PROFILE" + _clearaccountconf_mutable OCI_CLI_PROFILE fi - if [ "$OCI_CLI_KEY_FILE" ] && [ -z "$OCI_CLI_KEY" ]; then - if [ -f "$OCI_CLI_KEY_FILE" ]; then - OCI_CLI_KEY=$(_base64 <"$OCI_CLI_KEY_FILE") - else - _err "Fatal: unable to read key file: $OCI_CLI_KEY_FILE" - return 1 - fi + OCI_CLI_TENANCY="${OCI_CLI_TENANCY:-$(_readaccountconf_mutable OCI_CLI_TENANCY)}" + if [ "$OCI_CLI_TENANCY" ]; then + _saveaccountconf_mutable OCI_CLI_TENANCY "$OCI_CLI_TENANCY" + elif [ -f "$OCI_CLI_CONFIG_FILE" ]; then + _debug "Reading OCI_CLI_TENANCY value from: $OCI_CLI_CONFIG_FILE" + OCI_CLI_TENANCY="${OCI_CLI_TENANCY:-$(_readini "$OCI_CLI_CONFIG_FILE" tenancy "$OCI_CLI_PROFILE")}" fi if [ -z "$OCI_CLI_TENANCY" ]; then - _not_set="${_not_set}OCI_CLI_TENANCY " + _err "Error: unable to read OCI_CLI_TENANCY from config file or environment variable." + return 1 fi + OCI_CLI_USER="${OCI_CLI_USER:-$(_readaccountconf_mutable OCI_CLI_USER)}" + if [ "$OCI_CLI_USER" ]; then + _saveaccountconf_mutable OCI_CLI_USER "$OCI_CLI_USER" + elif [ -f "$OCI_CLI_CONFIG_FILE" ]; then + _debug "Reading OCI_CLI_USER value from: $OCI_CLI_CONFIG_FILE" + OCI_CLI_USER="${OCI_CLI_USER:-$(_readini "$OCI_CLI_CONFIG_FILE" user "$OCI_CLI_PROFILE")}" + fi if [ -z "$OCI_CLI_USER" ]; then - _not_set="${_not_set}OCI_CLI_USER " + _err "Error: unable to read OCI_CLI_USER from config file or environment variable." + return 1 fi + OCI_CLI_REGION="${OCI_CLI_REGION:-$(_readaccountconf_mutable OCI_CLI_REGION)}" + if [ "$OCI_CLI_REGION" ]; then + _saveaccountconf_mutable OCI_CLI_REGION "$OCI_CLI_REGION" + elif [ -f "$OCI_CLI_CONFIG_FILE" ]; then + _debug "Reading OCI_CLI_REGION value from: $OCI_CLI_CONFIG_FILE" + OCI_CLI_REGION="${OCI_CLI_REGION:-$(_readini "$OCI_CLI_CONFIG_FILE" region "$OCI_CLI_PROFILE")}" + fi if [ -z "$OCI_CLI_REGION" ]; then - _not_set="${_not_set}OCI_CLI_REGION " + _err "Error: unable to read OCI_CLI_REGION from config file or environment variable." + return 1 fi - if [ "$_not_set" ]; then - _err "Fatal: required environment variable(s): ${_not_set} not set." - _ret=1 - else - if [ "$_save_config" ]; then - _saveaccountconf_mutable OCI_CLI_TENANCY "$OCI_CLI_TENANCY" - _saveaccountconf_mutable OCI_CLI_USER "$OCI_CLI_USER" + OCI_CLI_KEY="${OCI_CLI_KEY:-$(_readaccountconf_mutable OCI_CLI_KEY)}" + if [ -z "$OCI_CLI_KEY" ]; then + _clearaccountconf_mutable OCI_CLI_KEY + OCI_CLI_KEY_FILE="${OCI_CLI_KEY_FILE:-$(_readini "$OCI_CLI_CONFIG_FILE" key_file "$OCI_CLI_PROFILE")}" + if [ "$OCI_CLI_KEY_FILE" ] && [ -f "$OCI_CLI_KEY_FILE" ]; then + _debug "Reading OCI_CLI_KEY value from: $OCI_CLI_KEY_FILE" + OCI_CLI_KEY=$(_base64 <"$OCI_CLI_KEY_FILE") _saveaccountconf_mutable OCI_CLI_KEY "$OCI_CLI_KEY" - _saveaccountconf_mutable OCI_CLI_REGION "$OCI_CLI_REGION" - else - _info "Success: OCI configuration retrieved from $OCI_CLI_CONFIG_FILE." fi + else + _saveaccountconf_mutable OCI_CLI_KEY "$OCI_CLI_KEY" + fi + + if [ -z "$OCI_CLI_KEY_FILE" ] && [ -z "$OCI_CLI_KEY" ]; then + _err "Error: unable to find key file path in OCI config file or OCI_CLI_KEY_FILE." + _err "Error: unable to load private API signing key from OCI_CLI_KEY." + return 1 fi - if ! _contains "PRIVATE KEY" "$OCI_CLI_KEY"; then + if [ "$(printf "%s\n" "$OCI_CLI_KEY" | wc -l)" -eq 1 ]; then OCI_CLI_KEY=$(printf "%s" "$OCI_CLI_KEY" | _dbase64 multiline) fi - return $_ret + return 0 } + # _get_zone(): retrieves the Zone name and OCID # # _sub_domain=_acme-challenge.www @@ -189,6 +206,7 @@ _get_zone() { #Usage: privatekey #Output MD5 fingerprint _fingerprint() { + pkey="$1" if [ -z "$pkey" ]; then _usage "Usage: _fingerprint privkey" @@ -272,36 +290,37 @@ _signed_request() { # file key [section] _readini() { - _key="$1" - _file="$2" + _file="$1" + _key="$2" _section="${3:-DEFAULT}" _start_n=$(grep -n '\['"$_section"']' "$_file" | cut -d : -f 1) - _debug2 _start_n "$_start_n" + _debug3 _start_n "$_start_n" if [ -z "$_start_n" ]; then _err "Can not find section: $_section" return 1 fi _start_nn=$(_math "$_start_n" + 1) - _debug2 "_start_nn" "$_start_nn" + _debug3 "_start_nn" "$_start_nn" _left="$(sed -n "${_start_nn},99999p" "$_file")" - _debug2 _left "$_left" + _debug3 _left "$_left" _end="$(echo "$_left" | grep -n "^\[" | _head_n 1)" - _debug2 "_end" "$_end" + _debug3 "_end" "$_end" if [ "$_end" ]; then _end_n=$(echo "$_end" | cut -d : -f 1) - _debug "_end_n" "$_end_n" + _debug3 "_end_n" "$_end_n" _seg_n=$(echo "$_left" | sed -n "1,${_end_n}p") else _seg_n="$_left" fi - _debug2 "_seg_n" "$_seg_n" + _debug3 "_seg_n" "$_seg_n" _lineini="$(echo "$_seg_n" | grep "^ *$_key *= *")" + _inivalue="$(printf "%b" "$(eval "echo $_lineini | sed \"s/^ *${_key} *= *//g\"")")" + _debug2 _inivalue "$_inivalue" + echo "$_inivalue" - _debug2 "_lineini" "$_lineini" - printf "%b" "$(eval "echo $_lineini | sed -e \"s/^ *${_key} *= *//g\"")" } From 7d1ffd439de5cacecba77186e6cea012e60badd0 Mon Sep 17 00:00:00 2001 From: Avi Miller Date: Sun, 20 Jun 2021 17:07:04 +1000 Subject: [PATCH 244/304] fix: fix a format issue reported by shellfmt Signed-off-by: Avi Miller --- dnsapi/dns_oci.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/dnsapi/dns_oci.sh b/dnsapi/dns_oci.sh index c27023e2..eb006120 100644 --- a/dnsapi/dns_oci.sh +++ b/dnsapi/dns_oci.sh @@ -166,7 +166,6 @@ _oci_config() { } - # _get_zone(): retrieves the Zone name and OCID # # _sub_domain=_acme-challenge.www @@ -322,5 +321,4 @@ _readini() { _debug2 _inivalue "$_inivalue" echo "$_inivalue" - } From 5563ff2a5f9453dd95eee1fefc3c63efab9e6f20 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 20 Jun 2021 16:57:58 +0800 Subject: [PATCH 245/304] minor --- .github/workflows/LetsEncrypt.yml | 11 +++-------- .github/workflows/Linux.yml | 12 ++++-------- .github/workflows/PebbleStrict.yml | 4 ++-- 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index b579d6e9..5986290d 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -4,20 +4,15 @@ on: branches: - '*' paths: - - '**.sh' + - '*.sh' - '**.yml' - - '!dnsapi/**' - - '!deploy/**' - - '!notify/**' + pull_request: branches: - dev paths: - - '**.sh' + - '*.sh' - '**.yml' - - '!dnsapi/**' - - '!deploy/**' - - '!notify/**' jobs: diff --git a/.github/workflows/Linux.yml b/.github/workflows/Linux.yml index 3e1d3cf8..6d4dcf7c 100644 --- a/.github/workflows/Linux.yml +++ b/.github/workflows/Linux.yml @@ -4,20 +4,16 @@ on: branches: - '*' paths: - - '**.sh' + - '*.sh' - '**.yml' - - '!dnsapi/**' - - '!deploy/**' - - '!notify/**' + pull_request: branches: - dev paths: - - '**.sh' + - '*.sh' - '**.yml' - - '!dnsapi/**' - - '!deploy/**' - - '!notify/**' + jobs: diff --git a/.github/workflows/PebbleStrict.yml b/.github/workflows/PebbleStrict.yml index 976e5373..fee41feb 100644 --- a/.github/workflows/PebbleStrict.yml +++ b/.github/workflows/PebbleStrict.yml @@ -4,13 +4,13 @@ on: branches: - '*' paths: - - '**.sh' + - '*.sh' - '**.yml' pull_request: branches: - dev paths: - - '**.sh' + - '*.sh' - '**.yml' jobs: From dd2060e105f7a9c8e9cb9215099cfd96baf3857c Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 21 Jun 2021 20:11:15 +0800 Subject: [PATCH 246/304] fix for compatibility to sslcom --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 6cea6648..3c8ef299 100755 --- a/acme.sh +++ b/acme.sh @@ -1210,7 +1210,7 @@ _createcsr() { _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")" From 08055a57a6fc3e28983ff943cb51be05b5cb522a Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 21 Jun 2021 21:31:00 +0800 Subject: [PATCH 247/304] support SSL.com --- README.md | 1 + acme.sh | 33 ++++++++++++++++++++++++++------- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index c1c3a3c4..88373193 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ https://github.com/acmesh-official/acmetest - [ZeroSSL.com CA](https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA)(default) - Letsencrypt.org CA - [BuyPass.com CA](https://github.com/acmesh-official/acme.sh/wiki/BuyPass.com-CA) +- [SSL.com CA](https://github.com/acmesh-official/acme.sh/wiki/SSL.com-CA) - [Pebble strict Mode](https://github.com/letsencrypt/pebble) - Any other [RFC8555](https://tools.ietf.org/html/rfc8555)-compliant CA diff --git a/acme.sh b/acme.sh index 3c8ef299..0f2578f8 100755 --- a/acme.sh +++ b/acme.sh @@ -29,18 +29,24 @@ CA_BUYPASS_TEST="https://api.test4.buypass.no/acme/directory" CA_ZEROSSL="https://acme.zerossl.com/v2/DV90" _ZERO_EAB_ENDPOINT="http://api.zerossl.com/acme/eab-credentials-email" + +CA_SSLCOM_RSA="https://acme.ssl.com/sslcom-dv-rsa" +CA_SSLCOM_ECC="https://acme.ssl.com/sslcom-dv-ecc" + + 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)" @@ -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" +_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" @@ -2617,7 +2625,13 @@ _initpath() { _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" + if [ -z "$_ACME_SERVER_PATH" ] || [ "$_ACME_SERVER_PATH" = "directory" ]; then + CA_DIR="$CA_HOME/$_ACME_SERVER_HOST" + else + CA_DIR="$CA_HOME/$_ACME_SERVER_HOST/$_ACME_SERVER_PATH" + fi _DEFAULT_CA_CONF="$CA_DIR/ca.conf" @@ -6640,9 +6654,10 @@ _checkSudo() { return 0 } -#server +#server #keylength _selectServer() { _server="$1" + _skeylength="$2" _server_lower="$(echo "$_server" | _lower_case)" _sindex=0 for snames in $CA_NAMES; do @@ -6653,6 +6668,9 @@ _selectServer() { 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 @@ -6884,7 +6902,6 @@ _process() { ;; --server) _server="$2" - _selectServer "$_server" shift ;; --debug) @@ -6983,7 +7000,6 @@ _process() { Le_DNSSleep="$_dnssleep" shift ;; - --keylength | -k) _keylength="$2" shift @@ -6992,7 +7008,6 @@ _process() { _accountkeylength="$2" shift ;; - --cert-file | --certpath) _cert_file="$2" shift @@ -7256,6 +7271,10 @@ _process() { shift 1 done + if [ "$_server" ]; then + _selectServer "$_server" "${_ecc-:$_keylength}" + fi + if [ "${_CMD}" != "install" ]; then if [ "$__INTERACTIVE" ] && ! _checkSudo; then if [ -z "$FORCE" ]; then From 9117cb62e38ce332201c3564010665f9a929ae0c Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 21 Jun 2021 21:41:56 +0800 Subject: [PATCH 248/304] typo --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 0f2578f8..361df9d9 100755 --- a/acme.sh +++ b/acme.sh @@ -7272,7 +7272,7 @@ _process() { done if [ "$_server" ]; then - _selectServer "$_server" "${_ecc-:$_keylength}" + _selectServer "$_server" "${_ecc:-$_keylength}" fi if [ "${_CMD}" != "install" ]; then From 6ac5d93e020a8c072075cf98e39fa4cda8f3df45 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 21 Jun 2021 22:29:14 +0800 Subject: [PATCH 249/304] fix format --- acme.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/acme.sh b/acme.sh index 361df9d9..b82798f6 100755 --- a/acme.sh +++ b/acme.sh @@ -29,11 +29,9 @@ CA_BUYPASS_TEST="https://api.test4.buypass.no/acme/directory" CA_ZEROSSL="https://acme.zerossl.com/v2/DV90" _ZERO_EAB_ENDPOINT="http://api.zerossl.com/acme/eab-credentials-email" - CA_SSLCOM_RSA="https://acme.ssl.com/sslcom-dv-rsa" CA_SSLCOM_ECC="https://acme.ssl.com/sslcom-dv-ecc" - DEFAULT_CA=$CA_ZEROSSL DEFAULT_STAGING_CA=$CA_LETSENCRYPT_V2_TEST From 810911e0efbec31dc6032a7d37eb15b9dc879121 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 21 Jun 2021 22:47:22 +0800 Subject: [PATCH 250/304] move ca key path --- acme.sh | 79 ++++++++++++++++++++++----------------------------------- 1 file changed, 31 insertions(+), 48 deletions(-) diff --git a/acme.sh b/acme.sh index b82798f6..da3f397c 100755 --- a/acme.sh +++ b/acme.sh @@ -2625,19 +2625,44 @@ _initpath() { _ACME_SERVER_PATH="$(echo "$ACME_DIRECTORY" | cut -d : -f 2- | tr -s / | cut -d / -f 3-)" _debug2 "_ACME_SERVER_PATH" "$_ACME_SERVER_PATH" - if [ -z "$_ACME_SERVER_PATH" ] || [ "$_ACME_SERVER_PATH" = "directory" ]; then - CA_DIR="$CA_HOME/$_ACME_SERVER_HOST" - else - CA_DIR="$CA_HOME/$_ACME_SERVER_HOST/$_ACME_SERVER_PATH" - fi + 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 @@ -2658,19 +2683,6 @@ _initpath() { 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" @@ -3503,15 +3515,6 @@ _regAccount() { _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 @@ -3649,16 +3652,6 @@ _regAccount() { 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 @@ -3701,16 +3694,6 @@ updateaccount() { 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 From eb0d7a2a20ef02f596ba8ff5e79e19045c171638 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 21 Jun 2021 22:59:14 +0800 Subject: [PATCH 251/304] fix format --- acme.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/acme.sh b/acme.sh index da3f397c..420fdbc3 100755 --- a/acme.sh +++ b/acme.sh @@ -2638,7 +2638,6 @@ _initpath() { _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 @@ -2662,7 +2661,6 @@ _initpath() { mv "$_OLD_CA_CONF" "$CA_CONF" fi - if [ -f "$CA_CONF" ]; then . "$CA_CONF" fi From 8e789b23c8835d8131b3eb8e0bde2d212ac6fee7 Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 22 Jun 2021 07:48:37 +0800 Subject: [PATCH 252/304] split in to multiple files, so that it can pass more. --- .github/workflows/FreeBSD.yml | 60 +++++++++ .github/workflows/LetsEncrypt.yml | 215 ------------------------------ .github/workflows/MacOS.yml | 52 ++++++++ .github/workflows/Solaris.yml | 58 ++++++++ .github/workflows/Ubuntu.yml | 52 ++++++++ .github/workflows/Windows.yml | 70 ++++++++++ 6 files changed, 292 insertions(+), 215 deletions(-) create mode 100644 .github/workflows/FreeBSD.yml delete mode 100644 .github/workflows/LetsEncrypt.yml create mode 100644 .github/workflows/MacOS.yml create mode 100644 .github/workflows/Solaris.yml create mode 100644 .github/workflows/Ubuntu.yml create mode 100644 .github/workflows/Windows.yml diff --git a/.github/workflows/FreeBSD.yml b/.github/workflows/FreeBSD.yml new file mode 100644 index 00000000..dd80a0b9 --- /dev/null +++ b/.github/workflows/FreeBSD.yml @@ -0,0 +1,60 @@ +name: FreeBSD +on: + push: + branches: + - '*' + paths: + - '*.sh' + - '**.yml' + + pull_request: + branches: + - dev + paths: + - '*.sh' + - '**.yml' + + +jobs: + FreeBSD: + strategy: + matrix: + include: + - TEST_ACME_Server: "" + CA_ECDSA: "" + CA: "" + CA_EMAIL: "" + - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" + CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" + CA: "ZeroSSL RSA Domain Secure Site CA" + CA_EMAIL: "githubtest@acme.sh" + runs-on: macos-latest + env: + TEST_LOCAL: 1 + ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} + CA_ECDSA: ${{ matrix.CA_ECDSA }} + CA: ${{ matrix.CA }} + CA_EMAIL: ${{ matrix.CA_EMAIL }} + steps: + - uses: actions/checkout@v2 + - uses: vmactions/cf-tunnel@v0.0.2 + id: tunnel + with: + protocol: http + port: 8080 + - name: Set envs + run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV + - name: Clone acmetest + run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ + - uses: vmactions/freebsd-vm@v0.1.4 + with: + envs: 'TEST_LOCAL TestingDomain ACME_DIRECTORY CA_ECDSA CA CA_EMAIL' + nat: | + "8080": "80" + prepare: pkg install -y socat curl + usesh: true + run: | + cd ../acmetest \ + && ./letest.sh + + diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml deleted file mode 100644 index 5986290d..00000000 --- a/.github/workflows/LetsEncrypt.yml +++ /dev/null @@ -1,215 +0,0 @@ -name: LetsEncrypt -on: - push: - branches: - - '*' - paths: - - '*.sh' - - '**.yml' - - pull_request: - branches: - - dev - paths: - - '*.sh' - - '**.yml' - - -jobs: - Ubuntu: - strategy: - matrix: - include: - - TEST_ACME_Server: "" - CA_ECDSA: "" - CA: "" - CA_EMAIL: "" - - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" - CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" - CA: "ZeroSSL RSA Domain Secure Site CA" - CA_EMAIL: "githubtest@acme.sh" - runs-on: ubuntu-latest - env: - TEST_LOCAL: 1 - ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} - CA_ECDSA: ${{ matrix.CA_ECDSA }} - CA: ${{ matrix.CA }} - CA_EMAIL: ${{ matrix.CA_EMAIL }} - steps: - - uses: actions/checkout@v2 - - name: Install tools - run: sudo apt-get install -y socat - - name: Clone acmetest - run: | - cd .. \ - && git clone https://github.com/acmesh-official/acmetest.git \ - && cp -r acme.sh acmetest/ - - name: Run acmetest - run: | - cd ../acmetest \ - && sudo --preserve-env ./letest.sh - - MacOS: - strategy: - matrix: - include: - - TEST_ACME_Server: "" - CA_ECDSA: "" - CA: "" - CA_EMAIL: "" - - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" - CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" - CA: "ZeroSSL RSA Domain Secure Site CA" - CA_EMAIL: "githubtest@acme.sh" - runs-on: macos-latest - env: - TEST_LOCAL: 1 - ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} - CA_ECDSA: ${{ matrix.CA_ECDSA }} - CA: ${{ matrix.CA }} - CA_EMAIL: ${{ matrix.CA_EMAIL }} - steps: - - uses: actions/checkout@v2 - - name: Install tools - run: brew install socat - - name: Clone acmetest - run: | - cd .. \ - && git clone https://github.com/acmesh-official/acmetest.git \ - && cp -r acme.sh acmetest/ - - name: Run acmetest - run: | - cd ../acmetest \ - && sudo --preserve-env ./letest.sh - - Windows: - strategy: - matrix: - include: - - TEST_ACME_Server: "" - CA_ECDSA: "" - CA: "" - CA_EMAIL: "" - - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" - CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" - CA: "ZeroSSL RSA Domain Secure Site CA" - CA_EMAIL: "githubtest@acme.sh" - runs-on: windows-latest - env: - ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} - CA_ECDSA: ${{ matrix.CA_ECDSA }} - CA: ${{ matrix.CA }} - CA_EMAIL: ${{ matrix.CA_EMAIL }} - TEST_LOCAL: 1 - #The 80 port is used by Windows server, we have to use a custom port, tunnel will also use this port. - Le_HTTPPort: 8888 - steps: - - name: Set git to use LF - run: | - git config --global core.autocrlf false - - uses: actions/checkout@v2 - - name: Install cygwin base packages with chocolatey - run: | - choco config get cacheLocation - choco install --no-progress cygwin - shell: cmd - - name: Install cygwin additional packages - run: | - C:\tools\cygwin\cygwinsetup.exe -qgnNdO -R C:/tools/cygwin -s http://mirrors.kernel.org/sourceware/cygwin/ -P socat,curl,cron,unzip,git - shell: cmd - - name: Set ENV - shell: cmd - run: | - echo PATH=C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin >> %GITHUB_ENV% - - name: Check ENV - shell: cmd - run: | - echo "PATH=%PATH%" - - name: Clone acmetest - shell: cmd - run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - name: Run acmetest - shell: cmd - run: cd ../acmetest && bash.exe -c ./letest.sh - - FreeBSD: - strategy: - matrix: - include: - - TEST_ACME_Server: "" - CA_ECDSA: "" - CA: "" - CA_EMAIL: "" - - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" - CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" - CA: "ZeroSSL RSA Domain Secure Site CA" - CA_EMAIL: "githubtest@acme.sh" - runs-on: macos-latest - env: - TEST_LOCAL: 1 - ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} - CA_ECDSA: ${{ matrix.CA_ECDSA }} - CA: ${{ matrix.CA }} - CA_EMAIL: ${{ matrix.CA_EMAIL }} - steps: - - uses: actions/checkout@v2 - - uses: vmactions/cf-tunnel@v0.0.2 - id: tunnel - with: - protocol: http - port: 8080 - - name: Set envs - run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV - - name: Clone acmetest - run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.1.4 - with: - envs: 'TEST_LOCAL TestingDomain ACME_DIRECTORY CA_ECDSA CA CA_EMAIL' - nat: | - "8080": "80" - prepare: pkg install -y socat curl - usesh: true - run: | - cd ../acmetest \ - && ./letest.sh - - Solaris: - strategy: - matrix: - include: - - TEST_ACME_Server: "" - CA_ECDSA: "" - CA: "" - CA_EMAIL: "" - - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" - CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" - CA: "ZeroSSL RSA Domain Secure Site CA" - CA_EMAIL: "githubtest@acme.sh" - runs-on: macos-latest - env: - TEST_LOCAL: 1 - ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} - CA_ECDSA: ${{ matrix.CA_ECDSA }} - CA: ${{ matrix.CA }} - CA_EMAIL: ${{ matrix.CA_EMAIL }} - steps: - - uses: actions/checkout@v2 - - uses: vmactions/cf-tunnel@v0.0.2 - id: tunnel - with: - protocol: http - port: 8080 - - name: Set envs - run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV - - name: Clone acmetest - run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/solaris-vm@v0.0.3 - with: - envs: 'TEST_LOCAL TestingDomain ACME_DIRECTORY CA_ECDSA CA CA_EMAIL' - nat: | - "8080": "80" - prepare: pkgutil -y -i socat curl - run: | - cd ../acmetest \ - && ./letest.sh - diff --git a/.github/workflows/MacOS.yml b/.github/workflows/MacOS.yml new file mode 100644 index 00000000..b03bec0c --- /dev/null +++ b/.github/workflows/MacOS.yml @@ -0,0 +1,52 @@ +name: MacOS +on: + push: + branches: + - '*' + paths: + - '*.sh' + - '**.yml' + + pull_request: + branches: + - dev + paths: + - '*.sh' + - '**.yml' + + +jobs: + MacOS: + strategy: + matrix: + include: + - TEST_ACME_Server: "" + CA_ECDSA: "" + CA: "" + CA_EMAIL: "" + - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" + CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" + CA: "ZeroSSL RSA Domain Secure Site CA" + CA_EMAIL: "githubtest@acme.sh" + runs-on: macos-latest + env: + TEST_LOCAL: 1 + ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} + CA_ECDSA: ${{ matrix.CA_ECDSA }} + CA: ${{ matrix.CA }} + CA_EMAIL: ${{ matrix.CA_EMAIL }} + steps: + - uses: actions/checkout@v2 + - name: Install tools + run: brew install socat + - name: Clone acmetest + run: | + cd .. \ + && git clone https://github.com/acmesh-official/acmetest.git \ + && cp -r acme.sh acmetest/ + - name: Run acmetest + run: | + cd ../acmetest \ + && sudo --preserve-env ./letest.sh + + diff --git a/.github/workflows/Solaris.yml b/.github/workflows/Solaris.yml new file mode 100644 index 00000000..ad976f59 --- /dev/null +++ b/.github/workflows/Solaris.yml @@ -0,0 +1,58 @@ +name: Solaris +on: + push: + branches: + - '*' + paths: + - '*.sh' + - '**.yml' + + pull_request: + branches: + - dev + paths: + - '*.sh' + - '**.yml' + + +jobs: + Solaris: + strategy: + matrix: + include: + - TEST_ACME_Server: "" + CA_ECDSA: "" + CA: "" + CA_EMAIL: "" + - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" + CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" + CA: "ZeroSSL RSA Domain Secure Site CA" + CA_EMAIL: "githubtest@acme.sh" + runs-on: macos-latest + env: + TEST_LOCAL: 1 + ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} + CA_ECDSA: ${{ matrix.CA_ECDSA }} + CA: ${{ matrix.CA }} + CA_EMAIL: ${{ matrix.CA_EMAIL }} + steps: + - uses: actions/checkout@v2 + - uses: vmactions/cf-tunnel@v0.0.2 + id: tunnel + with: + protocol: http + port: 8080 + - name: Set envs + run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV + - name: Clone acmetest + run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ + - uses: vmactions/solaris-vm@v0.0.3 + with: + envs: 'TEST_LOCAL TestingDomain ACME_DIRECTORY CA_ECDSA CA CA_EMAIL' + nat: | + "8080": "80" + prepare: pkgutil -y -i socat curl + run: | + cd ../acmetest \ + && ./letest.sh + diff --git a/.github/workflows/Ubuntu.yml b/.github/workflows/Ubuntu.yml new file mode 100644 index 00000000..1ec50189 --- /dev/null +++ b/.github/workflows/Ubuntu.yml @@ -0,0 +1,52 @@ +name: Ubuntu +on: + push: + branches: + - '*' + paths: + - '*.sh' + - '**.yml' + + pull_request: + branches: + - dev + paths: + - '*.sh' + - '**.yml' + + +jobs: + Ubuntu: + strategy: + matrix: + include: + - TEST_ACME_Server: "" + CA_ECDSA: "" + CA: "" + CA_EMAIL: "" + - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" + CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" + CA: "ZeroSSL RSA Domain Secure Site CA" + CA_EMAIL: "githubtest@acme.sh" + runs-on: ubuntu-latest + env: + TEST_LOCAL: 1 + ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} + CA_ECDSA: ${{ matrix.CA_ECDSA }} + CA: ${{ matrix.CA }} + CA_EMAIL: ${{ matrix.CA_EMAIL }} + steps: + - uses: actions/checkout@v2 + - name: Install tools + run: sudo apt-get install -y socat + - name: Clone acmetest + run: | + cd .. \ + && git clone https://github.com/acmesh-official/acmetest.git \ + && cp -r acme.sh acmetest/ + - name: Run acmetest + run: | + cd ../acmetest \ + && sudo --preserve-env ./letest.sh + + diff --git a/.github/workflows/Windows.yml b/.github/workflows/Windows.yml new file mode 100644 index 00000000..0219eaa5 --- /dev/null +++ b/.github/workflows/Windows.yml @@ -0,0 +1,70 @@ +name: Windows +on: + push: + branches: + - '*' + paths: + - '*.sh' + - '**.yml' + + pull_request: + branches: + - dev + paths: + - '*.sh' + - '**.yml' + + +jobs: + Windows: + strategy: + matrix: + include: + - TEST_ACME_Server: "" + CA_ECDSA: "" + CA: "" + CA_EMAIL: "" + - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" + CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" + CA: "ZeroSSL RSA Domain Secure Site CA" + CA_EMAIL: "githubtest@acme.sh" + runs-on: windows-latest + env: + ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} + CA_ECDSA: ${{ matrix.CA_ECDSA }} + CA: ${{ matrix.CA }} + CA_EMAIL: ${{ matrix.CA_EMAIL }} + TEST_LOCAL: 1 + #The 80 port is used by Windows server, we have to use a custom port, tunnel will also use this port. + Le_HTTPPort: 8888 + steps: + - name: Set git to use LF + run: | + git config --global core.autocrlf false + - uses: actions/checkout@v2 + - name: Install cygwin base packages with chocolatey + run: | + choco config get cacheLocation + choco install --no-progress cygwin + shell: cmd + - name: Install cygwin additional packages + run: | + C:\tools\cygwin\cygwinsetup.exe -qgnNdO -R C:/tools/cygwin -s http://mirrors.kernel.org/sourceware/cygwin/ -P socat,curl,cron,unzip,git + shell: cmd + - name: Set ENV + shell: cmd + run: | + echo PATH=C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin >> %GITHUB_ENV% + - name: Check ENV + shell: cmd + run: | + echo "PATH=%PATH%" + - name: Clone acmetest + shell: cmd + run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ + - name: Run acmetest + shell: cmd + run: cd ../acmetest && bash.exe -c ./letest.sh + + + From 3ba70095ecefb2f39734110a4752233baf79ee62 Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 22 Jun 2021 07:55:12 +0800 Subject: [PATCH 253/304] update status --- README.md | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 88373193..805b1c2c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ # An ACME Shell script: acme.sh -![LetsEncrypt](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg) +[![FreeBSD](https://github.com/acmesh-official/acme.sh/actions/workflows/FreeBSD.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/FreeBSD.yml) +[![MacOS](https://github.com/acmesh-official/acme.sh/actions/workflows/MacOS.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/MacOS.yml) +[![Ubuntu](https://github.com/acmesh-official/acme.sh/actions/workflows/Ubuntu.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Ubuntu.yml) +[![Windows](https://github.com/acmesh-official/acme.sh/actions/workflows/Windows.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Windows.yml) +[![Solaris](https://github.com/acmesh-official/acme.sh/actions/workflows/Solaris.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Solaris.yml) ![Shellcheck](https://github.com/acmesh-official/acme.sh/workflows/Shellcheck/badge.svg) ![PebbleStrict](https://github.com/acmesh-official/acme.sh/workflows/PebbleStrict/badge.svg) ![DockerHub](https://github.com/acmesh-official/acme.sh/workflows/Build%20DockerHub/badge.svg) @@ -57,11 +61,11 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa) | NO | Status| Platform| |----|-------|---------| -|1|[![MacOS](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|Mac OSX -|2|[![Windows](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|Windows (cygwin with curl, openssl and crontab included) -|3|[![FreeBSD](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|FreeBSD -|4|[![Solaris](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|Solaris -|5|[![Ubuntu](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)| Ubuntu +|1|[![MacOS](https://github.com/acmesh-official/acme.sh/actions/workflows/MacOS.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/MacOS.yml)|Mac OSX +|2|[![Windows](https://github.com/acmesh-official/acme.sh/actions/workflows/Windows.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Windows.yml)|Windows (cygwin with curl, openssl and crontab included) +|3|[![FreeBSD](https://github.com/acmesh-official/acme.sh/actions/workflows/FreeBSD.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/FreeBSD.yml)FreeBSD +|4|[![Solaris](https://github.com/acmesh-official/acme.sh/actions/workflows/Solaris.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Solaris.yml)Solaris +|5|[![Ubuntu](https://github.com/acmesh-official/acme.sh/actions/workflows/Ubuntu.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Ubuntu.yml)| Ubuntu |6|NA|pfsense |7|NA|OpenBSD |8|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)| Debian @@ -73,11 +77,12 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa) |14|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Kali Linux |15|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Oracle Linux |16|[![](https://acmesh-official.github.io/acmetest/status/proxmox.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Proxmox: See Proxmox VE Wiki. Version [4.x, 5.0, 5.1](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x,_5.0_and_5.1)#Let.27s_Encrypt_using_acme.sh), version [5.2 and up](https://pve.proxmox.com/wiki/Certificate_Management) -|17|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111 -|18|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Mageia -|19|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT) -|20|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Gentoo Linux -|21|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|ClearLinux +|17|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Mageia +|18|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Gentoo Linux +|19|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|ClearLinux +|20|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111 +|21|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT) + Check our [testing project](https://github.com/acmesh-official/acmetest): From 16378ab1c2f4dae9f4f52d2dc63b4066d32dce62 Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 22 Jun 2021 07:59:02 +0800 Subject: [PATCH 254/304] minor --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 805b1c2c..132a375a 100644 --- a/README.md +++ b/README.md @@ -63,8 +63,8 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa) |----|-------|---------| |1|[![MacOS](https://github.com/acmesh-official/acme.sh/actions/workflows/MacOS.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/MacOS.yml)|Mac OSX |2|[![Windows](https://github.com/acmesh-official/acme.sh/actions/workflows/Windows.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Windows.yml)|Windows (cygwin with curl, openssl and crontab included) -|3|[![FreeBSD](https://github.com/acmesh-official/acme.sh/actions/workflows/FreeBSD.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/FreeBSD.yml)FreeBSD -|4|[![Solaris](https://github.com/acmesh-official/acme.sh/actions/workflows/Solaris.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Solaris.yml)Solaris +|3|[![FreeBSD](https://github.com/acmesh-official/acme.sh/actions/workflows/FreeBSD.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/FreeBSD.yml)|FreeBSD +|4|[![Solaris](https://github.com/acmesh-official/acme.sh/actions/workflows/Solaris.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Solaris.yml)|Solaris |5|[![Ubuntu](https://github.com/acmesh-official/acme.sh/actions/workflows/Ubuntu.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Ubuntu.yml)| Ubuntu |6|NA|pfsense |7|NA|OpenBSD @@ -76,12 +76,12 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa) |13|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|fedora |14|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Kali Linux |15|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Oracle Linux -|16|[![](https://acmesh-official.github.io/acmetest/status/proxmox.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Proxmox: See Proxmox VE Wiki. Version [4.x, 5.0, 5.1](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x,_5.0_and_5.1)#Let.27s_Encrypt_using_acme.sh), version [5.2 and up](https://pve.proxmox.com/wiki/Certificate_Management) -|17|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Mageia -|18|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Gentoo Linux -|19|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|ClearLinux -|20|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111 -|21|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT) +|16|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Mageia +|17|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Gentoo Linux +|18|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|ClearLinux +|19|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111 +|20|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT) +|21|[![](https://acmesh-official.github.io/acmetest/status/proxmox.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Proxmox: See Proxmox VE Wiki. Version [4.x, 5.0, 5.1](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x,_5.0_and_5.1)#Let.27s_Encrypt_using_acme.sh), version [5.2 and up](https://pve.proxmox.com/wiki/Certificate_Management) Check our [testing project](https://github.com/acmesh-official/acmetest): From f5b350f144c8f8d9560291a31d400a5e2db83767 Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 22 Jun 2021 20:39:00 +0800 Subject: [PATCH 255/304] fix for list short name --- README.md | 1 + acme.sh | 3 +++ 2 files changed, 4 insertions(+) diff --git a/README.md b/README.md index 132a375a..c7f7e677 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ [![Ubuntu](https://github.com/acmesh-official/acme.sh/actions/workflows/Ubuntu.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Ubuntu.yml) [![Windows](https://github.com/acmesh-official/acme.sh/actions/workflows/Windows.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Windows.yml) [![Solaris](https://github.com/acmesh-official/acme.sh/actions/workflows/Solaris.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Solaris.yml) + ![Shellcheck](https://github.com/acmesh-official/acme.sh/workflows/Shellcheck/badge.svg) ![PebbleStrict](https://github.com/acmesh-official/acme.sh/workflows/PebbleStrict/badge.svg) ![DockerHub](https://github.com/acmesh-official/acme.sh/workflows/Build%20DockerHub/badge.svg) diff --git a/acme.sh b/acme.sh index 420fdbc3..75a9d719 100755 --- a/acme.sh +++ b/acme.sh @@ -6667,6 +6667,9 @@ _getCAShortName() { 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 From 5535bb4cf835357c9d3ff0e021027920dc71c6a0 Mon Sep 17 00:00:00 2001 From: Habetdin <15926758+Habetdin@users.noreply.github.com> Date: Wed, 23 Jun 2021 03:20:07 +0300 Subject: [PATCH 256/304] Fix special characters escaping To escape characters '_', '*', '`', '[' outside of an entity, prepend the characters '\' before them. --- notify/telegram.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notify/telegram.sh b/notify/telegram.sh index d16f3a98..454b4146 100644 --- a/notify/telegram.sh +++ b/notify/telegram.sh @@ -27,7 +27,7 @@ telegram_send() { fi _saveaccountconf_mutable TELEGRAM_BOT_CHATID "$TELEGRAM_BOT_CHATID" - _content="$(printf "%s" "$_content" | sed -e 's/*/\\\\*/')" + _content="$(printf "%s" "$_content" | sed -e 's/\([_*`\[]\)/\\\\\1/g')" _content="$(printf "*%s*\n%s" "$_subject" "$_content" | _json_encode)" _data="{\"text\": \"$_content\", " _data="$_data\"chat_id\": \"$TELEGRAM_BOT_CHATID\", " From f22aa744cc96440881fd020990aeb79f2e96131f Mon Sep 17 00:00:00 2001 From: Benoit Garret Date: Tue, 27 Apr 2021 16:03:40 +0200 Subject: [PATCH 257/304] Add Consul deploy hook --- deploy/consul.sh | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 deploy/consul.sh diff --git a/deploy/consul.sh b/deploy/consul.sh new file mode 100644 index 00000000..97aad380 --- /dev/null +++ b/deploy/consul.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env sh + +# Here is a script to deploy cert to hashicorp consul using curl +# (https://www.consul.io/) +# +# it requires following environment variables: +# +# CONSUL_PREFIX - this contains the prefix path in consul +# CONSUL_HTTP_ADDR - consul requires this to find your consul server +# +# additionally, you need to ensure that CONSUL_HTTP_TOKEN is available +# to access the consul server + +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +consul_deploy() { + + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + + # validate required env vars + _getdeployconf CONSUL_PREFIX + if [ -z "$CONSUL_PREFIX" ]; then + _err "CONSUL_PREFIX needs to be defined (contains prefix path in vault)" + return 1 + fi + _savedeployconf CONSUL_PREFIX "$CONSUL_PREFIX" + + _getdeployconf CONSUL_HTTP_ADDR + if [ -z "$CONSUL_HTTP_ADDR" ]; then + _err "CONSUL_HTTP_ADDR needs to be defined (contains consul connection address)" + return 1 + fi + _savedeployconf CONSUL_HTTP_ADDR "$CONSUL_HTTP_ADDR" + + CONSUL_CMD=$(command -v consul) + + # force CLI, but the binary does not exist => error + if [ -n "$USE_CLI" ] && [ -z "$CONSUL_CMD" ]; then + _err "Cannot find the consul binary!" + return 1 + fi + + # use the CLI first + if [ -n "$USE_CLI" ] || [ -n "$CONSUL_CMD" ]; then + _info "Found consul binary, deploying with CLI" + consul_deploy_cli "$CONSUL_CMD" "$CONSUL_PREFIX" + else + _info "Did not find consul binary, deploying with API" + consul_deploy_api "$CONSUL_HTTP_ADDR" "$CONSUL_PREFIX" "$CONSUL_HTTP_TOKEN" + fi +} + +consul_deploy_api() { + CONSUL_HTTP_ADDR="$1" + CONSUL_PREFIX="$2" + CONSUL_HTTP_TOKEN="$3" + + URL="$CONSUL_HTTP_ADDR/v1/kv/$CONSUL_PREFIX" + export _H1="X-Consul-Token: $CONSUL_HTTP_TOKEN" + + if [ -n "$FABIO" ]; then + _post "$(cat "$_cfullchain")" "$URL/${_cdomain}-cert.pem" '' "PUT" || return 1 + _post "$(cat "$_ckey")" "$URL/${_cdomain}-key.pem" '' "PUT" || return 1 + else + _post "$(cat "$_ccert")" "$URL/${_cdomain}/cert.pem" '' "PUT" || return 1 + _post "$(cat "$_ckey")" "$URL/${_cdomain}/cert.key" '' "PUT" || return 1 + _post "$(cat "$_cca")" "$URL/${_cdomain}/chain.pem" '' "PUT" || return 1 + _post "$(cat "$_cfullchain")" "$URL/${_cdomain}/fullchain.pem" '' "PUT" || return 1 + fi +} + +consul_deploy_cli() { + CONSUL_CMD="$1" + CONSUL_PREFIX="$2" + + if [ -n "$FABIO" ]; then + $CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}-cert.pem" @"$_cfullchain" || return 1 + $CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}-key.pem" @"$_ckey" || return 1 + else + $CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}/cert.pem" value=@"$_ccert" || return 1 + $CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}/cert.key" value=@"$_ckey" || return 1 + $CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}/chain.pem" value=@"$_cca" || return 1 + $CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}/fullchain.pem" value=@"$_cfullchain" || return 1 + fi +} From 468244e650efdf860d785786d054f6d9a8b5ee1a Mon Sep 17 00:00:00 2001 From: Benoit Garret Date: Fri, 7 May 2021 12:12:30 +0200 Subject: [PATCH 258/304] Fix the shfmt check --- deploy/consul.sh | 142 +++++++++++++++++++++++------------------------ 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/deploy/consul.sh b/deploy/consul.sh index 97aad380..f93fb452 100644 --- a/deploy/consul.sh +++ b/deploy/consul.sh @@ -18,81 +18,81 @@ #domain keyfile certfile cafile fullchain consul_deploy() { - _cdomain="$1" - _ckey="$2" - _ccert="$3" - _cca="$4" - _cfullchain="$5" - - _debug _cdomain "$_cdomain" - _debug _ckey "$_ckey" - _debug _ccert "$_ccert" - _debug _cca "$_cca" - _debug _cfullchain "$_cfullchain" - - # validate required env vars - _getdeployconf CONSUL_PREFIX - if [ -z "$CONSUL_PREFIX" ]; then - _err "CONSUL_PREFIX needs to be defined (contains prefix path in vault)" - return 1 - fi - _savedeployconf CONSUL_PREFIX "$CONSUL_PREFIX" - - _getdeployconf CONSUL_HTTP_ADDR - if [ -z "$CONSUL_HTTP_ADDR" ]; then - _err "CONSUL_HTTP_ADDR needs to be defined (contains consul connection address)" - return 1 - fi - _savedeployconf CONSUL_HTTP_ADDR "$CONSUL_HTTP_ADDR" - - CONSUL_CMD=$(command -v consul) - - # force CLI, but the binary does not exist => error - if [ -n "$USE_CLI" ] && [ -z "$CONSUL_CMD" ]; then - _err "Cannot find the consul binary!" - return 1 - fi - - # use the CLI first - if [ -n "$USE_CLI" ] || [ -n "$CONSUL_CMD" ]; then - _info "Found consul binary, deploying with CLI" - consul_deploy_cli "$CONSUL_CMD" "$CONSUL_PREFIX" - else - _info "Did not find consul binary, deploying with API" - consul_deploy_api "$CONSUL_HTTP_ADDR" "$CONSUL_PREFIX" "$CONSUL_HTTP_TOKEN" - fi + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + + # validate required env vars + _getdeployconf CONSUL_PREFIX + if [ -z "$CONSUL_PREFIX" ]; then + _err "CONSUL_PREFIX needs to be defined (contains prefix path in vault)" + return 1 + fi + _savedeployconf CONSUL_PREFIX "$CONSUL_PREFIX" + + _getdeployconf CONSUL_HTTP_ADDR + if [ -z "$CONSUL_HTTP_ADDR" ]; then + _err "CONSUL_HTTP_ADDR needs to be defined (contains consul connection address)" + return 1 + fi + _savedeployconf CONSUL_HTTP_ADDR "$CONSUL_HTTP_ADDR" + + CONSUL_CMD=$(command -v consul) + + # force CLI, but the binary does not exist => error + if [ -n "$USE_CLI" ] && [ -z "$CONSUL_CMD" ]; then + _err "Cannot find the consul binary!" + return 1 + fi + + # use the CLI first + if [ -n "$USE_CLI" ] || [ -n "$CONSUL_CMD" ]; then + _info "Found consul binary, deploying with CLI" + consul_deploy_cli "$CONSUL_CMD" "$CONSUL_PREFIX" + else + _info "Did not find consul binary, deploying with API" + consul_deploy_api "$CONSUL_HTTP_ADDR" "$CONSUL_PREFIX" "$CONSUL_HTTP_TOKEN" + fi } consul_deploy_api() { - CONSUL_HTTP_ADDR="$1" - CONSUL_PREFIX="$2" - CONSUL_HTTP_TOKEN="$3" - - URL="$CONSUL_HTTP_ADDR/v1/kv/$CONSUL_PREFIX" - export _H1="X-Consul-Token: $CONSUL_HTTP_TOKEN" - - if [ -n "$FABIO" ]; then - _post "$(cat "$_cfullchain")" "$URL/${_cdomain}-cert.pem" '' "PUT" || return 1 - _post "$(cat "$_ckey")" "$URL/${_cdomain}-key.pem" '' "PUT" || return 1 - else - _post "$(cat "$_ccert")" "$URL/${_cdomain}/cert.pem" '' "PUT" || return 1 - _post "$(cat "$_ckey")" "$URL/${_cdomain}/cert.key" '' "PUT" || return 1 - _post "$(cat "$_cca")" "$URL/${_cdomain}/chain.pem" '' "PUT" || return 1 - _post "$(cat "$_cfullchain")" "$URL/${_cdomain}/fullchain.pem" '' "PUT" || return 1 - fi + CONSUL_HTTP_ADDR="$1" + CONSUL_PREFIX="$2" + CONSUL_HTTP_TOKEN="$3" + + URL="$CONSUL_HTTP_ADDR/v1/kv/$CONSUL_PREFIX" + export _H1="X-Consul-Token: $CONSUL_HTTP_TOKEN" + + if [ -n "$FABIO" ]; then + _post "$(cat "$_cfullchain")" "$URL/${_cdomain}-cert.pem" '' "PUT" || return 1 + _post "$(cat "$_ckey")" "$URL/${_cdomain}-key.pem" '' "PUT" || return 1 + else + _post "$(cat "$_ccert")" "$URL/${_cdomain}/cert.pem" '' "PUT" || return 1 + _post "$(cat "$_ckey")" "$URL/${_cdomain}/cert.key" '' "PUT" || return 1 + _post "$(cat "$_cca")" "$URL/${_cdomain}/chain.pem" '' "PUT" || return 1 + _post "$(cat "$_cfullchain")" "$URL/${_cdomain}/fullchain.pem" '' "PUT" || return 1 + fi } consul_deploy_cli() { - CONSUL_CMD="$1" - CONSUL_PREFIX="$2" - - if [ -n "$FABIO" ]; then - $CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}-cert.pem" @"$_cfullchain" || return 1 - $CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}-key.pem" @"$_ckey" || return 1 - else - $CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}/cert.pem" value=@"$_ccert" || return 1 - $CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}/cert.key" value=@"$_ckey" || return 1 - $CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}/chain.pem" value=@"$_cca" || return 1 - $CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}/fullchain.pem" value=@"$_cfullchain" || return 1 - fi + CONSUL_CMD="$1" + CONSUL_PREFIX="$2" + + if [ -n "$FABIO" ]; then + $CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}-cert.pem" @"$_cfullchain" || return 1 + $CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}-key.pem" @"$_ckey" || return 1 + else + $CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}/cert.pem" value=@"$_ccert" || return 1 + $CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}/cert.key" value=@"$_ckey" || return 1 + $CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}/chain.pem" value=@"$_cca" || return 1 + $CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}/fullchain.pem" value=@"$_cfullchain" || return 1 + fi } From fa29233c91eedfb24a10d65f1aba974b460a8521 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 24 Jun 2021 20:35:49 +0800 Subject: [PATCH 259/304] add retry for init api --- acme.sh | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/acme.sh b/acme.sh index 75a9d719..aea94003 100755 --- a/acme.sh +++ b/acme.sh @@ -2540,12 +2540,18 @@ _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 for: $_api_server." - 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" @@ -2578,8 +2584,12 @@ _initAPI() { _debug "ACME_REVOKE_CERT" "$ACME_REVOKE_CERT" _debug "ACME_AGREEMENT" "$ACME_AGREEMENT" _debug "ACME_NEW_NONCE" "$ACME_NEW_NONCE" - - fi + if [ "$ACME_KEY_CHANGE" ] && [ "$ACME_NEW_AUTHZ" ] && [ "$ACME_NEW_ORDEW_ACCOUNT" ] && [ "$ACME_REVOR" ] && [ "$ACME_NEKE_CERT" ]; then + return 0 + fi + done + _err "Can not init api, for $_api_server" + return 1 } #[domain] [keylength or isEcc flag] From f3aab68a130eb30ba6290acd1c68c32b0bf267ad Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 24 Jun 2021 20:45:15 +0800 Subject: [PATCH 260/304] remove unnecessary check --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index aea94003..26c7bb0e 100755 --- a/acme.sh +++ b/acme.sh @@ -2584,7 +2584,7 @@ _initAPI() { _debug "ACME_REVOKE_CERT" "$ACME_REVOKE_CERT" _debug "ACME_AGREEMENT" "$ACME_AGREEMENT" _debug "ACME_NEW_NONCE" "$ACME_NEW_NONCE" - if [ "$ACME_KEY_CHANGE" ] && [ "$ACME_NEW_AUTHZ" ] && [ "$ACME_NEW_ORDEW_ACCOUNT" ] && [ "$ACME_REVOR" ] && [ "$ACME_NEKE_CERT" ]; then + if [ "$ACME_NEW_ACCOUNT" ] && [ "$ACME_NEW_ORDER" ]; then return 0 fi done From beec3f6fc9419f8180137492e2adc75ba58d468f Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 24 Jun 2021 22:03:00 +0800 Subject: [PATCH 261/304] add buypass test --- .github/workflows/Ubuntu.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/Ubuntu.yml b/.github/workflows/Ubuntu.yml index 1ec50189..c8ceffc7 100644 --- a/.github/workflows/Ubuntu.yml +++ b/.github/workflows/Ubuntu.yml @@ -28,6 +28,10 @@ jobs: CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" CA: "ZeroSSL RSA Domain Secure Site CA" CA_EMAIL: "githubtest@acme.sh" + - TEST_ACME_Server: "https://api.test4.buypass.no/acme/directory" + CA_ECDSA: "Buypass Class 2 Test4 CA 5" + CA: "Buypass Class 2 Test4 CA 5" + CA_EMAIL: "githubtest@acme.sh" runs-on: ubuntu-latest env: TEST_LOCAL: 1 From 934fd77d0ef702826fe2cf3af28c3302ff503fbb Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 24 Jun 2021 22:05:43 +0800 Subject: [PATCH 262/304] fix error --- .github/workflows/Ubuntu.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Ubuntu.yml b/.github/workflows/Ubuntu.yml index c8ceffc7..4113738f 100644 --- a/.github/workflows/Ubuntu.yml +++ b/.github/workflows/Ubuntu.yml @@ -28,7 +28,7 @@ jobs: CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" CA: "ZeroSSL RSA Domain Secure Site CA" CA_EMAIL: "githubtest@acme.sh" - - TEST_ACME_Server: "https://api.test4.buypass.no/acme/directory" + - TEST_ACME_Server: "https://api.test4.buypass.no/acme/directory" CA_ECDSA: "Buypass Class 2 Test4 CA 5" CA: "Buypass Class 2 Test4 CA 5" CA_EMAIL: "githubtest@acme.sh" From f88d6a155b7a464a9052817317c9ad32cf4eb923 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 24 Jun 2021 23:21:10 +0800 Subject: [PATCH 263/304] fix initapi --- acme.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/acme.sh b/acme.sh index 26c7bb0e..f728e537 100755 --- a/acme.sh +++ b/acme.sh @@ -2587,6 +2587,8 @@ _initAPI() { if [ "$ACME_NEW_ACCOUNT" ] && [ "$ACME_NEW_ORDER" ]; then return 0 fi + _info "Sleep $_sleep_retry_sec and retry." + _sleep "$_sleep_retry_sec" done _err "Can not init api, for $_api_server" return 1 From ff69be6029102a0645bb859a5b056c1b0d6e5874 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 24 Jun 2021 23:23:46 +0800 Subject: [PATCH 264/304] fix error --- .github/workflows/Ubuntu.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Ubuntu.yml b/.github/workflows/Ubuntu.yml index 4113738f..cddf14b5 100644 --- a/.github/workflows/Ubuntu.yml +++ b/.github/workflows/Ubuntu.yml @@ -28,7 +28,7 @@ jobs: CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" CA: "ZeroSSL RSA Domain Secure Site CA" CA_EMAIL: "githubtest@acme.sh" - - TEST_ACME_Server: "https://api.test4.buypass.no/acme/directory" + - TEST_ACME_Server: "https://api.test4.buypass.no/acme/directory" CA_ECDSA: "Buypass Class 2 Test4 CA 5" CA: "Buypass Class 2 Test4 CA 5" CA_EMAIL: "githubtest@acme.sh" From 88b7710ff56f320d941c99ed86786b57d5a69b21 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 24 Jun 2021 23:30:16 +0800 Subject: [PATCH 265/304] fix path filter --- .github/workflows/FreeBSD.yml | 2 +- .github/workflows/Linux.yml | 2 +- .github/workflows/MacOS.yml | 2 +- .github/workflows/PebbleStrict.yml | 2 +- .github/workflows/Solaris.yml | 2 +- .github/workflows/Ubuntu.yml | 2 +- .github/workflows/Windows.yml | 2 +- .github/workflows/dockerhub.yml | 5 +++++ .github/workflows/shellcheck.yml | 2 +- 9 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.github/workflows/FreeBSD.yml b/.github/workflows/FreeBSD.yml index dd80a0b9..8b6d4aa5 100644 --- a/.github/workflows/FreeBSD.yml +++ b/.github/workflows/FreeBSD.yml @@ -5,7 +5,7 @@ on: - '*' paths: - '*.sh' - - '**.yml' + - '.github/workflows/FreeBSD.yml' pull_request: branches: diff --git a/.github/workflows/Linux.yml b/.github/workflows/Linux.yml index 6d4dcf7c..a3cf1c59 100644 --- a/.github/workflows/Linux.yml +++ b/.github/workflows/Linux.yml @@ -12,7 +12,7 @@ on: - dev paths: - '*.sh' - - '**.yml' + - '.github/workflows/Linux.yml' diff --git a/.github/workflows/MacOS.yml b/.github/workflows/MacOS.yml index b03bec0c..e12ef8e2 100644 --- a/.github/workflows/MacOS.yml +++ b/.github/workflows/MacOS.yml @@ -12,7 +12,7 @@ on: - dev paths: - '*.sh' - - '**.yml' + - '.github/workflows/MacOS.yml' jobs: diff --git a/.github/workflows/PebbleStrict.yml b/.github/workflows/PebbleStrict.yml index fee41feb..15795367 100644 --- a/.github/workflows/PebbleStrict.yml +++ b/.github/workflows/PebbleStrict.yml @@ -11,7 +11,7 @@ on: - dev paths: - '*.sh' - - '**.yml' + - '.github/workflows/PebbleStrict.yml' jobs: PebbleStrict: diff --git a/.github/workflows/Solaris.yml b/.github/workflows/Solaris.yml index ad976f59..3f2adb6a 100644 --- a/.github/workflows/Solaris.yml +++ b/.github/workflows/Solaris.yml @@ -12,7 +12,7 @@ on: - dev paths: - '*.sh' - - '**.yml' + - '.github/workflows/Solaris.yml' jobs: diff --git a/.github/workflows/Ubuntu.yml b/.github/workflows/Ubuntu.yml index cddf14b5..dc704c04 100644 --- a/.github/workflows/Ubuntu.yml +++ b/.github/workflows/Ubuntu.yml @@ -12,7 +12,7 @@ on: - dev paths: - '*.sh' - - '**.yml' + - '.github/workflows/Ubuntu.yml' jobs: diff --git a/.github/workflows/Windows.yml b/.github/workflows/Windows.yml index 0219eaa5..ed73641f 100644 --- a/.github/workflows/Windows.yml +++ b/.github/workflows/Windows.yml @@ -12,7 +12,7 @@ on: - dev paths: - '*.sh' - - '**.yml' + - '.github/workflows/Windows.yml' jobs: diff --git a/.github/workflows/dockerhub.yml b/.github/workflows/dockerhub.yml index 238fde3a..0c3aec0a 100644 --- a/.github/workflows/dockerhub.yml +++ b/.github/workflows/dockerhub.yml @@ -6,6 +6,11 @@ on: - '*' tags: - '*' + paths: + - '**.sh' + - "Dockerfile" + - '.github/workflows/dockerhub.yml' + jobs: CheckToken: diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml index b22a2fd8..006b5873 100644 --- a/.github/workflows/shellcheck.yml +++ b/.github/workflows/shellcheck.yml @@ -11,7 +11,7 @@ on: - dev paths: - '**.sh' - - '**.yml' + - '.github/workflows/shellcheck.yml' jobs: ShellCheck: From ee10e2ab74b47ed0b1dd47710ef304965430d6a0 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 24 Jun 2021 23:57:21 +0800 Subject: [PATCH 266/304] add NO_ECC_384 --- .github/workflows/Ubuntu.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/Ubuntu.yml b/.github/workflows/Ubuntu.yml index dc704c04..88a9fd38 100644 --- a/.github/workflows/Ubuntu.yml +++ b/.github/workflows/Ubuntu.yml @@ -32,6 +32,7 @@ jobs: CA_ECDSA: "Buypass Class 2 Test4 CA 5" CA: "Buypass Class 2 Test4 CA 5" CA_EMAIL: "githubtest@acme.sh" + NO_ECC_384: "1" runs-on: ubuntu-latest env: TEST_LOCAL: 1 @@ -39,6 +40,7 @@ jobs: CA_ECDSA: ${{ matrix.CA_ECDSA }} CA: ${{ matrix.CA }} CA_EMAIL: ${{ matrix.CA_EMAIL }} + NO_ECC_384: ${{ matrix.NO_ECC_384 }} steps: - uses: actions/checkout@v2 - name: Install tools From 531318e0872ad3af7661e161b83bb016aee5b049 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 25 Jun 2021 00:01:46 +0800 Subject: [PATCH 267/304] fix filter --- .github/workflows/FreeBSD.yml | 2 +- .github/workflows/Linux.yml | 2 +- .github/workflows/MacOS.yml | 2 +- .github/workflows/PebbleStrict.yml | 2 +- .github/workflows/Solaris.yml | 2 +- .github/workflows/Ubuntu.yml | 2 +- .github/workflows/Windows.yml | 2 +- .github/workflows/shellcheck.yml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/FreeBSD.yml b/.github/workflows/FreeBSD.yml index 8b6d4aa5..407a9e6d 100644 --- a/.github/workflows/FreeBSD.yml +++ b/.github/workflows/FreeBSD.yml @@ -12,7 +12,7 @@ on: - dev paths: - '*.sh' - - '**.yml' + - '.github/workflows/FreeBSD.yml' jobs: diff --git a/.github/workflows/Linux.yml b/.github/workflows/Linux.yml index a3cf1c59..c4ec07c4 100644 --- a/.github/workflows/Linux.yml +++ b/.github/workflows/Linux.yml @@ -5,7 +5,7 @@ on: - '*' paths: - '*.sh' - - '**.yml' + - '.github/workflows/Linux.yml' pull_request: branches: diff --git a/.github/workflows/MacOS.yml b/.github/workflows/MacOS.yml index e12ef8e2..5ceeba7a 100644 --- a/.github/workflows/MacOS.yml +++ b/.github/workflows/MacOS.yml @@ -5,7 +5,7 @@ on: - '*' paths: - '*.sh' - - '**.yml' + - '.github/workflows/MacOS.yml' pull_request: branches: diff --git a/.github/workflows/PebbleStrict.yml b/.github/workflows/PebbleStrict.yml index 15795367..ea8e723d 100644 --- a/.github/workflows/PebbleStrict.yml +++ b/.github/workflows/PebbleStrict.yml @@ -5,7 +5,7 @@ on: - '*' paths: - '*.sh' - - '**.yml' + - '.github/workflows/PebbleStrict.yml' pull_request: branches: - dev diff --git a/.github/workflows/Solaris.yml b/.github/workflows/Solaris.yml index 3f2adb6a..c3c756bb 100644 --- a/.github/workflows/Solaris.yml +++ b/.github/workflows/Solaris.yml @@ -5,7 +5,7 @@ on: - '*' paths: - '*.sh' - - '**.yml' + - '.github/workflows/Solaris.yml' pull_request: branches: diff --git a/.github/workflows/Ubuntu.yml b/.github/workflows/Ubuntu.yml index 88a9fd38..e6102b97 100644 --- a/.github/workflows/Ubuntu.yml +++ b/.github/workflows/Ubuntu.yml @@ -5,7 +5,7 @@ on: - '*' paths: - '*.sh' - - '**.yml' + - '.github/workflows/Ubuntu.yml' pull_request: branches: diff --git a/.github/workflows/Windows.yml b/.github/workflows/Windows.yml index ed73641f..91605a52 100644 --- a/.github/workflows/Windows.yml +++ b/.github/workflows/Windows.yml @@ -5,7 +5,7 @@ on: - '*' paths: - '*.sh' - - '**.yml' + - '.github/workflows/Windows.yml' pull_request: branches: diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml index 006b5873..940a187d 100644 --- a/.github/workflows/shellcheck.yml +++ b/.github/workflows/shellcheck.yml @@ -5,7 +5,7 @@ on: - '*' paths: - '**.sh' - - '**.yml' + - '.github/workflows/shellcheck.yml' pull_request: branches: - dev From 7049537285d6e7eca19bb79d016a281ee0486530 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 25 Jun 2021 00:04:13 +0800 Subject: [PATCH 268/304] remove buypass test --- .github/workflows/Ubuntu.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/Ubuntu.yml b/.github/workflows/Ubuntu.yml index e6102b97..d3d66e19 100644 --- a/.github/workflows/Ubuntu.yml +++ b/.github/workflows/Ubuntu.yml @@ -28,11 +28,7 @@ jobs: CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" CA: "ZeroSSL RSA Domain Secure Site CA" CA_EMAIL: "githubtest@acme.sh" - - TEST_ACME_Server: "https://api.test4.buypass.no/acme/directory" - CA_ECDSA: "Buypass Class 2 Test4 CA 5" - CA: "Buypass Class 2 Test4 CA 5" - CA_EMAIL: "githubtest@acme.sh" - NO_ECC_384: "1" + runs-on: ubuntu-latest env: TEST_LOCAL: 1 From 0a990040e66bc8f58c18351a3935e0c4498603d0 Mon Sep 17 00:00:00 2001 From: Arnoud Vermeer Date: Fri, 25 Jun 2021 10:12:23 +0200 Subject: [PATCH 269/304] [dns_pdns] Fix: missing content type in PATCH requests #3454 --- dnsapi/dns_pdns.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_pdns.sh b/dnsapi/dns_pdns.sh index 28b35492..6aa2e953 100755 --- a/dnsapi/dns_pdns.sh +++ b/dnsapi/dns_pdns.sh @@ -103,7 +103,7 @@ set_record() { _build_record_string "$oldchallenge" done - if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [$_record_string]}]}"; then + if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [$_record_string]}]}" "application/json"; then _err "Set txt record error." return 1 fi @@ -126,7 +126,7 @@ rm_record() { if _contains "$_existing_challenges" "$txtvalue"; then #Delete all challenges (PowerDNS API does not allow to delete content) - if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"DELETE\", \"name\": \"$full.\", \"type\": \"TXT\"}]}"; then + if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"DELETE\", \"name\": \"$full.\", \"type\": \"TXT\"}]}" "application/json"; then _err "Delete txt record error." return 1 fi @@ -140,7 +140,7 @@ rm_record() { fi done #Recreate the existing challenges - if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [$_record_string]}]}"; then + if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [$_record_string]}]}" "application/json"; then _err "Set txt record error." return 1 fi @@ -203,12 +203,13 @@ _pdns_rest() { method=$1 ep=$2 data=$3 + ct=$4 export _H1="X-API-Key: $PDNS_Token" if [ ! "$method" = "GET" ]; then _debug data "$data" - response="$(_post "$data" "$PDNS_Url$ep" "" "$method")" + response="$(_post "$data" "$PDNS_Url$ep" "" "$method" "$ct")" else response="$(_get "$PDNS_Url$ep")" fi From c2094ae1562c2f6786b0bc8f987e5327ec15c19e Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 25 Jun 2021 20:56:17 +0800 Subject: [PATCH 270/304] remove unused file --- .github/auto-comment.yml | 40 ---------------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 .github/auto-comment.yml diff --git a/.github/auto-comment.yml b/.github/auto-comment.yml deleted file mode 100644 index 520b3ce3..00000000 --- a/.github/auto-comment.yml +++ /dev/null @@ -1,40 +0,0 @@ -# Comment to a new issue. -issuesOpened: > - If this is a bug report, please upgrade to the latest code and try again: - - 如果有 bug, 请先更新到最新版试试: - - ``` - acme.sh --upgrade - ``` - - please also provide the log with `--debug 2`. - - 同时请提供调试输出 `--debug 2` - - see: https://github.com/acmesh-official/acme.sh/wiki/How-to-debug-acme.sh - - Without `--debug 2` log, your issue will NEVER get replied. - - 没有调试输出, 你的 issue 不会得到任何解答. - - -pullRequestOpened: > - First, NEVER send a PR to `master` branch, it will NEVER be accepted. Please send to the `dev` branch instead. - - If this is a PR to support new DNS API or new notification API, please read this guide first: - https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Dev-Guide - - Please check the guide items one by one. - - Then add your usage here: - https://github.com/acmesh-official/acme.sh/wiki/dnsapi - - Or some other wiki pages: - - https://github.com/acmesh-official/acme.sh/wiki/deployhooks - - https://github.com/acmesh-official/acme.sh/wiki/notify - - - From 6b67132d04f530039e6caf45929a61838bffbeac Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 25 Jun 2021 21:18:03 +0800 Subject: [PATCH 271/304] use TEST_ACME_Server --- .github/workflows/Ubuntu.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/Ubuntu.yml b/.github/workflows/Ubuntu.yml index d3d66e19..df0faaf3 100644 --- a/.github/workflows/Ubuntu.yml +++ b/.github/workflows/Ubuntu.yml @@ -20,11 +20,11 @@ jobs: strategy: matrix: include: - - TEST_ACME_Server: "" + - TEST_ACME_Server: "LetsEncrypt.org" CA_ECDSA: "" CA: "" CA_EMAIL: "" - - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" + - TEST_ACME_Server: "ZeroSSL.com" CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" CA: "ZeroSSL RSA Domain Secure Site CA" CA_EMAIL: "githubtest@acme.sh" @@ -32,7 +32,7 @@ jobs: runs-on: ubuntu-latest env: TEST_LOCAL: 1 - ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} + TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }} CA_ECDSA: ${{ matrix.CA_ECDSA }} CA: ${{ matrix.CA }} CA_EMAIL: ${{ matrix.CA_EMAIL }} From 7be74df2ea3d338375fd49bfdbe71c22c294d970 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 25 Jun 2021 21:28:20 +0800 Subject: [PATCH 272/304] Use TEST_ACME_Server --- .github/workflows/FreeBSD.yml | 6 +++--- .github/workflows/MacOS.yml | 6 +++--- .github/workflows/PebbleStrict.yml | 2 +- .github/workflows/Solaris.yml | 6 +++--- .github/workflows/Windows.yml | 6 +++--- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/FreeBSD.yml b/.github/workflows/FreeBSD.yml index 407a9e6d..45b08405 100644 --- a/.github/workflows/FreeBSD.yml +++ b/.github/workflows/FreeBSD.yml @@ -20,18 +20,18 @@ jobs: strategy: matrix: include: - - TEST_ACME_Server: "" + - TEST_ACME_Server: "LetsEncrypt.org" CA_ECDSA: "" CA: "" CA_EMAIL: "" - - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" + - TEST_ACME_Server: "ZeroSSL.com" CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" CA: "ZeroSSL RSA Domain Secure Site CA" CA_EMAIL: "githubtest@acme.sh" runs-on: macos-latest env: TEST_LOCAL: 1 - ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} + TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }} CA_ECDSA: ${{ matrix.CA_ECDSA }} CA: ${{ matrix.CA }} CA_EMAIL: ${{ matrix.CA_EMAIL }} diff --git a/.github/workflows/MacOS.yml b/.github/workflows/MacOS.yml index 5ceeba7a..11d8e5c3 100644 --- a/.github/workflows/MacOS.yml +++ b/.github/workflows/MacOS.yml @@ -20,18 +20,18 @@ jobs: strategy: matrix: include: - - TEST_ACME_Server: "" + - TEST_ACME_Server: "LetsEncrypt.org" CA_ECDSA: "" CA: "" CA_EMAIL: "" - - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" + - TEST_ACME_Server: "ZeroSSL.com" CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" CA: "ZeroSSL RSA Domain Secure Site CA" CA_EMAIL: "githubtest@acme.sh" runs-on: macos-latest env: TEST_LOCAL: 1 - ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} + TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }} CA_ECDSA: ${{ matrix.CA_ECDSA }} CA: ${{ matrix.CA }} CA_EMAIL: ${{ matrix.CA_EMAIL }} diff --git a/.github/workflows/PebbleStrict.yml b/.github/workflows/PebbleStrict.yml index ea8e723d..f7907d8b 100644 --- a/.github/workflows/PebbleStrict.yml +++ b/.github/workflows/PebbleStrict.yml @@ -19,7 +19,7 @@ jobs: env: TestingDomain: example.com TestingAltDomains: www.example.com - ACME_DIRECTORY: https://localhost:14000/dir + TEST_ACME_Server: https://localhost:14000/dir HTTPS_INSECURE: 1 Le_HTTPPort: 5002 TEST_LOCAL: 1 diff --git a/.github/workflows/Solaris.yml b/.github/workflows/Solaris.yml index c3c756bb..27e9ad09 100644 --- a/.github/workflows/Solaris.yml +++ b/.github/workflows/Solaris.yml @@ -20,18 +20,18 @@ jobs: strategy: matrix: include: - - TEST_ACME_Server: "" + - TEST_ACME_Server: "LetsEncrypt.org" CA_ECDSA: "" CA: "" CA_EMAIL: "" - - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" + - TEST_ACME_Server: "ZeroSSL.com" CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" CA: "ZeroSSL RSA Domain Secure Site CA" CA_EMAIL: "githubtest@acme.sh" runs-on: macos-latest env: TEST_LOCAL: 1 - ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} + TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }} CA_ECDSA: ${{ matrix.CA_ECDSA }} CA: ${{ matrix.CA }} CA_EMAIL: ${{ matrix.CA_EMAIL }} diff --git a/.github/workflows/Windows.yml b/.github/workflows/Windows.yml index 91605a52..69ed64ea 100644 --- a/.github/workflows/Windows.yml +++ b/.github/workflows/Windows.yml @@ -20,17 +20,17 @@ jobs: strategy: matrix: include: - - TEST_ACME_Server: "" + - TEST_ACME_Server: "LetsEncrypt.org" CA_ECDSA: "" CA: "" CA_EMAIL: "" - - TEST_ACME_Server: "https://acme.zerossl.com/v2/DV90" + - TEST_ACME_Server: "ZeroSSL.com" CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" CA: "ZeroSSL RSA Domain Secure Site CA" CA_EMAIL: "githubtest@acme.sh" runs-on: windows-latest env: - ACME_DIRECTORY: ${{ matrix.TEST_ACME_Server }} + TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }} CA_ECDSA: ${{ matrix.CA_ECDSA }} CA: ${{ matrix.CA }} CA_EMAIL: ${{ matrix.CA_EMAIL }} From a14f3b348ddc02647c63aebd0759e6020f023c73 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 25 Jun 2021 21:59:38 +0800 Subject: [PATCH 273/304] fix deactivate --- acme.sh | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index f728e537..6a515971 100755 --- a/acme.sh +++ b/acme.sh @@ -5777,7 +5777,20 @@ remove() { _deactivate() { _d_domain="$1" _d_type="$2" - _initpath + _initpath "$_d_domain" "$_d_type" + + . "$DOMAIN_CONF" + _debug Le_API "$Le_API" + + if [ "$Le_API" ]; then + export ACME_DIRECTORY="$Le_API" + #reload ca configs + ACCOUNT_KEY_PATH="" + ACCOUNT_JSON_PATH="" + CA_CONF="" + _debug3 "initpath again." + _initpath "$Le_Domain" "$_d_type" + fi _identifiers="{\"type\":\"dns\",\"value\":\"$_d_domain\"}" if ! _send_signed_request "$ACME_NEW_ORDER" "{\"identifiers\": [$_identifiers]}"; then From 5afdbb7780937b7efdb9d75ef50c2d2a25661af3 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 25 Jun 2021 22:16:16 +0800 Subject: [PATCH 274/304] fix deactivate --- acme.sh | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/acme.sh b/acme.sh index 6a515971..9c783f69 100755 --- a/acme.sh +++ b/acme.sh @@ -2535,6 +2535,16 @@ __initHome() { 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}" @@ -5034,6 +5044,9 @@ renew() { _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="" @@ -5041,6 +5054,7 @@ renew() { CA_CONF="" _debug3 "initpath again." _initpath "$Le_Domain" "$_isEcc" + _initAPI fi if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(_time)" -lt "$Le_NextRenewTime" ]; then @@ -5783,6 +5797,9 @@ _deactivate() { _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="" @@ -5790,6 +5807,7 @@ _deactivate() { CA_CONF="" _debug3 "initpath again." _initpath "$Le_Domain" "$_d_type" + _initAPI fi _identifiers="{\"type\":\"dns\",\"value\":\"$_d_domain\"}" From 8e401ed465fc10daa46553006d3b1a60b5135cbb Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 25 Jun 2021 22:23:17 +0800 Subject: [PATCH 275/304] fix initapi --- acme.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/acme.sh b/acme.sh index 9c783f69..712ce7f6 100755 --- a/acme.sh +++ b/acme.sh @@ -2600,6 +2600,9 @@ _initAPI() { _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 } From 743814c8658b7c942f33efa525d89a232fd81354 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 25 Jun 2021 22:29:40 +0800 Subject: [PATCH 276/304] fix test server --- .github/workflows/FreeBSD.yml | 2 +- .github/workflows/MacOS.yml | 2 +- .github/workflows/Solaris.yml | 2 +- .github/workflows/Ubuntu.yml | 2 +- .github/workflows/Windows.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/FreeBSD.yml b/.github/workflows/FreeBSD.yml index 45b08405..83364b3c 100644 --- a/.github/workflows/FreeBSD.yml +++ b/.github/workflows/FreeBSD.yml @@ -20,7 +20,7 @@ jobs: strategy: matrix: include: - - TEST_ACME_Server: "LetsEncrypt.org" + - TEST_ACME_Server: "LetsEncrypt.org_test" CA_ECDSA: "" CA: "" CA_EMAIL: "" diff --git a/.github/workflows/MacOS.yml b/.github/workflows/MacOS.yml index 11d8e5c3..85ec7527 100644 --- a/.github/workflows/MacOS.yml +++ b/.github/workflows/MacOS.yml @@ -20,7 +20,7 @@ jobs: strategy: matrix: include: - - TEST_ACME_Server: "LetsEncrypt.org" + - TEST_ACME_Server: "LetsEncrypt.org_test" CA_ECDSA: "" CA: "" CA_EMAIL: "" diff --git a/.github/workflows/Solaris.yml b/.github/workflows/Solaris.yml index 27e9ad09..64dd741f 100644 --- a/.github/workflows/Solaris.yml +++ b/.github/workflows/Solaris.yml @@ -20,7 +20,7 @@ jobs: strategy: matrix: include: - - TEST_ACME_Server: "LetsEncrypt.org" + - TEST_ACME_Server: "LetsEncrypt.org_test" CA_ECDSA: "" CA: "" CA_EMAIL: "" diff --git a/.github/workflows/Ubuntu.yml b/.github/workflows/Ubuntu.yml index df0faaf3..af74965a 100644 --- a/.github/workflows/Ubuntu.yml +++ b/.github/workflows/Ubuntu.yml @@ -20,7 +20,7 @@ jobs: strategy: matrix: include: - - TEST_ACME_Server: "LetsEncrypt.org" + - TEST_ACME_Server: "LetsEncrypt.org_test" CA_ECDSA: "" CA: "" CA_EMAIL: "" diff --git a/.github/workflows/Windows.yml b/.github/workflows/Windows.yml index 69ed64ea..8c8e2842 100644 --- a/.github/workflows/Windows.yml +++ b/.github/workflows/Windows.yml @@ -20,7 +20,7 @@ jobs: strategy: matrix: include: - - TEST_ACME_Server: "LetsEncrypt.org" + - TEST_ACME_Server: "LetsEncrypt.org_test" CA_ECDSA: "" CA: "" CA_EMAIL: "" From ef1685d445c03ff12e62a30b2cd2fa193b9b9e5a Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 25 Jun 2021 22:44:23 +0800 Subject: [PATCH 277/304] fix revoke --- acme.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/acme.sh b/acme.sh index 712ce7f6..0a003d59 100755 --- a/acme.sh +++ b/acme.sh @@ -5715,6 +5715,23 @@ revoke() { 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 From 6cf5580a134205da3fa805c9b40a14e6abf58087 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 25 Jun 2021 22:46:55 +0800 Subject: [PATCH 278/304] fix format --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 0a003d59..1ef09574 100755 --- a/acme.sh +++ b/acme.sh @@ -5715,7 +5715,7 @@ revoke() { return 1 fi - . "$DOMAIN_CONF" + . "$DOMAIN_CONF" _debug Le_API "$Le_API" if [ "$Le_API" ]; then From 180460c69c96029b41e38d2bd86f5cd49a46e80f Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 25 Jun 2021 23:01:47 +0800 Subject: [PATCH 279/304] fix env --- .github/workflows/FreeBSD.yml | 2 +- .github/workflows/Solaris.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/FreeBSD.yml b/.github/workflows/FreeBSD.yml index 83364b3c..6a82156d 100644 --- a/.github/workflows/FreeBSD.yml +++ b/.github/workflows/FreeBSD.yml @@ -48,7 +48,7 @@ jobs: run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/freebsd-vm@v0.1.4 with: - envs: 'TEST_LOCAL TestingDomain ACME_DIRECTORY CA_ECDSA CA CA_EMAIL' + envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL' nat: | "8080": "80" prepare: pkg install -y socat curl diff --git a/.github/workflows/Solaris.yml b/.github/workflows/Solaris.yml index 64dd741f..9d1c46ac 100644 --- a/.github/workflows/Solaris.yml +++ b/.github/workflows/Solaris.yml @@ -48,7 +48,7 @@ jobs: run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/solaris-vm@v0.0.3 with: - envs: 'TEST_LOCAL TestingDomain ACME_DIRECTORY CA_ECDSA CA CA_EMAIL' + envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL' nat: | "8080": "80" prepare: pkgutil -y -i socat curl From 208c330da17ee9633bf2ce8fdbfe378da3cf071e Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 27 Jun 2021 11:29:51 +0800 Subject: [PATCH 280/304] fix for compatiblity --- acme.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index 1ef09574..5ba12b17 100755 --- a/acme.sh +++ b/acme.sh @@ -3579,7 +3579,7 @@ _regAccount() { return 1 fi _secure_debug2 _eabresp "$_eabresp" - _eab_id="$(echo "$_eabresp" | tr ',}' '\n' | grep '"eab_kid"' | cut -d : -f 2 | tr -d '"')" + _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" @@ -5859,7 +5859,7 @@ _deactivate() { _debug2 response "$response" _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 _info "No valid entries found." if [ -z "$thumbprint" ]; then @@ -6623,7 +6623,7 @@ _getRepoHash() { _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() { From c19446f696da0e30d4602f134424cee3010a1765 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 28 Jun 2021 21:16:32 +0800 Subject: [PATCH 281/304] use letsencrypt server to renew certs if no server was saved. --- acme.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/acme.sh b/acme.sh index 5ba12b17..11c886a9 100755 --- a/acme.sh +++ b/acme.sh @@ -5045,6 +5045,11 @@ renew() { . "$DOMAIN_CONF" _debug Le_API "$Le_API" + if [ -z "$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 From e8d9933823e05829a7c2c6426387290c41a1a862 Mon Sep 17 00:00:00 2001 From: jonwltn <86822083+jonwltn@users.noreply.github.com> Date: Fri, 2 Jul 2021 09:23:45 -0700 Subject: [PATCH 282/304] Fix the URL for checking DNSPod availability. --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 11c886a9..893c8344 100755 --- a/acme.sh +++ b/acme.sh @@ -3927,7 +3927,7 @@ _ns_lookup_ali() { } _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 From 6ee91e14a639b70a7c2b54bb53448b16c5e681f6 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 11 Jul 2021 21:58:47 +0800 Subject: [PATCH 283/304] update --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c7f7e677..91a18985 100644 --- a/README.md +++ b/README.md @@ -20,18 +20,18 @@ - An ACME protocol client written purely in Shell (Unix shell) language. - Full ACME protocol implementation. -- Support ACME v1 and ACME v2 -- Support ACME v2 wildcard certs +- Support ECDSA certs +- Support SAN and wildcard certs - Simple, powerful and very easy to use. You only need 3 minutes to learn it. - Bash, dash and sh compatible. -- Purely written in Shell with no dependencies on python or the official Let's Encrypt client. +- Purely written in Shell with no dependencies on python. - Just one script to issue, renew and install your certificates automatically. - DOES NOT require `root/sudoer` access. -- Docker friendly -- IPv6 support +- Docker ready +- IPv6 ready - Cron job notifications for renewal or error etc. -It's probably the `easiest & smartest` shell script to automatically issue & renew the free certificates from Let's Encrypt. +It's probably the `easiest & smartest` shell script to automatically issue & renew the free certificates. Wiki: https://github.com/acmesh-official/acme.sh/wiki From 276bfb04dee05f100f4c6bef5a43432311319d55 Mon Sep 17 00:00:00 2001 From: Steven Zhu Date: Tue, 6 Jul 2021 20:51:51 -0400 Subject: [PATCH 284/304] Add sender name for SendGrid notify hook --- notify/sendgrid.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/notify/sendgrid.sh b/notify/sendgrid.sh index 0d5ea3b3..ea4dcc93 100644 --- a/notify/sendgrid.sh +++ b/notify/sendgrid.sh @@ -37,11 +37,19 @@ sendgrid_send() { fi _saveaccountconf_mutable SENDGRID_FROM "$SENDGRID_FROM" + SENDGRID_FROM_NAME="${SENDGRID_FROM_NAME:-$(_readaccountconf_mutable SENDGRID_FROM_NAME)}" + _saveaccountconf_mutable SENDGRID_FROM_NAME "$SENDGRID_FROM_NAME" + export _H1="Authorization: Bearer $SENDGRID_API_KEY" export _H2="Content-Type: application/json" _content="$(echo "$_content" | _json_encode)" - _data="{\"personalizations\": [{\"to\": [{\"email\": \"$SENDGRID_TO\"}]}],\"from\": {\"email\": \"$SENDGRID_FROM\"},\"subject\": \"$_subject\",\"content\": [{\"type\": \"text/plain\", \"value\": \"$_content\"}]}" + + if [ -z "$SENDGRID_FROM_NAME" ]; then + _data="{\"personalizations\": [{\"to\": [{\"email\": \"$SENDGRID_TO\"}]}],\"from\": {\"email\": \"$SENDGRID_FROM\"},\"subject\": \"$_subject\",\"content\": [{\"type\": \"text/plain\", \"value\": \"$_content\"}]}" + else + _data="{\"personalizations\": [{\"to\": [{\"email\": \"$SENDGRID_TO\"}]}],\"from\": {\"email\": \"$SENDGRID_FROM\", \"name\": \"$SENDGRID_FROM_NAME\"},\"subject\": \"$_subject\",\"content\": [{\"type\": \"text/plain\", \"value\": \"$_content\"}]}" + fi response="$(_post "$_data" "https://api.sendgrid.com/v3/mail/send")" if [ "$?" = "0" ] && [ -z "$response" ]; then From fbe01cfeaa9de978cafc39956e38dafa8ae1dfdd Mon Sep 17 00:00:00 2001 From: Steven Zhu Date: Tue, 6 Jul 2021 22:54:15 -0400 Subject: [PATCH 285/304] Fix space inconsistency --- notify/sendgrid.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notify/sendgrid.sh b/notify/sendgrid.sh index ea4dcc93..82d3f6c6 100644 --- a/notify/sendgrid.sh +++ b/notify/sendgrid.sh @@ -44,7 +44,7 @@ sendgrid_send() { export _H2="Content-Type: application/json" _content="$(echo "$_content" | _json_encode)" - + if [ -z "$SENDGRID_FROM_NAME" ]; then _data="{\"personalizations\": [{\"to\": [{\"email\": \"$SENDGRID_TO\"}]}],\"from\": {\"email\": \"$SENDGRID_FROM\"},\"subject\": \"$_subject\",\"content\": [{\"type\": \"text/plain\", \"value\": \"$_content\"}]}" else From 28c18b4c050c29ea05f0c5024050917bb852003a Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 12 Jul 2021 21:46:08 +0800 Subject: [PATCH 286/304] fix https://github.com/acmesh-official/acme.sh/issues/3600 --- acme.sh | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/acme.sh b/acme.sh index 893c8344..7aaef489 100755 --- a/acme.sh +++ b/acme.sh @@ -4714,26 +4714,13 @@ $_authorizations_map" return 1 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" response="$(echo "$response" | _normalizeJson)" _debug2 response "$response" status=$(echo "$response" | _egrep_o '"status":"[^"]*' | cut -d : -f 2 | tr -d '"') - + _debug2 status "$status" if _contains "$status" "invalid"; then error="$(echo "$response" | _egrep_o '"error":\{[^\}]*')" _debug2 error "$error" @@ -4775,7 +4762,19 @@ $_authorizations_map" _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 From 29f0f0d04c42e7484114c19ad3c9dcae4a5ddf85 Mon Sep 17 00:00:00 2001 From: neil Date: Thu, 15 Jul 2021 22:21:32 +0800 Subject: [PATCH 287/304] add retry for get() and post() --- acme.sh | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 68 insertions(+), 6 deletions(-) diff --git a/acme.sh b/acme.sh index 7aaef489..74355244 100755 --- a/acme.sh +++ b/acme.sh @@ -1768,7 +1768,7 @@ _inithttp() { 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 @@ -1808,6 +1808,8 @@ _inithttp() { } +_HTTP_MAX_RETRY=8 + # body url [needbase64] [POST|PUT|DELETE] [ContentType] _post() { body="$1" @@ -1815,6 +1817,33 @@ _post() { 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" @@ -1866,7 +1895,9 @@ _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")" @@ -1922,7 +1953,9 @@ _post() { _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 @@ -1936,13 +1969,38 @@ _post() { # 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 @@ -1961,7 +2019,9 @@ _get() { 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")" @@ -1987,7 +2047,9 @@ _get() { _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=$? From b329dc004184fdfc685aed022f0df27c8ec44109 Mon Sep 17 00:00:00 2001 From: neil Date: Thu, 15 Jul 2021 22:47:20 +0800 Subject: [PATCH 288/304] format --- acme.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/acme.sh b/acme.sh index 74355244..aea8b3a5 100755 --- a/acme.sh +++ b/acme.sh @@ -1824,11 +1824,11 @@ _post() { [ "$_http_retry_times" = "$_HTTP_MAX_RETRY" ] _lastHCode="$?" _debug "Retrying post" - _post_impl "$body" "$_post_url" "$needbase64" "$httpmethod" "$_postContentType" "$_lastHCode"; + _post_impl "$body" "$_post_url" "$needbase64" "$httpmethod" "$_postContentType" "$_lastHCode" _hcode="$?" _debug _hcode "$_hcode" if [ "$_hcode" = "0" ]; then - break; + break fi _http_retry_times=$(_math $_http_retry_times + 1) _sleep $_sleep_retry_sec @@ -1979,11 +1979,11 @@ _get() { [ "$_http_retry_times" = "$_HTTP_MAX_RETRY" ] _lastHCode="$?" _debug "Retrying GET" - _get_impl "$url" "$onlyheader" "$t" "$_lastHCode"; + _get_impl "$url" "$onlyheader" "$t" "$_lastHCode" _hcode="$?" _debug _hcode "$_hcode" if [ "$_hcode" = "0" ]; then - break; + break fi _http_retry_times=$(_math $_http_retry_times + 1) _sleep $_sleep_retry_sec From 07359e2e9c32b3c6e4a50c857e97500795304c0b Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 20 Jul 2021 21:05:17 +0800 Subject: [PATCH 289/304] add info --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index aea8b3a5..32431aab 100755 --- a/acme.sh +++ b/acme.sh @@ -4814,9 +4814,9 @@ $_authorizations_map" 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" From ec1ad12701d6850d89dbaef226fa4101d073483a Mon Sep 17 00:00:00 2001 From: Ivanovitch_k Date: Thu, 22 Jul 2021 00:09:44 +0200 Subject: [PATCH 290/304] dns_ovh: fix random add/remove txt records failures due to inconsistent curl api response json --- dnsapi/dns_ovh.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_ovh.sh b/dnsapi/dns_ovh.sh index f6f9689a..b2c646fa 100755 --- a/dnsapi/dns_ovh.sh +++ b/dnsapi/dns_ovh.sh @@ -261,7 +261,9 @@ _get_root() { return 1 fi - if ! _contains "$response" "This service does not exist" >/dev/null && ! _contains "$response" "NOT_GRANTED_CALL" >/dev/null; then + if ! _contains "$response" "This service does not exist" >/dev/null && \ + ! _contains "$response" "This call has not been granted" >/dev/null && \ + ! _contains "$response" "NOT_GRANTED_CALL" >/dev/null; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain="$h" return 0 From f773383c534e797cbeeea856259cd0a53a2774ab Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 24 Jul 2021 15:46:58 +0800 Subject: [PATCH 291/304] fix format --- dnsapi/dns_ovh.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_ovh.sh b/dnsapi/dns_ovh.sh index b2c646fa..e65babbd 100755 --- a/dnsapi/dns_ovh.sh +++ b/dnsapi/dns_ovh.sh @@ -261,9 +261,9 @@ _get_root() { return 1 fi - if ! _contains "$response" "This service does not exist" >/dev/null && \ - ! _contains "$response" "This call has not been granted" >/dev/null && \ - ! _contains "$response" "NOT_GRANTED_CALL" >/dev/null; then + if ! _contains "$response" "This service does not exist" >/dev/null && + ! _contains "$response" "This call has not been granted" >/dev/null && + ! _contains "$response" "NOT_GRANTED_CALL" >/dev/null; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain="$h" return 0 From 04b057d3d2ce812c91c23075e334e4999c62d28f Mon Sep 17 00:00:00 2001 From: xpac1985 Date: Thu, 1 Jul 2021 22:25:49 +0200 Subject: [PATCH 292/304] Fix Infoblox_View handling + some cleanup URL is now constructed after possible fallback value for Infoblox_View is being set Infoblox_View is URLencoded to deal with e.g. spaces Some cleanup, clearer log messages etc. --- dnsapi/dns_infoblox.sh | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/dnsapi/dns_infoblox.sh b/dnsapi/dns_infoblox.sh index 4cbb2146..a4581585 100644 --- a/dnsapi/dns_infoblox.sh +++ b/dnsapi/dns_infoblox.sh @@ -9,7 +9,6 @@ dns_infoblox_add() { ## Nothing to see here, just some housekeeping fulldomain=$1 txtvalue=$2 - baseurlnObject="https://$Infoblox_Server/wapi/v2.2.2/record:txt?name=$fulldomain&text=$txtvalue&view=$Infoblox_View" _info "Using Infoblox API" _debug fulldomain "$fulldomain" @@ -19,32 +18,39 @@ dns_infoblox_add() { if [ -z "$Infoblox_Creds" ] || [ -z "$Infoblox_Server" ]; then Infoblox_Creds="" Infoblox_Server="" - _err "You didn't specify the credentials, server or infoblox view yet (Infoblox_Creds, Infoblox_Server and Infoblox_View)." - _err "Please set them via EXPORT ([username:password], [ip or hostname]) and try again." + _err "You didn't specify the Infoblox credentials or server (Infoblox_Creds; Infoblox_Server)." + _err "Please set them via EXPORT Infoblox_Creds=username:password or EXPORT Infoblox_server=ip/hostname and try again." return 1 fi if [ -z "$Infoblox_View" ]; then + _info "No Infoblox_View set, using fallback value 'default'" Infoblox_View="default" fi - + ## Save the credentials to the account file _saveaccountconf Infoblox_Creds "$Infoblox_Creds" _saveaccountconf Infoblox_Server "$Infoblox_Server" _saveaccountconf Infoblox_View "$Infoblox_View" + ## URLencode Infoblox View to deal with e.g. spaces + Infoblox_ViewEncoded=$(printf "%b" "$Infoblox_View" | _url_encode) + ## Base64 encode the credentials Infoblox_CredsEncoded=$(printf "%b" "$Infoblox_Creds" | _base64) ## Construct the HTTP Authorization header export _H1="Accept-Language:en-US" export _H2="Authorization: Basic $Infoblox_CredsEncoded" + + ## Construct the request URL + baseurlnObject="https://$Infoblox_Server/wapi/v2.2.2/record:txt?name=$fulldomain&text=$txtvalue&view=${Infoblox_ViewEncoded}" ## Add the challenge record to the Infoblox grid member result="$(_post "" "$baseurlnObject" "" "POST")" ## Let's see if we get something intelligible back from the unit - if [ "$(echo "$result" | _egrep_o "record:txt/.*:.*/$Infoblox_View")" ]; then + if [ "$(echo "$result" | _egrep_o "record:txt/.*:.*/${Infoblox_ViewEncoded}")" ]; then _info "Successfully created the txt record" return 0 else @@ -65,6 +71,9 @@ dns_infoblox_rm() { _debug fulldomain "$fulldomain" _debug txtvalue "$txtvalue" + ## URLencode Infoblox View to deal with e.g. spaces + Infoblox_ViewEncoded=$(printf "%b" "$Infoblox_View" | _url_encode) + ## Base64 encode the credentials Infoblox_CredsEncoded="$(printf "%b" "$Infoblox_Creds" | _base64)" @@ -73,18 +82,18 @@ dns_infoblox_rm() { export _H2="Authorization: Basic $Infoblox_CredsEncoded" ## Does the record exist? Let's check. - baseurlnObject="https://$Infoblox_Server/wapi/v2.2.2/record:txt?name=$fulldomain&text=$txtvalue&view=$Infoblox_View&_return_type=xml-pretty" + baseurlnObject="https://$Infoblox_Server/wapi/v2.2.2/record:txt?name=$fulldomain&text=$txtvalue&view=${Infoblox_ViewEncoded}&_return_type=xml-pretty" result="$(_get "$baseurlnObject")" ## Let's see if we get something intelligible back from the grid - if [ "$(echo "$result" | _egrep_o "record:txt/.*:.*/$Infoblox_View")" ]; then + if [ "$(echo "$result" | _egrep_o "record:txt/.*:.*/${Infoblox_ViewEncoded}")" ]; then ## Extract the object reference - objRef="$(printf "%b" "$result" | _egrep_o "record:txt/.*:.*/$Infoblox_View")" + objRef="$(printf "%b" "$result" | _egrep_o "record:txt/.*:.*/${Infoblox_ViewEncoded}")" objRmUrl="https://$Infoblox_Server/wapi/v2.2.2/$objRef" ## Delete them! All the stale records! rmResult="$(_post "" "$objRmUrl" "" "DELETE")" ## Let's see if that worked - if [ "$(echo "$rmResult" | _egrep_o "record:txt/.*:.*/$Infoblox_View")" ]; then + if [ "$(echo "$rmResult" | _egrep_o "record:txt/.*:.*/${Infoblox_ViewEncoded}")" ]; then _info "Successfully deleted $objRef" return 0 else From d38e28a1fb3813468339fc7f2c7e2513d73b56f5 Mon Sep 17 00:00:00 2001 From: xpac1985 Date: Thu, 1 Jul 2021 22:54:56 +0200 Subject: [PATCH 293/304] Clean up formatting (SHFMT) --- dnsapi/dns_infoblox.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_infoblox.sh b/dnsapi/dns_infoblox.sh index a4581585..827d92d1 100644 --- a/dnsapi/dns_infoblox.sh +++ b/dnsapi/dns_infoblox.sh @@ -27,7 +27,7 @@ dns_infoblox_add() { _info "No Infoblox_View set, using fallback value 'default'" Infoblox_View="default" fi - + ## Save the credentials to the account file _saveaccountconf Infoblox_Creds "$Infoblox_Creds" _saveaccountconf Infoblox_Server "$Infoblox_Server" @@ -45,7 +45,7 @@ dns_infoblox_add() { ## Construct the request URL baseurlnObject="https://$Infoblox_Server/wapi/v2.2.2/record:txt?name=$fulldomain&text=$txtvalue&view=${Infoblox_ViewEncoded}" - + ## Add the challenge record to the Infoblox grid member result="$(_post "" "$baseurlnObject" "" "POST")" From bf9dc6d788c19d52bf79956a5963dc409b7e87f0 Mon Sep 17 00:00:00 2001 From: xpac1985 Date: Thu, 1 Jul 2021 22:59:43 +0200 Subject: [PATCH 294/304] Shell formatting, again --- dnsapi/dns_infoblox.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_infoblox.sh b/dnsapi/dns_infoblox.sh index 827d92d1..6bfd36ee 100644 --- a/dnsapi/dns_infoblox.sh +++ b/dnsapi/dns_infoblox.sh @@ -42,10 +42,10 @@ dns_infoblox_add() { ## Construct the HTTP Authorization header export _H1="Accept-Language:en-US" export _H2="Authorization: Basic $Infoblox_CredsEncoded" - + ## Construct the request URL baseurlnObject="https://$Infoblox_Server/wapi/v2.2.2/record:txt?name=$fulldomain&text=$txtvalue&view=${Infoblox_ViewEncoded}" - + ## Add the challenge record to the Infoblox grid member result="$(_post "" "$baseurlnObject" "" "POST")" From 493af06e52d169466c9c804ba8e486fae7d4518f Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 24 Jul 2021 16:23:30 +0800 Subject: [PATCH 295/304] minor, clean links for renewal --- acme.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/acme.sh b/acme.sh index 32431aab..22f09165 100755 --- a/acme.sh +++ b/acme.sh @@ -4209,6 +4209,10 @@ issue() { if [ -z "$_ACME_IS_RENEW" ]; then _initpath "$_main_domain" "$_key_length" mkdir -p "$DOMAIN_PATH" + else + Le_OrderFinalize="" + Le_LinkOrder="" + Le_LinkCert="" fi if _hasfield "$_web_roots" "$W_DNS" && [ -z "$FORCE_DNS_MANUAL" ]; then From ba8e2e2625ca594d55ac51b718f582f4335a74a0 Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 28 Jul 2021 22:14:54 +0800 Subject: [PATCH 296/304] fix https://github.com/acmesh-official/acme.sh/issues/3624#issuecomment-887689325 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 22f09165..4b160e4f 100755 --- a/acme.sh +++ b/acme.sh @@ -3443,7 +3443,7 @@ _on_before_issue() { _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" From 4512b8e4d6b1d92ce36f317bc5f1f02c39e7e275 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 1 Aug 2021 13:11:52 +0800 Subject: [PATCH 297/304] fix https://github.com/acmesh-official/acme.sh/issues/3635 --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 4b160e4f..73a05f00 100755 --- a/acme.sh +++ b/acme.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -VER=3.0.0 +VER=3.0.1 PROJECT_NAME="acme.sh" @@ -4209,7 +4209,7 @@ issue() { if [ -z "$_ACME_IS_RENEW" ]; then _initpath "$_main_domain" "$_key_length" mkdir -p "$DOMAIN_PATH" - else + elif ! _hasfield "$_web_roots" "$W_DNS"; then Le_OrderFinalize="" Le_LinkOrder="" Le_LinkCert="" From 568262947d87ffad8f6be07074207ce6422dd698 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 1 Aug 2021 15:44:14 +0800 Subject: [PATCH 298/304] fix nginx mode --- acme.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index 73a05f00..bd351ac8 100755 --- a/acme.sh +++ b/acme.sh @@ -3161,14 +3161,14 @@ _checkConf() { FOUND_REAL_NGINX_CONF="$2" return 0 fi - if cat "$2" | tr "\t" " " | grep "^ *include *.*;" >/dev/null; then + if cat "$2" | tr "\t" " " | grep "^ *include *;" >/dev/null; then _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" 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 From 80427f12a33f8169925d5954418e38844f1736ff Mon Sep 17 00:00:00 2001 From: Felix Yan Date: Tue, 3 Aug 2021 01:36:59 +0800 Subject: [PATCH 299/304] Correct a typo in dns_aws.sh --- dnsapi/dns_aws.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_aws.sh b/dnsapi/dns_aws.sh index 068c337c..14a4594d 100755 --- a/dnsapi/dns_aws.sh +++ b/dnsapi/dns_aws.sh @@ -32,7 +32,7 @@ dns_aws_add() { if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then AWS_ACCESS_KEY_ID="" AWS_SECRET_ACCESS_KEY="" - _err "You haven't specifed the aws route53 api key id and and api key secret yet." + _err "You haven't specified the aws route53 api key id and and api key secret yet." _err "Please create your key and try again. see $(__green $AWS_WIKI)" return 1 fi From 5ab8a6e83fd8da67876390c4029bfb7b37240fd7 Mon Sep 17 00:00:00 2001 From: jonwltn <86822083+jonwltn@users.noreply.github.com> Date: Wed, 4 Aug 2021 10:44:48 -0700 Subject: [PATCH 300/304] Minor output formatting changes. --- acme.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/acme.sh b/acme.sh index bd351ac8..fa1e55b6 100755 --- a/acme.sh +++ b/acme.sh @@ -4986,10 +4986,10 @@ $_authorizations_map" _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 @@ -4998,8 +4998,8 @@ $_authorizations_map" 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" @@ -5543,7 +5543,7 @@ _installcert() { 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 @@ -5551,7 +5551,7 @@ _installcert() { 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 @@ -5564,7 +5564,7 @@ _installcert() { 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 @@ -5577,7 +5577,7 @@ _installcert() { 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 From 0cd012ec90ec6cef55be5d8afb95110feb5a795a Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 5 Aug 2021 20:12:42 +0800 Subject: [PATCH 301/304] fix https://github.com/acmesh-official/acme.sh/issues/1914#issuecomment-893188476 --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index fa1e55b6..d7db763e 100755 --- a/acme.sh +++ b/acme.sh @@ -3161,9 +3161,9 @@ _checkConf() { FOUND_REAL_NGINX_CONF="$2" return 0 fi - if cat "$2" | tr "\t" " " | grep "^ *include *;" >/dev/null; then + if cat "$2" | tr "\t" " " | grep "^ *include +.*;" >/dev/null; then _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" if ! _startswith "$included" "/" && _exists dirname; then _relpath="$(dirname "$_c_file")" From d8d5481121fd4ed487a999a8aa4e7dfd3d9f1e92 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 6 Aug 2021 21:22:10 +0800 Subject: [PATCH 302/304] fix nginx mode https://github.com/acmesh-official/acme.sh/issues/3648#issuecomment-894045613 --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index d7db763e..05b8e07e 100755 --- a/acme.sh +++ b/acme.sh @@ -3161,9 +3161,9 @@ _checkConf() { FOUND_REAL_NGINX_CONF="$2" return 0 fi - if cat "$2" | tr "\t" " " | grep "^ *include +.*;" >/dev/null; then + if cat "$2" | tr "\t" " " | grep "^ *include *.*;" >/dev/null; then _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" if ! _startswith "$included" "/" && _exists dirname; then _relpath="$(dirname "$_c_file")" From 80147c7afc2cd8de0e938bc029fed8bbc5a0e649 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 7 Aug 2021 21:06:05 +0800 Subject: [PATCH 303/304] fix https://github.com/acmesh-official/acme.sh/issues/3649 --- acme.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 05b8e07e..d08a0b06 100755 --- a/acme.sh +++ b/acme.sh @@ -20,6 +20,8 @@ _SUB_FOLDER_DEPLOY="deploy" _SUB_FOLDERS="$_SUB_FOLDER_DNSAPI $_SUB_FOLDER_DEPLOY $_SUB_FOLDER_NOTIFY" +CA_LETSENCRYPT_V1="https://acme-v01.api.letsencrypt.org/directory" + CA_LETSENCRYPT_V2="https://acme-v02.api.letsencrypt.org/directory" CA_LETSENCRYPT_V2_TEST="https://acme-staging-v02.api.letsencrypt.org/directory" @@ -5110,7 +5112,7 @@ renew() { . "$DOMAIN_CONF" _debug Le_API "$Le_API" - if [ -z "$Le_API" ]; then + 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" From 98525bf4ed5b9a623f567f2569047f1bccf99d6d Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 8 Aug 2021 08:49:15 +0800 Subject: [PATCH 304/304] fix docker test --- .github/workflows/DNS.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index b00ef263..13066fdd 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -61,22 +61,22 @@ jobs: run: | cd ../acmetest if [ "${{ secrets.TokenName1}}" ] ; then - echo "${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}" >> env.list + echo "${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}" >> docker.env fi if [ "${{ secrets.TokenName2}}" ] ; then - echo "${{ secrets.TokenName2}}=${{ secrets.TokenValue2}}" >> env.list + echo "${{ secrets.TokenName2}}=${{ secrets.TokenValue2}}" >> docker.env fi if [ "${{ secrets.TokenName3}}" ] ; then - echo "${{ secrets.TokenName3}}=${{ secrets.TokenValue3}}" >> env.list + echo "${{ secrets.TokenName3}}=${{ secrets.TokenValue3}}" >> docker.env fi if [ "${{ secrets.TokenName4}}" ] ; then - echo "${{ secrets.TokenName4}}=${{ secrets.TokenValue4}}" >> env.list + echo "${{ secrets.TokenName4}}=${{ secrets.TokenValue4}}" >> docker.env fi if [ "${{ secrets.TokenName5}}" ] ; then - echo "${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}" >> env.list + echo "${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}" >> docker.env fi - echo "TEST_DNS_NO_WILDCARD" >> env.list - echo "TEST_DNS_SLEEP" >> env.list + echo "TEST_DNS_NO_WILDCARD" >> docker.env + echo "TEST_DNS_SLEEP" >> docker.env - name: Run acmetest run: cd ../acmetest && ./rundocker.sh testall