From 8881a9f40e1ae697ec0004670cda032c5a17f1a1 Mon Sep 17 00:00:00 2001 From: Arnaud Launay <2205303+alaunay@users.noreply.github.com> Date: Mon, 5 Oct 2020 15:46:18 +0200 Subject: [PATCH 01/33] Add BookMyName API support --- dnsapi/dns_bookmyname.sh | 93 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 dnsapi/dns_bookmyname.sh diff --git a/dnsapi/dns_bookmyname.sh b/dnsapi/dns_bookmyname.sh new file mode 100644 index 00000000..188d93cb --- /dev/null +++ b/dnsapi/dns_bookmyname.sh @@ -0,0 +1,93 @@ +#!/usr/bin/env sh + +#Here is a sample custom api script. +#This file name is "dns_bookmyname.sh" +#So, here must be a method dns_bookmyname_add() +#Which will be called by acme.sh to add the txt record to your api system. +#returns 0 means success, otherwise error. +# +#Author: Neilpang +#Report Bugs here: https://github.com/acmesh-official/acme.sh +# +######## Public functions ##################### + +# Please Read this guide first: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Dev-Guide + + +# BMN urls: +# https://BMN_USER:BMN_PASSWORD@www.bookmyname.com/dyndns/?hostname=_acme-challenge.domain.tld&type=txt&ttl=300&do=add&value="XXXXXXXX"' +# https://BMN_USER:BMN_PASSWORD@www.bookmyname.com/dyndns/?hostname=_acme-challenge.domain.tld&type=txt&ttl=300&do=remove&value="XXXXXXXX"' + +# Output: +#good: update done, cid 123456, domain id 456789, type txt, ip XXXXXXXX +#good: remove done 1, cid 123456, domain id 456789, ttl 300, type txt, ip XXXXXXXX + +# Be careful, BMN DNS servers can be slow to pick up changes; using dnssleep is thus advised. + +# Usage: +# export BOOKMYNAME_USERNAME="ABCDE-FREE" +# export BOOKMYNAME_PASSWORD="MyPassword" +# /usr/local/ssl/acme.sh/acme.sh --dns dns_bookmyname --dnssleep 600 --issue -d domain.tld + + +#Usage: dns_bookmyname_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_bookmyname_add() { + fulldomain=$1 + txtvalue=$2 + _info "Using bookmyname" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + BOOKMYNAME_USERNAME="${BOOKMYNAME_USERNAME:-$(_readaccountconf_mutable BOOKMYNAME_USERNAME)}" + BOOKMYNAME_PASSWORD="${BOOKMYNAME_PASSWORD:-$(_readaccountconf_mutable BOOKMYNAME_PASSWORD)}" + + if [ -z "$BOOKMYNAME_USERNAME" ] || [ -z "$BOOKMYNAME_PASSWORD" ]; then + BOOKMYNAME_USERNAME="" + BOOKMYNAME_PASSWORD="" + _err "You didn't specify BookMyName username and password yet." + _err "Please specify them and try again." + return 1 + fi + + #save the credentials to the account conf file. + _saveaccountconf_mutable BOOKMYNAME_USERNAME "$BOOKMYNAME_USERNAME" + _saveaccountconf_mutable BOOKMYNAME_PASSWORD "$BOOKMYNAME_PASSWORD" + + + uri="https://${BOOKMYNAME_USERNAME}:${BOOKMYNAME_PASSWORD}@www.bookmyname.com/dyndns/" + data="?hostname=${fulldomain}&type=TXT&ttl=300&do=add&value=${txtvalue}" + result="$(_get "${uri}${data}")" + _debug "Result: $result" + + if ! _startswith "$result" 'good: update done, cid '; then + _err "Can't add $fulldomain" + return 1 + fi + +} + +#Usage: fulldomain txtvalue +#Remove the txt record after validation. +dns_bookmyname_rm() { + fulldomain=$1 + txtvalue=$2 + _info "Using bookmyname" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + BOOKMYNAME_USERNAME="${BOOKMYNAME_USERNAME:-$(_readaccountconf_mutable BOOKMYNAME_USERNAME)}" + BOOKMYNAME_PASSWORD="${BOOKMYNAME_PASSWORD:-$(_readaccountconf_mutable BOOKMYNAME_PASSWORD)}" + + + uri="https://${BOOKMYNAME_USERNAME}:${BOOKMYNAME_PASSWORD}@www.bookmyname.com/dyndns/" + data="?hostname=${fulldomain}&type=TXT&ttl=300&do=remove&value=${txtvalue}" + result="$(_get "${uri}${data}")" + _debug "Result: $result" + + if ! _startswith "$result" 'good: remove done 1, cid '; then + _info "Can't remove $fulldomain" + fi + +} + +#################### Private functions below ################################## From 4ab5456a984eeafed71a6f56d1dda2830780c446 Mon Sep 17 00:00:00 2001 From: Arnaud Launay <2205303+alaunay@users.noreply.github.com> Date: Mon, 5 Oct 2020 15:49:00 +0200 Subject: [PATCH 02/33] keep shfmt happy --- dnsapi/dns_bookmyname.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/dnsapi/dns_bookmyname.sh b/dnsapi/dns_bookmyname.sh index 188d93cb..99b3b680 100644 --- a/dnsapi/dns_bookmyname.sh +++ b/dnsapi/dns_bookmyname.sh @@ -13,7 +13,6 @@ # Please Read this guide first: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Dev-Guide - # BMN urls: # https://BMN_USER:BMN_PASSWORD@www.bookmyname.com/dyndns/?hostname=_acme-challenge.domain.tld&type=txt&ttl=300&do=add&value="XXXXXXXX"' # https://BMN_USER:BMN_PASSWORD@www.bookmyname.com/dyndns/?hostname=_acme-challenge.domain.tld&type=txt&ttl=300&do=remove&value="XXXXXXXX"' @@ -29,7 +28,6 @@ # export BOOKMYNAME_PASSWORD="MyPassword" # /usr/local/ssl/acme.sh/acme.sh --dns dns_bookmyname --dnssleep 600 --issue -d domain.tld - #Usage: dns_bookmyname_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_bookmyname_add() { fulldomain=$1 @@ -53,7 +51,6 @@ dns_bookmyname_add() { _saveaccountconf_mutable BOOKMYNAME_USERNAME "$BOOKMYNAME_USERNAME" _saveaccountconf_mutable BOOKMYNAME_PASSWORD "$BOOKMYNAME_PASSWORD" - uri="https://${BOOKMYNAME_USERNAME}:${BOOKMYNAME_PASSWORD}@www.bookmyname.com/dyndns/" data="?hostname=${fulldomain}&type=TXT&ttl=300&do=add&value=${txtvalue}" result="$(_get "${uri}${data}")" @@ -78,7 +75,6 @@ dns_bookmyname_rm() { BOOKMYNAME_USERNAME="${BOOKMYNAME_USERNAME:-$(_readaccountconf_mutable BOOKMYNAME_USERNAME)}" BOOKMYNAME_PASSWORD="${BOOKMYNAME_PASSWORD:-$(_readaccountconf_mutable BOOKMYNAME_PASSWORD)}" - uri="https://${BOOKMYNAME_USERNAME}:${BOOKMYNAME_PASSWORD}@www.bookmyname.com/dyndns/" data="?hostname=${fulldomain}&type=TXT&ttl=300&do=remove&value=${txtvalue}" result="$(_get "${uri}${data}")" From 7eea866869031a7a02aea7ada5c27edc37470458 Mon Sep 17 00:00:00 2001 From: Arnaud Launay <2205303+alaunay@users.noreply.github.com> Date: Mon, 5 Oct 2020 15:57:52 +0200 Subject: [PATCH 03/33] BMN -> BookMyName --- dnsapi/dns_bookmyname.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_bookmyname.sh b/dnsapi/dns_bookmyname.sh index 99b3b680..7acdea02 100644 --- a/dnsapi/dns_bookmyname.sh +++ b/dnsapi/dns_bookmyname.sh @@ -21,7 +21,7 @@ #good: update done, cid 123456, domain id 456789, type txt, ip XXXXXXXX #good: remove done 1, cid 123456, domain id 456789, ttl 300, type txt, ip XXXXXXXX -# Be careful, BMN DNS servers can be slow to pick up changes; using dnssleep is thus advised. +# Be careful, BookMyName DNS servers can be slow to pick up changes; using dnssleep is thus advised. # Usage: # export BOOKMYNAME_USERNAME="ABCDE-FREE" From 4a60292f8284bc74c54d7f376bac70b2ded6ecd9 Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 9 Oct 2020 22:33:21 +0800 Subject: [PATCH 04/33] update freebsd --- .github/workflows/DNS.yml | 3 ++- .github/workflows/LetsEncrypt.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 976aff56..b06db229 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -183,10 +183,11 @@ 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.4 + - uses: vmactions/freebsd-vm@v0.0.5 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 + usesh: true run: | if [ "${{ secrets.TokenName1}}" ] ; then export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}} diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index ba5e933d..d71f3ac1 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -106,10 +106,11 @@ 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.4 + - uses: vmactions/freebsd-vm@v0.0.5 with: envs: 'NGROK_TOKEN TEST_LOCAL' prepare: pkg install -y socat curl + usesh: true run: | cd ../acmetest && ./letest.sh From d76fb566a258ad1bdefe0d7629493ca85fbcf51d Mon Sep 17 00:00:00 2001 From: Arnaud Launay <2205303+alaunay@users.noreply.github.com> Date: Sat, 10 Oct 2020 11:02:47 +0200 Subject: [PATCH 05/33] no private functions --- dnsapi/dns_bookmyname.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/dnsapi/dns_bookmyname.sh b/dnsapi/dns_bookmyname.sh index 7acdea02..79e6b14d 100644 --- a/dnsapi/dns_bookmyname.sh +++ b/dnsapi/dns_bookmyname.sh @@ -85,5 +85,3 @@ dns_bookmyname_rm() { fi } - -#################### Private functions below ################################## From b71a088da73f4ecc3a4d3e4a79de0e838f532e5e Mon Sep 17 00:00:00 2001 From: Arnaud Launay <2205303+alaunay@users.noreply.github.com> Date: Sat, 10 Oct 2020 11:46:32 +0200 Subject: [PATCH 06/33] Revert "no private functions" This reverts commit d76fb566a258ad1bdefe0d7629493ca85fbcf51d. --- dnsapi/dns_bookmyname.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dnsapi/dns_bookmyname.sh b/dnsapi/dns_bookmyname.sh index 79e6b14d..7acdea02 100644 --- a/dnsapi/dns_bookmyname.sh +++ b/dnsapi/dns_bookmyname.sh @@ -85,3 +85,5 @@ dns_bookmyname_rm() { fi } + +#################### Private functions below ################################## From 6ee72e119c421474f9d966af37422a186b6a5852 Mon Sep 17 00:00:00 2001 From: Paul Dee Date: Fri, 31 Mar 2023 01:13:41 +0200 Subject: [PATCH 07/33] Spelling / grammar --- dnsapi/dns_loopia.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_loopia.sh b/dnsapi/dns_loopia.sh index 399c7867..60d072e0 100644 --- a/dnsapi/dns_loopia.sh +++ b/dnsapi/dns_loopia.sh @@ -107,7 +107,7 @@ _loopia_load_config() { fi if _contains "$LOOPIA_Password" "'" || _contains "$LOOPIA_Password" '"'; then - _err "Password contains quoute or double quoute and this is not supported by dns_loopia.sh" + _err "Password contains a quotation mark or double quotation marks and this is not supported by dns_loopia.sh" return 1 fi From 623d615cd737de93b73e1c1a70dafb19b41d91f1 Mon Sep 17 00:00:00 2001 From: Martin Arndt <5111490+Eagle3386@users.noreply.github.com> Date: Sun, 28 May 2023 21:42:53 +0200 Subject: [PATCH 08/33] Remove external OTP dependency from synology_dsm.sh Also adapt to DSM 7's API improvements. --- deploy/synology_dsm.sh | 142 +++++++++++++++++++++++------------------ 1 file changed, 79 insertions(+), 63 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index c31a5df0..4e6ce661 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -1,34 +1,35 @@ -#!/usr/bin/env sh +#!/bin/bash -# Here is a script to deploy cert to Synology DSM -# -# It requires following environment variables: -# -# SYNO_Username - Synology Username to login (must be an administrator) -# SYNO_Password - Synology Password to login -# SYNO_Certificate - Certificate description to target for replacement -# -# The following environmental variables may be set if you don't like their -# default values: -# -# SYNO_Scheme - defaults to http -# SYNO_Hostname - defaults to localhost -# SYNO_Port - defaults to 5000 -# SYNO_DID - device ID to skip OTP - defaults to empty -# SYNO_TOTP_SECRET - TOTP secret to generate OTP - defaults to empty -# +################################################################################ +# ACME.sh 3rd party deploy plugin for Synology DSM +################################################################################ +# Authors: Brian Hartvigsen (creator), https://github.com/tresni +# Martin Arndt (contributor), https://troublezone.net/ +# Updated: 2023-05-28 +# Issues: https://github.com/acmesh-official/acme.sh/issues/2727 +################################################################################ +# Usage: +# 1. export SYNO_Username="adminUser" +# 2. export SYNO_Password="adminPassword" +# Optional exports (shown values are the defaults): +# - export SYNO_Certificate="" to replace a specific certificate via description +# - export SYNO_Scheme="http" +# - export SYNO_Hostname="localhost" +# - export SYNO_Port="5000" +# - export SYNO_Device_Name="CertRenewal" - required for skipping 2FA-OTP +# - export SYNO_Device_ID="" - required for skipping 2FA-OTP +# 3. acme.sh --deploy --deploy-hook synology_dsm -d example.com +################################################################################ # Dependencies: -# ------------- -# - jq and curl -# - oathtool (When using 2 Factor Authentication and SYNO_TOTP_SECRET is set) -# -#returns 0 means success, otherwise error. - -######## Public functions ##################### +# - jq & curl +################################################################################ +# Return value: +# 0 means success, otherwise error. +################################################################################ +########## Public functions #################################################### #domain keyfile certfile cafile fullchain synology_dsm_deploy() { - _cdomain="$1" _ckey="$2" _ccert="$3" @@ -36,34 +37,39 @@ synology_dsm_deploy() { _debug _cdomain "$_cdomain" - # Get Username and Password, but don't save until we successfully authenticate + # Get username & password, but don't save until we authenticated successfully _getdeployconf SYNO_Username _getdeployconf SYNO_Password _getdeployconf SYNO_Create - _getdeployconf SYNO_DID - _getdeployconf SYNO_TOTP_SECRET + _getdeployconf SYNO_Device_Name + _getdeployconf SYNO_Device_ID if [ -z "${SYNO_Username:-}" ] || [ -z "${SYNO_Password:-}" ]; then _err "SYNO_Username & SYNO_Password must be set" return 1 fi + if [ -n "${SYNO_Device_Name:-}" ] && [ -z "${SYNO_Device_ID:-}" ]; then + _err "SYNO_Device_Name set, but SYNO_Device_ID is empty" + return 1 + fi _debug2 SYNO_Username "$SYNO_Username" _secure_debug2 SYNO_Password "$SYNO_Password" + _debug2 SYNO_Create "$SYNO_Create" + _debug2 SYNO_Device_Name "$SYNO_Device_Name" + _secure_debug2 SYNO_Device_ID "$SYNO_Device_ID" - # Optional scheme, hostname, and port for Synology DSM + # Optional scheme, hostname & port for Synology DSM _getdeployconf SYNO_Scheme _getdeployconf SYNO_Hostname _getdeployconf SYNO_Port - # default vaules for scheme, hostname, and port - # defaulting to localhost and http because it's localhost... + # Default values for scheme, hostname & port + # Defaulting to localhost & http, because it's localhost… [ -n "${SYNO_Scheme}" ] || SYNO_Scheme="http" [ -n "${SYNO_Hostname}" ] || SYNO_Hostname="localhost" [ -n "${SYNO_Port}" ] || SYNO_Port="5000" - _savedeployconf SYNO_Scheme "$SYNO_Scheme" _savedeployconf SYNO_Hostname "$SYNO_Hostname" _savedeployconf SYNO_Port "$SYNO_Port" - _debug2 SYNO_Scheme "$SYNO_Scheme" _debug2 SYNO_Hostname "$SYNO_Hostname" _debug2 SYNO_Port "$SYNO_Port" @@ -87,49 +93,49 @@ synology_dsm_deploy() { _debug3 response "$response" _debug3 api_version "$api_version" - # Login, get the token from JSON and session id from cookie + # Login, get the session ID & SynoToken from JSON _info "Logging into $SYNO_Hostname:$SYNO_Port" encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)" encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)" - otp_code="" - if [ -n "$SYNO_TOTP_SECRET" ]; then - if _exists oathtool; then - otp_code="$(oathtool --base32 --totp "${SYNO_TOTP_SECRET}" 2>/dev/null)" - else - _err "oathtool could not be found, install oathtool to use SYNO_TOTP_SECRET" - return 1 + # Get device ID if still empty first, otherwise log in right away + if [ -z "${SYNO_Device_ID:-}" ]; then + printf "Enter OTP code for user '%s': " "$SYNO_Username" + read -r otp_code + if [ -z "${SYNO_Device_Name:-}" ]; then + printf "Enter device name or leave empty for default (CertRenewal): " + read -r SYNO_Device_Name + [ -n "${SYNO_Device_Name}" ] || SYNO_Device_Name="CertRenewal" fi + + response=$(_get "$_base_url/webapi/entry.cgi?api=SYNO.API.Auth&version=$api_version&method=login&format=sid&account=$encoded_username&passwd=$encoded_password&otp_code=$otp_code&enable_syno_token=yes&enable_device_token=yes&device_name=$SYNO_Device_Name") + _debug3 response "$response" + SYNO_Device_ID=$(echo "$response" | grep "device_id" | sed -n 's/.*"device_id" *: *"\([^"]*\).*/\1/p') + _secure_debug2 SYNO_Device_ID "$SYNO_Device_ID" + else + response=$(_get "$_base_url/webapi/entry.cgi?api=SYNO.API.Auth&version=$api_version&method=login&format=sid&account=$encoded_username&passwd=$encoded_password&enable_syno_token=yes&device_name=$SYNO_Device_Name&device_id=$SYNO_Device_ID") + _debug3 response "$response" fi - if [ -n "$SYNO_DID" ]; then - _H1="Cookie: did=$SYNO_DID" - export _H1 - _debug3 H1 "${_H1}" - fi - - response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&api=SYNO.API.Auth&version=$api_version&enable_syno_token=yes&otp_code=$otp_code&device_name=certrenewal&device_id=$SYNO_DID" "$_base_url/webapi/auth.cgi?enable_syno_token=yes") + sid=$(echo "$response" | grep "sid" | sed -n 's/.*"sid" *: *"\([^"]*\).*/\1/p') token=$(echo "$response" | grep "synotoken" | sed -n 's/.*"synotoken" *: *"\([^"]*\).*/\1/p') - _debug3 response "$response" - _debug token "$token" - - if [ -z "$token" ]; then - _err "Unable to authenticate to $SYNO_Hostname:$SYNO_Port using $SYNO_Scheme." - _err "Check your username and password." - _err "If two-factor authentication is enabled for the user, set SYNO_TOTP_SECRET." + _debug Session ID "$sid" + _debug SynoToken "$token" + if [ -z "$SYNO_Device_ID" ] || [ -z "$sid" ] || [ -z "$token" ]; then + _err "Unable to authenticate to $_base_url - check your username & password." + _err "If two-factor authentication is enabled for the user, set SYNO_Device_ID." return 1 fi - sid=$(echo "$response" | grep "sid" | sed -n 's/.*"sid" *: *"\([^"]*\).*/\1/p') _H1="X-SYNO-TOKEN: $token" export _H1 _debug2 H1 "${_H1}" - # Now that we know the username and password are good, save them + # Now that we know the username & password are good, save them _savedeployconf SYNO_Username "$SYNO_Username" _savedeployconf SYNO_Password "$SYNO_Password" - _savedeployconf SYNO_DID "$SYNO_DID" - _savedeployconf SYNO_TOTP_SECRET "$SYNO_TOTP_SECRET" + _savedeployconf SYNO_Device_Name "$SYNO_Device_Name" + _savedeployconf SYNO_Device_ID "$SYNO_Device_ID" _info "Getting certificates in Synology DSM" response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1&_sid=$sid" "$_base_url/webapi/entry.cgi") @@ -140,7 +146,7 @@ synology_dsm_deploy() { _debug2 id "$id" if [ -z "$id" ] && [ -z "${SYNO_Create:-}" ]; then - _err "Unable to find certificate: $SYNO_Certificate and \$SYNO_Create is not set" + _err "Unable to find certificate: $SYNO_Certificate & \$SYNO_Create is not set" return 1 fi @@ -171,13 +177,23 @@ synology_dsm_deploy() { if ! echo "$response" | grep '"error":' >/dev/null; then if echo "$response" | grep '"restart_httpd":true' >/dev/null; then - _info "http services were restarted" + _info "Restarting HTTP services succeeded" else - _info "http services were NOT restarted" + _info "Restarting HTTP services failed" fi + + _logout return 0 else _err "Unable to update certificate, error code $response" + _logout return 1 fi } + +#################### Private functions below ################################## +_logout() { + # Logout to not occupy a permanent session, e. g. in DSM's "Connected Users" widget + response=$(_get "$_base_url/webapi/entry.cgi?api=SYNO.API.Auth&version=$api_version&method=logout") + _debug3 response "$response" +} From 0548ad2fc6b4febe557620ec2280bdec6b7ec304 Mon Sep 17 00:00:00 2001 From: Martin Arndt <5111490+Eagle3386@users.noreply.github.com> Date: Sun, 28 May 2023 22:33:15 +0200 Subject: [PATCH 09/33] Fix debug output of session ID --- 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 4e6ce661..f709e0fb 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -119,7 +119,7 @@ synology_dsm_deploy() { sid=$(echo "$response" | grep "sid" | sed -n 's/.*"sid" *: *"\([^"]*\).*/\1/p') token=$(echo "$response" | grep "synotoken" | sed -n 's/.*"synotoken" *: *"\([^"]*\).*/\1/p') - _debug Session ID "$sid" + _debug "Session ID" "$sid" _debug SynoToken "$token" if [ -z "$SYNO_Device_ID" ] || [ -z "$sid" ] || [ -z "$token" ]; then _err "Unable to authenticate to $_base_url - check your username & password." From f680ede9802fb7e1dfa5a68da53c50675bfa9607 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 10 Jun 2023 01:16:57 +0800 Subject: [PATCH 10/33] start 3.0.7 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 633eb9fa..0cc52131 100755 --- a/acme.sh +++ b/acme.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -VER=3.0.6 +VER=3.0.7 PROJECT_NAME="acme.sh" From 0d0478245fe4ac60eec7ab1621fa47fda3bfd27a Mon Sep 17 00:00:00 2001 From: Adrian Fedoreanu Date: Sat, 26 Nov 2022 20:11:41 +0100 Subject: [PATCH 11/33] dns_1984hosting.sh: fix login with valid csrftoken and sessionid --- dnsapi/dns_1984hosting.sh | 156 ++++++++++++++++++++------------------ 1 file changed, 84 insertions(+), 72 deletions(-) diff --git a/dnsapi/dns_1984hosting.sh b/dnsapi/dns_1984hosting.sh index 6accc597..2c6b2e4f 100755 --- a/dnsapi/dns_1984hosting.sh +++ b/dnsapi/dns_1984hosting.sh @@ -1,46 +1,46 @@ #!/usr/bin/env sh -#This file name is "dns_1984hosting.sh" -#So, here must be a method dns_1984hosting_add() -#Which will be called by acme.sh to add the txt record to your api system. -#returns 0 means success, otherwise error. +# This file name is "dns_1984hosting.sh" +# So, here must be a method dns_1984hosting_add() +# Which will be called by acme.sh to add the txt record to your api system. +# returns 0 means success, otherwise error. -#Author: Adrian Fedoreanu -#Report Bugs here: https://github.com/acmesh-official/acme.sh +# Author: Adrian Fedoreanu +# Report Bugs here: https://github.com/acmesh-official/acme.sh # or here... https://github.com/acmesh-official/acme.sh/issues/2851 -# -######## Public functions ##################### + +######## Public functions ##################### # Export 1984HOSTING username and password in following variables # # One984HOSTING_Username=username # One984HOSTING_Password=password # -# sessionid cookie is saved in ~/.acme.sh/account.conf -# username/password need to be set only when changed. +# username/password and csrftoken/sessionid cookies are saved in ~/.acme.sh/account.conf -#Usage: dns_1984hosting_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +# Usage: dns_1984hosting_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +# Add a text record. dns_1984hosting_add() { fulldomain=$1 txtvalue=$2 - _info "Add TXT record using 1984Hosting" + _info "Add TXT record using 1984Hosting." _debug fulldomain "$fulldomain" _debug txtvalue "$txtvalue" if ! _1984hosting_login; then - _err "1984Hosting login failed for user $One984HOSTING_Username. Check $HTTP_HEADER file" + _err "1984Hosting login failed for user $One984HOSTING_Username. Check $HTTP_HEADER file." return 1 fi - _debug "First detect the root zone" + _debug "First detect the root zone." if ! _get_root "$fulldomain"; then - _err "invalid domain" "$fulldomain" + _err "Invalid domain '$fulldomain'." return 1 fi _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - _debug "Add TXT record $fulldomain with value '$txtvalue'" + _debug "Add TXT record $fulldomain with value '$txtvalue'." value="$(printf '%s' "$txtvalue" | _url_encode)" url="https://1984.hosting/domains/entry/" @@ -53,93 +53,97 @@ dns_1984hosting_add() { _debug2 postdata "$postdata" _authpost "$postdata" "$url" - response="$(echo "$_response" | _normalizeJson)" - _debug2 response "$response" - - if _contains "$response" '"haserrors": true'; then - _err "1984Hosting failed to add TXT record for $_sub_domain bad RC from _post" + 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" "html>"; then - _err "1984Hosting failed to add TXT record for $_sub_domain. Check $HTTP_HEADER file" + 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 - _err "1984Hosting failed to add TXT record for $_sub_domain. Invalid or expired cookie" + elif _contains "$_response" '"auth": false'; then + _err "1984Hosting failed to add TXT record for $_sub_domain. Invalid or expired cookie." return 1 fi - _info "Added acme challenge TXT record for $fulldomain at 1984Hosting" + _info "Added acme challenge TXT record for $fulldomain at 1984Hosting." return 0 } -#Usage: fulldomain txtvalue -#Remove the txt record after validation. +# Usage: fulldomain txtvalue +# Remove the txt record after validation. dns_1984hosting_rm() { fulldomain=$1 txtvalue=$2 - _info "Delete TXT record using 1984Hosting" + _info "Delete TXT record using 1984Hosting." _debug fulldomain "$fulldomain" _debug txtvalue "$txtvalue" if ! _1984hosting_login; then - _err "1984Hosting login failed for user $One984HOSTING_Username. Check $HTTP_HEADER file" + _err "1984Hosting login failed for user $One984HOSTING_Username. Check $HTTP_HEADER file." return 1 fi - _debug "First detect the root zone" + _debug "First detect the root zone." if ! _get_root "$fulldomain"; then - _err "invalid domain" "$fulldomain" + _err "Invalid domain '$fulldomain'." return 1 fi _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - _debug "Delete $fulldomain TXT record" + _debug "Delete $fulldomain TXT record." url="https://1984.hosting/domains" if ! _get_zone_id "$url" "$_domain"; then - _err "invalid zone" "$_domain" + _err "Invalid zone '$_domain'." return 1 fi _htmlget "$url/$_zone_id" "$txtvalue" - _debug2 _response "$_response" entry_id="$(echo "$_response" | _egrep_o 'entry_[0-9]+' | sed 's/entry_//')" _debug2 entry_id "$entry_id" if [ -z "$entry_id" ]; then - _err "Error getting TXT entry_id for $1" + _err "Error getting TXT entry_id for $1." return 1 fi _authpost "entry=$entry_id" "$url/delentry/" - response="$(echo "$_response" | _normalizeJson)" - _debug2 response "$response" - - if ! _contains "$response" '"ok": true'; then - _err "1984Hosting failed to delete TXT record for $entry_id bad RC from _post" + if ! _contains "$_response" '"ok": true'; then + _err "1984Hosting failed to delete TXT record for $entry_id bad RC from _post." return 1 fi - _info "Deleted acme challenge TXT record for $fulldomain at 1984Hosting" + _info "Deleted acme challenge TXT record for $fulldomain at 1984Hosting." return 0 } #################### Private functions below ################################## - -# usage: _1984hosting_login username password -# returns 0 success _1984hosting_login() { if ! _check_credentials; then return 1; fi if _check_cookies; then - _debug "Already logged in" + _debug "Already logged in." return 0 fi - _debug "Login to 1984Hosting as user $One984HOSTING_Username" + _debug "Login to 1984Hosting as user $One984HOSTING_Username." username=$(printf '%s' "$One984HOSTING_Username" | _url_encode) password=$(printf '%s' "$One984HOSTING_Password" | _url_encode) url="https://1984.hosting/accounts/checkuserauth/" + _get "https://1984.hosting/accounts/login/" | grep "csrfmiddlewaretoken" + csrftoken="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'csrftoken=[^;]*;' | tr -d ';')" + sessionid="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'sessionid=[^;]*;' | tr -d ';')" + + if [ -z "$csrftoken" ] || [ -z "$sessionid" ]; then + _err "One or more cookies are empty: '$csrftoken', '$sessionid'." + return 1 + fi + + export _H1="Cookie: $csrftoken; $sessionid" + export _H2="Referer: https://1984.hosting/accounts/login/" + csrf_header=$(echo "$csrftoken" | sed 's/csrftoken=//' | _head_n 1) + export _H3="X-CSRFToken: $csrf_header" + response="$(_post "username=$username&password=$password&otpkey=" $url)" response="$(echo "$response" | _normalizeJson)" _debug2 response "$response" @@ -149,6 +153,8 @@ _1984hosting_login() { One984HOSTING_CSRFTOKEN_COOKIE="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'csrftoken=[^;]*;' | tr -d ';')" export One984HOSTING_SESSIONID_COOKIE export One984HOSTING_CSRFTOKEN_COOKIE + _saveaccountconf_mutable One984HOSTING_Username "$One984HOSTING_Username" + _saveaccountconf_mutable One984HOSTING_Password "$One984HOSTING_Password" _saveaccountconf_mutable One984HOSTING_SESSIONID_COOKIE "$One984HOSTING_SESSIONID_COOKIE" _saveaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE "$One984HOSTING_CSRFTOKEN_COOKIE" return 0 @@ -157,9 +163,13 @@ _1984hosting_login() { } _check_credentials() { + One984HOSTING_Username="${One984HOSTING_Username:-$(_readaccountconf_mutable One984HOSTING_Username)}" + One984HOSTING_Password="${One984HOSTING_Password:-$(_readaccountconf_mutable One984HOSTING_Password)}" if [ -z "$One984HOSTING_Username" ] || [ -z "$One984HOSTING_Password" ]; then One984HOSTING_Username="" One984HOSTING_Password="" + _clearaccountconf_mutable One984HOSTING_Username + _clearaccountconf_mutable One984HOSTING_Password _err "You haven't specified 1984Hosting username or password yet." _err "Please export as One984HOSTING_Username / One984HOSTING_Password and try again." return 1 @@ -171,42 +181,43 @@ _check_cookies() { One984HOSTING_SESSIONID_COOKIE="${One984HOSTING_SESSIONID_COOKIE:-$(_readaccountconf_mutable One984HOSTING_SESSIONID_COOKIE)}" One984HOSTING_CSRFTOKEN_COOKIE="${One984HOSTING_CSRFTOKEN_COOKIE:-$(_readaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE)}" if [ -z "$One984HOSTING_SESSIONID_COOKIE" ] || [ -z "$One984HOSTING_CSRFTOKEN_COOKIE" ]; then - _debug "No cached cookie(s) found" + _debug "No cached cookie(s) found." return 1 fi _authget "https://1984.hosting/accounts/loginstatus/" - if _contains "$response" '"ok": true'; then - _debug "Cached cookies still valid" + if _contains "$_response" '"ok": true'; then + _debug "Cached cookies still valid." return 0 fi - _debug "Cached cookies no longer valid" + + _debug "Cached cookies no longer valid. Clearing cookies." One984HOSTING_SESSIONID_COOKIE="" One984HOSTING_CSRFTOKEN_COOKIE="" - _saveaccountconf_mutable One984HOSTING_SESSIONID_COOKIE "$One984HOSTING_SESSIONID_COOKIE" - _saveaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE "$One984HOSTING_CSRFTOKEN_COOKIE" + _clearaccountconf_mutable One984HOSTING_SESSIONID_COOKIE + _clearaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE return 1 } -#_acme-challenge.www.domain.com -#returns -# _sub_domain=_acme-challenge.www -# _domain=domain.com +# _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) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) + # not valid if [ -z "$h" ]; then - #not valid return 1 fi _authget "https://1984.hosting/domains/soacheck/?zone=$h&nameserver=ns0.1984.is." if _contains "$_response" "serial" && ! _contains "$_response" "null"; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _domain="$h" return 0 fi @@ -216,46 +227,47 @@ _get_root() { return 1 } -#usage: _get_zone_id url domain.com -#returns zone id for domain.com +# Usage: _get_zone_id url domain.com +# Returns zone id for domain.com _get_zone_id() { url=$1 domain=$2 _htmlget "$url" "$domain" - _debug2 _response "$_response" _zone_id="$(echo "$_response" | _egrep_o 'zone\/[0-9]+' | _head_n 1)" _debug2 _zone_id "$_zone_id" if [ -z "$_zone_id" ]; then - _err "Error getting _zone_id for $2" + _err "Error getting _zone_id for $2." return 1 fi return 0 } -# add extra headers to request +# Add extra headers to request _authget() { - export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE;$One984HOSTING_SESSIONID_COOKIE" + export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE; $One984HOSTING_SESSIONID_COOKIE" _response=$(_get "$1" | _normalizeJson) _debug2 _response "$_response" } -# truncate huge HTML response -# echo: Argument list too long +# Truncate huge HTML response +# Echo: Argument list too long _htmlget() { - export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE;$One984HOSTING_SESSIONID_COOKIE" + export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE; $One984HOSTING_SESSIONID_COOKIE" _response=$(_get "$1" | grep "$2") if _contains "$_response" "@$2"; then _response=$(echo "$_response" | grep -v "[@]" | _head_n 1) fi + _debug2 _response "$_response" } -# add extra headers to request +# Add extra headers to request _authpost() { url="https://1984.hosting/domains" _get_zone_id "$url" "$_domain" csrf_header="$(echo "$One984HOSTING_CSRFTOKEN_COOKIE" | _egrep_o "=[^=][0-9a-zA-Z]*" | tr -d "=")" - export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE;$One984HOSTING_SESSIONID_COOKIE" + export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE; $One984HOSTING_SESSIONID_COOKIE" export _H2="Referer: https://1984.hosting/domains/$_zone_id" export _H3="X-CSRFToken: $csrf_header" - _response=$(_post "$1" "$2") + _response="$(_post "$1" "$2" | _normalizeJson)" + _debug2 _response "$_response" } From db3f131dfc92022fda39386b6b2f2ac33a29e010 Mon Sep 17 00:00:00 2001 From: Martin Arndt <5111490+Eagle3386@users.noreply.github.com> Date: Tue, 4 Jul 2023 15:47:19 +0200 Subject: [PATCH 12/33] Re-add deprecated SYNO_TOTP_SECRET part for legacy compatibility As requested in acmesh-official/acme.sh/pull/4646 by Neil Pang --- deploy/synology_dsm.sh | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index f709e0fb..406c6ac0 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -5,7 +5,7 @@ ################################################################################ # Authors: Brian Hartvigsen (creator), https://github.com/tresni # Martin Arndt (contributor), https://troublezone.net/ -# Updated: 2023-05-28 +# Updated: 2023-07-03 # Issues: https://github.com/acmesh-official/acme.sh/issues/2727 ################################################################################ # Usage: @@ -41,6 +41,8 @@ synology_dsm_deploy() { _getdeployconf SYNO_Username _getdeployconf SYNO_Password _getdeployconf SYNO_Create + _getdeployconf SYNO_DID + _getdeployconf SYNO_TOTP_SECRET _getdeployconf SYNO_Device_Name _getdeployconf SYNO_Device_ID if [ -z "${SYNO_Username:-}" ] || [ -z "${SYNO_Password:-}" ]; then @@ -74,7 +76,7 @@ synology_dsm_deploy() { _debug2 SYNO_Hostname "$SYNO_Hostname" _debug2 SYNO_Port "$SYNO_Port" - # Get the certificate description, but don't save it until we verfiy it's real + # Get the certificate description, but don't save it until we verify it's real _getdeployconf SYNO_Certificate _debug SYNO_Certificate "${SYNO_Certificate:-}" @@ -97,9 +99,31 @@ synology_dsm_deploy() { _info "Logging into $SYNO_Hostname:$SYNO_Port" encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)" encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)" + + # START - DEPRECATED, only kept for legacy compatibility reasons + if [ -n "$SYNO_TOTP_SECRET" ]; then + _info "WARNING: Usage of SYNO_TOTP_SECRET is deprecated!" + _info " See synology_dsm.sh script or ACME.sh Wiki page for details:" + _info " https://github.com/acmesh-official/acme.sh/wiki/Synology-NAS-Guide" + DEPRECATED_otp_code="" + if _exists oathtool; then + DEPRECATED_otp_code="$(oathtool --base32 --totp "${SYNO_TOTP_SECRET}" 2>/dev/null)" + else + _err "oathtool could not be found, install oathtool to use SYNO_TOTP_SECRET" + return 1 + fi + if [ -n "$SYNO_DID" ]; then + _H1="Cookie: did=$SYNO_DID" + export _H1 + _debug3 H1 "${_H1}" + fi + + response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&api=SYNO.API.Auth&version=$api_version&enable_syno_token=yes&otp_code=$otp_code&device_name=certrenewal&device_id=$SYNO_DID" "$_base_url/webapi/auth.cgi?enable_syno_token=yes") + _debug3 response "$response" + # END - DEPRECATED, only kept for legacy compatibility reasons # Get device ID if still empty first, otherwise log in right away - if [ -z "${SYNO_Device_ID:-}" ]; then + elif [ -z "${SYNO_Device_ID:-}" ]; then printf "Enter OTP code for user '%s': " "$SYNO_Username" read -r otp_code if [ -z "${SYNO_Device_Name:-}" ]; then @@ -121,7 +145,7 @@ synology_dsm_deploy() { token=$(echo "$response" | grep "synotoken" | sed -n 's/.*"synotoken" *: *"\([^"]*\).*/\1/p') _debug "Session ID" "$sid" _debug SynoToken "$token" - if [ -z "$SYNO_Device_ID" ] || [ -z "$sid" ] || [ -z "$token" ]; then + if [ -z "$SYNO_DID" && -z "$SYNO_Device_ID" ] || [ -z "$sid" ] || [ -z "$token" ]; then _err "Unable to authenticate to $_base_url - check your username & password." _err "If two-factor authentication is enabled for the user, set SYNO_Device_ID." return 1 @@ -150,7 +174,7 @@ synology_dsm_deploy() { return 1 fi - # we've verified this certificate description is a thing, so save it + # We've verified this certificate description is a thing, so save it _savedeployconf SYNO_Certificate "$SYNO_Certificate" "base64" _info "Generate form POST request" @@ -162,10 +186,10 @@ synology_dsm_deploy() { 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\":\"$escaped_certificate\",\([^{]*\).*/\1/p" | grep -- 'is_default":true' >/dev/null; then - _debug2 default "this is the default certificate" + _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" + _debug2 default "This is NOT the default certificate" fi content="$content${nl}--$delim--${nl}" content="$(printf "%b_" "$content")" @@ -193,7 +217,7 @@ synology_dsm_deploy() { #################### Private functions below ################################## _logout() { - # Logout to not occupy a permanent session, e. g. in DSM's "Connected Users" widget + # Logout to not occupy a permanent session, e.g. in DSM's "Connected Users" widget response=$(_get "$_base_url/webapi/entry.cgi?api=SYNO.API.Auth&version=$api_version&method=logout") _debug3 response "$response" } From 0c9e4f67a89bfbc6ee14802139324c3b80c3ac03 Mon Sep 17 00:00:00 2001 From: Martin Arndt <5111490+Eagle3386@users.noreply.github.com> Date: Tue, 4 Jul 2023 15:55:44 +0200 Subject: [PATCH 13/33] Update synology_dsm.sh Split "[ && ]" into "[ ] && [ ]" to make ShellCheck happy --- 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 406c6ac0..04d59e55 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -145,7 +145,7 @@ synology_dsm_deploy() { token=$(echo "$response" | grep "synotoken" | sed -n 's/.*"synotoken" *: *"\([^"]*\).*/\1/p') _debug "Session ID" "$sid" _debug SynoToken "$token" - if [ -z "$SYNO_DID" && -z "$SYNO_Device_ID" ] || [ -z "$sid" ] || [ -z "$token" ]; then + if [ -z "$SYNO_DID" ] && [ -z "$SYNO_Device_ID" ] || [ -z "$sid" ] || [ -z "$token" ]; then _err "Unable to authenticate to $_base_url - check your username & password." _err "If two-factor authentication is enabled for the user, set SYNO_Device_ID." return 1 From 0d7b831661dc01ba28d8b461c930049cea3e6ea4 Mon Sep 17 00:00:00 2001 From: Martin Arndt <5111490+Eagle3386@users.noreply.github.com> Date: Tue, 4 Jul 2023 16:58:14 +0200 Subject: [PATCH 14/33] Fix variable initialization --- deploy/synology_dsm.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 04d59e55..7398b350 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -99,7 +99,8 @@ synology_dsm_deploy() { _info "Logging into $SYNO_Hostname:$SYNO_Port" encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)" encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)" - + + otp_code="" # START - DEPRECATED, only kept for legacy compatibility reasons if [ -n "$SYNO_TOTP_SECRET" ]; then _info "WARNING: Usage of SYNO_TOTP_SECRET is deprecated!" @@ -119,7 +120,7 @@ synology_dsm_deploy() { _debug3 H1 "${_H1}" fi - response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&api=SYNO.API.Auth&version=$api_version&enable_syno_token=yes&otp_code=$otp_code&device_name=certrenewal&device_id=$SYNO_DID" "$_base_url/webapi/auth.cgi?enable_syno_token=yes") + response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&api=SYNO.API.Auth&version=$api_version&enable_syno_token=yes&otp_code=$DEPRECATED_otp_code&device_name=certrenewal&device_id=$SYNO_DID" "$_base_url/webapi/auth.cgi?enable_syno_token=yes") _debug3 response "$response" # END - DEPRECATED, only kept for legacy compatibility reasons # Get device ID if still empty first, otherwise log in right away From e0d96bcb3928fda0c8e40ffa189578250822323a Mon Sep 17 00:00:00 2001 From: Steven Zhu Date: Tue, 4 Jul 2023 21:54:49 -0400 Subject: [PATCH 15/33] Add initial AWS SES support Copied most of the v4 api stuff from DNS_AWS hook (Thanks!) New tokens added: AWS_SES_ACCESS_KEY_ID AWS_SES_SECRET_ACCESS_KEY AWS_SES_REGION AWS_SES_TO AWS_SES_FROM AWS_SES_FROM_NAME (Optional) --- notify/aws_ses.sh | 226 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 notify/aws_ses.sh diff --git a/notify/aws_ses.sh b/notify/aws_ses.sh new file mode 100644 index 00000000..0741ca81 --- /dev/null +++ b/notify/aws_ses.sh @@ -0,0 +1,226 @@ +#!/usr/bin/env sh + +# +#AWS_SES_ACCESS_KEY_ID="sdfsdfsdfljlbjkljlkjsdfoiwje" +# +#AWS_SES_SECRET_ACCESS_KEY="xxxxxxx" +# +#AWS_SES_REGION="us-east-1" +# +#AWS_SES_TO="xxxx@xxx.com" +# +#AWS_SES_FROM="xxxx@cccc.com" +# +#AWS_SES_FROM_NAME="Something something" +#This is the Amazon SES api wrapper for acme.sh +AWS_WIKI="https://docs.aws.amazon.com/ses/latest/dg/send-email-api.html" + +aws_ses_send() { + _subject="$1" + _content="$2" + _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped + _debug "_statusCode" "$_statusCode" + + AWS_SES_ACCESS_KEY_ID="${AWS_SES_ACCESS_KEY_ID:-$(_readaccountconf_mutable AWS_SES_ACCESS_KEY_ID)}" + AWS_SES_SECRET_ACCESS_KEY="${AWS_SES_SECRET_ACCESS_KEY:-$(_readaccountconf_mutable AWS_SES_SECRET_ACCESS_KEY)}" + AWS_SES_REGION="${AWS_SES_REGION:-$(_readaccountconf_mutable AWS_SES_REGION)}" + + + if [ -z "$AWS_SES_ACCESS_KEY_ID" ] || [ -z "$AWS_SES_SECRET_ACCESS_KEY" ]; then + _use_container_role || _use_instance_role + fi + + if [ -z "$AWS_SES_ACCESS_KEY_ID" ] || [ -z "$AWS_SES_SECRET_ACCESS_KEY" ]; then + AWS_SES_ACCESS_KEY_ID="" + AWS_SES_SECRET_ACCESS_KEY="" + _err "You haven't specified the aws SES api key id and and api key secret yet." + _err "Please create your key and try again. see $(__green $AWS_WIKI)" + return 1 + fi + + if [ -z "$AWS_SES_REGION" ]; then + AWS_SES_REGION="" + _err "You haven't specified the aws SES api region yet." + _err "Please specify your region and try again. see https://docs.aws.amazon.com/general/latest/gr/ses.html" + return 1 + fi + + #save for future use, unless using a role which will be fetched as needed + if [ -z "$_using_role" ]; then + _saveaccountconf_mutable AWS_SES_ACCESS_KEY_ID "$AWS_SES_ACCESS_KEY_ID" + _saveaccountconf_mutable AWS_SES_SECRET_ACCESS_KEY "$AWS_SES_SECRET_ACCESS_KEY" + fi + + AWS_SES_TO="${AWS_SES_TO:-$(_readaccountconf_mutable AWS_SES_TO)}" + if [ -z "$AWS_SES_TO" ]; then + AWS_SES_TO="" + _err "You didn't specify an email to AWS_SES_TO receive messages." + return 1 + fi + _saveaccountconf_mutable AWS_SES_TO "$AWS_SES_TO" + + AWS_SES_FROM="${AWS_SES_FROM:-$(_readaccountconf_mutable AWS_SES_FROM)}" + if [ -z "$AWS_SES_FROM" ]; then + AWS_SES_FROM="" + _err "You didn't specify an email to AWS_SES_FROM receive messages." + return 1 + fi + _saveaccountconf_mutable AWS_SES_FROM "$AWS_SES_FROM" + + AWS_SES_FROM_NAME="${AWS_SES_FROM_NAME:-$(_readaccountconf_mutable AWS_SES_FROM_NAME)}" + _saveaccountconf_mutable AWS_SES_FROM_NAME "$AWS_SES_FROM_NAME" + + AWS_SES_SENDFROM="$AWS_SES_FROM_NAME <$AWS_SES_FROM>" + + AWS_SES_ACTION="Action=SendEmail" + AWS_SES_SOURCE="Source=$AWS_SES_SENDFROM" + AWS_SES_TO="Destination.ToAddresses.member.1=$AWS_SES_TO" + AWS_SES_SUBJECT="Message.Subject.Data=$_subject" + AWS_SES_MESSAGE="Message.Body.Text.Data=$_content" + + _data="${AWS_SES_ACTION}&${AWS_SES_SOURCE}&${AWS_SES_TO}&${AWS_SES_SUBJECT}&${AWS_SES_MESSAGE}" + + response="$(aws_rest POST "" "" "$_data")" +} + +_use_metadata() { + _aws_creds="$( + _get "$1" "" 1 | + _normalizeJson | + tr '{,}' '\n' | + while read -r _line; do + _key="$(echo "${_line%%:*}" | tr -d '"')" + _value="${_line#*:}" + _debug3 "_key" "$_key" + _secure_debug3 "_value" "$_value" + case "$_key" in + AccessKeyId) echo "AWS_SES_ACCESS_KEY_ID=$_value" ;; + SecretAccessKey) echo "AWS_SES_SECRET_ACCESS_KEY=$_value" ;; + Token) echo "AWS_SESSION_TOKEN=$_value" ;; + esac + done | + paste -sd' ' - + )" + _secure_debug "_aws_creds" "$_aws_creds" + + if [ -z "$_aws_creds" ]; then + return 1 + fi + + eval "$_aws_creds" + _using_role=true +} + +#method uri qstr data +aws_rest() { + mtd="$1" + ep="$2" + qsr="$3" + data="$4" + + _debug mtd "$mtd" + _debug ep "$ep" + _debug qsr "$qsr" + _debug data "$data" + + CanonicalURI="/$ep" + _debug2 CanonicalURI "$CanonicalURI" + + CanonicalQueryString="$qsr" + _debug2 CanonicalQueryString "$CanonicalQueryString" + + RequestDate="$(date -u +"%Y%m%dT%H%M%SZ")" + _debug2 RequestDate "$RequestDate" + + #RequestDate="20161120T141056Z" ############## + + export _H1="x-amz-date: $RequestDate" + + aws_host="email.$AWS_SES_REGION.amazonaws.com" + CanonicalHeaders="host:$aws_host\nx-amz-date:$RequestDate\n" + SignedHeaders="host;x-amz-date" + if [ -n "$AWS_SESSION_TOKEN" ]; then + export _H3="x-amz-security-token: $AWS_SESSION_TOKEN" + CanonicalHeaders="${CanonicalHeaders}x-amz-security-token:$AWS_SESSION_TOKEN\n" + SignedHeaders="${SignedHeaders};x-amz-security-token" + fi + _debug2 CanonicalHeaders "$CanonicalHeaders" + _debug2 SignedHeaders "$SignedHeaders" + + RequestPayload="$data" + _debug2 RequestPayload "$RequestPayload" + + Hash="sha256" + + CanonicalRequest="$mtd\n$CanonicalURI\n$CanonicalQueryString\n$CanonicalHeaders\n$SignedHeaders\n$(printf "%s" "$RequestPayload" | _digest "$Hash" hex)" + _debug2 CanonicalRequest "$CanonicalRequest" + + HashedCanonicalRequest="$(printf "$CanonicalRequest%s" | _digest "$Hash" hex)" + _debug2 HashedCanonicalRequest "$HashedCanonicalRequest" + + Algorithm="AWS4-HMAC-SHA256" + _debug2 Algorithm "$Algorithm" + + RequestDateOnly="$(echo "$RequestDate" | cut -c 1-8)" + _debug2 RequestDateOnly "$RequestDateOnly" + + Region="$AWS_SES_REGION" + Service="ses" + + CredentialScope="$RequestDateOnly/$Region/$Service/aws4_request" + _debug2 CredentialScope "$CredentialScope" + + StringToSign="$Algorithm\n$RequestDate\n$CredentialScope\n$HashedCanonicalRequest" + + _debug2 StringToSign "$StringToSign" + + kSecret="AWS4$AWS_SES_SECRET_ACCESS_KEY" + + #kSecret="wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY" ############################ + + _secure_debug2 kSecret "$kSecret" + + kSecretH="$(printf "%s" "$kSecret" | _hex_dump | tr -d " ")" + _secure_debug2 kSecretH "$kSecretH" + + kDateH="$(printf "$RequestDateOnly%s" | _hmac "$Hash" "$kSecretH" hex)" + _debug2 kDateH "$kDateH" + + kRegionH="$(printf "$Region%s" | _hmac "$Hash" "$kDateH" hex)" + _debug2 kRegionH "$kRegionH" + + kServiceH="$(printf "$Service%s" | _hmac "$Hash" "$kRegionH" hex)" + _debug2 kServiceH "$kServiceH" + + kSigningH="$(printf "%s" "aws4_request" | _hmac "$Hash" "$kServiceH" hex)" + _debug2 kSigningH "$kSigningH" + + signature="$(printf "$StringToSign%s" | _hmac "$Hash" "$kSigningH" hex)" + _debug2 signature "$signature" + + Authorization="$Algorithm Credential=$AWS_SES_ACCESS_KEY_ID/$CredentialScope, SignedHeaders=$SignedHeaders, Signature=$signature" + _debug2 Authorization "$Authorization" + + _H2="Authorization: $Authorization" + _debug _H2 "$_H2" + + url="https://$aws_host/$ep" + if [ "$qsr" ]; then + url="https://$aws_host/$ep?$qsr" + fi + + if [ "$mtd" = "GET" ]; then + response="$(_get "$url")" + else + response="$(_post "$data" "$url")" + fi + + _ret="$?" + _debug2 response "$response" + if [ "$_ret" = "0" ]; then + if _contains "$response" " Date: Tue, 4 Jul 2023 22:14:17 -0400 Subject: [PATCH 16/33] Add newline at end of file to satisfy shfmt's "No newline at end of file" error --- notify/aws_ses.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notify/aws_ses.sh b/notify/aws_ses.sh index 0741ca81..3d4de630 100644 --- a/notify/aws_ses.sh +++ b/notify/aws_ses.sh @@ -223,4 +223,4 @@ aws_rest() { return 1 fi fi -} \ No newline at end of file +} From 8d136c6a25484687cc802b1425c48cbe6f63982d Mon Sep 17 00:00:00 2001 From: Steven Zhu Date: Tue, 4 Jul 2023 22:15:53 -0400 Subject: [PATCH 17/33] Add newline at end of file to satisfy shfmt's "extra line" error --- notify/aws_ses.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/notify/aws_ses.sh b/notify/aws_ses.sh index 3d4de630..1060763d 100644 --- a/notify/aws_ses.sh +++ b/notify/aws_ses.sh @@ -25,7 +25,6 @@ aws_ses_send() { AWS_SES_SECRET_ACCESS_KEY="${AWS_SES_SECRET_ACCESS_KEY:-$(_readaccountconf_mutable AWS_SES_SECRET_ACCESS_KEY)}" AWS_SES_REGION="${AWS_SES_REGION:-$(_readaccountconf_mutable AWS_SES_REGION)}" - if [ -z "$AWS_SES_ACCESS_KEY_ID" ] || [ -z "$AWS_SES_SECRET_ACCESS_KEY" ]; then _use_container_role || _use_instance_role fi From a6b5f0c9d41a514929bf503bd830244785f9ce95 Mon Sep 17 00:00:00 2001 From: Steven Zhu Date: Tue, 4 Jul 2023 22:31:30 -0400 Subject: [PATCH 18/33] Fix variable naming to make the access key and secret key consistent with Route53. --- notify/aws_ses.sh | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/notify/aws_ses.sh b/notify/aws_ses.sh index 1060763d..571fd392 100644 --- a/notify/aws_ses.sh +++ b/notify/aws_ses.sh @@ -1,9 +1,9 @@ #!/usr/bin/env sh # -#AWS_SES_ACCESS_KEY_ID="sdfsdfsdfljlbjkljlkjsdfoiwje" +#AWS_ACCESS_KEY_ID="sdfsdfsdfljlbjkljlkjsdfoiwje" # -#AWS_SES_SECRET_ACCESS_KEY="xxxxxxx" +#AWS_SECRET_ACCESS_KEY="xxxxxxx" # #AWS_SES_REGION="us-east-1" # @@ -21,17 +21,17 @@ aws_ses_send() { _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped _debug "_statusCode" "$_statusCode" - AWS_SES_ACCESS_KEY_ID="${AWS_SES_ACCESS_KEY_ID:-$(_readaccountconf_mutable AWS_SES_ACCESS_KEY_ID)}" - AWS_SES_SECRET_ACCESS_KEY="${AWS_SES_SECRET_ACCESS_KEY:-$(_readaccountconf_mutable AWS_SES_SECRET_ACCESS_KEY)}" + AWS_ACCESS_KEY_ID="${AWS_ACCESS_KEY_ID:-$(_readaccountconf_mutable AWS_ACCESS_KEY_ID)}" + AWS_SECRET_ACCESS_KEY="${AWS_SECRET_ACCESS_KEY:-$(_readaccountconf_mutable AWS_SECRET_ACCESS_KEY)}" AWS_SES_REGION="${AWS_SES_REGION:-$(_readaccountconf_mutable AWS_SES_REGION)}" - if [ -z "$AWS_SES_ACCESS_KEY_ID" ] || [ -z "$AWS_SES_SECRET_ACCESS_KEY" ]; then + if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then _use_container_role || _use_instance_role fi - if [ -z "$AWS_SES_ACCESS_KEY_ID" ] || [ -z "$AWS_SES_SECRET_ACCESS_KEY" ]; then - AWS_SES_ACCESS_KEY_ID="" - AWS_SES_SECRET_ACCESS_KEY="" + if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then + AWS_ACCESS_KEY_ID="" + AWS_SECRET_ACCESS_KEY="" _err "You haven't specified the aws SES api key id and and api key secret yet." _err "Please create your key and try again. see $(__green $AWS_WIKI)" return 1 @@ -46,8 +46,8 @@ aws_ses_send() { #save for future use, unless using a role which will be fetched as needed if [ -z "$_using_role" ]; then - _saveaccountconf_mutable AWS_SES_ACCESS_KEY_ID "$AWS_SES_ACCESS_KEY_ID" - _saveaccountconf_mutable AWS_SES_SECRET_ACCESS_KEY "$AWS_SES_SECRET_ACCESS_KEY" + _saveaccountconf_mutable AWS_ACCESS_KEY_ID "$AWS_ACCESS_KEY_ID" + _saveaccountconf_mutable AWS_SECRET_ACCESS_KEY "$AWS_SECRET_ACCESS_KEY" fi AWS_SES_TO="${AWS_SES_TO:-$(_readaccountconf_mutable AWS_SES_TO)}" @@ -93,8 +93,8 @@ _use_metadata() { _debug3 "_key" "$_key" _secure_debug3 "_value" "$_value" case "$_key" in - AccessKeyId) echo "AWS_SES_ACCESS_KEY_ID=$_value" ;; - SecretAccessKey) echo "AWS_SES_SECRET_ACCESS_KEY=$_value" ;; + AccessKeyId) echo "AWS_ACCESS_KEY_ID=$_value" ;; + SecretAccessKey) echo "AWS_SECRET_ACCESS_KEY=$_value" ;; Token) echo "AWS_SESSION_TOKEN=$_value" ;; esac done | @@ -173,7 +173,7 @@ aws_rest() { _debug2 StringToSign "$StringToSign" - kSecret="AWS4$AWS_SES_SECRET_ACCESS_KEY" + kSecret="AWS4$AWS_SECRET_ACCESS_KEY" #kSecret="wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY" ############################ @@ -197,7 +197,7 @@ aws_rest() { signature="$(printf "$StringToSign%s" | _hmac "$Hash" "$kSigningH" hex)" _debug2 signature "$signature" - Authorization="$Algorithm Credential=$AWS_SES_ACCESS_KEY_ID/$CredentialScope, SignedHeaders=$SignedHeaders, Signature=$signature" + Authorization="$Algorithm Credential=$AWS_ACCESS_KEY_ID/$CredentialScope, SignedHeaders=$SignedHeaders, Signature=$signature" _debug2 Authorization "$Authorization" _H2="Authorization: $Authorization" From 299a157409c7cd07228cbaf31ccfc0879dba8f44 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 8 Jul 2023 11:17:19 +0800 Subject: [PATCH 19/33] fix https://github.com/acmesh-official/acme.sh/issues/4680 zerossl returns retry-after header within "200 OK" code. so we don't check the "503" code anymore. --- acme.sh | 58 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/acme.sh b/acme.sh index 0cc52131..85082d5c 100755 --- a/acme.sh +++ b/acme.sh @@ -2222,40 +2222,40 @@ _send_signed_request() { _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" - if [ "$needbase64" ]; then - _body="$(echo "$_body" | _dbase64 multiline)" - _debug3 _body "$_body" - fi + _body="$response" + if [ "$needbase64" ]; then + _body="$(echo "$_body" | _dbase64 multiline)" + _debug3 _body "$_body" + fi + _retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *: *[0-9]\+ *" | cut -d : -f 2 | tr -d ' ' | tr -d '\r') - _retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *: *[0-9]\+ *" | cut -d : -f 2 | tr -d ' ' | tr -d '\r') - if [ "$code" = '503' ]; then - _sleep_overload_retry_sec=$_retryafter - if [ -z "$_sleep_overload_retry_sec" ]; then - _sleep_overload_retry_sec=5 - fi - if [ $_sleep_overload_retry_sec -le 600 ]; then - _info "It seems the CA server is currently overloaded, let's wait and retry. Sleeping $_sleep_overload_retry_sec seconds." - _sleep $_sleep_overload_retry_sec - continue - else - _info "The retryafter=$_retryafter is too large > 600, not retry anymore." - fi + if [ "$code" = '503' ] || [ "$_retryafter" ]; then + _sleep_overload_retry_sec=$_retryafter + if [ -z "$_sleep_overload_retry_sec" ]; then + _sleep_overload_retry_sec=5 fi - if _contains "$_body" "JWS has invalid anti-replay nonce" || _contains "$_body" "JWS has an invalid anti-replay nonce"; then - _info "It seems the CA server is busy now, let's wait and retry. Sleeping $_sleep_retry_sec seconds." - _CACHED_NONCE="" - _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 + if [ $_sleep_overload_retry_sec -le 600 ]; then + _info "It seems the CA server is currently overloaded, let's wait and retry. Sleeping $_sleep_overload_retry_sec seconds." + _sleep $_sleep_overload_retry_sec continue + else + _info "The retryafter=$_retryafter is too large > 600, not retry anymore." + return 1 fi fi + if _contains "$_body" "JWS has invalid anti-replay nonce" || _contains "$_body" "JWS has an invalid anti-replay nonce"; then + _info "It seems the CA server is busy now, let's wait and retry. Sleeping $_sleep_retry_sec seconds." + _CACHED_NONCE="" + _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 + return 0 done _info "Giving up sending to CA server after $MAX_REQUEST_RETRY_TIMES retries." From 09041fb81d3e6f8e931c97a9141f49d5fc3009dc Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 8 Jul 2023 11:19:09 +0800 Subject: [PATCH 20/33] fix format --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 85082d5c..f680e0fb 100755 --- a/acme.sh +++ b/acme.sh @@ -2224,8 +2224,8 @@ _send_signed_request() { _body="$response" if [ "$needbase64" ]; then - _body="$(echo "$_body" | _dbase64 multiline)" - _debug3 _body "$_body" + _body="$(echo "$_body" | _dbase64 multiline)" + _debug3 _body "$_body" fi _retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *: *[0-9]\+ *" | cut -d : -f 2 | tr -d ' ' | tr -d '\r') From 0472f5da6a01229967647cc31f2c113141e49ed3 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 8 Jul 2023 11:43:44 +0800 Subject: [PATCH 21/33] Revert "fix format" This reverts commit 09041fb81d3e6f8e931c97a9141f49d5fc3009dc. Revert "fix https://github.com/acmesh-official/acme.sh/issues/4680" This reverts commit 299a157409c7cd07228cbaf31ccfc0879dba8f44. --- acme.sh | 60 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/acme.sh b/acme.sh index f680e0fb..0cc52131 100755 --- a/acme.sh +++ b/acme.sh @@ -2222,40 +2222,40 @@ _send_signed_request() { _CACHED_NONCE="$(echo "$responseHeaders" | grep -i "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2 | cut -d , -f 1)" - _body="$response" - if [ "$needbase64" ]; then - _body="$(echo "$_body" | _dbase64 multiline)" - _debug3 _body "$_body" - fi - _retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *: *[0-9]\+ *" | cut -d : -f 2 | tr -d ' ' | tr -d '\r') - - if [ "$code" = '503' ] || [ "$_retryafter" ]; then - _sleep_overload_retry_sec=$_retryafter - if [ -z "$_sleep_overload_retry_sec" ]; then - _sleep_overload_retry_sec=5 + if ! _startswith "$code" "2"; then + _body="$response" + if [ "$needbase64" ]; then + _body="$(echo "$_body" | _dbase64 multiline)" + _debug3 _body "$_body" fi - if [ $_sleep_overload_retry_sec -le 600 ]; then - _info "It seems the CA server is currently overloaded, let's wait and retry. Sleeping $_sleep_overload_retry_sec seconds." - _sleep $_sleep_overload_retry_sec + + _retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *: *[0-9]\+ *" | cut -d : -f 2 | tr -d ' ' | tr -d '\r') + if [ "$code" = '503' ]; then + _sleep_overload_retry_sec=$_retryafter + if [ -z "$_sleep_overload_retry_sec" ]; then + _sleep_overload_retry_sec=5 + fi + if [ $_sleep_overload_retry_sec -le 600 ]; then + _info "It seems the CA server is currently overloaded, let's wait and retry. Sleeping $_sleep_overload_retry_sec seconds." + _sleep $_sleep_overload_retry_sec + continue + else + _info "The retryafter=$_retryafter is too large > 600, not retry anymore." + fi + fi + if _contains "$_body" "JWS has invalid anti-replay nonce" || _contains "$_body" "JWS has an invalid anti-replay nonce"; then + _info "It seems the CA server is busy now, let's wait and retry. Sleeping $_sleep_retry_sec seconds." + _CACHED_NONCE="" + _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 - else - _info "The retryafter=$_retryafter is too large > 600, not retry anymore." - return 1 fi fi - if _contains "$_body" "JWS has invalid anti-replay nonce" || _contains "$_body" "JWS has an invalid anti-replay nonce"; then - _info "It seems the CA server is busy now, let's wait and retry. Sleeping $_sleep_retry_sec seconds." - _CACHED_NONCE="" - _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 - return 0 done _info "Giving up sending to CA server after $MAX_REQUEST_RETRY_TIMES retries." From 3761fb4377f2a50ba9c1a4f863671ba1afa8c5eb Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 8 Jul 2023 12:37:01 +0800 Subject: [PATCH 22/33] fix bug https://github.com/acmesh-official/acme.sh/issues/4442 --- acme.sh | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/acme.sh b/acme.sh index 0cc52131..37bef388 100755 --- a/acme.sh +++ b/acme.sh @@ -2116,6 +2116,7 @@ _send_signed_request() { if [ -z "$keyfile" ]; then keyfile="$ACCOUNT_KEY_PATH" fi + _debug "=======Begin Send Signed Request=======" _debug url "$url" _debug payload "$payload" @@ -4602,9 +4603,10 @@ issue() { _d="*.$_d" fi _debug2 _d "$_d" - _authorizations_map="$_d,$response + _authorizations_map="$_d,$response#$_authz_url $_authorizations_map" done + _debug2 _authorizations_map "$_authorizations_map" _index=0 @@ -4656,7 +4658,8 @@ $_authorizations_map" _on_issue_err "$_post_hook" return 1 fi - + _authz_url="$(echo "$_candidates" | sed "s/$_idn_d,//" | _egrep_o "#.*" | sed "s/^#//")" + _debug _authz_url "$_authz_url" if [ -z "$thumbprint" ]; then thumbprint="$(__calc_account_thumbprint)" fi @@ -4708,7 +4711,7 @@ $_authorizations_map" _debug keyauthorization "$keyauthorization" fi - dvlist="$d$sep$keyauthorization$sep$uri$sep$vtype$sep$_currentRoot" + dvlist="$d$sep$keyauthorization$sep$uri$sep$vtype$sep$_currentRoot$sep$_authz_url" _debug dvlist "$dvlist" vlist="$vlist$dvlist$dvsep" @@ -4725,6 +4728,7 @@ $_authorizations_map" keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2) vtype=$(echo "$ventry" | cut -d "$sep" -f 4) _currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5) + _authz_url=$(echo "$ventry" | cut -d "$sep" -f 6) _debug d "$d" if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then _debug "$d is already verified, skip $vtype." @@ -4850,7 +4854,7 @@ $_authorizations_map" uri=$(echo "$ventry" | cut -d "$sep" -f 3) vtype=$(echo "$ventry" | cut -d "$sep" -f 4) _currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5) - + _authz_url=$(echo "$ventry" | cut -d "$sep" -f 6) if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then _info "$d is already verified, skip $vtype." continue @@ -4860,6 +4864,7 @@ $_authorizations_map" _debug "d" "$d" _debug "keyauthorization" "$keyauthorization" _debug "uri" "$uri" + _debug "_authz_url" "$_authz_url" removelevel="" token="$(printf "%s" "$keyauthorization" | cut -d '.' -f 1)" @@ -4967,6 +4972,7 @@ $_authorizations_map" MAX_RETRY_TIMES=30 fi + _debug "Lets check the status of the authz" while true; do waittimes=$(_math "$waittimes" + 1) if [ "$waittimes" -ge "$MAX_RETRY_TIMES" ]; then @@ -5029,7 +5035,7 @@ $_authorizations_map" _sleep 2 _debug "checking" - _send_signed_request "$uri" + _send_signed_request "$_authz_url" if [ "$?" != "0" ]; then _err "$d:Verify error:$response" From 8fd3a64e3581e01909d1e781ab4a4a697b3f0f37 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 8 Jul 2023 12:51:56 +0800 Subject: [PATCH 23/33] fix https://github.com/acmesh-official/acme.sh/issues/4442 --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 37bef388..65b0a5b9 100755 --- a/acme.sh +++ b/acme.sh @@ -5020,9 +5020,9 @@ $_authorizations_map" break fi - if [ "$status" = "pending" ]; then + if _contains "$status" "pending"; then _info "Pending, The CA is processing your order, please just wait. ($waittimes/$MAX_RETRY_TIMES)" - elif [ "$status" = "processing" ]; then + elif _contains "$status" "processing"; then _info "Processing, The CA is processing your order, please just wait. ($waittimes/$MAX_RETRY_TIMES)" else _err "$d:Verify error:$response" From a7455d7edd0e81f34b8e9071286e201389728148 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 8 Jul 2023 14:11:51 +0800 Subject: [PATCH 24/33] fix https://github.com/acmesh-official/acme.sh/issues/4562#issuecomment-1598731384 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 65b0a5b9..7a9468fd 100755 --- a/acme.sh +++ b/acme.sh @@ -2278,7 +2278,7 @@ _setopt() { if [ ! -f "$__conf" ]; then touch "$__conf" fi - if [ -n "$(tail -c 1 <"$__conf")" ]; then + if [ -n "$(tail -c1 <"$__conf")" ]; then echo >>"$__conf" fi From ee50f254df99368e0afbefd522806615f0c46a85 Mon Sep 17 00:00:00 2001 From: Arnaud Launay <2205303+alaunay@users.noreply.github.com> Date: Sun, 9 Jul 2023 20:08:10 +0200 Subject: [PATCH 25/33] Add BookMyName API support --- dnsapi/dns_bookmyname.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_bookmyname.sh b/dnsapi/dns_bookmyname.sh index 7acdea02..62548fd0 100644 --- a/dnsapi/dns_bookmyname.sh +++ b/dnsapi/dns_bookmyname.sh @@ -13,15 +13,15 @@ # Please Read this guide first: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Dev-Guide -# BMN urls: -# https://BMN_USER:BMN_PASSWORD@www.bookmyname.com/dyndns/?hostname=_acme-challenge.domain.tld&type=txt&ttl=300&do=add&value="XXXXXXXX"' -# https://BMN_USER:BMN_PASSWORD@www.bookmyname.com/dyndns/?hostname=_acme-challenge.domain.tld&type=txt&ttl=300&do=remove&value="XXXXXXXX"' +# BookMyName urls: +# https://BOOKMYNAME_USERNAME:BOOKMYNAME_PASSWORD@www.bookmyname.com/dyndns/?hostname=_acme-challenge.domain.tld&type=txt&ttl=300&do=add&value="XXXXXXXX"' +# https://BOOKMYNAME_USERNAME:BOOKMYNAME_PASSWORD@www.bookmyname.com/dyndns/?hostname=_acme-challenge.domain.tld&type=txt&ttl=300&do=remove&value="XXXXXXXX"' # Output: #good: update done, cid 123456, domain id 456789, type txt, ip XXXXXXXX #good: remove done 1, cid 123456, domain id 456789, ttl 300, type txt, ip XXXXXXXX -# Be careful, BookMyName DNS servers can be slow to pick up changes; using dnssleep is thus advised. +# Be careful, BMN DNS servers can be slow to pick up changes; using dnssleep is thus advised. # Usage: # export BOOKMYNAME_USERNAME="ABCDE-FREE" From dd958872a87bc4e383ea38aaed03919d0b753783 Mon Sep 17 00:00:00 2001 From: Steven Zhu Date: Fri, 14 Jul 2023 12:47:44 -0400 Subject: [PATCH 26/33] Fix SES region variable The last version do not save the SES region into the config file, breaking the notification hook. --- notify/aws_ses.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/notify/aws_ses.sh b/notify/aws_ses.sh index 571fd392..30db45ad 100644 --- a/notify/aws_ses.sh +++ b/notify/aws_ses.sh @@ -43,6 +43,7 @@ aws_ses_send() { _err "Please specify your region and try again. see https://docs.aws.amazon.com/general/latest/gr/ses.html" return 1 fi + _saveaccountconf_mutable AWS_SES_REGION "$AWS_SES_REGION" #save for future use, unless using a role which will be fetched as needed if [ -z "$_using_role" ]; then From c48c8d07de31bbb65a5621d37b9ff6b056e7a8a9 Mon Sep 17 00:00:00 2001 From: Harald Kapper <4014716+hknet@users.noreply.github.com> Date: Thu, 27 Jul 2023 21:49:23 +0200 Subject: [PATCH 27/33] Update dns_kappernet.sh dns update waiting time is reduced now (new backend at kapper.net) --- dnsapi/dns_kappernet.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_kappernet.sh b/dnsapi/dns_kappernet.sh index 83a7e5f8..0a8951cb 100644 --- a/dnsapi/dns_kappernet.sh +++ b/dnsapi/dns_kappernet.sh @@ -45,8 +45,8 @@ dns_kappernet_add() { if _kappernet_api GET "action=new&subject=$_domain&data=$data"; then if _contains "$response" "{\"OK\":true"; then - _info "Waiting 120 seconds for DNS to spread the new record" - _sleep 120 + _info "Waiting 1 second for DNS to spread the new record" + _sleep 1 return 0 else _err "Error creating a TXT DNS Record: $fullhostname TXT $txtvalue" From a51025fe8f5c0bacfecb943d997806e55477ce3e Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 29 Jul 2023 15:32:50 +0800 Subject: [PATCH 28/33] fix https://github.com/acmesh-official/acme.sh/issues/3645 --- acme.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 7a9468fd..03c838ac 100755 --- a/acme.sh +++ b/acme.sh @@ -924,7 +924,9 @@ _sed_i() { } _egrep_o() { - if ! egrep -o "$1" 2>/dev/null; then + if _exists egrep; then + egrep -o "$1" 2>/dev/null; + else sed -n 's/.*\('"$1"'\).*/\1/p' fi } From 7f39cdc85660ad3d1fb6b2f6b70cc094fd093e29 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 29 Jul 2023 16:45:49 +0800 Subject: [PATCH 29/33] fix format --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 03c838ac..7605c396 100755 --- a/acme.sh +++ b/acme.sh @@ -925,7 +925,7 @@ _sed_i() { _egrep_o() { if _exists egrep; then - egrep -o "$1" 2>/dev/null; + egrep -o "$1" 2>/dev/null else sed -n 's/.*\('"$1"'\).*/\1/p' fi From a7f3d413ef81782a43cf568ab7a136ffb7e9e5e5 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 29 Jul 2023 22:32:30 +0800 Subject: [PATCH 30/33] fix for solaris --- acme.sh | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 7605c396..c79cadfc 100755 --- a/acme.sh +++ b/acme.sh @@ -2103,9 +2103,20 @@ _head_n() { } _tail_n() { - if ! tail -n "$1" 2>/dev/null; then + if _is_solaris; then #fix for solaris tail -"$1" + else + tail -n "$1" + fi +} + +_tail_c() { + if _is_solaris; then + #fix for solaris + tail -"$1"c + else + tail -c "$1" fi } @@ -2280,7 +2291,7 @@ _setopt() { if [ ! -f "$__conf" ]; then touch "$__conf" fi - if [ -n "$(tail -c1 <"$__conf")" ]; then + if [ -n "$(_tail_c 1 <"$__conf")" ]; then echo >>"$__conf" fi From 6db8ae451ab3263570bdb2eb3b33d10c91f289c5 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 29 Jul 2023 23:17:20 +0800 Subject: [PATCH 31/33] fix for solaris --- acme.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index c79cadfc..3c9ba003 100755 --- a/acme.sh +++ b/acme.sh @@ -924,10 +924,10 @@ _sed_i() { } _egrep_o() { - if _exists egrep; then - egrep -o "$1" 2>/dev/null - else + if _is_solaris; then sed -n 's/.*\('"$1"'\).*/\1/p' + else + egrep -o "$1" fi } From 15ee036db17d13a8ec75275e0b7ef729a79dc9f2 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 29 Jul 2023 23:30:44 +0800 Subject: [PATCH 32/33] fix for solaris --- acme.sh | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index 3c9ba003..75efde4c 100755 --- a/acme.sh +++ b/acme.sh @@ -923,11 +923,17 @@ _sed_i() { fi } +if [ "$(echo abc | egrep -o b 2>/dev/null)" = "b" ]; then + __USE_EGREP=1 +else + __USE_EGREP="" +fi + _egrep_o() { - if _is_solaris; then - sed -n 's/.*\('"$1"'\).*/\1/p' - else + if [ "$__USE_EGREP" ]; then egrep -o "$1" + else + sed -n 's/.*\('"$1"'\).*/\1/p' fi } From b6f62ac446ab9ff78f4a90c4330dc314678545c9 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 30 Jul 2023 10:58:22 +0800 Subject: [PATCH 33/33] fix for curl bugs nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation see https://bugs.launchpad.net/ubuntu/+source/curl/+bug/2018342 --- .github/workflows/DragonFlyBSD.yml | 2 +- .github/workflows/OpenBSD.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/DragonFlyBSD.yml b/.github/workflows/DragonFlyBSD.yml index 6daa9be4..5a0d81ba 100644 --- a/.github/workflows/DragonFlyBSD.yml +++ b/.github/workflows/DragonFlyBSD.yml @@ -62,7 +62,7 @@ jobs: nat: | "8080": "80" prepare: | - pkg install -y curl socat + pkg install -y curl socat libnghttp2 usesh: true run: | cd ../acmetest \ diff --git a/.github/workflows/OpenBSD.yml b/.github/workflows/OpenBSD.yml index 7746645a..745a9408 100644 --- a/.github/workflows/OpenBSD.yml +++ b/.github/workflows/OpenBSD.yml @@ -66,7 +66,7 @@ jobs: envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET' nat: | "8080": "80" - prepare: pkg_add socat curl wget + prepare: pkg_add socat curl wget libnghttp2 usesh: true copyback: false run: |