From 861df496707b2837d1972f76ce5c8c1fdf2d19d7 Mon Sep 17 00:00:00 2001 From: Martin Kammerlander Date: Fri, 9 Mar 2018 16:29:47 +0100 Subject: [PATCH 001/357] Add All-inkl kasserver script. --- README.md | 1 + dnsapi/dns_kas.sh | 153 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100755 dnsapi/dns_kas.sh diff --git a/README.md b/README.md index bfcb477f..ed84f4a7 100644 --- a/README.md +++ b/README.md @@ -328,6 +328,7 @@ You don't have to do anything manually! 1. zonomi.com DNS API 1. DreamHost.com API 1. DirectAdmin API +1. All-inkl/Kasserver API And: diff --git a/dnsapi/dns_kas.sh b/dnsapi/dns_kas.sh new file mode 100755 index 00000000..64a44720 --- /dev/null +++ b/dnsapi/dns_kas.sh @@ -0,0 +1,153 @@ +#!/usr/bin/env sh +######################################################################## +# All-inkl Kasserver hook script for acme.sh +# +# Environment variables: +# +# - $KAS_Login (Kasserver API login name) +# - $KAS_Authtype (Kasserver API auth type. Default: sha1) +# - $KAS_Authdata (Kasserver API auth data.) +# +# Author: Martin Kammerlander, Phlegx Systems OG +# Credits: Inspired by dns_he.sh. Thanks a lot man! +# Git repo: TODO +# TODO: Better Error handling +# TODO: Does not work with Domains that have double endings like i.e. 'co.uk' +# => Get all root zones and compare once the provider offers that. + +KAS_Api="https://kasapi.kasserver.com/dokumentation/formular.php" + +######## Public functions ##################### + +dns_kas_add() { + _full_domain=$1 + _txt_value=$2 + _info "Using DNS-01 All-inkl/Kasserver hook" + _info "Adding or Updating $_full_domain DNS TXT entry on All-inkl/Kasserver" + + _check_and_save + _get_zone "$_full_domain" + _get_record_name "$_full_domain" + _get_record_id + + params="?kas_login=$KAS_Login" + params="$params&kas_auth_type=$KAS_Authtype" + params="$params&kas_auth_data=$KAS_Authdata" + params="$params&var1=record_name" + params="$params&wert1=$_record_name" + params="$params&var2=record_type" + params="$params&wert2=TXT" + params="$params&var3=record_data" + params="$params&wert3=$_txt_value" + params="$params&var4=record_aux" + params="$params&wert4=0" + # If there is no record_id create the record + if [ -z "$_record_id" ]; then + _info "Creating TXT DNS record" + params="$params&kas_action=add_dns_settings" + params="$params&var5=zone_host" + params="$params&wert5=$_zone" + else # Update the existing record + _info "Updating existing TXT DNS record" + params="$params&kas_action=update_dns_settings" + params="$params&var5=record_id" + params="$params&wert5=$_record_id" + fi + + response="$(_get "$KAS_Api$params")" + _debug2 "response" "$response" + + if ! _contains "$response" "TRUE"; then + _err "An unkown error occurred, please check manually." + return 1 + fi + return 0 +} + +dns_kas_rm() { + _full_domain=$1 + _txt_value=$2 + _info "Using DNS-01 All-inkl/Kasserver hook" + _info "Cleaning up after All-inkl/Kasserver hook" + _info "Removing $_full_domain DNS TXT entry on All-inkl/Kasserver" + + _check_and_save + _get_zone "$_full_domain" + _get_record_name "$_full_domain" + _get_record_id + + # If there is a record_id, delete the entry + if [ -n "$_record_id" ]; then + params="?kas_login=$KAS_Login" + params="$params&kas_auth_type=$KAS_Authtype" + params="$params&kas_auth_data=$KAS_Authdata" + params="$params&kas_action=delete_dns_settings" + params="$params&var1=record_id" + params="$params&wert1=$_record_id" + response="$(_get "$KAS_Api$params")" + _debug2 "response" "$response" + if ! _contains "$response" "TRUE"; then + _err "Either the txt record is not found or another error occurred, please check manually." + return 1 + fi + else # Cannot delete or unkown error + _err "No record_id found that can be deleted. Please check manually." + return 1 + fi + + return 0 +} + +########################## PRIVATE FUNCTIONS ########################### + +# Checks for the ENV variables and saves them +_check_and_save() { + KAS_Login="${KAS_Login:-$(_readaccountconf_mutable KAS_Login)}" + KAS_Authtype="${KAS_Authtype:-$(_readaccountconf_mutable KAS_Authtype)}" + KAS_Authdata="${KAS_Authdata:-$(_readaccountconf_mutable KAS_Authdata)}" + + if [ -z "$KAS_Login" ] || [ -z "$KAS_Authtype" ] || [ -z "$KAS_Authdata" ]; then + KAS_Login= + KAS_Authtype= + KAS_Authdata= + _err "No auth details provided. Please set user credentials using the \$KAS_Login, \$KAS_Authtype, and \$KAS_Authdata environment variables." + return 1 + fi + _saveaccountconf_mutable KAS_Login "$KAS_Login" + _saveaccountconf_mutable KAS_Authtype "$KAS_Authtype" + _saveaccountconf_mutable KAS_Authdata "$KAS_Authdata" + return 0 +} + +# Gets back the base domain/zone. +# TODO Get a list of all possible root zones and compare (Currently not possible via provider) +# See: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide +_get_zone() { + _zone=$(echo "$1" | rev | cut -d . -f1-2 | rev). +} + +# Removes the domain/subdomain from the entry since kasserver +# cannot handle _full_domain +# TODO Get a list of all possible root zones and compare (Currently not possible via provider) +# See: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide +_get_record_name() { + _record_name=$(echo "$1" | rev | cut -d"." -f3- | rev) +} + +# Retrieve the DNS record ID +_get_record_id() { + params="?kas_login=$KAS_Login" + params="$params&kas_auth_type=$KAS_Authtype" + params="$params&kas_auth_data=$KAS_Authdata" + params="$params&kas_action=get_dns_settings" + params="$params&var1=zone_host" + params="$params&wert1=$_zone" + + response="$(_get "$KAS_Api$params")" + _debug2 "response" "$response" + + _record_id="$(echo "$response" | grep -A 4 "$_record_name" | grep "record_id" | cut -f2 -d">" | xargs)" + _debug2 _record_id "$_record_id" + + return 0 +} From 32d7bd5ab1d390d67a2705dfa8c3914e4f43d00a Mon Sep 17 00:00:00 2001 From: Martin Kammerlander Date: Fri, 9 Mar 2018 16:33:35 +0100 Subject: [PATCH 002/357] Add own github repository URL. --- dnsapi/dns_kas.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_kas.sh b/dnsapi/dns_kas.sh index 64a44720..647a7bb2 100755 --- a/dnsapi/dns_kas.sh +++ b/dnsapi/dns_kas.sh @@ -10,7 +10,7 @@ # # Author: Martin Kammerlander, Phlegx Systems OG # Credits: Inspired by dns_he.sh. Thanks a lot man! -# Git repo: TODO +# Git repo: https://github.com/phlegx/acme.sh # TODO: Better Error handling # TODO: Does not work with Domains that have double endings like i.e. 'co.uk' # => Get all root zones and compare once the provider offers that. From cbf0ceacd57fe16f27fa6150ffd2b180d796f3b3 Mon Sep 17 00:00:00 2001 From: Martin Kammerlander Date: Fri, 16 Mar 2018 14:51:16 +0100 Subject: [PATCH 003/357] Update dnsapi Readme. --- dnsapi/README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/dnsapi/README.md b/dnsapi/README.md index 8b4a8358..ec6233fc 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -784,6 +784,27 @@ acme.sh --issue --dns dns_da -d example.com -d www.example.com The `DA_Api` and `DA_Api_Insecure` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. +## 42. Use All-inkl Kasserver API + +All-inkl Kasserver API (https://kasapi.kasserver.com/dokumentation) needs you to set your Login credentials like so: + +``` +export KAS_Login="yourusername" +export KAS_Authtype="sha1" +export KAS_Authdata="password" +``` + +Note: Please for now always set the `KAS_Authtype` always simply to `sha1`. + +Then you can issue your certificate: + +``` +acme.sh --issue --dns dns_kas -d example.com -d www.example.com +``` + +The `KAS_Login`, `KAS_Authtype` and `KAS_Authdata` settings will be saved in `~/.acme.sh/account.conf` and will be reused when needed. + +Please report any issues to https://github.com/phlegx/acme.sh. # Use custom API From e431df06ab6457292e9d82e03f4d5ca015d0b85d Mon Sep 17 00:00:00 2001 From: Martin Kammerlander Date: Fri, 16 Mar 2018 14:54:08 +0100 Subject: [PATCH 004/357] Only create entry. Remove update. --- dnsapi/dns_kas.sh | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/dnsapi/dns_kas.sh b/dnsapi/dns_kas.sh index 647a7bb2..518b2830 100755 --- a/dnsapi/dns_kas.sh +++ b/dnsapi/dns_kas.sh @@ -30,6 +30,7 @@ dns_kas_add() { _get_record_name "$_full_domain" _get_record_id + _info "Creating TXT DNS record" params="?kas_login=$KAS_Login" params="$params&kas_auth_type=$KAS_Authtype" params="$params&kas_auth_data=$KAS_Authdata" @@ -41,18 +42,9 @@ dns_kas_add() { params="$params&wert3=$_txt_value" params="$params&var4=record_aux" params="$params&wert4=0" - # If there is no record_id create the record - if [ -z "$_record_id" ]; then - _info "Creating TXT DNS record" - params="$params&kas_action=add_dns_settings" - params="$params&var5=zone_host" - params="$params&wert5=$_zone" - else # Update the existing record - _info "Updating existing TXT DNS record" - params="$params&kas_action=update_dns_settings" - params="$params&var5=record_id" - params="$params&wert5=$_record_id" - fi + params="$params&kas_action=add_dns_settings" + params="$params&var5=zone_host" + params="$params&wert5=$_zone" response="$(_get "$KAS_Api$params")" _debug2 "response" "$response" From 11bfb1e5fd679a21477c393f9cfc19004e72d306 Mon Sep 17 00:00:00 2001 From: Martin Kammerlander Date: Fri, 16 Mar 2018 15:02:47 +0100 Subject: [PATCH 005/357] Fix return values of some functions. --- dnsapi/dns_kas.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dnsapi/dns_kas.sh b/dnsapi/dns_kas.sh index 518b2830..dc87bee4 100755 --- a/dnsapi/dns_kas.sh +++ b/dnsapi/dns_kas.sh @@ -116,6 +116,7 @@ _check_and_save() { # See: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide _get_zone() { _zone=$(echo "$1" | rev | cut -d . -f1-2 | rev). + return 0 } # Removes the domain/subdomain from the entry since kasserver @@ -124,6 +125,7 @@ _get_zone() { # See: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide _get_record_name() { _record_name=$(echo "$1" | rev | cut -d"." -f3- | rev) + return 0 } # Retrieve the DNS record ID From 26b5180bf71f007f55c0264aba76defa0574626c Mon Sep 17 00:00:00 2001 From: Martin Kammerlander Date: Fri, 16 Mar 2018 15:49:40 +0100 Subject: [PATCH 006/357] Rename full_domain and txt_value variables. --- dnsapi/dns_kas.sh | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/dnsapi/dns_kas.sh b/dnsapi/dns_kas.sh index dc87bee4..0eda1d36 100755 --- a/dnsapi/dns_kas.sh +++ b/dnsapi/dns_kas.sh @@ -20,14 +20,14 @@ KAS_Api="https://kasapi.kasserver.com/dokumentation/formular.php" ######## Public functions ##################### dns_kas_add() { - _full_domain=$1 - _txt_value=$2 + _fulldomain=$1 + _txtvalue=$2 _info "Using DNS-01 All-inkl/Kasserver hook" - _info "Adding or Updating $_full_domain DNS TXT entry on All-inkl/Kasserver" + _info "Adding or Updating $_fulldomain DNS TXT entry on All-inkl/Kasserver" _check_and_save - _get_zone "$_full_domain" - _get_record_name "$_full_domain" + _get_zone "$_fulldomain" + _get_record_name "$_fulldomain" _get_record_id _info "Creating TXT DNS record" @@ -39,7 +39,7 @@ dns_kas_add() { params="$params&var2=record_type" params="$params&wert2=TXT" params="$params&var3=record_data" - params="$params&wert3=$_txt_value" + params="$params&wert3=$_txtvalue" params="$params&var4=record_aux" params="$params&wert4=0" params="$params&kas_action=add_dns_settings" @@ -57,15 +57,15 @@ dns_kas_add() { } dns_kas_rm() { - _full_domain=$1 - _txt_value=$2 + _fulldomain=$1 + _txtvalue=$2 _info "Using DNS-01 All-inkl/Kasserver hook" _info "Cleaning up after All-inkl/Kasserver hook" - _info "Removing $_full_domain DNS TXT entry on All-inkl/Kasserver" + _info "Removing $_fulldomain DNS TXT entry on All-inkl/Kasserver" _check_and_save - _get_zone "$_full_domain" - _get_record_name "$_full_domain" + _get_zone "$_fulldomain" + _get_record_name "$_fulldomain" _get_record_id # If there is a record_id, delete the entry @@ -86,7 +86,6 @@ dns_kas_rm() { _err "No record_id found that can be deleted. Please check manually." return 1 fi - return 0 } @@ -120,7 +119,7 @@ _get_zone() { } # Removes the domain/subdomain from the entry since kasserver -# cannot handle _full_domain +# cannot handle _fulldomain # TODO Get a list of all possible root zones and compare (Currently not possible via provider) # See: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide _get_record_name() { @@ -141,7 +140,12 @@ _get_record_id() { _debug2 "response" "$response" _record_id="$(echo "$response" | grep -A 4 "$_record_name" | grep "record_id" | cut -f2 -d">" | xargs)" + echo "###########################" + echo "$_record_name" + echo "$_record_id" + echo "###########################" + echo "$response" + echo "###########################" _debug2 _record_id "$_record_id" - return 0 } From cb4a2cf02921d538edc497f0af0d479df04ffb90 Mon Sep 17 00:00:00 2001 From: Martin Kammerlander Date: Fri, 16 Mar 2018 16:47:47 +0100 Subject: [PATCH 007/357] remove debug output --- dnsapi/dns_kas.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/dnsapi/dns_kas.sh b/dnsapi/dns_kas.sh index 0eda1d36..c3941d90 100755 --- a/dnsapi/dns_kas.sh +++ b/dnsapi/dns_kas.sh @@ -140,12 +140,6 @@ _get_record_id() { _debug2 "response" "$response" _record_id="$(echo "$response" | grep -A 4 "$_record_name" | grep "record_id" | cut -f2 -d">" | xargs)" - echo "###########################" - echo "$_record_name" - echo "$_record_id" - echo "###########################" - echo "$response" - echo "###########################" _debug2 _record_id "$_record_id" return 0 } From 68f66ca101ba04bf3abc3fb97f1f0162d6a2506c Mon Sep 17 00:00:00 2001 From: Martin Kammerlander Date: Thu, 2 Aug 2018 16:20:48 +0200 Subject: [PATCH 008/357] Add default delay for the calls to KAS api since they are very restrictive with that. --- dnsapi/dns_kas.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_kas.sh b/dnsapi/dns_kas.sh index c3941d90..3b608d43 100755 --- a/dnsapi/dns_kas.sh +++ b/dnsapi/dns_kas.sh @@ -45,7 +45,8 @@ dns_kas_add() { params="$params&kas_action=add_dns_settings" params="$params&var5=zone_host" params="$params&wert5=$_zone" - + _debug2 "Wait for 10 seconds by default before calling KAS API." + sleep 10 response="$(_get "$KAS_Api$params")" _debug2 "response" "$response" @@ -76,6 +77,8 @@ dns_kas_rm() { params="$params&kas_action=delete_dns_settings" params="$params&var1=record_id" params="$params&wert1=$_record_id" + _debug2 "Wait for 10 seconds by default before calling KAS API." + sleep 10 response="$(_get "$KAS_Api$params")" _debug2 "response" "$response" if ! _contains "$response" "TRUE"; then @@ -136,6 +139,8 @@ _get_record_id() { params="$params&var1=zone_host" params="$params&wert1=$_zone" + _debug2 "Wait for 10 seconds by default before calling KAS API." + sleep 10 response="$(_get "$KAS_Api$params")" _debug2 "response" "$response" From 16db9a7337ffbcfa5c8610a13fdedd66a5f4b956 Mon Sep 17 00:00:00 2001 From: Stephane Moser Date: Fri, 29 Mar 2019 14:12:34 +0000 Subject: [PATCH 009/357] Add --dnsslowrate arg --- acme.sh | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index f47a5ebb..47d11002 100755 --- a/acme.sh +++ b/acme.sh @@ -3974,9 +3974,16 @@ $_authorizations_map" return 1 fi - if ! $addcommand "$txtdomain" "$txt"; then - _err "Error add txt for domain:$txtdomain" - return 1 + if [ "$addcommand" = "dns_aws_add" -a -n "$_dnsslowrate" ] ; then + if ! $addcommand "$txtdomain" "$txt" "$_dnsslowrate"; then + _err "Error add txt for domain:$txtdomain" + return 1 + fi + else + if ! $addcommand "$txtdomain" "$txt"; then + _err "Error add txt for domain:$txtdomain" + return 1 + fi fi ) @@ -5919,6 +5926,7 @@ _process() { _httpport="" _tlsport="" _dnssleep="" + _dnsslowrate="" _listraw="" _stopRenewOnError="" #_insecure="" @@ -6158,6 +6166,12 @@ _process() { _webroot="$_webroot,$wvalue" fi ;; + + --dnsslowrate) + _dnsslowrate="$2" + shift + ;; + --dnssleep) _dnssleep="$2" Le_DNSSleep="$_dnssleep" From 3021c5cfadcf815c312857d9f27003071d331bdf Mon Sep 17 00:00:00 2001 From: Stephane Moser Date: Fri, 29 Mar 2019 14:12:50 +0000 Subject: [PATCH 010/357] Use dnsslowrate arg --- dnsapi/dns_aws.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dnsapi/dns_aws.sh b/dnsapi/dns_aws.sh index 2ad3c819..35781eb1 100755 --- a/dnsapi/dns_aws.sh +++ b/dnsapi/dns_aws.sh @@ -18,6 +18,7 @@ AWS_WIKI="https://github.com/Neilpang/acme.sh/wiki/How-to-use-Amazon-Route53-API dns_aws_add() { fulldomain=$1 txtvalue=$2 + slowrateslepp=$3 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)}" @@ -72,6 +73,10 @@ dns_aws_add() { if aws_rest POST "2013-04-01$_domain_id/rrset/" "" "$_aws_tmpl_xml" && _contains "$response" "ChangeResourceRecordSetsResponse"; then _info "TXT record updated successfully." + if [ -n "$slowrateslepp" ]; then + _info "Slow rate activated: sleeping for $slowrateslepp seconds" + sleep $slowrateslepp + fi return 0 fi From 8902a5c5cd558a18b2d4a0beb5b23fc013e9f459 Mon Sep 17 00:00:00 2001 From: Stephane Moser Date: Fri, 29 Mar 2019 14:33:15 +0000 Subject: [PATCH 011/357] Revert "Add --dnsslowrate arg" This reverts commit 16db9a7337ffbcfa5c8610a13fdedd66a5f4b956. --- acme.sh | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/acme.sh b/acme.sh index 47d11002..f47a5ebb 100755 --- a/acme.sh +++ b/acme.sh @@ -3974,16 +3974,9 @@ $_authorizations_map" return 1 fi - if [ "$addcommand" = "dns_aws_add" -a -n "$_dnsslowrate" ] ; then - if ! $addcommand "$txtdomain" "$txt" "$_dnsslowrate"; then - _err "Error add txt for domain:$txtdomain" - return 1 - fi - else - if ! $addcommand "$txtdomain" "$txt"; then - _err "Error add txt for domain:$txtdomain" - return 1 - fi + if ! $addcommand "$txtdomain" "$txt"; then + _err "Error add txt for domain:$txtdomain" + return 1 fi ) @@ -5926,7 +5919,6 @@ _process() { _httpport="" _tlsport="" _dnssleep="" - _dnsslowrate="" _listraw="" _stopRenewOnError="" #_insecure="" @@ -6166,12 +6158,6 @@ _process() { _webroot="$_webroot,$wvalue" fi ;; - - --dnsslowrate) - _dnsslowrate="$2" - shift - ;; - --dnssleep) _dnssleep="$2" Le_DNSSleep="$_dnssleep" From ea6a3c0963f3f7c2edff82691d05f92f6406302a Mon Sep 17 00:00:00 2001 From: Stephane Moser Date: Fri, 29 Mar 2019 14:39:32 +0000 Subject: [PATCH 012/357] Use AWS_DNS_SLOWRATE env variable instead of arg --- dnsapi/dns_aws.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_aws.sh b/dnsapi/dns_aws.sh index 35781eb1..91bc7d09 100755 --- a/dnsapi/dns_aws.sh +++ b/dnsapi/dns_aws.sh @@ -18,7 +18,7 @@ AWS_WIKI="https://github.com/Neilpang/acme.sh/wiki/How-to-use-Amazon-Route53-API dns_aws_add() { fulldomain=$1 txtvalue=$2 - slowrateslepp=$3 + slowrateslepp=$AWS_DNS_SLOWRATE 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)}" @@ -87,6 +87,7 @@ dns_aws_add() { dns_aws_rm() { fulldomain=$1 txtvalue=$2 + slowrateslepp=$AWS_DNS_SLOWRATE 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)}" @@ -121,6 +122,10 @@ dns_aws_rm() { if aws_rest POST "2013-04-01$_domain_id/rrset/" "" "$_aws_tmpl_xml" && _contains "$response" "ChangeResourceRecordSetsResponse"; then _info "TXT record deleted successfully." + if [ -n "$slowrateslepp" ]; then + _info "Slow rate activated: sleeping for $slowrateslepp seconds" + sleep $slowrateslepp + fi return 0 fi From aeed2871223b39eecf59917e19e1155e634588f2 Mon Sep 17 00:00:00 2001 From: Stephane Moser Date: Tue, 2 Apr 2019 10:27:22 +0100 Subject: [PATCH 013/357] Add Double quote to slowrateslepp --- dnsapi/dns_aws.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_aws.sh b/dnsapi/dns_aws.sh index 91bc7d09..cb4de878 100755 --- a/dnsapi/dns_aws.sh +++ b/dnsapi/dns_aws.sh @@ -75,7 +75,7 @@ dns_aws_add() { _info "TXT record updated successfully." if [ -n "$slowrateslepp" ]; then _info "Slow rate activated: sleeping for $slowrateslepp seconds" - sleep $slowrateslepp + sleep "$slowrateslepp" fi return 0 fi @@ -124,7 +124,7 @@ dns_aws_rm() { _info "TXT record deleted successfully." if [ -n "$slowrateslepp" ]; then _info "Slow rate activated: sleeping for $slowrateslepp seconds" - sleep $slowrateslepp + sleep "$slowrateslepp" fi return 0 fi From 1ef7fd36590068fd83631318c13b79bf384e0046 Mon Sep 17 00:00:00 2001 From: Dominic Jonas Date: Wed, 5 Jun 2019 11:38:41 +0200 Subject: [PATCH 014/357] support to delete multiple entries --- dnsapi/dns_kas.sh | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/dnsapi/dns_kas.sh b/dnsapi/dns_kas.sh index 3b608d43..14c0b378 100755 --- a/dnsapi/dns_kas.sh +++ b/dnsapi/dns_kas.sh @@ -69,27 +69,33 @@ dns_kas_rm() { _get_record_name "$_fulldomain" _get_record_id - # If there is a record_id, delete the entry + # If there is a record_id, delete the entry if [ -n "$_record_id" ]; then params="?kas_login=$KAS_Login" params="$params&kas_auth_type=$KAS_Authtype" params="$params&kas_auth_data=$KAS_Authdata" params="$params&kas_action=delete_dns_settings" - params="$params&var1=record_id" - params="$params&wert1=$_record_id" - _debug2 "Wait for 10 seconds by default before calling KAS API." - sleep 10 - response="$(_get "$KAS_Api$params")" - _debug2 "response" "$response" - if ! _contains "$response" "TRUE"; then - _err "Either the txt record is not found or another error occurred, please check manually." - return 1 - fi + + # split it into a seperated list, if there where multiples entries made + records=($_record_id) + for i in "${records[@]}" + do + params2="$params&var1=record_id" + params2="$params2&wert1=$i" + _debug2 "Wait for 10 seconds by default before calling KAS API." + sleep 10 + response="$(_get "$KAS_Api$params2")" + _debug2 "response" "$response" + if ! _contains "$response" "TRUE"; then + _err "Either the txt record is not found or another error occurred, please check manually." + return 1 + fi + done else # Cannot delete or unkown error _err "No record_id found that can be deleted. Please check manually." return 1 fi - return 0 +return 0 } ########################## PRIVATE FUNCTIONS ########################### @@ -147,4 +153,4 @@ _get_record_id() { _record_id="$(echo "$response" | grep -A 4 "$_record_name" | grep "record_id" | cut -f2 -d">" | xargs)" _debug2 _record_id "$_record_id" return 0 -} +} \ No newline at end of file From ae66c6f0b484ce5c451ff8c195f382115b3d15a0 Mon Sep 17 00:00:00 2001 From: David Kerr Date: Thu, 11 Jul 2019 15:46:17 -0400 Subject: [PATCH 015/357] Fix bug (in egrep regex) reported by @maks2018 in issue 2305 Fix bug reported by @maks2018 in issue https://github.com/Neilpang/acme.sh/issues/2305 by updating the regex in egrep of the subdomain html page. --- dnsapi/dns_freedns.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_freedns.sh b/dnsapi/dns_freedns.sh index e76e6495..ec845f89 100755 --- a/dnsapi/dns_freedns.sh +++ b/dnsapi/dns_freedns.sh @@ -305,7 +305,7 @@ _freedns_domain_id() { domain_id="$(echo "$htmlpage" | tr -d "[:space:]" | sed 's//@/g' | tr '@' '\n' \ | grep "$search_domain\|$search_domain(.*)" \ - | _egrep_o "edit\.php\?edit_domain_id=[0-9a-zA-Z]+" \ + | _egrep_o "edit\.php?edit_domain_id=[0-9a-zA-Z]*" \ | cut -d = -f 2)" # The above beauty extracts domain ID from the html page... # strip out all blank space and new lines. Then insert newlines @@ -352,7 +352,7 @@ _freedns_data_id() { data_id="$(echo "$htmlpage" | tr -d "[:space:]" | sed 's//@/g' | tr '@' '\n' \ | grep "$record_type" \ | grep "$search_domain" \ - | _egrep_o "edit\.php\?data_id=[0-9a-zA-Z]+" \ + | _egrep_o "edit\.php?data_id=[0-9a-zA-Z]*" \ | cut -d = -f 2)" # The above beauty extracts data ID from the html page... # strip out all blank space and new lines. Then insert newlines From 2ce9fb976024373850bb1de1e9ed939a995d3378 Mon Sep 17 00:00:00 2001 From: David Kerr Date: Thu, 11 Jul 2019 18:06:56 -0400 Subject: [PATCH 016/357] Work around bug in _egrep_o() function _egrep_o() function accepts extended regex and on systems that do not have egrep uses sed to emulate egrep. This is failing on the specific regex I was using before my last commit... https://github.com/dkerr64/acme.sh/commit/ae66c6f0b484ce5c451ff8c195f382115b3d15a0 The problem is that I fixed it by passing in non-extended regex which then fails on systems that do have egrep. So I am no longer using _egrep_o. --- dnsapi/dns_freedns.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_freedns.sh b/dnsapi/dns_freedns.sh index ec845f89..8a48cf77 100755 --- a/dnsapi/dns_freedns.sh +++ b/dnsapi/dns_freedns.sh @@ -305,7 +305,7 @@ _freedns_domain_id() { domain_id="$(echo "$htmlpage" | tr -d "[:space:]" | sed 's//@/g' | tr '@' '\n' \ | grep "$search_domain\|$search_domain(.*)" \ - | _egrep_o "edit\.php?edit_domain_id=[0-9a-zA-Z]*" \ + | grep -o "edit\.php?edit_domain_id=[0-9a-zA-Z]*" \ | cut -d = -f 2)" # The above beauty extracts domain ID from the html page... # strip out all blank space and new lines. Then insert newlines @@ -352,7 +352,7 @@ _freedns_data_id() { data_id="$(echo "$htmlpage" | tr -d "[:space:]" | sed 's//@/g' | tr '@' '\n' \ | grep "$record_type" \ | grep "$search_domain" \ - | _egrep_o "edit\.php?data_id=[0-9a-zA-Z]*" \ + | grep -o "edit\.php?data_id=[0-9a-zA-Z]*" \ | cut -d = -f 2)" # The above beauty extracts data ID from the html page... # strip out all blank space and new lines. Then insert newlines From 0b2b8b960b07232edd92fed0124a35cbfd969a87 Mon Sep 17 00:00:00 2001 From: David Kerr Date: Fri, 16 Aug 2019 22:56:22 -0400 Subject: [PATCH 017/357] Replace grep -o with sed --- dnsapi/dns_freedns.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_freedns.sh b/dnsapi/dns_freedns.sh index 8a48cf77..ee013662 100755 --- a/dnsapi/dns_freedns.sh +++ b/dnsapi/dns_freedns.sh @@ -305,7 +305,7 @@ _freedns_domain_id() { domain_id="$(echo "$htmlpage" | tr -d "[:space:]" | sed 's//@/g' | tr '@' '\n' \ | grep "$search_domain\|$search_domain(.*)" \ - | grep -o "edit\.php?edit_domain_id=[0-9a-zA-Z]*" \ + | sed -n 's/.*\(edit\.php?edit_domain_id=[0-9a-zA-Z]*\).*/\1/p' \ | cut -d = -f 2)" # The above beauty extracts domain ID from the html page... # strip out all blank space and new lines. Then insert newlines @@ -352,7 +352,7 @@ _freedns_data_id() { data_id="$(echo "$htmlpage" | tr -d "[:space:]" | sed 's//@/g' | tr '@' '\n' \ | grep "$record_type" \ | grep "$search_domain" \ - | grep -o "edit\.php?data_id=[0-9a-zA-Z]*" \ + | sed -n 's/.*\(edit\.php?data_id=[0-9a-zA-Z]*\).*/\1/p' \ | cut -d = -f 2)" # The above beauty extracts data ID from the html page... # strip out all blank space and new lines. Then insert newlines From e0deca33d00f6e8dfd9473b1d2bbf83132fb2e72 Mon Sep 17 00:00:00 2001 From: Rolph Haspers Date: Mon, 19 Aug 2019 14:27:23 +0200 Subject: [PATCH 018/357] Added Leaseweb API for dns-01 verification --- dnsapi/dns_leaseweb.sh | 130 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 dnsapi/dns_leaseweb.sh diff --git a/dnsapi/dns_leaseweb.sh b/dnsapi/dns_leaseweb.sh new file mode 100644 index 00000000..3edf55f0 --- /dev/null +++ b/dnsapi/dns_leaseweb.sh @@ -0,0 +1,130 @@ +#!/usr/bin/env sh + +#Author: Rolph Haspers +#Utilize leaseweb.com API to finish dns-01 verifications. +#Requires a Leaseweb API Key (export LSW_Key="Your Key") +######## Public functions ##################### + +LSW_API="https://api.leaseweb.com/hosting/v2/domains/" + +#Usage: dns_leaseweb_add _acme-challenge.www.domain.com +dns_leaseweb_add() { + fulldomain=$1 + txtvalue=$2 + + LSW_Key="${LSW_Key:-$(_readaccountconf_mutable LSW_Key)}" + if [ -z "$LSW_Key" ]; then + LSW_Key="" + _err "You don't specify Leaseweb api key yet." + _err "Please create your key and try again." + return 1 + fi + + #save the api key to the account conf file. + _saveaccountconf_mutable LSW_Key "$LSW_Key" + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + _debug _root_domain "$_domain" + _debug _domain "$fulldomain" + + if _lsw_api "POST" "$_domain" "$fulldomain" "$txtvalue"; then + if [ "$_code" = "201" ]; then + _info "Added, OK" + return 0 + else + _err "Add txt record error, invalid code. Code: $_code" + return 1 + fi + fi + _err "Add txt record error." + + return 1 +} + +#Usage: fulldomain txtvalue +#Remove the txt record after validation. +dns_leaseweb_rm() { + fulldomain=$1 + txtvalue=$2 + + LSW_Key="${LSW_Key:-$(_readaccountconf_mutable LSW_Key)}" + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + _debug _root_domain "$_domain" + _debug _domain "$fulldomain" + + if _lsw_api "DELETE" "$_domain" "$fulldomain" "$txtvalue"; then + if [ "$_code" = "204" ]; then + _info "Deleted, OK" + return 0 + else + _err "Delete txt record error." + return 1 + fi + fi + _err "Delete txt record error." + + return 1 +} + + +#################### Private functions below ################################## +# _acme-challenge.www.domain.com +# returns +# _domain=domain.com +_get_root() { + domain=$1 + i="$(echo "$fulldomain" | tr '.' ' ' | wc -w)" + i=$(_math "$i" - 1) + + while true; do + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) + if [ -z "$h" ]; then + return 1 + fi + _domain="$h" + return 0 + done + _debug "$domain not found" + return 1 +} + +_lsw_api() { + cmd=$1 + domain=$2 + fulldomain=$3 + txtvalue=$4 + + # Construct the HTTP Authorization header + export _H2="Content-Type: application/json" + export _H1="X-Lsw-Auth: ${LSW_Key}" + + if [ "$cmd" == "POST" ]; then + data="{\"name\": \"$fulldomain.\",\"type\": \"TXT\",\"content\": [\"$txtvalue\"],\"ttl\": 60}" + response="$(_post "$data" "$LSW_API/$domain/resourceRecordSets" "$data" "POST")" + _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" + _debug "http response code $_code" + _debug response "$response" + return 0 + fi + + if [ "$cmd" == "DELETE" ]; then + response="$(_post "" "$LSW_API/$domain/resourceRecordSets/$fulldomain/TXT" "" "DELETE")" + _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" + _debug "http response code $_code" + _debug response "$response" + return 0 + fi + + return 1 +} \ No newline at end of file From 54b38086e5abc37c48dcb55ffd2f3800098dd126 Mon Sep 17 00:00:00 2001 From: Rolph Haspers Date: Mon, 19 Aug 2019 15:39:19 +0200 Subject: [PATCH 019/357] Fix style issues --- dnsapi/dns_leaseweb.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_leaseweb.sh b/dnsapi/dns_leaseweb.sh index 3edf55f0..61609919 100644 --- a/dnsapi/dns_leaseweb.sh +++ b/dnsapi/dns_leaseweb.sh @@ -32,7 +32,7 @@ dns_leaseweb_add() { _debug _root_domain "$_domain" _debug _domain "$fulldomain" - if _lsw_api "POST" "$_domain" "$fulldomain" "$txtvalue"; then + if _lsw_api "POST" "$_domain" "$fulldomain" "$txtvalue"; then if [ "$_code" = "201" ]; then _info "Added, OK" return 0 @@ -63,7 +63,7 @@ dns_leaseweb_rm() { _debug _root_domain "$_domain" _debug _domain "$fulldomain" - if _lsw_api "DELETE" "$_domain" "$fulldomain" "$txtvalue"; then + if _lsw_api "DELETE" "$_domain" "$fulldomain" "$txtvalue"; then if [ "$_code" = "204" ]; then _info "Deleted, OK" return 0 @@ -109,16 +109,16 @@ _lsw_api() { export _H2="Content-Type: application/json" export _H1="X-Lsw-Auth: ${LSW_Key}" - if [ "$cmd" == "POST" ]; then + if [ "$cmd" = "POST" ]; then data="{\"name\": \"$fulldomain.\",\"type\": \"TXT\",\"content\": [\"$txtvalue\"],\"ttl\": 60}" - response="$(_post "$data" "$LSW_API/$domain/resourceRecordSets" "$data" "POST")" + response="$(_post "$data" "$LSW_API/$domain/resourceRecordSets" "$data" "POST")" _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" - _debug "http response code $_code" - _debug response "$response" + _debug "http response code $_code" + _debug response "$response" return 0 fi - if [ "$cmd" == "DELETE" ]; then + if [ "$cmd" = "DELETE" ]; then response="$(_post "" "$LSW_API/$domain/resourceRecordSets/$fulldomain/TXT" "" "DELETE")" _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" _debug "http response code $_code" @@ -127,4 +127,4 @@ _lsw_api() { fi return 1 -} \ No newline at end of file +} From 400c31d03162a596fcbb22330e38df26b960eac0 Mon Sep 17 00:00:00 2001 From: Rolph Haspers Date: Mon, 19 Aug 2019 16:01:51 +0200 Subject: [PATCH 020/357] Fixed another styling issue (trailing spaces) --- dnsapi/dns_leaseweb.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_leaseweb.sh b/dnsapi/dns_leaseweb.sh index 61609919..a792290b 100644 --- a/dnsapi/dns_leaseweb.sh +++ b/dnsapi/dns_leaseweb.sh @@ -111,7 +111,7 @@ _lsw_api() { if [ "$cmd" = "POST" ]; then data="{\"name\": \"$fulldomain.\",\"type\": \"TXT\",\"content\": [\"$txtvalue\"],\"ttl\": 60}" - response="$(_post "$data" "$LSW_API/$domain/resourceRecordSets" "$data" "POST")" + response="$(_post "$data" "$LSW_API/$domain/resourceRecordSets" "$data" "POST")" _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" _debug "http response code $_code" _debug response "$response" From 0ac37981cbd384ddfa7ccb890ccf4facb6c396ec Mon Sep 17 00:00:00 2001 From: Rolph Haspers Date: Mon, 19 Aug 2019 16:04:16 +0200 Subject: [PATCH 021/357] Styling, newline removed --- dnsapi/dns_leaseweb.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_leaseweb.sh b/dnsapi/dns_leaseweb.sh index a792290b..17038f46 100644 --- a/dnsapi/dns_leaseweb.sh +++ b/dnsapi/dns_leaseweb.sh @@ -77,7 +77,6 @@ dns_leaseweb_rm() { return 1 } - #################### Private functions below ################################## # _acme-challenge.www.domain.com # returns From 4a81205e04f22f0de645d117e243794ba6ca403a Mon Sep 17 00:00:00 2001 From: Rolph Haspers Date: Mon, 19 Aug 2019 16:22:48 +0200 Subject: [PATCH 022/357] Styling, trailing space --- dnsapi/dns_leaseweb.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_leaseweb.sh b/dnsapi/dns_leaseweb.sh index 17038f46..c9df4dc6 100644 --- a/dnsapi/dns_leaseweb.sh +++ b/dnsapi/dns_leaseweb.sh @@ -59,7 +59,7 @@ dns_leaseweb_rm() { _err "invalid domain" return 1 fi - + _debug _root_domain "$_domain" _debug _domain "$fulldomain" From f0d6d46766c8484e32010b2dc624130650900a3c Mon Sep 17 00:00:00 2001 From: Rolph Haspers Date: Mon, 19 Aug 2019 17:27:19 +0200 Subject: [PATCH 023/357] Added link to API docs --- dnsapi/dns_leaseweb.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/dnsapi/dns_leaseweb.sh b/dnsapi/dns_leaseweb.sh index c9df4dc6..976ad5ac 100644 --- a/dnsapi/dns_leaseweb.sh +++ b/dnsapi/dns_leaseweb.sh @@ -3,6 +3,7 @@ #Author: Rolph Haspers #Utilize leaseweb.com API to finish dns-01 verifications. #Requires a Leaseweb API Key (export LSW_Key="Your Key") +#See http://developer.leaseweb.com for more information. ######## Public functions ##################### LSW_API="https://api.leaseweb.com/hosting/v2/domains/" From 4bf1f579f51d7343c1b643f7bb357ba9e48d0cd6 Mon Sep 17 00:00:00 2001 From: Jesai Langenbach Date: Thu, 12 Sep 2019 16:28:57 +0200 Subject: [PATCH 024/357] Add OPNsense Bind API Support --- dnsapi/dns_opnsense.sh | 262 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100755 dnsapi/dns_opnsense.sh diff --git a/dnsapi/dns_opnsense.sh b/dnsapi/dns_opnsense.sh new file mode 100755 index 00000000..aa123541 --- /dev/null +++ b/dnsapi/dns_opnsense.sh @@ -0,0 +1,262 @@ +#!/usr/bin/env sh + +#OPNsense Bind API +#https://docs.opnsense.org/development/api.html +# +#OPNs_Host="opnsense.example.com" +#OPNs_Port="443" +#OPNs_Key="qocfU9RSbt8vTIBcnW8bPqCrpfAHMDvj5OzadE7Str+rbjyCyk7u6yMrSCHtBXabgDDXx/dY0POUp7ZA" +#OPNs_Token="pZEQ+3ce8dDlfBBdg3N8EpqpF5I1MhFqdxX06le6Gl8YzyQvYCfCzNaFX9O9+IOSyAs7X71fwdRiZ+Lv" +#OPNs_Api_Insecure=1 # Set 1 for insecure and 0 for secure -> difference is whether ssl cert is checked for validity (0) or whether it is just accepted (1) + +######## Public functions ##################### +#Usage: add _acme-challenge.www.domain.com "123456789ABCDEF0000000000000000000000000000000000000" +#fulldomain +#txtvalue +dns_opnsense_add() { + fulldomain=$1 + txtvalue=$2 + + _opns_check_auth || return 1 + + if ! set_record "$fulldomain" "$txtvalue"; then + return 1 + fi + + return 0 +} + +#fulldomain +dns_opnsense_rm() { + fulldomain=$1 + txtvalue=$2 + + _opns_check_auth || return 1 + + if ! rm_record "$fulldomain" "$txtvalue"; then + return 1 + fi + + return 0 +} + +set_record() { + _info "Adding record" + fulldomain=$1 + new_challenge=$2 + + _debug "Detect root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _domain "$_domain" + _debug _host "$_host" + _debug _domainid "$_domainid" + _return_str="" + _record_string="" + _build_record_string "$_domainid" "$_host" "$new_challenge" + _uuid="" + if _existingchallenge "$_domain" "$_host" "$new_challenge"; then + # Update + if _opns_rest "POST" "/record/setRecord/${_uuid}" "$_record_string"; then + _return_str="$response" + else + return 1 + fi + + else + #create + if _opns_rest "POST" "/record/addRecord" "$_record_string"; then + _return_str="$response" + else + return 1 + fi + fi + + if echo "$_return_str" | _egrep_o "\"result\":\"saved\"" >/dev/null + then + _opns_rest "POST" "/service/reconfigure" "{}" + _debug "Record created" + else + _err "Error createing record $_record_string" + return 1 + fi + + return 0 +} + +rm_record() { + _info "Remove record" + fulldomain=$1 + new_challenge="$2" + + _debug "Detect root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + _debug _domain "$_domain" + _debug _host "$_host" + _debug _domainid "$_domainid" + _uuid="" + if _existingchallenge "$_domain" "$_host" "$new_challenge"; then + # Delete + if _opns_rest "POST" "/record/delRecord/${_uuid}" "\{\}"; then + if echo "$_return_str" | _egrep_o "result":"deleted" >/dev/null; then + _opns_rest "POST" "/service/reconfigure" "{}" + _debug "Record deleted" + else + _err "Error delteting record $fulldomain" + return 1 + fi + else + _err "Error delteting record $fulldomain" + return 1 + fi + else + _info "Record not found, nothing to remove" + fi + + return 0 +} + +#################### Private functions below ################################## +#_acme-challenge.www.domain.com +#returns +# _domainid=domid + #_domain=domain.com +_get_root() { + domain=$1 + i=2 + p=1 + if _opns_rest "GET" "/domain/get"; then + _domain_response="$response" + else + return 1 + fi + + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + if [ -z "$h" ]; then + #not valid + return 1 + fi + _debug h "$h" + id=$(echo $_domain_response| _egrep_o "\"[^\"]*\":{\"enabled\":\"1\",\"type\":{\"master\":{\"value\":\"master\",\"selected\":1},\"slave\":{\"value\":\"slave\",\"selected\":0}},\"masterip\":\"[^\"]*\",\"domainname\":\"${h}\"" | cut -d ':' -f 1 | cut -d '"' -f 2 ) + + if [ -n "$id" ];then + _debug id "$id" + _host=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain="${h}" + _domainid="${id}" + return 0 + fi + p=$i + i=$(_math $i + 1) + done + _debug "$domain not found" + + return 1 +} + +_opns_rest() { + method=$1 + ep=$2 + data=$3 + #Percent encode user and token + key=$(echo $OPNs_Key | tr -d "\n\r" | _url_encode ) + token=$(echo $OPNs_Token| tr -d "\n\r" | _url_encode ) + + opnsense_url="https://${key}:${token}@${OPNs_Host}:${OPNs_Port}/api/bind${ep}" + export _H1="Content-Type: application/json" + if [ ! "$method" = "GET" ]; then + _debug data "$data" + export _H1="Content-Type: application/json" + response="$(_post "$data" "$opnsense_url" "" "$method")" + else + export _H1="" + response="$(_get "$opnsense_url")" + fi + + if [ "$?" != "0" ]; then + _err "error $ep" + return 1 + fi + _debug2 response "$response" + + return 0 +} + +_build_record_string() { + _record_string="{\"record\":{\"enabled\":\"1\",\"domain\":\"$1\",\"name\":\"$2\",\"type\":\"TXT\",\"value\":\"$3\"}}" +} + +_existingchallenge() { + if _opns_rest "GET" "/record/searchRecord"; then + _record_response="$response" + else + return 1 + fi + _uuid="" + _uuid=$( echo $_record_response| _egrep_o "\"uuid\":\"[^\"]*\",\"enabled\":\"[01]\",\"domain\":\"$1\",\"name\":\"$2\",\"type\":\"TXT\",\"value\":\"$3\"" | cut -d ':' -f 2 | cut -d '"' -f 2 ) + + if [ -n "$_uuid" ];then + _debug uuid "$_uuid" + return 0 + fi + _debug "${2}.$1{1} record not found" + + return 1 +} + +_opns_check_auth() { + OPNs_Host="${OPNs_Host:-$(_readaccountconf_mutable OPNs_Host)}" + OPNs_Port="${OPNs_Port:-$(_readaccountconf_mutable OPNs_Port)}" + OPNs_Key="${OPNs_Key:-$(_readaccountconf_mutable OPNs_Key)}" + OPNs_Token="${OPNs_Token:-$(_readaccountconf_mutable OPNs_Token)}" + OPNs_Api_Insecure="${OPNs_Api_Insecure:-$(_readaccountconf_mutable OPNs_Api_Insecure)}" + + if [ -z "$OPNs_Host" ]; then + OPNs_Host="localhost" + _err "You don't specify OPNsense address." + fi + + if [ -z "$OPNs_Port" ]; then + OPNs_Port="443" + _err "You don't specify OPNsense Port." + fi + + if [ -z "$OPNs_Api_Insecure" ]; then + OPNs_Api_Insecure="0" + fi + + if [ -z "$OPNs_Key" ]; then + OPNs_Key="" + _err "You don't specify OPNsense api key id." + _err "Please set you OPNs_Key and try again." + return 1 + fi + + if [ -z "$OPNs_Token" ]; then + OPNs_Token="" + _err "You don't specify OPNsense token." + _err "Please create you OPNs_Token and try again." + return 1 + fi + + #save the api addr and key to the account conf file. + _saveaccountconf_mutable OPNs_Host "$OPNs_Host" + _saveaccountconf_mutable OPNs_Port "$OPNs_Port" + _saveaccountconf_mutable OPNs_Key "$OPNs_Key" + _saveaccountconf_mutable OPNs_Token "$OPNs_Token" + _saveaccountconf_mutable OPNs_Api_Insecure "$OPNs_Api_Insecure" + export HTTPS_INSECURE="${OPNs_Api_Insecure}" + + if ! _opns_rest "GET" "/general/get";then + _err "Can't Access OPNsense" + return 1 + fi + return 0 +} From dfb4883c936bed4377424aa3df3bb4a5a4576c2c Mon Sep 17 00:00:00 2001 From: Jesai Langenbach Date: Thu, 12 Sep 2019 17:17:32 +0200 Subject: [PATCH 025/357] Some fixes --- dnsapi/dns_opnsense.sh | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/dnsapi/dns_opnsense.sh b/dnsapi/dns_opnsense.sh index aa123541..8b7942a7 100755 --- a/dnsapi/dns_opnsense.sh +++ b/dnsapi/dns_opnsense.sh @@ -7,7 +7,7 @@ #OPNs_Port="443" #OPNs_Key="qocfU9RSbt8vTIBcnW8bPqCrpfAHMDvj5OzadE7Str+rbjyCyk7u6yMrSCHtBXabgDDXx/dY0POUp7ZA" #OPNs_Token="pZEQ+3ce8dDlfBBdg3N8EpqpF5I1MhFqdxX06le6Gl8YzyQvYCfCzNaFX9O9+IOSyAs7X71fwdRiZ+Lv" -#OPNs_Api_Insecure=1 # Set 1 for insecure and 0 for secure -> difference is whether ssl cert is checked for validity (0) or whether it is just accepted (1) +#OPNs_Api_Insecure=0 # Set 1 for insecure and 0 for secure -> difference is whether ssl cert is checked for validity (0) or whether it is just accepted (1) ######## Public functions ##################### #Usage: add _acme-challenge.www.domain.com "123456789ABCDEF0000000000000000000000000000000000000" @@ -74,8 +74,7 @@ set_record() { fi fi - if echo "$_return_str" | _egrep_o "\"result\":\"saved\"" >/dev/null - then + if echo "$_return_str" | _egrep_o "\"result\":\"saved\"" >/dev/null; then _opns_rest "POST" "/service/reconfigure" "{}" _debug "Record created" else @@ -103,8 +102,8 @@ rm_record() { _uuid="" if _existingchallenge "$_domain" "$_host" "$new_challenge"; then # Delete - if _opns_rest "POST" "/record/delRecord/${_uuid}" "\{\}"; then - if echo "$_return_str" | _egrep_o "result":"deleted" >/dev/null; then + if _opns_rest "POST" "/record/delRecord/${_uuid}" "\{\}"; then + if echo "$_return_str" | _egrep_o "\"result\":\"deleted\"" >/dev/null; then _opns_rest "POST" "/service/reconfigure" "{}" _debug "Record deleted" else @@ -112,8 +111,8 @@ rm_record() { return 1 fi else - _err "Error delteting record $fulldomain" - return 1 + _err "Error delteting record $fulldomain" + return 1 fi else _info "Record not found, nothing to remove" @@ -126,7 +125,7 @@ rm_record() { #_acme-challenge.www.domain.com #returns # _domainid=domid - #_domain=domain.com +#_domain=domain.com _get_root() { domain=$1 i=2 @@ -144,9 +143,9 @@ _get_root() { return 1 fi _debug h "$h" - id=$(echo $_domain_response| _egrep_o "\"[^\"]*\":{\"enabled\":\"1\",\"type\":{\"master\":{\"value\":\"master\",\"selected\":1},\"slave\":{\"value\":\"slave\",\"selected\":0}},\"masterip\":\"[^\"]*\",\"domainname\":\"${h}\"" | cut -d ':' -f 1 | cut -d '"' -f 2 ) + id=$(echo "$_domain_response" | _egrep_o "\"[^\"]*\":{\"enabled\":\"1\",\"type\":{\"master\":{\"value\":\"master\",\"selected\":1},\"slave\":{\"value\":\"slave\",\"selected\":0}},\"masterip\":\"[^\"]*\",\"domainname\":\"${h}\"" | cut -d ':' -f 1 | cut -d '"' -f 2) - if [ -n "$id" ];then + if [ -n "$id" ]; then _debug id "$id" _host=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain="${h}" @@ -166,8 +165,8 @@ _opns_rest() { ep=$2 data=$3 #Percent encode user and token - key=$(echo $OPNs_Key | tr -d "\n\r" | _url_encode ) - token=$(echo $OPNs_Token| tr -d "\n\r" | _url_encode ) + key=$(echo "$OPNs_Key" | tr -d "\n\r" | _url_encode) + token=$(echo "$OPNs_Token" | tr -d "\n\r" | _url_encode) opnsense_url="https://${key}:${token}@${OPNs_Host}:${OPNs_Port}/api/bind${ep}" export _H1="Content-Type: application/json" @@ -200,9 +199,9 @@ _existingchallenge() { return 1 fi _uuid="" - _uuid=$( echo $_record_response| _egrep_o "\"uuid\":\"[^\"]*\",\"enabled\":\"[01]\",\"domain\":\"$1\",\"name\":\"$2\",\"type\":\"TXT\",\"value\":\"$3\"" | cut -d ':' -f 2 | cut -d '"' -f 2 ) + _uuid=$( echo "$_record_response" | _egrep_o "\"uuid\":\"[^\"]*\",\"enabled\":\"[01]\",\"domain\":\"$1\",\"name\":\"$2\",\"type\":\"TXT\",\"value\":\"$3\"" | cut -d ':' -f 2 | cut -d '"' -f 2) - if [ -n "$_uuid" ];then + if [ -n "$_uuid" ]; then _debug uuid "$_uuid" return 0 fi @@ -254,7 +253,7 @@ _opns_check_auth() { _saveaccountconf_mutable OPNs_Api_Insecure "$OPNs_Api_Insecure" export HTTPS_INSECURE="${OPNs_Api_Insecure}" - if ! _opns_rest "GET" "/general/get";then + if ! _opns_rest "GET" "/general/get"; then _err "Can't Access OPNsense" return 1 fi From ec654d2355b47571f6d6fc1cbfcc3a8e808491c3 Mon Sep 17 00:00:00 2001 From: Jesai Langenbach Date: Thu, 12 Sep 2019 17:24:00 +0200 Subject: [PATCH 026/357] More space removing --- dnsapi/dns_opnsense.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_opnsense.sh b/dnsapi/dns_opnsense.sh index 8b7942a7..ac8be539 100755 --- a/dnsapi/dns_opnsense.sh +++ b/dnsapi/dns_opnsense.sh @@ -74,7 +74,7 @@ set_record() { fi fi - if echo "$_return_str" | _egrep_o "\"result\":\"saved\"" >/dev/null; then + if echo "$_return_str" | _egrep_o "\"result\":\"saved\"" >/dev/null; then _opns_rest "POST" "/service/reconfigure" "{}" _debug "Record created" else @@ -143,7 +143,7 @@ _get_root() { return 1 fi _debug h "$h" - id=$(echo "$_domain_response" | _egrep_o "\"[^\"]*\":{\"enabled\":\"1\",\"type\":{\"master\":{\"value\":\"master\",\"selected\":1},\"slave\":{\"value\":\"slave\",\"selected\":0}},\"masterip\":\"[^\"]*\",\"domainname\":\"${h}\"" | cut -d ':' -f 1 | cut -d '"' -f 2) + id=$(echo "$_domain_response" | _egrep_o "\"[^\"]*\":{\"enabled\":\"1\",\"type\":{\"master\":{\"value\":\"master\",\"selected\":1},\"slave\":{\"value\":\"slave\",\"selected\":0}},\"masterip\":\"[^\"]*\",\"domainname\":\"${h}\"" | cut -d ':' -f 1 | cut -d '"' -f 2) if [ -n "$id" ]; then _debug id "$id" @@ -199,7 +199,7 @@ _existingchallenge() { return 1 fi _uuid="" - _uuid=$( echo "$_record_response" | _egrep_o "\"uuid\":\"[^\"]*\",\"enabled\":\"[01]\",\"domain\":\"$1\",\"name\":\"$2\",\"type\":\"TXT\",\"value\":\"$3\"" | cut -d ':' -f 2 | cut -d '"' -f 2) + _uuid=$( echo "$_record_response" | _egrep_o "\"uuid\":\"[^\"]*\",\"enabled\":\"[01]\",\"domain\":\"$1\",\"name\":\"$2\",\"type\":\"TXT\",\"value\":\"$3\"" | cut -d ':' -f 2 | cut -d '"' -f 2) if [ -n "$_uuid" ]; then _debug uuid "$_uuid" From bfa6e52470de86363112c4e265721cd36ed2e400 Mon Sep 17 00:00:00 2001 From: Jesai Langenbach Date: Thu, 12 Sep 2019 20:50:20 +0200 Subject: [PATCH 027/357] another whitespace --- dnsapi/dns_opnsense.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_opnsense.sh b/dnsapi/dns_opnsense.sh index ac8be539..ff6f8a54 100755 --- a/dnsapi/dns_opnsense.sh +++ b/dnsapi/dns_opnsense.sh @@ -199,7 +199,7 @@ _existingchallenge() { return 1 fi _uuid="" - _uuid=$( echo "$_record_response" | _egrep_o "\"uuid\":\"[^\"]*\",\"enabled\":\"[01]\",\"domain\":\"$1\",\"name\":\"$2\",\"type\":\"TXT\",\"value\":\"$3\"" | cut -d ':' -f 2 | cut -d '"' -f 2) + _uuid=$(echo "$_record_response" | _egrep_o "\"uuid\":\"[^\"]*\",\"enabled\":\"[01]\",\"domain\":\"$1\",\"name\":\"$2\",\"type\":\"TXT\",\"value\":\"$3\"" | cut -d ':' -f 2 | cut -d '"' -f 2) if [ -n "$_uuid" ]; then _debug uuid "$_uuid" From 10eec7d48c11e91e988be335f5bd4989b628aadb Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 3 Oct 2019 20:37:46 +0800 Subject: [PATCH 028/357] support google dns --- acme.sh | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/acme.sh b/acme.sh index 0ff24c98..bded4ada 100755 --- a/acme.sh +++ b/acme.sh @@ -90,6 +90,9 @@ DEBUG_LEVEL_3=3 DEBUG_LEVEL_DEFAULT=$DEBUG_LEVEL_1 DEBUG_LEVEL_NONE=0 +DOH_CLOUDFLARE=1 +DOH_GOOGLE=2 + HIDDEN_VALUE="[hidden](please add '--output-insecure' to see this value)" SYSLOG_ERROR="user.error" @@ -3636,7 +3639,7 @@ __trigger_validation() { } #endpoint domain type -_ns_lookup() { +_ns_lookup_impl() { _ns_ep="$1" _ns_domain="$2" _ns_type="$3" @@ -3660,7 +3663,7 @@ _ns_lookup_cf() { _cf_ld="$1" _cf_ld_type="$2" _cf_ep="https://cloudflare-dns.com/dns-query" - _ns_lookup "$_cf_ep" "$_cf_ld" "$_cf_ld_type" + _ns_lookup_impl "$_cf_ep" "$_cf_ld" "$_cf_ld_type" } #domain, type @@ -3673,6 +3676,44 @@ _ns_purge_cf() { _debug2 response "$response" } +#checks if cf server is available +_ns_is_available_cf() { + if _get "https://cloudflare-dns.com"; then + return 0 + else + return 1 + fi +} + +#domain, type +_ns_lookup_google() { + _cf_ld="$1" + _cf_ld_type="$2" + _cf_ep="https://dns.google/resolve" + _ns_lookup_impl "$_cf_ep" "$_cf_ld" "$_cf_ld_type" +} + +#domain, type +_ns_lookup() { + if [ -z "$DOH_USE" ]; then + _debug "Detect dns server first." + if _ns_is_available_cf; then + _debug "Use cloudflare doh server" + export DOH_USE=$DOH_CLOUDFLARE + else + _debug "Use google doh server" + export DOH_USE=$DOH_GOOGLE + fi + fi + + if [ "$DOH_USE" = "$DOH_CLOUDFLARE" ] || [ -z "$DOH_USE" ]; then + _ns_lookup_cf "$@" + else + _ns_lookup_google "$@" + fi + +} + #txtdomain, alias, txt __check_txt() { _c_txtdomain="$1" @@ -3681,7 +3722,7 @@ __check_txt() { _debug "_c_txtdomain" "$_c_txtdomain" _debug "_c_aliasdomain" "$_c_aliasdomain" _debug "_c_txt" "$_c_txt" - _answers="$(_ns_lookup_cf "$_c_aliasdomain" TXT)" + _answers="$(_ns_lookup "$_c_aliasdomain" TXT)" _contains "$_answers" "$_c_txt" } @@ -3690,7 +3731,13 @@ __check_txt() { __purge_txt() { _p_txtdomain="$1" _debug _p_txtdomain "$_p_txtdomain" - _ns_purge_cf "$_p_txtdomain" "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" + _sleep 5 + fi + } #wait and check each dns entries From b4a62bfa300b0d4c95a3f279b626227e50a8f0a5 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 3 Oct 2019 20:51:06 +0800 Subject: [PATCH 029/357] let's start 2.8.4 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index bded4ada..041b5b44 100755 --- a/acme.sh +++ b/acme.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -VER=2.8.3 +VER=2.8.4 PROJECT_NAME="acme.sh" From 8ef5daa8070d8c8e2d71b366f14d498c27a74261 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 3 Oct 2019 21:14:11 +0800 Subject: [PATCH 030/357] minor, update link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index faaf9aa9..d5012d68 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # An ACME Shell script: acme.sh [![Build Status](https://travis-ci.org/Neilpang/acme.sh.svg?branch=master)](https://travis-ci.org/Neilpang/acme.sh) - [![Join the chat at https://gitter.im/acme-sh/Lobby](https://badges.gitter.im/acme-sh/Lobby.svg)](https://gitter.im/acme-sh/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + [![Join the chat at https://gitter.im/acme-sh/Lobby](https://badges.gitter.im/acme-sh/Lobby.svg)](https://gitter.im/acme-sh/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - An ACME protocol client written purely in Shell (Unix shell) language. - Full ACME protocol implementation. - Support ACME v1 and ACME v2 From 72d800ed1098a77f565c14691f164be8ccab969b Mon Sep 17 00:00:00 2001 From: Michael Braunoeder Date: Sat, 5 Oct 2019 05:47:57 +0200 Subject: [PATCH 031/357] [DNSAPI] add dns_rcode0.sh - Support for https://my.rcodezero.at/api-doc (#2489) * first version dns_rcode0.sh * fixed URLs for ACME calls * fixed challenge remove * read & write Token/URL at rm too * make info messages debug * typos fixed * update rrset only if existing challenge is found * polish error messages and make "detect root zone" scaleable * fixed formating issues * code cleanup, remove some unneeded functions * removed empty lines * save rcode0 url only if not default --- dnsapi/dns_rcode0.sh | 224 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100755 dnsapi/dns_rcode0.sh diff --git a/dnsapi/dns_rcode0.sh b/dnsapi/dns_rcode0.sh new file mode 100755 index 00000000..9ed20e68 --- /dev/null +++ b/dnsapi/dns_rcode0.sh @@ -0,0 +1,224 @@ +#!/usr/bin/env sh + +#Rcode0 API Integration +#https://my.rcodezero.at/api-doc +# +# log into https://my.rcodezero.at/enableapi and get your ACME API Token (the ACME API token has limited +# access to the REST calls needed for acme.sh only) +# +#RCODE0_URL="https://my.rcodezero.at" +#RCODE0_API_TOKEN="0123456789ABCDEF" +#RCODE0_TTL=60 + +DEFAULT_RCODE0_URL="https://my.rcodezero.at" +DEFAULT_RCODE0_TTL=60 + +######## Public functions ##################### +#Usage: add _acme-challenge.www.domain.com "123456789ABCDEF0000000000000000000000000000000000000" +#fulldomain +#txtvalue +dns_rcode0_add() { + fulldomain=$1 + txtvalue=$2 + + RCODE0_API_TOKEN="${RCODE0_API_TOKEN:-$(_readaccountconf_mutable RCODE0_API_TOKEN)}" + RCODE0_URL="${RCODE0_URL:-$(_readaccountconf_mutable RCODE0_URL)}" + RCODE0_TTL="${RCODE0_TTL:-$(_readaccountconf_mutable RCODE0_TTL)}" + + if [ -z "$RCODE0_URL" ]; then + RCODE0_URL="$DEFAULT_RCODE0_URL" + fi + + if [ -z "$RCODE0_API_TOKEN" ]; then + RCODE0_API_TOKEN="" + _err "Missing Rcode0 ACME API Token." + _err "Please login and create your token at httsp://my.rcodezero.at/enableapi and try again." + return 1 + fi + + if [ -z "$RCODE0_TTL" ]; then + RCODE0_TTL="$DEFAULT_RCODE0_TTL" + fi + + #save the token to the account conf file. + _saveaccountconf_mutable RCODE0_API_TOKEN "$RCODE0_API_TOKEN" + + if [ "$RCODE0_URL" != "$DEFAULT_RCODE0_URL" ]; then + _saveaccountconf_mutable RCODE0_URL "$RCODE0_URL" + fi + + if [ "$RCODE0_TTL" != "$DEFAULT_RCODE0_TTL" ]; then + _saveaccountconf_mutable RCODE0_TTL "$RCODE0_TTL" + fi + + _debug "Detect root zone" + if ! _get_root "$fulldomain"; then + _err "No 'MASTER' zone for $fulldomain found at RcodeZero Anycast." + return 1 + fi + _debug _domain "$_domain" + + _debug "Adding record" + + _record_string="" + _build_record_string "$txtvalue" + _list_existingchallenges + for oldchallenge in $_existing_challenges; do + _build_record_string "$oldchallenge" + done + + _debug "Challenges: $_existing_challenges" + + if [ -z "$_existing_challenges" ]; then + if ! _rcode0_rest "PATCH" "/api/v1/acme/zones/$_domain/rrsets" "[{\"changetype\": \"add\", \"name\": \"$fulldomain.\", \"type\": \"TXT\", \"ttl\": $RCODE0_TTL, \"records\": [$_record_string]}]"; then + _err "Add txt record error." + return 1 + fi + else + # try update in case a records exists (need for wildcard certs) + if ! _rcode0_rest "PATCH" "/api/v1/acme/zones/$_domain/rrsets" "[{\"changetype\": \"update\", \"name\": \"$fulldomain.\", \"type\": \"TXT\", \"ttl\": $RCODE0_TTL, \"records\": [$_record_string]}]"; then + _err "Set txt record error." + return 1 + fi + fi + + return 0 +} + +#fulldomain txtvalue +dns_rcode0_rm() { + fulldomain=$1 + txtvalue=$2 + + RCODE0_API_TOKEN="${RCODE0_API_TOKEN:-$(_readaccountconf_mutable RCODE0_API_TOKEN)}" + RCODE0_URL="${RCODE0_URL:-$(_readaccountconf_mutable RCODE0_URL)}" + RCODE0_TTL="${RCODE0_TTL:-$(_readaccountconf_mutable RCODE0_TTL)}" + + if [ -z "$RCODE0_URL" ]; then + RCODE0_URL="$DEFAULT_RCODE0_URL" + fi + + if [ -z "$RCODE0_API_TOKEN" ]; then + RCODE0_API_TOKEN="" + _err "Missing Rcode0 API Token." + _err "Please login and create your token at httsp://my.rcodezero.at/enableapi and try again." + return 1 + fi + + #save the api addr and key to the account conf file. + _saveaccountconf_mutable RCODE0_URL "$RCODE0_URL" + _saveaccountconf_mutable RCODE0_API_TOKEN "$RCODE0_API_TOKEN" + + if [ "$RCODE0_TTL" != "$DEFAULT_RCODE0_TTL" ]; then + _saveaccountconf_mutable RCODE0_TTL "$RCODE0_TTL" + fi + + if [ -z "$RCODE0_TTL" ]; then + RCODE0_TTL="$DEFAULT_RCODE0_TTL" + fi + + _debug "Detect root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + _debug "Remove record" + + #Enumerate existing acme challenges + _list_existingchallenges + + if _contains "$_existing_challenges" "$txtvalue"; then + #Delete all challenges (PowerDNS API does not allow to delete content) + if ! _rcode0_rest "PATCH" "/api/v1/acme/zones/$_domain/rrsets" "[{\"changetype\": \"delete\", \"name\": \"$fulldomain.\", \"type\": \"TXT\"}]"; then + _err "Delete txt record error." + return 1 + fi + _record_string="" + #If the only existing challenge was the challenge to delete: nothing to do + if ! [ "$_existing_challenges" = "$txtvalue" ]; then + for oldchallenge in $_existing_challenges; do + #Build up the challenges to re-add, ommitting the one what should be deleted + if ! [ "$oldchallenge" = "$txtvalue" ]; then + _build_record_string "$oldchallenge" + fi + done + #Recreate the existing challenges + if ! _rcode0_rest "PATCH" "/api/v1/acme/zones/$_domain/rrsets" "[{\"changetype\": \"update\", \"name\": \"$fulldomain.\", \"type\": \"TXT\", \"ttl\": $RCODE0_TTL, \"records\": [$_record_string]}]"; then + _err "Set txt record error." + return 1 + fi + fi + else + _info "Record not found, nothing to remove" + fi + + return 0 +} + +#################### Private functions below ################################## +#_acme-challenge.www.domain.com +#returns +# _domain=domain.com +_get_root() { + domain=$1 + i=1 + + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + + _debug "try to find: $h" + if _rcode0_rest "GET" "/api/v1/acme/zones/$h"; then + if [ "$response" = "[\"found\"]" ]; then + _domain="$h" + if [ -z "$h" ]; then + _domain="=2E" + fi + return 0 + elif [ "$response" = "[\"not a master domain\"]" ]; then + return 1 + fi + fi + + if [ -z "$h" ]; then + return 1 + fi + i=$(_math $i + 1) + done + _debug "no matching domain for $domain found" + + return 1 +} + +_rcode0_rest() { + method=$1 + ep=$2 + data=$3 + + export _H1="Authorization: Bearer $RCODE0_API_TOKEN" + + if [ ! "$method" = "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$RCODE0_URL$ep" "" "$method")" + else + response="$(_get "$RCODE0_URL$ep")" + fi + + if [ "$?" != "0" ]; then + _err "error $ep" + return 1 + fi + _debug2 response "$response" + + return 0 +} + +_build_record_string() { + _record_string="${_record_string:+${_record_string}, }{\"content\": \"\\\"${1}\\\"\", \"disabled\": false}" +} + +_list_existingchallenges() { + _rcode0_rest "GET" "/api/v1/acme/zones/$_domain/rrsets" + _existing_challenges=$(echo "$response" | _normalizeJson | _egrep_o "\"name\":\"${fulldomain}[^]]*}" | _egrep_o 'content\":\"\\"[^\\]*' | sed -n 's/^content":"\\"//p') + _debug2 "$_existing_challenges" +} From 1e7534b9d7a4e629f46c6eb9995db20fcf962d80 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 5 Oct 2019 11:59:04 +0800 Subject: [PATCH 032/357] fix https://github.com/Neilpang/acme.sh/issues/2518#issuecomment-538474232 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 041b5b44..cac16d35 100755 --- a/acme.sh +++ b/acme.sh @@ -3678,7 +3678,7 @@ _ns_purge_cf() { #checks if cf server is available _ns_is_available_cf() { - if _get "https://cloudflare-dns.com"; then + if _get "https://cloudflare-dns.com" >/dev/null 2>&1; then return 0 else return 1 From ac9f6e3a4135dbc008c4e22af7f649d139690918 Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Sat, 5 Oct 2019 21:06:58 +0800 Subject: [PATCH 033/357] Remove trailing spaces in text files This issue in the shell scripts will also be detected in the stable version of shfmt(we are currently using an ancient pre-release of shfmt) --- .github/ISSUE_TEMPLATE.md | 2 +- .travis.yml | 4 ++-- acme.sh | 4 ++-- deploy/qiniu.sh | 2 +- deploy/routeros.sh | 2 +- deploy/vault_cli.sh | 4 ++-- dnsapi/dns_da.sh | 2 +- dnsapi/dns_doapi.sh | 6 +++--- dnsapi/dns_durabledns.sh | 10 +++++----- dnsapi/dns_euserv.sh | 2 +- dnsapi/dns_freedns.sh | 2 +- dnsapi/dns_me.sh | 2 +- dnsapi/dns_namecheap.sh | 6 +++--- dnsapi/dns_nsupdate.sh | 4 ++-- dnsapi/dns_rcode0.sh | 2 +- 15 files changed, 27 insertions(+), 27 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 189155e1..53112c6f 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -5,7 +5,7 @@ 如何调试 https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh If it is a bug report: -- make sure you are able to repro it on the latest released version. +- make sure you are able to repro it on the latest released version. You can install the latest version by: `acme.sh --upgrade` - Search the existing issues. diff --git a/.travis.yml b/.travis.yml index 04de1934..e77eb32c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,5 +34,5 @@ script: matrix: fast_finish: true - - + + diff --git a/acme.sh b/acme.sh index cac16d35..e060e334 100755 --- a/acme.sh +++ b/acme.sh @@ -178,7 +178,7 @@ _printargs() { printf -- "%s" "$1='$2'" fi printf "\n" - # return the saved exit status + # return the saved exit status return "$_exitstatus" } @@ -6215,7 +6215,7 @@ Parameters: --branch, -b Only valid for '--upgrade' command, specifies the branch name to upgrade to. --notify-level 0|1|2|3 Set the notification level: Default value is $NOTIFY_LEVEL_DEFAULT. - 0: disabled, no notification will be sent. + 0: disabled, no notification will be sent. 1: send notifications only when there is an error. 2: send notifications when a cert is successfully renewed, or there is an error. 3: send notifications when a cert is skipped, renewed, or error. diff --git a/deploy/qiniu.sh b/deploy/qiniu.sh index e46e6fb3..13b09651 100644 --- a/deploy/qiniu.sh +++ b/deploy/qiniu.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -# Script to create certificate to qiniu.com +# Script to create certificate to qiniu.com # # This deployment required following variables # export QINIU_AK="QINIUACCESSKEY" diff --git a/deploy/routeros.sh b/deploy/routeros.sh index 21c9196f..70fe70a3 100644 --- a/deploy/routeros.sh +++ b/deploy/routeros.sh @@ -85,7 +85,7 @@ routeros_deploy() { scp "$_ckey" "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST:$_cdomain.key" _info "Trying to push cert '$_cfullchain' to router" scp "$_cfullchain" "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST:$_cdomain.cer" - DEPLOY_SCRIPT_CMD="/system script add name=\"LE Cert Deploy - $_cdomain\" owner=admin policy=ftp,read,write,password,sensitive + DEPLOY_SCRIPT_CMD="/system script add name=\"LE Cert Deploy - $_cdomain\" owner=admin policy=ftp,read,write,password,sensitive source=\"## generated by routeros deploy script in acme.sh \n/certificate remove [ find name=$_cdomain.cer_0 ] \n/certificate remove [ find name=$_cdomain.cer_1 ] diff --git a/deploy/vault_cli.sh b/deploy/vault_cli.sh index b93fdd51..5395d87e 100644 --- a/deploy/vault_cli.sh +++ b/deploy/vault_cli.sh @@ -2,10 +2,10 @@ # Here is a script to deploy cert to hashicorp vault # (https://www.vaultproject.io/) -# +# # it requires the vault binary to be available in PATH, and the following # environment variables: -# +# # VAULT_PREFIX - this contains the prefix path in vault # VAULT_ADDR - vault requires this to find your vault server # diff --git a/dnsapi/dns_da.sh b/dnsapi/dns_da.sh index 7755c7e1..4e9c4ef0 100755 --- a/dnsapi/dns_da.sh +++ b/dnsapi/dns_da.sh @@ -9,7 +9,7 @@ # # User must provide login data and URL to DirectAdmin incl. port. # You can create login key, by using the Login Keys function -# ( https://da.example.com:8443/CMD_LOGIN_KEYS ), which only has access to +# ( https://da.example.com:8443/CMD_LOGIN_KEYS ), which only has access to # - CMD_API_DNS_CONTROL # - CMD_API_SHOW_DOMAINS # diff --git a/dnsapi/dns_doapi.sh b/dnsapi/dns_doapi.sh index 135f0b03..a001d52c 100755 --- a/dnsapi/dns_doapi.sh +++ b/dnsapi/dns_doapi.sh @@ -1,11 +1,11 @@ #!/usr/bin/env sh # Official Let's Encrypt API for do.de / Domain-Offensive -# +# # This is different from the dns_do adapter, because dns_do is only usable for enterprise customers # This API is also available to private customers/individuals -# -# Provide the required LetsEncrypt token like this: +# +# Provide the required LetsEncrypt token like this: # DO_LETOKEN="FmD408PdqT1E269gUK57" DO_API="https://www.do.de/api/letsencrypt" diff --git a/dnsapi/dns_durabledns.sh b/dnsapi/dns_durabledns.sh index 9a05eb32..677ae24d 100644 --- a/dnsapi/dns_durabledns.sh +++ b/dnsapi/dns_durabledns.sh @@ -147,11 +147,11 @@ _dd_soap() { # build SOAP XML _xml=' - '"$body"' ' diff --git a/dnsapi/dns_euserv.sh b/dnsapi/dns_euserv.sh index 38101565..cfb4b814 100644 --- a/dnsapi/dns_euserv.sh +++ b/dnsapi/dns_euserv.sh @@ -127,7 +127,7 @@ dns_euserv_rm() { else # find XML block where txtvalue is in. The record_id is allways prior this line! _endLine=$(echo "$response" | grep -n '>dns_record_content<.*>'"$txtvalue"'<' | cut -d ':' -f 1) - # record_id is the last Tag with a number before the row _endLine, identified by + # record_id is the last Tag with a number before the row _endLine, identified by _record_id=$(echo "$response" | sed -n '1,'"$_endLine"'p' | grep '' | _tail_n 1 | sed 's/.*\([0-9]*\)<\/name>.*/\1/') _info "Deleting record" _euserv_delete_record "$_record_id" diff --git a/dnsapi/dns_freedns.sh b/dnsapi/dns_freedns.sh index e76e6495..29b18921 100755 --- a/dnsapi/dns_freedns.sh +++ b/dnsapi/dns_freedns.sh @@ -359,7 +359,7 @@ _freedns_data_id() { # before each table row # search for the record type withing each row (e.g. TXT) # search for the domain within each row (which is within a - # anchor. And finally extract the domain ID. + # anchor. And finally extract the domain ID. if [ -n "$data_id" ]; then printf "%s" "$data_id" return 0 diff --git a/dnsapi/dns_me.sh b/dnsapi/dns_me.sh index 382eeedd..98a58411 100644 --- a/dnsapi/dns_me.sh +++ b/dnsapi/dns_me.sh @@ -2,7 +2,7 @@ # bug reports to dev@1e.ca -# ME_Key=qmlkdjflmkqdjf +# ME_Key=qmlkdjflmkqdjf # ME_Secret=qmsdlkqmlksdvnnpae ME_Api=https://api.dnsmadeeasy.com/V2.0/dns/managed diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index a82e12d7..2e389265 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -3,10 +3,10 @@ # Namecheap API # https://www.namecheap.com/support/api/intro.aspx # -# Requires Namecheap API key set in -#NAMECHEAP_API_KEY, +# Requires Namecheap API key set in +#NAMECHEAP_API_KEY, #NAMECHEAP_USERNAME, -#NAMECHEAP_SOURCEIP +#NAMECHEAP_SOURCEIP # Due to Namecheap's API limitation all the records of your domain will be read and re applied, make sure to have a backup of your records you could apply if any issue would arise. ######## Public functions ##################### diff --git a/dnsapi/dns_nsupdate.sh b/dnsapi/dns_nsupdate.sh index dfb3672a..cd4b7140 100755 --- a/dnsapi/dns_nsupdate.sh +++ b/dnsapi/dns_nsupdate.sh @@ -27,7 +27,7 @@ dns_nsupdate_add() { [ -n "$DEBUG" ] && [ "$DEBUG" -ge "$DEBUG_LEVEL_2" ] && nsdebug="-D" if [ -z "${NSUPDATE_ZONE}" ]; then nsupdate -k "${NSUPDATE_KEY}" $nsdebug < Date: Sat, 5 Oct 2019 21:13:23 +0800 Subject: [PATCH 034/357] Use shallow clone to speed up git clone on Travis CI Shallow clone is faster than a normal one, there is no need to clone the whole history of a repository when we only needs its latest or certain state of commit. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 04de1934..5f0ce0c4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,7 +28,7 @@ script: - if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck -V ; fi - if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck -e SC2181 **/*.sh && echo "shellcheck OK" ; fi - cd .. - - git clone https://github.com/Neilpang/acmetest.git && cp -r acme.sh acmetest/ && cd acmetest + - git clone --depth 1 https://github.com/Neilpang/acmetest.git && cp -r acme.sh acmetest/ && cd acmetest - if [ "$TRAVIS_OS_NAME" = "linux" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ./rundocker.sh testplat ubuntu:latest ; fi - if [ "$TRAVIS_OS_NAME" = "osx" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ACME_OPENSSL_BIN="$ACME_OPENSSL_BIN" ./letest.sh ; fi From bc396e7a90e05704eddf12d728809e72ce77d5dd Mon Sep 17 00:00:00 2001 From: Vadim Kalinnikov Date: Sun, 6 Oct 2019 14:38:26 +0300 Subject: [PATCH 035/357] Small fix in dns_vultr.sh --- dnsapi/dns_vultr.sh | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/dnsapi/dns_vultr.sh b/dnsapi/dns_vultr.sh index f15e7c49..0dce2ca1 100644 --- a/dnsapi/dns_vultr.sh +++ b/dnsapi/dns_vultr.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env sh +#!/bin/bash # #VULTR_API_KEY=000011112222333344445555666677778888 @@ -106,9 +106,9 @@ _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 + _domain=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug h "$_domain" + if [ -z "$_domain" ]; then return 1 fi @@ -119,11 +119,9 @@ _get_root() { if printf "%s\n" "$response" | grep '^\[.*\]' >/dev/null; then if _contains "$response" "\"domain\":\"$_domain\""; then _sub_domain="$(echo "$fulldomain" | sed "s/\\.$_domain\$//")" - _domain=$_domain return 0 else - _err 'Invalid domain' - return 1 + _debug "Go to next level of $_domain" fi else _err "$response" From e484f32b1abe2fea12a4b5fb9d13e7eb23996f9a Mon Sep 17 00:00:00 2001 From: Vadim Kalinnikov Date: Sun, 6 Oct 2019 14:40:57 +0300 Subject: [PATCH 036/357] - Return shell detect via env --- dnsapi/dns_vultr.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_vultr.sh b/dnsapi/dns_vultr.sh index 0dce2ca1..c7b52e84 100644 --- a/dnsapi/dns_vultr.sh +++ b/dnsapi/dns_vultr.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env sh # #VULTR_API_KEY=000011112222333344445555666677778888 From 65c950e1a41562b9eca0b23b04a260b18c3335d4 Mon Sep 17 00:00:00 2001 From: MooSE <32853697+moose-kazan@users.noreply.github.com> Date: Sun, 6 Oct 2019 15:02:48 +0300 Subject: [PATCH 037/357] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d5012d68..faaf9aa9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # An ACME Shell script: acme.sh [![Build Status](https://travis-ci.org/Neilpang/acme.sh.svg?branch=master)](https://travis-ci.org/Neilpang/acme.sh) - [![Join the chat at https://gitter.im/acme-sh/Lobby](https://badges.gitter.im/acme-sh/Lobby.svg)](https://gitter.im/acme-sh/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + [![Join the chat at https://gitter.im/acme-sh/Lobby](https://badges.gitter.im/acme-sh/Lobby.svg)](https://gitter.im/acme-sh/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - An ACME protocol client written purely in Shell (Unix shell) language. - Full ACME protocol implementation. - Support ACME v1 and ACME v2 From f500c7abcba29d19b2d49d8e3b25d9c6d5e2f726 Mon Sep 17 00:00:00 2001 From: Bill Gertz Date: Tue, 8 Oct 2019 15:47:39 +0200 Subject: [PATCH 038/357] dnsapi/dns_miab.sh MIAB DNS-01 Validation Know I'm new to contorting to this project. I i've broke conventions please let me know what I've screwed up and I'll set it right as quickly as possible. Propose this as a new DNS-01 validation script to dynamically add challenge DNS records to MailinaBox (MIAB) DNS. MIAB uses a custom DNS API to manage external DNS records. The script was originally written by Darven Dissek and can be found in his repository: https://framagit.org/DarvenDissek/acme.sh-MIAB-DNS-API/). This has been forked and some slight cleanup applied and change shebang to UNIx shell. The forked repository can be found here: https://github.com/billgertz/MIAB_dns_api. Wrote to Darven but received no reply. Support for this script has been submitted to the OPNsense project via this pull request: https://github.com/opnsense/plugins/pull/1531 --- dnsapi/dns_miab.sh | 273 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 dnsapi/dns_miab.sh diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh new file mode 100644 index 00000000..b0a52d7e --- /dev/null +++ b/dnsapi/dns_miab.sh @@ -0,0 +1,273 @@ +#!/usr/bin/env sh + +#Name: dns_miab.sh +# +#Authors: +# Darven Dissek 2018 +# William Gertz 2019 +# +# Thanks to Neil Pang for the code reused from acme.sh from HTTP-01 validation +# used to communicate with the MailintheBox Custom DNS API +#Report Bugs here: +# https://github.com/billgertz/MIAB_dns_api (for dns_miab.sh) +# https://github.com/Neilpang/acme.sh (for acme.sh) +# +######## Public functions ##################### + +#Usage: dns_miab_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_miab_add() { + fulldomain=$1 + txtvalue=$2 + _info "Using miab" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + MIAB_Username="${MIAB_Username:-$(_readaccountconf_mutable MIAB_Username)}" + MIAB_Password="${MIAB_Password:-$(_readaccountconf_mutable MIAB_Password)}" + MIAB_Server="${MIAB_Server:-$(_readaccountconf_mutable MIAB_Server)}" + + #debug log the environmental variables + _debug MIAB_Username "$MIAB_Username" + _debug MIAB_Password "$MIAB_Password" + _debug MIAB_Server "$MIAB_Server" + + if [ -z "$MIAB_Username" ] || [ -z "$MIAB_Password" ] || [ -z "$MIAB_Server" ]; then + MIAB_Username="" + MIAB_Password="" + MIAB_Server="" + _err "You didn't specify MIAB_Username or MIAB_Password or MIAB_Server." + _err "Please try again." + return 1 + fi + + #save the credentials to the account conf file. + _saveaccountconf_mutable MIAB_Username "$MIAB_Username" + _saveaccountconf_mutable MIAB_Password "$MIAB_Password" + _saveaccountconf_mutable MIAB_Server "$MIAB_Server" + + baseurl="https://$MIAB_Server/admin/dns/custom/$fulldomain/txt" + + #Add the challenge record + result="$(_miab_post "$txtvalue" "$baseurl" "" "POST" "" "$MIAB_Username" "$MIAB_Password")" + + _debug result "$result" + + #check if result was good + if _contains "$result" "updated DNS"; then + _info "Successfully created the txt record" + return 0 + else + _err "Error encountered during record addition" + _err "$result" + return 1 + fi + +} + +#Usage: fulldomain txtvalue +#Remove the txt record after validation. +dns_miab_rm() { + fulldomain=$1 + txtvalue=$2 + _info "Using miab" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + MIAB_Username="${MIAB_Username:-$(_readaccountconf_mutable MIAB_Username)}" + MIAB_Password="${MIAB_Password:-$(_readaccountconf_mutable MIAB_Password)}" + MIAB_Server="${MIAB_Server:-$(_readaccountconf_mutable MIAB_Server)}" + + #debug log the environmental variables + _debug MIAB_Username "$MIAB_Username" + _debug MIAB_Password "$MIAB_Password" + _debug MIAB_Server "$MIAB_Server" + + if [ -z "$MIAB_Username" ] || [ -z "$MIAB_Password" ] || [ -z "$MIAB_Server" ]; then + MIAB_Username="" + MIAB_Password="" + MIAB_Server="" + _err "You didn't specify MIAB_Username or MIAB_Password or MIAB_Server." + _err "Please try again." + return 1 + fi + + #save the credentials to the account conf file. + _saveaccountconf_mutable MIAB_Username "$MIAB_Username" + _saveaccountconf_mutable MIAB_Password "$MIAB_Password" + _saveaccountconf_mutable MIAB_Server "$MIAB_Server" + + baseurl="https://$MIAB_Server/admin/dns/custom/$fulldomain/txt" + + #Remove the challenge record + result="$(_miab_post "$txtvalue" "$baseurl" "" "DELETE" "" "$MIAB_Username" "$MIAB_Password")" + + _debug result $result + + #check if result was good + if _contains "$result" "updated DNS"; then + _info "Successfully created the txt record" + return 0 + else + _err "Error encountered during record addition" + _err "$result" + return 1 + fi +} + +#################### 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=2 + 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 _contains "$response" "\"name\":\"$h\"" >/dev/null; then + _domain_id=$(printf "%s\n" "$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 + return 0 + fi + + return 1 + fi + + p=$i + i=$(_math "$i" + 1) + done + + return 1 +} + +# post changes to MIAB dns (taken from acme.sh) +_miab_post() { + body="$1" + _post_url="$2" + needbase64="$3" + httpmethod="$4" + _postContentType="$5" + username="$6" + password="$7" + + if [ -z "$httpmethod" ]; then + httpmethod="POST" + fi + + _debug $httpmethod + _debug "_post_url" "$_post_url" + _debug2 "body" "$body" + _debug2 "_postContentType" "$_postContentType" + + _inithttp + + if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then + _CURL="$_ACME_CURL" + + if [ "$HTTPS_INSECURE" ]; then + _CURL="$_CURL --insecure " + fi + + _debug "_CURL" "$_CURL" + + if [ "$needbase64" ]; then + if [ "$_postContentType" ]; then + response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod --user "$username:$password" -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)" + else + response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod --user "$username:$password" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)" + fi + else + if [ "$_postContentType" ]; then + response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod --user "$username:$password" -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")" + else + response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod --user "$username:$password" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")" + fi + fi + + _ret="$?" + + if [ "$_ret" != "0" ]; then + _err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $_ret" + if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then + _err "Here is the curl dump log:" + _err "$(cat "$_CURL_DUMP")" + fi + fi + + elif [ "$_ACME_WGET" ]; then + _WGET="$_ACME_WGET" + + if [ "$HTTPS_INSECURE" ]; then + _WGET="$_WGET --no-check-certificate " + fi + + _debug "_WGET" "$_WGET" + + if [ "$needbase64" ]; then + + if [ "$httpmethod" = "POST" ]; then + if [ "$_postContentType" ]; then + response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)" + else + response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)" + fi + else + if [ "$_postContentType" ]; then + response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)" + else + response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)" + fi + fi + + else + + if [ "$httpmethod" = "POST" ]; then + if [ "$_postContentType" ]; then + response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER")" + else + response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER")" + fi + else + if [ "$_postContentType" ]; then + response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER")" + else + response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER")" + fi + fi + + fi + + _ret="$?" + + if [ "$_ret" = "8" ]; then + _ret=0 + _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" + fi + + _sed_i "s/^ *//g" "$HTTP_HEADER" + + else + _ret="$?" + _err "Neither curl nor wget was found, cannot do $httpmethod." + fi + + _debug "_ret" "$_ret" + printf "%s" "$response" + return $_ret +} From 47c33d0344208d0bb47f173d64672e69fc18ac37 Mon Sep 17 00:00:00 2001 From: Bill Gertz Date: Tue, 8 Oct 2019 16:29:23 +0200 Subject: [PATCH 039/357] Cleanup/ removed private function _get_root Function _get_root() copied from acme.sh and is not needed here. Other cleanup as recommended by acme.sh test bot. --- dnsapi/dns_miab.sh | 71 +++++++++++----------------------------------- 1 file changed, 17 insertions(+), 54 deletions(-) diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh index b0a52d7e..b68f6705 100644 --- a/dnsapi/dns_miab.sh +++ b/dnsapi/dns_miab.sh @@ -1,16 +1,16 @@ #!/usr/bin/env sh -#Name: dns_miab.sh +# Name: dns_miab.sh # -#Authors: -# Darven Dissek 2018 -# William Gertz 2019 +# Authors: +# Darven Dissek 2018 +# William Gertz 2019 # -# Thanks to Neil Pang for the code reused from acme.sh from HTTP-01 validation -# used to communicate with the MailintheBox Custom DNS API -#Report Bugs here: -# https://github.com/billgertz/MIAB_dns_api (for dns_miab.sh) -# https://github.com/Neilpang/acme.sh (for acme.sh) +# Thanks to Neil Pang for the code reused from acme.sh from HTTP-01 validation +# used to communicate with the MailintheBox Custom DNS API +# Report Bugs here: +# https://github.com/billgertz/MIAB_dns_api (for dns_miab.sh) +# https://github.com/Neilpang/acme.sh (for acme.sh) # ######## Public functions ##################### @@ -41,9 +41,9 @@ dns_miab_add() { fi #save the credentials to the account conf file. - _saveaccountconf_mutable MIAB_Username "$MIAB_Username" - _saveaccountconf_mutable MIAB_Password "$MIAB_Password" - _saveaccountconf_mutable MIAB_Server "$MIAB_Server" + _saveaccountconf_mutable MIAB_Username "$MIAB_Username" + _saveaccountconf_mutable MIAB_Password "$MIAB_Password" + _saveaccountconf_mutable MIAB_Server "$MIAB_Server" baseurl="https://$MIAB_Server/admin/dns/custom/$fulldomain/txt" @@ -61,7 +61,6 @@ dns_miab_add() { _err "$result" return 1 fi - } #Usage: fulldomain txtvalue @@ -92,16 +91,16 @@ dns_miab_rm() { fi #save the credentials to the account conf file. - _saveaccountconf_mutable MIAB_Username "$MIAB_Username" - _saveaccountconf_mutable MIAB_Password "$MIAB_Password" - _saveaccountconf_mutable MIAB_Server "$MIAB_Server" + _saveaccountconf_mutable MIAB_Username "$MIAB_Username" + _saveaccountconf_mutable MIAB_Password "$MIAB_Password" + _saveaccountconf_mutable MIAB_Server "$MIAB_Server" baseurl="https://$MIAB_Server/admin/dns/custom/$fulldomain/txt" #Remove the challenge record result="$(_miab_post "$txtvalue" "$baseurl" "" "DELETE" "" "$MIAB_Username" "$MIAB_Password")" - _debug result $result + _debug result "$result" #check if result was good if _contains "$result" "updated DNS"; then @@ -115,43 +114,7 @@ dns_miab_rm() { } #################### 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=2 - 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 _contains "$response" "\"name\":\"$h\"" >/dev/null; then - _domain_id=$(printf "%s\n" "$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 - return 0 - fi - - return 1 - fi - - p=$i - i=$(_math "$i" + 1) - done - - return 1 -} - +# # post changes to MIAB dns (taken from acme.sh) _miab_post() { body="$1" From a4ec9f8b44a0ae2a22c4af44d423b58e73fa6fdf Mon Sep 17 00:00:00 2001 From: Bill Gertz Date: Tue, 8 Oct 2019 16:34:56 +0200 Subject: [PATCH 040/357] Fixed weird spacing on line 180 Um, fixed. --- dnsapi/dns_miab.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh index b68f6705..c91bf3c8 100644 --- a/dnsapi/dns_miab.sh +++ b/dnsapi/dns_miab.sh @@ -180,7 +180,7 @@ _miab_post() { if [ "$needbase64" ]; then - if [ "$httpmethod" = "POST" ]; then + if [ "$httpmethod" = "POST" ]; then if [ "$_postContentType" ]; then response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)" else From 835f9aad91e9995e688b1be8e827f0a6443af746 Mon Sep 17 00:00:00 2001 From: Bill Gertz Date: Tue, 8 Oct 2019 16:47:32 +0200 Subject: [PATCH 041/357] Um that's a wee bit of nit pick. 'Errant' space removed on blank line on line 147. --- dnsapi/dns_miab.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh index c91bf3c8..8786634d 100644 --- a/dnsapi/dns_miab.sh +++ b/dnsapi/dns_miab.sh @@ -144,7 +144,7 @@ _miab_post() { fi _debug "_CURL" "$_CURL" - + if [ "$needbase64" ]; then if [ "$_postContentType" ]; then response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod --user "$username:$password" -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)" From c06ec7c6bae0cc40daede2121d006b764e73cb47 Mon Sep 17 00:00:00 2001 From: Bill Gertz Date: Tue, 8 Oct 2019 18:15:16 +0200 Subject: [PATCH 042/357] Removed parameters and unused code for _miab_post Ok, should have noticed earlier that the calls to the private function _miab_post() never used the _needbase64_ or the __postContentType parameters. Parameters and code to handle them has been factored out. --- dnsapi/dns_miab.sh | 70 +++++++++------------------------------------- 1 file changed, 13 insertions(+), 57 deletions(-) diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh index 8786634d..df2ca6e2 100644 --- a/dnsapi/dns_miab.sh +++ b/dnsapi/dns_miab.sh @@ -48,7 +48,7 @@ dns_miab_add() { baseurl="https://$MIAB_Server/admin/dns/custom/$fulldomain/txt" #Add the challenge record - result="$(_miab_post "$txtvalue" "$baseurl" "" "POST" "" "$MIAB_Username" "$MIAB_Password")" + result="$(_miab_post "$txtvalue" "$baseurl" "POST" "$MIAB_Username" "$MIAB_Password")" _debug result "$result" @@ -91,14 +91,14 @@ dns_miab_rm() { fi #save the credentials to the account conf file. - _saveaccountconf_mutable MIAB_Username "$MIAB_Username" - _saveaccountconf_mutable MIAB_Password "$MIAB_Password" - _saveaccountconf_mutable MIAB_Server "$MIAB_Server" + _saveaccountconf_mutable MIAB_Username "$MIAB_Username" + _saveaccountconf_mutable MIAB_Password "$MIAB_Password" + _saveaccountconf_mutable MIAB_Server "$MIAB_Server" baseurl="https://$MIAB_Server/admin/dns/custom/$fulldomain/txt" #Remove the challenge record - result="$(_miab_post "$txtvalue" "$baseurl" "" "DELETE" "" "$MIAB_Username" "$MIAB_Password")" + result="$(_miab_post "$txtvalue" "$baseurl" "DELETE" "$MIAB_Username" "$MIAB_Password")" _debug result "$result" @@ -119,11 +119,9 @@ dns_miab_rm() { _miab_post() { body="$1" _post_url="$2" - needbase64="$3" - httpmethod="$4" - _postContentType="$5" - username="$6" - password="$7" + httpmethod="$3" + username="$4" + password="$5" if [ -z "$httpmethod" ]; then httpmethod="POST" @@ -144,21 +142,7 @@ _miab_post() { fi _debug "_CURL" "$_CURL" - - if [ "$needbase64" ]; then - if [ "$_postContentType" ]; then - response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod --user "$username:$password" -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)" - else - response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod --user "$username:$password" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)" - fi - else - if [ "$_postContentType" ]; then - response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod --user "$username:$password" -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")" - else - response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod --user "$username:$password" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")" - fi - fi - + response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod --user "$username:$password" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")" _ret="$?" if [ "$_ret" != "0" ]; then @@ -178,40 +162,12 @@ _miab_post() { _debug "_WGET" "$_WGET" - if [ "$needbase64" ]; then - - if [ "$httpmethod" = "POST" ]; then - if [ "$_postContentType" ]; then - response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)" - else - response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)" - fi - else - if [ "$_postContentType" ]; then - response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)" - else - response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)" - fi - fi - + if [ "$httpmethod" = "POST" ]; then + response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER")" else - - if [ "$httpmethod" = "POST" ]; then - if [ "$_postContentType" ]; then - response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER")" - else - response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER")" - fi - else - if [ "$_postContentType" ]; then - response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER")" - else - response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER")" - fi - fi - + response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER")" fi - + _ret="$?" if [ "$_ret" = "8" ]; then From f323ced4ca0d46c4119a8c4ac3ce67125edce149 Mon Sep 17 00:00:00 2001 From: Bill Gertz Date: Tue, 8 Oct 2019 18:24:14 +0200 Subject: [PATCH 043/357] Style issues and orphan _postContentType debug fix Fixed spacing and removed unneeded debug for _postContenetType --- dnsapi/dns_miab.sh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh index df2ca6e2..e2f4d593 100644 --- a/dnsapi/dns_miab.sh +++ b/dnsapi/dns_miab.sh @@ -91,9 +91,9 @@ dns_miab_rm() { fi #save the credentials to the account conf file. - _saveaccountconf_mutable MIAB_Username "$MIAB_Username" - _saveaccountconf_mutable MIAB_Password "$MIAB_Password" - _saveaccountconf_mutable MIAB_Server "$MIAB_Server" + _saveaccountconf_mutable MIAB_Username "$MIAB_Username" + _saveaccountconf_mutable MIAB_Password "$MIAB_Password" + _saveaccountconf_mutable MIAB_Server "$MIAB_Server" baseurl="https://$MIAB_Server/admin/dns/custom/$fulldomain/txt" @@ -130,8 +130,7 @@ _miab_post() { _debug $httpmethod _debug "_post_url" "$_post_url" _debug2 "body" "$body" - _debug2 "_postContentType" "$_postContentType" - + _inithttp if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then @@ -167,7 +166,7 @@ _miab_post() { else response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER")" fi - + _ret="$?" if [ "$_ret" = "8" ]; then From f64b061a28bf06f7f1586048615cef090b9c09e9 Mon Sep 17 00:00:00 2001 From: Bill Gertz Date: Tue, 8 Oct 2019 18:46:35 +0200 Subject: [PATCH 044/357] Style issue Spaces on blank line on line 133. --- dnsapi/dns_miab.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh index e2f4d593..d17a1f75 100644 --- a/dnsapi/dns_miab.sh +++ b/dnsapi/dns_miab.sh @@ -130,7 +130,7 @@ _miab_post() { _debug $httpmethod _debug "_post_url" "$_post_url" _debug2 "body" "$body" - + _inithttp if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then From ba7db3edda2c3d4e8265d2c5302b973d6541afd8 Mon Sep 17 00:00:00 2001 From: David Robles Date: Wed, 9 Oct 2019 08:08:05 -0700 Subject: [PATCH 045/357] Use more widely supported options for the "tr" command line utility by removing the use of the character class representation option. Fixes #2536 --- dnsapi/dns_freedns.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_freedns.sh b/dnsapi/dns_freedns.sh index e76e6495..bb80dc44 100755 --- a/dnsapi/dns_freedns.sh +++ b/dnsapi/dns_freedns.sh @@ -303,7 +303,7 @@ _freedns_domain_id() { return 1 fi - domain_id="$(echo "$htmlpage" | tr -d "[:space:]" | sed 's//@/g' | tr '@' '\n' \ + domain_id="$(echo "$htmlpage" | tr -d "\r\n" | sed 's//@/g' | tr '@' '\n' \ | grep "$search_domain\|$search_domain(.*)" \ | _egrep_o "edit\.php\?edit_domain_id=[0-9a-zA-Z]+" \ | cut -d = -f 2)" @@ -349,7 +349,7 @@ _freedns_data_id() { return 1 fi - data_id="$(echo "$htmlpage" | tr -d "[:space:]" | sed 's//@/g' | tr '@' '\n' \ + data_id="$(echo "$htmlpage" | tr -d "\r\n" | sed 's//@/g' | tr '@' '\n' \ | grep "$record_type" \ | grep "$search_domain" \ | _egrep_o "edit\.php\?data_id=[0-9a-zA-Z]+" \ From 252a21e2ae715885e5c45044fe19538e6b009399 Mon Sep 17 00:00:00 2001 From: temoffey Date: Thu, 10 Oct 2019 00:36:34 +0300 Subject: [PATCH 046/357] fixed json parse regex for support api gcore_cdn --- deploy/gcore_cdn.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deploy/gcore_cdn.sh b/deploy/gcore_cdn.sh index bbda58ef..a2a35f7b 100644 --- a/deploy/gcore_cdn.sh +++ b/deploy/gcore_cdn.sh @@ -77,15 +77,15 @@ gcore_cdn_deploy() { _debug _regex "$_regex" _resource=$(echo "$_response" | sed 's/},{/},\n{/g' | _egrep_o "$_regex") _debug _resource "$_resource" - _regex=".*\"id\":\([0-9]*\),.*$" + _regex=".*\"id\":\([0-9]*\).*\"rules\".*$" _debug _regex "$_regex" _resourceId=$(echo "$_resource" | sed -n "s/$_regex/\1/p") _debug _resourceId "$_resourceId" - _regex=".*\"sslData\":\([0-9]*\)}.*$" + _regex=".*\"sslData\":\([0-9]*\).*$" _debug _regex "$_regex" _sslDataOld=$(echo "$_resource" | sed -n "s/$_regex/\1/p") _debug _sslDataOld "$_sslDataOld" - _regex=".*\"originGroup\":\([0-9]*\),.*$" + _regex=".*\"originGroup\":\([0-9]*\).*$" _debug _regex "$_regex" _originGroup=$(echo "$_resource" | sed -n "s/$_regex/\1/p") _debug _originGroup "$_originGroup" @@ -101,7 +101,7 @@ gcore_cdn_deploy() { _debug _request "$_request" _response=$(_post "$_request" "https://api.gcdn.co/sslData") _debug _response "$_response" - _regex=".*\"id\":\([0-9]*\),.*$" + _regex=".*\"id\":\([0-9]*\).*$" _debug _regex "$_regex" _sslDataAdd=$(echo "$_response" | sed -n "s/$_regex/\1/p") _debug _sslDataAdd "$_sslDataAdd" From aa6112482d90e17b19127b71d5f12d097e13c485 Mon Sep 17 00:00:00 2001 From: Bill Gertz Date: Sun, 13 Oct 2019 19:56:04 +0200 Subject: [PATCH 047/357] Rewrite to conform to Dev guide Created _get_root() that tests the requested host is a subdomain to the domains hosted on MailinaBox (MIAB) DNS Server. Created common _miab_rest() used with dns_miab_add(), dns_miab_rm() and _get_root(). Also created barbaric _is_json() to test the response given by the MIAB Custom DNS API at least looks like a JSON file. We should add a hint to use _normalizeJson with JSON responses so _startswith, _endswith won't perplexingly fail. --- dnsapi/dns_miab.sh | 257 ++++++++++++++++++++++++--------------------- 1 file changed, 139 insertions(+), 118 deletions(-) diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh index d17a1f75..313e4eb8 100644 --- a/dnsapi/dns_miab.sh +++ b/dnsapi/dns_miab.sh @@ -6,186 +6,207 @@ # Darven Dissek 2018 # William Gertz 2019 # -# Thanks to Neil Pang for the code reused from acme.sh from HTTP-01 validation -# used to communicate with the MailintheBox Custom DNS API +# Thanks to Neil Pang and other developers here for code reused from acme.sh from DNS-01 +# used to communicate with the MailinaBox Custom DNS API # Report Bugs here: # https://github.com/billgertz/MIAB_dns_api (for dns_miab.sh) # https://github.com/Neilpang/acme.sh (for acme.sh) # ######## Public functions ##################### -#Usage: dns_miab_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +#Usage: dns_miab_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_miab_add() { fulldomain=$1 txtvalue=$2 - _info "Using miab" + _info "Using miab challange add" _debug fulldomain "$fulldomain" _debug txtvalue "$txtvalue" - MIAB_Username="${MIAB_Username:-$(_readaccountconf_mutable MIAB_Username)}" - MIAB_Password="${MIAB_Password:-$(_readaccountconf_mutable MIAB_Password)}" - MIAB_Server="${MIAB_Server:-$(_readaccountconf_mutable MIAB_Server)}" - - #debug log the environmental variables - _debug MIAB_Username "$MIAB_Username" - _debug MIAB_Password "$MIAB_Password" - _debug MIAB_Server "$MIAB_Server" - - if [ -z "$MIAB_Username" ] || [ -z "$MIAB_Password" ] || [ -z "$MIAB_Server" ]; then - MIAB_Username="" - MIAB_Password="" - MIAB_Server="" - _err "You didn't specify MIAB_Username or MIAB_Password or MIAB_Server." - _err "Please try again." + #retrieve MIAB environemt vars + if ! _retrieve_miab_env; then + return 1 + fi + + #check domain and seperate into doamin and host + if ! _get_root "$fulldomain"; then + _err "Cannot find any part of ${fulldomain} is hosted on ${MIAB_Server}" return 1 fi - #save the credentials to the account conf file. - _saveaccountconf_mutable MIAB_Username "$MIAB_Username" - _saveaccountconf_mutable MIAB_Password "$MIAB_Password" - _saveaccountconf_mutable MIAB_Server "$MIAB_Server" - - baseurl="https://$MIAB_Server/admin/dns/custom/$fulldomain/txt" - - #Add the challenge record - result="$(_miab_post "$txtvalue" "$baseurl" "POST" "$MIAB_Username" "$MIAB_Password")" + _debug2 _sub_domain "$_sub_domain" + _debug2 _domain "$_domain" - _debug result "$result" + #add the challenge record + _api_path="custom/${fulldomain}/txt" + _miab_rest "$txtvalue" "$_api_path" "POST" #check if result was good - if _contains "$result" "updated DNS"; then + if _contains "$response" "updated DNS"; then _info "Successfully created the txt record" return 0 else - _err "Error encountered during record addition" - _err "$result" + _err "Error encountered during record add" + _err "$response" return 1 fi } -#Usage: fulldomain txtvalue -#Remove the txt record after validation. +#Usage: dns_miab_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_miab_rm() { fulldomain=$1 txtvalue=$2 - _info "Using miab" + + _info "Using miab challage delete" _debug fulldomain "$fulldomain" _debug txtvalue "$txtvalue" - MIAB_Username="${MIAB_Username:-$(_readaccountconf_mutable MIAB_Username)}" - MIAB_Password="${MIAB_Password:-$(_readaccountconf_mutable MIAB_Password)}" - MIAB_Server="${MIAB_Server:-$(_readaccountconf_mutable MIAB_Server)}" - - #debug log the environmental variables - _debug MIAB_Username "$MIAB_Username" - _debug MIAB_Password "$MIAB_Password" - _debug MIAB_Server "$MIAB_Server" + #retrieve MIAB environemt vars + if ! _retrieve_miab_env; then + return 1 + fi - if [ -z "$MIAB_Username" ] || [ -z "$MIAB_Password" ] || [ -z "$MIAB_Server" ]; then - MIAB_Username="" - MIAB_Password="" - MIAB_Server="" - _err "You didn't specify MIAB_Username or MIAB_Password or MIAB_Server." - _err "Please try again." + #check domain and seperate into doamin and host + if ! _get_root "$fulldomain"; then + _err "Cannot find any part of ${fulldomain} is hosted on ${MIAB_Server}" return 1 fi - #save the credentials to the account conf file. - _saveaccountconf_mutable MIAB_Username "$MIAB_Username" - _saveaccountconf_mutable MIAB_Password "$MIAB_Password" - _saveaccountconf_mutable MIAB_Server "$MIAB_Server" - - baseurl="https://$MIAB_Server/admin/dns/custom/$fulldomain/txt" + _debug2 _sub_domain "$_sub_domain" + _debug2 _domain "$_domain" #Remove the challenge record - result="$(_miab_post "$txtvalue" "$baseurl" "DELETE" "$MIAB_Username" "$MIAB_Password")" - - _debug result "$result" + _api_path="custom/${fulldomain}/txt" + _miab_rest "$txtvalue" "$_api_path" "DELETE" #check if result was good - if _contains "$result" "updated DNS"; then - _info "Successfully created the txt record" + if _contains "$response" "updated DNS"; then + _info "Successfully removed the txt record" return 0 else - _err "Error encountered during record addition" - _err "$result" + _err "Error encountered during record remove" + _err "$response" return 1 fi } #################### Private functions below ################################## # -# post changes to MIAB dns (taken from acme.sh) -_miab_post() { - body="$1" - _post_url="$2" - httpmethod="$3" - username="$4" - password="$5" - - if [ -z "$httpmethod" ]; then - httpmethod="POST" +#Usage: _get_root _acme-challenge.www.domain.com +#Returns: +# _sub_domain=_acme-challenge.www +# _domain=domain.com +_get_root() { + _passed_domain=$1 + _debug _passed_domain "$_passed_domain" + _i=2 + _p=1 + + #get the zones hosed on MIAB server, must be a json stream + _miab_rest "" "zones" "GET" + + _info "_startswith test:$(_startswith "test" "t")" + _info "_endstest test:$(_endswith "test" "t")" + + if ! _is_json "$response"; then + _err "ERROR fetching domain list" + _err "$response" + return 1 fi - _debug $httpmethod - _debug "_post_url" "$_post_url" - _debug2 "body" "$body" - - _inithttp - - if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then - _CURL="$_ACME_CURL" + #cycle through the passed domain seperating out a test domain discarding + # the subdomain by marching thorugh the dots + while true; do + _test_domain=$(printf "%s" "$_passed_domain" | cut -d . -f ${_i}-100) + _debug _test_domain "$_test_domain" - if [ "$HTTPS_INSECURE" ]; then - _CURL="$_CURL --insecure " + if [ -z "$_test_domain" ]; then + return 1 fi - _debug "_CURL" "$_CURL" - response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod --user "$username:$password" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")" - _ret="$?" - - if [ "$_ret" != "0" ]; then - _err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $_ret" - if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then - _err "Here is the curl dump log:" - _err "$(cat "$_CURL_DUMP")" - fi + #report found if the test domain is in the json response and + # report the subdomain + if _contains "$response" "\"$_test_domain\""; then + _sub_domain=$(printf "%s" "$_passed_domain" | cut -d . -f 1-${_p}) + _domain=${_test_domain} + return 0 fi - elif [ "$_ACME_WGET" ]; then - _WGET="$_ACME_WGET" + #cycle to the next dot in the passed domain + _p=${_i} + _i=$(_math "$_i" + 1) + done - if [ "$HTTPS_INSECURE" ]; then - _WGET="$_WGET --no-check-certificate " - fi + return 1 +} - _debug "_WGET" "$_WGET" +#Usage: _retrieve_miab_env +#Returns (from store or environment variables): +# MIAB_Username +# MIAB_Password +# MIAB_Server +#retrieve MIAB environment variables, report errors and quit if problems +_retrieve_miab_env() { + MIAB_Username="${MIAB_Username:-$(_readaccountconf_mutable MIAB_Username)}" + MIAB_Password="${MIAB_Password:-$(_readaccountconf_mutable MIAB_Password)}" + MIAB_Server="${MIAB_Server:-$(_readaccountconf_mutable MIAB_Server)}" - if [ "$httpmethod" = "POST" ]; then - response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER")" - else - response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER")" - fi + #debug log the environmental variables + _debug MIAB_Username "$MIAB_Username" + _debug MIAB_Password "$MIAB_Password" + _debug MIAB_Server "$MIAB_Server" - _ret="$?" + #check if MIAB environemt vars set and quit if not + if [ -z "$MIAB_Username" ] || [ -z "$MIAB_Password" ] || [ -z "$MIAB_Server" ]; then + _err "You didn't specify one or more of MIAB_Username, MIAB_Password or MIAB_Server." + _err "Please check these environment variables and try again." + return 1 + fi - if [ "$_ret" = "8" ]; then - _ret=0 - _debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later." - fi + #save the credentials to the account conf file. + _saveaccountconf_mutable MIAB_Username "$MIAB_Username" + _saveaccountconf_mutable MIAB_Password "$MIAB_Password" + _saveaccountconf_mutable MIAB_Server "$MIAB_Server" +} - if [ "$_ret" != "0" ]; then - _err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $_ret" - fi +#Useage: _miab_rest "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" "custom/_acme-challenge.www.domain.com/txt "POST" +#Returns: "updated DNS: domain.com" +#rest interface MIAB dns +_miab_rest() { + _data="$1" + _api_path="$2" + _httpmethod="$3" + + #encode username and password for url + _username="$(printf "%s" "$MIAB_Username" | _url_encode)" + _password="$(printf "%s" "$MIAB_Password" | _url_encode)" + _url="https://${_username}:${_password}@${MIAB_Server}/admin/dns/${_api_path}" + + _debug2 _data "$_data" + _debug _api_path "$_api_path" + _debug2 _url "$_url" + _debug _httpmethod "$_httpmethod" + + if [ "$_httpmethod" = "GET" ]; then + response="$(_get "$_url")" + else + response="$(_post "$_data" "$_url" "" "$_httpmethod")" + fi - _sed_i "s/^ *//g" "$HTTP_HEADER" + _retcode="$?" - else - _ret="$?" - _err "Neither curl nor wget was found, cannot do $httpmethod." + if [ "$_retcode" != "0" ]; then + _err "MAAB REST authentication failed on $_httpmethod" + return 1 fi - _debug "_ret" "$_ret" - printf "%s" "$response" - return $_ret + _debug response "$response" + return 0 +} + +#Usage: _is_json "\[\n "mydomain.com"\n]" +#Reurns "\[\n "mydomain.com"\n]" +#returns the string if it begins and ends with square braces +_is_json() { + _str="$(echo "$1" | _normalizeJson)" + echo "$_str" | grep '^\[.*\]$' >/dev/null 2>&1 } From 7ec52145e807fc15dfb6c1e501183f14b58f3d80 Mon Sep 17 00:00:00 2001 From: Bill Gertz Date: Sun, 13 Oct 2019 20:02:03 +0200 Subject: [PATCH 048/357] Space style changes. Local copy of shellcheck somehow missed these, odd. --- dnsapi/dns_miab.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh index 313e4eb8..7630a744 100644 --- a/dnsapi/dns_miab.sh +++ b/dnsapi/dns_miab.sh @@ -23,10 +23,10 @@ dns_miab_add() { _debug txtvalue "$txtvalue" #retrieve MIAB environemt vars - if ! _retrieve_miab_env; then - return 1 - fi - + if ! _retrieve_miab_env; then + return 1 + fi + #check domain and seperate into doamin and host if ! _get_root "$fulldomain"; then _err "Cannot find any part of ${fulldomain} is hosted on ${MIAB_Server}" @@ -61,9 +61,9 @@ dns_miab_rm() { _debug txtvalue "$txtvalue" #retrieve MIAB environemt vars - if ! _retrieve_miab_env; then - return 1 - fi + if ! _retrieve_miab_env; then + return 1 + fi #check domain and seperate into doamin and host if ! _get_root "$fulldomain"; then @@ -76,7 +76,7 @@ dns_miab_rm() { #Remove the challenge record _api_path="custom/${fulldomain}/txt" - _miab_rest "$txtvalue" "$_api_path" "DELETE" + _miab_rest "$txtvalue" "$_api_path" "DELETE" #check if result was good if _contains "$response" "updated DNS"; then From 9af85f5a7eedb7d3fd36a01834492e50e8c65138 Mon Sep 17 00:00:00 2001 From: Bill Gertz Date: Mon, 14 Oct 2019 00:01:25 +0200 Subject: [PATCH 049/357] Updated to use _H1 Authorization: Basic Updated to use suggested export _H1 env var to supply Authorization Basic credentials. This undocumented support for Basic Authorization, ContentType, etc. needs to be documented in DNSAPI Dev Guide. Removed two stray debugging lines. --- dnsapi/dns_miab.sh | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh index 7630a744..25a8ffc7 100644 --- a/dnsapi/dns_miab.sh +++ b/dnsapi/dns_miab.sh @@ -26,7 +26,7 @@ dns_miab_add() { if ! _retrieve_miab_env; then return 1 fi - + #check domain and seperate into doamin and host if ! _get_root "$fulldomain"; then _err "Cannot find any part of ${fulldomain} is hosted on ${MIAB_Server}" @@ -104,9 +104,6 @@ _get_root() { #get the zones hosed on MIAB server, must be a json stream _miab_rest "" "zones" "GET" - _info "_startswith test:$(_startswith "test" "t")" - _info "_endstest test:$(_endswith "test" "t")" - if ! _is_json "$response"; then _err "ERROR fetching domain list" _err "$response" @@ -176,14 +173,15 @@ _miab_rest() { _api_path="$2" _httpmethod="$3" - #encode username and password for url - _username="$(printf "%s" "$MIAB_Username" | _url_encode)" - _password="$(printf "%s" "$MIAB_Password" | _url_encode)" - _url="https://${_username}:${_password}@${MIAB_Server}/admin/dns/${_api_path}" + #encode username and password for basic authentication + _credentials="$(printf "%s" "$MIAB_Username:$MIAB_Password" | _base64)" + export _H1="Authorization: Basic $_credentials" + _url="https://${MIAB_Server}/admin/dns/${_api_path}" _debug2 _data "$_data" _debug _api_path "$_api_path" _debug2 _url "$_url" + _debug2 _credentails "$_credentials" _debug _httpmethod "$_httpmethod" if [ "$_httpmethod" = "GET" ]; then @@ -195,7 +193,7 @@ _miab_rest() { _retcode="$?" if [ "$_retcode" != "0" ]; then - _err "MAAB REST authentication failed on $_httpmethod" + _err "MIAB REST authentication failed on $_httpmethod" return 1 fi From 933d49b0b09cc886402c59e08de1651e8121d822 Mon Sep 17 00:00:00 2001 From: Bill Gertz Date: Mon, 14 Oct 2019 00:06:08 +0200 Subject: [PATCH 050/357] Style space change Extra space on empty line 27. --- dnsapi/dns_miab.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh index 25a8ffc7..23ff6cee 100644 --- a/dnsapi/dns_miab.sh +++ b/dnsapi/dns_miab.sh @@ -26,7 +26,7 @@ dns_miab_add() { if ! _retrieve_miab_env; then return 1 fi - + #check domain and seperate into doamin and host if ! _get_root "$fulldomain"; then _err "Cannot find any part of ${fulldomain} is hosted on ${MIAB_Server}" From dc5c220e8fc0d605a9c4434b421b9d33960b149c Mon Sep 17 00:00:00 2001 From: rserpent <53250916+rserpent@users.noreply.github.com> Date: Wed, 16 Oct 2019 15:12:21 +0500 Subject: [PATCH 051/357] dns_nic init --- dnsapi/dns_nic.sh | 185 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 dnsapi/dns_nic.sh diff --git a/dnsapi/dns_nic.sh b/dnsapi/dns_nic.sh new file mode 100644 index 00000000..277cc2d8 --- /dev/null +++ b/dnsapi/dns_nic.sh @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +#NIC_Token="sdfsdfsdfljlbjkljlkjsdfoiwjedfglgkdlfgkfgldfkg" +# +#NIC_Username="000000/NIC-D" + +#NIC_Password="xxxxxxx" + +NIC_Api="https://api.nic.ru" + +dns_nic_add() { + fulldomain="${1}" + txtvalue="${2}" + + NIC_Token="${NIC_Token:-$(_readaccountconf_mutable NIC_Token)}" + NIC_Username="${NIC_Username:-$(_readaccountconf_mutable NIC_Username)}" + NIC_Password="${NIC_Password:-$(_readaccountconf_mutable NIC_Password)}" + if [ -z "$NIC_Token" ] || [ -z "$NIC_Username" ] || [ -z "$NIC_Password" ]; then + NIC_Token="" + NIC_Username="" + NIC_Password="" + _err "You must export variables: NIC_Token, NIC_Username and NIC_Password" + return 1 + fi + + _saveaccountconf_mutable NIC_Customer "$NIC_Token" + _saveaccountconf_mutable NIC_Username "$NIC_Username" + _saveaccountconf_mutable NIC_Password "$NIC_Password" + + if ! _nic_get_authtoken "$NIC_Username" "$NIC_Password" "$NIC_Token"; then + _err "get NIC auth token failed" + 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" + _debug _service "$_service" + + _info "Adding record" + if ! _nic_rest PUT "services/$_service/zones/$_domain/records" "$_sub_domainTXT$txtvalue"; then + _err "Add TXT record error" + return 1 + fi + + if ! _nic_rest POST "services/$_service/zones/$_domain/commit" ""; then + return 1 + fi + _info "Added, OK" +} + +dns_nic_rm() { + fulldomain="${1}" + txtvalue="${2}" + + NIC_Token="${NIC_Token:-$(_readaccountconf_mutable NIC_Token)}" + NIC_Username="${NIC_Username:-$(_readaccountconf_mutable NIC_Username)}" + NIC_Password="${NIC_Password:-$(_readaccountconf_mutable NIC_Password)}" + if [ -z "$NIC_Token" ] || [ -z "$NIC_Username" ] || [ -z "$NIC_Password" ]; then + NIC_Token="" + NIC_Username="" + NIC_Password="" + _err "You must export variables: NIC_Token, NIC_Username and NIC_Password" + return 1 + fi + + if ! _nic_get_authtoken "$NIC_Username" "$NIC_Password" "$NIC_Token"; then + _err "get NIC auth token failed" + return 1 + fi + + if ! _get_root "$fulldomain"; then + _err "Invalid domain" + return 1 + fi + + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + _debug _service "$_service" + + if ! _nic_rest GET "services/$_service/zones/$_domain/records"; then + _err "Get records error" + return 1 + fi + + _domain_id=$(printf "%s" "$response" | grep "$_sub_domain" | grep "$txtvalue" | sed -r "s/.*"; then + error=$(printf "%s" "$response" | grep "error code" | sed -r "s/.*(.*)<\/error>/\1/g") + _err "Error: $error" + return 1 + fi + + if ! _contains "$response" "success"; then + return 1 + fi + _debug2 response "$response" + return 0 +} From e00f0b4cf1df691c4baf0293d49d380bf98b5e94 Mon Sep 17 00:00:00 2001 From: rserpent <53250916+rserpent@users.noreply.github.com> Date: Wed, 16 Oct 2019 15:31:50 +0500 Subject: [PATCH 052/357] Update dns_nic.sh --- dnsapi/dns_nic.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_nic.sh b/dnsapi/dns_nic.sh index 277cc2d8..b92d2ac9 100644 --- a/dnsapi/dns_nic.sh +++ b/dnsapi/dns_nic.sh @@ -113,7 +113,7 @@ _nic_get_authtoken() { export _H1="Authorization: Basic $token" export _H2="Content-Type: application/x-www-form-urlencoded" - res="$(_post "grant_type=password&username=$username&password=$password&scope=%28GET%7CPUT%7CPOST%7CDELETE%29%3A%2Fdns-master%2F.%2B" "$NIC_Api/oauth/token" "" "POST")" + res=$(_post "grant_type=password&username=$username&password=$password&scope=%28GET%7CPUT%7CPOST%7CDELETE%29%3A%2Fdns-master%2F.%2B" "$NIC_Api/oauth/token" "" "POST") if _contains "$res" "access_token"; then _auth_token=$(printf "%s" "$res" | cut -d , -f2 | tr -d "\"" | sed "s/access_token://") _info "Token received" From ffa5472b31b69cedae6e29bc10edf689176d54a0 Mon Sep 17 00:00:00 2001 From: rserpent <53250916+rserpent@users.noreply.github.com> Date: Wed, 16 Oct 2019 16:25:38 +0500 Subject: [PATCH 053/357] fix whitespaces --- dnsapi/dns_nic.sh | 48 +++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/dnsapi/dns_nic.sh b/dnsapi/dns_nic.sh index b92d2ac9..493b05bc 100644 --- a/dnsapi/dns_nic.sh +++ b/dnsapi/dns_nic.sh @@ -79,7 +79,7 @@ dns_nic_rm() { _err "Invalid domain" return 1 fi - + _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" _debug _service "$_service" @@ -129,28 +129,28 @@ _get_root() { p=1 if ! _nic_rest GET "zones"; then - return 1 + return 1 fi _all_domains=$(printf "%s" "$response" | grep "idn-name" | sed -r "s/.*idn-name=\"(.*)\" name=.*/\1/g") _debug2 _all_domains "$_all_domains" while true; do - h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) - _debug h "$h" - - if [ -z "$h" ]; then - return 1 - fi - - if _contains "$_all_domains" "^$h$"; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) - _domain=$h - _service=$(printf "%s" "$response" | grep "$_domain" | sed -r "s/.*service=\"(.*)\".*$/\1/") - return 0 - fi - p="$i" - i=$(_math "$i" + 1) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) + _debug h "$h" + + if [ -z "$h" ]; then + return 1 + fi + + if _contains "$_all_domains" "^$h$"; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain=$h + _service=$(printf "%s" "$response" | grep "$_domain" | sed -r "s/.*service=\"(.*)\".*$/\1/") + return 0 + fi + p="$i" + i=$(_math "$i" + 1) done return 1 } @@ -165,20 +165,20 @@ _nic_rest() { export _H2="Authorization: Bearer $_auth_token" if [ "$m" != "GET" ]; then - _debug data "$data" - response=$(_post "$data" "$NIC_Api/dns-master/$ep" "" "$m") + _debug data "$data" + response=$(_post "$data" "$NIC_Api/dns-master/$ep" "" "$m") else - response=$(_get "$NIC_Api/dns-master/$ep") + response=$(_get "$NIC_Api/dns-master/$ep") fi if _contains "$response" ""; then - error=$(printf "%s" "$response" | grep "error code" | sed -r "s/.*(.*)<\/error>/\1/g") - _err "Error: $error" - return 1 + error=$(printf "%s" "$response" | grep "error code" | sed -r "s/.*(.*)<\/error>/\1/g") + _err "Error: $error" + return 1 fi if ! _contains "$response" "success"; then - return 1 + return 1 fi _debug2 response "$response" return 0 From 573c8f3b13e002cc948adfee840005cc18982098 Mon Sep 17 00:00:00 2001 From: David Robles Date: Wed, 23 Oct 2019 07:20:01 -0700 Subject: [PATCH 054/357] Use more widely supported options for the "tr" command line utility by removing the use of the character class representation option. [:space:] => "\t\r\n\v\f" --- dnsapi/dns_freedns.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_freedns.sh b/dnsapi/dns_freedns.sh index 81b1de5b..6fac0c21 100755 --- a/dnsapi/dns_freedns.sh +++ b/dnsapi/dns_freedns.sh @@ -303,7 +303,7 @@ _freedns_domain_id() { return 1 fi - domain_id="$(echo "$htmlpage" | tr -d "\r\n" | sed 's//@/g' | tr '@' '\n' \ + domain_id="$(echo "$htmlpage" | tr -d "\t\r\n\v\f" | sed 's//@/g' | tr '@' '\n' \ | grep "$search_domain\|$search_domain(.*)" \ | sed -n 's/.*\(edit\.php?edit_domain_id=[0-9a-zA-Z]*\).*/\1/p' \ | cut -d = -f 2)" @@ -349,7 +349,7 @@ _freedns_data_id() { return 1 fi - data_id="$(echo "$htmlpage" | tr -d "\r\n" | sed 's//@/g' | tr '@' '\n' \ + data_id="$(echo "$htmlpage" | tr -d "\t\r\n\v\f" | sed 's//@/g' | tr '@' '\n' \ | grep "$record_type" \ | grep "$search_domain" \ | sed -n 's/.*\(edit\.php?data_id=[0-9a-zA-Z]*\).*/\1/p' \ From 18ad01533b3b5d0cf51f9e72464940e7a080d880 Mon Sep 17 00:00:00 2001 From: neil Date: Thu, 24 Oct 2019 09:19:18 +0800 Subject: [PATCH 055/357] add space. fix https://github.com/Neilpang/acme.sh/pull/2553 --- dnsapi/dns_freedns.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_freedns.sh b/dnsapi/dns_freedns.sh index 6fac0c21..32d240fc 100755 --- a/dnsapi/dns_freedns.sh +++ b/dnsapi/dns_freedns.sh @@ -303,7 +303,7 @@ _freedns_domain_id() { return 1 fi - domain_id="$(echo "$htmlpage" | tr -d "\t\r\n\v\f" | sed 's//@/g' | tr '@' '\n' \ + domain_id="$(echo "$htmlpage" | tr -d " \t\r\n\v\f" | sed 's//@/g' | tr '@' '\n' \ | grep "$search_domain\|$search_domain(.*)" \ | sed -n 's/.*\(edit\.php?edit_domain_id=[0-9a-zA-Z]*\).*/\1/p' \ | cut -d = -f 2)" From c0449a3ed22e102cd68f959460619dd9ceff18cc Mon Sep 17 00:00:00 2001 From: Jesai Langenbach Date: Fri, 25 Oct 2019 08:04:20 +0200 Subject: [PATCH 056/357] Only save Attributes if it is set --- dnsapi/dns_opnsense.sh | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_opnsense.sh b/dnsapi/dns_opnsense.sh index ff6f8a54..ea9677b7 100755 --- a/dnsapi/dns_opnsense.sh +++ b/dnsapi/dns_opnsense.sh @@ -220,22 +220,32 @@ _opns_check_auth() { if [ -z "$OPNs_Host" ]; then OPNs_Host="localhost" _err "You don't specify OPNsense address." + return 1 + else + _saveaccountconf_mutable OPNs_Host "$OPNs_Host" fi if [ -z "$OPNs_Port" ]; then OPNs_Port="443" - _err "You don't specify OPNsense Port." + else + _saveaccountconf_mutable OPNs_Port "$OPNs_Port" fi if [ -z "$OPNs_Api_Insecure" ]; then OPNs_Api_Insecure="0" + else + #save the api addr and key to the account conf file. + _saveaccountconf_mutable OPNs_Api_Insecure "$OPNs_Api_Insecure" fi + export HTTPS_INSECURE="${OPNs_Api_Insecure}" if [ -z "$OPNs_Key" ]; then OPNs_Key="" _err "You don't specify OPNsense api key id." _err "Please set you OPNs_Key and try again." return 1 + else + _saveaccountconf_mutable OPNs_Key "$OPNs_Key" fi if [ -z "$OPNs_Token" ]; then @@ -243,15 +253,10 @@ _opns_check_auth() { _err "You don't specify OPNsense token." _err "Please create you OPNs_Token and try again." return 1 + else + _saveaccountconf_mutable OPNs_Token "$OPNs_Token" fi - #save the api addr and key to the account conf file. - _saveaccountconf_mutable OPNs_Host "$OPNs_Host" - _saveaccountconf_mutable OPNs_Port "$OPNs_Port" - _saveaccountconf_mutable OPNs_Key "$OPNs_Key" - _saveaccountconf_mutable OPNs_Token "$OPNs_Token" - _saveaccountconf_mutable OPNs_Api_Insecure "$OPNs_Api_Insecure" - export HTTPS_INSECURE="${OPNs_Api_Insecure}" if ! _opns_rest "GET" "/general/get"; then _err "Can't Access OPNsense" From 430956d3043d0a958fa696fe51a1d88f5c77d48d Mon Sep 17 00:00:00 2001 From: Jesai Langenbach Date: Fri, 25 Oct 2019 08:13:35 +0200 Subject: [PATCH 057/357] Fix whitespaces --- dnsapi/dns_opnsense.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_opnsense.sh b/dnsapi/dns_opnsense.sh index ea9677b7..abd85abb 100755 --- a/dnsapi/dns_opnsense.sh +++ b/dnsapi/dns_opnsense.sh @@ -234,7 +234,7 @@ _opns_check_auth() { if [ -z "$OPNs_Api_Insecure" ]; then OPNs_Api_Insecure="0" else - #save the api addr and key to the account conf file. + #save the api addr and key to the account conf file. _saveaccountconf_mutable OPNs_Api_Insecure "$OPNs_Api_Insecure" fi export HTTPS_INSECURE="${OPNs_Api_Insecure}" From b85c1a88614b531698133565643e618482904f06 Mon Sep 17 00:00:00 2001 From: Jesai Langenbach Date: Fri, 25 Oct 2019 08:22:15 +0200 Subject: [PATCH 058/357] Fix additional line --- dnsapi/dns_opnsense.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_opnsense.sh b/dnsapi/dns_opnsense.sh index abd85abb..0f7cdea6 100755 --- a/dnsapi/dns_opnsense.sh +++ b/dnsapi/dns_opnsense.sh @@ -257,7 +257,6 @@ _opns_check_auth() { _saveaccountconf_mutable OPNs_Token "$OPNs_Token" fi - if ! _opns_rest "GET" "/general/get"; then _err "Can't Access OPNsense" return 1 From 1d1f61613c539eaa0eddf8b10e8a1dea47824b8a Mon Sep 17 00:00:00 2001 From: Rolph Haspers Date: Fri, 25 Oct 2019 09:25:29 +0200 Subject: [PATCH 059/357] Check for root domain via API --- dnsapi/dns_leaseweb.sh | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/dnsapi/dns_leaseweb.sh b/dnsapi/dns_leaseweb.sh index 976ad5ac..6a75ef33 100644 --- a/dnsapi/dns_leaseweb.sh +++ b/dnsapi/dns_leaseweb.sh @@ -88,14 +88,24 @@ _get_root() { i=$(_math "$i" - 1) while true; do - h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) + h=$(printf "%s" "$domain" | cut -d . -f $i-100) if [ -z "$h" ]; then - return 1 + return 1 #not valid domain + fi + + #Check API if domain exists + if _lsw_api "GET" "$h"; then + if [ "$_code" = "200"]; then + _domain="$h" + return 0 + fi + fi + i=$(_math "$i" - 1) + if (( $i < 1)); then + return 1 #not found fi - _domain="$h" - return 0 done - _debug "$domain not found" + return 1 } @@ -109,6 +119,14 @@ _lsw_api() { export _H2="Content-Type: application/json" export _H1="X-Lsw-Auth: ${LSW_Key}" + if [ "$cmd" = "GET" ]; then + response="$(_get "$LSW_API/$domain")" + _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" + _debug "http response code $_code" + _debug response "$response" + return 0 + fi + if [ "$cmd" = "POST" ]; then data="{\"name\": \"$fulldomain.\",\"type\": \"TXT\",\"content\": [\"$txtvalue\"],\"ttl\": 60}" response="$(_post "$data" "$LSW_API/$domain/resourceRecordSets" "$data" "POST")" From e10f447b5b6b56c8742136f1c288dce32c392f41 Mon Sep 17 00:00:00 2001 From: Rolph Haspers Date: Fri, 25 Oct 2019 11:42:15 +0200 Subject: [PATCH 060/357] Fixed some bugs, tested and working --- dnsapi/dns_leaseweb.sh | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/dnsapi/dns_leaseweb.sh b/dnsapi/dns_leaseweb.sh index 6a75ef33..cb49ce7b 100644 --- a/dnsapi/dns_leaseweb.sh +++ b/dnsapi/dns_leaseweb.sh @@ -83,19 +83,20 @@ dns_leaseweb_rm() { # returns # _domain=domain.com _get_root() { - domain=$1 - i="$(echo "$fulldomain" | tr '.' ' ' | wc -w)" + rdomain=$1 + i="$(echo "$rdomain" | tr '.' ' ' | wc -w)" i=$(_math "$i" - 1) while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) + h=$(printf "%s" "$rdomain" | cut -d . -f $i-100) + _debug h "$h" if [ -z "$h" ]; then return 1 #not valid domain fi #Check API if domain exists if _lsw_api "GET" "$h"; then - if [ "$_code" = "200"]; then + if [ "$_code" = "200" ]; then _domain="$h" return 0 fi @@ -111,16 +112,16 @@ _get_root() { _lsw_api() { cmd=$1 - domain=$2 - fulldomain=$3 - txtvalue=$4 + data=$2 + fd=$3 + tvalue=$4 # Construct the HTTP Authorization header export _H2="Content-Type: application/json" export _H1="X-Lsw-Auth: ${LSW_Key}" if [ "$cmd" = "GET" ]; then - response="$(_get "$LSW_API/$domain")" + response="$(_get "$LSW_API/$d")" _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" _debug "http response code $_code" _debug response "$response" @@ -128,8 +129,8 @@ _lsw_api() { fi if [ "$cmd" = "POST" ]; then - data="{\"name\": \"$fulldomain.\",\"type\": \"TXT\",\"content\": [\"$txtvalue\"],\"ttl\": 60}" - response="$(_post "$data" "$LSW_API/$domain/resourceRecordSets" "$data" "POST")" + data="{\"name\": \"$fd.\",\"type\": \"TXT\",\"content\": [\"$tvalue\"],\"ttl\": 60}" + response="$(_post "$data" "$LSW_API/$d/resourceRecordSets" "$data" "POST")" _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" _debug "http response code $_code" _debug response "$response" @@ -137,7 +138,7 @@ _lsw_api() { fi if [ "$cmd" = "DELETE" ]; then - response="$(_post "" "$LSW_API/$domain/resourceRecordSets/$fulldomain/TXT" "" "DELETE")" + response="$(_post "" "$LSW_API/$d/resourceRecordSets/$fd/TXT" "" "DELETE")" _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" _debug "http response code $_code" _debug response "$response" From 14f6f9ec94a5d0e68f495fe485610db82b6eefc0 Mon Sep 17 00:00:00 2001 From: Rolph Haspers Date: Fri, 25 Oct 2019 11:56:27 +0200 Subject: [PATCH 061/357] Fixed wrong assignement of var --- dnsapi/dns_leaseweb.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_leaseweb.sh b/dnsapi/dns_leaseweb.sh index cb49ce7b..31446bec 100644 --- a/dnsapi/dns_leaseweb.sh +++ b/dnsapi/dns_leaseweb.sh @@ -112,7 +112,7 @@ _get_root() { _lsw_api() { cmd=$1 - data=$2 + d=$2 fd=$3 tvalue=$4 From 6d62ae226a82c8c42129a1bae560495790e092d4 Mon Sep 17 00:00:00 2001 From: Rolph Haspers Date: Fri, 25 Oct 2019 12:14:53 +0200 Subject: [PATCH 062/357] Small fix --- dnsapi/dns_leaseweb.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_leaseweb.sh b/dnsapi/dns_leaseweb.sh index 31446bec..72f53b23 100644 --- a/dnsapi/dns_leaseweb.sh +++ b/dnsapi/dns_leaseweb.sh @@ -102,8 +102,8 @@ _get_root() { fi fi i=$(_math "$i" - 1) - if (( $i < 1)); then - return 1 #not found + if (( i < 2 )); then + return 1 #not found, no need to check _acme-challenge.sub.domain in leaseweb api. fi done From 58642286c95fa42d3e78754a9f0253fa70f529bb Mon Sep 17 00:00:00 2001 From: Rolph Haspers Date: Fri, 25 Oct 2019 13:22:19 +0200 Subject: [PATCH 063/357] Fix for SC2039/SC2086 --- dnsapi/dns_leaseweb.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_leaseweb.sh b/dnsapi/dns_leaseweb.sh index 72f53b23..0fd8dcc0 100644 --- a/dnsapi/dns_leaseweb.sh +++ b/dnsapi/dns_leaseweb.sh @@ -88,7 +88,7 @@ _get_root() { i=$(_math "$i" - 1) while true; do - h=$(printf "%s" "$rdomain" | cut -d . -f $i-100) + h=$(printf "%s" "$rdomain" | cut -d . -f "$i"-100) _debug h "$h" if [ -z "$h" ]; then return 1 #not valid domain @@ -102,7 +102,7 @@ _get_root() { fi fi i=$(_math "$i" - 1) - if (( i < 2 )); then + if $(( i < 2 )); then return 1 #not found, no need to check _acme-challenge.sub.domain in leaseweb api. fi done From e48daffad99af7cd09b0c5860b439de2895541ca Mon Sep 17 00:00:00 2001 From: Rolph Haspers Date: Fri, 25 Oct 2019 13:46:10 +0200 Subject: [PATCH 064/357] Fixed error --- dnsapi/dns_leaseweb.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_leaseweb.sh b/dnsapi/dns_leaseweb.sh index 0fd8dcc0..a1d9e749 100644 --- a/dnsapi/dns_leaseweb.sh +++ b/dnsapi/dns_leaseweb.sh @@ -102,7 +102,7 @@ _get_root() { fi fi i=$(_math "$i" - 1) - if $(( i < 2 )); then + if [ "$i" -lt 2 ]; then return 1 #not found, no need to check _acme-challenge.sub.domain in leaseweb api. fi done From d04c6dd3ac03ff6031cbb0d8a2d86645fe9adb20 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 25 Oct 2019 22:31:36 +0800 Subject: [PATCH 065/357] fix https://github.com/Neilpang/acme.sh/issues/2557 and https://github.com/Neilpang/acme.sh/issues/2544 --- acme.sh | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index e060e334..37ce15aa 100755 --- a/acme.sh +++ b/acme.sh @@ -4047,7 +4047,18 @@ $_authorizations_map" fi if [ "$ACME_VERSION" = "2" ]; then - response="$(echo "$_authorizations_map" | grep "^$(_idn "$d")," | sed "s/$d,//")" + _idn_d="$(_idn "$d")" + _candindates="$(echo "$_authorizations_map" | grep "^$_idn_d,")" + _debug2 _candindates "$_candindates" + if [ "$(echo "$_candindates" | wc -l)" -gt 1 ]; then + for _can in $_candindates; do + if _startswith "$(echo "$_can" | tr '.' '|')" "$(echo "$_idn_d" | tr '.' '|'),"; then + _candindates="$_can" + break + fi + done + fi + response="$(echo "$_candindates" | sed "s/$_idn_d,//")" _debug2 "response" "$response" if [ -z "$response" ]; then _err "get to authz error." From 2a2877231268cce11ccc624c007ecf3fc2c8dea6 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 25 Oct 2019 22:34:33 +0800 Subject: [PATCH 066/357] fix https://github.com/Neilpang/acme.sh/pull/2553#issuecomment-546173277 --- dnsapi/dns_freedns.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_freedns.sh b/dnsapi/dns_freedns.sh index 32d240fc..6a0b58ac 100755 --- a/dnsapi/dns_freedns.sh +++ b/dnsapi/dns_freedns.sh @@ -349,7 +349,7 @@ _freedns_data_id() { return 1 fi - data_id="$(echo "$htmlpage" | tr -d "\t\r\n\v\f" | sed 's//@/g' | tr '@' '\n' \ + data_id="$(echo "$htmlpage" | tr -d " \t\r\n\v\f" | sed 's//@/g' | tr '@' '\n' \ | grep "$record_type" \ | grep "$search_domain" \ | sed -n 's/.*\(edit\.php?data_id=[0-9a-zA-Z]*\).*/\1/p' \ From df3575217acc5c50d45145672a3008cdb5895cdc Mon Sep 17 00:00:00 2001 From: scottkof Date: Fri, 25 Oct 2019 12:05:15 -0700 Subject: [PATCH 067/357] Avoid API throttling errors in AWS DNS plugin --- dnsapi/dns_aws.sh | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_aws.sh b/dnsapi/dns_aws.sh index 246f4774..54b1bb3a 100755 --- a/dnsapi/dns_aws.sh +++ b/dnsapi/dns_aws.sh @@ -6,6 +6,8 @@ #AWS_SECRET_ACCESS_KEY="xxxxxxx" #This is the Amazon Route53 api wrapper for acme.sh +#All `sleep` commands are included to avoid Route53 throttling, see +#https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/DNSLimitations.html#limits-api-requests AWS_HOST="route53.amazonaws.com" AWS_URL="https://$AWS_HOST" @@ -43,6 +45,7 @@ dns_aws_add() { _debug "First detect the root zone" if ! _get_root "$fulldomain"; then _err "invalid domain" + sleep 1 return 1 fi _debug _domain_id "$_domain_id" @@ -51,6 +54,7 @@ dns_aws_add() { _info "Getting existing records for $fulldomain" if ! aws_rest GET "2013-04-01$_domain_id/rrset" "name=$fulldomain&type=TXT"; then + sleep 1 return 1 fi @@ -63,6 +67,7 @@ dns_aws_add() { if [ "$_resource_record" ] && _contains "$response" "$txtvalue"; then _info "The TXT record already exists. Skipping." + sleep 1 return 0 fi @@ -72,9 +77,10 @@ dns_aws_add() { if aws_rest POST "2013-04-01$_domain_id/rrset/" "" "$_aws_tmpl_xml" && _contains "$response" "ChangeResourceRecordSetsResponse"; then _info "TXT record updated successfully." + sleep 1 return 0 fi - + sleep 1 return 1 } @@ -93,6 +99,7 @@ dns_aws_rm() { _debug "First detect the root zone" if ! _get_root "$fulldomain"; then _err "invalid domain" + sleep 1 return 1 fi _debug _domain_id "$_domain_id" @@ -101,6 +108,7 @@ dns_aws_rm() { _info "Getting existing records for $fulldomain" if ! aws_rest GET "2013-04-01$_domain_id/rrset" "name=$fulldomain&type=TXT"; then + sleep 1 return 1 fi @@ -109,6 +117,7 @@ dns_aws_rm() { _debug "_resource_record" "$_resource_record" else _debug "no records exist, skip" + sleep 1 return 0 fi @@ -116,9 +125,10 @@ dns_aws_rm() { if aws_rest POST "2013-04-01$_domain_id/rrset/" "" "$_aws_tmpl_xml" && _contains "$response" "ChangeResourceRecordSetsResponse"; then _info "TXT record deleted successfully." + sleep 1 return 0 fi - + sleep 1 return 1 } From bba5376a3693dc19186edd6ffc42277d45dfa2fb Mon Sep 17 00:00:00 2001 From: "John L. Villalovos" Date: Tue, 15 Oct 2019 14:37:38 -0700 Subject: [PATCH 068/357] Improve debug capabilities when using bash When calling the _debug3() function will print the filename, function name, and line number when running under bash --- acme.sh | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index 041b5b44..46df2ed5 100755 --- a/acme.sh +++ b/acme.sh @@ -265,6 +265,37 @@ _usage() { printf "\n" >&2 } +__debug_bash_helper() { + # At this point only do for --debug 3 + if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -lt "$DEBUG_LEVEL_3" ]; then + echo "" + return + fi + # Return extra debug info when running with bash, otherwise return empty + # string. + if [ -z "${BASH_VERSION}" ]; then + echo "" + return + fi + # We are a bash shell at this point, return the filename, function name, and + # line number as a string + _dbh_saveIFS=$IFS + IFS=" " + # Must use eval or syntax error happens under dash + # Use 'caller 1' as we want one level up the stack as we should be called + # by one of the _debug* functions + eval "_dbh_called=($(caller 1))" + IFS=$_dbh_saveIFS + _dbh_file=${_dbh_called[2]} + if [ -n "${_script_home}" ]; then + # Trim off the _script_home directory name + _dbh_file=${_dbh_file#$_script_home/} + fi + _dbh_function=${_dbh_called[1]} + _dbh_lineno=${_dbh_called[0]} + printf "%-40s " "$_dbh_file:${_dbh_function}:${_dbh_lineno}" +} + _debug() { if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_1" ]; then _log "$@" @@ -273,7 +304,8 @@ _debug() { _syslog "$SYSLOG_DEBUG" "$@" fi if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_1" ]; then - _printargs "$@" >&2 + _bash_debug=$(__debug_bash_helper) + _printargs "${_bash_debug}$@" >&2 fi } @@ -306,7 +338,8 @@ _debug2() { _syslog "$SYSLOG_DEBUG" "$@" fi if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then - _printargs "$@" >&2 + _bash_debug=$(__debug_bash_helper) + _printargs "${_bash_debug}$@" >&2 fi } @@ -338,7 +371,8 @@ _debug3() { _syslog "$SYSLOG_DEBUG" "$@" fi if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_3" ]; then - _printargs "$@" >&2 + _bash_debug=$(__debug_bash_helper) + _printargs "${_bash_debug}$@" >&2 fi } From ed9e196bf68d9eb4494fbd33826eaa2e2a9366bf Mon Sep 17 00:00:00 2001 From: stilez Date: Sun, 27 Oct 2019 00:58:33 +0100 Subject: [PATCH 069/357] Update list of DNS providers for Plesk XML API --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c8bebc6f..32d30147 100644 --- a/README.md +++ b/README.md @@ -321,6 +321,7 @@ You don't have to do anything manually! 1. acme-dns (https://github.com/joohoi/acme-dns) 1. TELE3 (https://www.tele3.cz) 1. EUSERV.EU (https://www.euserv.eu) +1. Plesk XML API (https://www.plesk.com) And: From 1339b9422d0a7ad0f8c57b549ddb50eff7c18d05 Mon Sep 17 00:00:00 2001 From: stilez Date: Sun, 27 Oct 2019 01:04:08 +0100 Subject: [PATCH 070/357] Update for dns pleskxml --- dnsapi/README.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/dnsapi/README.md b/dnsapi/README.md index 1f394f92..568baba9 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -897,6 +897,26 @@ acme.sh --issue --dns dns_euserv -d example.com -d *.example.com --insecure The `EUSERV_Username` and `EUSERV_Password` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. Please report any issues to https://github.com/initit/acme.sh or to + +## 47. Use Plesk XML API to automatically issue cert + +The plesk plugin uses an XML API to add and remove dns records. +The Plesk API URI (URL), and the user name and password for logging in, must be configured. + +``` +export pleskxml_uri="https://YOUR_PLESK_URI_HERE:8443/enterprise/control/agent.php" + (or probably something similar) +export pleskxml_user="plesk username" +export pleskxml_pass="plesk password" +``` + +Ok, let's issue a cert now: +``` +acme.sh --issue --dns dns_pleskxml -d example.com -d www.example.com +``` + +The `pleskxml_user`, `pleskxml_pass` and `pleskxml_uri` will be saved in `~/.acme.sh/account.conf` and are reused when needed. + # Use custom API If your API is not supported yet, you can write your own DNS API. @@ -917,4 +937,4 @@ See: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide # Use lexicon DNS API -https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api \ No newline at end of file +https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api From 274393ac64fbccf994fd240498cb863348388da3 Mon Sep 17 00:00:00 2001 From: stilez Date: Sun, 27 Oct 2019 01:09:50 +0100 Subject: [PATCH 071/357] Create DNS 01 module for Plesk XML API --- dnsapi/dns_pleskxml | 402 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 402 insertions(+) create mode 100644 dnsapi/dns_pleskxml diff --git a/dnsapi/dns_pleskxml b/dnsapi/dns_pleskxml new file mode 100644 index 00000000..a8a74721 --- /dev/null +++ b/dnsapi/dns_pleskxml @@ -0,0 +1,402 @@ +#!/usr/bin/env sh + +## Name: dns_pleskxml.sh +## Created by Stilez. +## Also uses some code from PR#1832 by @romanlum (https://github.com/Neilpang/acme.sh/pull/1832/files) + +## This DNS01 method uses the Plesk XML API described at: +## https://docs.plesk.com/en-US/12.5/api-rpc/about-xml-api.28709 +## and more specifically: https://docs.plesk.com/en-US/12.5/api-rpc/reference.28784 + +## Note: a DNS ID with host = empty string is OK for this API, see +## https://docs.plesk.com/en-US/obsidian/api-rpc/about-xml-api/reference/managing-dns/managing-dns-records/adding-dns-record.34798 +## For example, to add a TXT record to DNS alias domain "acme-alias.com" would be a valid Plesk action. +## So this API module can handle such a request, if needed. + +## The plesk plugin uses the xml api to add and remvoe the dns records. Therefore the url, username +## and password have to be configured by the user before this module is called. +## +## ``` +## export pleskxml_uri="https://YOUR_PLESK_URI_HERE:8443/enterprise/control/agent.php" +## (or probably something similar) +## export pleskxml_user="plesk username" +## export pleskxml_pass="plesk password" +## ``` + +## Ok, let's issue a cert now: +## ``` +## acme.sh --issue --dns dns_pleskxml -d example.com -d www.example.com +## ``` +## +## The `pleskxml_uri`, `pleskxml_user` and `pleskxml_pass` will be saved in `~/.acme.sh/account.conf` and reused when needed. + + +#################### INTERNAL VARIABLES + NEWLINE ################################## + +pleskxml_init_checks_done=0 + +# Variable containing bare newline - not a style issue +# shellcheck disable=SC1004 +NEWLINE='\ +' + + +#################### API Templates ################################## + +pleskxml_tplt_get_domains="" + # Get a list of domains that PLESK can manage, so we can check root domain + host for acme.sh + # Also used to test credentials and URI. + # No args. +pleskxml_tplt_get_dns_records="%s" + # Get all DNS records for a Plesk domain ID. + # ARG = Plesk domain id to query +pleskxml_tplt_add_txt_record="%sTXT%s%s" + # Add a TXT record to a domain. + # ARGS = (1) Plesk internal domain ID, (2) "hostname" for the new record, eg '_acme_challenge', (3) TXT record value +pleskxml_tplt_rmv_dns_record="%s" + # Add a TXT record to a domain. + # ARG = the Plesk internal ID for the dns record to be deleted + + +#################### Public functions ################################## + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_pleskxml_add() { + fulldomain=$1 + txtvalue=$2 + + _info "Entering dns_pleskxml_add() to add TXT record '$2' to domain '$1'..." + + # Get credentials if not already checked, and confirm we can log in to Plesk XML API + if ! _credential_check; then + return 1 + fi + + # Get root and subdomain details, and Plesk domain ID + if ! _pleskxml_get_root_domain "$fulldomain"; then + return 1 + fi + + _debug 'Credentials OK, and domain identified. Calling Plesk XML API to add TXT record' + + + # printf using template in a variable - not a style issue + # shellcheck disable=SC2059 + request="$( printf "$pleskxml_tplt_add_txt_record" "$root_domain_id" "$sub_domain_name" "$txtvalue" )" + if ! _call_api "$request"; then + return 1 + fi + + # OK, we should have added a TXT record. Let's check and return success if so. + # All that should be left in the result, is one section, containing okNEW_DNS_RECORD_ID + + results="$( _api_response_split "$pleskxml_prettyprint_result" 'result' '' )" + + if ! _value "$results" | grep 'ok' | grep -qE '[0-9]+'; then + # Error - doesn't contain expected string. Something's wrong. + _err 'Error when calling Plesk XML API.' + _err 'The result did not contain the expected XXXXX section, or contained other values as well.' + _err 'This is unexpected: something has gone wrong.' + _err 'The full response was:\n' "$pleskxml_prettyprint_result" + return 1 + fi + + recid="$( _value "$results" | grep -E '[0-9]+' | sed -E 's/^.*([0-9]+)<\/id>.*$/\1/' )" + + _info "Success. TXT record appears to be correctly added (Plesk record ID=$recid). Exiting dns_pleskxml_add()." + + return 0 +} + +#Usage: rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_pleskxml_rm() { + fulldomain=$1 + txtvalue=$2 + + _info "Entering dns_pleskxml_rm() to remove TXT record '$2' from domain '$1'..." + + # Get credentials if not already checked, and confirm we can log in to Plesk XML API + if ! _credential_check; then + return 1 + fi + + # Get root and subdomain details, and Plesk domain ID + if ! _pleskxml_get_root_domain "$fulldomain"; then + return 1 + fi + + _debug 'Credentials OK, and domain identified. Calling Plesk XML API to get list of TXT records and their IDs' + + # printf using template in a variable - not a style issue + # shellcheck disable=SC2059 + request="$( printf "$pleskxml_tplt_get_dns_records" "$root_domain_id" )" + if ! _call_api "$request"; then + return 1 + fi + + # Reduce output to one line per DNS record, filtered for TXT records with a record ID only (which they should all have) + reclist="$( _api_response_split "$pleskxml_prettyprint_result" 'result' 'ok' | \ + grep "${root_domain_id}" | \ + grep -E '[0-9]+' | \ + grep 'TXT' \ + )" + + if [ -z "$reclist" ]; then + _err "No TXT records found for root domain ${root_domain_name} (Plesk domain ID ${root_domain_id}). Exiting." + return 1 + fi + + _debug "Got list of DNS TXT records for root domain '$root_domain_name'"':\n'"$reclist" + + recid="$( _value "$reclist" | \ + grep "$1." | \ + grep "$txtvalue" | \ + sed -E 's/(^.*|<\/id>.*$)//g' \ + )" + + _debug "List of DNS TXT records for host:"'\n'"$( _value "$reclist" | grep "$1." )" + + + if ! _value "$recid" | grep -Eq '^[0-9]+$'; then + _err "DNS records for root domain '${root_domain_name}' (Plesk ID ${root_domain_id}) + host '${sub_domain_name}' do not contain the TXT record '${txtvalue}'" + _err "Cannot delete TXT record. Exiting." + return 1 + fi + + _debug "Found Plesk record ID for target text string '${txtvalue}': ID=${recid}" + _debug 'Calling Plesk XML API to remove TXT record' + + # printf using template in a variable - not a style issue + # shellcheck disable=SC2059 + request="$( printf "$pleskxml_tplt_rmv_dns_record" "$recid" )" + if ! _call_api "$request"; then + return 1 + fi + + # OK, we should have removed a TXT record. Let's check and return success if so. + # All that should be left in the result, is one section, containing okPLESK_DELETED_DNS_RECORD_ID + + results="$( _api_response_split "$pleskxml_prettyprint_result" 'result' '' )" + + if ! _value "$results" | grep 'ok' | grep -qE '[0-9]+'; then + # Error - doesn't contain expected string. Something's wrong. + _err 'Error when calling Plesk XML API.' + _err 'The result did not contain the expected XXXXX section, or contained other values as well.' + _err 'This is unexpected: something has gone wrong.' + _err 'The full response was:\n' "$pleskxml_prettyprint_result" + return 1 + fi + + _info "Success. TXT record appears to be correctly removed. Exiting dns_pleskxml_rm()." + return 0 +} + + + +#################### Private functions below ################################## + +# Outputs value of a variable +_value() { + printf '%s' "$1" +} + + +# Outputs value of a variable (FQDN) and cuts it at 2 delimiters +# $1, $2 = where to cut +# $3 = FQDN +_valuecut() { + printf '%s' "$3" | cut -d . -f "${1}-${2}" +} + + +# Cleans up an API response, splits it "per item" and greps for a string to validate useful lines +# $1 - result string from API +# $2 - tag to resplit on (usually "result" or "domain") +# $3 - regex to recognise useful return lines +_api_response_split() { + printf '%s' "$1" | \ + sed -E 's/(^[[:space:]]+|[[:space:]]+$)//g' | \ + tr -d '\n\r' | \ + sed -E "s/<\/?$2>/${NEWLINE}/g" | \ + grep -E "$3" +} + + +# Calls Plesk XML API, and checks results for obvious issues +_call_api() { + request="$1" + errtext='' + + _debug 'Entered _call_api(). Calling Plesk XML API with request:\n' "'${request}'" + + export _H1="HTTP_AUTH_LOGIN: $pleskxml_user" + export _H2="HTTP_AUTH_PASSWD: $pleskxml_pass" + export _H3="content-Type: text/xml" + export _H4="HTTP_PRETTY_PRINT: true" + pleskxml_prettyprint_result="$(_post "${request}" "$pleskxml_uri" "" "POST")" + pleskxml_retcode="$?" + _debug "acme _post() returned retcode=$pleskxml_retcode. Literal response:" '\n' "'${pleskxml_prettyprint_result}'" + + # Error handling + + # Detect any that isn't "ok". None of the used calls should fail if the API is working correctly. + # Also detect if there simply aren't any status lines (null result?) and report that, as well. + + statuslines="$( echo "$pleskxml_prettyprint_result" | grep -E '^[[:space:]]*[^<]*[[:space:]]*$' )" + + if _value "$statuslines" | grep -qv 'ok'; then + + # We have some status lines that aren't "ok". Get the details + errtext="$( \ + _value "$pleskxml_prettyprint_result" | \ + grep -iE "(||)" | \ + sed -E 's/(^[[:space:]]+|<\/[a-z]+$)//g' | \ + sed -E 's/^<([a-z]+)>/\1: /' \ + )" + + elif ! _value "$statuslines" | grep -q 'ok'; then + + # We have no status lines at all. Results are empty + errtext='The Plesk XML API unexpectedly returned an empty set of results for this call.' + + fi + + if [ "$pleskxml_retcode" -ne 0 ] || [ "$errtext" != "" ]; then + _err "The Plesk XML API call failed." + _err "The return code for the POST request was $pleskxml_retcode (0=success)." + if [ "$errtext" != "" ]; then + _err 'Status and error messages received from the Plesk server:\n' "$errtext" + else + _err "No additional error messages were received back from the Plesk server" + fi + return 1 + fi + + _debug "Leaving _call_api(). Successful call." + + return 0 +} + + +_credential_check() { + # Startup checks (credentials, URI) + + _debug "Checking Plesk XML API login credentials and URI..." + + if [ "$pleskxml_init_checks_done" -eq 1 ]; then + _debug "Initial checks already done, no need to repeat. Skipped." + return 0 + fi + + + pleskxml_user="${pleskxml_user:-$(_readaccountconf_mutable pleskxml_user)}" + pleskxml_pass="${pleskxml_pass:-$(_readaccountconf_mutable pleskxml_pass)}" + pleskxml_uri="${pleskxml_uri:-$(_readaccountconf_mutable pleskxml_uri)}" + + _debug "Credentials - User: '${pleskxml_user}' Passwd: ****** URI: '${pleskxml_uri}'" + + if [ -z "$pleskxml_user" ] || [ -z "$pleskxml_pass" ] || [ -z "$pleskxml_uri" ]; then + pleskxml_user="" + pleskxml_pass="" + pleskxml_uri="" + _err "You didn't specify one or more of the Plesk XML API username, password, or URI." + _err "Please create these and try again." + _err "Instructions are in the module source code." + return 1 + fi + + # Test the API is usable, by trying to read the list of managed domains... + _call_api "$pleskxml_tplt_get_domains" + if [ "$pleskxml_retcode" -ne 0 ]; then + _err '\nFailed to access Plesk XML API.' + _err "Please check your login credentials and Plesk URI, and that the URI is reachable, and try again." + return 1 + fi + + _saveaccountconf_mutable pleskxml_uri "$pleskxml_uri" + _saveaccountconf_mutable pleskxml_user "$pleskxml_user" + _saveaccountconf_mutable pleskxml_pass "$pleskxml_pass" + + _debug "Test login to Plesk XML API successful. Login credentials and URI successfully saved to the acme.sh configuration file for future use." + + pleskxml_init_checks_done=1 + + return 0 +} + + +# For a FQDN, identify the root domain managed by Plesk, its domain ID in Plesk, and the host if any. +_pleskxml_get_root_domain() { + _debug "Identifying DNS root domain for '$1' that is managed by the Plesk account." + + # test if the domain is valid for splitting. + + if _value "$root_domain_name" | grep -qvE '^[^.]+\.[^.]+\.[^.]'; then + ### COMMENTED OUT ALSO FOR SAME REASON + ### _err "Invalid domain. The ACME domain must contain at least three parts (aa.bb.tld) to identify a host, domain, and tld for the TXT record." + _err "Invalid domain. The ACME domain must contain at least two parts (aa.bb) to identify a domain and tld for the TXT record." + return 1 + fi + + _debug "Querying Plesk server for list of managed domains..." + + _call_api "$pleskxml_tplt_get_domains" + if [ "$pleskxml_retcode" -ne 0 ]; then + return 1 + fi + + # Generate a hacked list of domains known to this Plesk account. + # We convert tags to so it'll flag on a hit with either or fields, + # for non-Western character sets. + # Output will be one line per known domain, containing 1 or 2 tages and an tag + # We don't actually need to check for type, name, *and* id, but it guarantees only usable lines are returned. + output="$( _api_response_split "$pleskxml_prettyprint_result" 'domain' 'domain' | sed -E 's/<(\/?)ascii-name>/<\1name>/g' | grep '' | grep '' )" + + _debug 'Domains managed by Plesk server are (ignore the hacked output):\n' "$output" + + # loop and test if domain, or any parent domain, is managed by Plesk + # Loop until we don't have any '.' in the sring we're testing as a root domain + + root_domain_name="$1" + doneloop=0 + + while _contains "$root_domain_name" '\.'; do + + _debug "Checking if '$root_domain_name' is managed by the Plesk server..." + + root_domain_id="$( _value "$output" | grep "$root_domain_name" | _head_n 1 | sed -E 's/^.*([0-9]+)<\/id>.*$/\1/' )" + + if [ -n "$root_domain_id" ]; then + # Found a match + # Note that a result with host = empty string is OK for this API, see + # https://docs.plesk.com/en-US/obsidian/api-rpc/about-xml-api/reference/managing-dns/managing-dns-records/adding-dns-record.34798 + # See notes at top of this file + sub_domain_name="$( _value "$1" | sed -E "s/\.?${root_domain_name}"'$//' )" + _info "Matched host '$1' to: DOMAIN '${root_domain_name}' (Plesk ID '${root_domain_id}'), HOST '${sub_domain_name}'. Returning." + return 0 + fi + + # No match, try next parent up (if any)... + + if _contains "$root_domain_name" '\.[^.]+\.'; then + _debug "No match, trying next parent up..." + else + _debug "No match,and next parent would be a TLD..." + fi + root_domain_name="$( _valuecut 2 1000 "$root_domain_name" )" + doneloop=1 + + done + + # if we get here, we failed to find a root domain match in the list of domains managed by Plesk. + # if we never ran the loop a first time, $1 wasn't at least a 2 level domain (domain.tld) and wasn't valid anyway + + if [ -z $doneloop ]; then + _err "'$1' isn't a valid domain for ACME DNS. Exiting." + else + _err "Cannot find '$1' or any parent domain of it, in Plesk." + _err "Are you sure that this domain is managed by this Plesk server?" + fi + + return 1 +} From a00300f88a7e9d85883616e55819f51052e64b7e Mon Sep 17 00:00:00 2001 From: stilez Date: Sun, 27 Oct 2019 01:23:14 +0100 Subject: [PATCH 072/357] revert changes to this file --- README.md | 536 ++++++++++++++---------------------------------------- 1 file changed, 134 insertions(+), 402 deletions(-) diff --git a/README.md b/README.md index 32d30147..613fff7f 100644 --- a/README.md +++ b/README.md @@ -1,503 +1,235 @@ -# An ACME Shell script: acme.sh [![Build Status](https://travis-ci.org/Neilpang/acme.sh.svg?branch=master)](https://travis-ci.org/Neilpang/acme.sh) - -[![Join the chat at https://gitter.im/acme-sh/Lobby](https://badges.gitter.im/acme-sh/Lobby.svg)](https://gitter.im/acme-sh/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -- 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 -- Simple, powerful and very easy to use. You only need 3 minutes to learn it. -- Bash, dash and sh compatible. -- Simplest shell script for Let's Encrypt free certificate client. -- Purely written in Shell with no dependencies on python or the official Let's Encrypt client. -- Just one script to issue, renew and install your certificates automatically. -- DOES NOT require `root/sudoer` access. -- Docker friendly -- IPv6 support - -It's probably the `easiest & smartest` shell script to automatically issue & renew the free certificates from Let's Encrypt. - -Wiki: https://github.com/Neilpang/acme.sh/wiki - -For Docker Fans: [acme.sh :two_hearts: Docker ](https://github.com/Neilpang/acme.sh/wiki/Run-acme.sh-in-docker) - -Twitter: [@neilpangxa](https://twitter.com/neilpangxa) - - -# [中文说明](https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E) - -# Who: -- [FreeBSD.org](https://blog.crashed.org/letsencrypt-in-freebsd-org/) -- [ruby-china.org](https://ruby-china.org/topics/31983) -- [Proxmox](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x_and_newer)) -- [pfsense](https://github.com/pfsense/FreeBSD-ports/pull/89) -- [webfaction](https://community.webfaction.com/questions/19988/using-letsencrypt) -- [Loadbalancer.org](https://www.loadbalancer.org/blog/loadbalancer-org-with-lets-encrypt-quick-and-dirty) -- [discourse.org](https://meta.discourse.org/t/setting-up-lets-encrypt/40709) -- [Centminmod](https://centminmod.com/letsencrypt-acmetool-https.html) -- [splynx](https://forum.splynx.com/t/free-ssl-cert-for-splynx-lets-encrypt/297) -- [archlinux](https://aur.archlinux.org/packages/acme.sh-git/) -- [opnsense.org](https://github.com/opnsense/plugins/tree/master/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient) -- [CentOS Web Panel](http://centos-webpanel.com/) -- [lnmp.org](https://lnmp.org/) -- [more...](https://github.com/Neilpang/acme.sh/wiki/Blogs-and-tutorials) - -# Tested OS - -| NO | Status| Platform| -|----|-------|---------| -|1|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/ubuntu-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)| Ubuntu -|2|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/debian-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)| Debian -|3|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/centos-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|CentOS -|4|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/windows-cygwin.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Windows (cygwin with curl, openssl and crontab included) -|5|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/freebsd.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|FreeBSD -|6|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/pfsense.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|pfsense -|7|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/opensuse-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|openSUSE -|8|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/alpine-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Alpine Linux (with curl) -|9|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/base-archlinux.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Archlinux -|10|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/fedora-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|fedora -|11|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/kalilinux-kali-linux-docker.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Kali Linux -|12|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/oraclelinux-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Oracle Linux -|13|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/proxmox.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)| Proxmox https://pve.proxmox.com/wiki/HTTPSCertificateConfiguration#Let.27s_Encrypt_using_acme.sh -|14|-----| Cloud Linux https://github.com/Neilpang/le/issues/111 -|15|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/openbsd.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|OpenBSD -|16|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/mageia.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Mageia -|17|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/Neilpang/acme.sh/wiki/How-to-run-on-OpenWRT) -|18|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/solaris.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|SunOS/Solaris -|19|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/gentoo-stage3-amd64.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Gentoo Linux -|20|[![Build Status](https://travis-ci.org/Neilpang/acme.sh.svg?branch=master)](https://travis-ci.org/Neilpang/acme.sh)|Mac OSX - -For all build statuses, check our [weekly build project](https://github.com/Neilpang/acmetest): - -https://github.com/Neilpang/acmetest - - -# Supported modes - -- Webroot mode -- Standalone mode -- Apache mode -- Nginx mode -- DNS mode -- [DNS alias mode](https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode) -- [Stateless mode](https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode) - - -# 1. How to install - -### 1. Install online - -Check this project: https://github.com/Neilpang/get.acme.sh - -```bash -curl https://get.acme.sh | sh -``` - -Or: - -```bash -wget -O - https://get.acme.sh | sh -``` - - -### 2. Or, Install from git - -Clone this project and launch installation: - -```bash -git clone https://github.com/Neilpang/acme.sh.git -cd ./acme.sh -./acme.sh --install -``` - -You `don't have to be root` then, although `it is recommended`. - -Advanced Installation: https://github.com/Neilpang/acme.sh/wiki/How-to-install - -The installer will perform 3 actions: - -1. Create and copy `acme.sh` to your home dir (`$HOME`): `~/.acme.sh/`. -All certs will be placed in this folder too. -2. Create alias for: `acme.sh=~/.acme.sh/acme.sh`. -3. Create daily cron job to check and renew the certs if needed. - -Cron entry example: - -```bash -0 0 * * * "/home/user/.acme.sh"/acme.sh --cron --home "/home/user/.acme.sh" > /dev/null -``` - -After the installation, you must close the current terminal and reopen it to make the alias take effect. - -Ok, you are ready to issue certs now. -Show help message: +Skip to content +Pull requests +Issues +Marketplace +Explore +@stilez +Learn Git and GitHub without any code! -```sh -root@v1:~# acme.sh -h -``` +Using the Hello World guide, you’ll start a branch, write comments, and open a pull request. -# 2. Just issue a cert +395 +14.7k -**Example 1:** Single domain. + 1.9k -```bash -acme.sh --issue -d example.com -w /home/wwwroot/example.com -``` +Neilpang/acme.sh +Code +Issues 415 +Pull requests 110 +Actions +Projects 0 +Wiki +Security +Insights +You’re editing a file in a project you don’t have write access to. Submitting a change to this file will write it to a new branch in your fork stilez/acme.sh, so you can send a pull request. +acme.sh/ -or: +1 -```bash -acme.sh --issue -d example.com -w /home/username/public_html -``` - -or: - -```bash -acme.sh --issue -d example.com -w /var/www/html -``` - -**Example 2:** Multiple domains in the same cert. - -```bash -acme.sh --issue -d example.com -d www.example.com -d cp.example.com -w /home/wwwroot/example.com -``` - -The parameter `/home/wwwroot/example.com` or `/home/username/public_html` or `/var/www/html` is the web root folder where you host your website files. You **MUST** have `write access` to this folder. - -Second argument **"example.com"** is the main domain you want to issue the cert for. -You must have at least one domain there. - -You must point and bind all the domains to the same webroot dir: `/home/wwwroot/example.com`. - -The certs will be placed in `~/.acme.sh/example.com/` - -The certs will be renewed automatically every **60** days. - -More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert - - -# 3. Install the cert to Apache/Nginx etc. - -After the cert is generated, you probably want to install/copy the cert to your Apache/Nginx or other servers. -You **MUST** use this command to copy the certs to the target files, **DO NOT** use the certs files in **~/.acme.sh/** folder, they are for internal use only, the folder structure may change in the future. - -**Apache** example: -```bash -acme.sh --install-cert -d example.com \ ---cert-file /path/to/certfile/in/apache/cert.pem \ ---key-file /path/to/keyfile/in/apache/key.pem \ ---fullchain-file /path/to/fullchain/certfile/apache/fullchain.pem \ ---reloadcmd "service apache2 force-reload" -``` - -**Nginx** example: -```bash -acme.sh --install-cert -d example.com \ ---key-file /path/to/keyfile/in/nginx/key.pem \ ---fullchain-file /path/to/fullchain/nginx/cert.pem \ ---reloadcmd "service nginx force-reload" -``` - -Only the domain is required, all the other parameters are optional. - -The ownership and permission info of existing files are preserved. You can pre-create the files to define the ownership and permission. - -Install/copy the cert/key to the production Apache or Nginx path. - -The cert will be renewed every **60** days by default (which is configurable). Once the cert is renewed, the Apache/Nginx service will be reloaded automatically by the command: `service apache2 force-reload` or `service nginx force-reload`. - - -**Please take care: The reloadcmd is very important. The cert can be automatically renewed, but, without a correct 'reloadcmd' the cert may not be flushed to your server(like nginx or apache), then your website will not be able to show renewed cert in 60 days.** - -# 4. Use Standalone server to issue cert - -**(requires you to be root/sudoer or have permission to listen on port 80 (TCP))** - -Port `80` (TCP) **MUST** be free to listen on, otherwise you will be prompted to free it and try again. - -```bash -acme.sh --issue --standalone -d example.com -d www.example.com -d cp.example.com -``` - -More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert - - -# 5. Use Apache mode - -**(requires you to be root/sudoer, since it is required to interact with Apache server)** - -If you are running a web server, Apache or Nginx, it is recommended to use the `Webroot mode`. - -Particularly, if you are running an Apache server, you can use Apache mode instead. This mode doesn't write any files to your web root folder. - -Just set string "apache" as the second argument and it will force use of apache plugin automatically. - -```sh -acme.sh --issue --apache -d example.com -d www.example.com -d cp.example.com -``` - -**This apache mode is only to issue the cert, it will not change your apache config files. -You will need to configure your website config files to use the cert by yourself. -We don't want to mess your apache server, don't worry.** +# An ACME Shell script: acme.sh [![Build Status](https://travis-ci.org/Neilpang/acme.sh.svg?branch=master)](https://travis-ci.org/Neilpang/acme.sh) -More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert +2 -# 6. Use Nginx mode +​ -**(requires you to be root/sudoer, since it is required to interact with Nginx server)** +3 -If you are running a web server, Apache or Nginx, it is recommended to use the `Webroot mode`. + [![Join the chat at https://gitter.im/acme-sh/Lobby](https://badges.gitter.im/acme-sh/Lobby.svg)](https://gitter.im/acme-sh/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -Particularly, if you are running an nginx server, you can use nginx mode instead. This mode doesn't write any files to your web root folder. +4 -Just set string "nginx" as the second argument. +- An ACME protocol client written purely in Shell (Unix shell) language. -It will configure nginx server automatically to verify the domain and then restore the nginx config to the original version. +5 -So, the config is not changed. +- Full ACME protocol implementation. -```sh -acme.sh --issue --nginx -d example.com -d www.example.com -d cp.example.com -``` +6 -**This nginx mode is only to issue the cert, it will not change your nginx config files. -You will need to configure your website config files to use the cert by yourself. -We don't want to mess your nginx server, don't worry.** +- Support ACME v1 and ACME v2 -More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert +7 -# 7. Automatic DNS API integration +- Support ACME v2 wildcard certs -If your DNS provider supports API access, we can use that API to automatically issue the certs. +8 -You don't have to do anything manually! +- Simple, powerful and very easy to use. You only need 3 minutes to learn it. -### Currently acme.sh supports: +9 -1. CloudFlare.com API -1. DNSPod.cn API -1. CloudXNS.com API -1. GoDaddy.com API -1. PowerDNS.com API -1. OVH, kimsufi, soyoustart and runabove API -1. nsupdate API -1. LuaDNS.com API -1. DNSMadeEasy.com API -1. AWS Route 53 -1. aliyun.com(阿里云) API -1. ISPConfig 3.1 API -1. Alwaysdata.com API -1. Linode.com API -1. FreeDNS (https://freedns.afraid.org/) -1. cyon.ch -1. Domain-Offensive/Resellerinterface/Domainrobot API -1. Gandi LiveDNS API -1. Knot DNS API -1. DigitalOcean API (native) -1. ClouDNS.net API -1. Infoblox NIOS API (https://www.infoblox.com/) -1. VSCALE (https://vscale.io/) -1. Dynu API (https://www.dynu.com) -1. DNSimple API -1. NS1.com API -1. DuckDNS.org API -1. Name.com API -1. Dyn Managed DNS API -1. Yandex PDD API (https://pdd.yandex.ru) -1. Hurricane Electric DNS service (https://dns.he.net) -1. UnoEuro API (https://www.unoeuro.com/) -1. INWX (https://www.inwx.de/) -1. Servercow (https://servercow.de) -1. Namesilo (https://www.namesilo.com) -1. InternetX autoDNS API (https://internetx.com) -1. Azure DNS -1. selectel.com(selectel.ru) DNS API -1. zonomi.com DNS API -1. DreamHost.com API -1. DirectAdmin API -1. KingHost (https://www.kinghost.com.br/) -1. Zilore (https://zilore.com) -1. Loopia.se API -1. acme-dns (https://github.com/joohoi/acme-dns) -1. TELE3 (https://www.tele3.cz) -1. EUSERV.EU (https://www.euserv.eu) -1. Plesk XML API (https://www.plesk.com) +- Bash, dash and sh compatible. -And: +10 -**lexicon DNS API: https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api - (DigitalOcean, DNSimple, DNSMadeEasy, DNSPark, EasyDNS, Namesilo, NS1, PointHQ, Rage4 and Vultr etc.)** +- Simplest shell script for Let's Encrypt free certificate client. +11 -**More APIs coming soon...** +- Purely written in Shell with no dependencies on python or the official Let's Encrypt client. -If your DNS provider is not on the supported list above, you can write your own DNS API script easily. If you do, please consider submitting a [Pull Request](https://github.com/Neilpang/acme.sh/pulls) and contribute it to the project. +12 -For more details: [How to use DNS API](dnsapi) +- Just one script to issue, renew and install your certificates automatically. -# 8. Use DNS manual mode: +13 -See: https://github.com/Neilpang/acme.sh/wiki/dns-manual-mode first. +- DOES NOT require `root/sudoer` access. -If your dns provider doesn't support any api access, you can add the txt record by your hand. +14 -```bash -acme.sh --issue --dns -d example.com -d www.example.com -d cp.example.com -``` +- Docker friendly -You should get an output like below: +15 -```sh -Add the following txt record: -Domain:_acme-challenge.example.com -Txt value:9ihDbjYfTExAYeDs4DBUeuTo18KBzwvTEjUnSwd32-c +- IPv6 support -Add the following txt record: -Domain:_acme-challenge.www.example.com -Txt value:9ihDbjxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +16 -Please add those txt records to the domains. Waiting for the dns to take effect. -``` +- Cron job notifications for renewal or error etc. -Then just rerun with `renew` argument: +17 -```bash -acme.sh --renew -d example.com -``` +​ -Ok, it's done. +18 -**Take care, this is dns manual mode, it can not be renewed automatically. you will have to add a new txt record to your domain by your hand when you renew your cert.** +It's probably the `easiest & smartest` shell script to automatically issue & renew the free certificates from Let's Encrypt. -**Please use dns api mode instead.** +19 -# 9. Issue ECC certificates +​ -`Let's Encrypt` can now issue **ECDSA** certificates. +20 -And we support them too! +Wiki: https://github.com/Neilpang/acme.sh/wiki -Just set the `keylength` parameter with a prefix `ec-`. +21 -For example: +​ -### Single domain ECC certificate +22 -```bash -acme.sh --issue -w /home/wwwroot/example.com -d example.com --keylength ec-256 -``` +For Docker Fans: [acme.sh :two_hearts: Docker ](https://github.com/Neilpang/acme.sh/wiki/Run-acme.sh-in-docker) -### SAN multi domain ECC certificate +23 -```bash -acme.sh --issue -w /home/wwwroot/example.com -d example.com -d www.example.com --keylength ec-256 -``` +​ -Please look at the `keylength` parameter above. +24 -Valid values are: +Twitter: [@neilpangxa](https://twitter.com/neilpangxa) -1. **ec-256 (prime256v1, "ECDSA P-256")** -2. **ec-384 (secp384r1, "ECDSA P-384")** -3. **ec-521 (secp521r1, "ECDSA P-521", which is not supported by Let's Encrypt yet.)** +25 +​ +26 -# 10. Issue Wildcard certificates +​ -It's simple, just give a wildcard domain as the `-d` parameter. +27 -```sh -acme.sh --issue -d example.com -d '*.example.com' --dns dns_cf -``` +# [中文说明](https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E) +28 +​ -# 11. How to renew the certs +29 -No, you don't need to renew the certs manually. All the certs will be renewed automatically every **60** days. +# Who: -However, you can also force to renew a cert: +30 -```sh -acme.sh --renew -d example.com --force -``` +- [FreeBSD.org](https://blog.crashed.org/letsencrypt-in-freebsd-org/) -or, for ECC cert: +31 -```sh -acme.sh --renew -d example.com --force --ecc -``` +- [ruby-china.org](https://ruby-china.org/topics/31983) +32 -# 12. How to stop cert renewal +- [Proxmox](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x_and_newer)) -To stop renewal of a cert, you can execute the following to remove the cert from the renewal list: +33 -```sh -acme.sh --remove -d example.com [--ecc] -``` +- [pfsense](https://github.com/pfsense/FreeBSD-ports/pull/89) -The cert/key file is not removed from the disk. +34 -You can remove the respective directory (e.g. `~/.acme.sh/example.com`) by yourself. +- [webfaction](https://community.webfaction.com/questions/19988/using-letsencrypt) +35 -# 13. How to upgrade `acme.sh` +- [Loadbalancer.org](https://www.loadbalancer.org/blog/loadbalancer-org-with-lets-encrypt-quick-and-dirty) -acme.sh is in constant development, so it's strongly recommended to use the latest code. +36 -You can update acme.sh to the latest code: +- [discourse.org](https://meta.discourse.org/t/setting-up-lets-encrypt/40709) -```sh -acme.sh --upgrade -``` +37 -You can also enable auto upgrade: +- [Centminmod](https://centminmod.com/letsencrypt-acmetool-https.html) -```sh -acme.sh --upgrade --auto-upgrade -``` +38 -Then **acme.sh** will be kept up to date automatically. +- [splynx](https://forum.splynx.com/t/free-ssl-cert-for-splynx-lets-encrypt/297) -Disable auto upgrade: +39 -```sh -acme.sh --upgrade --auto-upgrade 0 -``` +- [archlinux](https://www.archlinux.org/packages/community/any/acme.sh) +40 -# 14. Issue a cert from an existing CSR +- [opnsense.org](https://github.com/opnsense/plugins/tree/master/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient) -https://github.com/Neilpang/acme.sh/wiki/Issue-a-cert-from-existing-CSR +41 +- [CentOS Web Panel](http://centos-webpanel.com/) -# 15. Under the Hood +42 -Speak ACME language using shell, directly to "Let's Encrypt". +- [lnmp.org](https://lnmp.org/) -TODO: +43 +- [more...](https://github.com/Neilpang/acme.sh/wiki/Blogs-and-tutorials) -# 16. Acknowledgments +44 -1. Acme-tiny: https://github.com/diafygi/acme-tiny -2. ACME protocol: https://github.com/ietf-wg-acme/acme +​ +45 -# 17. License & Others +# Tested OS -License is GPLv3 +46 -Please Star and Fork me. +​ -[Issues](https://github.com/Neilpang/acme.sh/issues) and [pull requests](https://github.com/Neilpang/acme.sh/pulls) are welcome. +47 +| NO | Status| Platform| -# 18. Donate -Your donation makes **acme.sh** better: +@stilez +Propose file change +Commit summary +Optional extended description + + © 2019 GitHub, Inc. + Terms + Privacy + Security + Status + Help + + Contact GitHub + Pricing + API + Training + Blog + About -1. PayPal/Alipay(支付宝)/Wechat(微信): [https://donate.acme.sh/](https://donate.acme.sh/) - -[Donate List](https://github.com/Neilpang/acme.sh/wiki/Donate-list) From 4c9d99040c822b35eefbcee46b88bdb766af32a5 Mon Sep 17 00:00:00 2001 From: stilez Date: Sun, 27 Oct 2019 01:31:17 +0100 Subject: [PATCH 073/357] Fix (revert) edited .md file --- README.md | 501 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 407 insertions(+), 94 deletions(-) diff --git a/README.md b/README.md index 6c692885..d5012d68 100644 --- a/README.md +++ b/README.md @@ -1,185 +1,498 @@ +# An ACME Shell script: acme.sh [![Build Status](https://travis-ci.org/Neilpang/acme.sh.svg?branch=master)](https://travis-ci.org/Neilpang/acme.sh) -Skip to content -Pull requests -Issues -Marketplace -Explore -@stilez -Learn Git and GitHub without any code! + [![Join the chat at https://gitter.im/acme-sh/Lobby](https://badges.gitter.im/acme-sh/Lobby.svg)](https://gitter.im/acme-sh/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +- 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 +- Simple, powerful and very easy to use. You only need 3 minutes to learn it. +- Bash, dash and sh compatible. +- Simplest shell script for Let's Encrypt free certificate client. +- Purely written in Shell with no dependencies on python or the official Let's Encrypt client. +- Just one script to issue, renew and install your certificates automatically. +- DOES NOT require `root/sudoer` access. +- Docker friendly +- IPv6 support +- Cron job notifications for renewal or error etc. -Using the Hello World guide, you’ll start a branch, write comments, and open a pull request. +It's probably the `easiest & smartest` shell script to automatically issue & renew the free certificates from Let's Encrypt. -395 -14.7k +Wiki: https://github.com/Neilpang/acme.sh/wiki - 1.9k +For Docker Fans: [acme.sh :two_hearts: Docker ](https://github.com/Neilpang/acme.sh/wiki/Run-acme.sh-in-docker) -Neilpang/acme.sh -Code -Issues 415 -Pull requests 110 -Actions -Projects 0 -Wiki -Security -Insights -You’re editing a file in a project you don’t have write access to. Submitting a change to this file will write it to a new branch in your fork stilez/acme.sh, so you can send a pull request. -acme.sh/ +Twitter: [@neilpangxa](https://twitter.com/neilpangxa) -1 +# [中文说明](https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E) -2 +# Who: +- [FreeBSD.org](https://blog.crashed.org/letsencrypt-in-freebsd-org/) +- [ruby-china.org](https://ruby-china.org/topics/31983) +- [Proxmox](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x_and_newer)) +- [pfsense](https://github.com/pfsense/FreeBSD-ports/pull/89) +- [webfaction](https://community.webfaction.com/questions/19988/using-letsencrypt) +- [Loadbalancer.org](https://www.loadbalancer.org/blog/loadbalancer-org-with-lets-encrypt-quick-and-dirty) +- [discourse.org](https://meta.discourse.org/t/setting-up-lets-encrypt/40709) +- [Centminmod](https://centminmod.com/letsencrypt-acmetool-https.html) +- [splynx](https://forum.splynx.com/t/free-ssl-cert-for-splynx-lets-encrypt/297) +- [archlinux](https://www.archlinux.org/packages/community/any/acme.sh) +- [opnsense.org](https://github.com/opnsense/plugins/tree/master/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient) +- [CentOS Web Panel](http://centos-webpanel.com/) +- [lnmp.org](https://lnmp.org/) +- [more...](https://github.com/Neilpang/acme.sh/wiki/Blogs-and-tutorials) +# Tested OS -3 +| NO | Status| Platform| +|----|-------|---------| +|1|[![](https://neilpang.github.io/acmetest/status/ubuntu-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)| Ubuntu +|2|[![](https://neilpang.github.io/acmetest/status/debian-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)| Debian +|3|[![](https://neilpang.github.io/acmetest/status/centos-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|CentOS +|4|[![](https://neilpang.github.io/acmetest/status/windows-cygwin.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Windows (cygwin with curl, openssl and crontab included) +|5|[![](https://neilpang.github.io/acmetest/status/freebsd.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|FreeBSD +|6|[![](https://neilpang.github.io/acmetest/status/pfsense.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|pfsense +|7|[![](https://neilpang.github.io/acmetest/status/opensuse-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|openSUSE +|8|[![](https://neilpang.github.io/acmetest/status/alpine-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Alpine Linux (with curl) +|9|[![](https://neilpang.github.io/acmetest/status/base-archlinux.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Archlinux +|10|[![](https://neilpang.github.io/acmetest/status/fedora-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|fedora +|11|[![](https://neilpang.github.io/acmetest/status/kalilinux-kali-linux-docker.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Kali Linux +|12|[![](https://neilpang.github.io/acmetest/status/oraclelinux-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Oracle Linux +|13|[![](https://neilpang.github.io/acmetest/status/proxmox.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)| Proxmox https://pve.proxmox.com/wiki/HTTPSCertificateConfiguration#Let.27s_Encrypt_using_acme.sh +|14|-----| Cloud Linux https://github.com/Neilpang/le/issues/111 +|15|[![](https://neilpang.github.io/acmetest/status/openbsd.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|OpenBSD +|16|[![](https://neilpang.github.io/acmetest/status/mageia.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Mageia +|17|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/Neilpang/acme.sh/wiki/How-to-run-on-OpenWRT) +|18|[![](https://neilpang.github.io/acmetest/status/solaris.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|SunOS/Solaris +|19|[![](https://neilpang.github.io/acmetest/status/gentoo-stage3-amd64.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Gentoo Linux +|20|[![Build Status](https://travis-ci.org/Neilpang/acme.sh.svg?branch=master)](https://travis-ci.org/Neilpang/acme.sh)|Mac OSX - [![Join the chat at https://gitter.im/acme-sh/Lobby](https://badges.gitter.im/acme-sh/Lobby.svg)](https://gitter.im/acme-sh/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +For all build statuses, check our [weekly build project](https://github.com/Neilpang/acmetest): -4 +https://github.com/Neilpang/acmetest -- An ACME protocol client written purely in Shell (Unix shell) language. +# Supported CA -5 +- Letsencrypt.org CA(default) +- [BuyPass.com CA](https://github.com/Neilpang/acme.sh/wiki/BuyPass.com-CA) +- [Pebble strict Mode](https://github.com/letsencrypt/pebble) -- Full ACME protocol implementation. +# Supported modes -6 +- Webroot mode +- Standalone mode +- Standalone tls-alpn mode +- Apache mode +- Nginx mode +- DNS mode +- [DNS alias mode](https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode) +- [Stateless mode](https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode) -7 +# 1. How to install +### 1. Install online -8 +Check this project: https://github.com/Neilpang/get.acme.sh -- Simple, powerful and very easy to use. You only need 3 minutes to learn it. +```bash +curl https://get.acme.sh | sh +``` -- DOES NOT require `root/sudoer` access. +Or: -14 +```bash +wget -O - https://get.acme.sh | sh +``` -- Docker friendly -15 +### 2. Or, Install from git -- IPv6 support +Clone this project and launch installation: -16 +```bash +git clone https://github.com/Neilpang/acme.sh.git +cd ./acme.sh +./acme.sh --install +``` -- Cron job notifications for renewal or error etc. +You `don't have to be root` then, although `it is recommended`. -17 +Advanced Installation: https://github.com/Neilpang/acme.sh/wiki/How-to-install -​ +The installer will perform 3 actions: -18 +1. Create and copy `acme.sh` to your home dir (`$HOME`): `~/.acme.sh/`. +All certs will be placed in this folder too. +2. Create alias for: `acme.sh=~/.acme.sh/acme.sh`. +3. Create daily cron job to check and renew the certs if needed. -It's probably the `easiest & smartest` shell script to automatically issue & renew the free certificates from Let's Encrypt. +Cron entry example: -19 +```bash +0 0 * * * "/home/user/.acme.sh"/acme.sh --cron --home "/home/user/.acme.sh" > /dev/null +``` +After the installation, you must close the current terminal and reopen it to make the alias take effect. -20 +Ok, you are ready to issue certs now. -Wiki: https://github.com/Neilpang/acme.sh/wiki +Show help message: -21 +```sh +root@v1:~# acme.sh -h +``` -​ +# 2. Just issue a cert -22 +**Example 1:** Single domain. -For Docker Fans: [acme.sh :two_hearts: Docker ](https://github.com/Neilpang/acme.sh/wiki/Run-acme.sh-in-docker) +```bash +acme.sh --issue -d example.com -w /home/wwwroot/example.com +``` -23 +or: -​ +```bash +acme.sh --issue -d example.com -w /home/username/public_html +``` -24 +or: -Twitter: [@neilpangxa](https://twitter.com/neilpangxa) +```bash +acme.sh --issue -d example.com -w /var/www/html +``` -25 +**Example 2:** Multiple domains in the same cert. -​ +```bash +acme.sh --issue -d example.com -d www.example.com -d cp.example.com -w /home/wwwroot/example.com +``` -26 +The parameter `/home/wwwroot/example.com` or `/home/username/public_html` or `/var/www/html` is the web root folder where you host your website files. You **MUST** have `write access` to this folder. +Second argument **"example.com"** is the main domain you want to issue the cert for. +You must have at least one domain there. -27 +You must point and bind all the domains to the same webroot dir: `/home/wwwroot/example.com`. -# [中文说明](https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E) +The certs will be placed in `~/.acme.sh/example.com/` -28 +The certs will be renewed automatically every **60** days. -​ +More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert -# Who: +# 3. Install the cert to Apache/Nginx etc. -30 +After the cert is generated, you probably want to install/copy the cert to your Apache/Nginx or other servers. +You **MUST** use this command to copy the certs to the target files, **DO NOT** use the certs files in **~/.acme.sh/** folder, they are for internal use only, the folder structure may change in the future. -- [FreeBSD.org](https://blog.crashed.org/letsencrypt-in-freebsd-org/) +**Apache** example: +```bash +acme.sh --install-cert -d example.com \ +--cert-file /path/to/certfile/in/apache/cert.pem \ +--key-file /path/to/keyfile/in/apache/key.pem \ +--fullchain-file /path/to/fullchain/certfile/apache/fullchain.pem \ +--reloadcmd "service apache2 force-reload" +``` -31 +**Nginx** example: +```bash +acme.sh --install-cert -d example.com \ +--key-file /path/to/keyfile/in/nginx/key.pem \ +--fullchain-file /path/to/fullchain/nginx/cert.pem \ +--reloadcmd "service nginx force-reload" +``` -- [ruby-china.org](https://ruby-china.org/topics/31983) +Only the domain is required, all the other parameters are optional. -32 +The ownership and permission info of existing files are preserved. You can pre-create the files to define the ownership and permission. +Install/copy the cert/key to the production Apache or Nginx path. -33 +The cert will be renewed every **60** days by default (which is configurable). Once the cert is renewed, the Apache/Nginx service will be reloaded automatically by the command: `service apache2 force-reload` or `service nginx force-reload`. -- [pfsense](https://github.com/pfsense/FreeBSD-ports/pull/89) -34 +**Please take care: The reloadcmd is very important. The cert can be automatically renewed, but, without a correct 'reloadcmd' the cert may not be flushed to your server(like nginx or apache), then your website will not be able to show renewed cert in 60 days.** -- [webfaction](https://community.webfaction.com/questions/19988/using-letsencrypt) +# 4. Use Standalone server to issue cert -35 +**(requires you to be root/sudoer or have permission to listen on port 80 (TCP))** +Port `80` (TCP) **MUST** be free to listen on, otherwise you will be prompted to free it and try again. -36 +```bash +acme.sh --issue --standalone -d example.com -d www.example.com -d cp.example.com +``` -- [discourse.org](https://meta.discourse.org/t/setting-up-lets-encrypt/40709) +More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert -37 +# 5. Use Standalone ssl server to issue cert -- [Centminmod](https://centminmod.com/letsencrypt-acmetool-https.html) +**(requires you to be root/sudoer or have permission to listen on port 443 (TCP))** -38 +Port `443` (TCP) **MUST** be free to listen on, otherwise you will be prompted to free it and try again. -- [splynx](https://forum.splynx.com/t/free-ssl-cert-for-splynx-lets-encrypt/297) +```bash +acme.sh --issue --alpn -d example.com -d www.example.com -d cp.example.com +``` -39 +More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert -- [archlinux](https://www.archlinux.org/packages/community/any/acme.sh) -40 +# 6. Use Apache mode +**(requires you to be root/sudoer, since it is required to interact with Apache server)** -41 +If you are running a web server, Apache or Nginx, it is recommended to use the `Webroot mode`. -- [CentOS Web Panel](http://centos-webpanel.com/) +Particularly, if you are running an Apache server, you can use Apache mode instead. This mode doesn't write any files to your web root folder. +Just set string "apache" as the second argument and it will force use of apache plugin automatically. -- [lnmp.org](https://lnmp.org/) +```sh +acme.sh --issue --apache -d example.com -d www.example.com -d cp.example.com +``` -43 +**This apache mode is only to issue the cert, it will not change your apache config files. +You will need to configure your website config files to use the cert by yourself. +We don't want to mess your apache server, don't worry.** -- [more...](https://github.com/Neilpang/acme.sh/wiki/Blogs-and-tutorials) +More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert +# 7. Use Nginx mode -​ +**(requires you to be root/sudoer, since it is required to interact with Nginx server)** -45 +If you are running a web server, Apache or Nginx, it is recommended to use the `Webroot mode`. +Particularly, if you are running an nginx server, you can use nginx mode instead. This mode doesn't write any files to your web root folder. -46 +Just set string "nginx" as the second argument. -​ +It will configure nginx server automatically to verify the domain and then restore the nginx config to the original version. -47 +So, the config is not changed. -| NO | Status| Platform| +```sh +acme.sh --issue --nginx -d example.com -d www.example.com -d cp.example.com +``` + +**This nginx mode is only to issue the cert, it will not change your nginx config files. +You will need to configure your website config files to use the cert by yourself. +We don't want to mess your nginx server, don't worry.** + +More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert + +# 8. Automatic DNS API integration + +If your DNS provider supports API access, we can use that API to automatically issue the certs. + +You don't have to do anything manually! + +### Currently acme.sh supports most of the dns providers: + +https://github.com/Neilpang/acme.sh/wiki/dnsapi + +# 9. Use DNS manual mode: + +See: https://github.com/Neilpang/acme.sh/wiki/dns-manual-mode first. + +If your dns provider doesn't support any api access, you can add the txt record by your hand. + +```bash +acme.sh --issue --dns -d example.com -d www.example.com -d cp.example.com +``` + +You should get an output like below: + +```sh +Add the following txt record: +Domain:_acme-challenge.example.com +Txt value:9ihDbjYfTExAYeDs4DBUeuTo18KBzwvTEjUnSwd32-c + +Add the following txt record: +Domain:_acme-challenge.www.example.com +Txt value:9ihDbjxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + +Please add those txt records to the domains. Waiting for the dns to take effect. +``` + +Then just rerun with `renew` argument: + +```bash +acme.sh --renew -d example.com +``` + +Ok, it's done. + +**Take care, this is dns manual mode, it can not be renewed automatically. you will have to add a new txt record to your domain by your hand when you renew your cert.** + +**Please use dns api mode instead.** + +# 10. Issue ECC certificates + +`Let's Encrypt` can now issue **ECDSA** certificates. + +And we support them too! + +Just set the `keylength` parameter with a prefix `ec-`. + +For example: + +### Single domain ECC certificate + +```bash +acme.sh --issue -w /home/wwwroot/example.com -d example.com --keylength ec-256 +``` + +### SAN multi domain ECC certificate + +```bash +acme.sh --issue -w /home/wwwroot/example.com -d example.com -d www.example.com --keylength ec-256 +``` + +Please look at the `keylength` parameter above. + +Valid values are: + +1. **ec-256 (prime256v1, "ECDSA P-256")** +2. **ec-384 (secp384r1, "ECDSA P-384")** +3. **ec-521 (secp521r1, "ECDSA P-521", which is not supported by Let's Encrypt yet.)** + + + +# 11. Issue Wildcard certificates + +It's simple, just give a wildcard domain as the `-d` parameter. + +```sh +acme.sh --issue -d example.com -d '*.example.com' --dns dns_cf +``` + + + +# 12. How to renew the certs + +No, you don't need to renew the certs manually. All the certs will be renewed automatically every **60** days. + +However, you can also force to renew a cert: + +```sh +acme.sh --renew -d example.com --force +``` + +or, for ECC cert: + +```sh +acme.sh --renew -d example.com --force --ecc +``` + + +# 13. How to stop cert renewal + +To stop renewal of a cert, you can execute the following to remove the cert from the renewal list: + +```sh +acme.sh --remove -d example.com [--ecc] +``` + +The cert/key file is not removed from the disk. + +You can remove the respective directory (e.g. `~/.acme.sh/example.com`) by yourself. + + +# 14. How to upgrade `acme.sh` + +acme.sh is in constant development, so it's strongly recommended to use the latest code. + +You can update acme.sh to the latest code: + +```sh +acme.sh --upgrade +``` + +You can also enable auto upgrade: + +```sh +acme.sh --upgrade --auto-upgrade +``` + +Then **acme.sh** will be kept up to date automatically. + +Disable auto upgrade: + +```sh +acme.sh --upgrade --auto-upgrade 0 +``` + + +# 15. Issue a cert from an existing CSR + +https://github.com/Neilpang/acme.sh/wiki/Issue-a-cert-from-existing-CSR + + +# 16. Send notifications in cronjob + +https://github.com/Neilpang/acme.sh/wiki/notify + + +# 17. Under the Hood + +Speak ACME language using shell, directly to "Let's Encrypt". + +TODO: + + +# 18. Acknowledgments + +1. Acme-tiny: https://github.com/diafygi/acme-tiny +2. ACME protocol: https://github.com/ietf-wg-acme/acme + + +## Contributors + +### Code Contributors + +This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. + + +### Financial Contributors + +Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/acmesh/contribute)] + +#### Individuals + + + +#### Organizations + +Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/acmesh/contribute)] + + + + + + + + + + + + +# 19. License & Others + +License is GPLv3 + +Please Star and Fork me. + +[Issues](https://github.com/Neilpang/acme.sh/issues) and [pull requests](https://github.com/Neilpang/acme.sh/pulls) are welcome. + + +# 20. Donate +Your donation makes **acme.sh** better: + +1. PayPal/Alipay(支付宝)/Wechat(微信): [https://donate.acme.sh/](https://donate.acme.sh/) +[Donate List](https://github.com/Neilpang/acme.sh/wiki/Donate-list) From a6614abd24600618a23ee390470eea7af912b9f4 Mon Sep 17 00:00:00 2001 From: stilez Date: Sun, 27 Oct 2019 01:00:59 +0000 Subject: [PATCH 074/357] Formatting fixes for Travis --- dnsapi/dns_pleskxml | 102 +++++++++++++++++++++++--------------------- 1 file changed, 53 insertions(+), 49 deletions(-) diff --git a/dnsapi/dns_pleskxml b/dnsapi/dns_pleskxml index a8a74721..bed1b26f 100644 --- a/dnsapi/dns_pleskxml +++ b/dnsapi/dns_pleskxml @@ -44,18 +44,21 @@ NEWLINE='\ #################### API Templates ################################## pleskxml_tplt_get_domains="" - # Get a list of domains that PLESK can manage, so we can check root domain + host for acme.sh - # Also used to test credentials and URI. - # No args. +# Get a list of domains that PLESK can manage, so we can check root domain + host for acme.sh +# Also used to test credentials and URI. +# No args. + pleskxml_tplt_get_dns_records="%s" - # Get all DNS records for a Plesk domain ID. - # ARG = Plesk domain id to query +# Get all DNS records for a Plesk domain ID. +# ARG = Plesk domain id to query + pleskxml_tplt_add_txt_record="%sTXT%s%s" - # Add a TXT record to a domain. - # ARGS = (1) Plesk internal domain ID, (2) "hostname" for the new record, eg '_acme_challenge', (3) TXT record value +# Add a TXT record to a domain. +# ARGS = (1) Plesk internal domain ID, (2) "hostname" for the new record, eg '_acme_challenge', (3) TXT record value + pleskxml_tplt_rmv_dns_record="%s" - # Add a TXT record to a domain. - # ARG = the Plesk internal ID for the dns record to be deleted +# Add a TXT record to a domain. +# ARG = the Plesk internal ID for the dns record to be deleted #################### Public functions ################################## @@ -82,7 +85,7 @@ dns_pleskxml_add() { # printf using template in a variable - not a style issue # shellcheck disable=SC2059 - request="$( printf "$pleskxml_tplt_add_txt_record" "$root_domain_id" "$sub_domain_name" "$txtvalue" )" + request="$(printf "$pleskxml_tplt_add_txt_record" "$root_domain_id" "$sub_domain_name" "$txtvalue")" if ! _call_api "$request"; then return 1 fi @@ -90,7 +93,7 @@ dns_pleskxml_add() { # OK, we should have added a TXT record. Let's check and return success if so. # All that should be left in the result, is one section, containing okNEW_DNS_RECORD_ID - results="$( _api_response_split "$pleskxml_prettyprint_result" 'result' '' )" + results="$(_api_response_split "$pleskxml_prettyprint_result" 'result' '')" if ! _value "$results" | grep 'ok' | grep -qE '[0-9]+'; then # Error - doesn't contain expected string. Something's wrong. @@ -101,7 +104,7 @@ dns_pleskxml_add() { return 1 fi - recid="$( _value "$results" | grep -E '[0-9]+' | sed -E 's/^.*([0-9]+)<\/id>.*$/\1/' )" + recid="$(_value "$results" | grep -E '[0-9]+' | sed -E 's/^.*([0-9]+)<\/id>.*$/\1/')" _info "Success. TXT record appears to be correctly added (Plesk record ID=$recid). Exiting dns_pleskxml_add()." @@ -129,16 +132,16 @@ dns_pleskxml_rm() { # printf using template in a variable - not a style issue # shellcheck disable=SC2059 - request="$( printf "$pleskxml_tplt_get_dns_records" "$root_domain_id" )" + request="$(printf "$pleskxml_tplt_get_dns_records" "$root_domain_id")" if ! _call_api "$request"; then return 1 fi # Reduce output to one line per DNS record, filtered for TXT records with a record ID only (which they should all have) - reclist="$( _api_response_split "$pleskxml_prettyprint_result" 'result' 'ok' | \ - grep "${root_domain_id}" | \ - grep -E '[0-9]+' | \ - grep 'TXT' \ + reclist="$(_api_response_split "$pleskxml_prettyprint_result" 'result' 'ok' \ + | grep "${root_domain_id}" \ + | grep -E '[0-9]+' \ + | grep 'TXT' \ )" if [ -z "$reclist" ]; then @@ -148,14 +151,13 @@ dns_pleskxml_rm() { _debug "Got list of DNS TXT records for root domain '$root_domain_name'"':\n'"$reclist" - recid="$( _value "$reclist" | \ - grep "$1." | \ - grep "$txtvalue" | \ - sed -E 's/(^.*|<\/id>.*$)//g' \ - )" - - _debug "List of DNS TXT records for host:"'\n'"$( _value "$reclist" | grep "$1." )" + recid="$(_value "$reclist" \ + | grep "$1." \ + | grep "$txtvalue" \ + | sed -E 's/(^.*|<\/id>.*$)//g' \ + )" + _debug "List of DNS TXT records for host:"'\n'"$(_value "$reclist" | grep "$1.")" if ! _value "$recid" | grep -Eq '^[0-9]+$'; then _err "DNS records for root domain '${root_domain_name}' (Plesk ID ${root_domain_id}) + host '${sub_domain_name}' do not contain the TXT record '${txtvalue}'" @@ -168,7 +170,7 @@ dns_pleskxml_rm() { # printf using template in a variable - not a style issue # shellcheck disable=SC2059 - request="$( printf "$pleskxml_tplt_rmv_dns_record" "$recid" )" + request="$(printf "$pleskxml_tplt_rmv_dns_record" "$recid")" if ! _call_api "$request"; then return 1 fi @@ -176,7 +178,7 @@ dns_pleskxml_rm() { # OK, we should have removed a TXT record. Let's check and return success if so. # All that should be left in the result, is one section, containing okPLESK_DELETED_DNS_RECORD_ID - results="$( _api_response_split "$pleskxml_prettyprint_result" 'result' '' )" + results="$(_api_response_split "$pleskxml_prettyprint_result" 'result' '')" if ! _value "$results" | grep 'ok' | grep -qE '[0-9]+'; then # Error - doesn't contain expected string. Something's wrong. @@ -214,11 +216,11 @@ _valuecut() { # $2 - tag to resplit on (usually "result" or "domain") # $3 - regex to recognise useful return lines _api_response_split() { - printf '%s' "$1" | \ - sed -E 's/(^[[:space:]]+|[[:space:]]+$)//g' | \ - tr -d '\n\r' | \ - sed -E "s/<\/?$2>/${NEWLINE}/g" | \ - grep -E "$3" + printf '%s' "$1" \ + | sed -E 's/(^[[:space:]]+|[[:space:]]+$)//g' \ + | tr -d '\n\r' \ + | sed -E "s/<\/?$2>/${NEWLINE}/g" \ + | grep -E "$3" } @@ -242,17 +244,16 @@ _call_api() { # Detect any that isn't "ok". None of the used calls should fail if the API is working correctly. # Also detect if there simply aren't any status lines (null result?) and report that, as well. - statuslines="$( echo "$pleskxml_prettyprint_result" | grep -E '^[[:space:]]*[^<]*[[:space:]]*$' )" + statuslines="$(echo "$pleskxml_prettyprint_result" | grep -E '^[[:space:]]*[^<]*[[:space:]]*$')" if _value "$statuslines" | grep -qv 'ok'; then # We have some status lines that aren't "ok". Get the details - errtext="$( \ - _value "$pleskxml_prettyprint_result" | \ - grep -iE "(||)" | \ - sed -E 's/(^[[:space:]]+|<\/[a-z]+$)//g' | \ - sed -E 's/^<([a-z]+)>/\1: /' \ - )" + errtext="$( _value "$pleskxml_prettyprint_result" \ + | grep -iE "(||)" \ + | sed -E 's/(^[[:space:]]+|<\/[a-z]+$)//g' \ + | sed -E 's/^<([a-z]+)>/\1: /' \ + )" elif ! _value "$statuslines" | grep -q 'ok'; then @@ -326,14 +327,17 @@ _credential_check() { # For a FQDN, identify the root domain managed by Plesk, its domain ID in Plesk, and the host if any. + +# IMPORTANT NOTE: a result with host = empty string is OK for this API, see +# https://docs.plesk.com/en-US/obsidian/api-rpc/about-xml-api/reference/managing-dns/managing-dns-records/adding-dns-record.34798 +# See notes at top of this file + _pleskxml_get_root_domain() { _debug "Identifying DNS root domain for '$1' that is managed by the Plesk account." # test if the domain is valid for splitting. - if _value "$root_domain_name" | grep -qvE '^[^.]+\.[^.]+\.[^.]'; then - ### COMMENTED OUT ALSO FOR SAME REASON - ### _err "Invalid domain. The ACME domain must contain at least three parts (aa.bb.tld) to identify a host, domain, and tld for the TXT record." + if _value "$root_domain_name" | grep -qvE '^[^.]+\.[^.]+\.[^.]'; then _err "Invalid domain. The ACME domain must contain at least two parts (aa.bb) to identify a domain and tld for the TXT record." return 1 fi @@ -350,7 +354,8 @@ _pleskxml_get_root_domain() { # for non-Western character sets. # Output will be one line per known domain, containing 1 or 2 tages and an tag # We don't actually need to check for type, name, *and* id, but it guarantees only usable lines are returned. - output="$( _api_response_split "$pleskxml_prettyprint_result" 'domain' 'domain' | sed -E 's/<(\/?)ascii-name>/<\1name>/g' | grep '' | grep '' )" + + output="$(_api_response_split "$pleskxml_prettyprint_result" 'domain' 'domain' | sed -E 's/<(\/?)ascii-name>/<\1name>/g' | grep '' | grep '')" _debug 'Domains managed by Plesk server are (ignore the hacked output):\n' "$output" @@ -364,14 +369,13 @@ _pleskxml_get_root_domain() { _debug "Checking if '$root_domain_name' is managed by the Plesk server..." - root_domain_id="$( _value "$output" | grep "$root_domain_name" | _head_n 1 | sed -E 's/^.*([0-9]+)<\/id>.*$/\1/' )" + root_domain_id="$(_value "$output" | grep "$root_domain_name" | _head_n 1 | sed -E 's/^.*([0-9]+)<\/id>.*$/\1/')" if [ -n "$root_domain_id" ]; then # Found a match - # Note that a result with host = empty string is OK for this API, see - # https://docs.plesk.com/en-US/obsidian/api-rpc/about-xml-api/reference/managing-dns/managing-dns-records/adding-dns-record.34798 - # See notes at top of this file - sub_domain_name="$( _value "$1" | sed -E "s/\.?${root_domain_name}"'$//' )" + # SEE IMPORTANT NOTE ABOVE - THIS FUNCTION CAN RETURN HOST='', AND THAT'S OK FOR PLESK XML API WHICH ALLOWS IT. + # SO WE HANDLE IT AND DON'T PREVENT IT + sub_domain_name="$(_value "$1" | sed -E "s/\.?${root_domain_name}"'$//')" _info "Matched host '$1' to: DOMAIN '${root_domain_name}' (Plesk ID '${root_domain_id}'), HOST '${sub_domain_name}'. Returning." return 0 fi @@ -379,11 +383,11 @@ _pleskxml_get_root_domain() { # No match, try next parent up (if any)... if _contains "$root_domain_name" '\.[^.]+\.'; then - _debug "No match, trying next parent up..." + _debug "No match, trying next parent up..." else _debug "No match,and next parent would be a TLD..." fi - root_domain_name="$( _valuecut 2 1000 "$root_domain_name" )" + root_domain_name="$(_valuecut 2 1000 "$root_domain_name")" doneloop=1 done From 9299a83b175c77feec281a8f8754283e8c6333a0 Mon Sep 17 00:00:00 2001 From: stilez Date: Sun, 27 Oct 2019 01:10:03 +0000 Subject: [PATCH 075/357] Travis fixes --- dnsapi/dns_pleskxml | 40 +++++++++++++--------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/dnsapi/dns_pleskxml b/dnsapi/dns_pleskxml index bed1b26f..794127c7 100644 --- a/dnsapi/dns_pleskxml +++ b/dnsapi/dns_pleskxml @@ -30,8 +30,7 @@ ## ## The `pleskxml_uri`, `pleskxml_user` and `pleskxml_pass` will be saved in `~/.acme.sh/account.conf` and reused when needed. - -#################### INTERNAL VARIABLES + NEWLINE ################################## +#################### INTERNAL VARIABLES + NEWLINE + API TEMPLATES ################################## pleskxml_init_checks_done=0 @@ -40,9 +39,6 @@ pleskxml_init_checks_done=0 NEWLINE='\ ' - -#################### API Templates ################################## - pleskxml_tplt_get_domains="" # Get a list of domains that PLESK can manage, so we can check root domain + host for acme.sh # Also used to test credentials and URI. @@ -60,7 +56,6 @@ pleskxml_tplt_rmv_dns_record="%s # Add a TXT record to a domain. # ARG = the Plesk internal ID for the dns record to be deleted - #################### Public functions ################################## #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" @@ -141,7 +136,7 @@ dns_pleskxml_rm() { reclist="$(_api_response_split "$pleskxml_prettyprint_result" 'result' 'ok' \ | grep "${root_domain_id}" \ | grep -E '[0-9]+' \ - | grep 'TXT' \ + | grep 'TXT' )" if [ -z "$reclist" ]; then @@ -154,8 +149,8 @@ dns_pleskxml_rm() { recid="$(_value "$reclist" \ | grep "$1." \ | grep "$txtvalue" \ - | sed -E 's/(^.*|<\/id>.*$)//g' \ - )" + | sed -E 's/(^.*|<\/id>.*$)//g' + )" _debug "List of DNS TXT records for host:"'\n'"$(_value "$reclist" | grep "$1.")" @@ -193,8 +188,6 @@ dns_pleskxml_rm() { return 0 } - - #################### Private functions below ################################## # Outputs value of a variable @@ -202,7 +195,6 @@ _value() { printf '%s' "$1" } - # Outputs value of a variable (FQDN) and cuts it at 2 delimiters # $1, $2 = where to cut # $3 = FQDN @@ -210,20 +202,18 @@ _valuecut() { printf '%s' "$3" | cut -d . -f "${1}-${2}" } - # Cleans up an API response, splits it "per item" and greps for a string to validate useful lines # $1 - result string from API # $2 - tag to resplit on (usually "result" or "domain") # $3 - regex to recognise useful return lines _api_response_split() { printf '%s' "$1" \ - | sed -E 's/(^[[:space:]]+|[[:space:]]+$)//g' \ - | tr -d '\n\r' \ - | sed -E "s/<\/?$2>/${NEWLINE}/g" \ - | grep -E "$3" + | sed -E 's/(^[[:space:]]+|[[:space:]]+$)//g' \ + | tr -d '\n\r' \ + | sed -E "s/<\/?$2>/${NEWLINE}/g" \ + | grep -E "$3" } - # Calls Plesk XML API, and checks results for obvious issues _call_api() { request="$1" @@ -249,11 +239,11 @@ _call_api() { if _value "$statuslines" | grep -qv 'ok'; then # We have some status lines that aren't "ok". Get the details - errtext="$( _value "$pleskxml_prettyprint_result" \ + errtext="$(_value "$pleskxml_prettyprint_result" \ | grep -iE "(||)" \ | sed -E 's/(^[[:space:]]+|<\/[a-z]+$)//g' \ - | sed -E 's/^<([a-z]+)>/\1: /' \ - )" + | sed -E 's/^<([a-z]+)>/\1: /' + )" elif ! _value "$statuslines" | grep -q 'ok'; then @@ -278,10 +268,8 @@ _call_api() { return 0 } - +# Startup checks (credentials, URI) _credential_check() { - # Startup checks (credentials, URI) - _debug "Checking Plesk XML API login credentials and URI..." if [ "$pleskxml_init_checks_done" -eq 1 ]; then @@ -289,7 +277,6 @@ _credential_check() { return 0 fi - pleskxml_user="${pleskxml_user:-$(_readaccountconf_mutable pleskxml_user)}" pleskxml_pass="${pleskxml_pass:-$(_readaccountconf_mutable pleskxml_pass)}" pleskxml_uri="${pleskxml_uri:-$(_readaccountconf_mutable pleskxml_uri)}" @@ -325,7 +312,6 @@ _credential_check() { return 0 } - # For a FQDN, identify the root domain managed by Plesk, its domain ID in Plesk, and the host if any. # IMPORTANT NOTE: a result with host = empty string is OK for this API, see @@ -369,7 +355,7 @@ _pleskxml_get_root_domain() { _debug "Checking if '$root_domain_name' is managed by the Plesk server..." - root_domain_id="$(_value "$output" | grep "$root_domain_name" | _head_n 1 | sed -E 's/^.*([0-9]+)<\/id>.*$/\1/')" + root_domain_id="$(_value "$output" | grep "$root_domain_name" | _head_n 1 | sed -E 's/^.*([0-9]+)<\/id>.*$/\1/')" if [ -n "$root_domain_id" ]; then # Found a match From 6df31eb7f58f32428de4a57971b882421d19b3f5 Mon Sep 17 00:00:00 2001 From: stilez Date: Sun, 27 Oct 2019 01:13:15 +0000 Subject: [PATCH 076/357] travis --- dnsapi/dns_pleskxml | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_pleskxml b/dnsapi/dns_pleskxml index 794127c7..83017c3b 100644 --- a/dnsapi/dns_pleskxml +++ b/dnsapi/dns_pleskxml @@ -77,7 +77,6 @@ dns_pleskxml_add() { _debug 'Credentials OK, and domain identified. Calling Plesk XML API to add TXT record' - # printf using template in a variable - not a style issue # shellcheck disable=SC2059 request="$(printf "$pleskxml_tplt_add_txt_record" "$root_domain_id" "$sub_domain_name" "$txtvalue")" From 1253357a39206dd43047bdbbbd341ffef1d735ab Mon Sep 17 00:00:00 2001 From: stilez Date: Sun, 27 Oct 2019 01:48:02 +0000 Subject: [PATCH 077/357] edits to comments --- dnsapi/dns_pleskxml | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/dnsapi/dns_pleskxml b/dnsapi/dns_pleskxml index 83017c3b..e2ec5717 100644 --- a/dnsapi/dns_pleskxml +++ b/dnsapi/dns_pleskxml @@ -1,6 +1,6 @@ #!/usr/bin/env sh -## Name: dns_pleskxml.sh +## Name: dns_pleskxml ## Created by Stilez. ## Also uses some code from PR#1832 by @romanlum (https://github.com/Neilpang/acme.sh/pull/1832/files) @@ -13,14 +13,16 @@ ## For example, to add a TXT record to DNS alias domain "acme-alias.com" would be a valid Plesk action. ## So this API module can handle such a request, if needed. +## For ACME v2 purposes, new TXT records are appended when added, and removing one TXT record will not affect any other TXT records. + ## The plesk plugin uses the xml api to add and remvoe the dns records. Therefore the url, username ## and password have to be configured by the user before this module is called. ## ## ``` -## export pleskxml_uri="https://YOUR_PLESK_URI_HERE:8443/enterprise/control/agent.php" +## export pleskxml_uri="https://address-of-my-plesk-server.net:8443/enterprise/control/agent.php" ## (or probably something similar) -## export pleskxml_user="plesk username" -## export pleskxml_pass="plesk password" +## export pleskxml_user="my plesk username" +## export pleskxml_pass="my plesk password" ## ``` ## Ok, let's issue a cert now: @@ -42,19 +44,19 @@ NEWLINE='\ pleskxml_tplt_get_domains="" # Get a list of domains that PLESK can manage, so we can check root domain + host for acme.sh # Also used to test credentials and URI. -# No args. +# No params. pleskxml_tplt_get_dns_records="%s" # Get all DNS records for a Plesk domain ID. -# ARG = Plesk domain id to query +# PARAM = Plesk domain id to query pleskxml_tplt_add_txt_record="%sTXT%s%s" # Add a TXT record to a domain. -# ARGS = (1) Plesk internal domain ID, (2) "hostname" for the new record, eg '_acme_challenge', (3) TXT record value +# PARAMS = (1) Plesk internal domain ID, (2) "hostname" for the new record, eg '_acme_challenge', (3) TXT record value pleskxml_tplt_rmv_dns_record="%s" -# Add a TXT record to a domain. -# ARG = the Plesk internal ID for the dns record to be deleted +# Delete a specific TXT record from a domain. +# PARAM = the Plesk internal ID for the DNS record to be deleted #################### Public functions ################################## @@ -63,7 +65,7 @@ dns_pleskxml_add() { fulldomain=$1 txtvalue=$2 - _info "Entering dns_pleskxml_add() to add TXT record '$2' to domain '$1'..." + _info "Entering dns_pleskxml_add() to add TXT record '$txtvalue' to domain '$fulldomain'..." # Get credentials if not already checked, and confirm we can log in to Plesk XML API if ! _credential_check; then @@ -110,7 +112,7 @@ dns_pleskxml_rm() { fulldomain=$1 txtvalue=$2 - _info "Entering dns_pleskxml_rm() to remove TXT record '$2' from domain '$1'..." + _info "Entering dns_pleskxml_rm() to remove TXT record '$txtvalue' from domain '$fulldomain'..." # Get credentials if not already checked, and confirm we can log in to Plesk XML API if ! _credential_check; then @@ -189,19 +191,19 @@ dns_pleskxml_rm() { #################### Private functions below ################################## -# Outputs value of a variable +# Outputs value of a variable without additional newlines etc _value() { printf '%s' "$1" } -# Outputs value of a variable (FQDN) and cuts it at 2 delimiters +# Outputs value of a variable (FQDN) and cuts it at 2 specified '.' delimiters, returning the text in between # $1, $2 = where to cut # $3 = FQDN _valuecut() { printf '%s' "$3" | cut -d . -f "${1}-${2}" } -# Cleans up an API response, splits it "per item" and greps for a string to validate useful lines +# Cleans up an API response, splits it "one line per item in the response" and greps for a string that in the context, identifies "useful" lines # $1 - result string from API # $2 - tag to resplit on (usually "result" or "domain") # $3 - regex to recognise useful return lines @@ -228,8 +230,6 @@ _call_api() { pleskxml_retcode="$?" _debug "acme _post() returned retcode=$pleskxml_retcode. Literal response:" '\n' "'${pleskxml_prettyprint_result}'" - # Error handling - # Detect any that isn't "ok". None of the used calls should fail if the API is working correctly. # Also detect if there simply aren't any status lines (null result?) and report that, as well. @@ -320,7 +320,7 @@ _credential_check() { _pleskxml_get_root_domain() { _debug "Identifying DNS root domain for '$1' that is managed by the Plesk account." - # test if the domain is valid for splitting. + # test if the domain as provided is valid for splitting. if _value "$root_domain_name" | grep -qvE '^[^.]+\.[^.]+\.[^.]'; then _err "Invalid domain. The ACME domain must contain at least two parts (aa.bb) to identify a domain and tld for the TXT record." @@ -334,10 +334,10 @@ _pleskxml_get_root_domain() { return 1 fi - # Generate a hacked list of domains known to this Plesk account. + # Generate a crude list of domains known to this Plesk account. # We convert tags to so it'll flag on a hit with either or fields, # for non-Western character sets. - # Output will be one line per known domain, containing 1 or 2 tages and an tag + # Output will be one line per known domain, containing 2 tages and a single tag # We don't actually need to check for type, name, *and* id, but it guarantees only usable lines are returned. output="$(_api_response_split "$pleskxml_prettyprint_result" 'domain' 'domain' | sed -E 's/<(\/?)ascii-name>/<\1name>/g' | grep '' | grep '')" @@ -345,7 +345,7 @@ _pleskxml_get_root_domain() { _debug 'Domains managed by Plesk server are (ignore the hacked output):\n' "$output" # loop and test if domain, or any parent domain, is managed by Plesk - # Loop until we don't have any '.' in the sring we're testing as a root domain + # Loop until we don't have any '.' in the string we're testing as a candidate Plesk-managed domain root_domain_name="$1" doneloop=0 @@ -378,7 +378,7 @@ _pleskxml_get_root_domain() { done # if we get here, we failed to find a root domain match in the list of domains managed by Plesk. - # if we never ran the loop a first time, $1 wasn't at least a 2 level domain (domain.tld) and wasn't valid anyway + # if we never ran the loop even once, $1 wasn't a 2nd level (or deeper) domain (e.g. domain.tld) and wasn't valid anyway if [ -z $doneloop ]; then _err "'$1' isn't a valid domain for ACME DNS. Exiting." From 671edc33e173b0318972d7eb4fd50d03fbde85cd Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 27 Oct 2019 11:43:40 +0800 Subject: [PATCH 078/357] fix background color --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 37ce15aa..07dc63d2 100755 --- a/acme.sh +++ b/acme.sh @@ -153,7 +153,7 @@ fi __green() { if [ "${__INTERACTIVE}${ACME_NO_COLOR:-0}" = "10" -o "${ACME_FORCE_COLOR}" = "1" ]; then - printf '\033[1;31;32m%b\033[0m' "$1" + printf '\33[1;32m%b\33[0m' "$1" return fi printf -- "%b" "$1" @@ -161,7 +161,7 @@ __green() { __red() { if [ "${__INTERACTIVE}${ACME_NO_COLOR:-0}" = "10" -o "${ACME_FORCE_COLOR}" = "1" ]; then - printf '\033[1;31;40m%b\033[0m' "$1" + printf '\33[1;31m%b\33[0m' "$1" return fi printf -- "%b" "$1" From 9eb5f65b8f272b71fdf2d69a33492e67b5b76836 Mon Sep 17 00:00:00 2001 From: stilez Date: Sun, 27 Oct 2019 07:38:22 +0000 Subject: [PATCH 079/357] edit comments --- dnsapi/dns_pleskxml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_pleskxml b/dnsapi/dns_pleskxml index e2ec5717..d613f8e1 100644 --- a/dnsapi/dns_pleskxml +++ b/dnsapi/dns_pleskxml @@ -60,7 +60,7 @@ pleskxml_tplt_rmv_dns_record="%s #################### Public functions ################################## -#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +#Usage: dns_pleskxml_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_pleskxml_add() { fulldomain=$1 txtvalue=$2 @@ -107,7 +107,7 @@ dns_pleskxml_add() { return 0 } -#Usage: rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +#Usage: dns_pleskxml_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_pleskxml_rm() { fulldomain=$1 txtvalue=$2 From 582c77805c837962129ea5372a664658739a13e1 Mon Sep 17 00:00:00 2001 From: peterkelm Date: Sun, 27 Oct 2019 13:13:22 +0100 Subject: [PATCH 080/357] variomedia dns api initial commit for the variomedia dns api implementation --- dnsapi/dns_variomedia.sh | 166 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 dnsapi/dns_variomedia.sh diff --git a/dnsapi/dns_variomedia.sh b/dnsapi/dns_variomedia.sh new file mode 100644 index 00000000..56f1bf96 --- /dev/null +++ b/dnsapi/dns_variomedia.sh @@ -0,0 +1,166 @@ +#!/usr/bin/env sh + +# +#VARIOMEDIA_API_TOKEN=000011112222333344445555666677778888 + +VARIOMEDIA_API="https://api.variomedia.de" + +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_variomedia_add() { + fulldomain=$1 + txtvalue=$2 + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + VARIOMEDIA_API_TOKEN="${VARIOMEDIA_API_TOKEN:-$(_readaccountconf_mutable VARIOMEDIA_API_TOKEN)}" + if test -z "$VARIOMEDIA_API_TOKEN"; then + VARIOMEDIA_API_TOKEN="" + _err 'VARIOMEDIA_API_TOKEN was not exported' + return 1 + fi + + _saveaccountconf_mutable VARIOMEDIA_API_TOKEN "$VARIOMEDIA_API_TOKEN" + + _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' +# _variomedia_rest GET "/dns-records?filter[domain]=$_domain" + +# if printf "%s\n" "$response" | grep "\"record_type\": \"A\", \"fqdn\": \"$fulldomain\"" >/dev/null; then +# _err 'Error' +# return 1 +# fi + + if ! _variomedia_rest POST "dns-records" "{\"data\": {\"type\": \"dns-record\", \"attributes\": {\"record_type\": \"TXT\", \"name\": \"$_sub_domain\", \"domain\": \"$_domain\", \"data\": \"$txtvalue\", \"ttl\":300}}}"; then + _err "$response" + return 1 + fi + + _debug2 _response "$response" + return 0 +} + +#fulldomain txtvalue +dns_variomedia_rm() { + fulldomain=$1 + txtvalue=$2 + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + VARIOMEDIA_API_TOKEN="${VARIOMEDIA_API_TOKEN:-$(_readaccountconf_mutable VARIOMEDIA_API_TOKEN)}" + if test -z "$VARIOMEDIA_API_TOKEN"; then + VARIOMEDIA_API_TOKEN="" + _err 'VARIOMEDIA_API_TOKEN was not exported' + return 1 + fi + + _saveaccountconf_mutable VARIOMEDIA_API_TOKEN "$VARIOMEDIA_API_TOKEN" + + _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' + + if ! _variomedia_rest GET "dns-records?filter[domain]=$_domain"; then + _err 'Error' + return 1 + fi + + _record_id="$(echo $response | cut -d '[' -f2 | cut -d']' -f1 | sed 's/},[ \t]*{/\},§\{/g' | tr § '\n' | grep $_sub_domain | sed 's/^{//;s/}[,]?$//' | tr , '\n' | tr -d '\"' | grep ^id | cut -d : -f2 | tr -d ' ')" + _debug _record_id "$_record_id" + if [ "$_record_id" ]; then + _info "Successfully retrieved the record id for ACME challenge." + else + _info "Empty record id, it seems no such record." + return 0 + fi + + if ! _variomedia_rest DELETE "/dns-records/$_record_id"; then + _err "$response" + return 1 + fi + + _debug2 _response "$response" + return 0 +} + +#################### Private functions below ################################## +#_acme-challenge.www.domain.com +#returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +_get_root() { + fulldomain=$1 + i=1 + while true; do + h=$(printf "%s" "$fulldomain" | cut -d . -f $i-100) + _debug h "$h" + if [ -z "$h" ]; then + return 1 + fi + + if ! _variomedia_rest GET "domains/$h"; then + return 1 + fi + + if _startswith "$response" "\{\"data\":"; then + if _contains "$response" "\"id\": \"$h\""; then + _sub_domain="$(echo "$fulldomain" | sed "s/\\.$h\$//")" + _domain=$h + return 0 +# else +# _err 'Invalid domain' +# return 1 + fi +# else +# _err "$response" +# return 1 + fi + i=$(_math "$i" + 1) + done + + _debug "root domain not found" + + return 1 +} + +_variomedia_rest() { + m=$1 + ep="$2" + data="$3" + _debug "$ep" + +# api_key_trimmed=$(echo $VARIOMEDIA_API_TOKEN | tr -d '"') + +# export _H1="Api-Key: $api_key_trimmed" + + export _H1="Authorization: token $VARIOMEDIA_API_TOKEN" + export _H2="Content-Type: application/vnd.api+json" + export _H3="Accept: application/vnd.variomedia.v1+json" + + if [ "$m" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$VARIOMEDIA_API/$ep" "" "$m")" + else + response="$(_get "$VARIOMEDIA_API/$ep")" + fi + + if [ "$?" != "0" ]; then + _err "Error $ep" + return 1 + fi + + _debug2 response "$response" + return 0 +} From 1271f97b669ee66727293beea3f2a39da2899e04 Mon Sep 17 00:00:00 2001 From: peterkelm Date: Sun, 27 Oct 2019 16:52:51 +0100 Subject: [PATCH 081/357] fixed dns_variomedia_rm for wildcard certs fixed dns_variomedia_rm to respect the txtvalue supplied as function parameter --- dnsapi/dns_variomedia.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_variomedia.sh b/dnsapi/dns_variomedia.sh index 56f1bf96..2e822a0d 100644 --- a/dnsapi/dns_variomedia.sh +++ b/dnsapi/dns_variomedia.sh @@ -77,7 +77,7 @@ dns_variomedia_rm() { return 1 fi - _record_id="$(echo $response | cut -d '[' -f2 | cut -d']' -f1 | sed 's/},[ \t]*{/\},§\{/g' | tr § '\n' | grep $_sub_domain | sed 's/^{//;s/}[,]?$//' | tr , '\n' | tr -d '\"' | grep ^id | cut -d : -f2 | tr -d ' ')" + _record_id="$(echo $response | cut -d '[' -f2 | cut -d']' -f1 | sed 's/},[ \t]*{/\},§\{/g' | tr § '\n' | grep $_sub_domain | grep $txtvalue | sed 's/^{//;s/}[,]?$//' | tr , '\n' | tr -d '\"' | grep ^id | cut -d : -f2 | tr -d ' ')" _debug _record_id "$_record_id" if [ "$_record_id" ]; then _info "Successfully retrieved the record id for ACME challenge." From c1b089d1c3adb314daf29a084c3bf13042e72c7f Mon Sep 17 00:00:00 2001 From: peterkelm Date: Sun, 27 Oct 2019 16:58:36 +0100 Subject: [PATCH 082/357] unused code removed --- dnsapi/dns_variomedia.sh | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/dnsapi/dns_variomedia.sh b/dnsapi/dns_variomedia.sh index 2e822a0d..8588d7c8 100644 --- a/dnsapi/dns_variomedia.sh +++ b/dnsapi/dns_variomedia.sh @@ -30,14 +30,6 @@ dns_variomedia_add() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" -# _debug 'Getting txt records' -# _variomedia_rest GET "/dns-records?filter[domain]=$_domain" - -# if printf "%s\n" "$response" | grep "\"record_type\": \"A\", \"fqdn\": \"$fulldomain\"" >/dev/null; then -# _err 'Error' -# return 1 -# fi - if ! _variomedia_rest POST "dns-records" "{\"data\": {\"type\": \"dns-record\", \"attributes\": {\"record_type\": \"TXT\", \"name\": \"$_sub_domain\", \"domain\": \"$_domain\", \"data\": \"$txtvalue\", \"ttl\":300}}}"; then _err "$response" return 1 @@ -119,13 +111,7 @@ _get_root() { _sub_domain="$(echo "$fulldomain" | sed "s/\\.$h\$//")" _domain=$h return 0 -# else -# _err 'Invalid domain' -# return 1 fi -# else -# _err "$response" -# return 1 fi i=$(_math "$i" + 1) done @@ -141,10 +127,6 @@ _variomedia_rest() { data="$3" _debug "$ep" -# api_key_trimmed=$(echo $VARIOMEDIA_API_TOKEN | tr -d '"') - -# export _H1="Api-Key: $api_key_trimmed" - export _H1="Authorization: token $VARIOMEDIA_API_TOKEN" export _H2="Content-Type: application/vnd.api+json" export _H3="Accept: application/vnd.variomedia.v1+json" From bc291141b13a802ac0190ba06946ef2fa9add768 Mon Sep 17 00:00:00 2001 From: stilez Date: Sun, 27 Oct 2019 16:58:22 +0000 Subject: [PATCH 083/357] fix filename --- dnsapi/dns_pleskxml.sh | 391 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 391 insertions(+) create mode 100644 dnsapi/dns_pleskxml.sh diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh new file mode 100644 index 00000000..25d1e6dc --- /dev/null +++ b/dnsapi/dns_pleskxml.sh @@ -0,0 +1,391 @@ +#!/usr/bin/env sh + +## Name: dns_pleskxml.sh +## Created by Stilez. +## Also uses some code from PR#1832 by @romanlum (https://github.com/Neilpang/acme.sh/pull/1832/files) + +## This DNS01 method uses the Plesk XML API described at: +## https://docs.plesk.com/en-US/12.5/api-rpc/about-xml-api.28709 +## and more specifically: https://docs.plesk.com/en-US/12.5/api-rpc/reference.28784 + +## Note: a DNS ID with host = empty string is OK for this API, see +## https://docs.plesk.com/en-US/obsidian/api-rpc/about-xml-api/reference/managing-dns/managing-dns-records/adding-dns-record.34798 +## For example, to add a TXT record to DNS alias domain "acme-alias.com" would be a valid Plesk action. +## So this API module can handle such a request, if needed. + +## For ACME v2 purposes, new TXT records are appended when added, and removing one TXT record will not affect any other TXT records. + +## The plesk plugin uses the xml api to add and remvoe the dns records. Therefore the url, username +## and password have to be configured by the user before this module is called. +## +## ``` +## export pleskxml_uri="https://address-of-my-plesk-server.net:8443/enterprise/control/agent.php" +## (or probably something similar) +## export pleskxml_user="my plesk username" +## export pleskxml_pass="my plesk password" +## ``` + +## Ok, let's issue a cert now: +## ``` +## acme.sh --issue --dns dns_pleskxml -d example.com -d www.example.com +## ``` +## +## The `pleskxml_uri`, `pleskxml_user` and `pleskxml_pass` will be saved in `~/.acme.sh/account.conf` and reused when needed. + +#################### INTERNAL VARIABLES + NEWLINE + API TEMPLATES ################################## + +pleskxml_init_checks_done=0 + +# Variable containing bare newline - not a style issue +# shellcheck disable=SC1004 +NEWLINE='\ +' + +pleskxml_tplt_get_domains="" +# Get a list of domains that PLESK can manage, so we can check root domain + host for acme.sh +# Also used to test credentials and URI. +# No params. + +pleskxml_tplt_get_dns_records="%s" +# Get all DNS records for a Plesk domain ID. +# PARAM = Plesk domain id to query + +pleskxml_tplt_add_txt_record="%sTXT%s%s" +# Add a TXT record to a domain. +# PARAMS = (1) Plesk internal domain ID, (2) "hostname" for the new record, eg '_acme_challenge', (3) TXT record value + +pleskxml_tplt_rmv_dns_record="%s" +# Delete a specific TXT record from a domain. +# PARAM = the Plesk internal ID for the DNS record to be deleted + +#################### Public functions ################################## + +#Usage: dns_pleskxml_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_pleskxml_add() { + fulldomain=$1 + txtvalue=$2 + + _info "Entering dns_pleskxml_add() to add TXT record '$txtvalue' to domain '$fulldomain'..." + + # Get credentials if not already checked, and confirm we can log in to Plesk XML API + if ! _credential_check; then + return 1 + fi + + # Get root and subdomain details, and Plesk domain ID + if ! _pleskxml_get_root_domain "$fulldomain"; then + return 1 + fi + + _debug 'Credentials OK, and domain identified. Calling Plesk XML API to add TXT record' + + # printf using template in a variable - not a style issue + # shellcheck disable=SC2059 + request="$(printf "$pleskxml_tplt_add_txt_record" "$root_domain_id" "$sub_domain_name" "$txtvalue")" + if ! _call_api "$request"; then + return 1 + fi + + # OK, we should have added a TXT record. Let's check and return success if so. + # All that should be left in the result, is one section, containing okNEW_DNS_RECORD_ID + + results="$(_api_response_split "$pleskxml_prettyprint_result" 'result' '')" + + if ! _value "$results" | grep 'ok' | grep -qE '[0-9]+'; then + # Error - doesn't contain expected string. Something's wrong. + _err 'Error when calling Plesk XML API.' + _err 'The result did not contain the expected XXXXX section, or contained other values as well.' + _err 'This is unexpected: something has gone wrong.' + _err 'The full response was:\n' "$pleskxml_prettyprint_result" + return 1 + fi + + recid="$(_value "$results" | grep -E '[0-9]+' | sed -E 's/^.*([0-9]+)<\/id>.*$/\1/')" + + _info "Success. TXT record appears to be correctly added (Plesk record ID=$recid). Exiting dns_pleskxml_add()." + + return 0 +} + +#Usage: dns_pleskxml_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_pleskxml_rm() { + fulldomain=$1 + txtvalue=$2 + + _info "Entering dns_pleskxml_rm() to remove TXT record '$txtvalue' from domain '$fulldomain'..." + + # Get credentials if not already checked, and confirm we can log in to Plesk XML API + if ! _credential_check; then + return 1 + fi + + # Get root and subdomain details, and Plesk domain ID + if ! _pleskxml_get_root_domain "$fulldomain"; then + return 1 + fi + + _debug 'Credentials OK, and domain identified. Calling Plesk XML API to get list of TXT records and their IDs' + + # printf using template in a variable - not a style issue + # shellcheck disable=SC2059 + request="$(printf "$pleskxml_tplt_get_dns_records" "$root_domain_id")" + if ! _call_api "$request"; then + return 1 + fi + + # Reduce output to one line per DNS record, filtered for TXT records with a record ID only (which they should all have) + reclist="$(_api_response_split "$pleskxml_prettyprint_result" 'result' 'ok' \ + | grep "${root_domain_id}" \ + | grep -E '[0-9]+' \ + | grep 'TXT' + )" + + if [ -z "$reclist" ]; then + _err "No TXT records found for root domain ${root_domain_name} (Plesk domain ID ${root_domain_id}). Exiting." + return 1 + fi + + _debug "Got list of DNS TXT records for root domain '$root_domain_name'"':\n'"$reclist" + + recid="$(_value "$reclist" \ + | grep "$1." \ + | grep "$txtvalue" \ + | sed -E 's/(^.*|<\/id>.*$)//g' + )" + + _debug "List of DNS TXT records for host:"'\n'"$(_value "$reclist" | grep "$1.")" + + if ! _value "$recid" | grep -Eq '^[0-9]+$'; then + _err "DNS records for root domain '${root_domain_name}' (Plesk ID ${root_domain_id}) + host '${sub_domain_name}' do not contain the TXT record '${txtvalue}'" + _err "Cannot delete TXT record. Exiting." + return 1 + fi + + _debug "Found Plesk record ID for target text string '${txtvalue}': ID=${recid}" + _debug 'Calling Plesk XML API to remove TXT record' + + # printf using template in a variable - not a style issue + # shellcheck disable=SC2059 + request="$(printf "$pleskxml_tplt_rmv_dns_record" "$recid")" + if ! _call_api "$request"; then + return 1 + fi + + # OK, we should have removed a TXT record. Let's check and return success if so. + # All that should be left in the result, is one section, containing okPLESK_DELETED_DNS_RECORD_ID + + results="$(_api_response_split "$pleskxml_prettyprint_result" 'result' '')" + + if ! _value "$results" | grep 'ok' | grep -qE '[0-9]+'; then + # Error - doesn't contain expected string. Something's wrong. + _err 'Error when calling Plesk XML API.' + _err 'The result did not contain the expected XXXXX section, or contained other values as well.' + _err 'This is unexpected: something has gone wrong.' + _err 'The full response was:\n' "$pleskxml_prettyprint_result" + return 1 + fi + + _info "Success. TXT record appears to be correctly removed. Exiting dns_pleskxml_rm()." + return 0 +} + +#################### Private functions below ################################## + +# Outputs value of a variable without additional newlines etc +_value() { + printf '%s' "$1" +} + +# Outputs value of a variable (FQDN) and cuts it at 2 specified '.' delimiters, returning the text in between +# $1, $2 = where to cut +# $3 = FQDN +_valuecut() { + printf '%s' "$3" | cut -d . -f "${1}-${2}" +} + +# Cleans up an API response, splits it "one line per item in the response" and greps for a string that in the context, identifies "useful" lines +# $1 - result string from API +# $2 - tag to resplit on (usually "result" or "domain") +# $3 - regex to recognise useful return lines +_api_response_split() { + printf '%s' "$1" \ + | sed -E 's/(^[[:space:]]+|[[:space:]]+$)//g' \ + | tr -d '\n\r' \ + | sed -E "s/<\/?$2>/${NEWLINE}/g" \ + | grep -E "$3" +} + +# Calls Plesk XML API, and checks results for obvious issues +_call_api() { + request="$1" + errtext='' + + _debug 'Entered _call_api(). Calling Plesk XML API with request:\n' "'${request}'" + + export _H1="HTTP_AUTH_LOGIN: $pleskxml_user" + export _H2="HTTP_AUTH_PASSWD: $pleskxml_pass" + export _H3="content-Type: text/xml" + export _H4="HTTP_PRETTY_PRINT: true" + pleskxml_prettyprint_result="$(_post "${request}" "$pleskxml_uri" "" "POST")" + pleskxml_retcode="$?" + _debug "acme _post() returned retcode=$pleskxml_retcode. Literal response:" '\n' "'${pleskxml_prettyprint_result}'" + + # Detect any that isn't "ok". None of the used calls should fail if the API is working correctly. + # Also detect if there simply aren't any status lines (null result?) and report that, as well. + + statuslines="$(echo "$pleskxml_prettyprint_result" | grep -E '^[[:space:]]*[^<]*[[:space:]]*$')" + + if _value "$statuslines" | grep -qv 'ok'; then + + # We have some status lines that aren't "ok". Get the details + errtext="$(_value "$pleskxml_prettyprint_result" \ + | grep -iE "(||)" \ + | sed -E 's/(^[[:space:]]+|<\/[a-z]+$)//g' \ + | sed -E 's/^<([a-z]+)>/\1: /' + )" + + elif ! _value "$statuslines" | grep -q 'ok'; then + + # We have no status lines at all. Results are empty + errtext='The Plesk XML API unexpectedly returned an empty set of results for this call.' + + fi + + if [ "$pleskxml_retcode" -ne 0 ] || [ "$errtext" != "" ]; then + _err "The Plesk XML API call failed." + _err "The return code for the POST request was $pleskxml_retcode (0=success)." + if [ "$errtext" != "" ]; then + _err 'Status and error messages received from the Plesk server:\n' "$errtext" + else + _err "No additional error messages were received back from the Plesk server" + fi + return 1 + fi + + _debug "Leaving _call_api(). Successful call." + + return 0 +} + +# Startup checks (credentials, URI) +_credential_check() { + _debug "Checking Plesk XML API login credentials and URI..." + + if [ "$pleskxml_init_checks_done" -eq 1 ]; then + _debug "Initial checks already done, no need to repeat. Skipped." + return 0 + fi + + pleskxml_user="${pleskxml_user:-$(_readaccountconf_mutable pleskxml_user)}" + pleskxml_pass="${pleskxml_pass:-$(_readaccountconf_mutable pleskxml_pass)}" + pleskxml_uri="${pleskxml_uri:-$(_readaccountconf_mutable pleskxml_uri)}" + + _debug "Credentials - User: '${pleskxml_user}' Passwd: ****** URI: '${pleskxml_uri}'" + + if [ -z "$pleskxml_user" ] || [ -z "$pleskxml_pass" ] || [ -z "$pleskxml_uri" ]; then + pleskxml_user="" + pleskxml_pass="" + pleskxml_uri="" + _err "You didn't specify one or more of the Plesk XML API username, password, or URI." + _err "Please create these and try again." + _err "Instructions are in the module source code." + return 1 + fi + + # Test the API is usable, by trying to read the list of managed domains... + _call_api "$pleskxml_tplt_get_domains" + if [ "$pleskxml_retcode" -ne 0 ]; then + _err '\nFailed to access Plesk XML API.' + _err "Please check your login credentials and Plesk URI, and that the URI is reachable, and try again." + return 1 + fi + + _saveaccountconf_mutable pleskxml_uri "$pleskxml_uri" + _saveaccountconf_mutable pleskxml_user "$pleskxml_user" + _saveaccountconf_mutable pleskxml_pass "$pleskxml_pass" + + _debug "Test login to Plesk XML API successful. Login credentials and URI successfully saved to the acme.sh configuration file for future use." + + pleskxml_init_checks_done=1 + + return 0 +} + +# For a FQDN, identify the root domain managed by Plesk, its domain ID in Plesk, and the host if any. + +# IMPORTANT NOTE: a result with host = empty string is OK for this API, see +# https://docs.plesk.com/en-US/obsidian/api-rpc/about-xml-api/reference/managing-dns/managing-dns-records/adding-dns-record.34798 +# See notes at top of this file + +_pleskxml_get_root_domain() { + _debug "Identifying DNS root domain for '$1' that is managed by the Plesk account." + + # test if the domain as provided is valid for splitting. + + if _value "$root_domain_name" | grep -qvE '^[^.]+\.[^.]+\.[^.]'; then + _err "Invalid domain. The ACME domain must contain at least two parts (aa.bb) to identify a domain and tld for the TXT record." + return 1 + fi + + _debug "Querying Plesk server for list of managed domains..." + + _call_api "$pleskxml_tplt_get_domains" + if [ "$pleskxml_retcode" -ne 0 ]; then + return 1 + fi + + # Generate a crude list of domains known to this Plesk account. + # We convert tags to so it'll flag on a hit with either or fields, + # for non-Western character sets. + # Output will be one line per known domain, containing 2 tages and a single tag + # We don't actually need to check for type, name, *and* id, but it guarantees only usable lines are returned. + + output="$(_api_response_split "$pleskxml_prettyprint_result" 'domain' 'domain' | sed -E 's/<(\/?)ascii-name>/<\1name>/g' | grep '' | grep '')" + + _debug 'Domains managed by Plesk server are (ignore the hacked output):\n' "$output" + + # loop and test if domain, or any parent domain, is managed by Plesk + # Loop until we don't have any '.' in the string we're testing as a candidate Plesk-managed domain + + root_domain_name="$1" + doneloop=0 + + while _contains "$root_domain_name" '\.'; do + + _debug "Checking if '$root_domain_name' is managed by the Plesk server..." + + root_domain_id="$(_value "$output" | grep "$root_domain_name" | _head_n 1 | sed -E 's/^.*([0-9]+)<\/id>.*$/\1/')" + + if [ -n "$root_domain_id" ]; then + # Found a match + # SEE IMPORTANT NOTE ABOVE - THIS FUNCTION CAN RETURN HOST='', AND THAT'S OK FOR PLESK XML API WHICH ALLOWS IT. + # SO WE HANDLE IT AND DON'T PREVENT IT + sub_domain_name="$(_value "$1" | sed -E "s/\.?${root_domain_name}"'$//')" + _info "Matched host '$1' to: DOMAIN '${root_domain_name}' (Plesk ID '${root_domain_id}'), HOST '${sub_domain_name}'. Returning." + return 0 + fi + + # No match, try next parent up (if any)... + + if _contains "$root_domain_name" '\.[^.]+\.'; then + _debug "No match, trying next parent up..." + else + _debug "No match,and next parent would be a TLD..." + fi + root_domain_name="$(_valuecut 2 1000 "$root_domain_name")" + doneloop=1 + + done + + # if we get here, we failed to find a root domain match in the list of domains managed by Plesk. + # if we never ran the loop even once, $1 wasn't a 2nd level (or deeper) domain (e.g. domain.tld) and wasn't valid anyway + + if [ -z $doneloop ]; then + _err "'$1' isn't a valid domain for ACME DNS. Exiting." + else + _err "Cannot find '$1' or any parent domain of it, in Plesk." + _err "Are you sure that this domain is managed by this Plesk server?" + fi + + return 1 +} From 7c09bdc6e0dde113a241d1526ede4b9a01a7f864 Mon Sep 17 00:00:00 2001 From: stilez Date: Sun, 27 Oct 2019 16:58:58 +0000 Subject: [PATCH 084/357] renamed --- dnsapi/dns_pleskxml | 391 -------------------------------------------- 1 file changed, 391 deletions(-) delete mode 100644 dnsapi/dns_pleskxml diff --git a/dnsapi/dns_pleskxml b/dnsapi/dns_pleskxml deleted file mode 100644 index d613f8e1..00000000 --- a/dnsapi/dns_pleskxml +++ /dev/null @@ -1,391 +0,0 @@ -#!/usr/bin/env sh - -## Name: dns_pleskxml -## Created by Stilez. -## Also uses some code from PR#1832 by @romanlum (https://github.com/Neilpang/acme.sh/pull/1832/files) - -## This DNS01 method uses the Plesk XML API described at: -## https://docs.plesk.com/en-US/12.5/api-rpc/about-xml-api.28709 -## and more specifically: https://docs.plesk.com/en-US/12.5/api-rpc/reference.28784 - -## Note: a DNS ID with host = empty string is OK for this API, see -## https://docs.plesk.com/en-US/obsidian/api-rpc/about-xml-api/reference/managing-dns/managing-dns-records/adding-dns-record.34798 -## For example, to add a TXT record to DNS alias domain "acme-alias.com" would be a valid Plesk action. -## So this API module can handle such a request, if needed. - -## For ACME v2 purposes, new TXT records are appended when added, and removing one TXT record will not affect any other TXT records. - -## The plesk plugin uses the xml api to add and remvoe the dns records. Therefore the url, username -## and password have to be configured by the user before this module is called. -## -## ``` -## export pleskxml_uri="https://address-of-my-plesk-server.net:8443/enterprise/control/agent.php" -## (or probably something similar) -## export pleskxml_user="my plesk username" -## export pleskxml_pass="my plesk password" -## ``` - -## Ok, let's issue a cert now: -## ``` -## acme.sh --issue --dns dns_pleskxml -d example.com -d www.example.com -## ``` -## -## The `pleskxml_uri`, `pleskxml_user` and `pleskxml_pass` will be saved in `~/.acme.sh/account.conf` and reused when needed. - -#################### INTERNAL VARIABLES + NEWLINE + API TEMPLATES ################################## - -pleskxml_init_checks_done=0 - -# Variable containing bare newline - not a style issue -# shellcheck disable=SC1004 -NEWLINE='\ -' - -pleskxml_tplt_get_domains="" -# Get a list of domains that PLESK can manage, so we can check root domain + host for acme.sh -# Also used to test credentials and URI. -# No params. - -pleskxml_tplt_get_dns_records="%s" -# Get all DNS records for a Plesk domain ID. -# PARAM = Plesk domain id to query - -pleskxml_tplt_add_txt_record="%sTXT%s%s" -# Add a TXT record to a domain. -# PARAMS = (1) Plesk internal domain ID, (2) "hostname" for the new record, eg '_acme_challenge', (3) TXT record value - -pleskxml_tplt_rmv_dns_record="%s" -# Delete a specific TXT record from a domain. -# PARAM = the Plesk internal ID for the DNS record to be deleted - -#################### Public functions ################################## - -#Usage: dns_pleskxml_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" -dns_pleskxml_add() { - fulldomain=$1 - txtvalue=$2 - - _info "Entering dns_pleskxml_add() to add TXT record '$txtvalue' to domain '$fulldomain'..." - - # Get credentials if not already checked, and confirm we can log in to Plesk XML API - if ! _credential_check; then - return 1 - fi - - # Get root and subdomain details, and Plesk domain ID - if ! _pleskxml_get_root_domain "$fulldomain"; then - return 1 - fi - - _debug 'Credentials OK, and domain identified. Calling Plesk XML API to add TXT record' - - # printf using template in a variable - not a style issue - # shellcheck disable=SC2059 - request="$(printf "$pleskxml_tplt_add_txt_record" "$root_domain_id" "$sub_domain_name" "$txtvalue")" - if ! _call_api "$request"; then - return 1 - fi - - # OK, we should have added a TXT record. Let's check and return success if so. - # All that should be left in the result, is one section, containing okNEW_DNS_RECORD_ID - - results="$(_api_response_split "$pleskxml_prettyprint_result" 'result' '')" - - if ! _value "$results" | grep 'ok' | grep -qE '[0-9]+'; then - # Error - doesn't contain expected string. Something's wrong. - _err 'Error when calling Plesk XML API.' - _err 'The result did not contain the expected XXXXX section, or contained other values as well.' - _err 'This is unexpected: something has gone wrong.' - _err 'The full response was:\n' "$pleskxml_prettyprint_result" - return 1 - fi - - recid="$(_value "$results" | grep -E '[0-9]+' | sed -E 's/^.*([0-9]+)<\/id>.*$/\1/')" - - _info "Success. TXT record appears to be correctly added (Plesk record ID=$recid). Exiting dns_pleskxml_add()." - - return 0 -} - -#Usage: dns_pleskxml_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" -dns_pleskxml_rm() { - fulldomain=$1 - txtvalue=$2 - - _info "Entering dns_pleskxml_rm() to remove TXT record '$txtvalue' from domain '$fulldomain'..." - - # Get credentials if not already checked, and confirm we can log in to Plesk XML API - if ! _credential_check; then - return 1 - fi - - # Get root and subdomain details, and Plesk domain ID - if ! _pleskxml_get_root_domain "$fulldomain"; then - return 1 - fi - - _debug 'Credentials OK, and domain identified. Calling Plesk XML API to get list of TXT records and their IDs' - - # printf using template in a variable - not a style issue - # shellcheck disable=SC2059 - request="$(printf "$pleskxml_tplt_get_dns_records" "$root_domain_id")" - if ! _call_api "$request"; then - return 1 - fi - - # Reduce output to one line per DNS record, filtered for TXT records with a record ID only (which they should all have) - reclist="$(_api_response_split "$pleskxml_prettyprint_result" 'result' 'ok' \ - | grep "${root_domain_id}" \ - | grep -E '[0-9]+' \ - | grep 'TXT' - )" - - if [ -z "$reclist" ]; then - _err "No TXT records found for root domain ${root_domain_name} (Plesk domain ID ${root_domain_id}). Exiting." - return 1 - fi - - _debug "Got list of DNS TXT records for root domain '$root_domain_name'"':\n'"$reclist" - - recid="$(_value "$reclist" \ - | grep "$1." \ - | grep "$txtvalue" \ - | sed -E 's/(^.*|<\/id>.*$)//g' - )" - - _debug "List of DNS TXT records for host:"'\n'"$(_value "$reclist" | grep "$1.")" - - if ! _value "$recid" | grep -Eq '^[0-9]+$'; then - _err "DNS records for root domain '${root_domain_name}' (Plesk ID ${root_domain_id}) + host '${sub_domain_name}' do not contain the TXT record '${txtvalue}'" - _err "Cannot delete TXT record. Exiting." - return 1 - fi - - _debug "Found Plesk record ID for target text string '${txtvalue}': ID=${recid}" - _debug 'Calling Plesk XML API to remove TXT record' - - # printf using template in a variable - not a style issue - # shellcheck disable=SC2059 - request="$(printf "$pleskxml_tplt_rmv_dns_record" "$recid")" - if ! _call_api "$request"; then - return 1 - fi - - # OK, we should have removed a TXT record. Let's check and return success if so. - # All that should be left in the result, is one section, containing okPLESK_DELETED_DNS_RECORD_ID - - results="$(_api_response_split "$pleskxml_prettyprint_result" 'result' '')" - - if ! _value "$results" | grep 'ok' | grep -qE '[0-9]+'; then - # Error - doesn't contain expected string. Something's wrong. - _err 'Error when calling Plesk XML API.' - _err 'The result did not contain the expected XXXXX section, or contained other values as well.' - _err 'This is unexpected: something has gone wrong.' - _err 'The full response was:\n' "$pleskxml_prettyprint_result" - return 1 - fi - - _info "Success. TXT record appears to be correctly removed. Exiting dns_pleskxml_rm()." - return 0 -} - -#################### Private functions below ################################## - -# Outputs value of a variable without additional newlines etc -_value() { - printf '%s' "$1" -} - -# Outputs value of a variable (FQDN) and cuts it at 2 specified '.' delimiters, returning the text in between -# $1, $2 = where to cut -# $3 = FQDN -_valuecut() { - printf '%s' "$3" | cut -d . -f "${1}-${2}" -} - -# Cleans up an API response, splits it "one line per item in the response" and greps for a string that in the context, identifies "useful" lines -# $1 - result string from API -# $2 - tag to resplit on (usually "result" or "domain") -# $3 - regex to recognise useful return lines -_api_response_split() { - printf '%s' "$1" \ - | sed -E 's/(^[[:space:]]+|[[:space:]]+$)//g' \ - | tr -d '\n\r' \ - | sed -E "s/<\/?$2>/${NEWLINE}/g" \ - | grep -E "$3" -} - -# Calls Plesk XML API, and checks results for obvious issues -_call_api() { - request="$1" - errtext='' - - _debug 'Entered _call_api(). Calling Plesk XML API with request:\n' "'${request}'" - - export _H1="HTTP_AUTH_LOGIN: $pleskxml_user" - export _H2="HTTP_AUTH_PASSWD: $pleskxml_pass" - export _H3="content-Type: text/xml" - export _H4="HTTP_PRETTY_PRINT: true" - pleskxml_prettyprint_result="$(_post "${request}" "$pleskxml_uri" "" "POST")" - pleskxml_retcode="$?" - _debug "acme _post() returned retcode=$pleskxml_retcode. Literal response:" '\n' "'${pleskxml_prettyprint_result}'" - - # Detect any that isn't "ok". None of the used calls should fail if the API is working correctly. - # Also detect if there simply aren't any status lines (null result?) and report that, as well. - - statuslines="$(echo "$pleskxml_prettyprint_result" | grep -E '^[[:space:]]*[^<]*[[:space:]]*$')" - - if _value "$statuslines" | grep -qv 'ok'; then - - # We have some status lines that aren't "ok". Get the details - errtext="$(_value "$pleskxml_prettyprint_result" \ - | grep -iE "(||)" \ - | sed -E 's/(^[[:space:]]+|<\/[a-z]+$)//g' \ - | sed -E 's/^<([a-z]+)>/\1: /' - )" - - elif ! _value "$statuslines" | grep -q 'ok'; then - - # We have no status lines at all. Results are empty - errtext='The Plesk XML API unexpectedly returned an empty set of results for this call.' - - fi - - if [ "$pleskxml_retcode" -ne 0 ] || [ "$errtext" != "" ]; then - _err "The Plesk XML API call failed." - _err "The return code for the POST request was $pleskxml_retcode (0=success)." - if [ "$errtext" != "" ]; then - _err 'Status and error messages received from the Plesk server:\n' "$errtext" - else - _err "No additional error messages were received back from the Plesk server" - fi - return 1 - fi - - _debug "Leaving _call_api(). Successful call." - - return 0 -} - -# Startup checks (credentials, URI) -_credential_check() { - _debug "Checking Plesk XML API login credentials and URI..." - - if [ "$pleskxml_init_checks_done" -eq 1 ]; then - _debug "Initial checks already done, no need to repeat. Skipped." - return 0 - fi - - pleskxml_user="${pleskxml_user:-$(_readaccountconf_mutable pleskxml_user)}" - pleskxml_pass="${pleskxml_pass:-$(_readaccountconf_mutable pleskxml_pass)}" - pleskxml_uri="${pleskxml_uri:-$(_readaccountconf_mutable pleskxml_uri)}" - - _debug "Credentials - User: '${pleskxml_user}' Passwd: ****** URI: '${pleskxml_uri}'" - - if [ -z "$pleskxml_user" ] || [ -z "$pleskxml_pass" ] || [ -z "$pleskxml_uri" ]; then - pleskxml_user="" - pleskxml_pass="" - pleskxml_uri="" - _err "You didn't specify one or more of the Plesk XML API username, password, or URI." - _err "Please create these and try again." - _err "Instructions are in the module source code." - return 1 - fi - - # Test the API is usable, by trying to read the list of managed domains... - _call_api "$pleskxml_tplt_get_domains" - if [ "$pleskxml_retcode" -ne 0 ]; then - _err '\nFailed to access Plesk XML API.' - _err "Please check your login credentials and Plesk URI, and that the URI is reachable, and try again." - return 1 - fi - - _saveaccountconf_mutable pleskxml_uri "$pleskxml_uri" - _saveaccountconf_mutable pleskxml_user "$pleskxml_user" - _saveaccountconf_mutable pleskxml_pass "$pleskxml_pass" - - _debug "Test login to Plesk XML API successful. Login credentials and URI successfully saved to the acme.sh configuration file for future use." - - pleskxml_init_checks_done=1 - - return 0 -} - -# For a FQDN, identify the root domain managed by Plesk, its domain ID in Plesk, and the host if any. - -# IMPORTANT NOTE: a result with host = empty string is OK for this API, see -# https://docs.plesk.com/en-US/obsidian/api-rpc/about-xml-api/reference/managing-dns/managing-dns-records/adding-dns-record.34798 -# See notes at top of this file - -_pleskxml_get_root_domain() { - _debug "Identifying DNS root domain for '$1' that is managed by the Plesk account." - - # test if the domain as provided is valid for splitting. - - if _value "$root_domain_name" | grep -qvE '^[^.]+\.[^.]+\.[^.]'; then - _err "Invalid domain. The ACME domain must contain at least two parts (aa.bb) to identify a domain and tld for the TXT record." - return 1 - fi - - _debug "Querying Plesk server for list of managed domains..." - - _call_api "$pleskxml_tplt_get_domains" - if [ "$pleskxml_retcode" -ne 0 ]; then - return 1 - fi - - # Generate a crude list of domains known to this Plesk account. - # We convert tags to so it'll flag on a hit with either or fields, - # for non-Western character sets. - # Output will be one line per known domain, containing 2 tages and a single tag - # We don't actually need to check for type, name, *and* id, but it guarantees only usable lines are returned. - - output="$(_api_response_split "$pleskxml_prettyprint_result" 'domain' 'domain' | sed -E 's/<(\/?)ascii-name>/<\1name>/g' | grep '' | grep '')" - - _debug 'Domains managed by Plesk server are (ignore the hacked output):\n' "$output" - - # loop and test if domain, or any parent domain, is managed by Plesk - # Loop until we don't have any '.' in the string we're testing as a candidate Plesk-managed domain - - root_domain_name="$1" - doneloop=0 - - while _contains "$root_domain_name" '\.'; do - - _debug "Checking if '$root_domain_name' is managed by the Plesk server..." - - root_domain_id="$(_value "$output" | grep "$root_domain_name" | _head_n 1 | sed -E 's/^.*([0-9]+)<\/id>.*$/\1/')" - - if [ -n "$root_domain_id" ]; then - # Found a match - # SEE IMPORTANT NOTE ABOVE - THIS FUNCTION CAN RETURN HOST='', AND THAT'S OK FOR PLESK XML API WHICH ALLOWS IT. - # SO WE HANDLE IT AND DON'T PREVENT IT - sub_domain_name="$(_value "$1" | sed -E "s/\.?${root_domain_name}"'$//')" - _info "Matched host '$1' to: DOMAIN '${root_domain_name}' (Plesk ID '${root_domain_id}'), HOST '${sub_domain_name}'. Returning." - return 0 - fi - - # No match, try next parent up (if any)... - - if _contains "$root_domain_name" '\.[^.]+\.'; then - _debug "No match, trying next parent up..." - else - _debug "No match,and next parent would be a TLD..." - fi - root_domain_name="$(_valuecut 2 1000 "$root_domain_name")" - doneloop=1 - - done - - # if we get here, we failed to find a root domain match in the list of domains managed by Plesk. - # if we never ran the loop even once, $1 wasn't a 2nd level (or deeper) domain (e.g. domain.tld) and wasn't valid anyway - - if [ -z $doneloop ]; then - _err "'$1' isn't a valid domain for ACME DNS. Exiting." - else - _err "Cannot find '$1' or any parent domain of it, in Plesk." - _err "Are you sure that this domain is managed by this Plesk server?" - fi - - return 1 -} From a22d3b239070ddc573a283bf2a709e68a12d2085 Mon Sep 17 00:00:00 2001 From: scottkof Date: Mon, 28 Oct 2019 06:32:08 -0700 Subject: [PATCH 085/357] Switch from `sleep` to `_sleep` --- dnsapi/dns_aws.sh | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/dnsapi/dns_aws.sh b/dnsapi/dns_aws.sh index 54b1bb3a..6db87666 100755 --- a/dnsapi/dns_aws.sh +++ b/dnsapi/dns_aws.sh @@ -6,7 +6,7 @@ #AWS_SECRET_ACCESS_KEY="xxxxxxx" #This is the Amazon Route53 api wrapper for acme.sh -#All `sleep` commands are included to avoid Route53 throttling, see +#All `_sleep` commands are included to avoid Route53 throttling, see #https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/DNSLimitations.html#limits-api-requests AWS_HOST="route53.amazonaws.com" @@ -45,7 +45,7 @@ dns_aws_add() { _debug "First detect the root zone" if ! _get_root "$fulldomain"; then _err "invalid domain" - sleep 1 + _sleep 1 return 1 fi _debug _domain_id "$_domain_id" @@ -54,7 +54,7 @@ dns_aws_add() { _info "Getting existing records for $fulldomain" if ! aws_rest GET "2013-04-01$_domain_id/rrset" "name=$fulldomain&type=TXT"; then - sleep 1 + _sleep 1 return 1 fi @@ -67,7 +67,7 @@ dns_aws_add() { if [ "$_resource_record" ] && _contains "$response" "$txtvalue"; then _info "The TXT record already exists. Skipping." - sleep 1 + _sleep 1 return 0 fi @@ -77,10 +77,10 @@ dns_aws_add() { if aws_rest POST "2013-04-01$_domain_id/rrset/" "" "$_aws_tmpl_xml" && _contains "$response" "ChangeResourceRecordSetsResponse"; then _info "TXT record updated successfully." - sleep 1 + _sleep 1 return 0 fi - sleep 1 + _sleep 1 return 1 } @@ -99,7 +99,7 @@ dns_aws_rm() { _debug "First detect the root zone" if ! _get_root "$fulldomain"; then _err "invalid domain" - sleep 1 + _sleep 1 return 1 fi _debug _domain_id "$_domain_id" @@ -108,7 +108,7 @@ dns_aws_rm() { _info "Getting existing records for $fulldomain" if ! aws_rest GET "2013-04-01$_domain_id/rrset" "name=$fulldomain&type=TXT"; then - sleep 1 + _sleep 1 return 1 fi @@ -117,7 +117,7 @@ dns_aws_rm() { _debug "_resource_record" "$_resource_record" else _debug "no records exist, skip" - sleep 1 + _sleep 1 return 0 fi @@ -125,10 +125,10 @@ dns_aws_rm() { if aws_rest POST "2013-04-01$_domain_id/rrset/" "" "$_aws_tmpl_xml" && _contains "$response" "ChangeResourceRecordSetsResponse"; then _info "TXT record deleted successfully." - sleep 1 + _sleep 1 return 0 fi - sleep 1 + _sleep 1 return 1 } From d7affad05981f3fdc59ecf1f30e4455f06cc9f5a Mon Sep 17 00:00:00 2001 From: stilez Date: Tue, 29 Oct 2019 10:30:00 +0000 Subject: [PATCH 086/357] various small improves --- dnsapi/dns_pleskxml.sh | 71 +++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index 25d1e6dc..bd6eaa87 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -189,7 +189,7 @@ dns_pleskxml_rm() { return 0 } -#################### Private functions below ################################## +#################### Private functions below (utility functions) ################################## # Outputs value of a variable without additional newlines etc _value() { @@ -203,6 +203,12 @@ _valuecut() { printf '%s' "$3" | cut -d . -f "${1}-${2}" } +# Counts '.' present in a domain name +# $1 = domain name +_countdots() { + _value "$1" | tr -dc '.' | wc -c +} + # Cleans up an API response, splits it "one line per item in the response" and greps for a string that in the context, identifies "useful" lines # $1 - result string from API # $2 - tag to resplit on (usually "result" or "domain") @@ -215,6 +221,8 @@ _api_response_split() { | grep -E "$3" } +#################### Private functions below (DNS functions) ################################## + # Calls Plesk XML API, and checks results for obvious issues _call_api() { request="$1" @@ -228,7 +236,7 @@ _call_api() { export _H4="HTTP_PRETTY_PRINT: true" pleskxml_prettyprint_result="$(_post "${request}" "$pleskxml_uri" "" "POST")" pleskxml_retcode="$?" - _debug "acme _post() returned retcode=$pleskxml_retcode. Literal response:" '\n' "'${pleskxml_prettyprint_result}'" + _debug 'The responses from the Plesk XML server were:\n' "retcode=$pleskxml_retcode. Literal response:"'\n' "'$pleskxml_prettyprint_result'" # Detect any that isn't "ok". None of the used calls should fail if the API is working correctly. # Also detect if there simply aren't any status lines (null result?) and report that, as well. @@ -239,9 +247,9 @@ _call_api() { # We have some status lines that aren't "ok". Get the details errtext="$(_value "$pleskxml_prettyprint_result" \ - | grep -iE "(||)" \ - | sed -E 's/(^[[:space:]]+|<\/[a-z]+$)//g' \ - | sed -E 's/^<([a-z]+)>/\1: /' + | grep -E "(||)" \ + | sed -E 's/^<(status|errcode|errtext)>/\1: /' \ + | sed -E 's/(^[[:space:]]+|<\/(status|errcode|errtext)>$)//g' \ )" elif ! _value "$statuslines" | grep -q 'ok'; then @@ -252,14 +260,23 @@ _call_api() { fi if [ "$pleskxml_retcode" -ne 0 ] || [ "$errtext" != "" ]; then - _err "The Plesk XML API call failed." - _err "The return code for the POST request was $pleskxml_retcode (0=success)." + # Call failed, for reasons either in the retcode or the response text... + + if [ "$pleskxml_retcode" -eq 0 ]; then + _err "The POST request was successfully sent to the Plesk server." + else + _err "The return code for the POST request was $pleskxml_retcode (non-zero = could not submit request to server)." + fi + if [ "$errtext" != "" ]; then - _err 'Status and error messages received from the Plesk server:\n' "$errtext" + _err 'The error responses received from the Plesk server were:\n' "$errtext" else _err "No additional error messages were received back from the Plesk server" fi + + _err "The Plesk XML API call failed." return 1 + fi _debug "Leaving _call_api(). Successful call." @@ -319,10 +336,12 @@ _credential_check() { _pleskxml_get_root_domain() { _debug "Identifying DNS root domain for '$1' that is managed by the Plesk account." + original_full_domain_name="$1" + root_domain_name="$1" # test if the domain as provided is valid for splitting. - if _value "$root_domain_name" | grep -qvE '^[^.]+\.[^.]+\.[^.]'; then + if ! _countdots "$root_domain_name"; then _err "Invalid domain. The ACME domain must contain at least two parts (aa.bb) to identify a domain and tld for the TXT record." return 1 fi @@ -347,10 +366,7 @@ _pleskxml_get_root_domain() { # loop and test if domain, or any parent domain, is managed by Plesk # Loop until we don't have any '.' in the string we're testing as a candidate Plesk-managed domain - root_domain_name="$1" - doneloop=0 - - while _contains "$root_domain_name" '\.'; do + while true; do _debug "Checking if '$root_domain_name' is managed by the Plesk server..." @@ -360,32 +376,23 @@ _pleskxml_get_root_domain() { # Found a match # SEE IMPORTANT NOTE ABOVE - THIS FUNCTION CAN RETURN HOST='', AND THAT'S OK FOR PLESK XML API WHICH ALLOWS IT. # SO WE HANDLE IT AND DON'T PREVENT IT - sub_domain_name="$(_value "$1" | sed -E "s/\.?${root_domain_name}"'$//')" - _info "Matched host '$1' to: DOMAIN '${root_domain_name}' (Plesk ID '${root_domain_id}'), HOST '${sub_domain_name}'. Returning." + sub_domain_name="$(_value "$original_full_domain_name" | sed -E "s/\.?${root_domain_name}"'$//')" + _info "Success. Matched host '$original_full_domain_name' to: DOMAIN '${root_domain_name}' (Plesk ID '${root_domain_id}'), HOST '${sub_domain_name}'. Returning." return 0 fi # No match, try next parent up (if any)... - if _contains "$root_domain_name" '\.[^.]+\.'; then - _debug "No match, trying next parent up..." - else - _debug "No match,and next parent would be a TLD..." - fi root_domain_name="$(_valuecut 2 1000 "$root_domain_name")" - doneloop=1 - done + if ! _countdots "$root_domain_name"; then + _debug "No match, and next parent would be a TLD..." + _err "Cannot find '$original_full_domain_name' or any parent domain of it, in Plesk." + _err "Are you sure that this domain is managed by this Plesk server?" + return 1 + fi - # if we get here, we failed to find a root domain match in the list of domains managed by Plesk. - # if we never ran the loop even once, $1 wasn't a 2nd level (or deeper) domain (e.g. domain.tld) and wasn't valid anyway + _debug "No match, trying next parent up..." - if [ -z $doneloop ]; then - _err "'$1' isn't a valid domain for ACME DNS. Exiting." - else - _err "Cannot find '$1' or any parent domain of it, in Plesk." - _err "Are you sure that this domain is managed by this Plesk server?" - fi - - return 1 + done } From b7c3df455e275a6fa0556d178c48f944666410bf Mon Sep 17 00:00:00 2001 From: stilez Date: Wed, 30 Oct 2019 09:38:03 +0000 Subject: [PATCH 087/357] travis fix --- dnsapi/dns_pleskxml.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index bd6eaa87..aa1da6f4 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -249,7 +249,7 @@ _call_api() { errtext="$(_value "$pleskxml_prettyprint_result" \ | grep -E "(||)" \ | sed -E 's/^<(status|errcode|errtext)>/\1: /' \ - | sed -E 's/(^[[:space:]]+|<\/(status|errcode|errtext)>$)//g' \ + | sed -E 's/(^[[:space:]]+|<\/(status|errcode|errtext)>$)//g' )" elif ! _value "$statuslines" | grep -q 'ok'; then From 05ced9fbc4edf0c2d3bbe9913209e6c750702cad Mon Sep 17 00:00:00 2001 From: stilez Date: Wed, 30 Oct 2019 09:53:40 +0000 Subject: [PATCH 088/357] edit a comment --- dnsapi/dns_pleskxml.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index aa1da6f4..24650d10 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -4,7 +4,7 @@ ## Created by Stilez. ## Also uses some code from PR#1832 by @romanlum (https://github.com/Neilpang/acme.sh/pull/1832/files) -## This DNS01 method uses the Plesk XML API described at: +## This DNS-01 method uses the Plesk XML API described at: ## https://docs.plesk.com/en-US/12.5/api-rpc/about-xml-api.28709 ## and more specifically: https://docs.plesk.com/en-US/12.5/api-rpc/reference.28784 @@ -15,8 +15,8 @@ ## For ACME v2 purposes, new TXT records are appended when added, and removing one TXT record will not affect any other TXT records. -## The plesk plugin uses the xml api to add and remvoe the dns records. Therefore the url, username -## and password have to be configured by the user before this module is called. +## The user credentials (username+password) and URL/URI for the Plesk XML API must be set by the user +## before this module is called (case sensitive): ## ## ``` ## export pleskxml_uri="https://address-of-my-plesk-server.net:8443/enterprise/control/agent.php" From 3441bd0e7c476a5add8dbfec730b5fa25b7a9f7e Mon Sep 17 00:00:00 2001 From: stilez Date: Wed, 30 Oct 2019 10:22:04 +0000 Subject: [PATCH 089/357] improve _err message and remove a dubious _debug message. --- dnsapi/dns_pleskxml.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index 24650d10..8a957e40 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -297,15 +297,13 @@ _credential_check() { pleskxml_pass="${pleskxml_pass:-$(_readaccountconf_mutable pleskxml_pass)}" pleskxml_uri="${pleskxml_uri:-$(_readaccountconf_mutable pleskxml_uri)}" - _debug "Credentials - User: '${pleskxml_user}' Passwd: ****** URI: '${pleskxml_uri}'" - if [ -z "$pleskxml_user" ] || [ -z "$pleskxml_pass" ] || [ -z "$pleskxml_uri" ]; then pleskxml_user="" pleskxml_pass="" pleskxml_uri="" _err "You didn't specify one or more of the Plesk XML API username, password, or URI." _err "Please create these and try again." - _err "Instructions are in the module source code." + _err "Instructions are in the 'dns_pleskxml' plugin source code or in the acme.sh documentation." return 1 fi From 2422e0b481b74e008fc995afd4e1994d6f0817e4 Mon Sep 17 00:00:00 2001 From: stilez Date: Wed, 30 Oct 2019 17:01:06 +0000 Subject: [PATCH 090/357] grep -E and sed -E --- dnsapi/dns_pleskxml.sh | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index 8a957e40..03c58534 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -91,7 +91,7 @@ dns_pleskxml_add() { results="$(_api_response_split "$pleskxml_prettyprint_result" 'result' '')" - if ! _value "$results" | grep 'ok' | grep -qE '[0-9]+'; then + if ! _value "$results" | grep 'ok' | egrep -q '[0-9]+'; then # Error - doesn't contain expected string. Something's wrong. _err 'Error when calling Plesk XML API.' _err 'The result did not contain the expected XXXXX section, or contained other values as well.' @@ -100,7 +100,7 @@ dns_pleskxml_add() { return 1 fi - recid="$(_value "$results" | grep -E '[0-9]+' | sed -E 's/^.*([0-9]+)<\/id>.*$/\1/')" + recid="$(_value "$results" | egrep '[0-9]+' | sed -r 's/^.*([0-9]+)<\/id>.*$/\1/')" _info "Success. TXT record appears to be correctly added (Plesk record ID=$recid). Exiting dns_pleskxml_add()." @@ -136,7 +136,7 @@ dns_pleskxml_rm() { # Reduce output to one line per DNS record, filtered for TXT records with a record ID only (which they should all have) reclist="$(_api_response_split "$pleskxml_prettyprint_result" 'result' 'ok' \ | grep "${root_domain_id}" \ - | grep -E '[0-9]+' \ + | egrep '[0-9]+' \ | grep 'TXT' )" @@ -150,12 +150,12 @@ dns_pleskxml_rm() { recid="$(_value "$reclist" \ | grep "$1." \ | grep "$txtvalue" \ - | sed -E 's/(^.*|<\/id>.*$)//g' + | sed -r 's/(^.*|<\/id>.*$)//g' )" _debug "List of DNS TXT records for host:"'\n'"$(_value "$reclist" | grep "$1.")" - if ! _value "$recid" | grep -Eq '^[0-9]+$'; then + if ! _value "$recid" | egrep -q '^[0-9]+$'; then _err "DNS records for root domain '${root_domain_name}' (Plesk ID ${root_domain_id}) + host '${sub_domain_name}' do not contain the TXT record '${txtvalue}'" _err "Cannot delete TXT record. Exiting." return 1 @@ -176,7 +176,7 @@ dns_pleskxml_rm() { results="$(_api_response_split "$pleskxml_prettyprint_result" 'result' '')" - if ! _value "$results" | grep 'ok' | grep -qE '[0-9]+'; then + if ! _value "$results" | grep 'ok' | egrep -q '[0-9]+'; then # Error - doesn't contain expected string. Something's wrong. _err 'Error when calling Plesk XML API.' _err 'The result did not contain the expected XXXXX section, or contained other values as well.' @@ -215,10 +215,10 @@ _countdots() { # $3 - regex to recognise useful return lines _api_response_split() { printf '%s' "$1" \ - | sed -E 's/(^[[:space:]]+|[[:space:]]+$)//g' \ + | sed -r 's/(^[[:space:]]+|[[:space:]]+$)//g' \ | tr -d '\n\r' \ - | sed -E "s/<\/?$2>/${NEWLINE}/g" \ - | grep -E "$3" + | sed -r "s/<\/?$2>/${NEWLINE}/g" \ + | egrep "$3" } #################### Private functions below (DNS functions) ################################## @@ -241,15 +241,15 @@ _call_api() { # Detect any that isn't "ok". None of the used calls should fail if the API is working correctly. # Also detect if there simply aren't any status lines (null result?) and report that, as well. - statuslines="$(echo "$pleskxml_prettyprint_result" | grep -E '^[[:space:]]*[^<]*[[:space:]]*$')" + statuslines="$(echo "$pleskxml_prettyprint_result" | egrep '^[[:space:]]*[^<]*[[:space:]]*$')" if _value "$statuslines" | grep -qv 'ok'; then # We have some status lines that aren't "ok". Get the details errtext="$(_value "$pleskxml_prettyprint_result" \ - | grep -E "(||)" \ - | sed -E 's/^<(status|errcode|errtext)>/\1: /' \ - | sed -E 's/(^[[:space:]]+|<\/(status|errcode|errtext)>$)//g' + | egrep "(||)" \ + | sed -r 's/^<(status|errcode|errtext)>/\1: /' \ + | sed -r 's/(^[[:space:]]+|<\/(status|errcode|errtext)>$)//g' )" elif ! _value "$statuslines" | grep -q 'ok'; then @@ -357,7 +357,7 @@ _pleskxml_get_root_domain() { # Output will be one line per known domain, containing 2 tages and a single tag # We don't actually need to check for type, name, *and* id, but it guarantees only usable lines are returned. - output="$(_api_response_split "$pleskxml_prettyprint_result" 'domain' 'domain' | sed -E 's/<(\/?)ascii-name>/<\1name>/g' | grep '' | grep '')" + output="$(_api_response_split "$pleskxml_prettyprint_result" 'domain' 'domain' | sed -r 's/<(\/?)ascii-name>/<\1name>/g' | grep '' | grep '')" _debug 'Domains managed by Plesk server are (ignore the hacked output):\n' "$output" @@ -368,13 +368,13 @@ _pleskxml_get_root_domain() { _debug "Checking if '$root_domain_name' is managed by the Plesk server..." - root_domain_id="$(_value "$output" | grep "$root_domain_name" | _head_n 1 | sed -E 's/^.*([0-9]+)<\/id>.*$/\1/')" + root_domain_id="$(_value "$output" | grep "$root_domain_name" | _head_n 1 | sed -r 's/^.*([0-9]+)<\/id>.*$/\1/')" if [ -n "$root_domain_id" ]; then # Found a match # SEE IMPORTANT NOTE ABOVE - THIS FUNCTION CAN RETURN HOST='', AND THAT'S OK FOR PLESK XML API WHICH ALLOWS IT. # SO WE HANDLE IT AND DON'T PREVENT IT - sub_domain_name="$(_value "$original_full_domain_name" | sed -E "s/\.?${root_domain_name}"'$//')" + sub_domain_name="$(_value "$original_full_domain_name" | sed -r "s/\.?${root_domain_name}"'$//')" _info "Success. Matched host '$original_full_domain_name' to: DOMAIN '${root_domain_name}' (Plesk ID '${root_domain_id}'), HOST '${sub_domain_name}'. Returning." return 0 fi From a32b95544ba8aa385251f757940c93f3fef266c0 Mon Sep 17 00:00:00 2001 From: stilez Date: Wed, 30 Oct 2019 17:06:03 +0000 Subject: [PATCH 091/357] [[:space:]] -> " " --- dnsapi/dns_pleskxml.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index 03c58534..12f56316 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -215,7 +215,7 @@ _countdots() { # $3 - regex to recognise useful return lines _api_response_split() { printf '%s' "$1" \ - | sed -r 's/(^[[:space:]]+|[[:space:]]+$)//g' \ + | sed -r 's/(^ +| +$)//g' \ | tr -d '\n\r' \ | sed -r "s/<\/?$2>/${NEWLINE}/g" \ | egrep "$3" @@ -241,15 +241,15 @@ _call_api() { # Detect any that isn't "ok". None of the used calls should fail if the API is working correctly. # Also detect if there simply aren't any status lines (null result?) and report that, as well. - statuslines="$(echo "$pleskxml_prettyprint_result" | egrep '^[[:space:]]*[^<]*[[:space:]]*$')" + statuslines="$(echo "$pleskxml_prettyprint_result" | egrep '^ *[^<]* *$')" if _value "$statuslines" | grep -qv 'ok'; then # We have some status lines that aren't "ok". Get the details errtext="$(_value "$pleskxml_prettyprint_result" \ | egrep "(||)" \ - | sed -r 's/^<(status|errcode|errtext)>/\1: /' \ - | sed -r 's/(^[[:space:]]+|<\/(status|errcode|errtext)>$)//g' + | sed -r 's/^ *<(status|errcode|errtext)>/\1: /' \ + | sed -r 's/<\/(status|errcode|errtext)>$//g' )" elif ! _value "$statuslines" | grep -q 'ok'; then From dca6a4bbd57eed4b87f24cb7f1644fb5a51c2327 Mon Sep 17 00:00:00 2001 From: peterkelm Date: Wed, 30 Oct 2019 20:51:16 +0100 Subject: [PATCH 092/357] minor formatting changes --- dnsapi/dns_variomedia.sh | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/dnsapi/dns_variomedia.sh b/dnsapi/dns_variomedia.sh index 8588d7c8..ecc9ea4c 100644 --- a/dnsapi/dns_variomedia.sh +++ b/dnsapi/dns_variomedia.sh @@ -5,9 +5,9 @@ VARIOMEDIA_API="https://api.variomedia.de" -######## Public functions ##################### +######## Public functions ##################### -#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_variomedia_add() { fulldomain=$1 txtvalue=$2 @@ -69,7 +69,7 @@ dns_variomedia_rm() { return 1 fi - _record_id="$(echo $response | cut -d '[' -f2 | cut -d']' -f1 | sed 's/},[ \t]*{/\},§\{/g' | tr § '\n' | grep $_sub_domain | grep $txtvalue | sed 's/^{//;s/}[,]?$//' | tr , '\n' | tr -d '\"' | grep ^id | cut -d : -f2 | tr -d ' ')" + _record_id="$(echo $response | cut -d '[' -f2 | cut -d']' -f1 | sed 's/},[ \t]*{/\},§\{/g' | tr § '\n' | grep "$_sub_domain" | grep "$txtvalue" | sed 's/^{//;s/}[,]?$//' | tr , '\n' | tr -d '\"' | grep ^id | cut -d : -f2 | tr -d ' ')" _debug _record_id "$_record_id" if [ "$_record_id" ]; then _info "Successfully retrieved the record id for ACME challenge." @@ -87,7 +87,7 @@ dns_variomedia_rm() { return 0 } -#################### Private functions below ################################## +#################### Private functions below ################################## #_acme-challenge.www.domain.com #returns # _sub_domain=_acme-challenge.www @@ -117,7 +117,6 @@ _get_root() { done _debug "root domain not found" - return 1 } From 343d7df57c366fe594edf8f4a523611a18cb0ac2 Mon Sep 17 00:00:00 2001 From: stilez Date: Wed, 30 Oct 2019 22:11:16 +0000 Subject: [PATCH 093/357] shellcheck directive --- dnsapi/dns_pleskxml.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index 12f56316..c12b2eeb 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -1,5 +1,9 @@ #!/usr/bin/env sh +# Globally disable this shellcheck error. +# Shellcheck errors on egrep ("deprecated"), but acme.sh uses egrep for compatibility. +# shellcheck disable=SC2196 + ## Name: dns_pleskxml.sh ## Created by Stilez. ## Also uses some code from PR#1832 by @romanlum (https://github.com/Neilpang/acme.sh/pull/1832/files) From bec26ce754fb575a6969c917cd8fd5fa212a800e Mon Sep 17 00:00:00 2001 From: peterkelm Date: Thu, 31 Oct 2019 09:03:35 +0100 Subject: [PATCH 094/357] Shellcheck'd --- dnsapi/dns_variomedia.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_variomedia.sh b/dnsapi/dns_variomedia.sh index ecc9ea4c..729cda5e 100644 --- a/dnsapi/dns_variomedia.sh +++ b/dnsapi/dns_variomedia.sh @@ -69,7 +69,7 @@ dns_variomedia_rm() { return 1 fi - _record_id="$(echo $response | cut -d '[' -f2 | cut -d']' -f1 | sed 's/},[ \t]*{/\},§\{/g' | tr § '\n' | grep "$_sub_domain" | grep "$txtvalue" | sed 's/^{//;s/}[,]?$//' | tr , '\n' | tr -d '\"' | grep ^id | cut -d : -f2 | tr -d ' ')" + _record_id="$(echo "$response" | cut -d '[' -f2 | cut -d']' -f1 | sed 's/},[ \t]*{/\},§\{/g' | tr § '\n' | grep "$_sub_domain" | grep "$txtvalue" | sed 's/^{//;s/}[,]?$//' | tr , '\n' | tr -d '\"' | grep ^id | cut -d : -f2 | tr -d ' ')" _debug _record_id "$_record_id" if [ "$_record_id" ]; then _info "Successfully retrieved the record id for ACME challenge." From fee9baca895cecf5cb7a6d94791b655f09c73684 Mon Sep 17 00:00:00 2001 From: Johann Richard <189003+johannrichard@users.noreply.github.com> Date: Fri, 1 Nov 2019 17:59:40 +0100 Subject: [PATCH 095/357] Add openssh package * `acme.sh`'s `ssh.sh` is probably one of the hooks that's most versatile * By default, it's not installed on `alpine` docker images and therefore is lacking in the `acme.sh` docker image * This change adds the `openssh` package and therefore the `ssh` and associated commands --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index a6e37999..02dd5030 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,6 +3,7 @@ FROM alpine:3.10 RUN apk update -f \ && apk --no-cache add -f \ openssl \ + openssh \ coreutils \ bind-tools \ curl \ From 5698bec6213d8c1ffa8c3c30b1587c8f982638c8 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 2 Nov 2019 09:48:41 +0800 Subject: [PATCH 096/357] fix https://github.com/Neilpang/acme.sh/issues/2566 --- acme.sh | 2 +- notify/dingtalk.sh | 69 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 notify/dingtalk.sh diff --git a/acme.sh b/acme.sh index 07dc63d2..78604337 100755 --- a/acme.sh +++ b/acme.sh @@ -6070,7 +6070,7 @@ _send_notify() { _set_notify_hook() { _nhooks="$1" - _test_subject="Hello, this is notification from $PROJECT_NAME" + _test_subject="Hello, this is a notification from $PROJECT_NAME" _test_content="If you receive this message, your notification works." _send_notify "$_test_subject" "$_test_content" "$_nhooks" 0 diff --git a/notify/dingtalk.sh b/notify/dingtalk.sh new file mode 100644 index 00000000..7d354da2 --- /dev/null +++ b/notify/dingtalk.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env sh + +#Support dingtalk webhooks api + +#DINGTALK_WEBHOOK="xxxx" + +#optional +#DINGTALK_KEYWORD="yyyy" + +#DINGTALK_SIGNING_KEY="SEC08ffdbd403cbc3fc8a65xxxxxxxxxxxxxxxxxxxx" + +# subject content statusCode +dingtalk_send() { + _subject="$1" + _content="$2" + _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped + _debug "_subject" "$_subject" + _debug "_content" "$_content" + _debug "_statusCode" "$_statusCode" + + DINGTALK_WEBHOOK="${DINGTALK_WEBHOOK:-$(_readaccountconf_mutable DINGTALK_WEBHOOK)}" + if [ -z "$DINGTALK_WEBHOOK" ]; then + DINGTALK_WEBHOOK="" + _err "You didn't specify a dingtalk webhooks DINGTALK_WEBHOOK yet." + _err "You can get yours from https://dingtalk.com" + return 1 + fi + _saveaccountconf_mutable DINGTALK_WEBHOOK "$DINGTALK_WEBHOOK" + + DINGTALK_KEYWORD="${DINGTALK_KEYWORD:-$(_readaccountconf_mutable DINGTALK_KEYWORD)}" + if [ "$DINGTALK_KEYWORD" ]; then + _saveaccountconf_mutable DINGTALK_KEYWORD "$DINGTALK_KEYWORD" + fi + +# DINGTALK_SIGNING_KEY="${DINGTALK_SIGNING_KEY:-$(_readaccountconf_mutable DINGTALK_SIGNING_KEY)}" +# if [ -z "$DINGTALK_SIGNING_KEY" ]; then +# DINGTALK_SIGNING_KEY="value1" +# _info "The DINGTALK_SIGNING_KEY is not set, so use the default value1 as key." +# elif ! _hasfield "$_IFTTT_AVAIL_MSG_KEYS" "$DINGTALK_SIGNING_KEY"; then +# _err "The DINGTALK_SIGNING_KEY \"$DINGTALK_SIGNING_KEY\" is not available, should be one of $_IFTTT_AVAIL_MSG_KEYS" +# DINGTALK_SIGNING_KEY="" +# return 1 +# else +# _saveaccountconf_mutable DINGTALK_SIGNING_KEY "$DINGTALK_SIGNING_KEY" +# fi + +# if [ "$DINGTALK_SIGNING_KEY" = "$IFTTT_CONTENT_KEY" ]; then +# DINGTALK_SIGNING_KEY="" +# IFTTT_CONTENT_KEY="" +# _err "The DINGTALK_SIGNING_KEY must not be same as IFTTT_CONTENT_KEY." +# return 1 +# fi + + _content=$(echo "$_content" | _json_encode) + _subject=$(echo "$_subject" | _json_encode) + _data="{\"msgtype\": \"text\", \"text\": {\"content\": \"[$DINGTALK_KEYWORD]\n$_subject\n$_content\"}}" + + response="$(_post "$_data" "$DINGTALK_WEBHOOK" "" "POST" "application/json")" + + if [ "$?" = "0" ] && _contains "$response" "errmsg\":\"ok"; then + _info "dingtalk webhooks event fired success." + return 0 + fi + + _err "dingtalk webhooks event fired error." + _err "$response" + return 1 +} + From 05acf28e0ddb47b5eab3a3c32ed69f7813237736 Mon Sep 17 00:00:00 2001 From: Johann Richard <189003+johannrichard@users.noreply.github.com> Date: Sat, 2 Nov 2019 07:10:50 +0100 Subject: [PATCH 097/357] Update Dockerfile --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 02dd5030..5112bf07 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ FROM alpine:3.10 RUN apk update -f \ && apk --no-cache add -f \ openssl \ - openssh \ + openssh-client \ coreutils \ bind-tools \ curl \ From 35b34c43ed26ec2ad08ff004823f5b408e6a3401 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 2 Nov 2019 19:44:43 +0800 Subject: [PATCH 098/357] fix format --- notify/dingtalk.sh | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/notify/dingtalk.sh b/notify/dingtalk.sh index 7d354da2..c547da6e 100644 --- a/notify/dingtalk.sh +++ b/notify/dingtalk.sh @@ -32,24 +32,24 @@ dingtalk_send() { _saveaccountconf_mutable DINGTALK_KEYWORD "$DINGTALK_KEYWORD" fi -# DINGTALK_SIGNING_KEY="${DINGTALK_SIGNING_KEY:-$(_readaccountconf_mutable DINGTALK_SIGNING_KEY)}" -# if [ -z "$DINGTALK_SIGNING_KEY" ]; then -# DINGTALK_SIGNING_KEY="value1" -# _info "The DINGTALK_SIGNING_KEY is not set, so use the default value1 as key." -# elif ! _hasfield "$_IFTTT_AVAIL_MSG_KEYS" "$DINGTALK_SIGNING_KEY"; then -# _err "The DINGTALK_SIGNING_KEY \"$DINGTALK_SIGNING_KEY\" is not available, should be one of $_IFTTT_AVAIL_MSG_KEYS" -# DINGTALK_SIGNING_KEY="" -# return 1 -# else -# _saveaccountconf_mutable DINGTALK_SIGNING_KEY "$DINGTALK_SIGNING_KEY" -# fi + # DINGTALK_SIGNING_KEY="${DINGTALK_SIGNING_KEY:-$(_readaccountconf_mutable DINGTALK_SIGNING_KEY)}" + # if [ -z "$DINGTALK_SIGNING_KEY" ]; then + # DINGTALK_SIGNING_KEY="value1" + # _info "The DINGTALK_SIGNING_KEY is not set, so use the default value1 as key." + # elif ! _hasfield "$_IFTTT_AVAIL_MSG_KEYS" "$DINGTALK_SIGNING_KEY"; then + # _err "The DINGTALK_SIGNING_KEY \"$DINGTALK_SIGNING_KEY\" is not available, should be one of $_IFTTT_AVAIL_MSG_KEYS" + # DINGTALK_SIGNING_KEY="" + # return 1 + # else + # _saveaccountconf_mutable DINGTALK_SIGNING_KEY "$DINGTALK_SIGNING_KEY" + # fi -# if [ "$DINGTALK_SIGNING_KEY" = "$IFTTT_CONTENT_KEY" ]; then -# DINGTALK_SIGNING_KEY="" -# IFTTT_CONTENT_KEY="" -# _err "The DINGTALK_SIGNING_KEY must not be same as IFTTT_CONTENT_KEY." -# return 1 -# fi + # if [ "$DINGTALK_SIGNING_KEY" = "$IFTTT_CONTENT_KEY" ]; then + # DINGTALK_SIGNING_KEY="" + # IFTTT_CONTENT_KEY="" + # _err "The DINGTALK_SIGNING_KEY must not be same as IFTTT_CONTENT_KEY." + # return 1 + # fi _content=$(echo "$_content" | _json_encode) _subject=$(echo "$_subject" | _json_encode) @@ -66,4 +66,3 @@ dingtalk_send() { _err "$response" return 1 } - From 6eaf2d67b7588f23f1870c8813d3d6d391820b89 Mon Sep 17 00:00:00 2001 From: Kukushkin Alexander Date: Fri, 16 Nov 2018 08:30:44 +0300 Subject: [PATCH 099/357] Fix Vscale --- dnsapi/dns_vscale.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_vscale.sh b/dnsapi/dns_vscale.sh index e50b7d8b..d717d6e2 100755 --- a/dnsapi/dns_vscale.sh +++ b/dnsapi/dns_vscale.sh @@ -102,7 +102,7 @@ _get_root() { return 1 fi - hostedzone="$(echo "$response" | _egrep_o "{.*\"name\":\s*\"$h\".*}")" + hostedzone="$(echo "$response" | tr "{" "\n" | _egrep_o "\"name\":\s*\"$h\".*}")" if [ "$hostedzone" ]; then _domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "\"id\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ ) if [ "$_domain_id" ]; then From 2d1a776db792e475dfdedc3a3bfde7b649d8fa7e Mon Sep 17 00:00:00 2001 From: stilez Date: Mon, 4 Nov 2019 18:40:12 +0000 Subject: [PATCH 100/357] Replace egrep -> basic regex grep (( ... isn't it annoying that basic regex has * but not + ..... )) --- dnsapi/dns_pleskxml.sh | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index c12b2eeb..f3d6a1de 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -1,9 +1,5 @@ #!/usr/bin/env sh -# Globally disable this shellcheck error. -# Shellcheck errors on egrep ("deprecated"), but acme.sh uses egrep for compatibility. -# shellcheck disable=SC2196 - ## Name: dns_pleskxml.sh ## Created by Stilez. ## Also uses some code from PR#1832 by @romanlum (https://github.com/Neilpang/acme.sh/pull/1832/files) @@ -95,7 +91,7 @@ dns_pleskxml_add() { results="$(_api_response_split "$pleskxml_prettyprint_result" 'result' '')" - if ! _value "$results" | grep 'ok' | egrep -q '[0-9]+'; then + if ! _value "$results" | grep 'ok' | grep -q '[0-9][0-9]*'; then # Error - doesn't contain expected string. Something's wrong. _err 'Error when calling Plesk XML API.' _err 'The result did not contain the expected XXXXX section, or contained other values as well.' @@ -104,7 +100,7 @@ dns_pleskxml_add() { return 1 fi - recid="$(_value "$results" | egrep '[0-9]+' | sed -r 's/^.*([0-9]+)<\/id>.*$/\1/')" + recid="$(_value "$results" | grep '[0-9][0-9]*' | sed -r 's/^.*([0-9]+)<\/id>.*$/\1/')" _info "Success. TXT record appears to be correctly added (Plesk record ID=$recid). Exiting dns_pleskxml_add()." @@ -140,7 +136,7 @@ dns_pleskxml_rm() { # Reduce output to one line per DNS record, filtered for TXT records with a record ID only (which they should all have) reclist="$(_api_response_split "$pleskxml_prettyprint_result" 'result' 'ok' \ | grep "${root_domain_id}" \ - | egrep '[0-9]+' \ + | grep '[0-9][0-9]*' \ | grep 'TXT' )" @@ -159,7 +155,7 @@ dns_pleskxml_rm() { _debug "List of DNS TXT records for host:"'\n'"$(_value "$reclist" | grep "$1.")" - if ! _value "$recid" | egrep -q '^[0-9]+$'; then + if ! _value "$recid" | grep -q '^[0-9][0-9]*$'; then _err "DNS records for root domain '${root_domain_name}' (Plesk ID ${root_domain_id}) + host '${sub_domain_name}' do not contain the TXT record '${txtvalue}'" _err "Cannot delete TXT record. Exiting." return 1 @@ -180,7 +176,7 @@ dns_pleskxml_rm() { results="$(_api_response_split "$pleskxml_prettyprint_result" 'result' '')" - if ! _value "$results" | grep 'ok' | egrep -q '[0-9]+'; then + if ! _value "$results" | grep 'ok' | grep -q '[0-9][0-9]*'; then # Error - doesn't contain expected string. Something's wrong. _err 'Error when calling Plesk XML API.' _err 'The result did not contain the expected XXXXX section, or contained other values as well.' @@ -216,13 +212,16 @@ _countdots() { # Cleans up an API response, splits it "one line per item in the response" and greps for a string that in the context, identifies "useful" lines # $1 - result string from API # $2 - tag to resplit on (usually "result" or "domain") -# $3 - regex to recognise useful return lines +# $3 - basic regex to recognise useful return lines +# note: $3 matches via basic NOT extended regex (BRE), as extended regex capabilities not needed at the moment. +# Last line could change to instead, with suitablew ewscaping of ['"/$], +# if future Plesk XML API changes ever require extended regex _api_response_split() { printf '%s' "$1" \ | sed -r 's/(^ +| +$)//g' \ | tr -d '\n\r' \ | sed -r "s/<\/?$2>/${NEWLINE}/g" \ - | egrep "$3" + | grep "$3" } #################### Private functions below (DNS functions) ################################## @@ -245,15 +244,13 @@ _call_api() { # Detect any that isn't "ok". None of the used calls should fail if the API is working correctly. # Also detect if there simply aren't any status lines (null result?) and report that, as well. - statuslines="$(echo "$pleskxml_prettyprint_result" | egrep '^ *[^<]* *$')" + statuslines="$(echo "$pleskxml_prettyprint_result" | grep '^ *[^<]* *$')" if _value "$statuslines" | grep -qv 'ok'; then # We have some status lines that aren't "ok". Get the details errtext="$(_value "$pleskxml_prettyprint_result" \ - | egrep "(||)" \ - | sed -r 's/^ *<(status|errcode|errtext)>/\1: /' \ - | sed -r 's/<\/(status|errcode|errtext)>$//g' + | sed -rn 's/^ *<(status|errcode|errtext)>([^<]+)<\/(status|errcode|errtext)> *$/\1: \2/p' \ )" elif ! _value "$statuslines" | grep -q 'ok'; then From 63a779baa86ed8609c7030fa8aa37deb11341752 Mon Sep 17 00:00:00 2001 From: stilez Date: Mon, 4 Nov 2019 18:44:14 +0000 Subject: [PATCH 101/357] remove unnecessary \ --- dnsapi/dns_pleskxml.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index f3d6a1de..c673744f 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -250,7 +250,7 @@ _call_api() { # We have some status lines that aren't "ok". Get the details errtext="$(_value "$pleskxml_prettyprint_result" \ - | sed -rn 's/^ *<(status|errcode|errtext)>([^<]+)<\/(status|errcode|errtext)> *$/\1: \2/p' \ + | sed -rn 's/^ *<(status|errcode|errtext)>([^<]+)<\/(status|errcode|errtext)> *$/\1: \2/p' )" elif ! _value "$statuslines" | grep -q 'ok'; then From 04b0c62bf959c800c36f9b19da599741caacd1c8 Mon Sep 17 00:00:00 2001 From: stilez Date: Mon, 4 Nov 2019 19:05:44 +0000 Subject: [PATCH 102/357] basic regex's to use \+ Maybe BRE aren't as basic as they sound. But I'm sure `man grep` didn't list the extra syntax of "preceded by backslash" :) So let's use it --- dnsapi/dns_pleskxml.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index c673744f..dca0d246 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -91,7 +91,7 @@ dns_pleskxml_add() { results="$(_api_response_split "$pleskxml_prettyprint_result" 'result' '')" - if ! _value "$results" | grep 'ok' | grep -q '[0-9][0-9]*'; then + if ! _value "$results" | grep 'ok' | grep -q '[0-9]\+'; then # Error - doesn't contain expected string. Something's wrong. _err 'Error when calling Plesk XML API.' _err 'The result did not contain the expected XXXXX section, or contained other values as well.' @@ -100,7 +100,7 @@ dns_pleskxml_add() { return 1 fi - recid="$(_value "$results" | grep '[0-9][0-9]*' | sed -r 's/^.*([0-9]+)<\/id>.*$/\1/')" + recid="$(_value "$results" | grep '[0-9]\+' | sed -r 's/^.*([0-9]+)<\/id>.*$/\1/')" _info "Success. TXT record appears to be correctly added (Plesk record ID=$recid). Exiting dns_pleskxml_add()." @@ -136,7 +136,7 @@ dns_pleskxml_rm() { # Reduce output to one line per DNS record, filtered for TXT records with a record ID only (which they should all have) reclist="$(_api_response_split "$pleskxml_prettyprint_result" 'result' 'ok' \ | grep "${root_domain_id}" \ - | grep '[0-9][0-9]*' \ + | grep '[0-9]\+' \ | grep 'TXT' )" @@ -155,7 +155,7 @@ dns_pleskxml_rm() { _debug "List of DNS TXT records for host:"'\n'"$(_value "$reclist" | grep "$1.")" - if ! _value "$recid" | grep -q '^[0-9][0-9]*$'; then + if ! _value "$recid" | grep -q '^[0-9]\+$'; then _err "DNS records for root domain '${root_domain_name}' (Plesk ID ${root_domain_id}) + host '${sub_domain_name}' do not contain the TXT record '${txtvalue}'" _err "Cannot delete TXT record. Exiting." return 1 @@ -176,7 +176,7 @@ dns_pleskxml_rm() { results="$(_api_response_split "$pleskxml_prettyprint_result" 'result' '')" - if ! _value "$results" | grep 'ok' | grep -q '[0-9][0-9]*'; then + if ! _value "$results" | grep 'ok' | grep -q '[0-9]\+'; then # Error - doesn't contain expected string. Something's wrong. _err 'Error when calling Plesk XML API.' _err 'The result did not contain the expected XXXXX section, or contained other values as well.' From 896778cead810f88ffd8e5efa61d97cbd78dfe6d Mon Sep 17 00:00:00 2001 From: stilez Date: Tue, 5 Nov 2019 17:56:20 +0000 Subject: [PATCH 103/357] Grep fixes and minor improvements --- dnsapi/dns_pleskxml.sh | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index dca0d246..551e42fe 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -91,7 +91,7 @@ dns_pleskxml_add() { results="$(_api_response_split "$pleskxml_prettyprint_result" 'result' '')" - if ! _value "$results" | grep 'ok' | grep -q '[0-9]\+'; then + if ! _value "$results" | grep 'ok' | grep '[0-9]\{1,\}' >/dev/null; then # Error - doesn't contain expected string. Something's wrong. _err 'Error when calling Plesk XML API.' _err 'The result did not contain the expected XXXXX section, or contained other values as well.' @@ -100,7 +100,7 @@ dns_pleskxml_add() { return 1 fi - recid="$(_value "$results" | grep '[0-9]\+' | sed -r 's/^.*([0-9]+)<\/id>.*$/\1/')" + recid="$(_value "$results" | grep '[0-9]\{1,\}' | sed -r 's/^.*([0-9]+)<\/id>.*$/\1/')" _info "Success. TXT record appears to be correctly added (Plesk record ID=$recid). Exiting dns_pleskxml_add()." @@ -136,7 +136,7 @@ dns_pleskxml_rm() { # Reduce output to one line per DNS record, filtered for TXT records with a record ID only (which they should all have) reclist="$(_api_response_split "$pleskxml_prettyprint_result" 'result' 'ok' \ | grep "${root_domain_id}" \ - | grep '[0-9]\+' \ + | grep '[0-9]\{1,\}' \ | grep 'TXT' )" @@ -155,7 +155,7 @@ dns_pleskxml_rm() { _debug "List of DNS TXT records for host:"'\n'"$(_value "$reclist" | grep "$1.")" - if ! _value "$recid" | grep -q '^[0-9]\+$'; then + if ! _value "$recid" | grep '^[0-9]\{1,\}$' >/dev/null; then _err "DNS records for root domain '${root_domain_name}' (Plesk ID ${root_domain_id}) + host '${sub_domain_name}' do not contain the TXT record '${txtvalue}'" _err "Cannot delete TXT record. Exiting." return 1 @@ -176,7 +176,7 @@ dns_pleskxml_rm() { results="$(_api_response_split "$pleskxml_prettyprint_result" 'result' '')" - if ! _value "$results" | grep 'ok' | grep -q '[0-9]\+'; then + if ! _value "$results" | grep 'ok' | grep '[0-9]\{1,\}' >/dev/null; then # Error - doesn't contain expected string. Something's wrong. _err 'Error when calling Plesk XML API.' _err 'The result did not contain the expected XXXXX section, or contained other values as well.' @@ -244,20 +244,27 @@ _call_api() { # Detect any that isn't "ok". None of the used calls should fail if the API is working correctly. # Also detect if there simply aren't any status lines (null result?) and report that, as well. - statuslines="$(echo "$pleskxml_prettyprint_result" | grep '^ *[^<]* *$')" + statuslines_count_total="$(echo "$pleskxml_prettyprint_result" | grep -c '^ *[^<]* *$')" + statuslines_count_okay="$(echo "$pleskxml_prettyprint_result" | grep -c '^ *ok *$')" - if _value "$statuslines" | grep -qv 'ok'; then - - # We have some status lines that aren't "ok". Get the details - errtext="$(_value "$pleskxml_prettyprint_result" \ - | sed -rn 's/^ *<(status|errcode|errtext)>([^<]+)<\/(status|errcode|errtext)> *$/\1: \2/p' - )" - - elif ! _value "$statuslines" | grep -q 'ok'; then + if [ -z "$statuslines_count_total" ]; then # We have no status lines at all. Results are empty errtext='The Plesk XML API unexpectedly returned an empty set of results for this call.' + elif [ "$statuslines_count_okay" -ne "$statuslines_count_total" ]; then + + # We have some status lines that aren't "ok". Any available details are in API response fields "status" "errcode" and "errtext" + # Workaround for basic regex: + # - filter output to keep only lines like this: "SPACEStextSPACES" (shouldn't be necessary with prettyprint but guarantees subsequent code is ok) + # - then edit the 3 "useful" error tokens individually and remove closing tags on all lines + # - then filter again to remove all lines not edited (which will be the lines not starting A-Z) + errtext="$(_value "$pleskxml_prettyprint_result" \ + | grep '^ *<[a-z]\{1,\}>[^<]*<\/[a-z]\{1,\}> *$' \ + | sed 's/^ */Status: /;s/^ */Error code: /;s/^ */Error text: /;s/<\/.*$//' \ + | grep '^[A-Z]' + )" + fi if [ "$pleskxml_retcode" -ne 0 ] || [ "$errtext" != "" ]; then @@ -266,7 +273,7 @@ _call_api() { if [ "$pleskxml_retcode" -eq 0 ]; then _err "The POST request was successfully sent to the Plesk server." else - _err "The return code for the POST request was $pleskxml_retcode (non-zero = could not submit request to server)." + _err "The return code for the POST request was $pleskxml_retcode (non-zero = failure in submitting request to server)." fi if [ "$errtext" != "" ]; then From cbacc779fcc3dc9bf3b5924d5691c12f9d74ebe3 Mon Sep 17 00:00:00 2001 From: stilez Date: Tue, 5 Nov 2019 18:50:39 +0000 Subject: [PATCH 104/357] Fix some sed -r, and clean up some variable references ("$1" -> "$varname") --- dnsapi/dns_pleskxml.sh | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index 551e42fe..2c9a4d56 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -100,7 +100,7 @@ dns_pleskxml_add() { return 1 fi - recid="$(_value "$results" | grep '[0-9]\{1,\}' | sed -r 's/^.*([0-9]+)<\/id>.*$/\1/')" + recid="$(_value "$results" | grep '[0-9]\{1,\}' | sed 's/^.*\([0-9]\{1,\}\)<\/id>.*$/\1/')" _info "Success. TXT record appears to be correctly added (Plesk record ID=$recid). Exiting dns_pleskxml_add()." @@ -145,16 +145,16 @@ dns_pleskxml_rm() { return 1 fi - _debug "Got list of DNS TXT records for root domain '$root_domain_name'"':\n'"$reclist" + _debug "Got list of DNS TXT records for root domain '$root_domain_name'. Full list is:"'\n'"$reclist" + + _debug "DNS TXT records for host '$fulldomain':"'\n'"$(_value "$reclist" | grep "${fulldomain}.")" recid="$(_value "$reclist" \ - | grep "$1." \ - | grep "$txtvalue" \ - | sed -r 's/(^.*|<\/id>.*$)//g' + | grep "${fulldomain}." \ + | grep "${txtvalue}" \ + | sed 's/^.*\([0-9]\{1,\}\)<\/id>.*$/\1/' )" - _debug "List of DNS TXT records for host:"'\n'"$(_value "$reclist" | grep "$1.")" - if ! _value "$recid" | grep '^[0-9]\{1,\}$' >/dev/null; then _err "DNS records for root domain '${root_domain_name}' (Plesk ID ${root_domain_id}) + host '${sub_domain_name}' do not contain the TXT record '${txtvalue}'" _err "Cannot delete TXT record. Exiting." @@ -341,13 +341,13 @@ _credential_check() { # See notes at top of this file _pleskxml_get_root_domain() { - _debug "Identifying DNS root domain for '$1' that is managed by the Plesk account." original_full_domain_name="$1" - root_domain_name="$1" + + _debug "Identifying DNS root domain for '$original_full_domain_name' that is managed by the Plesk account." # test if the domain as provided is valid for splitting. - if ! _countdots "$root_domain_name"; then + if ! _countdots "$original_full_domain_name"; then _err "Invalid domain. The ACME domain must contain at least two parts (aa.bb) to identify a domain and tld for the TXT record." return 1 fi @@ -372,6 +372,8 @@ _pleskxml_get_root_domain() { # loop and test if domain, or any parent domain, is managed by Plesk # Loop until we don't have any '.' in the string we're testing as a candidate Plesk-managed domain + root_domain_name="$original_full_domain_name" + while true; do _debug "Checking if '$root_domain_name' is managed by the Plesk server..." From a8d670fc0d7abb2efa3cbcc411c79f37ad8c737d Mon Sep 17 00:00:00 2001 From: stilez Date: Tue, 5 Nov 2019 19:01:32 +0000 Subject: [PATCH 105/357] Rest of sed -r --- dnsapi/dns_pleskxml.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index 2c9a4d56..c2de2184 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -211,16 +211,16 @@ _countdots() { # Cleans up an API response, splits it "one line per item in the response" and greps for a string that in the context, identifies "useful" lines # $1 - result string from API -# $2 - tag to resplit on (usually "result" or "domain") +# $2 - plain text tag to resplit on (usually "result" or "domain"). NOT REGEX # $3 - basic regex to recognise useful return lines # note: $3 matches via basic NOT extended regex (BRE), as extended regex capabilities not needed at the moment. -# Last line could change to instead, with suitablew ewscaping of ['"/$], +# Last line could change to instead, with suitable escaping of ['"/$], # if future Plesk XML API changes ever require extended regex _api_response_split() { printf '%s' "$1" \ - | sed -r 's/(^ +| +$)//g' \ + | sed 's/^ +//;s/ +$//' \ | tr -d '\n\r' \ - | sed -r "s/<\/?$2>/${NEWLINE}/g" \ + | sed "s/<\/\{0,1\}$2>/${NEWLINE}/g" \ | grep "$3" } @@ -365,7 +365,7 @@ _pleskxml_get_root_domain() { # Output will be one line per known domain, containing 2 tages and a single tag # We don't actually need to check for type, name, *and* id, but it guarantees only usable lines are returned. - output="$(_api_response_split "$pleskxml_prettyprint_result" 'domain' 'domain' | sed -r 's/<(\/?)ascii-name>/<\1name>/g' | grep '' | grep '')" + output="$(_api_response_split "$pleskxml_prettyprint_result" 'domain' 'domain' | sed 's///g;s/<\/ascii-name>/<\/name>/g' | grep '' | grep '')" _debug 'Domains managed by Plesk server are (ignore the hacked output):\n' "$output" @@ -378,13 +378,13 @@ _pleskxml_get_root_domain() { _debug "Checking if '$root_domain_name' is managed by the Plesk server..." - root_domain_id="$(_value "$output" | grep "$root_domain_name" | _head_n 1 | sed -r 's/^.*([0-9]+)<\/id>.*$/\1/')" + root_domain_id="$(_value "$output" | grep "$root_domain_name" | _head_n 1 | sed 's/^.*\([0-9]\{1,\}\)<\/id>.*$/\1/')" if [ -n "$root_domain_id" ]; then # Found a match # SEE IMPORTANT NOTE ABOVE - THIS FUNCTION CAN RETURN HOST='', AND THAT'S OK FOR PLESK XML API WHICH ALLOWS IT. # SO WE HANDLE IT AND DON'T PREVENT IT - sub_domain_name="$(_value "$original_full_domain_name" | sed -r "s/\.?${root_domain_name}"'$//')" + sub_domain_name="$(_value "$original_full_domain_name" | sed "s/\.\{0,1\}${root_domain_name}"'$//')" _info "Success. Matched host '$original_full_domain_name' to: DOMAIN '${root_domain_name}' (Plesk ID '${root_domain_id}'), HOST '${sub_domain_name}'. Returning." return 0 fi From 4216c9e8f745d76588c8dc8592ade0e020f82d62 Mon Sep 17 00:00:00 2001 From: stilez Date: Tue, 5 Nov 2019 19:19:08 +0000 Subject: [PATCH 106/357] rmv spaces --- dnsapi/dns_pleskxml.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index c2de2184..d2a2684a 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -146,7 +146,7 @@ dns_pleskxml_rm() { fi _debug "Got list of DNS TXT records for root domain '$root_domain_name'. Full list is:"'\n'"$reclist" - + _debug "DNS TXT records for host '$fulldomain':"'\n'"$(_value "$reclist" | grep "${fulldomain}.")" recid="$(_value "$reclist" \ From a9726bd52f764f519332783f8002ef8e2c742b5b Mon Sep 17 00:00:00 2001 From: stilez Date: Tue, 5 Nov 2019 20:58:51 +0000 Subject: [PATCH 107/357] bugfix --- dnsapi/dns_pleskxml.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index d2a2684a..ad8d5cfd 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -393,7 +393,7 @@ _pleskxml_get_root_domain() { root_domain_name="$(_valuecut 2 1000 "$root_domain_name")" - if ! _countdots "$root_domain_name"; then + if [ _countdots "$root_domain_name" -eq 0 ]; then _debug "No match, and next parent would be a TLD..." _err "Cannot find '$original_full_domain_name' or any parent domain of it, in Plesk." _err "Are you sure that this domain is managed by this Plesk server?" From 38854bd876d11c4bf0f696e23c694a61d2b640ec Mon Sep 17 00:00:00 2001 From: stilez Date: Tue, 5 Nov 2019 21:00:34 +0000 Subject: [PATCH 108/357] bugfix --- dnsapi/dns_pleskxml.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index ad8d5cfd..ca64325b 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -393,7 +393,7 @@ _pleskxml_get_root_domain() { root_domain_name="$(_valuecut 2 1000 "$root_domain_name")" - if [ _countdots "$root_domain_name" -eq 0 ]; then + if [ "$(_countdots "$root_domain_name")" -eq 0 ]; then _debug "No match, and next parent would be a TLD..." _err "Cannot find '$original_full_domain_name' or any parent domain of it, in Plesk." _err "Are you sure that this domain is managed by this Plesk server?" From 43011f3bfa2e08807b3e7450d123aabcbd6905a8 Mon Sep 17 00:00:00 2001 From: stilez Date: Tue, 5 Nov 2019 21:04:10 +0000 Subject: [PATCH 109/357] enhance --- dnsapi/dns_pleskxml.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index ca64325b..5abe9dd1 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -203,10 +203,10 @@ _valuecut() { printf '%s' "$3" | cut -d . -f "${1}-${2}" } -# Counts '.' present in a domain name +# Counts '.' present in a domain name or other string # $1 = domain name _countdots() { - _value "$1" | tr -dc '.' | wc -c + _value "$1" | tr -dc '.' | wc -c | sed 's/ //g' } # Cleans up an API response, splits it "one line per item in the response" and greps for a string that in the context, identifies "useful" lines From 05247dc4a4dca564a8d38e223da89556e2e68493 Mon Sep 17 00:00:00 2001 From: stilez Date: Tue, 5 Nov 2019 21:09:14 +0000 Subject: [PATCH 110/357] fix --- dnsapi/dns_pleskxml.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index 5abe9dd1..b6781c2e 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -347,7 +347,7 @@ _pleskxml_get_root_domain() { # test if the domain as provided is valid for splitting. - if ! _countdots "$original_full_domain_name"; then + if [ "$(_countdots "$original_full_domain_name")" -eq 0 ]; then _err "Invalid domain. The ACME domain must contain at least two parts (aa.bb) to identify a domain and tld for the TXT record." return 1 fi From 6d0e4bed4b9d9bcb31e445ecadc7c4f741abc6fc Mon Sep 17 00:00:00 2001 From: stilez Date: Tue, 5 Nov 2019 23:26:05 +0000 Subject: [PATCH 111/357] remove \n in output messages --- dnsapi/dns_pleskxml.sh | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index b6781c2e..ca07bc4e 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -96,7 +96,8 @@ dns_pleskxml_add() { _err 'Error when calling Plesk XML API.' _err 'The result did not contain the expected XXXXX section, or contained other values as well.' _err 'This is unexpected: something has gone wrong.' - _err 'The full response was:\n' "$pleskxml_prettyprint_result" + _err 'The full response was:' + _err "$pleskxml_prettyprint_result" return 1 fi @@ -134,7 +135,9 @@ dns_pleskxml_rm() { fi # Reduce output to one line per DNS record, filtered for TXT records with a record ID only (which they should all have) + # Also strip out spaces between tags, redundant and group tags and any tags reclist="$(_api_response_split "$pleskxml_prettyprint_result" 'result' 'ok' \ + | sed 's# \{1,\}<\([a-zA-Z]\)#<\1#g;s###g;s#<[a-z][^/<>]*/>##g' \ | grep "${root_domain_id}" \ | grep '[0-9]\{1,\}' \ | grep 'TXT' @@ -145,9 +148,8 @@ dns_pleskxml_rm() { return 1 fi - _debug "Got list of DNS TXT records for root domain '$root_domain_name'. Full list is:"'\n'"$reclist" - - _debug "DNS TXT records for host '$fulldomain':"'\n'"$(_value "$reclist" | grep "${fulldomain}.")" + _debug "Got list of DNS TXT records for root domain '$root_domain_name':" + _debug "$reclist" recid="$(_value "$reclist" \ | grep "${fulldomain}." \ @@ -181,7 +183,8 @@ dns_pleskxml_rm() { _err 'Error when calling Plesk XML API.' _err 'The result did not contain the expected XXXXX section, or contained other values as well.' _err 'This is unexpected: something has gone wrong.' - _err 'The full response was:\n' "$pleskxml_prettyprint_result" + _err 'The full response was:' + _err "$pleskxml_prettyprint_result" return 1 fi @@ -231,7 +234,8 @@ _call_api() { request="$1" errtext='' - _debug 'Entered _call_api(). Calling Plesk XML API with request:\n' "'${request}'" + _debug 'Entered _call_api(). Calling Plesk XML API with request:' + _debug "'$request'" export _H1="HTTP_AUTH_LOGIN: $pleskxml_user" export _H2="HTTP_AUTH_PASSWD: $pleskxml_pass" @@ -239,7 +243,9 @@ _call_api() { export _H4="HTTP_PRETTY_PRINT: true" pleskxml_prettyprint_result="$(_post "${request}" "$pleskxml_uri" "" "POST")" pleskxml_retcode="$?" - _debug 'The responses from the Plesk XML server were:\n' "retcode=$pleskxml_retcode. Literal response:"'\n' "'$pleskxml_prettyprint_result'" + _debug 'The responses from the Plesk XML server were:' + _debug "retcode=$pleskxml_retcode. Literal response:" + _debug "'$pleskxml_prettyprint_result'" # Detect any that isn't "ok". None of the used calls should fail if the API is working correctly. # Also detect if there simply aren't any status lines (null result?) and report that, as well. @@ -277,7 +283,8 @@ _call_api() { fi if [ "$errtext" != "" ]; then - _err 'The error responses received from the Plesk server were:\n' "$errtext" + _err 'The error responses received from the Plesk server were:' + _err "$errtext" else _err "No additional error messages were received back from the Plesk server" fi @@ -318,7 +325,7 @@ _credential_check() { # Test the API is usable, by trying to read the list of managed domains... _call_api "$pleskxml_tplt_get_domains" if [ "$pleskxml_retcode" -ne 0 ]; then - _err '\nFailed to access Plesk XML API.' + _err 'Failed to access Plesk XML API.' _err "Please check your login credentials and Plesk URI, and that the URI is reachable, and try again." return 1 fi @@ -367,7 +374,8 @@ _pleskxml_get_root_domain() { output="$(_api_response_split "$pleskxml_prettyprint_result" 'domain' 'domain' | sed 's///g;s/<\/ascii-name>/<\/name>/g' | grep '' | grep '')" - _debug 'Domains managed by Plesk server are (ignore the hacked output):\n' "$output" + _debug 'Domains managed by Plesk server are (ignore the hacked output):' + _debug "$output" # loop and test if domain, or any parent domain, is managed by Plesk # Loop until we don't have any '.' in the string we're testing as a candidate Plesk-managed domain From 51cfd996eb8aaa142c9cbe61270bf1c5751f7d1e Mon Sep 17 00:00:00 2001 From: stilez Date: Tue, 5 Nov 2019 23:29:51 +0000 Subject: [PATCH 112/357] rmv space --- dnsapi/dns_pleskxml.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index ca07bc4e..c5d9e544 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -96,7 +96,7 @@ dns_pleskxml_add() { _err 'Error when calling Plesk XML API.' _err 'The result did not contain the expected XXXXX section, or contained other values as well.' _err 'This is unexpected: something has gone wrong.' - _err 'The full response was:' + _err 'The full response was:' _err "$pleskxml_prettyprint_result" return 1 fi From 0b3ae1f9727787f46eec66ce796e030a5474a845 Mon Sep 17 00:00:00 2001 From: Jesai Langenbach Date: Thu, 7 Nov 2019 14:10:30 +0100 Subject: [PATCH 113/357] Add suggestions --- dnsapi/dns_opnsense.sh | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/dnsapi/dns_opnsense.sh b/dnsapi/dns_opnsense.sh index 0f7cdea6..97f18d1a 100755 --- a/dnsapi/dns_opnsense.sh +++ b/dnsapi/dns_opnsense.sh @@ -4,15 +4,19 @@ #https://docs.opnsense.org/development/api.html # #OPNs_Host="opnsense.example.com" -#OPNs_Port="443" +#OPNs_Port="443" (optional, defaults to 443 if unset) #OPNs_Key="qocfU9RSbt8vTIBcnW8bPqCrpfAHMDvj5OzadE7Str+rbjyCyk7u6yMrSCHtBXabgDDXx/dY0POUp7ZA" #OPNs_Token="pZEQ+3ce8dDlfBBdg3N8EpqpF5I1MhFqdxX06le6Gl8YzyQvYCfCzNaFX9O9+IOSyAs7X71fwdRiZ+Lv" -#OPNs_Api_Insecure=0 # Set 1 for insecure and 0 for secure -> difference is whether ssl cert is checked for validity (0) or whether it is just accepted (1) +#OPNs_Api_Insecure=0 (optional, defaults to 0 if unset) # Set 1 for insecure and 0 for secure -> difference is whether ssl cert is checked for validity (0) or whether it is just accepted (1) ######## Public functions ##################### #Usage: add _acme-challenge.www.domain.com "123456789ABCDEF0000000000000000000000000000000000000" #fulldomain #txtvalue +OPNs_DefaultPort=443 +OPNs_DefaultApi_Insecure=0 + + dns_opnsense_add() { fulldomain=$1 txtvalue=$2 @@ -168,7 +172,7 @@ _opns_rest() { key=$(echo "$OPNs_Key" | tr -d "\n\r" | _url_encode) token=$(echo "$OPNs_Token" | tr -d "\n\r" | _url_encode) - opnsense_url="https://${key}:${token}@${OPNs_Host}:${OPNs_Port}/api/bind${ep}" + opnsense_url="https://${key}:${token}@${OPNs_Host}:${OPNs_Port:-$OPNs_DefaultPort}/api/bind${ep}" export _H1="Content-Type: application/json" if [ ! "$method" = "GET" ]; then _debug data "$data" @@ -218,29 +222,30 @@ _opns_check_auth() { OPNs_Api_Insecure="${OPNs_Api_Insecure:-$(_readaccountconf_mutable OPNs_Api_Insecure)}" if [ -z "$OPNs_Host" ]; then - OPNs_Host="localhost" _err "You don't specify OPNsense address." return 1 else _saveaccountconf_mutable OPNs_Host "$OPNs_Host" fi - if [ -z "$OPNs_Port" ]; then - OPNs_Port="443" + if ! printf '%s' "$OPNs_Port" | grep -q '^[0-9]*$'; then + _err 'OPNs_Port specified but not numeric value' + return 1 + elif [ -z "$OPNs_Port" ]; then + _info "OPNSense port not specified. Defaulting to using port $OPNs_DefaultPort" else _saveaccountconf_mutable OPNs_Port "$OPNs_Port" fi - - if [ -z "$OPNs_Api_Insecure" ]; then - OPNs_Api_Insecure="0" - else - #save the api addr and key to the account conf file. + + if ! printf '%s' "$OPNs_Api_Insecure" | grep -q '^[01]$'; then + _err 'OPNs_Api_Insecure specified but not 0/1 value' + return 1 + elif [ -n "$OPNs_Api_Insecure" ]; then _saveaccountconf_mutable OPNs_Api_Insecure "$OPNs_Api_Insecure" fi - export HTTPS_INSECURE="${OPNs_Api_Insecure}" + export HTTPS_INSECURE="${OPNs_Api_Insecure:-$OPNs_DefaultApi_Insecure}" if [ -z "$OPNs_Key" ]; then - OPNs_Key="" _err "You don't specify OPNsense api key id." _err "Please set you OPNs_Key and try again." return 1 @@ -249,7 +254,6 @@ _opns_check_auth() { fi if [ -z "$OPNs_Token" ]; then - OPNs_Token="" _err "You don't specify OPNsense token." _err "Please create you OPNs_Token and try again." return 1 From afdf8a78c0a42e22265309c522ee3cda4993e227 Mon Sep 17 00:00:00 2001 From: Jesai Langenbach Date: Thu, 7 Nov 2019 14:18:09 +0100 Subject: [PATCH 114/357] fix space --- dnsapi/dns_opnsense.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_opnsense.sh b/dnsapi/dns_opnsense.sh index 97f18d1a..afd96c3e 100755 --- a/dnsapi/dns_opnsense.sh +++ b/dnsapi/dns_opnsense.sh @@ -236,7 +236,7 @@ _opns_check_auth() { else _saveaccountconf_mutable OPNs_Port "$OPNs_Port" fi - + if ! printf '%s' "$OPNs_Api_Insecure" | grep -q '^[01]$'; then _err 'OPNs_Api_Insecure specified but not 0/1 value' return 1 From fc8d9df5162bdec5e401edc4e8d6faba80e92d89 Mon Sep 17 00:00:00 2001 From: Jesai Langenbach Date: Thu, 7 Nov 2019 14:33:38 +0100 Subject: [PATCH 115/357] fix newline --- dnsapi/dns_opnsense.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_opnsense.sh b/dnsapi/dns_opnsense.sh index afd96c3e..6dde12a5 100755 --- a/dnsapi/dns_opnsense.sh +++ b/dnsapi/dns_opnsense.sh @@ -16,7 +16,6 @@ OPNs_DefaultPort=443 OPNs_DefaultApi_Insecure=0 - dns_opnsense_add() { fulldomain=$1 txtvalue=$2 From 18fc42e63b5f4491502b8a2203036c93b1c4eaba Mon Sep 17 00:00:00 2001 From: Jesai Langenbach Date: Thu, 7 Nov 2019 22:06:32 +0100 Subject: [PATCH 116/357] typos and integrate suggestions from stilez --- dnsapi/dns_opnsense.sh | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/dnsapi/dns_opnsense.sh b/dnsapi/dns_opnsense.sh index 6dde12a5..4fbe9447 100755 --- a/dnsapi/dns_opnsense.sh +++ b/dnsapi/dns_opnsense.sh @@ -4,10 +4,13 @@ #https://docs.opnsense.org/development/api.html # #OPNs_Host="opnsense.example.com" -#OPNs_Port="443" (optional, defaults to 443 if unset) +#OPNs_Port="443" +# optional, defaults to 443 if unset #OPNs_Key="qocfU9RSbt8vTIBcnW8bPqCrpfAHMDvj5OzadE7Str+rbjyCyk7u6yMrSCHtBXabgDDXx/dY0POUp7ZA" #OPNs_Token="pZEQ+3ce8dDlfBBdg3N8EpqpF5I1MhFqdxX06le6Gl8YzyQvYCfCzNaFX9O9+IOSyAs7X71fwdRiZ+Lv" -#OPNs_Api_Insecure=0 (optional, defaults to 0 if unset) # Set 1 for insecure and 0 for secure -> difference is whether ssl cert is checked for validity (0) or whether it is just accepted (1) +#OPNs_Api_Insecure=0 +# optional, defaults to 0 if unset +# Set 1 for insecure and 0 for secure -> difference is whether ssl cert is checked for validity (0) or whether it is just accepted (1) ######## Public functions ##################### #Usage: add _acme-challenge.www.domain.com "123456789ABCDEF0000000000000000000000000000000000000" @@ -44,15 +47,16 @@ dns_opnsense_rm() { } set_record() { - _info "Adding record" fulldomain=$1 new_challenge=$2 + _info "Adding record $fulldomain with challenge: $new_challenge" _debug "Detect root zone" if ! _get_root "$fulldomain"; then _err "invalid domain" return 1 fi + _debug _domain "$_domain" _debug _host "$_host" _debug _domainid "$_domainid" @@ -81,7 +85,7 @@ set_record() { _opns_rest "POST" "/service/reconfigure" "{}" _debug "Record created" else - _err "Error createing record $_record_string" + _err "Error creating record $_record_string" return 1 fi @@ -89,9 +93,9 @@ set_record() { } rm_record() { - _info "Remove record" fulldomain=$1 new_challenge="$2" + _info "Remove record $fulldomain with challenge: $new_challenge" _debug "Detect root zone" if ! _get_root "$fulldomain"; then @@ -110,18 +114,18 @@ rm_record() { _opns_rest "POST" "/service/reconfigure" "{}" _debug "Record deleted" else - _err "Error delteting record $fulldomain" + _err "Error deleting record $host from domain $fulldomain" return 1 fi else - _err "Error delteting record $fulldomain" + _err "Error deleting record $host from domain $fulldomain" return 1 fi else _info "Record not found, nothing to remove" fi - return 0 + return 0 } #################### Private functions below ################################## @@ -173,6 +177,7 @@ _opns_rest() { opnsense_url="https://${key}:${token}@${OPNs_Host}:${OPNs_Port:-$OPNs_DefaultPort}/api/bind${ep}" export _H1="Content-Type: application/json" + _debug2 "Try to call api: https://${OPNs_Host}:${OPNs_Port:-$OPNs_DefaultPort}/api/bind${ep}" if [ ! "$method" = "GET" ]; then _debug data "$data" export _H1="Content-Type: application/json" @@ -227,7 +232,7 @@ _opns_check_auth() { _saveaccountconf_mutable OPNs_Host "$OPNs_Host" fi - if ! printf '%s' "$OPNs_Port" | grep -q '^[0-9]*$'; then + if ! printf '%s' "$OPNs_Port" | grep '^[0-9]*$' >/dev/null ; then _err 'OPNs_Port specified but not numeric value' return 1 elif [ -z "$OPNs_Port" ]; then @@ -236,7 +241,7 @@ _opns_check_auth() { _saveaccountconf_mutable OPNs_Port "$OPNs_Port" fi - if ! printf '%s' "$OPNs_Api_Insecure" | grep -q '^[01]$'; then + if ! printf '%s' "$OPNs_Api_Insecure" | grep '^[01]$' >/dev/null ; then _err 'OPNs_Api_Insecure specified but not 0/1 value' return 1 elif [ -n "$OPNs_Api_Insecure" ]; then @@ -245,23 +250,23 @@ _opns_check_auth() { export HTTPS_INSECURE="${OPNs_Api_Insecure:-$OPNs_DefaultApi_Insecure}" if [ -z "$OPNs_Key" ]; then - _err "You don't specify OPNsense api key id." - _err "Please set you OPNs_Key and try again." + _err "you have not specified your OPNsense api key id." + _err "Please set OPNs_Key and try again." return 1 else _saveaccountconf_mutable OPNs_Key "$OPNs_Key" fi if [ -z "$OPNs_Token" ]; then - _err "You don't specify OPNsense token." - _err "Please create you OPNs_Token and try again." + _err "you have not specified your OPNsense token." + _err "Please create OPNs_Token and try again." return 1 else _saveaccountconf_mutable OPNs_Token "$OPNs_Token" fi if ! _opns_rest "GET" "/general/get"; then - _err "Can't Access OPNsense" + _err "Call to OPNsense API interface failed. Unable to access OPNsense API." return 1 fi return 0 From 0c76890572932edc06bf3fb39c9e329b2ceec326 Mon Sep 17 00:00:00 2001 From: Jesai Langenbach Date: Fri, 8 Nov 2019 08:52:10 +0100 Subject: [PATCH 117/357] whitespace fix --- dnsapi/dns_opnsense.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_opnsense.sh b/dnsapi/dns_opnsense.sh index 4fbe9447..9e4af15f 100755 --- a/dnsapi/dns_opnsense.sh +++ b/dnsapi/dns_opnsense.sh @@ -125,7 +125,7 @@ rm_record() { _info "Record not found, nothing to remove" fi - return 0 + return 0 } #################### Private functions below ################################## @@ -232,7 +232,7 @@ _opns_check_auth() { _saveaccountconf_mutable OPNs_Host "$OPNs_Host" fi - if ! printf '%s' "$OPNs_Port" | grep '^[0-9]*$' >/dev/null ; then + if ! printf '%s' "$OPNs_Port" | grep '^[0-9]*$' >/dev/null; then _err 'OPNs_Port specified but not numeric value' return 1 elif [ -z "$OPNs_Port" ]; then @@ -241,7 +241,7 @@ _opns_check_auth() { _saveaccountconf_mutable OPNs_Port "$OPNs_Port" fi - if ! printf '%s' "$OPNs_Api_Insecure" | grep '^[01]$' >/dev/null ; then + if ! printf '%s' "$OPNs_Api_Insecure" | grep '^[01]$' >/dev/null; then _err 'OPNs_Api_Insecure specified but not 0/1 value' return 1 elif [ -n "$OPNs_Api_Insecure" ]; then From 9cb328966c63d86565276e3ccc7d7e53d5101514 Mon Sep 17 00:00:00 2001 From: Jesai Langenbach Date: Fri, 8 Nov 2019 08:58:51 +0100 Subject: [PATCH 118/357] typo --- dnsapi/dns_opnsense.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_opnsense.sh b/dnsapi/dns_opnsense.sh index 9e4af15f..b2a3746f 100755 --- a/dnsapi/dns_opnsense.sh +++ b/dnsapi/dns_opnsense.sh @@ -114,11 +114,11 @@ rm_record() { _opns_rest "POST" "/service/reconfigure" "{}" _debug "Record deleted" else - _err "Error deleting record $host from domain $fulldomain" + _err "Error deleting record $_host from domain $fulldomain" return 1 fi else - _err "Error deleting record $host from domain $fulldomain" + _err "Error deleting record $_host from domain $fulldomain" return 1 fi else From f1f14040b85cb05330552d644c94890f6b82f2c3 Mon Sep 17 00:00:00 2001 From: Vitalii Tverdokhlib Date: Sat, 9 Nov 2019 12:12:30 +0200 Subject: [PATCH 119/357] DOCS: typo --- notify/mailgun.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notify/mailgun.sh b/notify/mailgun.sh index 4b6ee3ba..93cdf793 100644 --- a/notify/mailgun.sh +++ b/notify/mailgun.sh @@ -7,7 +7,7 @@ #MAILGUN_REGION="us|eu" #optional, use "us" as default #MAILGUN_API_DOMAIN="xxxxxx.com" #optional, use the default sandbox domain -#MAILGUN_FROM="xxx@xxxxx.com" #optional, use the default sendbox account +#MAILGUN_FROM="xxx@xxxxx.com" #optional, use the default sandbox account _MAILGUN_BASE_US="https://api.mailgun.net/v3" _MAILGUN_BASE_EU="https://api.eu.mailgun.net/v3" From 867ec010abe4aa4af349895a1d1ac93c3d0fba66 Mon Sep 17 00:00:00 2001 From: arlecchino Date: Tue, 12 Nov 2019 19:58:36 +0100 Subject: [PATCH 120/357] Fix callhook error in manual mode Fixes #1586 Check force manual switch before causing error about it. --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 81a20b0b..0164d54e 100755 --- a/acme.sh +++ b/acme.sh @@ -3365,7 +3365,7 @@ _on_issue_success() { fi fi - if _hasfield "$Le_Webroot" "$W_DNS"; then + if _hasfield "$Le_Webroot" "$W_DNS" && [ -z "$FORCE_DNS_MANUAL" ]; then _err "$_DNS_MANUAL_WARN" fi From adce8f52e8b71da504541bec2a10a607b9b3fac4 Mon Sep 17 00:00:00 2001 From: "John L. Villalovos" Date: Tue, 12 Nov 2019 08:48:41 -0800 Subject: [PATCH 121/357] debug_bash_helper: Use eval as busybox systems have problems In _debug_bash_helper use eval as we are seeing issues with busybox systems having issues with array access. Even though they aren't actually running the code they appear to be parsing it and failing. Also older versions of busybox have a bug with eval and double quotes, so make sure to use single quotes when using eval. Resolves: #2579 --- acme.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/acme.sh b/acme.sh index 81a20b0b..0c8ab903 100755 --- a/acme.sh +++ b/acme.sh @@ -268,31 +268,31 @@ _usage() { __debug_bash_helper() { # At this point only do for --debug 3 if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -lt "$DEBUG_LEVEL_3" ]; then - echo "" return fi # Return extra debug info when running with bash, otherwise return empty # string. if [ -z "${BASH_VERSION}" ]; then - echo "" return fi # We are a bash shell at this point, return the filename, function name, and # line number as a string _dbh_saveIFS=$IFS IFS=" " - # Must use eval or syntax error happens under dash + # Must use eval or syntax error happens under dash. The eval should use + # single quotes as older versions of busybox had a bug with double quotes and + # eval. # Use 'caller 1' as we want one level up the stack as we should be called # by one of the _debug* functions - eval "_dbh_called=($(caller 1))" + eval '_dbh_called=($(caller 1))' IFS=$_dbh_saveIFS - _dbh_file=${_dbh_called[2]} + eval '_dbh_file=${_dbh_called[2]}' if [ -n "${_script_home}" ]; then # Trim off the _script_home directory name - _dbh_file=${_dbh_file#$_script_home/} + eval '_dbh_file=${_dbh_file#$_script_home/}' fi - _dbh_function=${_dbh_called[1]} - _dbh_lineno=${_dbh_called[0]} + eval '_dbh_function=${_dbh_called[1]}' + eval '_dbh_lineno=${_dbh_called[0]}' printf "%-40s " "$_dbh_file:${_dbh_function}:${_dbh_lineno}" } From c282dd086fe0fc2152f7d47fb4ee1885f26aec09 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 16 Nov 2019 08:06:21 +0800 Subject: [PATCH 122/357] minor --- dnsapi/dns_nic.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_nic.sh b/dnsapi/dns_nic.sh index 493b05bc..e3b39b0c 100644 --- a/dnsapi/dns_nic.sh +++ b/dnsapi/dns_nic.sh @@ -89,7 +89,7 @@ dns_nic_rm() { return 1 fi - _domain_id=$(printf "%s" "$response" | grep "$_sub_domain" | grep "$txtvalue" | sed -r "s/.* Date: Tue, 26 Nov 2019 20:39:08 +1100 Subject: [PATCH 123/357] Added trailing slash to end of each line of DEPLOY_SCRIPT_CMD --- deploy/routeros.sh | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/deploy/routeros.sh b/deploy/routeros.sh index 21c9196f..2f349999 100644 --- a/deploy/routeros.sh +++ b/deploy/routeros.sh @@ -85,19 +85,19 @@ routeros_deploy() { scp "$_ckey" "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST:$_cdomain.key" _info "Trying to push cert '$_cfullchain' to router" scp "$_cfullchain" "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST:$_cdomain.cer" - DEPLOY_SCRIPT_CMD="/system script add name=\"LE Cert Deploy - $_cdomain\" owner=admin policy=ftp,read,write,password,sensitive -source=\"## generated by routeros deploy script in acme.sh -\n/certificate remove [ find name=$_cdomain.cer_0 ] -\n/certificate remove [ find name=$_cdomain.cer_1 ] -\ndelay 1 -\n/certificate import file-name=$_cdomain.cer passphrase=\\\"\\\" -\n/certificate import file-name=$_cdomain.key passphrase=\\\"\\\" -\ndelay 1 -\n/file remove $_cdomain.cer -\n/file remove $_cdomain.key -\ndelay 2 -\n/ip service set www-ssl certificate=$_cdomain.cer_0 -\n$ROUTER_OS_ADDITIONAL_SERVICES + DEPLOY_SCRIPT_CMD="/system script add name=\"LE Cert Deploy - $_cdomain\" owner=admin policy=ftp,read,write,password,sensitive \ +source=\"## generated by routeros deploy script in acme.sh;\ +\n/certificate remove [ find name=$_cdomain.cer_0 ];\ +\n/certificate remove [ find name=$_cdomain.cer_1 ];\ +\ndelay 1;\ +\n/certificate import file-name=$_cdomain.cer passphrase=\\\"\\\";\ +\n/certificate import file-name=$_cdomain.key passphrase=\\\"\\\";\ +\ndelay 1;\ +\n/file remove $_cdomain.cer;\ +\n/file remove $_cdomain.key;\ +\ndelay 2;\ +\n/ip service set www-ssl certificate=$_cdomain.cer_0;\ +\n$ROUTER_OS_ADDITIONAL_SERVICES;\ \n\" " # shellcheck disable=SC2029 From ec1f9841b21cd9aa7ca96aac4589472f3624f4eb Mon Sep 17 00:00:00 2001 From: Martin Kammerlander Date: Fri, 29 Nov 2019 22:22:26 +0100 Subject: [PATCH 124/357] Replace grep -A. --- dnsapi/dns_kas.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_kas.sh b/dnsapi/dns_kas.sh index 14c0b378..bf01fef3 100755 --- a/dnsapi/dns_kas.sh +++ b/dnsapi/dns_kas.sh @@ -69,13 +69,13 @@ dns_kas_rm() { _get_record_name "$_fulldomain" _get_record_id - # If there is a record_id, delete the entry + # If there is a record_id, delete the entry if [ -n "$_record_id" ]; then params="?kas_login=$KAS_Login" params="$params&kas_auth_type=$KAS_Authtype" params="$params&kas_auth_data=$KAS_Authdata" params="$params&kas_action=delete_dns_settings" - + # split it into a seperated list, if there where multiples entries made records=($_record_id) for i in "${records[@]}" @@ -150,7 +150,7 @@ _get_record_id() { response="$(_get "$KAS_Api$params")" _debug2 "response" "$response" - _record_id="$(echo "$response" | grep -A 4 "$_record_name" | grep "record_id" | cut -f2 -d">" | xargs)" + _record_id="$(echo "$response" | tr -d "\n\r" | sed "s/=> Array/\n=> Array/g" | tr -d " " | tr '[]' '<>' | grep "=>$_record_name<" | grep '>TXT<' | tr '<' '\n' | grep record_id | cut -d '>' -f 3)" _debug2 _record_id "$_record_id" return 0 -} \ No newline at end of file +} From c641b61b26f20771b044bf838ce5943fc163d8f7 Mon Sep 17 00:00:00 2001 From: Martin Kammerlander Date: Fri, 29 Nov 2019 22:46:44 +0100 Subject: [PATCH 125/357] Fix a few snytax issues --- dnsapi/dns_kas.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_kas.sh b/dnsapi/dns_kas.sh index bf01fef3..759b3aaa 100755 --- a/dnsapi/dns_kas.sh +++ b/dnsapi/dns_kas.sh @@ -78,8 +78,7 @@ dns_kas_rm() { # split it into a seperated list, if there where multiples entries made records=($_record_id) - for i in "${records[@]}" - do + for i in "${records[@]}"; do params2="$params&var1=record_id" params2="$params2&wert1=$i" _debug2 "Wait for 10 seconds by default before calling KAS API." @@ -95,7 +94,7 @@ dns_kas_rm() { _err "No record_id found that can be deleted. Please check manually." return 1 fi -return 0 + return 0 } ########################## PRIVATE FUNCTIONS ########################### From 953a9b17681a456ed4538f82e071eca3f713199d Mon Sep 17 00:00:00 2001 From: Martin Kammerlander Date: Fri, 29 Nov 2019 22:51:23 +0100 Subject: [PATCH 126/357] Remove obsolete blank. --- dnsapi/dns_kas.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_kas.sh b/dnsapi/dns_kas.sh index 759b3aaa..4f2b1d5a 100755 --- a/dnsapi/dns_kas.sh +++ b/dnsapi/dns_kas.sh @@ -149,7 +149,7 @@ _get_record_id() { response="$(_get "$KAS_Api$params")" _debug2 "response" "$response" - _record_id="$(echo "$response" | tr -d "\n\r" | sed "s/=> Array/\n=> Array/g" | tr -d " " | tr '[]' '<>' | grep "=>$_record_name<" | grep '>TXT<' | tr '<' '\n' | grep record_id | cut -d '>' -f 3)" + _record_id="$(echo "$response" | tr -d "\n\r" | sed "s/=> Array/\n=> Array/g" | tr -d " " | tr '[]' '<>' | grep "=>$_record_name<" | grep '>TXT<' | tr '<' '\n' | grep record_id | cut -d '>' -f 3)" _debug2 _record_id "$_record_id" return 0 } From 5014f83b86cf456869063043a526476dd9937d46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbyszek=20=C5=BB=C3=B3=C5=82kiewski?= Date: Fri, 6 Dec 2019 09:59:35 +0100 Subject: [PATCH 127/357] Fix case sensitive detection of domain in the response request --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 4d4957f5..07838b29 100755 --- a/acme.sh +++ b/acme.sh @@ -4082,7 +4082,7 @@ $_authorizations_map" if [ "$ACME_VERSION" = "2" ]; then _idn_d="$(_idn "$d")" - _candindates="$(echo "$_authorizations_map" | grep "^$_idn_d,")" + _candindates="$(echo "$_authorizations_map" | grep -i "^$_idn_d,")" _debug2 _candindates "$_candindates" if [ "$(echo "$_candindates" | wc -l)" -gt 1 ]; then for _can in $_candindates; do From 0ffd5de6fc4a414f207f532e0501929b009935ee Mon Sep 17 00:00:00 2001 From: Gustav Genberg Date: Sun, 8 Dec 2019 00:13:30 +0100 Subject: [PATCH 128/357] Fix add record error --- dnsapi/dns_unoeuro.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_unoeuro.sh b/dnsapi/dns_unoeuro.sh index 9132f136..c4593a63 100644 --- a/dnsapi/dns_unoeuro.sh +++ b/dnsapi/dns_unoeuro.sh @@ -52,7 +52,7 @@ dns_unoeuro_add() { fi _info "Adding record" - if _uno_rest POST "my/products/$h/dns/records" "{\"name\":\"$fulldomain\",\"type\":\"TXT\",\"data\":\"$txtvalue\",\"ttl\":120}"; then + if _uno_rest POST "my/products/$h/dns/records" "{\"name\":\"$fulldomain\",\"type\":\"TXT\",\"data\":\"$txtvalue\",\"ttl\":120,\"priority\":0}"; then if _contains "$response" "\"status\": 200" >/dev/null; then _info "Added, OK" return 0 From c22705a59392f11007bdd18b086520399794b6e6 Mon Sep 17 00:00:00 2001 From: Wout Date: Wed, 11 Dec 2019 17:13:11 +0100 Subject: [PATCH 129/357] Add DNS API support for Constellix. --- dnsapi/dns_constellix.sh | 137 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 dnsapi/dns_constellix.sh diff --git a/dnsapi/dns_constellix.sh b/dnsapi/dns_constellix.sh new file mode 100644 index 00000000..bc552316 --- /dev/null +++ b/dnsapi/dns_constellix.sh @@ -0,0 +1,137 @@ +#!/usr/bin/env sh + +# Author: Wout Decre + +CONSTELLIX_API="https://api.dns.constellix.com/v1" +#CONSTELLIX_KEY="XXX" +#CONSTELLIX_SECRET="XXX" + +######## Public functions ##################### + +dns_constellix_add() { + fulldomain=$1 + txtvalue=$2 + + CONSTELLIX_KEY="${CONSTELLIX_KEY:-$(_readaccountconf_mutable CONSTELLIX_KEY)}" + CONSTELLIX_SECRET="${CONSTELLIX_SECRET:-$(_readaccountconf_mutable CONSTELLIX_SECRET)}" + + if [ -z "$CONSTELLIX_KEY" ] || [ -z "$CONSTELLIX_SECRET" ]; then + _err "You did not specify the Contellix API key and secret yet." + return 1 + fi + + _saveaccountconf_mutable CONSTELLIX_KEY "$CONSTELLIX_KEY" + _saveaccountconf_mutable CONSTELLIX_SECRET "$CONSTELLIX_SECRET" + + if ! _get_root "$fulldomain"; then + _err "Invalid domain" + 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 + else + _err "Error adding TXT record" + return 1 + fi + fi +} + +dns_constellix_rm() { + fulldomain=$1 + txtvalue=$2 + + CONSTELLIX_KEY="${CONSTELLIX_KEY:-$(_readaccountconf_mutable CONSTELLIX_KEY)}" + CONSTELLIX_SECRET="${CONSTELLIX_SECRET:-$(_readaccountconf_mutable CONSTELLIX_SECRET)}" + + if [ -z "$CONSTELLIX_KEY" ] || [ -z "$CONSTELLIX_SECRET" ]; then + _err "You did not specify the Contellix API key and secret yet." + return 1 + fi + + if ! _get_root "$fulldomain"; then + _err "Invalid domain" + 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 + _info "Removed" + return 0 + else + _err "Error removing TXT record" + return 1 + fi + fi +} + +#################### Private functions below ################################## + +_get_root() { + domain=$1 + i=2 + p=1 + _debug "Detecting root zone" + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + if [ -z "$h" ]; then + return 1 + fi + + if ! _constellix_rest GET "domains"; then + return 1 + fi + + if _contains "$response" "\"name\":\"$h\""; then + _domain_id=$(printf "%s\n" "$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" + + _debug _domain_id "$_domain_id" + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + return 0 + fi + return 1 + fi + p=$i + i=$(_math "$i" + 1) + done + return 1 +} + +_constellix_rest() { + m=$1 + ep="$2" + data="$3" + _debug "$ep" + + rdate=$(date +"%s")"000" + hmac=$(printf "%s" "$rdate" | _hmac sha1 "$(printf "%s" "$CONSTELLIX_SECRET" | _hex_dump | tr -d ' ')" | _base64) + + export _H1="x-cnsdns-apiKey: $CONSTELLIX_KEY" + export _H2="x-cnsdns-requestDate: $rdate" + export _H3="x-cnsdns-hmac: $hmac" + export _H4="Accept: application/json" + export _H5="Content-Type: application/json" + + if [ "$m" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$CONSTELLIX_API/$ep" "" "$m")" + else + response="$(_get "$CONSTELLIX_API/$ep")" + fi + + if [ "$?" != "0" ]; then + _err "Error $ep" + return 1 + fi + + _debug response "$response" + return 0 +} From e8e6feeb0ffd273c20328bfa11a36f3f916c997a Mon Sep 17 00:00:00 2001 From: Wout Date: Wed, 11 Dec 2019 17:15:35 +0100 Subject: [PATCH 130/357] Use different e-mail. --- 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 bc552316..55f4a71b 100644 --- a/dnsapi/dns_constellix.sh +++ b/dnsapi/dns_constellix.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -# Author: Wout Decre +# Author: Wout Decre CONSTELLIX_API="https://api.dns.constellix.com/v1" #CONSTELLIX_KEY="XXX" From 3ccac629bcbb9f94602a7338891ec56ad9a1501d Mon Sep 17 00:00:00 2001 From: Martin Kammerlander Date: Thu, 12 Dec 2019 16:23:42 +0100 Subject: [PATCH 131/357] Change the loop for sh. --- dnsapi/dns_kas.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dnsapi/dns_kas.sh b/dnsapi/dns_kas.sh index 4f2b1d5a..a2dc0d5f 100755 --- a/dnsapi/dns_kas.sh +++ b/dnsapi/dns_kas.sh @@ -76,9 +76,7 @@ dns_kas_rm() { params="$params&kas_auth_data=$KAS_Authdata" params="$params&kas_action=delete_dns_settings" - # split it into a seperated list, if there where multiples entries made - records=($_record_id) - for i in "${records[@]}"; do + for i in $_record_id; do params2="$params&var1=record_id" params2="$params2&wert1=$i" _debug2 "Wait for 10 seconds by default before calling KAS API." From f37546e173e41827a7aab169de32124d4fdfd5e9 Mon Sep 17 00:00:00 2001 From: Siyuan Miao Date: Fri, 13 Dec 2019 18:46:09 +0800 Subject: [PATCH 132/357] add acme.sh support for misaka.io dns service --- dnsapi/dns_misaka.sh | 160 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100755 dnsapi/dns_misaka.sh diff --git a/dnsapi/dns_misaka.sh b/dnsapi/dns_misaka.sh new file mode 100755 index 00000000..7d83bf51 --- /dev/null +++ b/dnsapi/dns_misaka.sh @@ -0,0 +1,160 @@ +#!/usr/bin/env sh + +# bug reports to support+acmesh@misaka.io +# based on dns_nsone.sh by dev@1e.ca + +# +#Misaka_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" +# + +Misaka_Api="https://dnsapi.misaka.io/dns" + +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_misaka_add() { + fulldomain=$1 + txtvalue=$2 + + if [ -z "$Misaka_Key" ]; then + Misaka_Key="" + _err "You didn't specify misaka.io dns api key yet." + _err "Please create you key and try again." + return 1 + fi + + #save the api key and email to the account conf file. + _saveaccountconf Misaka_Key "$Misaka_Key" + + _debug "checking root zone [$fulldomain]" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting txt records" + _misaka_rest GET "zones/${_domain}/recordsets?search=${_sub_domain}" + + if ! _contains "$response" "\"results\":"; then + _err "Error" + return 1 + fi + + count=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"$_sub_domain\",[^{]*\"type\":\"TXT\"" | wc -l | tr -d " ") + _debug count "$count" + if [ "$count" = "0" ]; then + _info "Adding record" + + if _misaka_rest PUT "zones/${_domain}/recordsets/${_sub_domain}/TXT" "{\"records\":[{\"value\":\"\\\"$txtvalue\\\"\"}],\"filters\":[],\"ttl\":1}"; then + _debug response "$response" + if _contains "$response" "$_sub_domain"; then + _info "Added" + return 0 + else + _err "Add txt record error." + return 1 + fi + fi + _err "Add txt record error." + else + _info "Updating record" + + # todo: add existing challenges + _misaka_rest POST "zones/${_domain}/recordsets/${_sub_domain}/TXT" "{\"records\": [{\"value\": \"\\\"$txtvalue\\\"\"}],\"ttl\":1}" + if [ "$?" = "0" ] && _contains "$response" "$_sub_domain"; then + _info "Updated!" + #todo: check if the record takes effect + return 0 + fi + _err "Update error" + return 1 + fi + +} + +#fulldomain +dns_misaka_rm() { + fulldomain=$1 + txtvalue=$2 + _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" + _misaka_rest GET "zones/${_domain}/recordsets?search=${_sub_domain}" + + count=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"$_sub_domain\",[^{]*\"type\":\"TXT\"" | wc -l | tr -d " ") + _debug count "$count" + if [ "$count" = "0" ]; then + _info "Don't need to remove." + else + if ! _misaka_rest DELETE "zones/${_domain}/recordsets/${_sub_domain}/TXT"; then + _err "Delete record error." + return 1 + fi + _contains "$response" "" + fi +} + +#################### 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=2 + p=1 + if ! _misaka_rest GET "zones?limit=1000"; 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" "\"name\":\"$h\""; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain="$h" + return 0 + fi + p=$i + i=$(_math "$i" + 1) + done + return 1 +} + +_misaka_rest() { + m=$1 + ep="$2" + data="$3" + _debug "$ep" + + export _H1="Content-Type: application/json" + export _H2="User-Agent: acme.sh/$VER misaka-dns-acmesh/20191213" + export _H3="Authorization: Token $Misaka_Key" + + if [ "$m" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$Misaka_Api/$ep" "" "$m")" + else + response="$(_get "$Misaka_Api/$ep")" + fi + + if [ "$?" != "0" ]; then + _err "error $ep" + return 1 + fi + _debug2 response "$response" + return 0 +} From 375b8dceb70ab9fc32e4da4aa62fcb2cb3654284 Mon Sep 17 00:00:00 2001 From: Siyuan Miao Date: Sat, 14 Dec 2019 10:44:57 +0800 Subject: [PATCH 133/357] use append mode to update recordsets --- dnsapi/dns_misaka.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dnsapi/dns_misaka.sh b/dnsapi/dns_misaka.sh index 7d83bf51..eed4170e 100755 --- a/dnsapi/dns_misaka.sh +++ b/dnsapi/dns_misaka.sh @@ -61,8 +61,7 @@ dns_misaka_add() { else _info "Updating record" - # todo: add existing challenges - _misaka_rest POST "zones/${_domain}/recordsets/${_sub_domain}/TXT" "{\"records\": [{\"value\": \"\\\"$txtvalue\\\"\"}],\"ttl\":1}" + _misaka_rest POST "zones/${_domain}/recordsets/${_sub_domain}/TXT?append=true" "{\"records\": [{\"value\": \"\\\"$txtvalue\\\"\"}],\"ttl\":1}" if [ "$?" = "0" ] && _contains "$response" "$_sub_domain"; then _info "Updated!" #todo: check if the record takes effect From 549ebbb462caa0ad49f9936f28c51dd8191f1fd4 Mon Sep 17 00:00:00 2001 From: wurzelpanzer <32928046+wurzelpanzer@users.noreply.github.com> Date: Sat, 21 Dec 2019 20:19:02 +0100 Subject: [PATCH 134/357] Add easyDNS support --- dnsapi/dns_easydns.sh | 172 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 dnsapi/dns_easydns.sh diff --git a/dnsapi/dns_easydns.sh b/dnsapi/dns_easydns.sh new file mode 100644 index 00000000..1d905841 --- /dev/null +++ b/dnsapi/dns_easydns.sh @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +####################################################### +# +# easyDNS REST API for acme.sh by Neilpang based on dns_cf.sh +# +# Please note: # API is currently beta and subject to constant change +# http://sandbox.rest.easydns.net:3000/ +# +# Author: wurzelpanzer [wurzelpanzer@maximolider.net] +# Report Bugs here: https://github.com/Neilpang/acme.sh/issues/2647 +# +#################### Public functions ################# + +#EASYDNS_Key="xxxxxxxxxxxxxxxxxxxxxxxx" +#EASYDNS_Token="xxxxxxxxxxxxxxxxxxxxxxxx" +EASYDNS_Api="https://rest.easydns.net" + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_easydns_add() { + fulldomain=$1 + txtvalue=$2 + + EASYDNS_Token="${EASYDNS_Token:-$(_readaccountconf_mutable EASYDNS_Token)}" + EASYDNS_Key="${EASYDNS_Key:-$(_readaccountconf_mutable EASYDNS_Key)}" + + if [ -z "$EASYDNS_Token" ] || [ -z "$EASYDNS_Key" ]; then + _err "You didn't specify an easydns.net token or api key. Please sign up at http://docs.sandbox.rest.easydns.net/beta_signup.php" + return 1 + else + _saveaccountconf_mutable EASYDNS_Token "$EASYDNS_Token" + _saveaccountconf_mutable EASYDNS_Key "$EASYDNS_Key" + 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" + + _debug "Getting txt records" + _EASYDNS_rest GET "zones/records/all/${_domain}/search/${_sub_domain}" + + if ! printf "%s" "$response" | grep \"status\":200 >/dev/null; then + _err "Error" + return 1 + fi + + _info "Adding record" + if _EASYDNS_rest PUT "zones/records/add/$_domain/TXT" "{\"host\":\"$_sub_domain\",\"rdata\":\"$txtvalue\"}"; then + if _contains "$response" "\"status\":201"; then + _info "Added, OK" + return 0 + elif _contains "$response" "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 + +} + +dns_easydns_rm() { + fulldomain=$1 + txtvalue=$2 + + EASYDNS_Token="${EASYDNS_Token:-$(_readaccountconf_mutable EASYDNS_Token)}" + EASYDNS_Key="${EASYDNS_Key:-$(_readaccountconf_mutable EASYDNS_Key)}" + + _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" + _EASYDNS_rest GET "zones/records/all/${_domain}/search/${_sub_domain}" + + if ! printf "%s" "$response" | grep \"status\":200 >/dev/null; then + _err "Error" + return 1 + fi + + count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | 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 ! _EASYDNS_rest DELETE "zones/records/$_domain/$record_id"; then + _err "Delete record error." + return 1 + fi + _contains "$response" "\"status\":200" + 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 ! _EASYDNS_rest GET "zones/records/all/$h"; then + return 1 + fi + + if _contains "$response" "\"status\":200"; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain=$h + return 0 + fi + + p=$i + i=$(_math "$i" + 1) + done + return 1 +} + +_EASYDNS_rest() { + m=$1 + ep="$2" + data="$3" + _debug "$ep" + + basicauth=$(printf "%s" "$EASYDNS_Token":"$EASYDNS_Key" | _base64) + + export _H1="accept: application/json" + if [ "$basicauth" ]; then + export _H2="Authorization: Basic $basicauth" + fi + + if [ "$m" != "GET" ]; then + export _H3="Content-Type: application/json" + _debug data "$data" + response="$(_post "$data" "$EASYDNS_Api/$ep" "" "$m")" + else + response="$(_get "$EASYDNS_Api/$ep")" + fi + + if [ "$?" != "0" ]; then + _err "error $ep" + return 1 + fi + _debug2 response "$response" + return 0 +} From 594b83e7a646e6d5a8176e50712c688da31a8d6a Mon Sep 17 00:00:00 2001 From: Marco4223 Date: Sat, 28 Dec 2019 11:58:21 +0100 Subject: [PATCH 135/357] Update dns_kas.sh remove "rev" command fix "Error removing txt for domain:_acme-challenge.foo" --- dnsapi/dns_kas.sh | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/dnsapi/dns_kas.sh b/dnsapi/dns_kas.sh index a2dc0d5f..19bfd6bb 100755 --- a/dnsapi/dns_kas.sh +++ b/dnsapi/dns_kas.sh @@ -12,8 +12,7 @@ # Credits: Inspired by dns_he.sh. Thanks a lot man! # Git repo: https://github.com/phlegx/acme.sh # TODO: Better Error handling -# TODO: Does not work with Domains that have double endings like i.e. 'co.uk' -# => Get all root zones and compare once the provider offers that. +######################################################################## KAS_Api="https://kasapi.kasserver.com/dokumentation/formular.php" @@ -26,8 +25,7 @@ dns_kas_add() { _info "Adding or Updating $_fulldomain DNS TXT entry on All-inkl/Kasserver" _check_and_save - _get_zone "$_fulldomain" - _get_record_name "$_fulldomain" + _get_zone_and_record_name "$_fulldomain" _get_record_id _info "Creating TXT DNS record" @@ -65,8 +63,7 @@ dns_kas_rm() { _info "Removing $_fulldomain DNS TXT entry on All-inkl/Kasserver" _check_and_save - _get_zone "$_fulldomain" - _get_record_name "$_fulldomain" + _get_zone_and_record_name "$_fulldomain" _get_record_id # If there is a record_id, delete the entry @@ -116,20 +113,28 @@ _check_and_save() { return 0 } -# Gets back the base domain/zone. -# TODO Get a list of all possible root zones and compare (Currently not possible via provider) +# Gets back the base domain/zone and record name. # See: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide -_get_zone() { - _zone=$(echo "$1" | rev | cut -d . -f1-2 | rev). - return 0 -} - -# Removes the domain/subdomain from the entry since kasserver -# cannot handle _fulldomain -# TODO Get a list of all possible root zones and compare (Currently not possible via provider) -# See: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide -_get_record_name() { - _record_name=$(echo "$1" | rev | cut -d"." -f3- | rev) +_get_zone_and_record_name()() { + _zonen="$( cat testfile.txt | tr -d "\n\r" | tr -d " " | tr '[]' '<>' | sed "s/=>Array/\n=> Array/g" | tr ' ' '\n' | grep "domain_name" | tr '<' '\n' | grep "domain_name" | cut -d '>' -f 3)" + _domain="$1" + if _endswith "$_domain" "."; then + _domain="$(echo "$_domain" | sed 's/.$//')" + fi + _rootzone="$_domain" + for i in $_zonen; do + l1=${#_rootzone} + l2=${#i} + if _endswith "$_domain" "$i" && [ "$l1" -ge "$l2" ]; then + _rootzone="$i" + fi + done + _zone="$_rootzone" + _debug2 "zone:" "$_zone" + + l3=$((${#_domain}-l1-1)) + _record_name="$(echo "$_domain" | cut -c -"$l3")" + _debug2 "record_name:" "$_record_name" return 0 } @@ -146,8 +151,7 @@ _get_record_id() { sleep 10 response="$(_get "$KAS_Api$params")" _debug2 "response" "$response" - - _record_id="$(echo "$response" | tr -d "\n\r" | sed "s/=> Array/\n=> Array/g" | tr -d " " | tr '[]' '<>' | grep "=>$_record_name<" | grep '>TXT<' | tr '<' '\n' | grep record_id | cut -d '>' -f 3)" + _record_id="$(echo "$response" | tr -d "\n\r" | tr -d " " | tr '[]' '<>' | sed "s/=>Array/\n=> Array/g" | tr ' ' '\n' | grep "=>$_record_name<" | grep '>TXT<' | tr '<' '\n' | grep record_id | cut -d '>' -f 3)" _debug2 _record_id "$_record_id" return 0 } From 99c47dd50a7a41fa8ef519c23ee5fc94644135bf Mon Sep 17 00:00:00 2001 From: Marco4223 Date: Sat, 28 Dec 2019 22:42:51 +0100 Subject: [PATCH 136/357] Update dns_kas.sh only bash needed --- dnsapi/dns_kas.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_kas.sh b/dnsapi/dns_kas.sh index 19bfd6bb..a39f8c9e 100755 --- a/dnsapi/dns_kas.sh +++ b/dnsapi/dns_kas.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env sh +#!/bin/bash ######################################################################## # All-inkl Kasserver hook script for acme.sh # From a138425417fe76deb6eade981a6e4c240f9afc41 Mon Sep 17 00:00:00 2001 From: Marco4223 Date: Sat, 28 Dec 2019 23:42:46 +0100 Subject: [PATCH 137/357] Update dns_kas.sh sorry for this commit. ;) Fix NewBeMistakes --- dnsapi/dns_kas.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_kas.sh b/dnsapi/dns_kas.sh index a39f8c9e..437422bd 100755 --- a/dnsapi/dns_kas.sh +++ b/dnsapi/dns_kas.sh @@ -115,8 +115,8 @@ _check_and_save() { # Gets back the base domain/zone and record name. # See: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide -_get_zone_and_record_name()() { - _zonen="$( cat testfile.txt | tr -d "\n\r" | tr -d " " | tr '[]' '<>' | sed "s/=>Array/\n=> Array/g" | tr ' ' '\n' | grep "domain_name" | tr '<' '\n' | grep "domain_name" | cut -d '>' -f 3)" +_get_zone_and_record_name() { + _zonen="$( echo "$response" | tr -d "\n\r" | tr -d " " | tr '[]' '<>' | sed "s/=>Array/\n=> Array/g" | tr ' ' '\n' | grep "domain_name" | tr '<' '\n' | grep "domain_name" | cut -d '>' -f 3)" _domain="$1" if _endswith "$_domain" "."; then _domain="$(echo "$_domain" | sed 's/.$//')" From 2214507db01f547520fbed05afb3ecc1035c6fd3 Mon Sep 17 00:00:00 2001 From: Marco4223 Date: Sun, 29 Dec 2019 10:59:28 +0100 Subject: [PATCH 138/357] Revert "Update dns_kas.sh" This reverts commit 99c47dd50a7a41fa8ef519c23ee5fc94644135bf. --- dnsapi/dns_kas.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_kas.sh b/dnsapi/dns_kas.sh index 437422bd..5c7cd9ef 100755 --- a/dnsapi/dns_kas.sh +++ b/dnsapi/dns_kas.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env sh ######################################################################## # All-inkl Kasserver hook script for acme.sh # From a44ea0ddf0ea5ee46e2cf8a6dc54d79e0584639e Mon Sep 17 00:00:00 2001 From: gildea Date: Tue, 31 Dec 2019 20:22:08 -0800 Subject: [PATCH 139/357] Return failure when falling through limiting loop In _send_signed_request and _check_dns_entries, return 1 when the timeout (or number of retries) has been exhausted. This allows the calling function to correctly handle the error. --- acme.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 4d4957f5..902b39d4 100755 --- a/acme.sh +++ b/acme.sh @@ -2040,8 +2040,10 @@ _send_signed_request() { continue fi fi - break + return 0 done + _info "Giving up sending to CA server after $MAX_REQUEST_RETRY_TIMES retries." + return 1 } @@ -3819,9 +3821,11 @@ _check_dns_entries() { _sleep 10 else _info "All success, let's return" - break + return 0 fi done + _info "Timed out waiting for DNS." + return 1 } From b59b0f0386fd1b0a35dd68dce0d5d18054973e34 Mon Sep 17 00:00:00 2001 From: Tambet Liiv Date: Thu, 2 Jan 2020 14:55:36 +0200 Subject: [PATCH 140/357] use different method to get root --- dnsapi/dns_zone.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_zone.sh b/dnsapi/dns_zone.sh index 847e32cd..176fc494 100755 --- a/dnsapi/dns_zone.sh +++ b/dnsapi/dns_zone.sh @@ -136,10 +136,10 @@ _get_root() { if [ -z "$h" ]; then return 1 fi - if ! _zone_rest GET "dns/$h/a"; then + if ! _zone_rest GET "dns/$h"; then return 1 fi - if _contains "$response" "\"name\":\"$h\"" >/dev/null; then + if _contains "$response" "\"identificator\":\"$h\"" >/dev/null; then _domain=$h return 0 fi From 8dd1df71cc6cf59eaedbe9b2fd0a40279cb98f60 Mon Sep 17 00:00:00 2001 From: Marco4223 Date: Thu, 2 Jan 2020 17:10:36 +0100 Subject: [PATCH 141/357] Update dns_kas.sh tested and works now --- dnsapi/dns_kas.sh | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/dnsapi/dns_kas.sh b/dnsapi/dns_kas.sh index 5c7cd9ef..b17eeee4 100755 --- a/dnsapi/dns_kas.sh +++ b/dnsapi/dns_kas.sh @@ -13,19 +13,18 @@ # Git repo: https://github.com/phlegx/acme.sh # TODO: Better Error handling ######################################################################## - KAS_Api="https://kasapi.kasserver.com/dokumentation/formular.php" - ######## Public functions ##################### - -dns_kas_add() { +dns_kas_add(){ _fulldomain=$1 _txtvalue=$2 _info "Using DNS-01 All-inkl/Kasserver hook" _info "Adding or Updating $_fulldomain DNS TXT entry on All-inkl/Kasserver" - + _info "Check and Save Props" _check_and_save + _info "Checking Zone and Record_Name" _get_zone_and_record_name "$_fulldomain" + _info "Getting Record ID" _get_record_id _info "Creating TXT DNS record" @@ -61,11 +60,14 @@ dns_kas_rm() { _info "Using DNS-01 All-inkl/Kasserver hook" _info "Cleaning up after All-inkl/Kasserver hook" _info "Removing $_fulldomain DNS TXT entry on All-inkl/Kasserver" - + + _info "Check and Save Props" _check_and_save + _info "Checking Zone and Record_Name" _get_zone_and_record_name "$_fulldomain" + _info "Getting Record ID" _get_record_id - + # If there is a record_id, delete the entry if [ -n "$_record_id" ]; then params="?kas_login=$KAS_Login" @@ -116,11 +118,19 @@ _check_and_save() { # Gets back the base domain/zone and record name. # See: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide _get_zone_and_record_name() { - _zonen="$( echo "$response" | tr -d "\n\r" | tr -d " " | tr '[]' '<>' | sed "s/=>Array/\n=> Array/g" | tr ' ' '\n' | grep "domain_name" | tr '<' '\n' | grep "domain_name" | cut -d '>' -f 3)" + + params="?kas_login=$KAS_Login" + params="$params&kas_auth_type=$KAS_Authtype" + params="$params&kas_auth_data=$KAS_Authdata" + params="$params&kas_action=get_domains" + + _debug2 "Wait for 10 seconds by default before calling KAS API." + sleep 10 + response="$(_get "$KAS_Api$params")" + _debug2 "response" "$response" + _zonen="$( echo "$response" | tr -d "\n\r" | tr -d " " | tr '[]' '<>' | sed "s/=>Array/\n=> Array/g" | tr ' ' '\n' | grep "domain_name" | tr '<' '\n' | grep "domain_name" | sed "s/domain_name>=>//g")" _domain="$1" - if _endswith "$_domain" "."; then - _domain="$(echo "$_domain" | sed 's/.$//')" - fi + _temp_domain="$(echo "$1" | sed 's/\.$//')" _rootzone="$_domain" for i in $_zonen; do l1=${#_rootzone} @@ -129,12 +139,12 @@ _get_zone_and_record_name() { _rootzone="$i" fi done - _zone="$_rootzone" - _debug2 "zone:" "$_zone" - - l3=$((${#_domain}-l1-1)) - _record_name="$(echo "$_domain" | cut -c -"$l3")" - _debug2 "record_name:" "$_record_name" + _zone="${_rootzone}." + _temp_record_name="$(echo "$_temp_domain" | sed "s/"$_rootzone"//g")" + _record_name="$(echo "$_temp_record_name" | sed 's/\.$//')" + _debug2 "Zone:" "$_zone" + _debug2 "Domain:" "$_domain" + _debug2 "Record_Name:" "$_record_name" return 0 } @@ -151,7 +161,7 @@ _get_record_id() { sleep 10 response="$(_get "$KAS_Api$params")" _debug2 "response" "$response" - _record_id="$(echo "$response" | tr -d "\n\r" | tr -d " " | tr '[]' '<>' | sed "s/=>Array/\n=> Array/g" | tr ' ' '\n' | grep "=>$_record_name<" | grep '>TXT<' | tr '<' '\n' | grep record_id | cut -d '>' -f 3)" + _record_id="$(echo "$response" | tr -d "\n\r" | tr -d " " | tr '[]' '<>' | sed "s/=>Array/\n=> Array/g" | tr ' ' '\n' | grep "=>$_record_name<" | grep '>TXT<' | tr '<' '\n' | grep record_id | sed "s/record_id>=>//g")" _debug2 _record_id "$_record_id" return 0 } From 7a3c61b7449dfe57e079eb124fbe2e934139e132 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 3 Jan 2020 21:38:47 +0800 Subject: [PATCH 142/357] check upgrade hash https://github.com/Neilpang/acme.sh/issues/2667 --- acme.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/acme.sh b/acme.sh index fcebab7f..570e2836 100755 --- a/acme.sh +++ b/acme.sh @@ -6303,6 +6303,7 @@ _installOnline() { chmod +x $PROJECT_ENTRY if ./$PROJECT_ENTRY install "$_nocron" "" "$_noprofile"; then _info "Install success!" + _saveaccountconf "UPGRADE_HASH" "$(_getMasterHash)" fi cd .. @@ -6312,9 +6313,15 @@ _installOnline() { ) } +_getMasterHash() { + _hash_url="https://api.github.com/repos/Neilpang/acme.sh/git/refs/heads/master" + _get $_hash_url | tr -d "\r\n" | tr '{},' '\n' | grep '"sha":' | cut -d '"' -f 4 +} + upgrade() { if ( _initpath + [ -z "$FORCE" ] && [ "$(_getMasterHash)" = "$(_readaccountconf "UPGRADE_HASH")" ] && _info "Already uptodate!" && exit 0 export LE_WORKING_DIR cd "$LE_WORKING_DIR" _installOnline "nocron" "noprofile" From 8aedf26a87fff9aadf33df74fafa4615ea1106ef Mon Sep 17 00:00:00 2001 From: Ryan Meyers Date: Sat, 4 Jan 2020 10:51:32 -0600 Subject: [PATCH 143/357] Replace \s with hard space --- dnsapi/dns_linode_v4.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dnsapi/dns_linode_v4.sh b/dnsapi/dns_linode_v4.sh index ee7ee892..fc49bb6f 100755 --- a/dnsapi/dns_linode_v4.sh +++ b/dnsapi/dns_linode_v4.sh @@ -36,7 +36,7 @@ dns_linode_v4_add() { }" if _rest POST "/$_domain_id/records" "$_payload" && [ -n "$response" ]; then - _resource_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\s*[0-9]+" | cut -d : -f 2 | tr -d " " | _head_n 1) + _resource_id=$(printf "%s\n" "$response" | _egrep_o "\"id\": *[0-9]+" | cut -d : -f 2 | tr -d " " | _head_n 1) _debug _resource_id "$_resource_id" if [ -z "$_resource_id" ]; then @@ -74,9 +74,9 @@ dns_linode_v4_rm() { if _rest GET "/$_domain_id/records" && [ -n "$response" ]; then response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")" - resource="$(echo "$response" | _egrep_o "{.*\"name\":\s*\"$_sub_domain\".*}")" + resource="$(echo "$response" | _egrep_o "{.*\"name\": *\"$_sub_domain\".*}")" if [ "$resource" ]; then - _resource_id=$(printf "%s\n" "$resource" | _egrep_o "\"id\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ ) + _resource_id=$(printf "%s\n" "$resource" | _egrep_o "\"id\": *[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ ) if [ "$_resource_id" ]; then _debug _resource_id "$_resource_id" @@ -139,9 +139,9 @@ _get_root() { return 1 fi - hostedzone="$(echo "$response" | _egrep_o "{.*\"domain\":\s*\"$h\".*}")" + hostedzone="$(echo "$response" | _egrep_o "{.*\"domain\": *\"$h\".*}")" if [ "$hostedzone" ]; then - _domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "\"id\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ ) + _domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "\"id\": *[0-9]+" | _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 From 38a8721a91be420a5ce83b6b18558c79ee0eb48a Mon Sep 17 00:00:00 2001 From: Ryan Meyers Date: Sat, 4 Jan 2020 10:52:52 -0600 Subject: [PATCH 144/357] Escape opening brackets --- dnsapi/dns_linode_v4.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_linode_v4.sh b/dnsapi/dns_linode_v4.sh index fc49bb6f..c2bebc57 100755 --- a/dnsapi/dns_linode_v4.sh +++ b/dnsapi/dns_linode_v4.sh @@ -74,7 +74,7 @@ dns_linode_v4_rm() { if _rest GET "/$_domain_id/records" && [ -n "$response" ]; then response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")" - resource="$(echo "$response" | _egrep_o "{.*\"name\": *\"$_sub_domain\".*}")" + resource="$(echo "$response" | _egrep_o "\{.*\"name\": *\"$_sub_domain\".*}")" if [ "$resource" ]; then _resource_id=$(printf "%s\n" "$resource" | _egrep_o "\"id\": *[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ ) if [ "$_resource_id" ]; then @@ -139,7 +139,7 @@ _get_root() { return 1 fi - hostedzone="$(echo "$response" | _egrep_o "{.*\"domain\": *\"$h\".*}")" + hostedzone="$(echo "$response" | _egrep_o "\{.*\"domain\": *\"$h\".*}")" if [ "$hostedzone" ]; then _domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "\"id\": *[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ ) if [ "$_domain_id" ]; then From f174d7dd39ac0bc39f12e537e7c987afcaf950aa Mon Sep 17 00:00:00 2001 From: Silvan Raijer Date: Sun, 5 Jan 2020 15:27:04 +0100 Subject: [PATCH 145/357] dns_lexicon.sh: Add extra variable _API_KEY --- dnsapi/dns_lexicon.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dnsapi/dns_lexicon.sh b/dnsapi/dns_lexicon.sh index f6f54464..bb9f7efc 100755 --- a/dnsapi/dns_lexicon.sh +++ b/dnsapi/dns_lexicon.sh @@ -63,6 +63,16 @@ _lexicon_init() { _saveaccountconf_mutable "$Lx_domaintoken" "$Lx_domaintoken_v" eval export "$Lx_domaintoken" fi + + # shellcheck disable=SC2018,SC2019 + Lx_api_key=$(echo LEXICON_"${PROVIDER}"_API_KEY | tr 'a-z' 'A-Z') + eval "$Lx_api_key=\${$Lx_api_key:-$(_readaccountconf_mutable "$Lx_api_key")}" + Lx_api_key_v=$(eval echo \$"$Lx_api_key") + _secure_debug "$Lx_api_key" "$Lx_api_key_v" + if [ "$Lx_api_key_v" ]; then + _saveaccountconf_mutable "$Lx_api_key" "$Lx_api_key_v" + eval export "$Lx_api_key" + fi } ######## Public functions ##################### From c3fbc36ce7142e7013aa4bad3e2d2d4e8596bbca Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 6 Jan 2020 20:57:12 +0800 Subject: [PATCH 146/357] fix https://github.com/Neilpang/acme.sh/issues/2547#issuecomment-570963981 --- dnsapi/dns_nic.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_nic.sh b/dnsapi/dns_nic.sh index e3b39b0c..76e30a87 100644 --- a/dnsapi/dns_nic.sh +++ b/dnsapi/dns_nic.sh @@ -24,7 +24,7 @@ dns_nic_add() { return 1 fi - _saveaccountconf_mutable NIC_Customer "$NIC_Token" + _saveaccountconf_mutable NIC_Token "$NIC_Token" _saveaccountconf_mutable NIC_Username "$NIC_Username" _saveaccountconf_mutable NIC_Password "$NIC_Password" From a88622c1be477dead8175334c08aa450b8e75b1c Mon Sep 17 00:00:00 2001 From: Sergey Zorin Date: Mon, 6 Jan 2020 23:39:15 +0300 Subject: [PATCH 147/357] #2547 replace NIC_Token to NIC_ClientID&NIC_ClientSecret with backward compatibility --- dnsapi/dns_nic.sh | 86 +++++++++++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 32 deletions(-) diff --git a/dnsapi/dns_nic.sh b/dnsapi/dns_nic.sh index 76e30a87..4c3b280f 100644 --- a/dnsapi/dns_nic.sh +++ b/dnsapi/dns_nic.sh @@ -13,22 +13,8 @@ dns_nic_add() { fulldomain="${1}" txtvalue="${2}" - NIC_Token="${NIC_Token:-$(_readaccountconf_mutable NIC_Token)}" - NIC_Username="${NIC_Username:-$(_readaccountconf_mutable NIC_Username)}" - NIC_Password="${NIC_Password:-$(_readaccountconf_mutable NIC_Password)}" - if [ -z "$NIC_Token" ] || [ -z "$NIC_Username" ] || [ -z "$NIC_Password" ]; then - NIC_Token="" - NIC_Username="" - NIC_Password="" - _err "You must export variables: NIC_Token, NIC_Username and NIC_Password" - return 1 - fi - - _saveaccountconf_mutable NIC_Token "$NIC_Token" - _saveaccountconf_mutable NIC_Username "$NIC_Username" - _saveaccountconf_mutable NIC_Password "$NIC_Password" - if ! _nic_get_authtoken "$NIC_Username" "$NIC_Password" "$NIC_Token"; then + if ! _nic_get_authtoken save; then _err "get NIC auth token failed" return 1 fi @@ -59,18 +45,7 @@ dns_nic_rm() { fulldomain="${1}" txtvalue="${2}" - NIC_Token="${NIC_Token:-$(_readaccountconf_mutable NIC_Token)}" - NIC_Username="${NIC_Username:-$(_readaccountconf_mutable NIC_Username)}" - NIC_Password="${NIC_Password:-$(_readaccountconf_mutable NIC_Password)}" - if [ -z "$NIC_Token" ] || [ -z "$NIC_Username" ] || [ -z "$NIC_Password" ]; then - NIC_Token="" - NIC_Username="" - NIC_Password="" - _err "You must export variables: NIC_Token, NIC_Username and NIC_Password" - return 1 - fi - - if ! _nic_get_authtoken "$NIC_Username" "$NIC_Password" "$NIC_Token"; then + if ! _nic_get_authtoken; then _err "get NIC auth token failed" return 1 fi @@ -103,17 +78,64 @@ dns_nic_rm() { #################### Private functions below ################################## +#_nic_get_auth_elements [need2save] +_nic_get_auth_elements() { + _need2save=$1 + + NIC_ClientID="${NIC_ClientID:-$(_readaccountconf_mutable NIC_ClientID)}" + NIC_ClientSecret="${NIC_ClientSecret:-$(_readaccountconf_mutable NIC_ClientSecret)}" + NIC_Username="${NIC_Username:-$(_readaccountconf_mutable NIC_Username)}" + NIC_Password="${NIC_Password:-$(_readaccountconf_mutable NIC_Password)}" + + ## for backward compatibility + if [ -z "$NIC_ClientID" ] || [ -z "$NIC_ClientSecret" ]; then + NIC_Token="${NIC_Token:-$(_readaccountconf_mutable NIC_Token)}" + _debug NIC_Token "$NIC_Token" + if [ -n "$NIC_Token" ]; then + _two_values="$(echo "${NIC_Token}" | _dbase64)" + _debug _two_values "$_two_values" + IFS=":" read -r NIC_ClientID NIC_ClientSecret <<< $_two_values + _debug restored_NIC_ClientID "$NIC_ClientID" + _debug restored_NIC_ClientSecret "$NIC_ClientSecret" + fi + fi + + + if [ -z "$NIC_ClientID" ] || [ -z "$NIC_ClientSecret" ] || [ -z "$NIC_Username" ] || [ -z "$NIC_Password" ]; then + NIC_ClientID="" + NIC_ClientSecret="" + NIC_Username="" + NIC_Password="" + _err "You must export variables: NIC_ClientID, NIC_ClientSecret, NIC_Username and NIC_Password" + return 1 + fi + + if [ "$_need2save" ]; then + _saveaccountconf_mutable NIC_ClientID "$NIC_ClientID" + _saveaccountconf_mutable NIC_ClientSecret "$NIC_ClientSecret" + _saveaccountconf_mutable NIC_Username "$NIC_Username" + _saveaccountconf_mutable NIC_Password "$NIC_Password" + fi + + NIC_BasicAuth=$(printf "%s:%s" "${NIC_ClientID}" "${NIC_ClientSecret}" | _base64) + _debug NIC_BasicAuth "$NIC_BasicAuth" + +} + +#_nic_get_authtoken [need2save] _nic_get_authtoken() { - username="$1" - password="$2" - token="$3" + _need2save=$1 + + if ! _nic_get_auth_elements $_need2save; then + return 1 + fi _info "Getting NIC auth token" - export _H1="Authorization: Basic $token" + export _H1="Authorization: Basic ${NIC_BasicAuth}" export _H2="Content-Type: application/x-www-form-urlencoded" - res=$(_post "grant_type=password&username=$username&password=$password&scope=%28GET%7CPUT%7CPOST%7CDELETE%29%3A%2Fdns-master%2F.%2B" "$NIC_Api/oauth/token" "" "POST") + res=$(_post "grant_type=password&username=${NIC_Username}&password=${NIC_Password}&scope=%28GET%7CPUT%7CPOST%7CDELETE%29%3A%2Fdns-master%2F.%2B" "$NIC_Api/oauth/token" "" "POST") if _contains "$res" "access_token"; then _auth_token=$(printf "%s" "$res" | cut -d , -f2 | tr -d "\"" | sed "s/access_token://") _info "Token received" From 9666cf680e87df90238480ca960d2a7ff83692b3 Mon Sep 17 00:00:00 2001 From: Sergey Zorin Date: Mon, 6 Jan 2020 23:42:08 +0300 Subject: [PATCH 148/357] #2547 fix multiply _service selection --- dnsapi/dns_nic.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_nic.sh b/dnsapi/dns_nic.sh index 4c3b280f..9dba92c2 100644 --- a/dnsapi/dns_nic.sh +++ b/dnsapi/dns_nic.sh @@ -168,7 +168,7 @@ _get_root() { if _contains "$_all_domains" "^$h$"; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain=$h - _service=$(printf "%s" "$response" | grep "$_domain" | sed -r "s/.*service=\"(.*)\".*$/\1/") + _service=$(printf "%s" "$response" | grep -F "idn-name=\"$_domain\"" | sed -r "s/.*service=\"(.*)\".*$/\1/") return 0 fi p="$i" From c822870cf850936db13d2fb5a30be230c75209d5 Mon Sep 17 00:00:00 2001 From: Sergey Zorin Date: Mon, 6 Jan 2020 23:52:11 +0300 Subject: [PATCH 149/357] comment cleaning --- dnsapi/dns_nic.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_nic.sh b/dnsapi/dns_nic.sh index 9dba92c2..5629b3be 100644 --- a/dnsapi/dns_nic.sh +++ b/dnsapi/dns_nic.sh @@ -1,10 +1,9 @@ #!/usr/bin/env sh # -#NIC_Token="sdfsdfsdfljlbjkljlkjsdfoiwjedfglgkdlfgkfgldfkg" -# +#NIC_ClientID='0dc0xxxxxxxxxxxxxxxxxxxxxxxxce88' +#NIC_ClientSecret='3LTtxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxnuW8' #NIC_Username="000000/NIC-D" - #NIC_Password="xxxxxxx" NIC_Api="https://api.nic.ru" From 346454c21bdee14074001f6e2aa6e1b7686a0d5d Mon Sep 17 00:00:00 2001 From: Sergey Zorin Date: Tue, 7 Jan 2020 00:26:44 +0300 Subject: [PATCH 150/357] fix CI warnings --- dnsapi/dns_nic.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_nic.sh b/dnsapi/dns_nic.sh index 5629b3be..d0d6e546 100644 --- a/dnsapi/dns_nic.sh +++ b/dnsapi/dns_nic.sh @@ -12,7 +12,6 @@ dns_nic_add() { fulldomain="${1}" txtvalue="${2}" - if ! _nic_get_authtoken save; then _err "get NIC auth token failed" return 1 @@ -93,7 +92,7 @@ _nic_get_auth_elements() { if [ -n "$NIC_Token" ]; then _two_values="$(echo "${NIC_Token}" | _dbase64)" _debug _two_values "$_two_values" - IFS=":" read -r NIC_ClientID NIC_ClientSecret <<< $_two_values + IFS=":" read -r NIC_ClientID NIC_ClientSecret <<<"$_two_values" _debug restored_NIC_ClientID "$NIC_ClientID" _debug restored_NIC_ClientSecret "$NIC_ClientSecret" fi @@ -117,7 +116,7 @@ _nic_get_auth_elements() { fi NIC_BasicAuth=$(printf "%s:%s" "${NIC_ClientID}" "${NIC_ClientSecret}" | _base64) - _debug NIC_BasicAuth "$NIC_BasicAuth" + _debug NIC_BasicAuth "$NIC_BasicAuth" } @@ -125,7 +124,7 @@ _nic_get_auth_elements() { _nic_get_authtoken() { _need2save=$1 - if ! _nic_get_auth_elements $_need2save; then + if ! _nic_get_auth_elements "$_need2save"; then return 1 fi From 8e2f11389d7b17c90a04ef97b2bd1ddb28176960 Mon Sep 17 00:00:00 2001 From: Sergey Zorin Date: Tue, 7 Jan 2020 00:49:13 +0300 Subject: [PATCH 151/357] fix CI warnings SC2039 --- dnsapi/dns_nic.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_nic.sh b/dnsapi/dns_nic.sh index d0d6e546..34429fe4 100644 --- a/dnsapi/dns_nic.sh +++ b/dnsapi/dns_nic.sh @@ -92,7 +92,7 @@ _nic_get_auth_elements() { if [ -n "$NIC_Token" ]; then _two_values="$(echo "${NIC_Token}" | _dbase64)" _debug _two_values "$_two_values" - IFS=":" read -r NIC_ClientID NIC_ClientSecret <<<"$_two_values" + IFS=":" read -r NIC_ClientID NIC_ClientSecret < <(echo "$_two_values") _debug restored_NIC_ClientID "$NIC_ClientID" _debug restored_NIC_ClientSecret "$NIC_ClientSecret" fi From be7688a4dfae5dac8d95707e985aefbfbccfd50d Mon Sep 17 00:00:00 2001 From: Sergey Zorin Date: Tue, 7 Jan 2020 01:05:50 +0300 Subject: [PATCH 152/357] fix CI warnings SC2039 v2 --- dnsapi/dns_nic.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_nic.sh b/dnsapi/dns_nic.sh index 34429fe4..190d4d1f 100644 --- a/dnsapi/dns_nic.sh +++ b/dnsapi/dns_nic.sh @@ -92,7 +92,8 @@ _nic_get_auth_elements() { if [ -n "$NIC_Token" ]; then _two_values="$(echo "${NIC_Token}" | _dbase64)" _debug _two_values "$_two_values" - IFS=":" read -r NIC_ClientID NIC_ClientSecret < <(echo "$_two_values") + NIC_ClientID=$(echo "$_two_values" | cut -d':' -f1) + NIC_ClientSecret=$(echo "$_two_values" | cut -d':' -f2-) _debug restored_NIC_ClientID "$NIC_ClientID" _debug restored_NIC_ClientSecret "$NIC_ClientSecret" fi From f3dd1603db9f998f2496e2baee89bac0b9ac7615 Mon Sep 17 00:00:00 2001 From: Sergey Zorin Date: Tue, 7 Jan 2020 01:11:43 +0300 Subject: [PATCH 153/357] fix CI warnings v3 --- dnsapi/dns_nic.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_nic.sh b/dnsapi/dns_nic.sh index 190d4d1f..1ad18d5b 100644 --- a/dnsapi/dns_nic.sh +++ b/dnsapi/dns_nic.sh @@ -99,7 +99,6 @@ _nic_get_auth_elements() { fi fi - if [ -z "$NIC_ClientID" ] || [ -z "$NIC_ClientSecret" ] || [ -z "$NIC_Username" ] || [ -z "$NIC_Password" ]; then NIC_ClientID="" NIC_ClientSecret="" From efd3e8067b28c269517ec89e08d77284a8907931 Mon Sep 17 00:00:00 2001 From: Sergey Zorin Date: Thu, 9 Jan 2020 17:05:18 +0300 Subject: [PATCH 154/357] remove -F option --- dnsapi/dns_nic.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_nic.sh b/dnsapi/dns_nic.sh index 1ad18d5b..5052ee10 100644 --- a/dnsapi/dns_nic.sh +++ b/dnsapi/dns_nic.sh @@ -166,7 +166,7 @@ _get_root() { if _contains "$_all_domains" "^$h$"; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain=$h - _service=$(printf "%s" "$response" | grep -F "idn-name=\"$_domain\"" | sed -r "s/.*service=\"(.*)\".*$/\1/") + _service=$(printf "%s" "$response" | grep "idn-name=\"$_domain\"" | sed -r "s/.*service=\"(.*)\".*$/\1/") return 0 fi p="$i" From 0712e98904448fd16fc5aeaece54685d099f730d Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 12 Jan 2020 13:36:24 +0800 Subject: [PATCH 155/357] fix https://github.com/Neilpang/acme.sh/pull/2559 --- acme.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/acme.sh b/acme.sh index 570e2836..539e843d 100755 --- a/acme.sh +++ b/acme.sh @@ -2019,7 +2019,7 @@ _send_signed_request() { _debug code "$code" _debug2 original "$response" - if echo "$responseHeaders" | grep -i "Content-Type: application/json" >/dev/null 2>&1; then + if echo "$responseHeaders" | grep -i "Content-Type: *application/json" >/dev/null 2>&1; then response="$(echo "$response" | _normalizeJson)" fi _debug2 response "$response" @@ -3447,7 +3447,7 @@ _regAccount() { fi _debug2 responseHeaders "$responseHeaders" - _accUri="$(echo "$responseHeaders" | grep -i "^Location:" | _head_n 1 | cut -d ' ' -f 2 | tr -d "\r\n")" + _accUri="$(echo "$responseHeaders" | grep -i "^Location:" | _head_n 1 | cut -d ':' -f 2- | tr -d "\r\n ")" _debug "_accUri" "$_accUri" if [ -z "$_accUri" ]; then _err "Can not find account id url." @@ -4006,7 +4006,7 @@ issue() { _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)" + 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" @@ -4521,7 +4521,7 @@ $_authorizations_map" return 1 fi if [ -z "$Le_LinkOrder" ]; then - Le_LinkOrder="$(echo "$responseHeaders" | grep -i '^Location.*$' | _tail_n 1 | tr -d "\r\n" | cut -d " " -f 2)" + Le_LinkOrder="$(echo "$responseHeaders" | grep -i '^Location.*$' | _tail_n 1 | tr -d "\r\n" | cut -d ":" -f 2-)" fi _savedomainconf "Le_LinkOrder" "$Le_LinkOrder" @@ -5572,7 +5572,7 @@ _deactivate() { return 1 fi - authzUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ' ' -f 2 | tr -d "\r\n")" + 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" From 8494ac8f3dbe88123db60ab4441f27574d13f46e Mon Sep 17 00:00:00 2001 From: Nick Stepa Date: Sun, 12 Jan 2020 13:29:09 +0100 Subject: [PATCH 156/357] Fix dns records removing after usage. --- dnsapi/dns_yandex.sh | 128 ++++++++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 57 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index a4f39784..90bbf74e 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -6,83 +6,91 @@ # Values to export: # export PDD_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +# Sometimes cloudflare / google doesn't pick new dns recods fast enough. +# You can add --dnssleep XX to params as workaround. + ######## Public functions ##################### #Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_yandex_add() { - fulldomain="${1}" - txtvalue="${2}" - _debug "Calling: dns_yandex_add() '${fulldomain}' '${txtvalue}'" + local fulldomain="${1}" + local txtvalue="${2}" + _debug "Calling: dns_yandex_add() '${fulldomain}' '$txtvalue'" + _PDD_credentials || return 1 - export _H1="PddToken: $PDD_Token" _PDD_get_domain "$fulldomain" || return 1 - _debug "Found suitable domain in pdd: $curDomain" - curData="domain=${curDomain}&type=TXT&subdomain=${curSubdomain}&ttl=360&content=${txtvalue}" - curUri="https://pddimp.yandex.ru/api2/admin/dns/add" - curResult="$(_post "${curData}" "${curUri}")" - _debug "Result: $curResult" + _debug "Found suitable domain: $domain" + + _PDD_get_record_ids "${domain}" "${subdomain}" || return 1 + _debug "Record_ids: $record_ids" + + if [ ! -z "$record_ids" ]; then + _err "Remove all existing $subdomain records from $domain" + return 1 + fi + + local data="domain=${domain}&type=TXT&subdomain=${subdomain}&ttl=300&content=${txtvalue}" + local uri="https://pddimp.yandex.ru/api2/admin/dns/add" + local result="$(_post "${data}" "${uri}" | _normalizeJson)" + _debug "Result: $result" + + if ! _contains "$result" '"success":"ok"'; then + _err "Can't add $subdomain to $domain" + return 1 + fi } #Usage: dns_myapi_rm _acme-challenge.www.domain.com dns_yandex_rm() { - fulldomain="${1}" + local fulldomain="${1}" _debug "Calling: dns_yandex_rm() '${fulldomain}'" + _PDD_credentials || return 1 - export _H1="PddToken: $PDD_Token" _PDD_get_domain "$fulldomain" || return 1 - _debug "Found suitable domain in pdd: $curDomain" + _debug "Found suitable domain: $domain" - record_id=$(pdd_get_record_id "${fulldomain}") - _debug "Result: $record_id" + _PDD_get_record_ids "${domain}" "${subdomain}" || return 1 + _debug "Record_ids: $record_ids" - for rec_i in $record_id; do - curUri="https://pddimp.yandex.ru/api2/admin/dns/del" - curData="domain=${curDomain}&record_id=${rec_i}" - curResult="$(_post "${curData}" "${curUri}")" - _debug "Result: $curResult" + for record_id in $record_ids; do + local data="domain=${domain}&record_id=${record_id}" + local uri="https://pddimp.yandex.ru/api2/admin/dns/del" + local result="$(_post "${data}" "${uri}" | _normalizeJson)" + _debug "Result: $result" + + if ! _contains "$result" '"success":"ok"'; then + _info "Can't remove $subdomain from $domain" + fi done } #################### Private functions below ################################## _PDD_get_domain() { - fulldomain="${1}" - __page=1 - __last=0 - while [ $__last -eq 0 ]; do - uri1="https://pddimp.yandex.ru/api2/admin/domain/domains?page=${__page}&on_page=20" - res1="$(_get "$uri1" | _normalizeJson)" - _debug2 "res1" "$res1" - __found="$(echo "$res1" | sed -n -e 's#.* "found": \([^,]*\),.*#\1#p')" - _debug "found: $__found results on page" - if [ "0$__found" -lt 20 ]; then - _debug "last page: $__page" - __last=1 - fi + local fulldomain=${1} - __all_domains="$__all_domains $(echo "$res1" | tr "," "\n" | grep '"name"' | cut -d: -f2 | sed -e 's@"@@g')" + local subdomain_start=1 + while true; do + local domain_start=$(_math $subdomain_start + 1) + domain=$(echo "$fulldomain" | cut -d . -f $domain_start-) + subdomain=$(echo "$fulldomain" | cut -d . -f -$subdomain_start) - __page=$(_math $__page + 1) - done + _debug "Checking domain $domain" + if [ -z "$domain" ]; then + return 1 + fi + + local uri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=$domain" + local result="$(_get "${uri}" | _normalizeJson)" + _debug "Result: $result" - k=2 - while [ $k -lt 10 ]; do - __t=$(echo "$fulldomain" | cut -d . -f $k-100) - _debug "finding zone for domain $__t" - for d in $__all_domains; do - if [ "$d" = "$__t" ]; then - p=$(_math $k - 1) - curSubdomain="$(echo "$fulldomain" | cut -d . -f "1-$p")" - curDomain="$__t" + if _contains "$result" '"success":"ok"'; then return 0 - fi - done - k=$(_math $k + 1) + fi + subdomain_start=$(_math $subdomain_start + 1) done - _err "No suitable domain found in your account" - return 1 } _PDD_credentials() { @@ -94,16 +102,22 @@ _PDD_credentials() { else _saveaccountconf PDD_Token "${PDD_Token}" fi + export _H1="PddToken: $PDD_Token" } -pdd_get_record_id() { - fulldomain="${1}" +_PDD_get_record_ids() { + local domain="${1}" + local subdomain="${2}" + + _debug "Check existing records for $subdomain" - _PDD_get_domain "$fulldomain" - _debug "Found suitable domain in pdd: $curDomain" + local uri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${domain}" + local result="$(_get "${uri}" | _normalizeJson)" + _debug "Result: $result" + + if ! _contains "$result" '"success":"ok"'; then + return 1 + fi - curUri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${curDomain}" - curResult="$(_get "${curUri}" | _normalizeJson)" - _debug "Result: $curResult" - echo "$curResult" | _egrep_o "{[^{]*\"content\":[^{]*\"subdomain\":\"${curSubdomain}\"" | sed -n -e 's#.* "record_id": \(.*\),[^,]*#\1#p' + record_ids=$(echo "$result" | _egrep_o "{[^{]*\"subdomain\":\"${subdomain}\"[^}]*}" | sed -n -e 's#.*"record_id": \([0-9]*\).*#\1#p') } From ef7b51beb7d7c0e6607efca377e1089531aeb435 Mon Sep 17 00:00:00 2001 From: Nick Stepa Date: Sun, 12 Jan 2020 13:54:18 +0100 Subject: [PATCH 157/357] Remove local keyword. --- dnsapi/dns_yandex.sh | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index 90bbf74e..fc693d6e 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -6,15 +6,15 @@ # Values to export: # export PDD_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -# Sometimes cloudflare / google doesn't pick new dns recods fast enough. +# Sometimes cloudflare / google doesn't pick new dns records fast enough. # You can add --dnssleep XX to params as workaround. ######## Public functions ##################### #Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_yandex_add() { - local fulldomain="${1}" - local txtvalue="${2}" + fulldomain="${1}" + txtvalue="${2}" _debug "Calling: dns_yandex_add() '${fulldomain}' '$txtvalue'" _PDD_credentials || return 1 @@ -30,9 +30,9 @@ dns_yandex_add() { return 1 fi - local data="domain=${domain}&type=TXT&subdomain=${subdomain}&ttl=300&content=${txtvalue}" - local uri="https://pddimp.yandex.ru/api2/admin/dns/add" - local result="$(_post "${data}" "${uri}" | _normalizeJson)" + data="domain=${domain}&type=TXT&subdomain=${subdomain}&ttl=300&content=${txtvalue}" + uri="https://pddimp.yandex.ru/api2/admin/dns/add" + result="$(_post "${data}" "${uri}" | _normalizeJson)" _debug "Result: $result" if ! _contains "$result" '"success":"ok"'; then @@ -43,7 +43,7 @@ dns_yandex_add() { #Usage: dns_myapi_rm _acme-challenge.www.domain.com dns_yandex_rm() { - local fulldomain="${1}" + fulldomain="${1}" _debug "Calling: dns_yandex_rm() '${fulldomain}'" _PDD_credentials || return 1 @@ -55,9 +55,9 @@ dns_yandex_rm() { _debug "Record_ids: $record_ids" for record_id in $record_ids; do - local data="domain=${domain}&record_id=${record_id}" - local uri="https://pddimp.yandex.ru/api2/admin/dns/del" - local result="$(_post "${data}" "${uri}" | _normalizeJson)" + data="domain=${domain}&record_id=${record_id}" + uri="https://pddimp.yandex.ru/api2/admin/dns/del" + result="$(_post "${data}" "${uri}" | _normalizeJson)" _debug "Result: $result" if ! _contains "$result" '"success":"ok"'; then @@ -69,21 +69,21 @@ dns_yandex_rm() { #################### Private functions below ################################## _PDD_get_domain() { - local fulldomain=${1} + fulldomain=${1} - local subdomain_start=1 + subdomain_start=1 while true; do - local domain_start=$(_math $subdomain_start + 1) - domain=$(echo "$fulldomain" | cut -d . -f $domain_start-) - subdomain=$(echo "$fulldomain" | cut -d . -f -$subdomain_start) + domain_start=$(_math $subdomain_start + 1) + domain=$(echo "$fulldomain" | cut -d . -f "$domain_start"-) + subdomain=$(echo "$fulldomain" | cut -d . -f -"$subdomain_start") _debug "Checking domain $domain" if [ -z "$domain" ]; then return 1 fi - local uri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=$domain" - local result="$(_get "${uri}" | _normalizeJson)" + uri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=$domain" + result="$(_get "${uri}" | _normalizeJson)" _debug "Result: $result" if _contains "$result" '"success":"ok"'; then @@ -106,13 +106,13 @@ _PDD_credentials() { } _PDD_get_record_ids() { - local domain="${1}" - local subdomain="${2}" + domain="${1}" + subdomain="${2}" _debug "Check existing records for $subdomain" - local uri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${domain}" - local result="$(_get "${uri}" | _normalizeJson)" + uri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${domain}" + result="$(_get "${uri}" | _normalizeJson)" _debug "Result: $result" if ! _contains "$result" '"success":"ok"'; then From e5f69f0815b39d37e49188e659f3b0b6f4d9b58f Mon Sep 17 00:00:00 2001 From: Nick Stepa Date: Sun, 12 Jan 2020 14:07:49 +0100 Subject: [PATCH 158/357] Fix indentation. --- dnsapi/dns_yandex.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index fc693d6e..cf702ba8 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -26,8 +26,8 @@ dns_yandex_add() { _debug "Record_ids: $record_ids" if [ ! -z "$record_ids" ]; then - _err "Remove all existing $subdomain records from $domain" - return 1 + _err "Remove all existing $subdomain records from $domain" + return 1 fi data="domain=${domain}&type=TXT&subdomain=${subdomain}&ttl=300&content=${txtvalue}" @@ -36,8 +36,8 @@ dns_yandex_add() { _debug "Result: $result" if ! _contains "$result" '"success":"ok"'; then - _err "Can't add $subdomain to $domain" - return 1 + _err "Can't add $subdomain to $domain" + return 1 fi } @@ -87,7 +87,7 @@ _PDD_get_domain() { _debug "Result: $result" if _contains "$result" '"success":"ok"'; then - return 0 + return 0 fi subdomain_start=$(_math $subdomain_start + 1) done @@ -116,7 +116,7 @@ _PDD_get_record_ids() { _debug "Result: $result" if ! _contains "$result" '"success":"ok"'; then - return 1 + return 1 fi record_ids=$(echo "$result" | _egrep_o "{[^{]*\"subdomain\":\"${subdomain}\"[^}]*}" | sed -n -e 's#.*"record_id": \([0-9]*\).*#\1#p') From 4eff3b6a24efd9cae60183cbbde4b89eef8f391c Mon Sep 17 00:00:00 2001 From: Nick Stepa Date: Sun, 12 Jan 2020 15:16:48 +0100 Subject: [PATCH 159/357] Change error to info in case record already exists. --- dnsapi/dns_yandex.sh | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index cf702ba8..5721f994 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -15,19 +15,18 @@ dns_yandex_add() { fulldomain="${1}" txtvalue="${2}" - _debug "Calling: dns_yandex_add() '${fulldomain}' '$txtvalue'" + _debug "Calling: dns_yandex_add() '${fulldomain}' '${txtvalue}'" _PDD_credentials || return 1 - _PDD_get_domain "$fulldomain" || return 1 + _PDD_get_domain || return 1 _debug "Found suitable domain: $domain" - _PDD_get_record_ids "${domain}" "${subdomain}" || return 1 + _PDD_get_record_ids || return 1 _debug "Record_ids: $record_ids" if [ ! -z "$record_ids" ]; then - _err "Remove all existing $subdomain records from $domain" - return 1 + _info "All existing $subdomain records from $domain will be removed at the very end." fi data="domain=${domain}&type=TXT&subdomain=${subdomain}&ttl=300&content=${txtvalue}" @@ -36,8 +35,12 @@ dns_yandex_add() { _debug "Result: $result" if ! _contains "$result" '"success":"ok"'; then - _err "Can't add $subdomain to $domain" - return 1 + if _contains "$result" '"success":"error"' && _contains "$result" '"error":"record_exists"'; then + _info "Record already exists." + else + _err "Can't add $subdomain to $domain." + return 1 + fi fi } @@ -61,7 +64,7 @@ dns_yandex_rm() { _debug "Result: $result" if ! _contains "$result" '"success":"ok"'; then - _info "Can't remove $subdomain from $domain" + _info "Can't remove $subdomain from $domain." fi done } @@ -69,8 +72,6 @@ dns_yandex_rm() { #################### Private functions below ################################## _PDD_get_domain() { - fulldomain=${1} - subdomain_start=1 while true; do domain_start=$(_math $subdomain_start + 1) @@ -96,8 +97,8 @@ _PDD_get_domain() { _PDD_credentials() { if [ -z "${PDD_Token}" ]; then PDD_Token="" - _err "You need to export PDD_Token=xxxxxxxxxxxxxxxxx" - _err "You can get it at https://pddimp.yandex.ru/api2/admin/get_token" + _err "You need to export PDD_Token=xxxxxxxxxxxxxxxxx." + _err "You can get it at https://pddimp.yandex.ru/api2/admin/get_token." return 1 else _saveaccountconf PDD_Token "${PDD_Token}" @@ -106,9 +107,6 @@ _PDD_credentials() { } _PDD_get_record_ids() { - domain="${1}" - subdomain="${2}" - _debug "Check existing records for $subdomain" uri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${domain}" From 70fdb1042fd194e6e107e57d5ce1a670f3df0070 Mon Sep 17 00:00:00 2001 From: Andrey Tuzhilin Date: Tue, 14 Jan 2020 15:55:44 +0300 Subject: [PATCH 160/357] fix: added public dns zones filter --- dnsapi/dns_gcloud.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_gcloud.sh b/dnsapi/dns_gcloud.sh index ebbeecf2..6365b338 100755 --- a/dnsapi/dns_gcloud.sh +++ b/dnsapi/dns_gcloud.sh @@ -131,7 +131,7 @@ _dns_gcloud_find_zone() { filter="$filter$part. " part="$(echo "$part" | sed 's/[^.]*\.*//')" done - filter="$filter)" + filter="$filter) AND visibility=public" _debug filter "$filter" # List domains and find the zone with the deepest sub-domain (in case of some levels of delegation) From f01936ca4fac5499d90787098c2eec3a6359ab56 Mon Sep 17 00:00:00 2001 From: helbgd Date: Tue, 14 Jan 2020 15:19:37 +0100 Subject: [PATCH 161/357] Server Name not correct the servername of the server that has the upd.php file was not correct --- dnsapi/dns_ddnss.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_ddnss.sh b/dnsapi/dns_ddnss.sh index 903b9619..1bf258f5 100644 --- a/dnsapi/dns_ddnss.sh +++ b/dnsapi/dns_ddnss.sh @@ -12,7 +12,7 @@ # -- # -DDNSS_DNS_API="https://ddnss.de/upd.php" +DDNSS_DNS_API="https://www.ddnss.de/upd.php" ######## Public functions ##################### From b1ce6ffcc79da2d0b458a4195c10d1fd45a59182 Mon Sep 17 00:00:00 2001 From: helbgd Date: Tue, 14 Jan 2020 15:27:35 +0100 Subject: [PATCH 162/357] www is incorrect as well use ip4 and not www, if you use www it deletes the ip4 address of the host and updates only the ip6 address --- dnsapi/dns_ddnss.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_ddnss.sh b/dnsapi/dns_ddnss.sh index 1bf258f5..53781d0d 100644 --- a/dnsapi/dns_ddnss.sh +++ b/dnsapi/dns_ddnss.sh @@ -12,7 +12,7 @@ # -- # -DDNSS_DNS_API="https://www.ddnss.de/upd.php" +DDNSS_DNS_API="https://ip4.ddnss.de/upd.php" ######## Public functions ##################### From 024619676b73e2cf20527471c6209c924d63c0e4 Mon Sep 17 00:00:00 2001 From: Marco4223 Date: Wed, 15 Jan 2020 13:56:01 +0100 Subject: [PATCH 163/357] Update dns_kas.sh fixing 4 Travis style --- dnsapi/dns_kas.sh | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/dnsapi/dns_kas.sh b/dnsapi/dns_kas.sh index b17eeee4..31d68e62 100755 --- a/dnsapi/dns_kas.sh +++ b/dnsapi/dns_kas.sh @@ -9,17 +9,18 @@ # - $KAS_Authdata (Kasserver API auth data.) # # Author: Martin Kammerlander, Phlegx Systems OG +# Updated by: Marc-Oliver Lange # Credits: Inspired by dns_he.sh. Thanks a lot man! # Git repo: https://github.com/phlegx/acme.sh # TODO: Better Error handling ######################################################################## KAS_Api="https://kasapi.kasserver.com/dokumentation/formular.php" -######## Public functions ##################### -dns_kas_add(){ +######## Public functions ##################### +dns_kas_add() { _fulldomain=$1 _txtvalue=$2 _info "Using DNS-01 All-inkl/Kasserver hook" - _info "Adding or Updating $_fulldomain DNS TXT entry on All-inkl/Kasserver" + _info "Adding $_fulldomain DNS TXT entry on All-inkl/Kasserver" _info "Check and Save Props" _check_and_save _info "Checking Zone and Record_Name" @@ -128,9 +129,9 @@ _get_zone_and_record_name() { sleep 10 response="$(_get "$KAS_Api$params")" _debug2 "response" "$response" - _zonen="$( echo "$response" | tr -d "\n\r" | tr -d " " | tr '[]' '<>' | sed "s/=>Array/\n=> Array/g" | tr ' ' '\n' | grep "domain_name" | tr '<' '\n' | grep "domain_name" | sed "s/domain_name>=>//g")" + _zonen="$(echo "$response" | tr -d "\n\r" | tr -d " " | tr '[]' '<>' | sed "s/=>Array/\n=> Array/g" | tr ' ' '\n' | grep "domain_name" | tr '<' '\n' | grep "domain_name" | sed "s/domain_name>=>//g")" _domain="$1" - _temp_domain="$(echo "$1" | sed 's/\.$//')" + _temp_domain="$(echo "$1" | sed 's/\.$//')" _rootzone="$_domain" for i in $_zonen; do l1=${#_rootzone} @@ -140,8 +141,8 @@ _get_zone_and_record_name() { fi done _zone="${_rootzone}." - _temp_record_name="$(echo "$_temp_domain" | sed "s/"$_rootzone"//g")" - _record_name="$(echo "$_temp_record_name" | sed 's/\.$//')" + _temp_record_name="$(echo "$_temp_domain" | sed "s/$_rootzone//g")" + _record_name="$(echo "$_temp_record_name" | sed 's/\.$//')" _debug2 "Zone:" "$_zone" _debug2 "Domain:" "$_domain" _debug2 "Record_Name:" "$_record_name" From ac3667c7652a6338aba1528de4a4dd7b0d77e8cd Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 15 Jan 2020 21:43:49 +0800 Subject: [PATCH 164/357] fix https://github.com/Neilpang/acme.sh/issues/2693 --- acme.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/acme.sh b/acme.sh index 539e843d..f461c575 100755 --- a/acme.sh +++ b/acme.sh @@ -6303,6 +6303,7 @@ _installOnline() { chmod +x $PROJECT_ENTRY if ./$PROJECT_ENTRY install "$_nocron" "" "$_noprofile"; then _info "Install success!" + _initpath _saveaccountconf "UPGRADE_HASH" "$(_getMasterHash)" fi From f8f53a6bd99d50293bc775fb74fcee9bde8a1280 Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 15 Jan 2020 22:01:34 +0800 Subject: [PATCH 165/357] debug --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index f461c575..cae7c30e 100755 --- a/acme.sh +++ b/acme.sh @@ -2415,7 +2415,7 @@ __initHome() { if [ -z "$ACCOUNT_CONF_PATH" ]; then ACCOUNT_CONF_PATH="$_DEFAULT_ACCOUNT_CONF_PATH" fi - + _debug3 ACCOUNT_CONF_PATH "$ACCOUNT_CONF_PATH" DEFAULT_LOG_FILE="$LE_CONFIG_HOME/$PROJECT_NAME.log" DEFAULT_CA_HOME="$LE_CONFIG_HOME/ca" From 26309f51e380c0c60798a62ba1842b1263cc6fcf Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 15 Jan 2020 22:04:49 +0800 Subject: [PATCH 166/357] start 2.8.5 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 539e843d..547d4a1d 100755 --- a/acme.sh +++ b/acme.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -VER=2.8.4 +VER=2.8.5 PROJECT_NAME="acme.sh" From 431c53efcf6f8ee4ae011b572729b624c9c86ace Mon Sep 17 00:00:00 2001 From: Marco4223 Date: Wed, 15 Jan 2020 17:48:30 +0100 Subject: [PATCH 167/357] Update dns_kas.sh Removing spaces in empty lines --- dnsapi/dns_kas.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_kas.sh b/dnsapi/dns_kas.sh index 31d68e62..95401684 100755 --- a/dnsapi/dns_kas.sh +++ b/dnsapi/dns_kas.sh @@ -61,14 +61,14 @@ dns_kas_rm() { _info "Using DNS-01 All-inkl/Kasserver hook" _info "Cleaning up after All-inkl/Kasserver hook" _info "Removing $_fulldomain DNS TXT entry on All-inkl/Kasserver" - + _info "Check and Save Props" _check_and_save _info "Checking Zone and Record_Name" _get_zone_and_record_name "$_fulldomain" _info "Getting Record ID" _get_record_id - + # If there is a record_id, delete the entry if [ -n "$_record_id" ]; then params="?kas_login=$KAS_Login" @@ -119,7 +119,7 @@ _check_and_save() { # Gets back the base domain/zone and record name. # See: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide _get_zone_and_record_name() { - + params="?kas_login=$KAS_Login" params="?kas_login=$KAS_Login" params="$params&kas_auth_type=$KAS_Authtype" params="$params&kas_auth_data=$KAS_Authdata" From 0f54cf83f4f24f037e1adf52be37c9e809df4825 Mon Sep 17 00:00:00 2001 From: StefanAbl Date: Sat, 18 Jan 2020 13:48:29 +0100 Subject: [PATCH 168/357] fixed dynv6 dns validation --- dnsapi/dns_dynv6.sh | 125 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 dnsapi/dns_dynv6.sh diff --git a/dnsapi/dns_dynv6.sh b/dnsapi/dns_dynv6.sh new file mode 100644 index 00000000..b1fa7650 --- /dev/null +++ b/dnsapi/dns_dynv6.sh @@ -0,0 +1,125 @@ +#!/usr/bin/env sh +#Author StefanAbl +#Usage specify a private keyfile to use with dynv6 'export KEY="path/to/keyfile"' +#if no keyfile is specified, you will be asked if you want to create one in /home/$USER/.ssh/dynv6 and /home/$USER/.ssh/dynv6.pub +######## Public functions ##################### +# Please Read this guide first: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide +#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_dynv6_add() { + fulldomain=$1 + txtvalue=$2 + _info "Using dynv6 api" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + _get_keyfile + + _info "using keyfile $dynv6_keyfile" + _get_domain "$fulldomain" + _your_hosts="$(ssh -i "$dynv6_keyfile" api@dynv6.com hosts)" + if ! _contains "$_your_hosts" "$_host"; then + _debug "The host is $_host and the record $_record" + _debug "Dynv6 returned $_your_hosts" + _err "The host $_host does not exists on your dynv6 account" + return 1 + fi + _debug "found host on your account" + returnval="$(ssh -i "$dynv6_keyfile" api@dynv6.com hosts \""$_host"\" records set \""$_record"\" txt data \""$txtvalue"\")" + _debug "Dynv6 returend this after record was added: $returnval" + if _contains "$returnval" "created"; then + return 0 + elif _contains "$returnval" "updated"; then + return 0 + else + _err "Something went wrong! it does not seem like the record was added succesfully" + return 1 + fi + return 1 +} +#Usage: fulldomain txtvalue +#Remove the txt record after validation. +dns_dynv6_rm() { + fulldomain=$1 + txtvalue=$2 + _info "Using dynv6 api" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + _get_keyfile + _info "using keyfile $dynv6_keyfile" + _get_domain "$fulldomain" + _your_hosts="$(ssh -i "$dynv6_keyfile" api@dynv6.com hosts)" + if ! _contains "$_your_hosts" "$_host"; then + _debug "The host is $_host and the record $_record" + _debug "Dynv6 returned $_your_hosts" + _err "The host $_host does not exists on your dynv6 account" + return 1 + fi + _debug "found host on your account" + _info "$(ssh -i "$dynv6_keyfile" api@dynv6.com hosts "\"$_host\"" records del "\"$_record\"" txt)" + return 0 + +} +#################### Private functions below ################################## +#Usage: No Input required +#returns +#dynv6_keyfile the path to the new keyfile that has been generated +_generate_new_key() { + dynv6_keyfile="$(eval echo ~"$USER")/.ssh/dynv6" + _info "Path to key file used: $dynv6_keyfile" + if [ ! -f "$dynv6_keyfile" ] && [ ! -f "$dynv6_keyfile.pub" ]; then + _debug "generating key in $dynv6_keyfile and $dynv6_keyfile.pub" + ssh-keygen -f "$dynv6_keyfile" -t ssh-ed25519 -N '' + else + _err "There is already a file in $dynv6_keyfile or $dynv6_keyfile.pub" + return 1 + fi + +} +#Usage: _acme-challenge.www.example.dynv6.net +#returns +#_host= example.dynv6.net +#_record=_acme-challenge.www +#aborts if not a valid domain +_get_domain() { + _full_domain="$1" + _debug "getting domain for $_full_domain" + if ! _contains "$_full_domain" 'dynv6.net' && ! _contains "$_full_domain" 'dns.army' && ! _contains "$_full_domain" 'dns.navy'; then + _err "The hosts does not seem to be a dynv6 host" + return 1 + fi + _record="${_full_domain%.*}" + _record="${_record%.*}" + _record="${_record%.*}" + _debug "The record we are ging to use is $_record" + _host="$_full_domain" + while [ "$(echo "$_host" | grep -o '\.' | wc -l)" != "2" ]; do + _host="${_host#*.}" + done + _debug "And the host is $_host" + return 0 + +} + +# Usage: No input required +#returns +#dynv6_keyfile path to the key that will be used +_get_keyfile() { + _debug "get keyfile method called" + dynv6_keyfile="${dynv6_keyfile:-$(_readaccountconf_mutable dynv6_keyfile)}" + _debug Your key is "$dynv6_keyfile" + if [ -z "$dynv6_keyfile" ]; then + if [ -z "$KEY" ]; then + _err "You did not specify a key to use with dynv6" + _info "Creating new dynv6 api key to add to dynv6.com" + _generate_new_key + _info "Please add this key to dynv6.com $(cat "$dynv6_keyfile.pub")" + _info "Hit Enter to contiue" + read _ + #save the credentials to the account conf file. + else + dynv6_keyfile="$KEY" + fi + _saveaccountconf_mutable dynv6_keyfile "$dynv6_keyfile" + fi + + +} From 6e3ba3ca45daaa47f2afe901647585bb6d5c2010 Mon Sep 17 00:00:00 2001 From: StefanAbl Date: Sat, 18 Jan 2020 13:53:26 +0100 Subject: [PATCH 169/357] travis --- dnsapi/dns_dynv6.sh | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/dnsapi/dns_dynv6.sh b/dnsapi/dns_dynv6.sh index b1fa7650..cf39282b 100644 --- a/dnsapi/dns_dynv6.sh +++ b/dnsapi/dns_dynv6.sh @@ -12,7 +12,6 @@ dns_dynv6_add() { _debug fulldomain "$fulldomain" _debug txtvalue "$txtvalue" _get_keyfile - _info "using keyfile $dynv6_keyfile" _get_domain "$fulldomain" _your_hosts="$(ssh -i "$dynv6_keyfile" api@dynv6.com hosts)" @@ -72,7 +71,6 @@ _generate_new_key() { _err "There is already a file in $dynv6_keyfile or $dynv6_keyfile.pub" return 1 fi - } #Usage: _acme-challenge.www.example.dynv6.net #returns @@ -103,7 +101,7 @@ _get_domain() { #returns #dynv6_keyfile path to the key that will be used _get_keyfile() { - _debug "get keyfile method called" + _debug "get keyfile method called" dynv6_keyfile="${dynv6_keyfile:-$(_readaccountconf_mutable dynv6_keyfile)}" _debug Your key is "$dynv6_keyfile" if [ -z "$dynv6_keyfile" ]; then @@ -113,13 +111,11 @@ _get_keyfile() { _generate_new_key _info "Please add this key to dynv6.com $(cat "$dynv6_keyfile.pub")" _info "Hit Enter to contiue" - read _ + read -r _ #save the credentials to the account conf file. else dynv6_keyfile="$KEY" fi _saveaccountconf_mutable dynv6_keyfile "$dynv6_keyfile" fi - - } From e7d130cc11e4a52695e84fd1ea86d7c27a090b18 Mon Sep 17 00:00:00 2001 From: Radek SPRTA Date: Tue, 21 Jan 2020 06:36:31 +0100 Subject: [PATCH 170/357] Add support for CloudDNS API --- dnsapi/dns_clouddns.sh | 186 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100755 dnsapi/dns_clouddns.sh diff --git a/dnsapi/dns_clouddns.sh b/dnsapi/dns_clouddns.sh new file mode 100755 index 00000000..2678c66b --- /dev/null +++ b/dnsapi/dns_clouddns.sh @@ -0,0 +1,186 @@ +#!/usr/bin/env sh + +# Author: Radek Sprta + +#CLOUDDNS_EMAIL=XXXXX +#CLOUDDNS_PASSWORD="YYYYYYYYY" +#CLOUDDNS_CLIENT_ID=XXXXX + +CLOUDDNS_API='https://admin.vshosting.cloud/clouddns' +CLOUDDNS_LOGIN_API='https://admin.vshosting.cloud/api/public/auth/login' + +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_clouddns_add() { + fulldomain=$1 + txtvalue=$2 + + CLOUDDNS_CLIENT_ID="${CLOUDDNS_CLIENT_ID:-$(_readaccountconf_mutable CLOUDDNS_CLIENT_ID)}" + CLOUDDNS_EMAIL="${CLOUDDNS_EMAIL:-$(_readaccountconf_mutable CLOUDDNS_EMAIL)}" + CLOUDDNS_PASSWORD="${CLOUDDNS_PASSWORD:-$(_readaccountconf_mutable CLOUDDNS_PASSWORD)}" + + if [ -z "$CLOUDDNS_PASSWORD" ] || [ -z "$CLOUDDNS_EMAIL" ] || [ -z "$CLOUDDNS_CLIENT_ID" ]; then + CLOUDDNS_CLIENT_ID="" + CLOUDDNS_EMAIL="" + CLOUDDNS_PASSWORD="" + _err "You didn't specify a CloudDNS password, email and client id yet." + return 1 + fi + if ! _contains "$CLOUDDNS_EMAIL" "@"; then + _err "It seems that the CLOUDDNS_EMAIL=$CLOUDDNS_EMAIL is not a valid email address." + _err "Please check and retry." + return 1 + fi + # Save CloudDNS client id, email and password to config file + _saveaccountconf_mutable CLOUDDNS_CLIENT_ID "$CLOUDDNS_CLIENT_ID" + _saveaccountconf_mutable CLOUDDNS_EMAIL "$CLOUDDNS_EMAIL" + _saveaccountconf_mutable CLOUDDNS_PASSWORD "$CLOUDDNS_PASSWORD" + + _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" + + # For wildcard cert, the main root domain and the wildcard domain have the same txt subdomain name, so + # we can not use updating anymore. + _info "Adding record" + if _clouddns_api POST "record-txt" "{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"value\":\"$txtvalue\",\"domainId\":\"$_domain_id\"}"; then + if _contains "$response" "$txtvalue"; then + _info "Added, OK" + elif _contains "$response" '"code":4136'; then + _info "Already exists, OK" + else + _err "Add txt record error." + return 1 + fi + fi + + # Publish challenge record + _debug "Publishing record changes" + _clouddns_api PUT "domain/$_domain_id/publish" "{\"soaTtl\":300}" +} + +#fulldomain txtvalue +dns_clouddns_rm() { + fulldomain=$1 + txtvalue=$2 + + CLOUDDNS_CLIENT_ID="${CLOUDDNS_CLIENT_ID:-$(_readaccountconf_mutable CLOUDDNS_CLIENT_ID)}" + CLOUDDNS_EMAIL="${CLOUDDNS_EMAIL:-$(_readaccountconf_mutable CLOUDDNS_EMAIL)}" + CLOUDDNS_PASSWORD="${CLOUDDNS_PASSWORD:-$(_readaccountconf_mutable CLOUDDNS_PASSWORD)}" + + _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" + + # Get record Id + response="$(_clouddns_api GET "domain/$_domain_id" | tr -d '\t\r\n ')" + _debug response "$response" + if _contains "$response" "lastDomainRecordList"; then + re="\"lastDomainRecordList\".*\"id\":\"([^\"}]*)\"[^}]*\"name\":\"$fulldomain.\"," + _last_domains=$(echo "$response" | _egrep_o "$re") + re2="\"id\":\"([^\"}]*)\"[^}]*\"name\":\"$fulldomain.\"," + _record_id=$(echo "$_last_domains" | _egrep_o "$re2" | _head_n 1 | cut -d : -f 2 | cut -d , -f 1 | tr -d "\"") + _debug _record_id "$_record_id" + else + _err "Could not retrieve record id" + return 1 + fi + + _info "Removing record" + if _clouddns_api DELETE "record/$_record_id"; then + if _contains "$response" "\"error\":"; then + _err "Could not remove record" + return 1 + fi + fi + + # Publish challenge record + _debug "Publishing record changes" + _clouddns_api PUT "domain/$_domain_id/publish" "{\"soaTtl\":300}" +} + +#################### Private functions below ################################## +#_acme-challenge.www.domain.com +#returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +# _domain_id=sdjkglgdfewsdfg +_get_root() { + domain=$1 + domain_root=$(echo "$fulldomain" | _egrep_o '\.([^\.]*\.[^\.]*)$' | cut -c 2-) + _debug domain_root "$domain_root" + + # Get domain id + data="{\"search\": [{\"name\": \"clientId\", \"operator\": \"eq\", \"value\": \"$CLOUDDNS_CLIENT_ID\"}, \ + {\"name\": \"domainName\", \"operator\": \"eq\", \"value\": \"$domain_root.\"}]}" + response="$(_clouddns_api "POST" "domain/search" "$data" | tr -d '\t\r\n ')" + _debug "Domain id $response" + + if _contains "$response" "\"id\":\""; then + re='domainType\":\"[^\"]*\",\"id\":\"([^\"]*)\",' # Match domain id + _domain_id=$(echo "$response" | _egrep_o "$re" | _head_n 1 | cut -d : -f 3 | tr -d "\",") + if [ "$_domain_id" ]; then + _sub_domain=$(printf "%s" "$domain" | sed "s/.$domain_root//") + _domain="$domain_root" + return 0 + fi + _err 'Domain name not found on your CloudDNS account' + return 1 + fi + return 1 +} + +_clouddns_api() { + method=$1 + endpoint="$2" + data="$3" + _debug endpoint "$endpoint" + + if [ -z "$CLOUDDNS_TOKEN" ]; then + _clouddns_login + fi + _debug CLOUDDNS_TOKEN "$CLOUDDNS_TOKEN" + + export _H1="Content-Type: application/json" + export _H2="Authorization: Bearer $CLOUDDNS_TOKEN" + + if [ "$method" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$CLOUDDNS_API/$endpoint" "" "$method")" + else + response="$(_get "$CLOUDDNS_API/$endpoint")" + fi + + if [ "$?" != "0" ]; then + _err "error $endpoint" + return 1 + fi + printf "%s" "$response" + return 0 +} + +_clouddns_login() { + login_data="{\"email\": \"$CLOUDDNS_EMAIL\", \"password\": \"$CLOUDDNS_PASSWORD\"}" + response="$(_post "$login_data" "$CLOUDDNS_LOGIN_API" "" "POST" "Content-Type: application/json")" + _debug2 response "$response" + + if _contains "$response" "\"accessToken\":\""; then + CLOUDDNS_TOKEN=$(echo "$response" | _egrep_o "\"accessToken\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \") + export CLOUDDNS_TOKEN + else + echo 'Could not get CloudDNS access token; check your credentials' + return 1 + fi + return 0 +} From 69392f67e8c49bfaaa447bd7f1dd14a428cf357c Mon Sep 17 00:00:00 2001 From: Radek SPRTA Date: Wed, 22 Jan 2020 01:33:15 +0100 Subject: [PATCH 171/357] Correctly handle .co.uk type domains --- dnsapi/dns_clouddns.sh | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/dnsapi/dns_clouddns.sh b/dnsapi/dns_clouddns.sh index 2678c66b..174d740f 100755 --- a/dnsapi/dns_clouddns.sh +++ b/dnsapi/dns_clouddns.sh @@ -118,15 +118,24 @@ dns_clouddns_rm() { # _domain_id=sdjkglgdfewsdfg _get_root() { domain=$1 - domain_root=$(echo "$fulldomain" | _egrep_o '\.([^\.]*\.[^\.]*)$' | cut -c 2-) - _debug domain_root "$domain_root" + + # Get domain root + data="{\"search\": [{\"name\": \"clientId\", \"operator\": \"eq\", \"value\": \"$CLOUDDNS_CLIENT_ID\"}]}" + response="$(_clouddns_api "POST" "domain/search" "$data" | tr -d '\t\r\n ')" + _debug2 "response" "$response" + domain_slice="$domain" + while [ -z "$domain_root" ]; do + if _contains "$response" "\"domainName\":\"$domain_slice\.\""; then + domain_root="$domain_slice" + _debug domain_root "$domain_root" + fi + domain_slice="$(echo "$domain_slice" | cut -d . -f 2-)" + done # Get domain id data="{\"search\": [{\"name\": \"clientId\", \"operator\": \"eq\", \"value\": \"$CLOUDDNS_CLIENT_ID\"}, \ - {\"name\": \"domainName\", \"operator\": \"eq\", \"value\": \"$domain_root.\"}]}" + {\"name\": \"domainName\", \"operator\": \"eq\", \"value\": \"$domain_root.\"}]}" response="$(_clouddns_api "POST" "domain/search" "$data" | tr -d '\t\r\n ')" - _debug "Domain id $response" - if _contains "$response" "\"id\":\""; then re='domainType\":\"[^\"]*\",\"id\":\"([^\"]*)\",' # Match domain id _domain_id=$(echo "$response" | _egrep_o "$re" | _head_n 1 | cut -d : -f 3 | tr -d "\",") From 36e0feea430a008d63b818a4dc3cc8b46ddf459f Mon Sep 17 00:00:00 2001 From: Radek SPRTA Date: Wed, 22 Jan 2020 01:59:40 +0100 Subject: [PATCH 172/357] Clean up comments --- dnsapi/dns_clouddns.sh | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/dnsapi/dns_clouddns.sh b/dnsapi/dns_clouddns.sh index 174d740f..75d9ca6c 100755 --- a/dnsapi/dns_clouddns.sh +++ b/dnsapi/dns_clouddns.sh @@ -11,10 +11,11 @@ CLOUDDNS_LOGIN_API='https://admin.vshosting.cloud/api/public/auth/login' ######## Public functions ##################### -#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_clouddns_add() { fulldomain=$1 txtvalue=$2 + _debug "fulldomain" "$fulldomain" CLOUDDNS_CLIENT_ID="${CLOUDDNS_CLIENT_ID:-$(_readaccountconf_mutable CLOUDDNS_CLIENT_ID)}" CLOUDDNS_EMAIL="${CLOUDDNS_EMAIL:-$(_readaccountconf_mutable CLOUDDNS_EMAIL)}" @@ -24,7 +25,7 @@ dns_clouddns_add() { CLOUDDNS_CLIENT_ID="" CLOUDDNS_EMAIL="" CLOUDDNS_PASSWORD="" - _err "You didn't specify a CloudDNS password, email and client id yet." + _err "You didn't specify a CloudDNS password, email and client ID yet." return 1 fi if ! _contains "$CLOUDDNS_EMAIL" "@"; then @@ -46,8 +47,6 @@ dns_clouddns_add() { _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. _info "Adding record" if _clouddns_api POST "record-txt" "{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"value\":\"$txtvalue\",\"domainId\":\"$_domain_id\"}"; then if _contains "$response" "$txtvalue"; then @@ -55,20 +54,19 @@ dns_clouddns_add() { elif _contains "$response" '"code":4136'; then _info "Already exists, OK" else - _err "Add txt record error." + _err "Add TXT record error." return 1 fi fi - # Publish challenge record _debug "Publishing record changes" _clouddns_api PUT "domain/$_domain_id/publish" "{\"soaTtl\":300}" } -#fulldomain txtvalue +# Usage: rm _acme-challenge.www.domain.com dns_clouddns_rm() { fulldomain=$1 - txtvalue=$2 + _debug "fulldomain" "$fulldomain" CLOUDDNS_CLIENT_ID="${CLOUDDNS_CLIENT_ID:-$(_readaccountconf_mutable CLOUDDNS_CLIENT_ID)}" CLOUDDNS_EMAIL="${CLOUDDNS_EMAIL:-$(_readaccountconf_mutable CLOUDDNS_EMAIL)}" @@ -76,16 +74,16 @@ dns_clouddns_rm() { _debug "First detect the root zone" if ! _get_root "$fulldomain"; then - _err "invalid domain" + _err "Invalid domain" return 1 fi _debug _domain_id "$_domain_id" _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - # Get record Id + # Get record ID response="$(_clouddns_api GET "domain/$_domain_id" | tr -d '\t\r\n ')" - _debug response "$response" + _debug2 response "$response" if _contains "$response" "lastDomainRecordList"; then re="\"lastDomainRecordList\".*\"id\":\"([^\"}]*)\"[^}]*\"name\":\"$fulldomain.\"," _last_domains=$(echo "$response" | _egrep_o "$re") @@ -93,7 +91,7 @@ dns_clouddns_rm() { _record_id=$(echo "$_last_domains" | _egrep_o "$re2" | _head_n 1 | cut -d : -f 2 | cut -d , -f 1 | tr -d "\"") _debug _record_id "$_record_id" else - _err "Could not retrieve record id" + _err "Could not retrieve record ID" return 1 fi @@ -105,14 +103,14 @@ dns_clouddns_rm() { fi fi - # Publish challenge record _debug "Publishing record changes" _clouddns_api PUT "domain/$_domain_id/publish" "{\"soaTtl\":300}" } #################### Private functions below ################################## -#_acme-challenge.www.domain.com -#returns + +# Usage: _get_root _acme-challenge.www.domain.com +# Returns: # _sub_domain=_acme-challenge.www # _domain=domain.com # _domain_id=sdjkglgdfewsdfg @@ -122,7 +120,7 @@ _get_root() { # Get domain root data="{\"search\": [{\"name\": \"clientId\", \"operator\": \"eq\", \"value\": \"$CLOUDDNS_CLIENT_ID\"}]}" response="$(_clouddns_api "POST" "domain/search" "$data" | tr -d '\t\r\n ')" - _debug2 "response" "$response" + _debug2 response "$response" domain_slice="$domain" while [ -z "$domain_root" ]; do if _contains "$response" "\"domainName\":\"$domain_slice\.\""; then @@ -134,7 +132,7 @@ _get_root() { # Get domain id data="{\"search\": [{\"name\": \"clientId\", \"operator\": \"eq\", \"value\": \"$CLOUDDNS_CLIENT_ID\"}, \ - {\"name\": \"domainName\", \"operator\": \"eq\", \"value\": \"$domain_root.\"}]}" + {\"name\": \"domainName\", \"operator\": \"eq\", \"value\": \"$domain_root.\"}]}" response="$(_clouddns_api "POST" "domain/search" "$data" | tr -d '\t\r\n ')" if _contains "$response" "\"id\":\""; then re='domainType\":\"[^\"]*\",\"id\":\"([^\"]*)\",' # Match domain id @@ -150,6 +148,9 @@ _get_root() { return 1 } +# Usage: _clouddns_api GET domain/search '{"data": "value"}' +# Returns: +# response='{"message": "api response"}' _clouddns_api() { method=$1 endpoint="$2" @@ -172,13 +173,15 @@ _clouddns_api() { fi if [ "$?" != "0" ]; then - _err "error $endpoint" + _err "Error $endpoint" return 1 fi printf "%s" "$response" return 0 } +# Returns: +# CLOUDDNS_TOKEN=dslfje2rj23l _clouddns_login() { login_data="{\"email\": \"$CLOUDDNS_EMAIL\", \"password\": \"$CLOUDDNS_PASSWORD\"}" response="$(_post "$login_data" "$CLOUDDNS_LOGIN_API" "" "POST" "Content-Type: application/json")" From 6b675117481153bd8067737969f089bd24ada53e Mon Sep 17 00:00:00 2001 From: Radek SPRTA Date: Wed, 22 Jan 2020 02:03:11 +0100 Subject: [PATCH 173/357] Disable check --- dnsapi/dns_clouddns.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/dnsapi/dns_clouddns.sh b/dnsapi/dns_clouddns.sh index 75d9ca6c..1e9987db 100755 --- a/dnsapi/dns_clouddns.sh +++ b/dnsapi/dns_clouddns.sh @@ -172,6 +172,7 @@ _clouddns_api() { response="$(_get "$CLOUDDNS_API/$endpoint")" fi + # shellcheck disable=SC2181 if [ "$?" != "0" ]; then _err "Error $endpoint" return 1 From 23f26770523807630df8d87cd38016a8359c57a9 Mon Sep 17 00:00:00 2001 From: Radek SPRTA Date: Wed, 22 Jan 2020 02:53:50 +0100 Subject: [PATCH 174/357] Do not print HTTP responses to stdout --- dnsapi/dns_clouddns.sh | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/dnsapi/dns_clouddns.sh b/dnsapi/dns_clouddns.sh index 1e9987db..cfbb1cbb 100755 --- a/dnsapi/dns_clouddns.sh +++ b/dnsapi/dns_clouddns.sh @@ -47,8 +47,9 @@ dns_clouddns_add() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - _info "Adding record" - if _clouddns_api POST "record-txt" "{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"value\":\"$txtvalue\",\"domainId\":\"$_domain_id\"}"; then + # Add TXT record + data="{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"value\":\"$txtvalue\",\"domainId\":\"$_domain_id\"}" + if _clouddns_api POST "record-txt" "$data"; then if _contains "$response" "$txtvalue"; then _info "Added, OK" elif _contains "$response" '"code":4136'; then @@ -82,8 +83,7 @@ dns_clouddns_rm() { _debug _domain "$_domain" # Get record ID - response="$(_clouddns_api GET "domain/$_domain_id" | tr -d '\t\r\n ')" - _debug2 response "$response" + _clouddns_api GET "domain/$_domain_id" if _contains "$response" "lastDomainRecordList"; then re="\"lastDomainRecordList\".*\"id\":\"([^\"}]*)\"[^}]*\"name\":\"$fulldomain.\"," _last_domains=$(echo "$response" | _egrep_o "$re") @@ -119,8 +119,7 @@ _get_root() { # Get domain root data="{\"search\": [{\"name\": \"clientId\", \"operator\": \"eq\", \"value\": \"$CLOUDDNS_CLIENT_ID\"}]}" - response="$(_clouddns_api "POST" "domain/search" "$data" | tr -d '\t\r\n ')" - _debug2 response "$response" + _clouddns_api "POST" "domain/search" "$data" domain_slice="$domain" while [ -z "$domain_root" ]; do if _contains "$response" "\"domainName\":\"$domain_slice\.\""; then @@ -133,7 +132,7 @@ _get_root() { # Get domain id data="{\"search\": [{\"name\": \"clientId\", \"operator\": \"eq\", \"value\": \"$CLOUDDNS_CLIENT_ID\"}, \ {\"name\": \"domainName\", \"operator\": \"eq\", \"value\": \"$domain_root.\"}]}" - response="$(_clouddns_api "POST" "domain/search" "$data" | tr -d '\t\r\n ')" + _clouddns_api "POST" "domain/search" "$data" if _contains "$response" "\"id\":\""; then re='domainType\":\"[^\"]*\",\"id\":\"([^\"]*)\",' # Match domain id _domain_id=$(echo "$response" | _egrep_o "$re" | _head_n 1 | cut -d : -f 3 | tr -d "\",") @@ -167,9 +166,9 @@ _clouddns_api() { if [ "$method" != "GET" ]; then _debug data "$data" - response="$(_post "$data" "$CLOUDDNS_API/$endpoint" "" "$method")" + response="$(_post "$data" "$CLOUDDNS_API/$endpoint" "" "$method" | tr -d '\t\r\n ')" else - response="$(_get "$CLOUDDNS_API/$endpoint")" + response="$(_get "$CLOUDDNS_API/$endpoint" | tr -d '\t\r\n ')" fi # shellcheck disable=SC2181 @@ -177,7 +176,7 @@ _clouddns_api() { _err "Error $endpoint" return 1 fi - printf "%s" "$response" + _debug2 response "$response" return 0 } @@ -186,7 +185,6 @@ _clouddns_api() { _clouddns_login() { login_data="{\"email\": \"$CLOUDDNS_EMAIL\", \"password\": \"$CLOUDDNS_PASSWORD\"}" response="$(_post "$login_data" "$CLOUDDNS_LOGIN_API" "" "POST" "Content-Type: application/json")" - _debug2 response "$response" if _contains "$response" "\"accessToken\":\""; then CLOUDDNS_TOKEN=$(echo "$response" | _egrep_o "\"accessToken\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \") From 5c7feba77bd4a0b6f8ba1edaca2c1118a26cfa17 Mon Sep 17 00:00:00 2001 From: Radek SPRTA Date: Wed, 22 Jan 2020 05:33:46 +0100 Subject: [PATCH 175/357] Format with shfmt --- dnsapi/dns_clouddns.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_clouddns.sh b/dnsapi/dns_clouddns.sh index cfbb1cbb..31ae4ee9 100755 --- a/dnsapi/dns_clouddns.sh +++ b/dnsapi/dns_clouddns.sh @@ -85,7 +85,7 @@ dns_clouddns_rm() { # Get record ID _clouddns_api GET "domain/$_domain_id" if _contains "$response" "lastDomainRecordList"; then - re="\"lastDomainRecordList\".*\"id\":\"([^\"}]*)\"[^}]*\"name\":\"$fulldomain.\"," + re="\"lastDomainRecordList\".*\"id\":\"([^\"}]*)\"[^}]*\"name\":\"$fulldomain.\"," _last_domains=$(echo "$response" | _egrep_o "$re") re2="\"id\":\"([^\"}]*)\"[^}]*\"name\":\"$fulldomain.\"," _record_id=$(echo "$_last_domains" | _egrep_o "$re2" | _head_n 1 | cut -d : -f 2 | cut -d , -f 1 | tr -d "\"") @@ -94,7 +94,7 @@ dns_clouddns_rm() { _err "Could not retrieve record ID" return 1 fi - + _info "Removing record" if _clouddns_api DELETE "record/$_record_id"; then if _contains "$response" "\"error\":"; then @@ -119,7 +119,7 @@ _get_root() { # Get domain root data="{\"search\": [{\"name\": \"clientId\", \"operator\": \"eq\", \"value\": \"$CLOUDDNS_CLIENT_ID\"}]}" - _clouddns_api "POST" "domain/search" "$data" + _clouddns_api "POST" "domain/search" "$data" domain_slice="$domain" while [ -z "$domain_root" ]; do if _contains "$response" "\"domainName\":\"$domain_slice\.\""; then From 3c98fae4f286f0ed1f68ae86ec8781b471be23d6 Mon Sep 17 00:00:00 2001 From: xpac1985 Date: Wed, 22 Jan 2020 20:00:04 +0100 Subject: [PATCH 176/357] Updated/fixed some entries in --help output --- acme.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index b5f80b35..9b33fc74 100755 --- a/acme.sh +++ b/acme.sh @@ -6202,7 +6202,7 @@ Parameters: --force, -f Used to force to install or force to renew a cert immediately. --staging, --test Use staging server, just for test. --debug Output debug info. - --output-insecure Output all the sensitive messages. By default all the credentials/sensitive messages are hidden from the output/debug/log for secure. + --output-insecure Output all the sensitive messages. By default all the credentials/sensitive messages are hidden from the output/debug/log for security. --webroot, -w /path/to/webroot Specifies the web root folder for web root mode. --standalone Use standalone mode. --alpn Use standalone alpn mode. @@ -6211,7 +6211,7 @@ Parameters: --dns [dns_cf|dns_dp|dns_cx|/path/to/api/file] Use dns mode or dns api. --dnssleep [$DEFAULT_DNS_SLEEP] The time in seconds to wait for all the txt records to take effect in dns api mode. Default $DEFAULT_DNS_SLEEP seconds. - --keylength, -k [2048] Specifies the domain key length: 2048, 3072, 4096, 8192 or ec-256, ec-384. + --keylength, -k [2048] Specifies the domain key length: 2048, 3072, 4096, 8192 or ec-256, ec-384, ec-521. --accountkeylength, -ak [2048] Specifies the account key length. --log [/path/to/logfile] Specifies the log file. The default is: \"$DEFAULT_LOG_FILE\" if you don't give a file path here. --log-level 1|2 Specifies the log level, default is 1. @@ -6226,7 +6226,7 @@ Parameters: --reloadcmd \"service nginx reload\" After issue/renew, it's used to reload the server. - --server SERVER ACME Directory Resource URI. (default: https://acme-v01.api.letsencrypt.org/directory) + --server SERVER ACME Directory Resource URI. (default: $DEFAULT_CA) --accountconf Specifies a customized account config file. --home Specifies the home dir for $PROJECT_NAME. --cert-home Specifies the home dir to save all the certs, only valid for '--install' command. From b6552aff7502c5ef183fdee8a91cd7cb143eea2e Mon Sep 17 00:00:00 2001 From: xpac1985 Date: Wed, 22 Jan 2020 21:21:38 +0100 Subject: [PATCH 177/357] Added maximum account key length to --help output --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 9b33fc74..dae42714 100755 --- a/acme.sh +++ b/acme.sh @@ -6212,7 +6212,7 @@ Parameters: --dnssleep [$DEFAULT_DNS_SLEEP] The time in seconds to wait for all the txt records to take effect in dns api mode. Default $DEFAULT_DNS_SLEEP seconds. --keylength, -k [2048] Specifies the domain key length: 2048, 3072, 4096, 8192 or ec-256, ec-384, ec-521. - --accountkeylength, -ak [2048] Specifies the account key length. + --accountkeylength, -ak [2048] Specifies the account key length: 2048, 3072, 4096 --log [/path/to/logfile] Specifies the log file. The default is: \"$DEFAULT_LOG_FILE\" if you don't give a file path here. --log-level 1|2 Specifies the log level, default is 1. --syslog [0|3|6|7] Syslog level, 0: disable syslog, 3: error, 6: info, 7: debug. From 6613ae57b0a08dbae9e1f089d948c832a6b00074 Mon Sep 17 00:00:00 2001 From: Marco4223 Date: Thu, 23 Jan 2020 19:20:44 +0100 Subject: [PATCH 178/357] Update dns_kas.sh sleep 10 to _sleep 10 --- dnsapi/dns_kas.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_kas.sh b/dnsapi/dns_kas.sh index 95401684..2cb0b439 100755 --- a/dnsapi/dns_kas.sh +++ b/dnsapi/dns_kas.sh @@ -44,7 +44,7 @@ dns_kas_add() { params="$params&var5=zone_host" params="$params&wert5=$_zone" _debug2 "Wait for 10 seconds by default before calling KAS API." - sleep 10 + _sleep 10 response="$(_get "$KAS_Api$params")" _debug2 "response" "$response" @@ -80,7 +80,7 @@ dns_kas_rm() { params2="$params&var1=record_id" params2="$params2&wert1=$i" _debug2 "Wait for 10 seconds by default before calling KAS API." - sleep 10 + _sleep 10 response="$(_get "$KAS_Api$params2")" _debug2 "response" "$response" if ! _contains "$response" "TRUE"; then @@ -126,7 +126,7 @@ _get_zone_and_record_name() { params="$params&kas_action=get_domains" _debug2 "Wait for 10 seconds by default before calling KAS API." - sleep 10 + _sleep 10 response="$(_get "$KAS_Api$params")" _debug2 "response" "$response" _zonen="$(echo "$response" | tr -d "\n\r" | tr -d " " | tr '[]' '<>' | sed "s/=>Array/\n=> Array/g" | tr ' ' '\n' | grep "domain_name" | tr '<' '\n' | grep "domain_name" | sed "s/domain_name>=>//g")" @@ -159,7 +159,7 @@ _get_record_id() { params="$params&wert1=$_zone" _debug2 "Wait for 10 seconds by default before calling KAS API." - sleep 10 + _sleep 10 response="$(_get "$KAS_Api$params")" _debug2 "response" "$response" _record_id="$(echo "$response" | tr -d "\n\r" | tr -d " " | tr '[]' '<>' | sed "s/=>Array/\n=> Array/g" | tr ' ' '\n' | grep "=>$_record_name<" | grep '>TXT<' | tr '<' '\n' | grep record_id | sed "s/record_id>=>//g")" From 05aa26e6197241231bf968d23c03e1af4d6ad3b4 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 27 Jan 2020 21:22:42 +0800 Subject: [PATCH 179/357] minor, remove space key --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index b5f80b35..786d929a 100755 --- a/acme.sh +++ b/acme.sh @@ -4006,7 +4006,7 @@ issue() { _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-)" + 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" From 4f303de00c8d640351db5fb065bf0861786fab18 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 27 Jan 2020 22:12:21 +0800 Subject: [PATCH 180/357] fix bug https://github.com/Neilpang/acme.sh/issues/2695 If a domain was already verified by http-01 method, when we try to issue a cert for them same domain with dns-01 method, we just get only one challenge object of type http-01 with "valid" status, from the authz-v3 url. So, we report error that we are not able the validate the domain, because of that we don't find dns-01 challenge. This behavior is not the same as before. I believe it was changed by the letsencrypt CA. --- acme.sh | 80 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 33 deletions(-) diff --git a/acme.sh b/acme.sh index 786d929a..0de32794 100755 --- a/acme.sh +++ b/acme.sh @@ -4119,45 +4119,59 @@ $_authorizations_map" entry="$(echo "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')" _debug entry "$entry" + keyauthorization="" if [ -z "$entry" ]; then - _err "Error, can not get domain token entry $d" - _supported_vtypes="$(echo "$response" | _egrep_o "\"challenges\":\[[^]]*]" | tr '{' "\n" | grep type | cut -d '"' -f 4 | tr "\n" ' ')" - if [ "$_supported_vtypes" ]; then - _err "The supported validation types are: $_supported_vtypes, but you specified: $vtype" + _err "Error, can not get domain token entry $d for $vtype" + if ! _startswith "$d" '*.'; then + _debug "Not a wildcard domain, lets check whether the validation is already valid." + if echo "$response" | grep '"status":"valid"' >/dev/null 2>&1; then + _debug "$d is already valid." + keyauthorization="$STATE_VERIFIED" + _debug keyauthorization "$keyauthorization" + fi + fi + if [ -z "$keyauthorization" ]; then + _supported_vtypes="$(echo "$response" | _egrep_o "\"challenges\":\[[^]]*]" | tr '{' "\n" | grep type | cut -d '"' -f 4 | tr "\n" ' ')" + if [ "$_supported_vtypes" ]; then + _err "The supported validation types are: $_supported_vtypes, but you specified: $vtype" + fi + _clearup + _on_issue_err "$_post_hook" + return 1 fi - _clearup - _on_issue_err "$_post_hook" - return 1 - fi - token="$(echo "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')" - _debug token "$token" - - if [ -z "$token" ]; then - _err "Error, can not get domain token $entry" - _clearup - _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 - _debug uri "$uri" + + if [ -z "$keyauthorization" ]; then + token="$(echo "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')" + _debug token "$token" - if [ -z "$uri" ]; then - _err "Error, can not get domain uri. $entry" - _clearup - _on_issue_err "$_post_hook" - return 1 - fi - keyauthorization="$token.$thumbprint" - _debug keyauthorization "$keyauthorization" + if [ -z "$token" ]; then + _err "Error, can not get domain token $entry" + _clearup + _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 + _debug uri "$uri" - if printf "%s" "$response" | grep '"status":"valid"' >/dev/null 2>&1; then - _debug "$d is already verified." - keyauthorization="$STATE_VERIFIED" + if [ -z "$uri" ]; then + _err "Error, can not get domain uri. $entry" + _clearup + _on_issue_err "$_post_hook" + return 1 + fi + keyauthorization="$token.$thumbprint" _debug keyauthorization "$keyauthorization" + + if printf "%s" "$response" | grep '"status":"valid"' >/dev/null 2>&1; then + _debug "$d is already verified." + keyauthorization="$STATE_VERIFIED" + _debug keyauthorization "$keyauthorization" + fi fi dvlist="$d$sep$keyauthorization$sep$uri$sep$vtype$sep$_currentRoot" From dc0cca8c8371e0040fea4db3c0f19bd2740776b7 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 27 Jan 2020 22:22:25 +0800 Subject: [PATCH 181/357] move the error message --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 0de32794..c8b5bf95 100755 --- a/acme.sh +++ b/acme.sh @@ -4121,7 +4121,6 @@ $_authorizations_map" _debug entry "$entry" keyauthorization="" if [ -z "$entry" ]; then - _err "Error, can not get domain token entry $d for $vtype" if ! _startswith "$d" '*.'; then _debug "Not a wildcard domain, lets check whether the validation is already valid." if echo "$response" | grep '"status":"valid"' >/dev/null 2>&1; then @@ -4131,6 +4130,7 @@ $_authorizations_map" fi fi if [ -z "$keyauthorization" ]; then + _err "Error, can not get domain token entry $d for $vtype" _supported_vtypes="$(echo "$response" | _egrep_o "\"challenges\":\[[^]]*]" | tr '{' "\n" | grep type | cut -d '"' -f 4 | tr "\n" ' ')" if [ "$_supported_vtypes" ]; then _err "The supported validation types are: $_supported_vtypes, but you specified: $vtype" From f716f6060e7ee99704055dc57f603da3668e7da6 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 27 Jan 2020 23:02:09 +0800 Subject: [PATCH 182/357] minor check update hash for branch name --- acme.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 786d929a..b4974fe3 100755 --- a/acme.sh +++ b/acme.sh @@ -6315,7 +6315,11 @@ _installOnline() { } _getMasterHash() { - _hash_url="https://api.github.com/repos/Neilpang/acme.sh/git/refs/heads/master" + _b="$BRANCH" + if [ -z "$_b" ]; then + _b="master" + fi + _hash_url="https://api.github.com/repos/Neilpang/acme.sh/git/refs/heads/$_b" _get $_hash_url | tr -d "\r\n" | tr '{},' '\n' | grep '"sha":' | cut -d '"' -f 4 } From 9541ea6a9fee42567a194fbec82b6c80bd2a04bb Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 27 Jan 2020 22:12:21 +0800 Subject: [PATCH 183/357] fix bug https://github.com/Neilpang/acme.sh/issues/2695 If a domain was already verified by http-01 method, when we try to issue a cert for them same domain with dns-01 method, we just get only one challenge object of type http-01 with "valid" status, from the authz-v3 url. So, we report error that we are not able the validate the domain, because of that we don't find dns-01 challenge. This behavior is not the same as before. I believe it was changed by the letsencrypt CA. --- acme.sh | 80 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 33 deletions(-) diff --git a/acme.sh b/acme.sh index b4974fe3..3c21c75b 100755 --- a/acme.sh +++ b/acme.sh @@ -4119,45 +4119,59 @@ $_authorizations_map" entry="$(echo "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')" _debug entry "$entry" + keyauthorization="" if [ -z "$entry" ]; then - _err "Error, can not get domain token entry $d" - _supported_vtypes="$(echo "$response" | _egrep_o "\"challenges\":\[[^]]*]" | tr '{' "\n" | grep type | cut -d '"' -f 4 | tr "\n" ' ')" - if [ "$_supported_vtypes" ]; then - _err "The supported validation types are: $_supported_vtypes, but you specified: $vtype" + _err "Error, can not get domain token entry $d for $vtype" + if ! _startswith "$d" '*.'; then + _debug "Not a wildcard domain, lets check whether the validation is already valid." + if echo "$response" | grep '"status":"valid"' >/dev/null 2>&1; then + _debug "$d is already valid." + keyauthorization="$STATE_VERIFIED" + _debug keyauthorization "$keyauthorization" + fi + fi + if [ -z "$keyauthorization" ]; then + _supported_vtypes="$(echo "$response" | _egrep_o "\"challenges\":\[[^]]*]" | tr '{' "\n" | grep type | cut -d '"' -f 4 | tr "\n" ' ')" + if [ "$_supported_vtypes" ]; then + _err "The supported validation types are: $_supported_vtypes, but you specified: $vtype" + fi + _clearup + _on_issue_err "$_post_hook" + return 1 fi - _clearup - _on_issue_err "$_post_hook" - return 1 - fi - token="$(echo "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')" - _debug token "$token" - - if [ -z "$token" ]; then - _err "Error, can not get domain token $entry" - _clearup - _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 - _debug uri "$uri" + + if [ -z "$keyauthorization" ]; then + token="$(echo "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')" + _debug token "$token" - if [ -z "$uri" ]; then - _err "Error, can not get domain uri. $entry" - _clearup - _on_issue_err "$_post_hook" - return 1 - fi - keyauthorization="$token.$thumbprint" - _debug keyauthorization "$keyauthorization" + if [ -z "$token" ]; then + _err "Error, can not get domain token $entry" + _clearup + _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 + _debug uri "$uri" - if printf "%s" "$response" | grep '"status":"valid"' >/dev/null 2>&1; then - _debug "$d is already verified." - keyauthorization="$STATE_VERIFIED" + if [ -z "$uri" ]; then + _err "Error, can not get domain uri. $entry" + _clearup + _on_issue_err "$_post_hook" + return 1 + fi + keyauthorization="$token.$thumbprint" _debug keyauthorization "$keyauthorization" + + if printf "%s" "$response" | grep '"status":"valid"' >/dev/null 2>&1; then + _debug "$d is already verified." + keyauthorization="$STATE_VERIFIED" + _debug keyauthorization "$keyauthorization" + fi fi dvlist="$d$sep$keyauthorization$sep$uri$sep$vtype$sep$_currentRoot" From fc3a181779e8c4dbc3dd65a727df656619a100df Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 27 Jan 2020 22:22:25 +0800 Subject: [PATCH 184/357] move the error message --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 3c21c75b..5ae2e312 100755 --- a/acme.sh +++ b/acme.sh @@ -4121,7 +4121,6 @@ $_authorizations_map" _debug entry "$entry" keyauthorization="" if [ -z "$entry" ]; then - _err "Error, can not get domain token entry $d for $vtype" if ! _startswith "$d" '*.'; then _debug "Not a wildcard domain, lets check whether the validation is already valid." if echo "$response" | grep '"status":"valid"' >/dev/null 2>&1; then @@ -4131,6 +4130,7 @@ $_authorizations_map" fi fi if [ -z "$keyauthorization" ]; then + _err "Error, can not get domain token entry $d for $vtype" _supported_vtypes="$(echo "$response" | _egrep_o "\"challenges\":\[[^]]*]" | tr '{' "\n" | grep type | cut -d '"' -f 4 | tr "\n" ' ')" if [ "$_supported_vtypes" ]; then _err "The supported validation types are: $_supported_vtypes, but you specified: $vtype" From f8b225e70e2286622e01134d4e5ba5e69d1ab00e Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 27 Jan 2020 23:30:36 +0800 Subject: [PATCH 185/357] fix format --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 5ae2e312..200c95c0 100755 --- a/acme.sh +++ b/acme.sh @@ -4140,7 +4140,7 @@ $_authorizations_map" return 1 fi fi - + if [ -z "$keyauthorization" ]; then token="$(echo "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')" _debug token "$token" From 09f74a9af8f1de082f605e1f4338fb5ca7cb148e Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 30 Jan 2020 10:50:39 +0800 Subject: [PATCH 186/357] start v2.8.6, change the repo name --- acme.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/acme.sh b/acme.sh index 200c95c0..b05c341b 100755 --- a/acme.sh +++ b/acme.sh @@ -1,12 +1,12 @@ #!/usr/bin/env sh -VER=2.8.5 +VER=2.8.6 PROJECT_NAME="acme.sh" PROJECT_ENTRY="acme.sh" -PROJECT="https://github.com/Neilpang/$PROJECT_NAME" +PROJECT="https://github.com/acmesh-official/$PROJECT_NAME" DEFAULT_INSTALL_HOME="$HOME/.$PROJECT_NAME" @@ -126,19 +126,19 @@ NOTIFY_MODE_CERT=1 NOTIFY_MODE_DEFAULT=$NOTIFY_MODE_BULK -_DEBUG_WIKI="https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh" +_DEBUG_WIKI="https://github.com/acmesh-official/acme.sh/wiki/How-to-debug-acme.sh" -_PREPARE_LINK="https://github.com/Neilpang/acme.sh/wiki/Install-preparations" +_PREPARE_LINK="https://github.com/acmesh-official/acme.sh/wiki/Install-preparations" -_STATELESS_WIKI="https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode" +_STATELESS_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Stateless-Mode" -_DNS_ALIAS_WIKI="https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode" +_DNS_ALIAS_WIKI="https://github.com/acmesh-official/acme.sh/wiki/DNS-alias-mode" -_DNS_MANUAL_WIKI="https://github.com/Neilpang/acme.sh/wiki/dns-manual-mode" +_DNS_MANUAL_WIKI="https://github.com/acmesh-official/acme.sh/wiki/dns-manual-mode" -_NOTIFY_WIKI="https://github.com/Neilpang/acme.sh/wiki/notify" +_NOTIFY_WIKI="https://github.com/acmesh-official/acme.sh/wiki/notify" -_SUDO_WIKI="https://github.com/Neilpang/acme.sh/wiki/sudo" +_SUDO_WIKI="https://github.com/acmesh-official/acme.sh/wiki/sudo" _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." @@ -6333,7 +6333,7 @@ _getMasterHash() { if [ -z "$_b" ]; then _b="master" fi - _hash_url="https://api.github.com/repos/Neilpang/acme.sh/git/refs/heads/$_b" + _hash_url="https://api.github.com/repos/acmesh-official/$PROJECT_NAME/git/refs/heads/$_b" _get $_hash_url | tr -d "\r\n" | tr '{},' '\n' | grep '"sha":' | cut -d '"' -f 4 } From d795fac37a3ea23b3e3fa1babf685f1e2c079ad3 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 30 Jan 2020 12:06:39 +0800 Subject: [PATCH 187/357] update repo name --- .github/ISSUE_TEMPLATE.md | 4 +- .github/PULL_REQUEST_TEMPLATE.md | 2 +- .travis.yml | 2 +- README.md | 86 ++++++++++++++++---------------- deploy/README.md | 2 +- deploy/docker.sh | 2 +- dnsapi/README.md | 2 +- dnsapi/dns_aws.sh | 2 +- dnsapi/dns_azure.sh | 2 +- dnsapi/dns_cyon.sh | 2 +- dnsapi/dns_easydns.sh | 2 +- dnsapi/dns_freedns.sh | 2 +- dnsapi/dns_lexicon.sh | 2 +- dnsapi/dns_miab.sh | 2 +- dnsapi/dns_myapi.sh | 4 +- dnsapi/dns_openprovider.sh | 2 +- dnsapi/dns_ovh.sh | 4 +- dnsapi/dns_pleskxml.sh | 2 +- dnsapi/dns_rackspace.sh | 2 +- dnsapi/dns_servercow.sh | 2 +- 20 files changed, 65 insertions(+), 65 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 53112c6f..c9c1b555 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -2,7 +2,7 @@ 我很忙, 每天可能只有 几秒钟 时间看你的 issue, 如果不按照我的要求写 issue, 你可能不会得到任何回复, 石沉大海. 请确保已经更新到最新的代码, 然后贴上来 `--debug 2` 的调试输出. 没有调试信息. 我做不了什么. -如何调试 https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh +如何调试 https://github.com/acmesh-official/acme.sh/wiki/How-to-debug-acme.sh If it is a bug report: - make sure you are able to repro it on the latest released version. @@ -10,7 +10,7 @@ You can install the latest version by: `acme.sh --upgrade` - Search the existing issues. - Refer to the [WIKI](https://wiki.acme.sh). -- Debug info [Debug](https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh). +- Debug info [Debug](https://github.com/acmesh-official/acme.sh/wiki/How-to-debug-acme.sh). --> diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 3bd170b7..4f7ceb47 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -3,7 +3,7 @@ Please send to `dev` branch instead. Any PR to `master` branch will NOT be merged. -2. For dns api support, read this guide first: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide +2. For dns api support, read this guide first: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Dev-Guide You will NOT get any review without passing this guide. You also need to fix the CI errors. --> \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 1264803e..155ec64b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,7 +28,7 @@ script: - if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck -V ; fi - if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck -e SC2181 **/*.sh && echo "shellcheck OK" ; fi - cd .. - - git clone --depth 1 https://github.com/Neilpang/acmetest.git && cp -r acme.sh acmetest/ && cd acmetest + - git clone --depth 1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ && cd acmetest - if [ "$TRAVIS_OS_NAME" = "linux" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ./rundocker.sh testplat ubuntu:latest ; fi - if [ "$TRAVIS_OS_NAME" = "osx" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ACME_OPENSSL_BIN="$ACME_OPENSSL_BIN" ./letest.sh ; fi diff --git a/README.md b/README.md index d5012d68..d71c3c57 100644 --- a/README.md +++ b/README.md @@ -17,14 +17,14 @@ It's probably the `easiest & smartest` shell script to automatically issue & renew the free certificates from Let's Encrypt. -Wiki: https://github.com/Neilpang/acme.sh/wiki +Wiki: https://github.com/acmesh-official/acme.sh/wiki -For Docker Fans: [acme.sh :two_hearts: Docker ](https://github.com/Neilpang/acme.sh/wiki/Run-acme.sh-in-docker) +For Docker Fans: [acme.sh :two_hearts: Docker ](https://github.com/acmesh-official/acme.sh/wiki/Run-acme.sh-in-docker) Twitter: [@neilpangxa](https://twitter.com/neilpangxa) -# [中文说明](https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E) +# [中文说明](https://github.com/acmesh-official/acme.sh/wiki/%E8%AF%B4%E6%98%8E) # Who: - [FreeBSD.org](https://blog.crashed.org/letsencrypt-in-freebsd-org/) @@ -40,41 +40,41 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa) - [opnsense.org](https://github.com/opnsense/plugins/tree/master/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient) - [CentOS Web Panel](http://centos-webpanel.com/) - [lnmp.org](https://lnmp.org/) -- [more...](https://github.com/Neilpang/acme.sh/wiki/Blogs-and-tutorials) +- [more...](https://github.com/acmesh-official/acme.sh/wiki/Blogs-and-tutorials) # Tested OS | NO | Status| Platform| |----|-------|---------| -|1|[![](https://neilpang.github.io/acmetest/status/ubuntu-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)| Ubuntu -|2|[![](https://neilpang.github.io/acmetest/status/debian-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)| Debian -|3|[![](https://neilpang.github.io/acmetest/status/centos-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|CentOS -|4|[![](https://neilpang.github.io/acmetest/status/windows-cygwin.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Windows (cygwin with curl, openssl and crontab included) -|5|[![](https://neilpang.github.io/acmetest/status/freebsd.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|FreeBSD -|6|[![](https://neilpang.github.io/acmetest/status/pfsense.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|pfsense -|7|[![](https://neilpang.github.io/acmetest/status/opensuse-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|openSUSE -|8|[![](https://neilpang.github.io/acmetest/status/alpine-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Alpine Linux (with curl) -|9|[![](https://neilpang.github.io/acmetest/status/base-archlinux.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Archlinux -|10|[![](https://neilpang.github.io/acmetest/status/fedora-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|fedora -|11|[![](https://neilpang.github.io/acmetest/status/kalilinux-kali-linux-docker.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Kali Linux -|12|[![](https://neilpang.github.io/acmetest/status/oraclelinux-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Oracle Linux -|13|[![](https://neilpang.github.io/acmetest/status/proxmox.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)| Proxmox https://pve.proxmox.com/wiki/HTTPSCertificateConfiguration#Let.27s_Encrypt_using_acme.sh -|14|-----| Cloud Linux https://github.com/Neilpang/le/issues/111 -|15|[![](https://neilpang.github.io/acmetest/status/openbsd.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|OpenBSD -|16|[![](https://neilpang.github.io/acmetest/status/mageia.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Mageia -|17|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/Neilpang/acme.sh/wiki/How-to-run-on-OpenWRT) -|18|[![](https://neilpang.github.io/acmetest/status/solaris.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|SunOS/Solaris -|19|[![](https://neilpang.github.io/acmetest/status/gentoo-stage3-amd64.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Gentoo Linux +|1|[![](https://acmesh-official.github.io/acmetest/status/ubuntu-latest.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Ubuntu +|2|[![](https://acmesh-official.github.io/acmetest/status/debian-latest.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Debian +|3|[![](https://acmesh-official.github.io/acmetest/status/centos-latest.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|CentOS +|4|[![](https://acmesh-official.github.io/acmetest/status/windows-cygwin.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Windows (cygwin with curl, openssl and crontab included) +|5|[![](https://acmesh-official.github.io/acmetest/status/freebsd.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|FreeBSD +|6|[![](https://acmesh-official.github.io/acmetest/status/pfsense.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|pfsense +|7|[![](https://acmesh-official.github.io/acmetest/status/opensuse-latest.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|openSUSE +|8|[![](https://acmesh-official.github.io/acmetest/status/alpine-latest.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Alpine Linux (with curl) +|9|[![](https://acmesh-official.github.io/acmetest/status/base-archlinux.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Archlinux +|10|[![](https://acmesh-official.github.io/acmetest/status/fedora-latest.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|fedora +|11|[![](https://acmesh-official.github.io/acmetest/status/kalilinux-kali-linux-docker.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Kali Linux +|12|[![](https://acmesh-official.github.io/acmetest/status/oraclelinux-latest.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Oracle Linux +|13|[![](https://acmesh-official.github.io/acmetest/status/proxmox.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Proxmox https://pve.proxmox.com/wiki/HTTPSCertificateConfiguration#Let.27s_Encrypt_using_acme.sh +|14|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111 +|15|[![](https://acmesh-official.github.io/acmetest/status/openbsd.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|OpenBSD +|16|[![](https://acmesh-official.github.io/acmetest/status/mageia.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Mageia +|17|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT) +|18|[![](https://acmesh-official.github.io/acmetest/status/solaris.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|SunOS/Solaris +|19|[![](https://acmesh-official.github.io/acmetest/status/gentoo-stage3-amd64.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Gentoo Linux |20|[![Build Status](https://travis-ci.org/Neilpang/acme.sh.svg?branch=master)](https://travis-ci.org/Neilpang/acme.sh)|Mac OSX -For all build statuses, check our [weekly build project](https://github.com/Neilpang/acmetest): +For all build statuses, check our [weekly build project](https://github.com/acmesh-official/acmetest): -https://github.com/Neilpang/acmetest +https://github.com/acmesh-official/acmetest # Supported CA - Letsencrypt.org CA(default) -- [BuyPass.com CA](https://github.com/Neilpang/acme.sh/wiki/BuyPass.com-CA) +- [BuyPass.com CA](https://github.com/acmesh-official/acme.sh/wiki/BuyPass.com-CA) - [Pebble strict Mode](https://github.com/letsencrypt/pebble) # Supported modes @@ -85,15 +85,15 @@ https://github.com/Neilpang/acmetest - Apache mode - Nginx mode - DNS mode -- [DNS alias mode](https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode) -- [Stateless mode](https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode) +- [DNS alias mode](https://github.com/acmesh-official/acme.sh/wiki/DNS-alias-mode) +- [Stateless mode](https://github.com/acmesh-official/acme.sh/wiki/Stateless-Mode) # 1. How to install ### 1. Install online -Check this project: https://github.com/Neilpang/get.acme.sh +Check this project: https://github.com/acmesh-official/get.acme.sh ```bash curl https://get.acme.sh | sh @@ -111,14 +111,14 @@ wget -O - https://get.acme.sh | sh Clone this project and launch installation: ```bash -git clone https://github.com/Neilpang/acme.sh.git +git clone https://github.com/acmesh-official/acme.sh.git cd ./acme.sh ./acme.sh --install ``` You `don't have to be root` then, although `it is recommended`. -Advanced Installation: https://github.com/Neilpang/acme.sh/wiki/How-to-install +Advanced Installation: https://github.com/acmesh-official/acme.sh/wiki/How-to-install The installer will perform 3 actions: @@ -180,7 +180,7 @@ The certs will be placed in `~/.acme.sh/example.com/` The certs will be renewed automatically every **60** days. -More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert +More examples: https://github.com/acmesh-official/acme.sh/wiki/How-to-issue-a-cert # 3. Install the cert to Apache/Nginx etc. @@ -226,7 +226,7 @@ Port `80` (TCP) **MUST** be free to listen on, otherwise you will be prompted to acme.sh --issue --standalone -d example.com -d www.example.com -d cp.example.com ``` -More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert +More examples: https://github.com/acmesh-official/acme.sh/wiki/How-to-issue-a-cert # 5. Use Standalone ssl server to issue cert @@ -238,7 +238,7 @@ Port `443` (TCP) **MUST** be free to listen on, otherwise you will be prompted t acme.sh --issue --alpn -d example.com -d www.example.com -d cp.example.com ``` -More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert +More examples: https://github.com/acmesh-official/acme.sh/wiki/How-to-issue-a-cert # 6. Use Apache mode @@ -259,7 +259,7 @@ acme.sh --issue --apache -d example.com -d www.example.com -d cp.example.com You will need to configure your website config files to use the cert by yourself. We don't want to mess your apache server, don't worry.** -More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert +More examples: https://github.com/acmesh-official/acme.sh/wiki/How-to-issue-a-cert # 7. Use Nginx mode @@ -283,7 +283,7 @@ acme.sh --issue --nginx -d example.com -d www.example.com -d cp.example.com You will need to configure your website config files to use the cert by yourself. We don't want to mess your nginx server, don't worry.** -More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert +More examples: https://github.com/acmesh-official/acme.sh/wiki/How-to-issue-a-cert # 8. Automatic DNS API integration @@ -293,11 +293,11 @@ You don't have to do anything manually! ### Currently acme.sh supports most of the dns providers: -https://github.com/Neilpang/acme.sh/wiki/dnsapi +https://github.com/acmesh-official/acme.sh/wiki/dnsapi # 9. Use DNS manual mode: -See: https://github.com/Neilpang/acme.sh/wiki/dns-manual-mode first. +See: https://github.com/acmesh-official/acme.sh/wiki/dns-manual-mode first. If your dns provider doesn't support any api access, you can add the txt record by your hand. @@ -430,12 +430,12 @@ acme.sh --upgrade --auto-upgrade 0 # 15. Issue a cert from an existing CSR -https://github.com/Neilpang/acme.sh/wiki/Issue-a-cert-from-existing-CSR +https://github.com/acmesh-official/acme.sh/wiki/Issue-a-cert-from-existing-CSR # 16. Send notifications in cronjob -https://github.com/Neilpang/acme.sh/wiki/notify +https://github.com/acmesh-official/acme.sh/wiki/notify # 17. Under the Hood @@ -456,7 +456,7 @@ TODO: ### Code Contributors This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. - + ### Financial Contributors @@ -487,7 +487,7 @@ License is GPLv3 Please Star and Fork me. -[Issues](https://github.com/Neilpang/acme.sh/issues) and [pull requests](https://github.com/Neilpang/acme.sh/pulls) are welcome. +[Issues](https://github.com/acmesh-official/acme.sh/issues) and [pull requests](https://github.com/acmesh-official/acme.sh/pulls) are welcome. # 20. Donate @@ -495,4 +495,4 @@ Your donation makes **acme.sh** better: 1. PayPal/Alipay(支付宝)/Wechat(微信): [https://donate.acme.sh/](https://donate.acme.sh/) -[Donate List](https://github.com/Neilpang/acme.sh/wiki/Donate-list) +[Donate List](https://github.com/acmesh-official/acme.sh/wiki/Donate-list) diff --git a/deploy/README.md b/deploy/README.md index fc633ad7..e3f239fa 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -2,5 +2,5 @@ deploy hook usage: -https://github.com/Neilpang/acme.sh/wiki/deployhooks +https://github.com/acmesh-official/acme.sh/wiki/deployhooks diff --git a/deploy/docker.sh b/deploy/docker.sh index 05333b3f..06d79855 100755 --- a/deploy/docker.sh +++ b/deploy/docker.sh @@ -8,7 +8,7 @@ #DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE="/path/to/fullchain.pem" #DEPLOY_DOCKER_CONTAINER_RELOAD_CMD="service nginx force-reload" -_DEPLOY_DOCKER_WIKI="https://github.com/Neilpang/acme.sh/wiki/deploy-to-docker-containers" +_DEPLOY_DOCKER_WIKI="https://github.com/acmesh-official/acme.sh/wiki/deploy-to-docker-containers" _DOCKER_HOST_DEFAULT="/var/run/docker.sock" diff --git a/dnsapi/README.md b/dnsapi/README.md index 4fa59cf2..e81f7916 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -2,5 +2,5 @@ DNS api usage: -https://github.com/Neilpang/acme.sh/wiki/dnsapi +https://github.com/acmesh-official/acme.sh/wiki/dnsapi diff --git a/dnsapi/dns_aws.sh b/dnsapi/dns_aws.sh index 6db87666..0503d0f2 100755 --- a/dnsapi/dns_aws.sh +++ b/dnsapi/dns_aws.sh @@ -12,7 +12,7 @@ AWS_HOST="route53.amazonaws.com" AWS_URL="https://$AWS_HOST" -AWS_WIKI="https://github.com/Neilpang/acme.sh/wiki/How-to-use-Amazon-Route53-API" +AWS_WIKI="https://github.com/acmesh-official/acme.sh/wiki/How-to-use-Amazon-Route53-API" ######## Public functions ##################### diff --git a/dnsapi/dns_azure.sh b/dnsapi/dns_azure.sh index 8b52dee7..bf7cf2bf 100644 --- a/dnsapi/dns_azure.sh +++ b/dnsapi/dns_azure.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -WIKI="https://github.com/Neilpang/acme.sh/wiki/How-to-use-Azure-DNS" +WIKI="https://github.com/acmesh-official/acme.sh/wiki/How-to-use-Azure-DNS" ######## Public functions ##################### diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index d7ad712c..8db3011d 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -1,7 +1,7 @@ #!/usr/bin/env sh ######## -# Custom cyon.ch DNS API for use with [acme.sh](https://github.com/Neilpang/acme.sh) +# Custom cyon.ch DNS API for use with [acme.sh](https://github.com/acmesh-official/acme.sh) # # Usage: acme.sh --issue --dns dns_cyon -d www.domain.com # diff --git a/dnsapi/dns_easydns.sh b/dnsapi/dns_easydns.sh index 1d905841..ca8faab2 100644 --- a/dnsapi/dns_easydns.sh +++ b/dnsapi/dns_easydns.sh @@ -8,7 +8,7 @@ # http://sandbox.rest.easydns.net:3000/ # # Author: wurzelpanzer [wurzelpanzer@maximolider.net] -# Report Bugs here: https://github.com/Neilpang/acme.sh/issues/2647 +# Report Bugs here: https://github.com/acmesh-official/acme.sh/issues/2647 # #################### Public functions ################# diff --git a/dnsapi/dns_freedns.sh b/dnsapi/dns_freedns.sh index 6a0b58ac..4a58931f 100755 --- a/dnsapi/dns_freedns.sh +++ b/dnsapi/dns_freedns.sh @@ -7,7 +7,7 @@ # #Author: David Kerr #Report Bugs here: https://github.com/dkerr64/acme.sh -#or here... https://github.com/Neilpang/acme.sh/issues/2305 +#or here... https://github.com/acmesh-official/acme.sh/issues/2305 # ######## Public functions ##################### diff --git a/dnsapi/dns_lexicon.sh b/dnsapi/dns_lexicon.sh index bb9f7efc..516b6eff 100755 --- a/dnsapi/dns_lexicon.sh +++ b/dnsapi/dns_lexicon.sh @@ -5,7 +5,7 @@ # https://github.com/AnalogJ/lexicon lexicon_cmd="lexicon" -wiki="https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api" +wiki="https://github.com/acmesh-official/acme.sh/wiki/How-to-use-lexicon-dns-api" _lexicon_init() { if ! _exists "$lexicon_cmd"; then diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh index 23ff6cee..7e697704 100644 --- a/dnsapi/dns_miab.sh +++ b/dnsapi/dns_miab.sh @@ -10,7 +10,7 @@ # used to communicate with the MailinaBox Custom DNS API # Report Bugs here: # https://github.com/billgertz/MIAB_dns_api (for dns_miab.sh) -# https://github.com/Neilpang/acme.sh (for acme.sh) +# https://github.com/acmesh-official/acme.sh (for acme.sh) # ######## Public functions ##################### diff --git a/dnsapi/dns_myapi.sh b/dnsapi/dns_myapi.sh index 2451d193..7f3c5a86 100755 --- a/dnsapi/dns_myapi.sh +++ b/dnsapi/dns_myapi.sh @@ -7,11 +7,11 @@ #returns 0 means success, otherwise error. # #Author: Neilpang -#Report Bugs here: https://github.com/Neilpang/acme.sh +#Report Bugs here: https://github.com/acmesh-official/acme.sh # ######## Public functions ##################### -# Please Read this guide first: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide +# Please Read this guide first: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Dev-Guide #Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_myapi_add() { diff --git a/dnsapi/dns_openprovider.sh b/dnsapi/dns_openprovider.sh index 1b1b760e..ad1e5838 100755 --- a/dnsapi/dns_openprovider.sh +++ b/dnsapi/dns_openprovider.sh @@ -3,7 +3,7 @@ # This is the OpenProvider API wrapper for acme.sh # # Author: Sylvia van Os -# Report Bugs here: https://github.com/Neilpang/acme.sh/issues/2104 +# Report Bugs here: https://github.com/acmesh-official/acme.sh/issues/2104 # # export OPENPROVIDER_USER="username" # export OPENPROVIDER_PASSWORDHASH="hashed_password" diff --git a/dnsapi/dns_ovh.sh b/dnsapi/dns_ovh.sh index 65567efd..7c18d009 100755 --- a/dnsapi/dns_ovh.sh +++ b/dnsapi/dns_ovh.sh @@ -32,9 +32,9 @@ SYS_CA='https://ca.api.soyoustart.com/1.0' #'runabove-ca' RAV_CA='https://api.runabove.com/1.0' -wiki="https://github.com/Neilpang/acme.sh/wiki/How-to-use-OVH-domain-api" +wiki="https://github.com/acmesh-official/acme.sh/wiki/How-to-use-OVH-domain-api" -ovh_success="https://github.com/Neilpang/acme.sh/wiki/OVH-Success" +ovh_success="https://github.com/acmesh-official/acme.sh/wiki/OVH-Success" _ovh_get_api() { _ogaep="$1" diff --git a/dnsapi/dns_pleskxml.sh b/dnsapi/dns_pleskxml.sh index c5d9e544..fe18bef4 100644 --- a/dnsapi/dns_pleskxml.sh +++ b/dnsapi/dns_pleskxml.sh @@ -2,7 +2,7 @@ ## Name: dns_pleskxml.sh ## Created by Stilez. -## Also uses some code from PR#1832 by @romanlum (https://github.com/Neilpang/acme.sh/pull/1832/files) +## Also uses some code from PR#1832 by @romanlum (https://github.com/acmesh-official/acme.sh/pull/1832/files) ## This DNS-01 method uses the Plesk XML API described at: ## https://docs.plesk.com/en-US/12.5/api-rpc/about-xml-api.28709 diff --git a/dnsapi/dns_rackspace.sh b/dnsapi/dns_rackspace.sh index 3939fd81..159671f9 100644 --- a/dnsapi/dns_rackspace.sh +++ b/dnsapi/dns_rackspace.sh @@ -9,7 +9,7 @@ RACKSPACE_Endpoint="https://dns.api.rackspacecloud.com/v1.0" # 20190213 - The name & id fields swapped in the API response; fix sed # 20190101 - Duplicating file for new pull request to dev branch -# Original - tcocca:rackspace_dnsapi https://github.com/Neilpang/acme.sh/pull/1297 +# Original - tcocca:rackspace_dnsapi https://github.com/acmesh-official/acme.sh/pull/1297 ######## Public functions ##################### #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" diff --git a/dnsapi/dns_servercow.sh b/dnsapi/dns_servercow.sh index be4e59da..e73d85b0 100755 --- a/dnsapi/dns_servercow.sh +++ b/dnsapi/dns_servercow.sh @@ -1,7 +1,7 @@ #!/usr/bin/env sh ########## -# Custom servercow.de DNS API v1 for use with [acme.sh](https://github.com/Neilpang/acme.sh) +# Custom servercow.de DNS API v1 for use with [acme.sh](https://github.com/acmesh-official/acme.sh) # # Usage: # export SERVERCOW_API_Username=username From d610eb15d8b8f7ea4f9a407ee230d4822e510b65 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 30 Jan 2020 12:44:02 +0800 Subject: [PATCH 188/357] update repo name --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d71c3c57..d1c793d4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# An ACME Shell script: acme.sh [![Build Status](https://travis-ci.org/Neilpang/acme.sh.svg?branch=master)](https://travis-ci.org/Neilpang/acme.sh) +# An ACME Shell script: acme.sh [![Build Status](https://travis-ci.org/acmesh-official/acme.sh.svg?branch=master)](https://travis-ci.org/acmesh-official/acme.sh) [![Join the chat at https://gitter.im/acme-sh/Lobby](https://badges.gitter.im/acme-sh/Lobby.svg)](https://gitter.im/acme-sh/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - An ACME protocol client written purely in Shell (Unix shell) language. @@ -65,7 +65,7 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa) |17|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT) |18|[![](https://acmesh-official.github.io/acmetest/status/solaris.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|SunOS/Solaris |19|[![](https://acmesh-official.github.io/acmetest/status/gentoo-stage3-amd64.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Gentoo Linux -|20|[![Build Status](https://travis-ci.org/Neilpang/acme.sh.svg?branch=master)](https://travis-ci.org/Neilpang/acme.sh)|Mac OSX +|20|[![Build Status](https://travis-ci.org/acmesh-official/acme.sh.svg?branch=master)](https://travis-ci.org/acmesh-official/acme.sh)|Mac OSX For all build statuses, check our [weekly build project](https://github.com/acmesh-official/acmetest): From d9a9695fe089f07e81199fcfb9ebb75fe6def7be Mon Sep 17 00:00:00 2001 From: Paul Nguyen Date: Wed, 5 Feb 2020 14:29:01 -0800 Subject: [PATCH 189/357] Deploy certificates to Palo Alto Network Firewalls --- deploy/panos.sh | 144 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 deploy/panos.sh diff --git a/deploy/panos.sh b/deploy/panos.sh new file mode 100644 index 00000000..8a288e7b --- /dev/null +++ b/deploy/panos.sh @@ -0,0 +1,144 @@ +#!/usr/bin/env sh + +# Script to deploy certificates to Palo Alto Networks PANOS via API +# Note PANOS API KEY and IP address needs to be set prior to running. +# The following variables exported from environment will be used. +# If not set then values previously saved in domain.conf file are used. +# +# Firewall admin with superuser and IP address is required. +# +# export PANOS_USER="" # required +# export PANOS_PASS="" # required +# export PANOS_HOST="" # required + +# This function is to parse the XML +parse_response() { + status=$(echo "$1" | sed 's/^.*"\([a-z]*\)".*/\1/g') + message=$(echo "$1" | sed 's/^.*\(.*\)<\/result.*/\1/g') + return 0 +} + +deployer() { + type=$1 # Types are cert, key, commit + _debug "**** Deploying $type *****" + + #Generate DEIM + delim="-----MultipartDelimiter$(date "+%s%N")" + nl="\015\012" + #Set Header + _H1="Content-Type: multipart/form-data; boundary=$delim" + if [ $type = 'cert' ]; then + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_cfullchain")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cfullchain")" + fi + if [ $type = 'key' ]; then + #Add key + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")" + fi + #Close multipart + content="$content${nl}--$delim--${nl}" + #Convert CRLF + content=$(printf %b "$content") + + if [ $type = 'cert' ]; then + panos_url="https://$_panos_host/api/?type=import&category=certificate&certificate-name=$_cdomain&format=pem&key=$_panos_key" + fi + + if [ $type = 'key' ]; then + panos_url="https://$_panos_host/api/?type=import&category=private-key&certificate-name=$_cdomain&format=pem&passphrase=none&key=$_panos_key" + fi + if [ $type = 'commit' ]; then + cmd=$(_url_encode "<$_panos_user>") + panos_url="https://$_panos_host/api/?type=commit&cmd=$cmd&key=$_panos_key" + fi + + if [ $type = 'key' ] || [ $type = 'cert' ]; then + response=$(_post "$content" "$panos_url" "" "POST") + else + response=$(_get $panos_url) + fi + _debug panos_url $panos_url + _debug "RESPONSE $response" + parse_response "$response" + _debug "STATUS IS $status" + _debug "MESSAGE IS $message" + # Saving response to variables + response_status=$status + # Check for cert upload error and handle gracefully. + + #DEBUG + _debug header "$_H1" + # _debug content "$content" + _debug response_status "$response_status" + if [ "$response_status" = "success" ]; then + _debug "Successfully deployed $type" + return 0 + else + _err "Deploy of type $type failed. Try deploying with --debug to troubleshoot." + _debug "$message" + return 1 + fi +} + +# This is the main function that will call the other functions to deploy everything. +panos_deploy() { + _cdomain="$1" + _ckey="$2" + _cfullchain="$5" + # PANOS HOST is required to make API calls to the PANOS/Panorama + if [ -z "$PANOS_HOST" ]; then + if [ -z "$_panos_host" ]; then + _err "PANOS_HOST not defined." + return 1 + fi + else + _debug "PANOS HOST is set. Save to domain conf." + _panos_host="$PANOS_HOST" + _savedomainconf _panos_host "$_panos_host" + fi + # Retrieve stored variables + _panos_user="$(_readaccountconf_mutable PANOS_USER)" + _panos_pass="$(_readaccountconf_mutable PANOS_PASS)" + # PANOS Credentials check + if [ -z "$PANOS_USER" ] || [ -z "$PANOS_PASS" ]; then + _debug "PANOS_USER, PANOS_PASS is not defined" + if [ -z "$_panos_user" ] && [ -z "$_panos_pass" ]; then + _err "No user and pass found in storage. If this is the first time deploying please set PANOS_USER and PANOS_PASS in environment variables." + return 1 + else + _debug "ok" + fi + else + _debug "Saving environment variables" + # Encrypt and save user + _saveaccountconf_mutable PANOS_USER "$PANOS_USER" + _saveaccountconf_mutable PANOS_PASS "$PANOS_PASS" + _panos_user="$PANOS_USER" + _panos_pass="$PANOS_PASS" + fi + _debug "Let's use username and pass to generate token." + if [ -z "$_panos_user" ] || [ -z "$_panos_pass" ] || [ -z "$_panos_host" ]; then + _err "Please pass username and password and host as env variables PANOS_USER, PANOS_PASS and PANOS_HOST" + return 1 + else + _debug "Getting PANOS KEY" + panos_key_response=$(_get "https://$_panos_host/api/?type=keygen&user=$_panos_user&password=$_panos_pass") + _debug "PANOS KEY FULL RESPONSE $panos_key_response" + status=$(echo "$panos_key_response" | sed 's/^.*\(['\'']\)\([a-z]*\)'\''.*/\2/g') + _debug "STATUS IS $status" + if [ "$status" = "success" ]; then + panos_key=$(echo "$panos_key_response" | sed 's/^.*\(\)\(.*\)<\/key>.*/\2/g') + _panos_key=$panos_key + else + _err "PANOS Key could not be set. Deploy with --debug to troubleshoot" + return 1 + fi + if [ -z "$_panos_host" ] && [ -z "$_panos_key" ] && [ -z "$_panos_user" ]; then + _err "Missing host, apikey, user." + return 1 + else + deployer cert + deployer key + deployer commit + fi + fi +} \ No newline at end of file From 64f8a222cb1ef1a036957ba613afe30d2a2dd770 Mon Sep 17 00:00:00 2001 From: Victor Huang Date: Thu, 6 Feb 2020 11:12:14 +0800 Subject: [PATCH 190/357] Add support for CQHTTP QQ bot API --- notify/cqhttp.sh | 75 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 notify/cqhttp.sh diff --git a/notify/cqhttp.sh b/notify/cqhttp.sh new file mode 100644 index 00000000..a47f4c92 --- /dev/null +++ b/notify/cqhttp.sh @@ -0,0 +1,75 @@ +#!/bin/bash + +#Support for CQHTTP api. Push notification on CoolQ +#CQHTTP_TOKEN="" Required, QQ application token +#CQHTTP_USER="" Required, QQ reciever ID +#CQHTTP_APIROOT="" Required, CQHTTP Server URL (without slash suffix) +#CQHTTP_CUSTOM_MSGHEAD="" Optional, custom message header + +CQHTTP_APIPATH="/send_private_msg" + +cqhttp_send() { + _subject="$1" + _content="$2" + _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped + _debug "_statusCode" "$_statusCode" + + CQHTTP_TOKEN="${CQHTTP_TOKEN:-$(_readaccountconf_mutable CQHTTP_TOKEN)}" + if [ -z "$CQHTTP_TOKEN" ]; then + CQHTTP_TOKEN="" + _err "You didn't specify a CQHTTP application token yet. If it's empty please pass \"__ACME_SH_TOKEN_EMPTY__\" (without quote)." + return 1 + fi + _saveaccountconf_mutable CQHTTP_TOKEN "$CQHTTP_TOKEN" + if [ "$CQHTTP_TOKEN" = "__ACME_SH_TOKEN_EMPTY__" ]; then + CQHTTP_TOKEN="" + fi + + CQHTTP_USER="${CQHTTP_USER:-$(_readaccountconf_mutable CQHTTP_USER)}" + if [ -z "$CQHTTP_USER" ]; then + CQHTTP_USER="" + _err "You didn't specify a QQ user yet." + return 1 + fi + _saveaccountconf_mutable CQHTTP_USER "$CQHTTP_USER" + + CQHTTP_APIROOT="${CQHTTP_APIROOT:-$(_readaccountconf_mutable CQHTTP_APIROOT)}" + if [ -z "$CQHTTP_APIROOT" ]; then + CQHTTP_APIROOT="" + _err "You didn't specify a QQ user yet." + return 1 + fi + _saveaccountconf_mutable CQHTTP_APIROOT "$CQHTTP_APIROOT" + + CQHTTP_APIROOT="${CQHTTP_APIROOT:-$(_readaccountconf_mutable CQHTTP_APIROOT)}" + if [ -z "$CQHTTP_APIROOT" ]; then + CQHTTP_APIROOT="" + _err "You didn't specify a QQ user yet." + return 1 + fi + _saveaccountconf_mutable CQHTTP_APIROOT "$CQHTTP_APIROOT" + + CQHTTP_CUSTOM_MSGHEAD="${CQHTTP_CUSTOM_MSGHEAD:-$(_readaccountconf_mutable CQHTTP_CUSTOM_MSGHEAD)}" + if [ -z "$CQHTTP_CUSTOM_MSGHEAD" ]; then + CQHTTP_CUSTOM_MSGHEAD="A message from acme.sh:" + else + _saveaccountconf_mutable CQHTTP_CUSTOM_MSGHEAD "$CQHTTP_CUSTOM_MSGHEAD" + fi + + _access_token="$(printf "%s" "$CQHTTP_TOKEN" | _url_encode)" + _user_id="$(printf "%s" "$CQHTTP_USER" | _url_encode)" + _message="$(printf "$CQHTTP_CUSTOM_MSGHEAD %s\\n%s" "$_subject" "$_content" | _url_encode)" + + _finalUrl="$CQHTTP_APIROOT$CQHTTP_APIPATH?access_token=$_access_token&user_id=$_user_id&message=$_message" + response="$(_get "$_finalUrl")" + + if [ "$?" = "0" ] && _contains "$response" "\"retcode\":0,\"status\":\"ok\""; then + _info "QQ send success." + return 0 + fi + + _err "QQ send error." + _err "URL: $_finalUrl" + _err "Response: $response" + return 1 +} From 33670a5bd0788ffc403f6e6b32feef179382413a Mon Sep 17 00:00:00 2001 From: Victor Huang Date: Thu, 6 Feb 2020 11:26:56 +0800 Subject: [PATCH 191/357] CQHTTP: Change shebang to "/usr/bin/env sh" --- notify/cqhttp.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notify/cqhttp.sh b/notify/cqhttp.sh index a47f4c92..fe78a0fd 100644 --- a/notify/cqhttp.sh +++ b/notify/cqhttp.sh @@ -1,8 +1,8 @@ -#!/bin/bash +#!/usr/bin/env sh #Support for CQHTTP api. Push notification on CoolQ #CQHTTP_TOKEN="" Required, QQ application token -#CQHTTP_USER="" Required, QQ reciever ID +#CQHTTP_USER="" Required, QQ receiver ID #CQHTTP_APIROOT="" Required, CQHTTP Server URL (without slash suffix) #CQHTTP_CUSTOM_MSGHEAD="" Optional, custom message header From 2cc50a2b65d4e443d7469675c5639999a27f8f19 Mon Sep 17 00:00:00 2001 From: Wout Date: Sat, 8 Feb 2020 12:27:19 +0100 Subject: [PATCH 192/357] Cosmetic fixes. --- dnsapi/dns_constellix.sh | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/dnsapi/dns_constellix.sh b/dnsapi/dns_constellix.sh index 55f4a71b..c47ede44 100644 --- a/dnsapi/dns_constellix.sh +++ b/dnsapi/dns_constellix.sh @@ -2,26 +2,28 @@ # Author: Wout Decre -CONSTELLIX_API="https://api.dns.constellix.com/v1" -#CONSTELLIX_KEY="XXX" -#CONSTELLIX_SECRET="XXX" +CONSTELLIX_Api="https://api.dns.constellix.com/v1" +#CONSTELLIX_Key="XXX" +#CONSTELLIX_Secret="XXX" ######## Public functions ##################### +# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +# Used to add txt record dns_constellix_add() { fulldomain=$1 txtvalue=$2 - CONSTELLIX_KEY="${CONSTELLIX_KEY:-$(_readaccountconf_mutable CONSTELLIX_KEY)}" - CONSTELLIX_SECRET="${CONSTELLIX_SECRET:-$(_readaccountconf_mutable CONSTELLIX_SECRET)}" + CONSTELLIX_Key="${CONSTELLIX_Key:-$(_readaccountconf_mutable CONSTELLIX_Key)}" + CONSTELLIX_Secret="${CONSTELLIX_Secret:-$(_readaccountconf_mutable CONSTELLIX_Secret)}" - if [ -z "$CONSTELLIX_KEY" ] || [ -z "$CONSTELLIX_SECRET" ]; then + if [ -z "$CONSTELLIX_Key" ] || [ -z "$CONSTELLIX_Secret" ]; then _err "You did not specify the Contellix API key and secret yet." return 1 fi - _saveaccountconf_mutable CONSTELLIX_KEY "$CONSTELLIX_KEY" - _saveaccountconf_mutable CONSTELLIX_SECRET "$CONSTELLIX_SECRET" + _saveaccountconf_mutable CONSTELLIX_Key "$CONSTELLIX_Key" + _saveaccountconf_mutable CONSTELLIX_Secret "$CONSTELLIX_Secret" if ! _get_root "$fulldomain"; then _err "Invalid domain" @@ -40,14 +42,16 @@ dns_constellix_add() { fi } +# Usage: fulldomain txtvalue +# Used to remove the txt record after validation dns_constellix_rm() { fulldomain=$1 txtvalue=$2 - CONSTELLIX_KEY="${CONSTELLIX_KEY:-$(_readaccountconf_mutable CONSTELLIX_KEY)}" - CONSTELLIX_SECRET="${CONSTELLIX_SECRET:-$(_readaccountconf_mutable CONSTELLIX_SECRET)}" + CONSTELLIX_Key="${CONSTELLIX_Key:-$(_readaccountconf_mutable CONSTELLIX_Key)}" + CONSTELLIX_Secret="${CONSTELLIX_Secret:-$(_readaccountconf_mutable CONSTELLIX_Secret)}" - if [ -z "$CONSTELLIX_KEY" ] || [ -z "$CONSTELLIX_SECRET" ]; then + if [ -z "$CONSTELLIX_Key" ] || [ -z "$CONSTELLIX_Secret" ]; then _err "You did not specify the Contellix API key and secret yet." return 1 fi @@ -112,9 +116,9 @@ _constellix_rest() { _debug "$ep" rdate=$(date +"%s")"000" - hmac=$(printf "%s" "$rdate" | _hmac sha1 "$(printf "%s" "$CONSTELLIX_SECRET" | _hex_dump | tr -d ' ')" | _base64) + hmac=$(printf "%s" "$rdate" | _hmac sha1 "$(printf "%s" "$CONSTELLIX_Secret" | _hex_dump | tr -d ' ')" | _base64) - export _H1="x-cnsdns-apiKey: $CONSTELLIX_KEY" + export _H1="x-cnsdns-apiKey: $CONSTELLIX_Key" export _H2="x-cnsdns-requestDate: $rdate" export _H3="x-cnsdns-hmac: $hmac" export _H4="Accept: application/json" @@ -122,9 +126,9 @@ _constellix_rest() { if [ "$m" != "GET" ]; then _debug data "$data" - response="$(_post "$data" "$CONSTELLIX_API/$ep" "" "$m")" + response="$(_post "$data" "$CONSTELLIX_Api/$ep" "" "$m")" else - response="$(_get "$CONSTELLIX_API/$ep")" + response="$(_get "$CONSTELLIX_Api/$ep")" fi if [ "$?" != "0" ]; then From 5d88ad554feb1f7b676ecb75c89e2f1543261fbf Mon Sep 17 00:00:00 2001 From: Victor Huang Date: Sat, 8 Feb 2020 23:24:45 +0800 Subject: [PATCH 193/357] Improved token processing method and misc bugfixes Replace '_err' to '_debug' in the final error report. Removed redundancy code. --- notify/cqhttp.sh | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/notify/cqhttp.sh b/notify/cqhttp.sh index fe78a0fd..ac76f5b8 100644 --- a/notify/cqhttp.sh +++ b/notify/cqhttp.sh @@ -1,7 +1,7 @@ #!/usr/bin/env sh #Support for CQHTTP api. Push notification on CoolQ -#CQHTTP_TOKEN="" Required, QQ application token +#CQHTTP_TOKEN="" Recommended to be not empty, QQ application token #CQHTTP_USER="" Required, QQ receiver ID #CQHTTP_APIROOT="" Required, CQHTTP Server URL (without slash suffix) #CQHTTP_CUSTOM_MSGHEAD="" Optional, custom message header @@ -17,12 +17,9 @@ cqhttp_send() { CQHTTP_TOKEN="${CQHTTP_TOKEN:-$(_readaccountconf_mutable CQHTTP_TOKEN)}" if [ -z "$CQHTTP_TOKEN" ]; then CQHTTP_TOKEN="" - _err "You didn't specify a CQHTTP application token yet. If it's empty please pass \"__ACME_SH_TOKEN_EMPTY__\" (without quote)." - return 1 - fi - _saveaccountconf_mutable CQHTTP_TOKEN "$CQHTTP_TOKEN" - if [ "$CQHTTP_TOKEN" = "__ACME_SH_TOKEN_EMPTY__" ]; then - CQHTTP_TOKEN="" + _info "You didn't specify a CQHTTP application token yet, which is unsafe. Assuming it to be empty." + else + _saveaccountconf_mutable CQHTTP_TOKEN "$CQHTTP_TOKEN" fi CQHTTP_USER="${CQHTTP_USER:-$(_readaccountconf_mutable CQHTTP_USER)}" @@ -36,15 +33,7 @@ cqhttp_send() { CQHTTP_APIROOT="${CQHTTP_APIROOT:-$(_readaccountconf_mutable CQHTTP_APIROOT)}" if [ -z "$CQHTTP_APIROOT" ]; then CQHTTP_APIROOT="" - _err "You didn't specify a QQ user yet." - return 1 - fi - _saveaccountconf_mutable CQHTTP_APIROOT "$CQHTTP_APIROOT" - - CQHTTP_APIROOT="${CQHTTP_APIROOT:-$(_readaccountconf_mutable CQHTTP_APIROOT)}" - if [ -z "$CQHTTP_APIROOT" ]; then - CQHTTP_APIROOT="" - _err "You didn't specify a QQ user yet." + _err "You didn't specify the API root yet." return 1 fi _saveaccountconf_mutable CQHTTP_APIROOT "$CQHTTP_APIROOT" @@ -69,7 +58,7 @@ cqhttp_send() { fi _err "QQ send error." - _err "URL: $_finalUrl" - _err "Response: $response" + _debug "URL" "$_finalUrl" + _debug "Response" "$response" return 1 } From 8189a34d145050a3ffb5598d330e6bcdd4cadf02 Mon Sep 17 00:00:00 2001 From: Blfrg Date: Sat, 8 Feb 2020 16:43:23 -0600 Subject: [PATCH 194/357] fix dns_me id parse The API seems to have changed and the ID is no longer in the same location. --- dnsapi/dns_me.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_me.sh b/dnsapi/dns_me.sh index 98a58411..302603ea 100644 --- a/dnsapi/dns_me.sh +++ b/dnsapi/dns_me.sh @@ -114,7 +114,7 @@ _get_root() { fi if _contains "$response" "\"name\":\"$h\""; then - _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*" | head -n 1 | cut -d : -f 2 | tr -d '}') + _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]+}$" | 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" From 555e0de9e45f36ddd2507975a0368eaab9141074 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sat, 29 Jun 2019 21:47:24 -0600 Subject: [PATCH 195/357] Initial support for Synology DSM This allows you to update a key on a Synology DSM using the existing API. Handles restarting the necessary services the certificate is attached to and all other internal stuff (copying the certificate around, etc.) This is way less error prone than most articles I've found on how to update a Synology DSM certificate. --- deploy/synology_dsm.sh | 145 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 deploy/synology_dsm.sh diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh new file mode 100644 index 00000000..45eab335 --- /dev/null +++ b/deploy/synology_dsm.sh @@ -0,0 +1,145 @@ +#!/usr/bin/env sh + +# Here is a script to deploy cert to Synology DSM vault +# (https://www.vaultproject.io/) +# +# it requires the jq and curl are in the $PATH and the following +# environment variables must be set: +# +# 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 +# +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +synology_dsm_deploy() { + + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + + _debug _cdomain "$_cdomain" + + # Get Username and Password, but don't save until we successfully authenticate + SYNO_Username="${SYNO_Username:-$(_readaccountconf_mutable SYNO_Username)}" + SYNO_Password="${SYNO_Password:-$(_readaccountconf_mutable SYNO_Password)}" + if [ -z "$SYNO_Username" ] || [ -z "$SYNO_Password" ]; then + SYNO_Username="" + SYNO_Password="" + _err "SYNO_Username & SYNO_Password must be set" + return 1 + fi + _debug2 SYNO_Username "$SYNO_Username" + _secure_debug2 SYNO_Password "$SYNO_Password" + + # Optional scheme, hostname, and port for Synology DSM + SYNO_Scheme="${SYNO_Scheme:-$(_readaccountconf_mutable SYNO_Scheme)}" + SYNO_Hostname="${SYNO_Hostname:-$(_readaccountconf_mutable SYNO_Hostname)}" + SYNO_Port="${SYNO_Port:-$(_readaccountconf_mutable SYNO_Port)}" + _saveaccountconf_mutable SYNO_Scheme "$SYNO_Scheme" + _saveaccountconf_mutable SYNO_Hostname "$SYNO_Hostname" + _saveaccountconf_mutable SYNO_Port "$SYNO_Port" + + # default vaules for scheme, hostname, and port + # defaulting to localhost and http because it's localhost... + [ -n "${SYNO_Scheme}" ] || SYNO_Scheme="http" + [ -n "${SYNO_Hostname}" ] || SYNO_Hostname="localhost" + [ -n "${SYNO_Port}" ] || SYNO_Port="5000" + + _debug2 SYNO_Scheme "$SYNO_Scheme" + _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 + _getdeployconf SYNO_Certificate + if [ -z "${SYNO_Certificate}" ]; then + _err "SYNO_Certificate needs to be defined (with the Certificate description name)" + return 1 + fi + _debug SYNO_Certificate "$SYNO_Certificate" + + # We can't use _get or _post because they lack support for cookies + # use jq because I'm too lazy to figure out what is required to parse json + # by hand. Also it seems to be in place for Synology DSM (6.2.1 at least) + for x in curl jq; do + if ! _exists "$x"; then + _err "Please install $x first." + _err "We need $x to work." + return 1 + fi + done + + _base_url="$SYNO_Scheme://$SYNO_Hostname:$SYNO_Port" + _debug _base_url "$_base_url" + + _cookie_jar="$(_mktemp)" + _debug _cookie_jar "$_cookie_jar" + + # Login, get the token from JSON and session id from cookie + _debug "Logging into $SYNO_Hostname:$SYNO_Port" + token=$(curl -sk -c $_cookie_jar "$_base_url/webman/login.cgi?username=$SYNO_Username&passwd=$SYNO_Password&enable_syno_token=yes" | jq -r .SynoToken) + if [ $token = "null" ]; then + _err "Unable to authenticate to $SYNO_Hostname:$SYNO_Port using $SYNO_Scheme." + _err "Check your username and password." + rm "$_cookie_jar" + return 1 + fi + + # Now that we know the username and password are good, save them + _saveaccountconf_mutable SYNO_Username "$SYNO_Username" + _saveaccountconf_mutable SYNO_Password "$SYNO_Password" + _secure_debug2 token "$token" + + # Use token and session id to get the list of certificates + response=$(curl -sk -b $_cookie_jar $_base_url/webapi/entry.cgi -H "X-SYNO-TOKEN: $token" -d api=SYNO.Core.Certificate.CRT -d method=list -d version=1) + _debug3 response "$response" + # select the first certificate matching our description + cert=$(echo "$response" | jq -r ".data.certificates | map(select(.desc == \"$SYNO_Certificate\"))[0]") + _debug3 cert "$cert" + + if [ "$cert" = "null" ]; then + _err "Unable to find certificate: $SYNO_Certificate" + rm "$_cookie_jar" + return 1 + fi + + # we've verified this certificate description is a thing, so save it + _savedeployconf SYNO_Certificate "$SYNO_Certificate" + + id=$(echo $cert | jq -r ".id") + default=$(echo "$cert" | jq -r ".is_default") + _debug2 id "$id" + _debug2 default "$default" + + # This is the heavy lifting, make the API call to update a certificate in place + response=$(curl -sk -b $_cookie_jar "$_base_url/webapi/entry.cgi?api=SYNO.Core.Certificate&method=import&version=1&SynoToken=$token" -F key=@$_ckey -F cert=@$_ccert -F inter_cert=@$_cca -F id=$id -F desc=$SYNO_Certificate -F as_default=$default) + _debug3 response "$response" + success=$(echo "$response" | jq -r ".success") + _debug2 success "$success" + rm "$_cookie_jar" + + if [ "$success" = "true" ]; then + restarted=$(echo "$response" | jq -r ".data.restart_httpd") + if [ "$restarted" = "true" ]; then + _info "http services were restarted" + else + _info "http services were NOT restarted" + fi + return 0; + else + code=$(echo "$response" | jq -r ".error.code") + _err "Unable to update certificate, error code $code" + return 1 + fi +} From 548f83c3adf4533140980774892cc484937960ac Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sun, 30 Jun 2019 00:13:07 -0600 Subject: [PATCH 196/357] Cleanup shellcheck errors --- deploy/synology_dsm.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 45eab335..d131e9cd 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -63,6 +63,7 @@ synology_dsm_deploy() { # Get the certificate description, but don't save it until we verfiy it's real _getdeployconf SYNO_Certificate + # shellcheck disable=SC2154 if [ -z "${SYNO_Certificate}" ]; then _err "SYNO_Certificate needs to be defined (with the Certificate description name)" return 1 @@ -88,8 +89,8 @@ synology_dsm_deploy() { # Login, get the token from JSON and session id from cookie _debug "Logging into $SYNO_Hostname:$SYNO_Port" - token=$(curl -sk -c $_cookie_jar "$_base_url/webman/login.cgi?username=$SYNO_Username&passwd=$SYNO_Password&enable_syno_token=yes" | jq -r .SynoToken) - if [ $token = "null" ]; then + token=$(curl -sk -c "$_cookie_jar" "$_base_url/webman/login.cgi?username=$SYNO_Username&passwd=$SYNO_Password&enable_syno_token=yes" | jq -r .SynoToken) + if [ "$token" = "null" ]; then _err "Unable to authenticate to $SYNO_Hostname:$SYNO_Port using $SYNO_Scheme." _err "Check your username and password." rm "$_cookie_jar" @@ -102,7 +103,7 @@ synology_dsm_deploy() { _secure_debug2 token "$token" # Use token and session id to get the list of certificates - response=$(curl -sk -b $_cookie_jar $_base_url/webapi/entry.cgi -H "X-SYNO-TOKEN: $token" -d api=SYNO.Core.Certificate.CRT -d method=list -d version=1) + response=$(curl -sk -b "$_cookie_jar" "$_base_url/webapi/entry.cgi" -H "X-SYNO-TOKEN: $token" -d api=SYNO.Core.Certificate.CRT -d method=list -d version=1) _debug3 response "$response" # select the first certificate matching our description cert=$(echo "$response" | jq -r ".data.certificates | map(select(.desc == \"$SYNO_Certificate\"))[0]") @@ -117,13 +118,13 @@ synology_dsm_deploy() { # we've verified this certificate description is a thing, so save it _savedeployconf SYNO_Certificate "$SYNO_Certificate" - id=$(echo $cert | jq -r ".id") + id=$(echo "$cert" | jq -r ".id") default=$(echo "$cert" | jq -r ".is_default") _debug2 id "$id" _debug2 default "$default" # This is the heavy lifting, make the API call to update a certificate in place - response=$(curl -sk -b $_cookie_jar "$_base_url/webapi/entry.cgi?api=SYNO.Core.Certificate&method=import&version=1&SynoToken=$token" -F key=@$_ckey -F cert=@$_ccert -F inter_cert=@$_cca -F id=$id -F desc=$SYNO_Certificate -F as_default=$default) + response=$(curl -sk -b "$_cookie_jar" "$_base_url/webapi/entry.cgi?api=SYNO.Core.Certificate&method=import&version=1&SynoToken=$token" -F "key=@$_ckey" -F "cert=@$_ccert" -F "inter_cert=@$_cca" -F "id=$id" -F "desc=$SYNO_Certificate" -F "as_default=$default") _debug3 response "$response" success=$(echo "$response" | jq -r ".success") _debug2 success "$success" From 6459ccb18517c3f9f6c87410df8d76a0082020e3 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sun, 30 Jun 2019 00:13:45 -0600 Subject: [PATCH 197/357] Cleanup shfmt warnings --- deploy/synology_dsm.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index d131e9cd..7fab47d8 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -74,11 +74,11 @@ synology_dsm_deploy() { # use jq because I'm too lazy to figure out what is required to parse json # by hand. Also it seems to be in place for Synology DSM (6.2.1 at least) for x in curl jq; do - if ! _exists "$x"; then - _err "Please install $x first." - _err "We need $x to work." - return 1 - fi + if ! _exists "$x"; then + _err "Please install $x first." + _err "We need $x to work." + return 1 + fi done _base_url="$SYNO_Scheme://$SYNO_Hostname:$SYNO_Port" @@ -133,11 +133,11 @@ synology_dsm_deploy() { if [ "$success" = "true" ]; then restarted=$(echo "$response" | jq -r ".data.restart_httpd") if [ "$restarted" = "true" ]; then - _info "http services were restarted" + _info "http services were restarted" else - _info "http services were NOT restarted" + _info "http services were NOT restarted" fi - return 0; + return 0 else code=$(echo "$response" | jq -r ".error.code") _err "Unable to update certificate, error code $code" From 8e8cda132c0ab64548122478ab59f6eea7262dba Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sun, 30 Jun 2019 00:30:35 -0600 Subject: [PATCH 198/357] Remove boilerplate from what I used for template --- deploy/synology_dsm.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 7fab47d8..e37d7d44 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -1,7 +1,6 @@ #!/usr/bin/env sh -# Here is a script to deploy cert to Synology DSM vault -# (https://www.vaultproject.io/) +# Here is a script to deploy cert to Synology DSM # # it requires the jq and curl are in the $PATH and the following # environment variables must be set: From b3b00b6700e7bc960d96ddd0f2abf1315cab0e03 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Mon, 30 Sep 2019 14:06:04 -0600 Subject: [PATCH 199/357] Using domainconf instead of account --- deploy/synology_dsm.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index e37d7d44..25b63767 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -31,8 +31,8 @@ synology_dsm_deploy() { _debug _cdomain "$_cdomain" # Get Username and Password, but don't save until we successfully authenticate - SYNO_Username="${SYNO_Username:-$(_readaccountconf_mutable SYNO_Username)}" - SYNO_Password="${SYNO_Password:-$(_readaccountconf_mutable SYNO_Password)}" + SYNO_Username="${SYNO_Username:-$(_readdomainconf SYNO_Username)}" + SYNO_Password="${SYNO_Password:-$(_readdomainconf SYNO_Password)}" if [ -z "$SYNO_Username" ] || [ -z "$SYNO_Password" ]; then SYNO_Username="" SYNO_Password="" @@ -43,12 +43,12 @@ synology_dsm_deploy() { _secure_debug2 SYNO_Password "$SYNO_Password" # Optional scheme, hostname, and port for Synology DSM - SYNO_Scheme="${SYNO_Scheme:-$(_readaccountconf_mutable SYNO_Scheme)}" - SYNO_Hostname="${SYNO_Hostname:-$(_readaccountconf_mutable SYNO_Hostname)}" - SYNO_Port="${SYNO_Port:-$(_readaccountconf_mutable SYNO_Port)}" - _saveaccountconf_mutable SYNO_Scheme "$SYNO_Scheme" - _saveaccountconf_mutable SYNO_Hostname "$SYNO_Hostname" - _saveaccountconf_mutable SYNO_Port "$SYNO_Port" + SYNO_Scheme="${SYNO_Scheme:-$(_readdomainconf SYNO_Scheme)}" + SYNO_Hostname="${SYNO_Hostname:-$(_readdomainconf SYNO_Hostname)}" + SYNO_Port="${SYNO_Port:-$(_readdomainconf SYNO_Port)}" + _savedomainconf SYNO_Scheme "$SYNO_Scheme" + _savedomainconf SYNO_Hostname "$SYNO_Hostname" + _savedomainconf SYNO_Port "$SYNO_Port" # default vaules for scheme, hostname, and port # defaulting to localhost and http because it's localhost... @@ -97,8 +97,8 @@ synology_dsm_deploy() { fi # Now that we know the username and password are good, save them - _saveaccountconf_mutable SYNO_Username "$SYNO_Username" - _saveaccountconf_mutable SYNO_Password "$SYNO_Password" + _savedomainconf SYNO_Username "$SYNO_Username" + _savedomainconf SYNO_Password "$SYNO_Password" _secure_debug2 token "$token" # Use token and session id to get the list of certificates From 52a168b96160d5c407e54067181bedebe2c9aad9 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sat, 8 Feb 2020 16:27:18 -0800 Subject: [PATCH 200/357] Stop using jq/curl directly This is a lot more fragile then the previous code due to treating JSON as just a string --- deploy/synology_dsm.sh | 103 ++++++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 48 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 25b63767..82645829 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -20,6 +20,12 @@ ######## Public functions ##################### +_syno_get_cookie_data() { + _debug2 Cookie "$1" + _debug3 grep "$(grep "\W$1=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';' )" + grep "\W$1=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';' +} + #domain keyfile certfile cafile fullchain synology_dsm_deploy() { @@ -31,8 +37,8 @@ synology_dsm_deploy() { _debug _cdomain "$_cdomain" # Get Username and Password, but don't save until we successfully authenticate - SYNO_Username="${SYNO_Username:-$(_readdomainconf SYNO_Username)}" - SYNO_Password="${SYNO_Password:-$(_readdomainconf SYNO_Password)}" + SYNO_Username="${SYNO_Username:-$(_getdeployconf SYNO_Username)}" + SYNO_Password="${SYNO_Password:-$(_getdeployconf SYNO_Password)}" if [ -z "$SYNO_Username" ] || [ -z "$SYNO_Password" ]; then SYNO_Username="" SYNO_Password="" @@ -43,12 +49,12 @@ synology_dsm_deploy() { _secure_debug2 SYNO_Password "$SYNO_Password" # Optional scheme, hostname, and port for Synology DSM - SYNO_Scheme="${SYNO_Scheme:-$(_readdomainconf SYNO_Scheme)}" - SYNO_Hostname="${SYNO_Hostname:-$(_readdomainconf SYNO_Hostname)}" - SYNO_Port="${SYNO_Port:-$(_readdomainconf SYNO_Port)}" - _savedomainconf SYNO_Scheme "$SYNO_Scheme" - _savedomainconf SYNO_Hostname "$SYNO_Hostname" - _savedomainconf SYNO_Port "$SYNO_Port" + SYNO_Scheme="${SYNO_Scheme:-$(_getdeployconf SYNO_Scheme)}" + SYNO_Hostname="${SYNO_Hostname:-$(_getdeployconf SYNO_Hostname)}" + SYNO_Port="${SYNO_Port:-$(_getdeployconf SYNO_Port)}" + _savedeployconf SYNO_Scheme "$SYNO_Scheme" + _savedeployconf SYNO_Hostname "$SYNO_Hostname" + _savedeployconf SYNO_Port "$SYNO_Port" # default vaules for scheme, hostname, and port # defaulting to localhost and http because it's localhost... @@ -69,77 +75,78 @@ synology_dsm_deploy() { fi _debug SYNO_Certificate "$SYNO_Certificate" - # We can't use _get or _post because they lack support for cookies - # use jq because I'm too lazy to figure out what is required to parse json - # by hand. Also it seems to be in place for Synology DSM (6.2.1 at least) - for x in curl jq; do - if ! _exists "$x"; then - _err "Please install $x first." - _err "We need $x to work." - return 1 - fi - done - _base_url="$SYNO_Scheme://$SYNO_Hostname:$SYNO_Port" _debug _base_url "$_base_url" - _cookie_jar="$(_mktemp)" - _debug _cookie_jar "$_cookie_jar" - # Login, get the token from JSON and session id from cookie - _debug "Logging into $SYNO_Hostname:$SYNO_Port" - token=$(curl -sk -c "$_cookie_jar" "$_base_url/webman/login.cgi?username=$SYNO_Username&passwd=$SYNO_Password&enable_syno_token=yes" | jq -r .SynoToken) - if [ "$token" = "null" ]; then + _info "Logging into $SYNO_Hostname:$SYNO_Port" + response=$(_get "$_base_url/webman/login.cgi?username=$SYNO_Username&passwd=$SYNO_Password&enable_syno_token=yes") + token=$(echo "$response" | grep "SynoToken" | sed -n 's/.*"SynoToken" *: *"\([^"]*\).*/\1/p') + _debug3 response "$response" + + if [ -z "$token" ]; then _err "Unable to authenticate to $SYNO_Hostname:$SYNO_Port using $SYNO_Scheme." _err "Check your username and password." - rm "$_cookie_jar" return 1 fi + _H1="Cookie: $(_syno_get_cookie_data "id"); $(_syno_get_cookie_data "smid")" + _H2="X-SYNO-TOKEN: $token" + export _H1 + export _H2 + _debug3 H1 "${_H1}" + _debug3 H2 "${_H2}" + # Now that we know the username and password are good, save them - _savedomainconf SYNO_Username "$SYNO_Username" - _savedomainconf SYNO_Password "$SYNO_Password" + _savedeployconf SYNO_Username "$SYNO_Username" + _savedeployconf SYNO_Password "$SYNO_Password" _secure_debug2 token "$token" - # Use token and session id to get the list of certificates - response=$(curl -sk -b "$_cookie_jar" "$_base_url/webapi/entry.cgi" -H "X-SYNO-TOKEN: $token" -d api=SYNO.Core.Certificate.CRT -d method=list -d version=1) + _info "Getting certificates in Synology DSM" + response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1" "$_base_url/webapi/entry.cgi") _debug3 response "$response" - # select the first certificate matching our description - cert=$(echo "$response" | jq -r ".data.certificates | map(select(.desc == \"$SYNO_Certificate\"))[0]") - _debug3 cert "$cert" + id=$(printf "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\"id\":\"\([^\"]*\).*/\1/p") + _debug2 id "$id" - if [ "$cert" = "null" ]; then + if [ -z "$id" ]; then _err "Unable to find certificate: $SYNO_Certificate" - rm "$_cookie_jar" return 1 fi # we've verified this certificate description is a thing, so save it _savedeployconf SYNO_Certificate "$SYNO_Certificate" - id=$(echo "$cert" | jq -r ".id") - default=$(echo "$cert" | jq -r ".is_default") - _debug2 id "$id" + default=false + if printf "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\([^{]*\).*/\1/p" | grep -q -- 'is_default":true'; then + default=true + fi _debug2 default "$default" - # This is the heavy lifting, make the API call to update a certificate in place - response=$(curl -sk -b "$_cookie_jar" "$_base_url/webapi/entry.cgi?api=SYNO.Core.Certificate&method=import&version=1&SynoToken=$token" -F "key=@$_ckey" -F "cert=@$_ccert" -F "inter_cert=@$_cca" -F "id=$id" -F "desc=$SYNO_Certificate" -F "as_default=$default") + _info "Generate form POST request" + nl="\015\012" + delim="--------------------------$(date +%Y%m%d%H%M%S)" + content="--$delim${nl}Content-Disposition: form-data; name=\"key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")\012" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"cert\"; filename=\"$(basename "$_ccert")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ccert")\012" + 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")\012" + 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}" + content="$content${nl}--$delim--${nl}" + content="$(printf "%b_" "$content")";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}") _debug3 response "$response" - success=$(echo "$response" | jq -r ".success") - _debug2 success "$success" - rm "$_cookie_jar" - if [ "$success" = "true" ]; then - restarted=$(echo "$response" | jq -r ".data.restart_httpd") - if [ "$restarted" = "true" ]; then + if ! printf "$response" | grep -q '"error":'; then + if printf "$response" | grep -q '"restart_httpd":true'; then _info "http services were restarted" else _info "http services were NOT restarted" fi return 0 else - code=$(echo "$response" | jq -r ".error.code") - _err "Unable to update certificate, error code $code" + _err "Unable to update certificate, error code $response" return 1 fi } From 95769de464b6e21a3b31c644febd262738d0f63c Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sun, 9 Feb 2020 02:01:26 -0800 Subject: [PATCH 201/357] Fix shfmt/shellcheck issues --- deploy/synology_dsm.sh | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 82645829..7d713930 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -22,7 +22,7 @@ _syno_get_cookie_data() { _debug2 Cookie "$1" - _debug3 grep "$(grep "\W$1=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';' )" + _debug3 grep "$(grep "\W$1=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';')" grep "\W$1=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';' } @@ -105,7 +105,7 @@ synology_dsm_deploy() { _info "Getting certificates in Synology DSM" response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1" "$_base_url/webapi/entry.cgi") _debug3 response "$response" - id=$(printf "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\"id\":\"\([^\"]*\).*/\1/p") + id=$(echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\"id\":\"\([^\"]*\).*/\1/p") _debug2 id "$id" if [ -z "$id" ]; then @@ -117,8 +117,8 @@ synology_dsm_deploy() { _savedeployconf SYNO_Certificate "$SYNO_Certificate" default=false - if printf "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\([^{]*\).*/\1/p" | grep -q -- 'is_default":true'; then - default=true + if echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\([^{]*\).*/\1/p" | grep -q -- 'is_default":true'; then + default=true fi _debug2 default "$default" @@ -132,14 +132,15 @@ synology_dsm_deploy() { 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}" content="$content${nl}--$delim--${nl}" - content="$(printf "%b_" "$content")";content="${content%_}" # protect trailing \n + content="$(printf "%b_" "$content")" + 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}") _debug3 response "$response" - if ! printf "$response" | grep -q '"error":'; then - if printf "$response" | grep -q '"restart_httpd":true'; then + if ! echo "$response" | grep -q '"error":'; then + if echo "$response" | grep -q '"restart_httpd":true'; then _info "http services were restarted" else _info "http services were NOT restarted" From de25232a7345d8dfe221d1d1a131419182989ca6 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sun, 9 Feb 2020 02:26:55 -0800 Subject: [PATCH 202/357] Allow creating new certificates when certificate is not found --- 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 7d713930..71d9e7dc 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -39,6 +39,7 @@ synology_dsm_deploy() { # Get Username and Password, but don't save until we successfully authenticate SYNO_Username="${SYNO_Username:-$(_getdeployconf SYNO_Username)}" SYNO_Password="${SYNO_Password:-$(_getdeployconf SYNO_Password)}" + SYNO_Create="${SYNO_Create:-$(_getdeployconf SYNO_Create)}" if [ -z "$SYNO_Username" ] || [ -z "$SYNO_Password" ]; then SYNO_Username="" SYNO_Password="" @@ -108,8 +109,8 @@ synology_dsm_deploy() { id=$(echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\"id\":\"\([^\"]*\).*/\1/p") _debug2 id "$id" - if [ -z "$id" ]; then - _err "Unable to find certificate: $SYNO_Certificate" + if [ -z "$id" ] && [ -z "$SYNO_Create" ]; then + _err "Unable to find certificate: $SYNO_Certificate and \$SYNO_Create is not set" return 1 fi From 5d3bc95ac529550077505189b4e2cc07ca4b5155 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sun, 9 Feb 2020 02:50:29 -0800 Subject: [PATCH 203/357] Fix some debug output --- deploy/synology_dsm.sh | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 71d9e7dc..bb49f279 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -21,8 +21,6 @@ ######## Public functions ##################### _syno_get_cookie_data() { - _debug2 Cookie "$1" - _debug3 grep "$(grep "\W$1=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';')" grep "\W$1=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';' } @@ -95,13 +93,13 @@ synology_dsm_deploy() { _H2="X-SYNO-TOKEN: $token" export _H1 export _H2 - _debug3 H1 "${_H1}" - _debug3 H2 "${_H2}" + _debug2 H1 "${_H1}" + _debug2 H2 "${_H2}" # Now that we know the username and password are good, save them _savedeployconf SYNO_Username "$SYNO_Username" _savedeployconf SYNO_Password "$SYNO_Password" - _secure_debug2 token "$token" + _debug token "$token" _info "Getting certificates in Synology DSM" response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1" "$_base_url/webapi/entry.cgi") From 1259341095f2b15946f0db39ce53f821b194c00f Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sun, 9 Feb 2020 03:10:11 -0800 Subject: [PATCH 204/357] Use deployconf properly --- deploy/synology_dsm.sh | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index bb49f279..13728d66 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -35,9 +35,9 @@ synology_dsm_deploy() { _debug _cdomain "$_cdomain" # Get Username and Password, but don't save until we successfully authenticate - SYNO_Username="${SYNO_Username:-$(_getdeployconf SYNO_Username)}" - SYNO_Password="${SYNO_Password:-$(_getdeployconf SYNO_Password)}" - SYNO_Create="${SYNO_Create:-$(_getdeployconf SYNO_Create)}" + _getdeployconf SYNO_Username + _getdeployconf SYNO_Password + _getdeployconf SYNO_Create if [ -z "$SYNO_Username" ] || [ -z "$SYNO_Password" ]; then SYNO_Username="" SYNO_Password="" @@ -48,12 +48,9 @@ synology_dsm_deploy() { _secure_debug2 SYNO_Password "$SYNO_Password" # Optional scheme, hostname, and port for Synology DSM - SYNO_Scheme="${SYNO_Scheme:-$(_getdeployconf SYNO_Scheme)}" - SYNO_Hostname="${SYNO_Hostname:-$(_getdeployconf SYNO_Hostname)}" - SYNO_Port="${SYNO_Port:-$(_getdeployconf SYNO_Port)}" - _savedeployconf SYNO_Scheme "$SYNO_Scheme" - _savedeployconf SYNO_Hostname "$SYNO_Hostname" - _savedeployconf SYNO_Port "$SYNO_Port" + _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... @@ -61,6 +58,10 @@ synology_dsm_deploy() { [ -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" @@ -107,6 +108,7 @@ synology_dsm_deploy() { id=$(echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\"id\":\"\([^\"]*\).*/\1/p") _debug2 id "$id" + # shellcheck disable=SC2154 if [ -z "$id" ] && [ -z "$SYNO_Create" ]; then _err "Unable to find certificate: $SYNO_Certificate and \$SYNO_Create is not set" return 1 From 79637097bada83f251c68159df4baa657f16d7ad Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sun, 9 Feb 2020 11:50:50 -0800 Subject: [PATCH 205/357] Use _utc_date --- 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 13728d66..dd26e3d8 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -125,7 +125,7 @@ synology_dsm_deploy() { _info "Generate form POST request" nl="\015\012" - delim="--------------------------$(date +%Y%m%d%H%M%S)" + delim="--------------------------$(_utc_date | tr -d -- '-: ')" content="--$delim${nl}Content-Disposition: form-data; name=\"key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")\012" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"cert\"; filename=\"$(basename "$_ccert")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ccert")\012" 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")\012" From d07172a52843b8eeb412e85f2cdfc9a527c646c6 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sun, 9 Feb 2020 12:06:13 -0800 Subject: [PATCH 206/357] Replace disabled linter with variable substituion --- deploy/synology_dsm.sh | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index dd26e3d8..f1c08c36 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -68,8 +68,7 @@ synology_dsm_deploy() { # Get the certificate description, but don't save it until we verfiy it's real _getdeployconf SYNO_Certificate - # shellcheck disable=SC2154 - if [ -z "${SYNO_Certificate}" ]; then + if [ -z "${SYNO_Certificate:?}" ]; then _err "SYNO_Certificate needs to be defined (with the Certificate description name)" return 1 fi @@ -108,8 +107,7 @@ synology_dsm_deploy() { id=$(echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\"id\":\"\([^\"]*\).*/\1/p") _debug2 id "$id" - # shellcheck disable=SC2154 - if [ -z "$id" ] && [ -z "$SYNO_Create" ]; then + if [ -z "$id" ] && [ -z "${SYNO_Create:?}" ]; then _err "Unable to find certificate: $SYNO_Certificate and \$SYNO_Create is not set" return 1 fi From eb49127b9ec75472c663eaaebb6370ab95a3f357 Mon Sep 17 00:00:00 2001 From: Blfrg Date: Sun, 9 Feb 2020 14:50:29 -0600 Subject: [PATCH 207/357] improve id parse Locate only the outer most "id" property --- dnsapi/dns_me.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_me.sh b/dnsapi/dns_me.sh index 302603ea..db51cc7c 100644 --- a/dnsapi/dns_me.sh +++ b/dnsapi/dns_me.sh @@ -114,7 +114,7 @@ _get_root() { fi if _contains "$response" "\"name\":\"$h\""; then - _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]+}$" | head -n 1 | cut -d : -f 2 | tr -d '}') + _domain_id=$(printf "%s\n" "$response" | cut -c 2- | head -c -2 | sed 's/{.*}//' | sed -r 's/^.*"id":([0-9]+).*$/\1/') if [ "$_domain_id" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain="$h" From 719b690451c9ec28f42bb7889fb1658f9efc0591 Mon Sep 17 00:00:00 2001 From: Arthur Wiebe Date: Mon, 10 Feb 2020 10:22:55 -0500 Subject: [PATCH 208/357] add support for using a Zone ID --- dnsapi/dns_cf.sh | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/dnsapi/dns_cf.sh b/dnsapi/dns_cf.sh index 62e40caf..f29f0f51 100755 --- a/dnsapi/dns_cf.sh +++ b/dnsapi/dns_cf.sh @@ -7,6 +7,7 @@ #CF_Token="xxxx" #CF_Account_ID="xxxx" +#CF_Zone_ID="xxxx" CF_Api="https://api.cloudflare.com/client/v4" @@ -19,12 +20,14 @@ dns_cf_add() { CF_Token="${CF_Token:-$(_readaccountconf_mutable CF_Token)}" CF_Account_ID="${CF_Account_ID:-$(_readaccountconf_mutable CF_Account_ID)}" + CF_Zone_ID="${CF_Zone_ID:-$(_readaccountconf_mutable CF_Zone_ID)}" CF_Key="${CF_Key:-$(_readaccountconf_mutable CF_Key)}" CF_Email="${CF_Email:-$(_readaccountconf_mutable CF_Email)}" if [ "$CF_Token" ]; then _saveaccountconf_mutable CF_Token "$CF_Token" _saveaccountconf_mutable CF_Account_ID "$CF_Account_ID" + _saveaccountconf_mutable CF_Zone_ID "$CF_Zone_ID" else if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then CF_Key="" @@ -141,6 +144,28 @@ _get_root() { domain=$1 i=1 p=1 + + # Use Zone ID directly if provided + if [ "$CF_Zone_ID" ]; then + if ! _cf_rest GET "zones/$CF_Zone_ID"; then + return 1 + else + if _contains "$response" '"success":true'; then + _domain=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1) + if [ "$_domain" ]; then + _cutlength=$(expr ${#domain} - ${#_domain} - 1) + _sub_domain=$(printf "%s" "$domain" | cut -c 1-$_cutlength) + _domain_id=$CF_Zone_ID + return 0 + else + return 1 + fi + else + return 1 + fi + fi + fi + while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug h "$h" From 1b475cf9f3997c27aae49ab578dd7070d9169b3d Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Mon, 10 Feb 2020 21:02:27 -0700 Subject: [PATCH 209/357] Remove -q from greps --- deploy/synology_dsm.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index f1c08c36..0c2b1185 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -116,7 +116,7 @@ synology_dsm_deploy() { _savedeployconf SYNO_Certificate "$SYNO_Certificate" default=false - if echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\([^{]*\).*/\1/p" | grep -q -- 'is_default":true'; then + if echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\([^{]*\).*/\1/p" | grep -- 'is_default":true' >/dev/null; then default=true fi _debug2 default "$default" @@ -138,8 +138,8 @@ synology_dsm_deploy() { response=$(_post "$content" "$_base_url/webapi/entry.cgi?api=SYNO.Core.Certificate&method=import&version=1&SynoToken=$token" "" "POST" "multipart/form-data; boundary=${delim}") _debug3 response "$response" - if ! echo "$response" | grep -q '"error":'; then - if echo "$response" | grep -q '"restart_httpd":true'; then + if ! echo "$response" | grep '"error":' >/dev/null; then + if echo "$response" | grep '"restart_httpd":true' >/dev/null; then _info "http services were restarted" else _info "http services were NOT restarted" From d43227ede4fdc47f22abe971e647b3686678b607 Mon Sep 17 00:00:00 2001 From: Arthur Wiebe Date: Tue, 11 Feb 2020 13:07:10 -0500 Subject: [PATCH 210/357] fix shellcheck issues --- dnsapi/dns_cf.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_cf.sh b/dnsapi/dns_cf.sh index f29f0f51..2927ab4b 100755 --- a/dnsapi/dns_cf.sh +++ b/dnsapi/dns_cf.sh @@ -153,8 +153,8 @@ _get_root() { if _contains "$response" '"success":true'; then _domain=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1) if [ "$_domain" ]; then - _cutlength=$(expr ${#domain} - ${#_domain} - 1) - _sub_domain=$(printf "%s" "$domain" | cut -c 1-$_cutlength) + _cutlength=$((${#domain} - ${#_domain} - 1)) + _sub_domain=$(printf "%s" "$domain" | cut -c "1-$_cutlength") _domain_id=$CF_Zone_ID return 0 else From c2812896f8947c29117fe3a8b0832965aabdabeb Mon Sep 17 00:00:00 2001 From: Paul Nguyen Date: Tue, 11 Feb 2020 18:15:10 -0800 Subject: [PATCH 211/357] Update deployer --- deploy/panos.sh | 112 +++++++++++++++++++++++++----------------------- 1 file changed, 58 insertions(+), 54 deletions(-) diff --git a/deploy/panos.sh b/deploy/panos.sh index 8a288e7b..ca03706f 100644 --- a/deploy/panos.sh +++ b/deploy/panos.sh @@ -13,61 +13,75 @@ # This function is to parse the XML parse_response() { - status=$(echo "$1" | sed 's/^.*"\([a-z]*\)".*/\1/g') - message=$(echo "$1" | sed 's/^.*\(.*\)<\/result.*/\1/g') + type=$2 + if [ $type = 'keygen' ]; then + status=$(echo "$1" | sed 's/^.*\(['\'']\)\([a-z]*\)'\''.*/\2/g') + if [ "$status" = "success" ]; then + panos_key=$(echo "$1" | sed 's/^.*\(\)\(.*\)<\/key>.*/\2/g') + _panos_key=$panos_key + message='PAN-OS key is set.' + else + message="PAN-OS Key could not be set." + fi + else + status=$(echo "$1" | sed 's/^.*"\([a-z]*\)".*/\1/g') + message=$(echo "$1" | sed 's/^.*\(.*\)<\/result.*/\1/g') + fi return 0 } deployer() { - type=$1 # Types are cert, key, commit + type=$1 # Types are keygen, cert, key, commit _debug "**** Deploying $type *****" - - #Generate DEIM - delim="-----MultipartDelimiter$(date "+%s%N")" - nl="\015\012" - #Set Header - _H1="Content-Type: multipart/form-data; boundary=$delim" - if [ $type = 'cert' ]; then - content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_cfullchain")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cfullchain")" - fi - if [ $type = 'key' ]; then - #Add key - content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")" - fi - #Close multipart - content="$content${nl}--$delim--${nl}" - #Convert CRLF - content=$(printf %b "$content") - - if [ $type = 'cert' ]; then - panos_url="https://$_panos_host/api/?type=import&category=certificate&certificate-name=$_cdomain&format=pem&key=$_panos_key" - fi + panos_url="https://$_panos_host/api/" - if [ $type = 'key' ]; then - panos_url="https://$_panos_host/api/?type=import&category=private-key&certificate-name=$_cdomain&format=pem&passphrase=none&key=$_panos_key" + if [ $type = 'keygen' ]; then + _H1="Content-Type: application/x-www-form-urlencoded" + content="type=keygen&user=$_panos_user&password=$_panos_pass" + # content="$content${nl}--$delim${nl}Content-Disposition: form-data; type=\"keygen\"; user=\"$_panos_user\"; password=\"$_panos_pass\"${nl}Content-Type: application/octet-stream${nl}${nl}" fi - if [ $type = 'commit' ]; then - cmd=$(_url_encode "<$_panos_user>") - panos_url="https://$_panos_host/api/?type=commit&cmd=$cmd&key=$_panos_key" + + if [ $type = 'cert' ] || [ $type = 'key' ]; then + #Generate DEIM + delim="-----MultipartDelimiter$(date "+%s%N")" + nl="\015\012" + #Set Header + _H1="Content-Type: multipart/form-data; boundary=$delim" + + if [ $type = 'cert' ]; then + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"type\"\r\n\r\n\r\nimport" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"category\"\r\n\r\n\r\ncertificate" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"certificate-name\"\r\n\r\n\r\n$_cdomain" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"\r\n\r\n\r\n$_panos_key" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"format\"\r\n\r\n\r\npem" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_cfullchain")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cfullchain")" + fi + if [ $type = 'key' ]; then + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"type\"\r\n\r\n\r\nimport" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"category\"\r\n\r\n\r\nprivate-key" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"certificate-name\"\r\n\r\n\r\n$_cdomain" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"\r\n\r\n\r\n$_panos_key" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"format\"\r\n\r\n\r\npem" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"passphrase\"\r\n\r\n\r\nnone" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")" + fi + #Close multipart + content="$content${nl}--$delim--${nl}" + #Convert CRLF + content=$(printf %b "$content") fi - if [ $type = 'key' ] || [ $type = 'cert' ]; then - response=$(_post "$content" "$panos_url" "" "POST") - else - response=$(_get $panos_url) + if [ $type = 'commit' ]; then + _H1="Content-Type: application/x-www-form-urlencoded" + cmd=$(printf "%s" "<$_panos_user>" | _url_encode) + content="type=commit&key=$_panos_key&cmd=$cmd" fi - _debug panos_url $panos_url - _debug "RESPONSE $response" - parse_response "$response" - _debug "STATUS IS $status" - _debug "MESSAGE IS $message" + + response=$(_post "$content" "$panos_url" "" "POST") + parse_response "$response" $type # Saving response to variables response_status=$status - # Check for cert upload error and handle gracefully. - #DEBUG - _debug header "$_H1" - # _debug content "$content" _debug response_status "$response_status" if [ "$response_status" = "success" ]; then _debug "Successfully deployed $type" @@ -121,18 +135,8 @@ panos_deploy() { return 1 else _debug "Getting PANOS KEY" - panos_key_response=$(_get "https://$_panos_host/api/?type=keygen&user=$_panos_user&password=$_panos_pass") - _debug "PANOS KEY FULL RESPONSE $panos_key_response" - status=$(echo "$panos_key_response" | sed 's/^.*\(['\'']\)\([a-z]*\)'\''.*/\2/g') - _debug "STATUS IS $status" - if [ "$status" = "success" ]; then - panos_key=$(echo "$panos_key_response" | sed 's/^.*\(\)\(.*\)<\/key>.*/\2/g') - _panos_key=$panos_key - else - _err "PANOS Key could not be set. Deploy with --debug to troubleshoot" - return 1 - fi - if [ -z "$_panos_host" ] && [ -z "$_panos_key" ] && [ -z "$_panos_user" ]; then + deployer keygen + if [ -z "$_panos_key" ]; then _err "Missing host, apikey, user." return 1 else From 71bc993e3ddf72d497b16a2a9ee598bcc0f92847 Mon Sep 17 00:00:00 2001 From: Paul Nguyen Date: Tue, 11 Feb 2020 22:23:10 -0800 Subject: [PATCH 212/357] Fixed Shellchecks --- deploy/panos.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/deploy/panos.sh b/deploy/panos.sh index ca03706f..b2c3b1d9 100644 --- a/deploy/panos.sh +++ b/deploy/panos.sh @@ -14,7 +14,7 @@ # This function is to parse the XML parse_response() { type=$2 - if [ $type = 'keygen' ]; then + if [ $type = "keygen" ]; then status=$(echo "$1" | sed 's/^.*\(['\'']\)\([a-z]*\)'\''.*/\2/g') if [ "$status" = "success" ]; then panos_key=$(echo "$1" | sed 's/^.*\(\)\(.*\)<\/key>.*/\2/g') @@ -35,20 +35,20 @@ deployer() { _debug "**** Deploying $type *****" panos_url="https://$_panos_host/api/" - if [ $type = 'keygen' ]; then + if [ $type = "keygen" ]; then _H1="Content-Type: application/x-www-form-urlencoded" content="type=keygen&user=$_panos_user&password=$_panos_pass" # content="$content${nl}--$delim${nl}Content-Disposition: form-data; type=\"keygen\"; user=\"$_panos_user\"; password=\"$_panos_pass\"${nl}Content-Type: application/octet-stream${nl}${nl}" fi - if [ $type = 'cert' ] || [ $type = 'key' ]; then + if [ $type = "cert" ] || [ $type = "key" ]; then #Generate DEIM delim="-----MultipartDelimiter$(date "+%s%N")" nl="\015\012" #Set Header - _H1="Content-Type: multipart/form-data; boundary=$delim" + export _H1="Content-Type: multipart/form-data; boundary=$delim" - if [ $type = 'cert' ]; then + if [ $type = "cert" ]; then content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"type\"\r\n\r\n\r\nimport" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"category\"\r\n\r\n\r\ncertificate" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"certificate-name\"\r\n\r\n\r\n$_cdomain" @@ -56,7 +56,7 @@ deployer() { content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"format\"\r\n\r\n\r\npem" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_cfullchain")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cfullchain")" fi - if [ $type = 'key' ]; then + if [ $type = "key" ]; then content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"type\"\r\n\r\n\r\nimport" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"category\"\r\n\r\n\r\nprivate-key" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"certificate-name\"\r\n\r\n\r\n$_cdomain" @@ -71,14 +71,14 @@ deployer() { content=$(printf %b "$content") fi - if [ $type = 'commit' ]; then - _H1="Content-Type: application/x-www-form-urlencoded" + if [ $type = "commit" ]; then + export _H1="Content-Type: application/x-www-form-urlencoded" cmd=$(printf "%s" "<$_panos_user>" | _url_encode) content="type=commit&key=$_panos_key&cmd=$cmd" fi response=$(_post "$content" "$panos_url" "" "POST") - parse_response "$response" $type + parse_response "$response" "$type" # Saving response to variables response_status=$status #DEBUG From 5dcb4176769321555f953f44a046258dc1096294 Mon Sep 17 00:00:00 2001 From: Paul Nguyen Date: Tue, 11 Feb 2020 22:26:48 -0800 Subject: [PATCH 213/357] ShellCheck fixes --- deploy/panos.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/deploy/panos.sh b/deploy/panos.sh index b2c3b1d9..8e00fd6c 100644 --- a/deploy/panos.sh +++ b/deploy/panos.sh @@ -14,7 +14,7 @@ # This function is to parse the XML parse_response() { type=$2 - if [ $type = "keygen" ]; then + if [ "$type" = 'keygen' ]; then status=$(echo "$1" | sed 's/^.*\(['\'']\)\([a-z]*\)'\''.*/\2/g') if [ "$status" = "success" ]; then panos_key=$(echo "$1" | sed 's/^.*\(\)\(.*\)<\/key>.*/\2/g') @@ -35,20 +35,20 @@ deployer() { _debug "**** Deploying $type *****" panos_url="https://$_panos_host/api/" - if [ $type = "keygen" ]; then + if [ "$type" = 'keygen' ]; then _H1="Content-Type: application/x-www-form-urlencoded" content="type=keygen&user=$_panos_user&password=$_panos_pass" # content="$content${nl}--$delim${nl}Content-Disposition: form-data; type=\"keygen\"; user=\"$_panos_user\"; password=\"$_panos_pass\"${nl}Content-Type: application/octet-stream${nl}${nl}" fi - if [ $type = "cert" ] || [ $type = "key" ]; then + if [ "$type" = 'cert' ] || [ "$type" = 'key' ]; then #Generate DEIM delim="-----MultipartDelimiter$(date "+%s%N")" nl="\015\012" #Set Header export _H1="Content-Type: multipart/form-data; boundary=$delim" - if [ $type = "cert" ]; then + if [ "$type" = 'cert' ]; then content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"type\"\r\n\r\n\r\nimport" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"category\"\r\n\r\n\r\ncertificate" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"certificate-name\"\r\n\r\n\r\n$_cdomain" @@ -56,7 +56,7 @@ deployer() { content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"format\"\r\n\r\n\r\npem" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_cfullchain")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cfullchain")" fi - if [ $type = "key" ]; then + if [ "$type" = 'key' ]; then content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"type\"\r\n\r\n\r\nimport" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"category\"\r\n\r\n\r\nprivate-key" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"certificate-name\"\r\n\r\n\r\n$_cdomain" @@ -71,7 +71,7 @@ deployer() { content=$(printf %b "$content") fi - if [ $type = "commit" ]; then + if [ "$type" = 'commit' ]; then export _H1="Content-Type: application/x-www-form-urlencoded" cmd=$(printf "%s" "<$_panos_user>" | _url_encode) content="type=commit&key=$_panos_key&cmd=$cmd" From cbdb8bd9b96a8370051f952806fa24dc13d80f9b Mon Sep 17 00:00:00 2001 From: Paul Nguyen Date: Tue, 11 Feb 2020 22:34:55 -0800 Subject: [PATCH 214/357] Fixing gitdiff --- deploy/panos.sh | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/deploy/panos.sh b/deploy/panos.sh index 8e00fd6c..c199caf4 100644 --- a/deploy/panos.sh +++ b/deploy/panos.sh @@ -42,11 +42,11 @@ deployer() { fi if [ "$type" = 'cert' ] || [ "$type" = 'key' ]; then - #Generate DEIM - delim="-----MultipartDelimiter$(date "+%s%N")" - nl="\015\012" - #Set Header - export _H1="Content-Type: multipart/form-data; boundary=$delim" + #Generate DEIM + delim="-----MultipartDelimiter$(date "+%s%N")" + nl="\015\012" + #Set Header + export _H1="Content-Type: multipart/form-data; boundary=$delim" if [ "$type" = 'cert' ]; then content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"type\"\r\n\r\n\r\nimport" @@ -76,7 +76,6 @@ deployer() { cmd=$(printf "%s" "<$_panos_user>" | _url_encode) content="type=commit&key=$_panos_key&cmd=$cmd" fi - response=$(_post "$content" "$panos_url" "" "POST") parse_response "$response" "$type" # Saving response to variables @@ -145,4 +144,4 @@ panos_deploy() { deployer commit fi fi -} \ No newline at end of file +} From 2077a70d03a548dfbb5501a5b4388948b93db9f7 Mon Sep 17 00:00:00 2001 From: Paul Nguyen Date: Tue, 11 Feb 2020 22:44:51 -0800 Subject: [PATCH 215/357] Fixing gitdiff --- deploy/panos.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/deploy/panos.sh b/deploy/panos.sh index c199caf4..3806f14f 100644 --- a/deploy/panos.sh +++ b/deploy/panos.sh @@ -34,7 +34,6 @@ deployer() { type=$1 # Types are keygen, cert, key, commit _debug "**** Deploying $type *****" panos_url="https://$_panos_host/api/" - if [ "$type" = 'keygen' ]; then _H1="Content-Type: application/x-www-form-urlencoded" content="type=keygen&user=$_panos_user&password=$_panos_pass" @@ -47,7 +46,6 @@ deployer() { nl="\015\012" #Set Header export _H1="Content-Type: multipart/form-data; boundary=$delim" - if [ "$type" = 'cert' ]; then content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"type\"\r\n\r\n\r\nimport" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"category\"\r\n\r\n\r\ncertificate" From 930e16b64a25e60fbb6998d3f27749a257111939 Mon Sep 17 00:00:00 2001 From: Paul Nguyen Date: Tue, 11 Feb 2020 22:50:05 -0800 Subject: [PATCH 216/357] fix gitdiff --- deploy/panos.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/deploy/panos.sh b/deploy/panos.sh index 3806f14f..eaa19c89 100644 --- a/deploy/panos.sh +++ b/deploy/panos.sh @@ -19,7 +19,6 @@ parse_response() { if [ "$status" = "success" ]; then panos_key=$(echo "$1" | sed 's/^.*\(\)\(.*\)<\/key>.*/\2/g') _panos_key=$panos_key - message='PAN-OS key is set.' else message="PAN-OS Key could not be set." fi From 1fe3d80838d2aab564ad15aca7c2342b29e04f97 Mon Sep 17 00:00:00 2001 From: Paul Nguyen Date: Wed, 12 Feb 2020 14:57:31 -0800 Subject: [PATCH 217/357] Updated to use saveconf function and base64encode. --- deploy/panos.sh | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/deploy/panos.sh b/deploy/panos.sh index eaa19c89..627a59de 100644 --- a/deploy/panos.sh +++ b/deploy/panos.sh @@ -94,36 +94,31 @@ panos_deploy() { _cdomain="$1" _ckey="$2" _cfullchain="$5" - # PANOS HOST is required to make API calls to the PANOS/Panorama - if [ -z "$PANOS_HOST" ]; then - if [ -z "$_panos_host" ]; then - _err "PANOS_HOST not defined." - return 1 - fi - else - _debug "PANOS HOST is set. Save to domain conf." - _panos_host="$PANOS_HOST" - _savedomainconf _panos_host "$_panos_host" - fi - # Retrieve stored variables - _panos_user="$(_readaccountconf_mutable PANOS_USER)" - _panos_pass="$(_readaccountconf_mutable PANOS_PASS)" - # PANOS Credentials check - if [ -z "$PANOS_USER" ] || [ -z "$PANOS_PASS" ]; then - _debug "PANOS_USER, PANOS_PASS is not defined" - if [ -z "$_panos_user" ] && [ -z "$_panos_pass" ]; then - _err "No user and pass found in storage. If this is the first time deploying please set PANOS_USER and PANOS_PASS in environment variables." + + # PANOS ENV VAR check + if [ -z "$PANOS_USER" ] || [ -z "$PANOS_PASS" ] || [ -z "$PANOS_HOST" ]; then + _debug "No ENV variables found lets check for saved variables" + _getdeployconf PANOS_USER + _getdeployconf PANOS_PASS + _getdeployconf PANOS_HOST + _panos_user=$PANOS_USER + _panos_pass=$PANOS_PASS + _panos_host=$PANOS_HOST + if [ -z "$_panos_user" ] && [ -z "$_panos_pass" ] && [ -z "$_panos_host" ]; then + _err "No host, user and pass found.. If this is the first time deploying please set PANOS_HOST, PANOS_USER and PANOS_PASS in environment variables. Delete them after you have succesfully deployed certs." return 1 else - _debug "ok" + _debug "Using saved env variables." fi else - _debug "Saving environment variables" + _debug "Detected ENV variables to be saved to the deploy conf." # Encrypt and save user - _saveaccountconf_mutable PANOS_USER "$PANOS_USER" - _saveaccountconf_mutable PANOS_PASS "$PANOS_PASS" + _savedeployconf PANOS_USER "$PANOS_USER" 1 + _savedeployconf PANOS_PASS "$PANOS_PASS" 1 + _savedeployconf PANOS_HOST "$PANOS_HOST" 1 _panos_user="$PANOS_USER" _panos_pass="$PANOS_PASS" + _panos_host="$PANOS_HOST" fi _debug "Let's use username and pass to generate token." if [ -z "$_panos_user" ] || [ -z "$_panos_pass" ] || [ -z "$_panos_host" ]; then @@ -133,7 +128,7 @@ panos_deploy() { _debug "Getting PANOS KEY" deployer keygen if [ -z "$_panos_key" ]; then - _err "Missing host, apikey, user." + _err "Missing apikey." return 1 else deployer cert From c355b25bb1eea5fbf1b5d08185bc52032b60cabd Mon Sep 17 00:00:00 2001 From: Paul Nguyen Date: Wed, 12 Feb 2020 15:00:23 -0800 Subject: [PATCH 218/357] Fixed line formatting --- deploy/panos.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/deploy/panos.sh b/deploy/panos.sh index 627a59de..a550d877 100644 --- a/deploy/panos.sh +++ b/deploy/panos.sh @@ -94,7 +94,6 @@ panos_deploy() { _cdomain="$1" _ckey="$2" _cfullchain="$5" - # PANOS ENV VAR check if [ -z "$PANOS_USER" ] || [ -z "$PANOS_PASS" ] || [ -z "$PANOS_HOST" ]; then _debug "No ENV variables found lets check for saved variables" From 21450a08c27af39e3788526464c249a41c3db61f Mon Sep 17 00:00:00 2001 From: Paul Nguyen Date: Thu, 13 Feb 2020 18:01:27 -0800 Subject: [PATCH 219/357] Fixed 6 character requirement. --- deploy/panos.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/deploy/panos.sh b/deploy/panos.sh index a550d877..6316784a 100644 --- a/deploy/panos.sh +++ b/deploy/panos.sh @@ -30,6 +30,7 @@ parse_response() { } deployer() { + content="" type=$1 # Types are keygen, cert, key, commit _debug "**** Deploying $type *****" panos_url="https://$_panos_host/api/" @@ -59,7 +60,7 @@ deployer() { content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"certificate-name\"\r\n\r\n\r\n$_cdomain" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"\r\n\r\n\r\n$_panos_key" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"format\"\r\n\r\n\r\npem" - content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"passphrase\"\r\n\r\n\r\nnone" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"passphrase\"\r\n\r\n\r\n123456" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")" fi #Close multipart From 463df9e4ba25273cc9a9fe82d12c47ad412518af Mon Sep 17 00:00:00 2001 From: xpac1985 Date: Tue, 18 Feb 2020 16:26:15 +0100 Subject: [PATCH 220/357] Make socat debug output show version + features instead of help text --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index c9cd0d1c..3a01c13d 100755 --- a/acme.sh +++ b/acme.sh @@ -207,7 +207,7 @@ _dlg_versions() { echo "socat:" if _exists "socat"; then - socat -h 2>&1 + socat -V 2>&1 else _debug "socat doesn't exists." fi From f8662c9bc21329fc4f0481e50a27df81cb57c249 Mon Sep 17 00:00:00 2001 From: adrian5 Date: Thu, 20 Feb 2020 18:43:08 +0100 Subject: [PATCH 221/357] Fix phrasing in README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d1c793d4..de674cbf 100644 --- a/README.md +++ b/README.md @@ -257,7 +257,7 @@ acme.sh --issue --apache -d example.com -d www.example.com -d cp.example.com **This apache mode is only to issue the cert, it will not change your apache config files. You will need to configure your website config files to use the cert by yourself. -We don't want to mess your apache server, don't worry.** +We don't want to mess with your apache server, don't worry.** More examples: https://github.com/acmesh-official/acme.sh/wiki/How-to-issue-a-cert @@ -281,7 +281,7 @@ acme.sh --issue --nginx -d example.com -d www.example.com -d cp.example.com **This nginx mode is only to issue the cert, it will not change your nginx config files. You will need to configure your website config files to use the cert by yourself. -We don't want to mess your nginx server, don't worry.** +We don't want to mess with your nginx server, don't worry.** More examples: https://github.com/acmesh-official/acme.sh/wiki/How-to-issue-a-cert From e184a1b9e64f9985387cc402449f459a2b1e6649 Mon Sep 17 00:00:00 2001 From: xpac1985 Date: Thu, 20 Feb 2020 23:28:55 +0100 Subject: [PATCH 222/357] haproxy deploy script now compatible with OpenSSL v1.1+ haproxy deploy script now compatible with OpenSSL v1.1+ The OpenSSL OCSP request for haproxy deployment breaks from OpenSSL v1.1.0 on. The format of the `-header` option has been changed and does now contain a `=` instead of a whitespace. Other projects have hit the same issue: https://github.com/nghttp2/nghttp2/issues/742 This commit determines the OpenSSL/LibreSSL version and then adjusts the request accordingly. Also removed the duplicate command line and added some more debug output. --- deploy/haproxy.sh | 52 +++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/deploy/haproxy.sh b/deploy/haproxy.sh index 836c5182..3cd2a80a 100644 --- a/deploy/haproxy.sh +++ b/deploy/haproxy.sh @@ -208,33 +208,37 @@ haproxy_deploy() { _issuerdn=$(openssl x509 -in "${_issuer}" -issuer -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10) _debug _issuerdn "${_issuerdn}" _info "Requesting OCSP response" - # Request the OCSP response from the issuer and store it + # If the issuer is a CA cert then our command line has "-CAfile" added if [ "${_subjectdn}" = "${_issuerdn}" ]; then - # If the issuer is a CA cert then our command line has "-CAfile" added - openssl ocsp \ - -issuer "${_issuer}" \ - -cert "${_pem}" \ - -url "${_ocsp_url}" \ - -header Host "${_ocsp_host}" \ - -respout "${_ocsp}" \ - -verify_other "${_issuer}" \ - -no_nonce \ - -CAfile "${_issuer}" \ - | grep -q "${_pem}: good" - _ret=$? + _cafile_argument="-CAfile \"${_issuer}\"" + else + _cafile_argument="" + fi + _debug _cafile_argument "${_cafile_argument}" + # if OpenSSL/LibreSSL is v1.1 or above, the format for the -header option has changed + _openssl_version=$(openssl version | cut -d' ' -f2) + _debug _openssl_version "${_openssl_version}" + _openssl_major=$(echo "${_openssl_version}" | cut -d '.' -f1) + _openssl_minor=$(echo "${_openssl_version}" | cut -d '.' -f2) + if [ "${_openssl_major}" -eq "1" ] && [ "${_openssl_minor}" -ge "1" ] || [ "${_openssl_major}" -ge "2" ]; then + _header_sep="=" else - # Issuer is not a root CA so no "-CAfile" option - openssl ocsp \ - -issuer "${_issuer}" \ - -cert "${_pem}" \ - -url "${_ocsp_url}" \ - -header Host "${_ocsp_host}" \ - -respout "${_ocsp}" \ - -verify_other "${_issuer}" \ - -no_nonce \ - | grep -q "${_pem}: good" - _ret=$? + _header_sep=" " fi + # Request the OCSP response from the issuer and store it + _openssl_ocsp_cmd="openssl ocsp \ + -issuer \"${_issuer}\" \ + -cert \"${_pem}\" \ + -url \"${_ocsp_url}\" \ + -header Host${_header_sep}\"${_ocsp_host}\" \ + -respout \"${_ocsp}\" \ + -verify_other \"${_issuer}\" \ + -no_nonce \ + ${_cafile_argument} \ + | grep -q \"${_pem}: good\"" + _debug _openssl_ocsp_cmd "${_openssl_ocsp_cmd}" + eval "${_openssl_ocsp_cmd}" + _ret=$? else # Non fatal: No issuer file was present so no OCSP stapling file created _err "OCSP stapling in use but no .issuer file was present" From 3d9608faa086890321ba8d9d630c5b659f89ed46 Mon Sep 17 00:00:00 2001 From: dkerr64 Date: Sat, 22 Feb 2020 20:09:24 -0500 Subject: [PATCH 223/357] Move -T parameter into default ssh command variable --- deploy/ssh.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index 9cb0af9e..783e6f7b 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -12,7 +12,7 @@ # Only a username is required. All others are optional. # # The following examples are for QNAP NAS running QTS 4.2 -# export DEPLOY_SSH_CMD="" # defaults to ssh +# export DEPLOY_SSH_CMD="" # defaults to "ssh -T" # export DEPLOY_SSH_USER="admin" # required # export DEPLOY_SSH_SERVER="qnap" # defaults to domain name # export DEPLOY_SSH_KEYFILE="/etc/stunnel/stunnel.pem" @@ -71,7 +71,7 @@ ssh_deploy() { Le_Deploy_ssh_cmd="$DEPLOY_SSH_CMD" _savedomainconf Le_Deploy_ssh_cmd "$Le_Deploy_ssh_cmd" elif [ -z "$Le_Deploy_ssh_cmd" ]; then - Le_Deploy_ssh_cmd="ssh" + Le_Deploy_ssh_cmd="ssh -T" fi # BACKUP is optional. If not provided then default to yes @@ -194,7 +194,7 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d _info "Submitting sequence of commands to remote server by ssh" # quotations in bash cmd below intended. Squash travis spellcheck error # shellcheck disable=SC2029 - $Le_Deploy_ssh_cmd -T "$Le_Deploy_ssh_user@$Le_Deploy_ssh_server" sh -c "'$_cmdstr'" + $Le_Deploy_ssh_cmd "$Le_Deploy_ssh_user@$Le_Deploy_ssh_server" sh -c "'$_cmdstr'" _ret="$?" if [ "$_ret" != "0" ]; then From 04771e5a4ae243cdc757b7d3159cef92fce40605 Mon Sep 17 00:00:00 2001 From: dkerr64 Date: Sat, 22 Feb 2020 20:16:36 -0500 Subject: [PATCH 224/357] Move call to remote system into separate function --- deploy/ssh.sh | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index 783e6f7b..8c83f0b3 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -31,6 +31,7 @@ ssh_deploy() { _ccert="$3" _cca="$4" _cfullchain="$5" + _err_code=0 _cmdstr="" _homedir='~' _backupprefix="$_homedir/.acme_ssh_deploy/$_cdomain-backup" @@ -190,16 +191,25 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d _info "Backup directories erased after 180 days." fi - _secure_debug "Remote commands to execute: " "$_cmdstr" - _info "Submitting sequence of commands to remote server by ssh" + if ! _ssh_remote_cmd "$_cmdstr"; then + return $_err_code + fi + + return 0 +} + +#cmd +_ssh_remote_cmd() { + _secure_debug "Remote commands to execute: $_cmd" + _info "Submitting sequence of commands to remote server by $Le_Deploy_ssh_cmd" # quotations in bash cmd below intended. Squash travis spellcheck error # shellcheck disable=SC2029 - $Le_Deploy_ssh_cmd "$Le_Deploy_ssh_user@$Le_Deploy_ssh_server" sh -c "'$_cmdstr'" - _ret="$?" + $Le_Deploy_ssh_cmd "$Le_Deploy_ssh_user@$Le_Deploy_ssh_server" sh -c "'$_cmd'" + _err_code="$?" - if [ "$_ret" != "0" ]; then - _err "Error code $_ret returned from $Le_Deploy_ssh_cmd" + if [ "$_err_code" != "0" ]; then + _err "Error code $_err_code returned from $Le_Deploy_ssh_cmd" fi - return $_ret + return $_err_code } From 6420d1239fda00fb5d40299bfbf1b22c4af4762f Mon Sep 17 00:00:00 2001 From: dkerr64 Date: Sat, 22 Feb 2020 20:31:52 -0500 Subject: [PATCH 225/357] Move call to remote system into separate function --- deploy/ssh.sh | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index 783e6f7b..00d9d21d 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -31,6 +31,7 @@ ssh_deploy() { _ccert="$3" _cca="$4" _cfullchain="$5" + _err_code=0 _cmdstr="" _homedir='~' _backupprefix="$_homedir/.acme_ssh_deploy/$_cdomain-backup" @@ -190,16 +191,26 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d _info "Backup directories erased after 180 days." fi - _secure_debug "Remote commands to execute: " "$_cmdstr" - _info "Submitting sequence of commands to remote server by ssh" + if ! _ssh_remote_cmd "$_cmdstr"; then + return $_err_code + fi + + return 0 +} + +#cmd +_ssh_remote_cmd() { + _cmd="$1" + _secure_debug "Remote commands to execute: $_cmd" + _info "Submitting sequence of commands to remote server by $Le_Deploy_ssh_cmd" # quotations in bash cmd below intended. Squash travis spellcheck error # shellcheck disable=SC2029 - $Le_Deploy_ssh_cmd "$Le_Deploy_ssh_user@$Le_Deploy_ssh_server" sh -c "'$_cmdstr'" - _ret="$?" + $Le_Deploy_ssh_cmd "$Le_Deploy_ssh_user@$Le_Deploy_ssh_server" sh -c "'$_cmd'" + _err_code="$?" - if [ "$_ret" != "0" ]; then - _err "Error code $_ret returned from $Le_Deploy_ssh_cmd" + if [ "$_err_code" != "0" ]; then + _err "Error code $_err_code returned from $Le_Deploy_ssh_cmd" fi - return $_ret + return $_err_code } From 283b04df739dff70ed22ee20ffac6a1c576db842 Mon Sep 17 00:00:00 2001 From: dkerr64 Date: Sat, 22 Feb 2020 20:43:28 -0500 Subject: [PATCH 226/357] Move cleanup of backup directory to first step in the function. --- deploy/ssh.sh | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index 00d9d21d..39a0a218 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -85,6 +85,19 @@ ssh_deploy() { _info "Deploy certificates to remote server $Le_Deploy_ssh_user@$Le_Deploy_ssh_server" + if [ "$Le_Deploy_ssh_backup" = "yes" ]; then + # run cleanup on the backup directory, erase all older + # than 180 days (15552000 seconds). + _cmdstr="{ now=\"\$(date -u +%s)\"; for fn in $_backupprefix*; \ +do if [ -d \"\$fn\" ] && [ \"\$(expr \$now - \$(date -ur \$fn +%s) )\" -ge \"15552000\" ]; \ +then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; done; }; $_cmdstr" + # Alternate version of above... _cmdstr="find $_backupprefix* -type d -mtime +180 2>/dev/null | xargs rm -rf; $_cmdstr" + # Create our backup directory for overwritten cert files. + _cmdstr="mkdir -p $_backupdir; $_cmdstr" + _info "Backup of old certificate files will be placed in remote directory $_backupdir" + _info "Backup directories erased after 180 days." + fi + # KEYFILE is optional. # If provided then private key will be copied to provided filename. if [ -n "$DEPLOY_SSH_KEYFILE" ]; then @@ -178,17 +191,6 @@ ssh_deploy() { if [ -z "$_cmdstr" ]; then _err "No remote commands to excute. Failed to deploy certificates to remote server" return 1 - elif [ "$Le_Deploy_ssh_backup" = "yes" ]; then - # run cleanup on the backup directory, erase all older - # than 180 days (15552000 seconds). - _cmdstr="{ now=\"\$(date -u +%s)\"; for fn in $_backupprefix*; \ -do if [ -d \"\$fn\" ] && [ \"\$(expr \$now - \$(date -ur \$fn +%s) )\" -ge \"15552000\" ]; \ -then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; done; }; $_cmdstr" - # Alternate version of above... _cmdstr="find $_backupprefix* -type d -mtime +180 2>/dev/null | xargs rm -rf; $_cmdstr" - # Create our backup directory for overwritten cert files. - _cmdstr="mkdir -p $_backupdir; $_cmdstr" - _info "Backup of old certificate files will be placed in remote directory $_backupdir" - _info "Backup directories erased after 180 days." fi if ! _ssh_remote_cmd "$_cmdstr"; then From cc820e97c6e7cea1d5de0165bd5b7b5d84249843 Mon Sep 17 00:00:00 2001 From: dkerr64 Date: Sat, 22 Feb 2020 21:10:42 -0500 Subject: [PATCH 227/357] Add support for DEPLOY_SSH_BATCH_MODE with default of yes. Before this update all remote commands were bunched together and sent to the remote host in a single SSH command. This could result in a very long sequence of commands that might be rejected by a remote host (example is VMware ESXi that uses busybox sh). With this update you can set DEPLOY_SSH_BATCH_MODE="no" and each remote command is sent as a separate SSH call so now we do not have big long sequence of commands. Defaults to same behaviour as before this update. --- deploy/ssh.sh | 63 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index 39a0a218..92aa43d9 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -21,6 +21,7 @@ # export DEPLOY_SSH_FULLCHAIN="" # export DEPLOY_SSH_REMOTE_CMD="/etc/init.d/stunnel.sh restart" # export DEPLOY_SSH_BACKUP="" # yes or no, default to yes +# export DEPLOY_SSH_BATCH_MODE="yes" # yes or no, default to yes # ######## Public functions ##################### @@ -83,7 +84,20 @@ ssh_deploy() { fi _savedomainconf Le_Deploy_ssh_backup "$Le_Deploy_ssh_backup" + # BATCH_MODE is optional. If not provided then default to yes + if [ "$DEPLOY_SSH_BATCH_MODE" = "no" ]; then + Le_Deploy_ssh_batch_mode="no" + elif [ -z "$Le_Deploy_ssh_batch_mode" ]; then + Le_Deploy_ssh_batch_mode="yes" + fi + _savedomainconf Le_Deploy_ssh_batch_mode "$Le_Deploy_ssh_batch_mode" + _info "Deploy certificates to remote server $Le_Deploy_ssh_user@$Le_Deploy_ssh_server" + if [ "$Le_Deploy_ssh_batch_mode" = "yes" ]; then + _info "Using BATCH MODE... Multiple commands sent in single call to remote host" + else + _info "Commands sent individually in multiple calls to remote host" + fi if [ "$Le_Deploy_ssh_backup" = "yes" ]; then # run cleanup on the backup directory, erase all older @@ -96,6 +110,12 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d _cmdstr="mkdir -p $_backupdir; $_cmdstr" _info "Backup of old certificate files will be placed in remote directory $_backupdir" _info "Backup directories erased after 180 days." + if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if ! _ssh_remote_cmd "$_cmdstr"; then + return $_err_code + fi + _cmdstr="" + fi fi # KEYFILE is optional. @@ -112,6 +132,12 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d # copy new certificate into file. _cmdstr="$_cmdstr echo \"$(cat "$_ckey")\" > $Le_Deploy_ssh_keyfile;" _info "will copy private key to remote file $Le_Deploy_ssh_keyfile" + if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if ! _ssh_remote_cmd "$_cmdstr"; then + return $_err_code + fi + _cmdstr="" + fi fi # CERTFILE is optional. @@ -132,6 +158,12 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d # copy new certificate into file. _cmdstr="$_cmdstr echo \"$(cat "$_ccert")\" $_pipe $Le_Deploy_ssh_certfile;" _info "will copy certificate to remote file $Le_Deploy_ssh_certfile" + if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if ! _ssh_remote_cmd "$_cmdstr"; then + return $_err_code + fi + _cmdstr="" + fi fi # CAFILE is optional. @@ -153,6 +185,12 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d # copy new certificate into file. _cmdstr="$_cmdstr echo \"$(cat "$_cca")\" $_pipe $Le_Deploy_ssh_cafile;" _info "will copy CA file to remote file $Le_Deploy_ssh_cafile" + if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if ! _ssh_remote_cmd "$_cmdstr"; then + return $_err_code + fi + _cmdstr="" + fi fi # FULLCHAIN is optional. @@ -175,6 +213,12 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d # copy new certificate into file. _cmdstr="$_cmdstr echo \"$(cat "$_cfullchain")\" $_pipe $Le_Deploy_ssh_fullchain;" _info "will copy fullchain to remote file $Le_Deploy_ssh_fullchain" + if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if ! _ssh_remote_cmd "$_cmdstr"; then + return $_err_code + fi + _cmdstr="" + fi fi # REMOTE_CMD is optional. @@ -186,17 +230,20 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d if [ -n "$Le_Deploy_ssh_remote_cmd" ]; then _cmdstr="$_cmdstr $Le_Deploy_ssh_remote_cmd;" _info "Will execute remote command $Le_Deploy_ssh_remote_cmd" + if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if ! _ssh_remote_cmd "$_cmdstr"; then + return $_err_code + fi + _cmdstr="" + fi fi - if [ -z "$_cmdstr" ]; then - _err "No remote commands to excute. Failed to deploy certificates to remote server" - return 1 - fi - - if ! _ssh_remote_cmd "$_cmdstr"; then - return $_err_code + # if running as batch mode then all commands sent in a single SSH call now... + if [ -n "$_cmdstr" ]; then + if ! _ssh_remote_cmd "$_cmdstr"; then + return $_err_code + fi fi - return 0 } From 806b746fc0522bed79a1b51f3c0137a0fa721dc5 Mon Sep 17 00:00:00 2001 From: dkerr64 Date: Sat, 22 Feb 2020 21:23:59 -0500 Subject: [PATCH 228/357] Fix bug where backup and batch_mode yes/no values could not be changed. Once set to "no" then they could never be set back to "yes" --- deploy/ssh.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index 92aa43d9..113ae23e 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -79,7 +79,7 @@ ssh_deploy() { # BACKUP is optional. If not provided then default to yes if [ "$DEPLOY_SSH_BACKUP" = "no" ]; then Le_Deploy_ssh_backup="no" - elif [ -z "$Le_Deploy_ssh_backup" ]; then + elif [ -z "$Le_Deploy_ssh_backup" ] || [ "$DEPLOY_SSH_BACKUP" = "yes" ]; then Le_Deploy_ssh_backup="yes" fi _savedomainconf Le_Deploy_ssh_backup "$Le_Deploy_ssh_backup" @@ -87,7 +87,7 @@ ssh_deploy() { # BATCH_MODE is optional. If not provided then default to yes if [ "$DEPLOY_SSH_BATCH_MODE" = "no" ]; then Le_Deploy_ssh_batch_mode="no" - elif [ -z "$Le_Deploy_ssh_batch_mode" ]; then + elif [ -z "$Le_Deploy_ssh_batch_mode" ] || [ "$DEPLOY_SSH_BATCH_MODE" = "yes" ]; then Le_Deploy_ssh_batch_mode="yes" fi _savedomainconf Le_Deploy_ssh_batch_mode "$Le_Deploy_ssh_batch_mode" From 46ee74ed1687bcc5dbb7732bf7483e6c793ec253 Mon Sep 17 00:00:00 2001 From: dkerr64 Date: Sat, 22 Feb 2020 22:05:06 -0500 Subject: [PATCH 229/357] Remove variable from info/error printout that could potentially expose login credentials. --- deploy/ssh.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index 113ae23e..b68dad7e 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -251,14 +251,14 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d _ssh_remote_cmd() { _cmd="$1" _secure_debug "Remote commands to execute: $_cmd" - _info "Submitting sequence of commands to remote server by $Le_Deploy_ssh_cmd" + _info "Submitting sequence of commands to remote server by ssh" # quotations in bash cmd below intended. Squash travis spellcheck error # shellcheck disable=SC2029 $Le_Deploy_ssh_cmd "$Le_Deploy_ssh_user@$Le_Deploy_ssh_server" sh -c "'$_cmd'" _err_code="$?" if [ "$_err_code" != "0" ]; then - _err "Error code $_err_code returned from $Le_Deploy_ssh_cmd" + _err "Error code $_err_code returned from ssh" fi return $_err_code From f73a49440790018aacff9e1d540c937f481cfc20 Mon Sep 17 00:00:00 2001 From: dkerr64 Date: Sat, 22 Feb 2020 22:09:28 -0500 Subject: [PATCH 230/357] Remove spaces on blank line to fix travis error --- deploy/ssh.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index b68dad7e..b3e040b3 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -91,7 +91,7 @@ ssh_deploy() { Le_Deploy_ssh_batch_mode="yes" fi _savedomainconf Le_Deploy_ssh_batch_mode "$Le_Deploy_ssh_batch_mode" - + _info "Deploy certificates to remote server $Le_Deploy_ssh_user@$Le_Deploy_ssh_server" if [ "$Le_Deploy_ssh_batch_mode" = "yes" ]; then _info "Using BATCH MODE... Multiple commands sent in single call to remote host" From b64f0ba83f2a55c2a619f838d3f35ec512901fc8 Mon Sep 17 00:00:00 2001 From: Stephane Moser Date: Mon, 24 Feb 2020 23:14:40 +0000 Subject: [PATCH 231/357] Update usage of AWS_DNS_SLOWRATE --- dnsapi/dns_aws.sh | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_aws.sh b/dnsapi/dns_aws.sh index 4fab09e2..a3d0082e 100755 --- a/dnsapi/dns_aws.sh +++ b/dnsapi/dns_aws.sh @@ -20,10 +20,10 @@ AWS_WIKI="https://github.com/Neilpang/acme.sh/wiki/How-to-use-Amazon-Route53-API dns_aws_add() { fulldomain=$1 txtvalue=$2 - slowrateslepp=$AWS_DNS_SLOWRATE 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_DNS_SLOWRATE="${AWS_DNS_SLOWRATE:-$(_readaccountconf_mutable AWS_DNS_SLOWRATE)}" if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then _use_container_role || _use_instance_role @@ -41,6 +41,7 @@ dns_aws_add() { if [ -z "$_using_role" ]; then _saveaccountconf_mutable AWS_ACCESS_KEY_ID "$AWS_ACCESS_KEY_ID" _saveaccountconf_mutable AWS_SECRET_ACCESS_KEY "$AWS_SECRET_ACCESS_KEY" + _saveaccountconf_mutable AWS_DNS_SLOWRATE "$AWS_DNS_SLOWRATE" fi _debug "First detect the root zone" @@ -78,9 +79,9 @@ dns_aws_add() { if aws_rest POST "2013-04-01$_domain_id/rrset/" "" "$_aws_tmpl_xml" && _contains "$response" "ChangeResourceRecordSetsResponse"; then _info "TXT record updated successfully." - if [ -n "$slowrateslepp" ]; then - _info "Slow rate activated: sleeping for $slowrateslepp seconds" - _sleep "$slowrateslepp" + if [ -n "$AWS_DNS_SLOWRATE" ]; then + _info "Slow rate activated: sleeping for $AWS_DNS_SLOWRATE seconds" + _sleep "$AWS_DNS_SLOWRATE" else _sleep 1 fi @@ -95,10 +96,10 @@ dns_aws_add() { dns_aws_rm() { fulldomain=$1 txtvalue=$2 - slowrateslepp=$AWS_DNS_SLOWRATE 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_DNS_SLOWRATE="${AWS_DNS_SLOWRATE:-$(_readaccountconf_mutable AWS_DNS_SLOWRATE)}" if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then _use_container_role || _use_instance_role @@ -133,9 +134,9 @@ dns_aws_rm() { if aws_rest POST "2013-04-01$_domain_id/rrset/" "" "$_aws_tmpl_xml" && _contains "$response" "ChangeResourceRecordSetsResponse"; then _info "TXT record deleted successfully." - if [ -n "$slowrateslepp" ]; then - _info "Slow rate activated: sleeping for $slowrateslepp seconds" - _sleep "$slowrateslepp" + if [ -n "$AWS_DNS_SLOWRATE" ]; then + _info "Slow rate activated: sleeping for $AWS_DNS_SLOWRATE seconds" + _sleep "$AWS_DNS_SLOWRATE" else _sleep 1 fi From 22f9a3b467095635b4ab755f6229888ff563f92b Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 25 Feb 2020 12:33:50 +0100 Subject: [PATCH 232/357] Fix error on docker deploy command with spaces. This adds quotes to the last eval in _getdeployconf which is reponsible for loading and exporting saved environment variables back into the acme.sh process. This caused some errors if used with the docker deploy-hook and the example nginx "service nginx force-reload" command as it contains spaces. --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 3a01c13d..283b0a39 100755 --- a/acme.sh +++ b/acme.sh @@ -2166,7 +2166,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 8ba573d1967e13dcdc03631308f5dbdd3acf565c Mon Sep 17 00:00:00 2001 From: dkerr64 Date: Tue, 3 Mar 2020 13:40:33 -0500 Subject: [PATCH 233/357] Change variable name to MULTI_CALL so default can be "no" --- deploy/ssh.sh | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index b3e040b3..7eed8a34 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -21,7 +21,7 @@ # export DEPLOY_SSH_FULLCHAIN="" # export DEPLOY_SSH_REMOTE_CMD="/etc/init.d/stunnel.sh restart" # export DEPLOY_SSH_BACKUP="" # yes or no, default to yes -# export DEPLOY_SSH_BATCH_MODE="yes" # yes or no, default to yes +# export DEPLOY_SSH_MULTI_CALL="" # yes or no, default to no # ######## Public functions ##################### @@ -84,19 +84,19 @@ ssh_deploy() { fi _savedomainconf Le_Deploy_ssh_backup "$Le_Deploy_ssh_backup" - # BATCH_MODE is optional. If not provided then default to yes - if [ "$DEPLOY_SSH_BATCH_MODE" = "no" ]; then - Le_Deploy_ssh_batch_mode="no" - elif [ -z "$Le_Deploy_ssh_batch_mode" ] || [ "$DEPLOY_SSH_BATCH_MODE" = "yes" ]; then - Le_Deploy_ssh_batch_mode="yes" + # MULTI_CALL is optional. If not provided then default to no + if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then + Le_Deploy_ssh_multi_call="yes" + elif [ -z "$Le_Deploy_ssh_multi_call" ] || [ "$DEPLOY_SSH_MULTI_CALL" = "no" ]; then + Le_Deploy_ssh_multi_call="no" fi - _savedomainconf Le_Deploy_ssh_batch_mode "$Le_Deploy_ssh_batch_mode" + _savedomainconf Le_Deploy_ssh_multi_call "$Le_Deploy_ssh_multi_call" _info "Deploy certificates to remote server $Le_Deploy_ssh_user@$Le_Deploy_ssh_server" - if [ "$Le_Deploy_ssh_batch_mode" = "yes" ]; then - _info "Using BATCH MODE... Multiple commands sent in single call to remote host" + if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then + _info "Using MULTI_CALL mode... Required commands sent in multiple calls to remote host" else - _info "Commands sent individually in multiple calls to remote host" + _info "Required commands batched and sent in single call to remote host" fi if [ "$Le_Deploy_ssh_backup" = "yes" ]; then @@ -110,7 +110,7 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d _cmdstr="mkdir -p $_backupdir; $_cmdstr" _info "Backup of old certificate files will be placed in remote directory $_backupdir" _info "Backup directories erased after 180 days." - if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then if ! _ssh_remote_cmd "$_cmdstr"; then return $_err_code fi @@ -132,7 +132,7 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d # copy new certificate into file. _cmdstr="$_cmdstr echo \"$(cat "$_ckey")\" > $Le_Deploy_ssh_keyfile;" _info "will copy private key to remote file $Le_Deploy_ssh_keyfile" - if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then if ! _ssh_remote_cmd "$_cmdstr"; then return $_err_code fi @@ -158,7 +158,7 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d # copy new certificate into file. _cmdstr="$_cmdstr echo \"$(cat "$_ccert")\" $_pipe $Le_Deploy_ssh_certfile;" _info "will copy certificate to remote file $Le_Deploy_ssh_certfile" - if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then if ! _ssh_remote_cmd "$_cmdstr"; then return $_err_code fi @@ -185,7 +185,7 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d # copy new certificate into file. _cmdstr="$_cmdstr echo \"$(cat "$_cca")\" $_pipe $Le_Deploy_ssh_cafile;" _info "will copy CA file to remote file $Le_Deploy_ssh_cafile" - if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then if ! _ssh_remote_cmd "$_cmdstr"; then return $_err_code fi @@ -213,7 +213,7 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d # copy new certificate into file. _cmdstr="$_cmdstr echo \"$(cat "$_cfullchain")\" $_pipe $Le_Deploy_ssh_fullchain;" _info "will copy fullchain to remote file $Le_Deploy_ssh_fullchain" - if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then if ! _ssh_remote_cmd "$_cmdstr"; then return $_err_code fi @@ -230,7 +230,7 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d if [ -n "$Le_Deploy_ssh_remote_cmd" ]; then _cmdstr="$_cmdstr $Le_Deploy_ssh_remote_cmd;" _info "Will execute remote command $Le_Deploy_ssh_remote_cmd" - if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then if ! _ssh_remote_cmd "$_cmdstr"; then return $_err_code fi @@ -238,7 +238,7 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d fi fi - # if running as batch mode then all commands sent in a single SSH call now... + # if commands not all sent in multiple calls then all commands sent in a single SSH call now... if [ -n "$_cmdstr" ]; then if ! _ssh_remote_cmd "$_cmdstr"; then return $_err_code From 72e1a1b2e9973dc65dd74514e75f30687248d781 Mon Sep 17 00:00:00 2001 From: Ian Wienand Date: Wed, 4 Mar 2020 09:12:28 +1100 Subject: [PATCH 234/357] Update account.json on account update When running --updateaccount, the ca//account.json file isn't updated with the new response showing the updated account details. This can be a bit confusing if you add an email to the account but then you're not sure if it actually applied looking at this file. Write out the new response on successful account updates. --- acme.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/acme.sh b/acme.sh index 283b0a39..1f4d3687 100755 --- a/acme.sh +++ b/acme.sh @@ -3518,6 +3518,7 @@ updateaccount() { _send_signed_request "$_accUri" "$updjson" if [ "$code" = '200' ]; then + echo "$response" >"$ACCOUNT_JSON_PATH" _info "account update success for $_accUri." else _info "Error. The account was not updated." From 69b11575e38cbafb84686831f81e151affabca5b Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 4 Mar 2020 09:51:16 +0800 Subject: [PATCH 235/357] add clearlinux fix https://github.com/acmesh-official/acme.sh/issues/2768 --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index de674cbf..249dc85f 100644 --- a/README.md +++ b/README.md @@ -52,11 +52,11 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa) |4|[![](https://acmesh-official.github.io/acmetest/status/windows-cygwin.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Windows (cygwin with curl, openssl and crontab included) |5|[![](https://acmesh-official.github.io/acmetest/status/freebsd.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|FreeBSD |6|[![](https://acmesh-official.github.io/acmetest/status/pfsense.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|pfsense -|7|[![](https://acmesh-official.github.io/acmetest/status/opensuse-latest.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|openSUSE +|7|[![](https://acmesh-official.github.io/acmetest/status/opensuse-leap.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|openSUSE |8|[![](https://acmesh-official.github.io/acmetest/status/alpine-latest.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Alpine Linux (with curl) -|9|[![](https://acmesh-official.github.io/acmetest/status/base-archlinux.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Archlinux +|9|[![](https://acmesh-official.github.io/acmetest/status/archlinux-latest.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Archlinux |10|[![](https://acmesh-official.github.io/acmetest/status/fedora-latest.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|fedora -|11|[![](https://acmesh-official.github.io/acmetest/status/kalilinux-kali-linux-docker.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Kali Linux +|11|[![](https://acmesh-official.github.io/acmetest/status/kalilinux-kali.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Kali Linux |12|[![](https://acmesh-official.github.io/acmetest/status/oraclelinux-latest.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Oracle Linux |13|[![](https://acmesh-official.github.io/acmetest/status/proxmox.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Proxmox https://pve.proxmox.com/wiki/HTTPSCertificateConfiguration#Let.27s_Encrypt_using_acme.sh |14|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111 @@ -66,6 +66,7 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa) |18|[![](https://acmesh-official.github.io/acmetest/status/solaris.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|SunOS/Solaris |19|[![](https://acmesh-official.github.io/acmetest/status/gentoo-stage3-amd64.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Gentoo Linux |20|[![Build Status](https://travis-ci.org/acmesh-official/acme.sh.svg?branch=master)](https://travis-ci.org/acmesh-official/acme.sh)|Mac OSX +|21|[![](https://acmesh-official.github.io/acmetest/status/clearlinux-latest.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|ClearLinux For all build statuses, check our [weekly build project](https://github.com/acmesh-official/acmetest): From f84a87f2a2d3697280b22e49b55f470af368d04f Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 7 Mar 2020 18:26:22 +0800 Subject: [PATCH 236/357] remove DEFAULT_DNS_SLEEP. fix https://github.com/acmesh-official/acme.sh/issues/2773 --- acme.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 283b0a39..eb5c78b2 100755 --- a/acme.sh +++ b/acme.sh @@ -48,7 +48,6 @@ LOCAL_ANY_ADDRESS="0.0.0.0" DEFAULT_RENEW=60 -DEFAULT_DNS_SLEEP=120 NO_VALUE="no" @@ -6223,7 +6222,7 @@ Parameters: --stateless Use stateless mode, see: $_STATELESS_WIKI --apache Use apache mode. --dns [dns_cf|dns_dp|dns_cx|/path/to/api/file] Use dns mode or dns api. - --dnssleep [$DEFAULT_DNS_SLEEP] The time in seconds to wait for all the txt records to take effect in dns api mode. Default $DEFAULT_DNS_SLEEP seconds. + --dnssleep 300 The time in seconds to wait for all the txt records to take effect in dns api mode. It's not necessary to use this by default, $PROJECT_NAME polls dns status automatically. --keylength, -k [2048] Specifies the domain key length: 2048, 3072, 4096, 8192 or ec-256, ec-384, ec-521. --accountkeylength, -ak [2048] Specifies the account key length: 2048, 3072, 4096 From f21ef0d2e9ee0a6cbb020dc1cf3edbe0f615c1c6 Mon Sep 17 00:00:00 2001 From: ThiloGa Date: Sat, 7 Mar 2020 14:55:09 +0100 Subject: [PATCH 237/357] add support for namemaster.de --- dnsapi/dns_nm.sh | 92 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 dnsapi/dns_nm.sh diff --git a/dnsapi/dns_nm.sh b/dnsapi/dns_nm.sh new file mode 100644 index 00000000..53c0c768 --- /dev/null +++ b/dnsapi/dns_nm.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env sh + +######################################################################## +# https://namemaster.de hook script for acme.sh +# +# Environment variables: +# +# - $NM_user (your namemaster.de API username) +# - $NM_md5 (your namemaster.de API password_as_md5hash) +# +# Author: Thilo Gass +# Git repo: https://github.com/ThiloGa/acme.sh + +#-- dns_nm_add() - Add TXT record -------------------------------------- +# Usage: dns_nm_add _acme-challenge.subdomain.domain.com "XyZ123..." + +dns_nm_add() { + fulldomain=$1 + txt_value=$2 + _info "Using DNS-01 namemaster hook" + + NM_user="${NM_user:-$(_readaccountconf_mutable NM_user)}" + NM_md5="${NM_md5:-$(_readaccountconf_mutable NM_md5)}" + if [ -z "$NM_user" ] || [ -z "$NM_md5" ]; then + NM_user="" + NM_md5="" + _err "No auth details provided. Please set user credentials using the \$NM_user and \$NM_md5 environment variables." + return 1 + fi + #save the api user and md5 password to the account conf file. + _debug "Save user and hash" + _saveaccountconf_mutable NM_user "$NM_user" + _saveaccountconf_mutable NM_md5 "$NM_md5" + + + zone="$(echo $fulldomain | _egrep_o "[^.]+.[^.]+$")" + get="https://namemaster.de/api/api.php?User=$NM_user&Password=$NM_md5&Antwort=csv&Int=0&Typ=ACME&Zone=$zone&hostname=$fulldomain&TXT=$txt_value&Action=Auto&Lifetime=3600" + erg="$(_get "$get")" + + if [ "$?" != "0" ]; then + _err "error $action $zone TXT: $txt" + _err "Error $?" + return 1 + fi + + if _contains "$erg" "Success"; then + _info "Success, TXT Added, OK" + else + _err "error Auto $zone TXT: $txt erg: $erg" + return 1 + fi + + _debug "ok Auto $zone TXT: $txt erg: $erg" + return 0 +} + +dns_nm_rm() { + +fulldomain=$1 +txt_value=$2 + + NM_user="${NM_user:-$(_readaccountconf_mutable NM_user)}" + NM_md5="${NM_md5:-$(_readaccountconf_mutable NM_md5)}" + if [ -z "$NM_user" ] || [ -z "$NM_md5" ]; then + NM_user="" + NM_md5="" + _err "No auth details provided. Please set user credentials using the \$NM_user and \$NM_md5 environment variables." + return 1 + fi + + zone="$(echo $fulldomain | _egrep_o "[^.]+.[^.]+$")" + get="https://namemaster.de/api/api.php?User=$NM_user&Password=$NM_md5&Antwort=csv&Int=0&Typ=TXT&Zone=$zone&hostname=$fulldomain&TXT=$txt_value&Action=Delete_IN&TTL=0" + erg="$(_get "$get")" + if [ "$?" != "0" ]; then + _err "error $action $zone TXT: $txt" + _err "Error $?" + return 1 + fi + +if _contains "$erg" "Success"; then + _info "Success, TXT removed, OK" + +else + _err "error Auto $zone TXT: $txt erg: $erg" + return 1 +fi + +_debug "ok Auto $zone TXT: $txt erg: $erg" +return 0 + + +} From 30416f54d169fbf391df1dffbea939003f69acd0 Mon Sep 17 00:00:00 2001 From: ThiloGa Date: Sat, 7 Mar 2020 15:18:25 +0100 Subject: [PATCH 238/357] Fixes for Travis CI -removing some blanks etc. --- dnsapi/dns_nm.sh | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/dnsapi/dns_nm.sh b/dnsapi/dns_nm.sh index 53c0c768..b7e2d498 100644 --- a/dnsapi/dns_nm.sh +++ b/dnsapi/dns_nm.sh @@ -18,29 +18,28 @@ dns_nm_add() { fulldomain=$1 txt_value=$2 _info "Using DNS-01 namemaster hook" - + NM_user="${NM_user:-$(_readaccountconf_mutable NM_user)}" NM_md5="${NM_md5:-$(_readaccountconf_mutable NM_md5)}" if [ -z "$NM_user" ] || [ -z "$NM_md5" ]; then NM_user="" NM_md5="" - _err "No auth details provided. Please set user credentials using the \$NM_user and \$NM_md5 environment variables." + _err "No auth details provided. Please set user credentials using the \$NM_user and \$NM_md5 environment variables." return 1 fi #save the api user and md5 password to the account conf file. _debug "Save user and hash" _saveaccountconf_mutable NM_user "$NM_user" _saveaccountconf_mutable NM_md5 "$NM_md5" - - + zone="$(echo $fulldomain | _egrep_o "[^.]+.[^.]+$")" get="https://namemaster.de/api/api.php?User=$NM_user&Password=$NM_md5&Antwort=csv&Int=0&Typ=ACME&Zone=$zone&hostname=$fulldomain&TXT=$txt_value&Action=Auto&Lifetime=3600" erg="$(_get "$get")" if [ "$?" != "0" ]; then - _err "error $action $zone TXT: $txt" + _err "error Auto $zone TXT: $txt" _err "Error $?" - return 1 + return 1 fi if _contains "$erg" "Success"; then @@ -56,15 +55,15 @@ dns_nm_add() { dns_nm_rm() { -fulldomain=$1 -txt_value=$2 + fulldomain=$1 + txt_value=$2 NM_user="${NM_user:-$(_readaccountconf_mutable NM_user)}" NM_md5="${NM_md5:-$(_readaccountconf_mutable NM_md5)}" if [ -z "$NM_user" ] || [ -z "$NM_md5" ]; then NM_user="" NM_md5="" - _err "No auth details provided. Please set user credentials using the \$NM_user and \$NM_md5 environment variables." + _err "No auth details provided. Please set user credentials using the \$NM_user and \$NM_md5 environment variables." return 1 fi @@ -73,20 +72,19 @@ txt_value=$2 erg="$(_get "$get")" if [ "$?" != "0" ]; then _err "error $action $zone TXT: $txt" - _err "Error $?" + _err "Error $?" return 1 fi -if _contains "$erg" "Success"; then - _info "Success, TXT removed, OK" - -else - _err "error Auto $zone TXT: $txt erg: $erg" - return 1 -fi + if _contains "$erg" "Success"; then + _info "Success, TXT removed, OK" + else + _err "error Auto $zone TXT: $txt erg: $erg" + return 1 + fi -_debug "ok Auto $zone TXT: $txt erg: $erg" -return 0 + _debug "ok Auto $zone TXT: $txt erg: $erg" + return 0 } From 3b01bf7bda9e2d05db2bc7e1f2a25d9233c0d021 Mon Sep 17 00:00:00 2001 From: ThiloGa Date: Sat, 7 Mar 2020 15:33:21 +0100 Subject: [PATCH 239/357] removed the probably last blank line --- dnsapi/dns_nm.sh | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/dnsapi/dns_nm.sh b/dnsapi/dns_nm.sh index b7e2d498..9928270b 100644 --- a/dnsapi/dns_nm.sh +++ b/dnsapi/dns_nm.sh @@ -37,7 +37,7 @@ dns_nm_add() { erg="$(_get "$get")" if [ "$?" != "0" ]; then - _err "error Auto $zone TXT: $txt" + _err "error Auto $zone TXT: $txt_value" _err "Error $?" return 1 fi @@ -45,11 +45,11 @@ dns_nm_add() { if _contains "$erg" "Success"; then _info "Success, TXT Added, OK" else - _err "error Auto $zone TXT: $txt erg: $erg" + _err "error Auto $zone TXT: $txt_value erg: $erg" return 1 fi - _debug "ok Auto $zone TXT: $txt erg: $erg" + _debug "ok Auto $zone TXT: $txt_value erg: $erg" return 0 } @@ -71,7 +71,7 @@ dns_nm_rm() { get="https://namemaster.de/api/api.php?User=$NM_user&Password=$NM_md5&Antwort=csv&Int=0&Typ=TXT&Zone=$zone&hostname=$fulldomain&TXT=$txt_value&Action=Delete_IN&TTL=0" erg="$(_get "$get")" if [ "$?" != "0" ]; then - _err "error $action $zone TXT: $txt" + _err "error $action $zone TXT: $txt_value" _err "Error $?" return 1 fi @@ -79,12 +79,11 @@ dns_nm_rm() { if _contains "$erg" "Success"; then _info "Success, TXT removed, OK" else - _err "error Auto $zone TXT: $txt erg: $erg" + _err "error Auto $zone TXT: $txt_value erg: $erg" return 1 fi - _debug "ok Auto $zone TXT: $txt erg: $erg" + _debug "ok Auto $zone TXT: $txt_value erg: $erg" return 0 - } From 142ca58d387c248ca34fec45efcc08bc981e62df Mon Sep 17 00:00:00 2001 From: ThiloGa Date: Sat, 7 Mar 2020 15:45:41 +0100 Subject: [PATCH 240/357] removed some unused Vars --- acme.sh | 1 - dnsapi/dns_nm.sh | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/acme.sh b/acme.sh index 12f2cbed..4d9a7c25 100755 --- a/acme.sh +++ b/acme.sh @@ -48,7 +48,6 @@ LOCAL_ANY_ADDRESS="0.0.0.0" DEFAULT_RENEW=60 - NO_VALUE="no" W_DNS="dns" diff --git a/dnsapi/dns_nm.sh b/dnsapi/dns_nm.sh index 9928270b..4c3f6c44 100644 --- a/dnsapi/dns_nm.sh +++ b/dnsapi/dns_nm.sh @@ -37,7 +37,7 @@ dns_nm_add() { erg="$(_get "$get")" if [ "$?" != "0" ]; then - _err "error Auto $zone TXT: $txt_value" + _err "error Ading $zone TXT: $txt_value" _err "Error $?" return 1 fi @@ -45,7 +45,7 @@ dns_nm_add() { if _contains "$erg" "Success"; then _info "Success, TXT Added, OK" else - _err "error Auto $zone TXT: $txt_value erg: $erg" + _err "error Adding $zone TXT: $txt_value erg: $erg" return 1 fi @@ -71,7 +71,7 @@ dns_nm_rm() { get="https://namemaster.de/api/api.php?User=$NM_user&Password=$NM_md5&Antwort=csv&Int=0&Typ=TXT&Zone=$zone&hostname=$fulldomain&TXT=$txt_value&Action=Delete_IN&TTL=0" erg="$(_get "$get")" if [ "$?" != "0" ]; then - _err "error $action $zone TXT: $txt_value" + _err "error Deleting $zone TXT: $txt_value" _err "Error $?" return 1 fi From e1e1ee31f07d28d460be4677f3ef75221fe3aa38 Mon Sep 17 00:00:00 2001 From: ThiloGa Date: Sat, 7 Mar 2020 16:00:52 +0100 Subject: [PATCH 241/357] Dont use $? directly anymore --- dnsapi/dns_nm.sh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_nm.sh b/dnsapi/dns_nm.sh index 4c3f6c44..7ba5ce3c 100644 --- a/dnsapi/dns_nm.sh +++ b/dnsapi/dns_nm.sh @@ -36,9 +36,10 @@ dns_nm_add() { get="https://namemaster.de/api/api.php?User=$NM_user&Password=$NM_md5&Antwort=csv&Int=0&Typ=ACME&Zone=$zone&hostname=$fulldomain&TXT=$txt_value&Action=Auto&Lifetime=3600" erg="$(_get "$get")" - if [ "$?" != "0" ]; then + exit_code="$?" + if [ "$exit_code" != 0 ]; then _err "error Ading $zone TXT: $txt_value" - _err "Error $?" + _err "Error $exit_code" return 1 fi @@ -70,9 +71,11 @@ dns_nm_rm() { zone="$(echo $fulldomain | _egrep_o "[^.]+.[^.]+$")" get="https://namemaster.de/api/api.php?User=$NM_user&Password=$NM_md5&Antwort=csv&Int=0&Typ=TXT&Zone=$zone&hostname=$fulldomain&TXT=$txt_value&Action=Delete_IN&TTL=0" erg="$(_get "$get")" - if [ "$?" != "0" ]; then + + exit_code="$?" + if [ "$exit_code" != "0" ]; then _err "error Deleting $zone TXT: $txt_value" - _err "Error $?" + _err "Error $exit_code?" return 1 fi From efef76d9cf2edd8711bd15d795942647a780e889 Mon Sep 17 00:00:00 2001 From: ThiloGa Date: Sat, 7 Mar 2020 19:34:57 +0100 Subject: [PATCH 242/357] fixed typo --- dnsapi/dns_nm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_nm.sh b/dnsapi/dns_nm.sh index 7ba5ce3c..ec0e2d88 100644 --- a/dnsapi/dns_nm.sh +++ b/dnsapi/dns_nm.sh @@ -75,7 +75,7 @@ dns_nm_rm() { exit_code="$?" if [ "$exit_code" != "0" ]; then _err "error Deleting $zone TXT: $txt_value" - _err "Error $exit_code?" + _err "Error $exit_code" return 1 fi From 7d7e9501facc62f89618c2ad12963a57de253e82 Mon Sep 17 00:00:00 2001 From: ThiloGa Date: Sat, 7 Mar 2020 20:37:29 +0100 Subject: [PATCH 243/357] fixing https://github.com/koalaman/shellcheck/wiki/SC2181 problems --- dnsapi/dns_nm.sh | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/dnsapi/dns_nm.sh b/dnsapi/dns_nm.sh index ec0e2d88..af98bbe3 100644 --- a/dnsapi/dns_nm.sh +++ b/dnsapi/dns_nm.sh @@ -34,11 +34,10 @@ dns_nm_add() { zone="$(echo $fulldomain | _egrep_o "[^.]+.[^.]+$")" get="https://namemaster.de/api/api.php?User=$NM_user&Password=$NM_md5&Antwort=csv&Int=0&Typ=ACME&Zone=$zone&hostname=$fulldomain&TXT=$txt_value&Action=Auto&Lifetime=3600" - erg="$(_get "$get")" - exit_code="$?" - if [ "$exit_code" != 0 ]; then - _err "error Ading $zone TXT: $txt_value" + if ! erg="$(_get "$get")" + then + _err "error Deleting $zone TXT: $txt_value" _err "Error $exit_code" return 1 fi @@ -70,10 +69,9 @@ dns_nm_rm() { zone="$(echo $fulldomain | _egrep_o "[^.]+.[^.]+$")" get="https://namemaster.de/api/api.php?User=$NM_user&Password=$NM_md5&Antwort=csv&Int=0&Typ=TXT&Zone=$zone&hostname=$fulldomain&TXT=$txt_value&Action=Delete_IN&TTL=0" - erg="$(_get "$get")" - exit_code="$?" - if [ "$exit_code" != "0" ]; then + if ! erg="$(_get "$get")" + then _err "error Deleting $zone TXT: $txt_value" _err "Error $exit_code" return 1 From 20702d26ec1dc48aa228052d4703d4569e0c2dcc Mon Sep 17 00:00:00 2001 From: ThiloGa Date: Sat, 7 Mar 2020 21:05:42 +0100 Subject: [PATCH 244/357] fixing https://github.com/koalaman/shellcheck/wiki/SC2181 problems --- dnsapi/dns_nm.sh | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_nm.sh b/dnsapi/dns_nm.sh index af98bbe3..090101e3 100644 --- a/dnsapi/dns_nm.sh +++ b/dnsapi/dns_nm.sh @@ -35,8 +35,7 @@ dns_nm_add() { zone="$(echo $fulldomain | _egrep_o "[^.]+.[^.]+$")" get="https://namemaster.de/api/api.php?User=$NM_user&Password=$NM_md5&Antwort=csv&Int=0&Typ=ACME&Zone=$zone&hostname=$fulldomain&TXT=$txt_value&Action=Auto&Lifetime=3600" - if ! erg="$(_get "$get")" - then + if ! erg="$(_get "$get")"; then _err "error Deleting $zone TXT: $txt_value" _err "Error $exit_code" return 1 @@ -70,8 +69,7 @@ dns_nm_rm() { zone="$(echo $fulldomain | _egrep_o "[^.]+.[^.]+$")" get="https://namemaster.de/api/api.php?User=$NM_user&Password=$NM_md5&Antwort=csv&Int=0&Typ=TXT&Zone=$zone&hostname=$fulldomain&TXT=$txt_value&Action=Delete_IN&TTL=0" - if ! erg="$(_get "$get")" - then + if ! erg="$(_get "$get")"; then _err "error Deleting $zone TXT: $txt_value" _err "Error $exit_code" return 1 From d8dbb85946527ee377eaae82dc9876fd88c7adc9 Mon Sep 17 00:00:00 2001 From: ThiloGa Date: Sat, 7 Mar 2020 21:11:08 +0100 Subject: [PATCH 245/357] small fixes --- dnsapi/dns_nm.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dnsapi/dns_nm.sh b/dnsapi/dns_nm.sh index 090101e3..74ffd6f2 100644 --- a/dnsapi/dns_nm.sh +++ b/dnsapi/dns_nm.sh @@ -37,7 +37,6 @@ dns_nm_add() { if ! erg="$(_get "$get")"; then _err "error Deleting $zone TXT: $txt_value" - _err "Error $exit_code" return 1 fi @@ -50,6 +49,7 @@ dns_nm_add() { _debug "ok Auto $zone TXT: $txt_value erg: $erg" return 0 + } dns_nm_rm() { @@ -71,7 +71,6 @@ dns_nm_rm() { if ! erg="$(_get "$get")"; then _err "error Deleting $zone TXT: $txt_value" - _err "Error $exit_code" return 1 fi From 3c79bb77db87fd3e94b0b8431cf65d8469b4dd90 Mon Sep 17 00:00:00 2001 From: ThiloGa Date: Sat, 7 Mar 2020 21:21:39 +0100 Subject: [PATCH 246/357] fixing travis-ci warnings SC2086: Double quote to prevent globbing and word splitting. --- dnsapi/dns_nm.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_nm.sh b/dnsapi/dns_nm.sh index 74ffd6f2..f5b0bd0e 100644 --- a/dnsapi/dns_nm.sh +++ b/dnsapi/dns_nm.sh @@ -32,7 +32,7 @@ dns_nm_add() { _saveaccountconf_mutable NM_user "$NM_user" _saveaccountconf_mutable NM_md5 "$NM_md5" - zone="$(echo $fulldomain | _egrep_o "[^.]+.[^.]+$")" + zone="$(echo "$fulldomain" | _egrep_o "[^.]+.[^.]+$")" get="https://namemaster.de/api/api.php?User=$NM_user&Password=$NM_md5&Antwort=csv&Int=0&Typ=ACME&Zone=$zone&hostname=$fulldomain&TXT=$txt_value&Action=Auto&Lifetime=3600" if ! erg="$(_get "$get")"; then @@ -66,7 +66,7 @@ dns_nm_rm() { return 1 fi - zone="$(echo $fulldomain | _egrep_o "[^.]+.[^.]+$")" + zone="$(echo "$fulldomain" | _egrep_o "[^.]+.[^.]+$")" get="https://namemaster.de/api/api.php?User=$NM_user&Password=$NM_md5&Antwort=csv&Int=0&Typ=TXT&Zone=$zone&hostname=$fulldomain&TXT=$txt_value&Action=Delete_IN&TTL=0" if ! erg="$(_get "$get")"; then From ea652c023e75344e408f698b4a8687bf46fc3658 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 8 Mar 2020 10:17:21 +0800 Subject: [PATCH 247/357] fix https://github.com/acmesh-official/acme.sh/issues/2778 --- dnsapi/dns_inwx.sh | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/dnsapi/dns_inwx.sh b/dnsapi/dns_inwx.sh index f4590cf8..7c08d72e 100755 --- a/dnsapi/dns_inwx.sh +++ b/dnsapi/dns_inwx.sh @@ -55,6 +55,7 @@ dns_inwx_rm() { INWX_User="${INWX_User:-$(_readaccountconf_mutable INWX_User)}" INWX_Password="${INWX_Password:-$(_readaccountconf_mutable INWX_Password)}" + INWX_Shared_Secret="${INWX_Shared_Secret:-$(_readaccountconf_mutable INWX_Shared_Secret)}" if [ -z "$INWX_User" ] || [ -z "$INWX_Password" ]; then INWX_User="" INWX_Password="" @@ -63,10 +64,6 @@ dns_inwx_rm() { return 1 fi - #save the api key and email to the account conf file. - _saveaccountconf_mutable INWX_User "$INWX_User" - _saveaccountconf_mutable INWX_Password "$INWX_Password" - _debug "First detect the root zone" if ! _get_root "$fulldomain"; then _err "invalid domain" From 15b841da06e0f2babf639103e7d0d5615a8d9f7b Mon Sep 17 00:00:00 2001 From: Honza Hommer Date: Sun, 8 Mar 2020 04:47:55 +0100 Subject: [PATCH 248/357] Feat: simplify conditions for bin and command --- notify/mail.sh | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/notify/mail.sh b/notify/mail.sh index ec9aa0de..f992cd4b 100644 --- a/notify/mail.sh +++ b/notify/mail.sh @@ -76,17 +76,16 @@ mail_send() { } _mail_bin() { - if [ -n "$MAIL_BIN" ]; then - _MAIL_BIN="$MAIL_BIN" - elif _exists "sendmail"; then - _MAIL_BIN="sendmail" - elif _exists "ssmtp"; then - _MAIL_BIN="ssmtp" - elif _exists "mutt"; then - _MAIL_BIN="mutt" - elif _exists "mail"; then - _MAIL_BIN="mail" - else + _MAIL_BIN="" + + for b in "$MAIL_BIN" sendmail ssmtp mutt mail; do + if _exists "$b"; then + _MAIL_BIN="$b" + break + fi + done + + if [ -z "$_MAIL_BIN" ]; then _err "Please install sendmail, ssmtp, mutt or mail first." return 1 fi @@ -95,25 +94,22 @@ _mail_bin() { } _mail_cmnd() { + _MAIL_ARGS="" + case $(basename "$_MAIL_BIN") in sendmail) if [ -n "$MAIL_FROM" ]; then - echo "'$_MAIL_BIN' -f '$MAIL_FROM' '$MAIL_TO'" - else - echo "'$_MAIL_BIN' '$MAIL_TO'" + _MAIL_ARGS="-f '$MAIL_FROM'" fi ;; - ssmtp) - echo "'$_MAIL_BIN' '$MAIL_TO'" - ;; mutt | mail) - echo "'$_MAIL_BIN' -s '$_subject' '$MAIL_TO'" + _MAIL_ARGS="-s '$_subject'" ;; *) - _err "Command $MAIL_BIN is not supported, use sendmail, ssmtp, mutt or mail." - return 1 ;; esac + + echo "'$_MAIL_BIN' $_MAIL_ARGS '$MAIL_TO'" } _mail_body() { From 80f1034dd6d9c0635ce8820453130654be3798de Mon Sep 17 00:00:00 2001 From: Markus Lippert Date: Sun, 8 Mar 2020 19:49:46 +0100 Subject: [PATCH 249/357] add OTP support --- deploy/synology_dsm.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 0c2b1185..23e97f24 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -15,6 +15,7 @@ # 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 # #returns 0 means success, otherwise error. @@ -79,7 +80,7 @@ synology_dsm_deploy() { # Login, get the token from JSON and session id from cookie _info "Logging into $SYNO_Hostname:$SYNO_Port" - response=$(_get "$_base_url/webman/login.cgi?username=$SYNO_Username&passwd=$SYNO_Password&enable_syno_token=yes") + response=$(_get "$_base_url/webman/login.cgi?username=$SYNO_Username&passwd=$SYNO_Password&enable_syno_token=yes&device_id=$SYNO_DID") token=$(echo "$response" | grep "SynoToken" | sed -n 's/.*"SynoToken" *: *"\([^"]*\).*/\1/p') _debug3 response "$response" From fd64c20807978d576cd3fcfb484f930e9ca406d7 Mon Sep 17 00:00:00 2001 From: Markus Lippert Date: Sun, 8 Mar 2020 20:22:31 +0100 Subject: [PATCH 250/357] store device ID --- deploy/synology_dsm.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 23e97f24..5aef3b93 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -39,6 +39,7 @@ synology_dsm_deploy() { _getdeployconf SYNO_Username _getdeployconf SYNO_Password _getdeployconf SYNO_Create + _getdeployconf SYNO_DID if [ -z "$SYNO_Username" ] || [ -z "$SYNO_Password" ]; then SYNO_Username="" SYNO_Password="" @@ -100,6 +101,7 @@ synology_dsm_deploy() { # Now that we know the username and password are good, save them _savedeployconf SYNO_Username "$SYNO_Username" _savedeployconf SYNO_Password "$SYNO_Password" + _savedeployconf SYNO_DID "$SYNO_DID" _debug token "$token" _info "Getting certificates in Synology DSM" From c25b4ba0991f083634063a076b51f7d71f004b97 Mon Sep 17 00:00:00 2001 From: Jeremiah Date: Sun, 8 Mar 2020 15:39:18 -0600 Subject: [PATCH 251/357] dns_me id parse using only sed --- dnsapi/dns_me.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_me.sh b/dnsapi/dns_me.sh index db51cc7c..3a01f803 100644 --- a/dnsapi/dns_me.sh +++ b/dnsapi/dns_me.sh @@ -114,7 +114,7 @@ _get_root() { fi if _contains "$response" "\"name\":\"$h\""; then - _domain_id=$(printf "%s\n" "$response" | cut -c 2- | head -c -2 | sed 's/{.*}//' | sed -r 's/^.*"id":([0-9]+).*$/\1/') + _domain_id=$(printf "%s\n" "$response" | sed 's/^{//; s/}$//; s/{.*}//' | sed -E 's/^.*"id":([0-9]+).*$/\1/') if [ "$_domain_id" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain="$h" From 3d8164113916a54db1f266ca34f13eb60d5a0ceb Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 9 Mar 2020 19:04:32 +0800 Subject: [PATCH 252/357] fix format --- acme.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/acme.sh b/acme.sh index 12f2cbed..4d9a7c25 100755 --- a/acme.sh +++ b/acme.sh @@ -48,7 +48,6 @@ LOCAL_ANY_ADDRESS="0.0.0.0" DEFAULT_RENEW=60 - NO_VALUE="no" W_DNS="dns" From 5d881a8b0ff8dc5db10a4da1379113e7163ea155 Mon Sep 17 00:00:00 2001 From: Jeremiah Date: Mon, 9 Mar 2020 11:34:50 -0600 Subject: [PATCH 253/357] use more compatible regex flag --- dnsapi/dns_me.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_me.sh b/dnsapi/dns_me.sh index 3a01f803..49007402 100644 --- a/dnsapi/dns_me.sh +++ b/dnsapi/dns_me.sh @@ -114,7 +114,7 @@ _get_root() { fi if _contains "$response" "\"name\":\"$h\""; then - _domain_id=$(printf "%s\n" "$response" | sed 's/^{//; s/}$//; s/{.*}//' | sed -E 's/^.*"id":([0-9]+).*$/\1/') + _domain_id=$(printf "%s\n" "$response" | sed 's/^{//; s/}$//; s/{.*}//' | sed -r 's/^.*"id":([0-9]+).*$/\1/') if [ "$_domain_id" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain="$h" From 554e083f3d387baacbc151b98463efc697091706 Mon Sep 17 00:00:00 2001 From: dkerr64 Date: Wed, 11 Mar 2020 10:58:36 -0400 Subject: [PATCH 254/357] For MULTI_CALL default to undefined, deleting entry in config file if set to "no" --- deploy/ssh.sh | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index 7eed8a34..5d1ee805 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -20,8 +20,8 @@ # export DEPLOY_SSH_CAFILE="/etc/stunnel/uca.pem" # export DEPLOY_SSH_FULLCHAIN="" # export DEPLOY_SSH_REMOTE_CMD="/etc/init.d/stunnel.sh restart" -# export DEPLOY_SSH_BACKUP="" # yes or no, default to yes -# export DEPLOY_SSH_MULTI_CALL="" # yes or no, default to no +# export DEPLOY_SSH_BACKUP="" # yes or no, default to yes or previously saved value +# export DEPLOY_SSH_MULTI_CALL="" # yes or no, default to no or previously saved value # ######## Public functions ##################### @@ -76,7 +76,7 @@ ssh_deploy() { Le_Deploy_ssh_cmd="ssh -T" fi - # BACKUP is optional. If not provided then default to yes + # BACKUP is optional. If not provided then default to previously saved value or yes. if [ "$DEPLOY_SSH_BACKUP" = "no" ]; then Le_Deploy_ssh_backup="no" elif [ -z "$Le_Deploy_ssh_backup" ] || [ "$DEPLOY_SSH_BACKUP" = "yes" ]; then @@ -84,13 +84,15 @@ ssh_deploy() { fi _savedomainconf Le_Deploy_ssh_backup "$Le_Deploy_ssh_backup" - # MULTI_CALL is optional. If not provided then default to no + # MULTI_CALL is optional. If not provided then default to previously saved + # value (which may be undefined... equivalent to "no"). if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then Le_Deploy_ssh_multi_call="yes" - elif [ -z "$Le_Deploy_ssh_multi_call" ] || [ "$DEPLOY_SSH_MULTI_CALL" = "no" ]; then - Le_Deploy_ssh_multi_call="no" + _savedomainconf Le_Deploy_ssh_multi_call "$Le_Deploy_ssh_multi_call" + elif [ "$DEPLOY_SSH_MULTI_CALL" = "no" ]; then + Le_Deploy_ssh_multi_call="" + _cleardomainconf Le_Deploy_ssh_multi_call fi - _savedomainconf Le_Deploy_ssh_multi_call "$Le_Deploy_ssh_multi_call" _info "Deploy certificates to remote server $Le_Deploy_ssh_user@$Le_Deploy_ssh_server" if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then From 2a8746f6b0702238b28a69a79e8fe4d05ffcaddc Mon Sep 17 00:00:00 2001 From: Honza Hommer Date: Sun, 8 Mar 2020 04:51:39 +0100 Subject: [PATCH 255/357] Feat: add msmtp command --- notify/mail.sh | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/notify/mail.sh b/notify/mail.sh index f992cd4b..54b2a6d4 100644 --- a/notify/mail.sh +++ b/notify/mail.sh @@ -6,6 +6,7 @@ #MAIL_FROM="yyyy@gmail.com" #MAIL_TO="yyyy@gmail.com" #MAIL_NOVALIDATE="" +#MAIL_MSMTP_ACCOUNT="" mail_send() { _subject="$1" @@ -78,7 +79,7 @@ mail_send() { _mail_bin() { _MAIL_BIN="" - for b in "$MAIL_BIN" sendmail ssmtp mutt mail; do + for b in "$MAIL_BIN" sendmail ssmtp mutt mail msmtp; do if _exists "$b"; then _MAIL_BIN="$b" break @@ -86,7 +87,7 @@ _mail_bin() { done if [ -z "$_MAIL_BIN" ]; then - _err "Please install sendmail, ssmtp, mutt or mail first." + _err "Please install sendmail, ssmtp, mutt, mail or msmtp first." return 1 fi @@ -105,8 +106,16 @@ _mail_cmnd() { mutt | mail) _MAIL_ARGS="-s '$_subject'" ;; - *) + msmtp) + if [ -n "$MAIL_FROM" ]; then + _MAIL_ARGS="-f '$MAIL_FROM'" + fi + + if [ -n "$MAIL_MSMTP_ACCOUNT" ]; then + _MAIL_ARGS="$_MAIL_ARGS -a '$MAIL_MSMTP_ACCOUNT'" + fi ;; + *) ;; esac echo "'$_MAIL_BIN' $_MAIL_ARGS '$MAIL_TO'" @@ -114,7 +123,7 @@ _mail_cmnd() { _mail_body() { case $(basename "$_MAIL_BIN") in - sendmail | ssmtp) + sendmail | ssmtp | msmtp) if [ -n "$MAIL_FROM" ]; then echo "From: $MAIL_FROM" fi From f38df4df1151822d50628be22f27ab3eb20429f4 Mon Sep 17 00:00:00 2001 From: dkerr64 Date: Sat, 14 Mar 2020 21:51:21 -0400 Subject: [PATCH 256/357] Make remote backup directory path user configurable. --- deploy/ssh.sh | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index 5d1ee805..d71637a1 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -21,6 +21,7 @@ # export DEPLOY_SSH_FULLCHAIN="" # export DEPLOY_SSH_REMOTE_CMD="/etc/init.d/stunnel.sh restart" # export DEPLOY_SSH_BACKUP="" # yes or no, default to yes or previously saved value +# export DEPLOY_SSH_BACKUP_PATH=".acme_ssh_deploy" # path on remote system. Defaults to .acme_ssh_deploy # export DEPLOY_SSH_MULTI_CALL="" # yes or no, default to no or previously saved value # ######## Public functions ##################### @@ -34,9 +35,8 @@ ssh_deploy() { _cfullchain="$5" _err_code=0 _cmdstr="" - _homedir='~' - _backupprefix="$_homedir/.acme_ssh_deploy/$_cdomain-backup" - _backupdir="$_backupprefix-$(_utc_date | tr ' ' '-')" + _backupprefix="" + _backupdir="" if [ -f "$DOMAIN_CONF" ]; then # shellcheck disable=SC1090 @@ -84,6 +84,14 @@ ssh_deploy() { fi _savedomainconf Le_Deploy_ssh_backup "$Le_Deploy_ssh_backup" + # BACKUP_PATH is optional. If not provided then default to previously saved value or .acme_ssh_deploy + if [ -n "$DEPLOY_SSH_BACKUP_PATH" ]; then + Le_Deploy_ssh_backup_path="$DEPLOY_SSH_BACKUP_PATH" + elif [ -z "$Le_Deploy_ssh_backup_path" ]; then + Le_Deploy_ssh_backup_path=".acme_ssh_deploy" + fi + _savedomainconf Le_Deploy_ssh_backup_path "$Le_Deploy_ssh_backup_path" + # MULTI_CALL is optional. If not provided then default to previously saved # value (which may be undefined... equivalent to "no"). if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then @@ -102,6 +110,8 @@ ssh_deploy() { fi if [ "$Le_Deploy_ssh_backup" = "yes" ]; then + _backupprefix="$Le_Deploy_ssh_backup_path/$_cdomain-backup" + _backupdir="$_backupprefix-$(_utc_date | tr ' ' '-')" # run cleanup on the backup directory, erase all older # than 180 days (15552000 seconds). _cmdstr="{ now=\"\$(date -u +%s)\"; for fn in $_backupprefix*; \ From f61f2d6e5e024e7e08687beaacf8a9807c3a6bee Mon Sep 17 00:00:00 2001 From: ThiloGa Date: Sat, 21 Mar 2020 19:28:16 +0100 Subject: [PATCH 257/357] adaptations to the new api functions _get_root fully functional due to the extended api --- dnsapi/dns_nm.sh | 79 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 23 deletions(-) diff --git a/dnsapi/dns_nm.sh b/dnsapi/dns_nm.sh index f5b0bd0e..f9e98b2a 100644 --- a/dnsapi/dns_nm.sh +++ b/dnsapi/dns_nm.sh @@ -6,7 +6,7 @@ # Environment variables: # # - $NM_user (your namemaster.de API username) -# - $NM_md5 (your namemaster.de API password_as_md5hash) +# - $NM_sha256 (your namemaster.de API password_as_sha256hash) # # Author: Thilo Gass # Git repo: https://github.com/ThiloGa/acme.sh @@ -14,42 +14,53 @@ #-- dns_nm_add() - Add TXT record -------------------------------------- # Usage: dns_nm_add _acme-challenge.subdomain.domain.com "XyZ123..." +namemaster_api="https://namemaster.de/api/api.php" + + dns_nm_add() { fulldomain=$1 txt_value=$2 _info "Using DNS-01 namemaster hook" NM_user="${NM_user:-$(_readaccountconf_mutable NM_user)}" - NM_md5="${NM_md5:-$(_readaccountconf_mutable NM_md5)}" - if [ -z "$NM_user" ] || [ -z "$NM_md5" ]; then + NM_sha256="${NM_sha256:-$(_readaccountconf_mutable NM_sha256)}" + if [ -z "$NM_user" ] || [ -z "$NM_sha256" ]; then NM_user="" - NM_md5="" - _err "No auth details provided. Please set user credentials using the \$NM_user and \$NM_md5 environment variables." + NM_sha256="" + _err "No auth details provided. Please set user credentials using the \$NM_user and \$NM_sha256 environment variables." return 1 fi - #save the api user and md5 password to the account conf file. + #save the api user and sha256 password to the account conf file. _debug "Save user and hash" _saveaccountconf_mutable NM_user "$NM_user" - _saveaccountconf_mutable NM_md5 "$NM_md5" + _saveaccountconf_mutable NM_sha256 "$NM_sha256" - zone="$(echo "$fulldomain" | _egrep_o "[^.]+.[^.]+$")" - get="https://namemaster.de/api/api.php?User=$NM_user&Password=$NM_md5&Antwort=csv&Int=0&Typ=ACME&Zone=$zone&hostname=$fulldomain&TXT=$txt_value&Action=Auto&Lifetime=3600" - if ! erg="$(_get "$get")"; then - _err "error Deleting $zone TXT: $txt_value" + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" "$fulldomain" + return 1 + fi + + _info "die Zone lautet:" "$zone" + + get="$namemaster_api?User=$NM_user&Password=$NM_sha256&Antwort=csv&Typ=ACME&zone=$zone&hostname=$fulldomain&TXT=$txt_value&Action=Auto&Lifetime=3600" + + if ! erg="$(_get "$get")" + then + _err "error Adding $fulldomain TXT: $txt_value" return 1 fi if _contains "$erg" "Success"; then _info "Success, TXT Added, OK" else - _err "error Adding $zone TXT: $txt_value erg: $erg" + _err "error Adding $fulldomain TXT: $txt_value erg: $erg" return 1 fi - _debug "ok Auto $zone TXT: $txt_value erg: $erg" + _debug "ok Auto $fulldomain TXT: $txt_value erg: $erg" return 0 - } dns_nm_rm() { @@ -58,30 +69,52 @@ dns_nm_rm() { txt_value=$2 NM_user="${NM_user:-$(_readaccountconf_mutable NM_user)}" - NM_md5="${NM_md5:-$(_readaccountconf_mutable NM_md5)}" - if [ -z "$NM_user" ] || [ -z "$NM_md5" ]; then + NM_sha256="${NM_sha256:-$(_readaccountconf_mutable NM_sha256)}" + if [ -z "$NM_user" ] || [ -z "$NM_sha256" ]; then NM_user="" - NM_md5="" - _err "No auth details provided. Please set user credentials using the \$NM_user and \$NM_md5 environment variables." + NM_sha256="" + _err "No auth details provided. Please set user credentials using the \$NM_user and \$NM_sha256 environment variables." return 1 fi + zone="$(echo "$fulldomain" | _egrep_o "[^.]+.[^.]+$")" - get="https://namemaster.de/api/api.php?User=$NM_user&Password=$NM_md5&Antwort=csv&Int=0&Typ=TXT&Zone=$zone&hostname=$fulldomain&TXT=$txt_value&Action=Delete_IN&TTL=0" + get="$namemaster_api?User=$NM_user&Password=$NM_sha256&Antwort=csv&Typ=TXT&Zone=$zone&hostname=$fulldomain&TXT=$txt_value&Action=Delete_IN" - if ! erg="$(_get "$get")"; then - _err "error Deleting $zone TXT: $txt_value" + if ! erg="$(_get "$get")" + then + _err "error Deleting $fulldomain TXT: $txt_value" return 1 fi if _contains "$erg" "Success"; then _info "Success, TXT removed, OK" else - _err "error Auto $zone TXT: $txt_value erg: $erg" + _err "error Auto $fulldomain TXT: $txt_value erg: $erg" return 1 fi - _debug "ok Auto $zone TXT: $txt_value erg: $erg" + _debug "ok Auto $fulldomain TXT: $txt_value erg: $erg" return 0 } + + +_get_root() { + + domain=$1 + + get="$namemaster_api?User=$NM_user&Password=$NM_sha256&Typ=acme&hostname=$domain&Action=getzone&antwort=csv" + + if ! zone="$(_get "$get")" + then + _err "error getting Zone" + return 1 + else + if _contains "$zone" "hostname not found" + then + return 1 + fi + fi + +} \ No newline at end of file From 598f29b78e107baad00e8a07365c322d41c5b2c9 Mon Sep 17 00:00:00 2001 From: ThiloGa Date: Sat, 21 Mar 2020 19:41:46 +0100 Subject: [PATCH 258/357] doing shellcheck staff --- dnsapi/dns_nm.sh | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/dnsapi/dns_nm.sh b/dnsapi/dns_nm.sh index f9e98b2a..24ff5409 100644 --- a/dnsapi/dns_nm.sh +++ b/dnsapi/dns_nm.sh @@ -16,7 +16,6 @@ namemaster_api="https://namemaster.de/api/api.php" - dns_nm_add() { fulldomain=$1 txt_value=$2 @@ -35,7 +34,6 @@ dns_nm_add() { _saveaccountconf_mutable NM_user "$NM_user" _saveaccountconf_mutable NM_sha256 "$NM_sha256" - _debug "First detect the root zone" if ! _get_root "$fulldomain"; then _err "invalid domain" "$fulldomain" @@ -46,8 +44,8 @@ dns_nm_add() { get="$namemaster_api?User=$NM_user&Password=$NM_sha256&Antwort=csv&Typ=ACME&zone=$zone&hostname=$fulldomain&TXT=$txt_value&Action=Auto&Lifetime=3600" - if ! erg="$(_get "$get")" - then + + if ! erg="$(_get "$get")"; then _err "error Adding $fulldomain TXT: $txt_value" return 1 fi @@ -77,12 +75,10 @@ dns_nm_rm() { return 1 fi - zone="$(echo "$fulldomain" | _egrep_o "[^.]+.[^.]+$")" get="$namemaster_api?User=$NM_user&Password=$NM_sha256&Antwort=csv&Typ=TXT&Zone=$zone&hostname=$fulldomain&TXT=$txt_value&Action=Delete_IN" - if ! erg="$(_get "$get")" - then + if ! erg="$(_get "$get")"; then _err "error Deleting $fulldomain TXT: $txt_value" return 1 fi @@ -99,15 +95,13 @@ dns_nm_rm() { } - _get_root() { domain=$1 get="$namemaster_api?User=$NM_user&Password=$NM_sha256&Typ=acme&hostname=$domain&Action=getzone&antwort=csv" - if ! zone="$(_get "$get")" - then + if ! zone="$(_get "$get")"; then _err "error getting Zone" return 1 else @@ -117,4 +111,4 @@ _get_root() { fi fi -} \ No newline at end of file +} From a1c4d159dd1710cd451f3d0bcac15b6b9121f58f Mon Sep 17 00:00:00 2001 From: ThiloGa Date: Sat, 21 Mar 2020 19:48:17 +0100 Subject: [PATCH 259/357] further shellcheck fixes --- dnsapi/dns_nm.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dnsapi/dns_nm.sh b/dnsapi/dns_nm.sh index 24ff5409..18369ebd 100644 --- a/dnsapi/dns_nm.sh +++ b/dnsapi/dns_nm.sh @@ -44,7 +44,6 @@ dns_nm_add() { get="$namemaster_api?User=$NM_user&Password=$NM_sha256&Antwort=csv&Typ=ACME&zone=$zone&hostname=$fulldomain&TXT=$txt_value&Action=Auto&Lifetime=3600" - if ! erg="$(_get "$get")"; then _err "error Adding $fulldomain TXT: $txt_value" return 1 @@ -105,8 +104,7 @@ _get_root() { _err "error getting Zone" return 1 else - if _contains "$zone" "hostname not found" - then + if _contains "$zone" "hostname not found"; then return 1 fi fi From bc2ed602e7d4596a1f1a0d009b8ed152a8987862 Mon Sep 17 00:00:00 2001 From: ThiloGa Date: Sat, 21 Mar 2020 21:18:25 +0100 Subject: [PATCH 260/357] deleted txt entry routine by request of namemaster.de, entry is deleted automatically --- dnsapi/dns_nm.sh | 32 ++++---------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/dnsapi/dns_nm.sh b/dnsapi/dns_nm.sh index 18369ebd..4dfcc777 100644 --- a/dnsapi/dns_nm.sh +++ b/dnsapi/dns_nm.sh @@ -63,34 +63,10 @@ dns_nm_add() { dns_nm_rm() { fulldomain=$1 - txt_value=$2 - - NM_user="${NM_user:-$(_readaccountconf_mutable NM_user)}" - NM_sha256="${NM_sha256:-$(_readaccountconf_mutable NM_sha256)}" - if [ -z "$NM_user" ] || [ -z "$NM_sha256" ]; then - NM_user="" - NM_sha256="" - _err "No auth details provided. Please set user credentials using the \$NM_user and \$NM_sha256 environment variables." - return 1 - fi - - zone="$(echo "$fulldomain" | _egrep_o "[^.]+.[^.]+$")" - get="$namemaster_api?User=$NM_user&Password=$NM_sha256&Antwort=csv&Typ=TXT&Zone=$zone&hostname=$fulldomain&TXT=$txt_value&Action=Delete_IN" - - if ! erg="$(_get "$get")"; then - _err "error Deleting $fulldomain TXT: $txt_value" - return 1 - fi - - if _contains "$erg" "Success"; then - _info "Success, TXT removed, OK" - else - _err "error Auto $fulldomain TXT: $txt_value erg: $erg" - return 1 - fi - - _debug "ok Auto $fulldomain TXT: $txt_value erg: $erg" - return 0 + txtvalue=$2 + _info "TXT enrty in $fulldomain is deleted automatically" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" } From 4fa59ea04ec8e31777ce4fcd7c4456094518dee4 Mon Sep 17 00:00:00 2001 From: Ehsan Aliakbar Date: Tue, 24 Mar 2020 17:56:50 +0430 Subject: [PATCH 261/357] Adding Arvan Dns Api --- dnsapi/dns_arvan.sh | 163 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 dnsapi/dns_arvan.sh diff --git a/dnsapi/dns_arvan.sh b/dnsapi/dns_arvan.sh new file mode 100644 index 00000000..af9de462 --- /dev/null +++ b/dnsapi/dns_arvan.sh @@ -0,0 +1,163 @@ +#!/usr/bin/env sh + +#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 +# +######## Public functions ##################### + +#Usage: dns_arvan_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_arvan_add() { + fulldomain=$1 + txtvalue=$2 + _info "Using Arvan" + + Arvan_Token="${Arvan_Token:-$(_readaccountconf_mutable Arvan_Token)}" + + if [ -z "$Arvan_Token" ]; then + _err "You didn't specify \"Arvan_Token\" token yet." + _err "You can get yours from here https://npanel.arvancloud.com/profile/api-keys" + return 1 + fi + #save the api token to the account conf file. + _saveaccountconf_mutable Arvan_Token "$Arvan_Token" + + _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 _arvan_rest POST "$_domain/dns-records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":{\"text\":\"$txtvalue\"},\"ttl\":120}"; then + if _contains "$response" "$txtvalue"; then + _info "Added, OK" + return 0 + elif _contains "$response" "Record Data is Duplicated"; then + _info "Already exists, OK" + return 0 + else + _err "Add txt record error." + return 1 + fi + fi + _err "Add txt record error." + return 1 +} + +#Usage: fulldomain txtvalue +#Remove the txt record after validation. +dns_arvan_rm() { + fulldomain=$1 + txtvalue=$2 + _info "Using Arvan" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + Arvan_Token="${Arvan_Token:-$(_readaccountconf_mutable Arvan_Token)}" + + _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 txt 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 + + 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 +} + +#################### 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 ! _arvan_rest GET "?search=$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 [ "$_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 +} + +_arvan_rest() { + mtd="$1" + ep="$2" + data="$3" + + token_trimmed=$(echo "$Arvan_Token" | tr -d '"') + + export _H1="Authorization: $token_trimmed" + + if [ "$mtd" == "DELETE" ]; then + # DELETE Request shouldn't have Content-Type + _debug data "$data" + response="$(_post "$data" "$ARVAN_API_URL/$ep" "" "$mtd")" + elif [ "$mtd" == "POST" ]; then + export _H2="Content-Type: application/json" + _debug data "$data" + response="$(_post "$data" "$ARVAN_API_URL/$ep" "" "$mtd")" + else + response="$(_get "$ARVAN_API_URL/$ep$data")" + fi +} \ No newline at end of file From cb7e38577df79f6c19047e9dfa2cd60438c08bd3 Mon Sep 17 00:00:00 2001 From: Oliver Blaha Date: Tue, 24 Mar 2020 14:44:35 +0100 Subject: [PATCH 262/357] add support for upgrade from tag --- acme.sh | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/acme.sh b/acme.sh index 4d9a7c25..f5e79ee8 100755 --- a/acme.sh +++ b/acme.sh @@ -6317,7 +6317,7 @@ _installOnline() { if ./$PROJECT_ENTRY install "$_nocron" "" "$_noprofile"; then _info "Install success!" _initpath - _saveaccountconf "UPGRADE_HASH" "$(_getMasterHash)" + _saveaccountconf "UPGRADE_HASH" "$(_getUpgradeHash)" fi cd .. @@ -6327,19 +6327,27 @@ _installOnline() { ) } -_getMasterHash() { +_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 +} + +_getUpgradeHash() { _b="$BRANCH" if [ -z "$_b" ]; then _b="master" fi - _hash_url="https://api.github.com/repos/acmesh-official/$PROJECT_NAME/git/refs/heads/$_b" - _get $_hash_url | tr -d "\r\n" | tr '{},' '\n' | grep '"sha":' | cut -d '"' -f 4 + _hash=$(_getRepoHash "heads/$_b") + if [ -z "$_hash" ]; then _hash=$(_getRepoHash "tags/$_b"); fi + echo $_hash } upgrade() { if ( _initpath - [ -z "$FORCE" ] && [ "$(_getMasterHash)" = "$(_readaccountconf "UPGRADE_HASH")" ] && _info "Already uptodate!" && exit 0 + [ -z "$FORCE" ] && [ "$(_getUpgradeHash)" = "$(_readaccountconf "UPGRADE_HASH")" ] && _info "Already uptodate!" && exit 0 export LE_WORKING_DIR cd "$LE_WORKING_DIR" _installOnline "nocron" "noprofile" From 0453d656d629705059800a7d91cd3ea152649747 Mon Sep 17 00:00:00 2001 From: Brian Torres-Gil Date: Tue, 24 Mar 2020 20:01:51 -0700 Subject: [PATCH 263/357] fix(deploy/panos): data format improvements It was discovered in testing that PAN-OS < 9.0 has slightly different requirements for the multipart/form-data format and requires the `type` parameter to be passed in the URL. These corrections should work for all PAN-OS versions. --- deploy/panos.sh | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/deploy/panos.sh b/deploy/panos.sh index 6316784a..ef622ded 100644 --- a/deploy/panos.sh +++ b/deploy/panos.sh @@ -47,24 +47,24 @@ deployer() { #Set Header export _H1="Content-Type: multipart/form-data; boundary=$delim" if [ "$type" = 'cert' ]; then - content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"type\"\r\n\r\n\r\nimport" - content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"category\"\r\n\r\n\r\ncertificate" - content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"certificate-name\"\r\n\r\n\r\n$_cdomain" - content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"\r\n\r\n\r\n$_panos_key" - content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"format\"\r\n\r\n\r\npem" + panos_url="${panos_url}?type=import" + content="--$delim${nl}Content-Disposition: form-data; name=\"category\"\r\n\r\ncertificate" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"certificate-name\"\r\n\r\n$_cdomain" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"\r\n\r\n$_panos_key" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"format\"\r\n\r\npem" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_cfullchain")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cfullchain")" fi if [ "$type" = 'key' ]; then - content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"type\"\r\n\r\n\r\nimport" - content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"category\"\r\n\r\n\r\nprivate-key" - content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"certificate-name\"\r\n\r\n\r\n$_cdomain" - content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"\r\n\r\n\r\n$_panos_key" - content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"format\"\r\n\r\n\r\npem" - content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"passphrase\"\r\n\r\n\r\n123456" + panos_url="${panos_url}?type=import" + content="--$delim${nl}Content-Disposition: form-data; name=\"category\"\r\n\r\nprivate-key" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"certificate-name\"\r\n\r\n$_cdomain" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"\r\n\r\n$_panos_key" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"format\"\r\n\r\npem" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"passphrase\"\r\n\r\n123456" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")" fi #Close multipart - content="$content${nl}--$delim--${nl}" + content="$content${nl}--$delim--${nl}${nl}" #Convert CRLF content=$(printf %b "$content") fi From 20ba82025316e033d7cf9cc9db0f1abaaedf1b4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BD=97=E8=AF=9A?= Date: Wed, 25 Mar 2020 14:39:52 +0800 Subject: [PATCH 264/357] Update dns_dp.sh https://dnsapi.cn has change the default language to cn other then en. So the api call need to add `lang=en` to url params for getting the english messages. And, They also change the susccess message from "Action completed successful" to "Operation successful". Simply use "successful" as keyword will be fine. --- dnsapi/dns_dp.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dnsapi/dns_dp.sh b/dnsapi/dns_dp.sh index 480c1f9a..033fa5aa 100755 --- a/dnsapi/dns_dp.sh +++ b/dnsapi/dns_dp.sh @@ -53,7 +53,7 @@ dns_dp_rm() { return 1 fi - if ! _rest POST "Record.List" "login_token=$DP_Id,$DP_Key&format=json&domain_id=$_domain_id&sub_domain=$_sub_domain"; then + if ! _rest POST "Record.List" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain_id=$_domain_id&sub_domain=$_sub_domain"; then _err "Record.Lis error." return 1 fi @@ -70,12 +70,12 @@ dns_dp_rm() { return 1 fi - if ! _rest POST "Record.Remove" "login_token=$DP_Id,$DP_Key&format=json&domain_id=$_domain_id&record_id=$record_id"; then + if ! _rest POST "Record.Remove" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain_id=$_domain_id&record_id=$record_id"; then _err "Record.Remove error." return 1 fi - _contains "$response" "Action completed successful" + _contains "$response" "successful" } @@ -89,11 +89,11 @@ add_record() { _info "Adding record" - if ! _rest POST "Record.Create" "login_token=$DP_Id,$DP_Key&format=json&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=默认"; then return 1 fi - _contains "$response" "Action completed successful" || _contains "$response" "Domain record already exists" + _contains "$response" "successful" || _contains "$response" "Domain record already exists" } #################### Private functions below ################################## @@ -113,11 +113,11 @@ _get_root() { return 1 fi - if ! _rest POST "Domain.Info" "login_token=$DP_Id,$DP_Key&format=json&domain=$h"; then + if ! _rest POST "Domain.Info" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain=$h"; then return 1 fi - if _contains "$response" "Action completed successful"; then + if _contains "$response" "successful"; then _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \") _debug _domain_id "$_domain_id" if [ "$_domain_id" ]; then From 6132af8ecb1e978f1e9d01f2670af22b7d179d8a Mon Sep 17 00:00:00 2001 From: ucando Date: Thu, 26 Mar 2020 14:59:23 +0800 Subject: [PATCH 265/357] enable qiniu to deploy more than one domain --- deploy/qiniu.sh | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/deploy/qiniu.sh b/deploy/qiniu.sh index 13b09651..70669917 100644 --- a/deploy/qiniu.sh +++ b/deploy/qiniu.sh @@ -6,6 +6,8 @@ # export QINIU_AK="QINIUACCESSKEY" # export QINIU_SK="QINIUSECRETKEY" # export QINIU_CDN_DOMAIN="cdn.example.com" +# If you have more than one domain, just +# export QINIU_CDN_DOMAIN="cdn1.example.com cdn2.example.com" QINIU_API_BASE="https://api.qiniu.com" @@ -67,21 +69,23 @@ qiniu_deploy() { _debug certId "$_certId" ## update domain ssl config - update_path="/domain/$QINIU_CDN_DOMAIN/httpsconf" update_body="{\"certid\":$_certId,\"forceHttps\":false}" - update_access_token="$(_make_access_token "$update_path")" - _debug update_access_token "$update_access_token" - export _H1="Authorization: QBox $update_access_token" - update_response=$(_post "$update_body" "$QINIU_API_BASE$update_path" 0 "PUT" "application/json" | _dbase64 "multiline") - - if _contains "$update_response" "error"; then - _err "Error in updating domain httpsconf:" - _err "$update_response" - return 1 - fi - - _debug update_response "$update_response" - _info "Certificate successfully deployed" + for domain in $QINIU_CDN_DOMAIN; do + update_path="/domain/$domain/httpsconf" + update_access_token="$(_make_access_token "$update_path")" + _debug update_access_token "$update_access_token" + export _H1="Authorization: QBox $update_access_token" + update_response=$(_post "$update_body" "$QINIU_API_BASE$update_path" 0 "PUT" "application/json" | _dbase64 "multiline") + + if _contains "$update_response" "error"; then + _err "Error in updating domain $domain httpsconf:" + _err "$update_response" + return 1 + fi + + _debug update_response "$update_response" + _info "Domain $domain certificate has been deployed successfully" + done return 0 } From 200cd5972aac175a11536218cb2b21c0026a6172 Mon Sep 17 00:00:00 2001 From: Ehsan Aliakbar Date: Sat, 28 Mar 2020 21:50:58 +0430 Subject: [PATCH 266/357] fix shellcheck errors in Arvan Dns Api --- 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 af9de462..341c8c17 100644 --- a/dnsapi/dns_arvan.sh +++ b/dnsapi/dns_arvan.sh @@ -78,7 +78,7 @@ dns_arvan_rm() { 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" + _err "Please create a github issue with debbug log" return 1 fi @@ -149,11 +149,11 @@ _arvan_rest() { export _H1="Authorization: $token_trimmed" - if [ "$mtd" == "DELETE" ]; then + if [ "$mtd" = "DELETE" ]; then # DELETE Request shouldn't have Content-Type _debug data "$data" response="$(_post "$data" "$ARVAN_API_URL/$ep" "" "$mtd")" - elif [ "$mtd" == "POST" ]; then + elif [ "$mtd" = "POST" ]; then export _H2="Content-Type: application/json" _debug data "$data" response="$(_post "$data" "$ARVAN_API_URL/$ep" "" "$mtd")" From 34cebe8c0c1e08b25684e5b94535013087875519 Mon Sep 17 00:00:00 2001 From: netpok Date: Sun, 29 Mar 2020 23:45:52 +0200 Subject: [PATCH 267/357] Fix invalid domain error on dns_cf update When dns_cf used with Zone ID it fails on removal of the entry. This pull request adds the missing CF_Zone_ID loading. --- dnsapi/dns_cf.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/dnsapi/dns_cf.sh b/dnsapi/dns_cf.sh index 2927ab4b..040934e2 100755 --- a/dnsapi/dns_cf.sh +++ b/dnsapi/dns_cf.sh @@ -94,6 +94,7 @@ dns_cf_rm() { CF_Token="${CF_Token:-$(_readaccountconf_mutable CF_Token)}" CF_Account_ID="${CF_Account_ID:-$(_readaccountconf_mutable CF_Account_ID)}" + CF_Zone_ID="${CF_Zone_ID:-$(_readaccountconf_mutable CF_Zone_ID)}" CF_Key="${CF_Key:-$(_readaccountconf_mutable CF_Key)}" CF_Email="${CF_Email:-$(_readaccountconf_mutable CF_Email)}" From ff9be30f869147428fb70fc08262a53ce8cac7f0 Mon Sep 17 00:00:00 2001 From: Xiaohui Lam Date: Tue, 31 Mar 2020 03:10:12 +0800 Subject: [PATCH 268/357] resolved #2818 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index f5e79ee8..aaab2104 100755 --- a/acme.sh +++ b/acme.sh @@ -4540,7 +4540,7 @@ $_authorizations_map" _savedomainconf "Le_LinkOrder" "$Le_LinkOrder" _link_cert_retry=0 - _MAX_CERT_RETRY=5 + _MAX_CERT_RETRY=30 while [ "$_link_cert_retry" -lt "$_MAX_CERT_RETRY" ]; do if _contains "$response" "\"status\":\"valid\""; then _debug "Order status is valid." From dc697a686279caf6a534dca51d5c9f4ec23e8f3c Mon Sep 17 00:00:00 2001 From: Oliver Burgmaier Date: Wed, 1 Apr 2020 20:24:40 +0200 Subject: [PATCH 269/357] fix #2830 Autorization segment typo fixed This fixes the parsing of the authorization segment in the response of an order. Without this fix the start of the array is not found correctly and therefore the finalize URL is part of the authorization segment. Changing the regex to *\[[^\[]*\] fix this. Seems to be a typo which has not been recognized so far. This can be only recognized if the response is in a single line. --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index aaab2104..937e435c 100755 --- a/acme.sh +++ b/acme.sh @@ -4019,7 +4019,7 @@ issue() { #for dns manual mode _savedomainconf "Le_OrderFinalize" "$Le_OrderFinalize" - _authorizations_seg="$(echo "$response" | _egrep_o '"authorizations" *: *\[[^\]*\]' | cut -d '[' -f 2 | tr -d ']' | tr -d '"')" + _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." From 37d22a144a0f4e6e08941672b3137a2045cf1d17 Mon Sep 17 00:00:00 2001 From: Oliver Burgmaier Date: Wed, 1 Apr 2020 20:31:06 +0200 Subject: [PATCH 270/357] fix #2830 Autorization segment typo fixed This fixes the parsing of the authorization segment in the response of an order. Without this fix the start of the array is not found correctly and therefore the finalize URL is part of the authorization segment. Changing the regex to *\[[^\[]*\] fix this. Seems to be a typo which has not been recognized so far. This can be only recognized if the response is in a single line. --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 937e435c..adf03427 100755 --- a/acme.sh +++ b/acme.sh @@ -4019,7 +4019,7 @@ issue() { #for dns manual mode _savedomainconf "Le_OrderFinalize" "$Le_OrderFinalize" - _authorizations_seg="$(echo "$response" | _egrep_o '"authorizations" *: *\[[^\[]]*\]' | cut -d '[' -f 2 | tr -d ']' | tr -d '"')" + _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." From 7595808d260410177d92cd41df1c1b9c97c2ff00 Mon Sep 17 00:00:00 2001 From: Oliver Burgmaier Date: Wed, 1 Apr 2020 20:35:07 +0200 Subject: [PATCH 271/357] fix #2828 mailto compliant to RFC6068 This fix removes the space between "mailto:" and the email address to make the contact attribute compliant to RFC6068. --- acme.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index adf03427..512d57e8 100755 --- a/acme.sh +++ b/acme.sh @@ -3417,13 +3417,13 @@ _regAccount() { if [ "$ACME_VERSION" = "2" ]; then regjson='{"termsOfServiceAgreed": true}' if [ "$ACCOUNT_EMAIL" ]; then - regjson='{"contact": ["mailto: '$ACCOUNT_EMAIL'"], "termsOfServiceAgreed": true}' + regjson='{"contact": ["mailto:'$ACCOUNT_EMAIL'"], "termsOfServiceAgreed": true}' fi else _reg_res="$ACME_NEW_ACCOUNT_RES" regjson='{"resource": "'$_reg_res'", "terms-of-service-agreed": true, "agreement": "'$ACME_AGREEMENT'"}' if [ "$ACCOUNT_EMAIL" ]; then - regjson='{"resource": "'$_reg_res'", "contact": ["mailto: '$ACCOUNT_EMAIL'"], "terms-of-service-agreed": true, "agreement": "'$ACME_AGREEMENT'"}' + regjson='{"resource": "'$_reg_res'", "contact": ["mailto:'$ACCOUNT_EMAIL'"], "terms-of-service-agreed": true, "agreement": "'$ACME_AGREEMENT'"}' fi fi @@ -3503,7 +3503,7 @@ updateaccount() { if [ "$ACME_VERSION" = "2" ]; then if [ "$ACCOUNT_EMAIL" ]; then - updjson='{"contact": ["mailto: '$ACCOUNT_EMAIL'"]}' + updjson='{"contact": ["mailto:'$ACCOUNT_EMAIL'"]}' fi else # ACMEv1: Updates happen the same way a registration is done. From 47883a94a6af56c39af62e9a8c297b089154e741 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 5 Apr 2020 13:46:02 +0800 Subject: [PATCH 272/357] support auto-comment --- .github/auto-comment.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/auto-comment.yml diff --git a/.github/auto-comment.yml b/.github/auto-comment.yml new file mode 100644 index 00000000..75e6ac5d --- /dev/null +++ b/.github/auto-comment.yml @@ -0,0 +1,18 @@ +# Comment to a new issue. +issuesOpened: > + If this is a bug report, please upgrade to the latest code and try again: + 请先更新到最新版再试: + ```sh + acme.sh --upgrade + ``` + + +pullRequestOpened: > + 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 + From 5530e743827a043f467fc647247c7908432b924f Mon Sep 17 00:00:00 2001 From: aattww <52109748+aattww@users.noreply.github.com> Date: Sun, 5 Apr 2020 21:57:37 +0300 Subject: [PATCH 273/357] Initial release --- dnsapi/dns_joker.sh | 129 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 dnsapi/dns_joker.sh diff --git a/dnsapi/dns_joker.sh b/dnsapi/dns_joker.sh new file mode 100644 index 00000000..14a0e3cf --- /dev/null +++ b/dnsapi/dns_joker.sh @@ -0,0 +1,129 @@ +#!/usr/bin/env sh + +# Joker.com API for acme.sh +# +# This script adds the necessary TXT record to a domain in Joker.com. +# +# You must activate Dynamic DNS in Joker.com DNS configuration first. +# Username and password below refer to Dynamic DNS authentication, +# not your Joker.com login credentials. +# See: https://joker.com/faq/content/11/427/en/what-is-dynamic-dns-dyndns.html +# +# NOTE: This script does not support wildcard certificates, because +# Joker.com API does not support adding two TXT records with the same +# subdomain. Adding the second record will overwrite the first one. +# See: https://joker.com/faq/content/6/496/en/let_s-encrypt-support.html +# "... this request will replace all TXT records for the specified +# label by the provided content" +# +# Author: aattww (https://github.com/aattww/) +# +# JOKER_USERNAME="xxxx" +# JOKER_PASSWORD="xxxx" + +JOKER_API="https://svc.joker.com/nic/replace" + +######## Public functions ##################### + +#Usage: dns_joker_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_joker_add() { + fulldomain=$1 + txtvalue=$2 + + JOKER_USERNAME="${JOKER_USERNAME:-$(_readaccountconf_mutable JOKER_USERNAME)}" + JOKER_PASSWORD="${JOKER_PASSWORD:-$(_readaccountconf_mutable JOKER_PASSWORD)}" + + if [ -z "$JOKER_USERNAME" ] || [ -z "$JOKER_PASSWORD" ]; then + _err "No Joker.com username and password specified." + return 1 + fi + + _saveaccountconf_mutable JOKER_USERNAME "$JOKER_USERNAME" + _saveaccountconf_mutable JOKER_PASSWORD "$JOKER_PASSWORD" + + if ! _get_root "$fulldomain"; then + _err "Invalid domain" + return 1 + fi + + _info "Adding TXT record" + if _joker_rest "username=$JOKER_USERNAME&password=$JOKER_PASSWORD&zone=$_domain&label=$_sub_domain&type=TXT&value=$txtvalue"; then + if _startswith "$response" "OK"; then + _info "Added, OK" + return 0 + fi + fi + _err "Error adding TXT record." + return 1 +} + +#fulldomain txtvalue +dns_joker_rm() { + fulldomain=$1 + txtvalue=$2 + + JOKER_USERNAME="${JOKER_USERNAME:-$(_readaccountconf_mutable JOKER_USERNAME)}" + JOKER_PASSWORD="${JOKER_PASSWORD:-$(_readaccountconf_mutable JOKER_PASSWORD)}" + + if ! _get_root "$fulldomain"; then + _err "Invalid domain" + return 1 + fi + + _info "Removing TXT record" + # TXT record is removed by setting its value to empty. + if _joker_rest "username=$JOKER_USERNAME&password=$JOKER_PASSWORD&zone=$_domain&label=$_sub_domain&type=TXT&value="; then + if _startswith "$response" "OK"; then + _info "Removed, OK" + return 0 + fi + fi + _err "Error removing TXT record." + return 1 +} + +#################### Private functions below ################################## +#_acme-challenge.www.domain.com +#returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +_get_root() { + fulldomain=$1 + i=1 + while true; do + h=$(printf "%s" "$fulldomain" | cut -d . -f $i-100) + _debug h "$h" + if [ -z "$h" ]; then + return 1 + fi + + # Try to remove a test record. With correct root domain, username and password this will return "OK: ..." regardless + # of record in question existing or not. + if _joker_rest "username=$JOKER_USERNAME&password=$JOKER_PASSWORD&zone=$h&label=jokerTXTUpdateTest&type=TXT&value="; then + if _startswith "$response" "OK"; then + _sub_domain="$(echo "$fulldomain" | sed "s/\\.$h\$//")" + _domain=$h + return 0 + fi + fi + + i=$(_math "$i" + 1) + done + + _debug "Root domain not found" + return 1 +} + +_joker_rest() { + data="$1" + _debug data "$data" + + response="$(_post "$data" "$JOKER_API" "" "POST")" + + if [ "$?" != "0" ]; then + _err "Error POSTing" + return 1 + fi + _debug response "$response" + return 0 +} From 8400d1e60ea75bc0ced48ba43ad649135be31121 Mon Sep 17 00:00:00 2001 From: aattww <52109748+aattww@users.noreply.github.com> Date: Sun, 5 Apr 2020 22:07:20 +0300 Subject: [PATCH 274/357] Add bugs report link --- dnsapi/dns_joker.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dnsapi/dns_joker.sh b/dnsapi/dns_joker.sh index 14a0e3cf..e25530c1 100644 --- a/dnsapi/dns_joker.sh +++ b/dnsapi/dns_joker.sh @@ -18,6 +18,8 @@ # # Author: aattww (https://github.com/aattww/) # +# Report bugs to https://github.com/acmesh-official/acme.sh/issues/2840 +# # JOKER_USERNAME="xxxx" # JOKER_PASSWORD="xxxx" From c064b3896a6ab6a24a8d2ff6a9364c42d453850d Mon Sep 17 00:00:00 2001 From: aattww <52109748+aattww@users.noreply.github.com> Date: Mon, 6 Apr 2020 01:13:59 +0300 Subject: [PATCH 275/357] Change command check to fully pass shellcheck --- dnsapi/dns_joker.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dnsapi/dns_joker.sh b/dnsapi/dns_joker.sh index e25530c1..5d50953e 100644 --- a/dnsapi/dns_joker.sh +++ b/dnsapi/dns_joker.sh @@ -120,9 +120,7 @@ _joker_rest() { data="$1" _debug data "$data" - response="$(_post "$data" "$JOKER_API" "" "POST")" - - if [ "$?" != "0" ]; then + if ! response="$(_post "$data" "$JOKER_API" "" "POST")"; then _err "Error POSTing" return 1 fi From 5fac282ee098394ee3cd6eff1975e699bc5ce9b2 Mon Sep 17 00:00:00 2001 From: der-berni Date: Tue, 7 Apr 2020 19:25:39 +0200 Subject: [PATCH 276/357] Update to work with new one.com procedure Since some Months, its no longer possible to add TXT Records with the Name "_acme-challenge" to the base domain. To override the fallback value, you must use a CNAME and proxy it. For example. CNAME _acme-challenge.yourdomain.com => proxy_acme-challenge.yourdomain.com The TXT Records have to be created on proxy_acme-challenge.yourdomain.com Since the default CNAME TTL is 3600 seconds, it is recommended to leave the CNAME record. But if you would like to use the build-in SSL (for your web-site etc.) from one.com, you have to delete the record. A new variable "ONECOM_KeepCnameProxy" you can set in the account.conf is used to keep the CNAME record. By default the CNAME record will be removed. For ex.: SAVED_ONECOM_KeepCnameProxy='1' to keep the CNAME Record and speedup the process. --- dnsapi/dns_one.sh | 189 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 143 insertions(+), 46 deletions(-) diff --git a/dnsapi/dns_one.sh b/dnsapi/dns_one.sh index 0fdc3d5e..4cc159da 100644 --- a/dnsapi/dns_one.sh +++ b/dnsapi/dns_one.sh @@ -5,7 +5,7 @@ # Author: github: @diseq # Created: 2019-02-17 # Fixed by: @der-berni -# Modified: 2019-05-31 +# Modified: 2020-04-07 # # export ONECOM_User="username" # export ONECOM_Password="password" @@ -29,33 +29,46 @@ dns_one_add() { _err "root domain not found" return 1 fi - - mysubdomain=$_sub_domain - mydomain=$_domain - _debug mysubdomain "$mysubdomain" - _debug mydomain "$mydomain" - - # get entries - response="$(_get "https://www.one.com/admin/api/domains/$mydomain/dns/custom_records")" - _debug response "$response" - - # Update the IP address for domain entry - postdata="{\"type\":\"dns_custom_records\",\"attributes\":{\"priority\":0,\"ttl\":600,\"type\":\"TXT\",\"prefix\":\"$mysubdomain\",\"content\":\"$txtvalue\"}}" - _debug postdata "$postdata" - response="$(_post "$postdata" "https://www.one.com/admin/api/domains/$mydomain/dns/custom_records" "" "POST" "application/json")" - response="$(echo "$response" | _normalizeJson)" - _debug response "$response" - - id=$(echo "$response" | sed -n "s/{\"result\":{\"data\":{\"type\":\"dns_custom_records\",\"id\":\"\([^\"]*\)\",\"attributes\":{\"prefix\":\"$mysubdomain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"priority\":0,\"ttl\":600}}},\"metadata\":null}/\1/p") - + + 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" + if [ ! -z "$id" ]; then + _info "$(__green "Txt record with the same value found. Skip adding.")" + return 0 + fi + + _dns_one_addrecord "TXT" "$subdomain" "$txtvalue" if [ -z "$id" ]; then - _err "Add txt record error." + _err "Add CNAME record error." return 1 else - _info "Added, OK ($id)" + _info "$(__green "Added, OK ($id)")" return 0 fi - } dns_one_rm() { @@ -73,36 +86,46 @@ dns_one_rm() { return 1 fi - mysubdomain=$_sub_domain - mydomain=$_domain - _debug mysubdomain "$mysubdomain" - _debug mydomain "$mydomain" - - # get entries - response="$(_get "https://www.one.com/admin/api/domains/$mydomain/dns/custom_records")" - response="$(echo "$response" | _normalizeJson)" - _debug response "$response" - - id=$(printf -- "%s" "$response" | sed -n "s/.*{\"type\":\"dns_custom_records\",\"id\":\"\([^\"]*\)\",\"attributes\":{\"prefix\":\"$mysubdomain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"priority\":0,\"ttl\":600}.*/\1/p") - + 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 [ ! -z "$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" if [ -z "$id" ]; then _err "Txt record not found." return 1 fi - + # delete entry - response="$(_post "$postdata" "https://www.one.com/admin/api/domains/$mydomain/dns/custom_records/$id" "" "DELETE" "application/json")" - response="$(echo "$response" | _normalizeJson)" - _debug response "$response" - - if [ "$response" = '{"result":null,"metadata":null}' ]; then - _info "Removed, OK" - return 0 + + if _dns_one_delrecord "$id"; then + _info "$(__green Removed, OK)" + return 0 else - _err "Removing txt record error." - return 1 + _err "Removing txt record error." + return 1 fi - } #_acme-challenge.www.domain.com @@ -138,6 +161,7 @@ _get_root() { _dns_one_login() { # get credentials + ONECOM_KeepCnameProxy="${ONECOM_KeepCnameProxy:-$(_readaccountconf_mutable ONECOM_KeepCnameProxy)}" ONECOM_User="${ONECOM_User:-$(_readaccountconf_mutable ONECOM_User)}" ONECOM_Password="${ONECOM_Password:-$(_readaccountconf_mutable ONECOM_Password)}" if [ -z "$ONECOM_User" ] || [ -z "$ONECOM_Password" ]; then @@ -177,3 +201,76 @@ _dns_one_login() { return 0 } + +_dns_one_getrecord() { + type="$1" + name="$2" + value="$3" + if [ -z "$type" ]; then + type="TXT" + fi + if [ -z "$name" ]; then + _err "Record name is empty." + return 1 + fi + + response="$(_get "https://www.one.com/admin/api/domains/$maindomain/dns/custom_records")" + response="$(echo "$response" | _normalizeJson)" + _debug response "$response" + + if [ -z "${value}" ]; then + id=$(printf -- "%s" "$response" | sed -n "s/.*{\"type\":\"dns_custom_records\",\"id\":\"\([^\"]*\)\",\"attributes\":{\"prefix\":\"${name}\",\"type\":\"${type}\",\"content\":\"[^\"]*\",\"priority\":0,\"ttl\":600}.*/\1/p") + response=$(printf -- "%s" "$response" | sed -n "s/.*{\"type\":\"dns_custom_records\",\"id\":\"[^\"]*\",\"attributes\":{\"prefix\":\"${name}\",\"type\":\"${type}\",\"content\":\"\([^\"]*\)\",\"priority\":0,\"ttl\":600}.*/\1/p") + else + id=$(printf -- "%s" "$response" | sed -n "s/.*{\"type\":\"dns_custom_records\",\"id\":\"\([^\"]*\)\",\"attributes\":{\"prefix\":\"${name}\",\"type\":\"${type}\",\"content\":\"${value}\",\"priority\":0,\"ttl\":600}.*/\1/p") + fi + if [ -z "$id" ]; then + _err "Record not found." + return 1 + fi + return 0 +} + +_dns_one_addrecord() { + type="$1" + name="$2" + value="$3" + if [ -z "$type" ]; then + type="TXT" + fi + if [ -z "$name" ]; then + _err "Record name is empty." + return 1 + fi + + postdata="{\"type\":\"dns_custom_records\",\"attributes\":{\"priority\":0,\"ttl\":600,\"type\":\"${type}\",\"prefix\":\"${name}\",\"content\":\"${value}\"}}" + _debug postdata "$postdata" + response="$(_post "$postdata" "https://www.one.com/admin/api/domains/$maindomain/dns/custom_records" "" "POST" "application/json")" + response="$(echo "$response" | _normalizeJson)" + _debug response "$response" + + id=$(echo "$response" | sed -n "s/{\"result\":{\"data\":{\"type\":\"dns_custom_records\",\"id\":\"\([^\"]*\)\",\"attributes\":{\"prefix\":\"$subdomain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"priority\":0,\"ttl\":600}}},\"metadata\":null}/\1/p") + + if [ -z "$id" ]; then + return 1 + else + return 0 + fi +} + +_dns_one_delrecord() { + id="$1" + if [ -z "$id" ]; then + return 1 + fi + + response="$(_post "" "https://www.one.com/admin/api/domains/$maindomain/dns/custom_records/$id" "" "DELETE" "application/json")" + response="$(echo "$response" | _normalizeJson)" + _debug response "$response" + + if [ "$response" = '{"result":null,"metadata":null}' ]; then + return 0 + else + return 1 + fi +} From 62378d063e9592837f33a9bf50fdab334569d63a Mon Sep 17 00:00:00 2001 From: Wout Date: Tue, 7 Apr 2020 22:34:05 +0200 Subject: [PATCH 277/357] Fixes getting the correct domain id using Contellix API. --- 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 c47ede44..2eb266b7 100644 --- a/dnsapi/dns_constellix.sh +++ b/dnsapi/dns_constellix.sh @@ -86,12 +86,12 @@ _get_root() { return 1 fi - if ! _constellix_rest GET "domains"; then + if ! _constellix_rest GET "domains/search?name=$h"; then return 1 fi if _contains "$response" "\"name\":\"$h\""; then - _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*" | head -n 1 | cut -d ':' -f 2 | tr -d '}') + _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 da7b1fb014ceb1791bff30f65967c3aa1af491e4 Mon Sep 17 00:00:00 2001 From: der-berni Date: Thu, 9 Apr 2020 12:17:08 +0200 Subject: [PATCH 278/357] cleanup according to styleguide / ShellCheck --- dnsapi/dns_one.sh | 87 ++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 42 deletions(-) diff --git a/dnsapi/dns_one.sh b/dnsapi/dns_one.sh index 4cc159da..96ef5969 100644 --- a/dnsapi/dns_one.sh +++ b/dnsapi/dns_one.sh @@ -6,7 +6,10 @@ # 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" # @@ -29,41 +32,41 @@ dns_one_add() { _err "root domain not found" return 1 fi - + 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" - if [ ! -z "$id" ]; then + if [ -n "$id" ]; then _info "$(__green "Txt record with the same value found. Skip adding.")" return 0 fi - + _dns_one_addrecord "TXT" "$subdomain" "$txtvalue" if [ -z "$id" ]; then - _err "Add CNAME record error." + _err "Add TXT record error." return 1 else _info "$(__green "Added, OK ($id)")" @@ -88,43 +91,42 @@ 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 [ ! -z "$id" ]; then - _info "$(__red "Removing CNAME Proxy record: '$(__green "\"$_sub_domain\" => \"$subdomain.$maindomain\"")'")" - _dns_one_delrecord "$id" - fi + 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" if [ -z "$id" ]; then _err "Txt record not found." return 1 fi - + # delete entry - if _dns_one_delrecord "$id"; then - _info "$(__green Removed, OK)" - return 0 + _info "$(__green Removed, OK)" + return 0 else - _err "Removing txt record error." - return 1 + _err "Removing txt record error." + return 1 fi } @@ -162,6 +164,7 @@ _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 @@ -173,6 +176,7 @@ _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" @@ -207,17 +211,17 @@ _dns_one_getrecord() { name="$2" value="$3" if [ -z "$type" ]; then - type="TXT" + type="TXT" fi if [ -z "$name" ]; then - _err "Record name is empty." - return 1 + _err "Record name is empty." + return 1 fi - + response="$(_get "https://www.one.com/admin/api/domains/$maindomain/dns/custom_records")" response="$(echo "$response" | _normalizeJson)" _debug response "$response" - + if [ -z "${value}" ]; then id=$(printf -- "%s" "$response" | sed -n "s/.*{\"type\":\"dns_custom_records\",\"id\":\"\([^\"]*\)\",\"attributes\":{\"prefix\":\"${name}\",\"type\":\"${type}\",\"content\":\"[^\"]*\",\"priority\":0,\"ttl\":600}.*/\1/p") response=$(printf -- "%s" "$response" | sed -n "s/.*{\"type\":\"dns_custom_records\",\"id\":\"[^\"]*\",\"attributes\":{\"prefix\":\"${name}\",\"type\":\"${type}\",\"content\":\"\([^\"]*\)\",\"priority\":0,\"ttl\":600}.*/\1/p") @@ -225,7 +229,6 @@ _dns_one_getrecord() { id=$(printf -- "%s" "$response" | sed -n "s/.*{\"type\":\"dns_custom_records\",\"id\":\"\([^\"]*\)\",\"attributes\":{\"prefix\":\"${name}\",\"type\":\"${type}\",\"content\":\"${value}\",\"priority\":0,\"ttl\":600}.*/\1/p") fi if [ -z "$id" ]; then - _err "Record not found." return 1 fi return 0 @@ -236,13 +239,13 @@ _dns_one_addrecord() { name="$2" value="$3" if [ -z "$type" ]; then - type="TXT" + type="TXT" fi if [ -z "$name" ]; then - _err "Record name is empty." - return 1 + _err "Record name is empty." + return 1 fi - + postdata="{\"type\":\"dns_custom_records\",\"attributes\":{\"priority\":0,\"ttl\":600,\"type\":\"${type}\",\"prefix\":\"${name}\",\"content\":\"${value}\"}}" _debug postdata "$postdata" response="$(_post "$postdata" "https://www.one.com/admin/api/domains/$maindomain/dns/custom_records" "" "POST" "application/json")" @@ -261,16 +264,16 @@ _dns_one_addrecord() { _dns_one_delrecord() { id="$1" if [ -z "$id" ]; then - return 1 + return 1 fi - + response="$(_post "" "https://www.one.com/admin/api/domains/$maindomain/dns/custom_records/$id" "" "DELETE" "application/json")" response="$(echo "$response" | _normalizeJson)" _debug response "$response" if [ "$response" = '{"result":null,"metadata":null}' ]; then - return 0 + return 0 else - return 1 + return 1 fi } From e158b5ccf65848233dd00c7fbafcf41f87a68a18 Mon Sep 17 00:00:00 2001 From: Wout Date: Thu, 9 Apr 2020 19:15:32 +0200 Subject: [PATCH 279/357] Constellix made changes to their API. They added more search capabilities, but the changes are not backwards compatible. We need to use the `exact` parameter instead of `name` now. --- 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 2eb266b7..42df710d 100644 --- a/dnsapi/dns_constellix.sh +++ b/dnsapi/dns_constellix.sh @@ -86,7 +86,7 @@ _get_root() { return 1 fi - if ! _constellix_rest GET "domains/search?name=$h"; then + if ! _constellix_rest GET "domains/search?exact=$h"; then return 1 fi From eef9a60037cc9771a43074f1f6bf855c5850113d Mon Sep 17 00:00:00 2001 From: Adrian Fedoreanu Date: Fri, 10 Apr 2020 23:25:28 +0200 Subject: [PATCH 280/357] add dns_1984hosting dns api --- dnsapi/dns_1984hosting.sh | 254 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100755 dnsapi/dns_1984hosting.sh diff --git a/dnsapi/dns_1984hosting.sh b/dnsapi/dns_1984hosting.sh new file mode 100755 index 00000000..b7cb36d7 --- /dev/null +++ b/dnsapi/dns_1984hosting.sh @@ -0,0 +1,254 @@ +#!/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. +# +#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 ##################### + +# 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. + +#Usage: dns_1984hosting_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_1984hosting_add() { + fulldomain=$1 + txtvalue=$2 + + _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" + return 1 + fi + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" "$fulldomain" + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _1984hosting_add_txt_record "$_domain" "$_sub_domain" "$txtvalue" + return $? +} + +#Usage: fulldomain txtvalue +#Remove the txt record after validation. +dns_1984hosting_rm() { + fulldomain=$1 + txtvalue=$2 + + _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" + return 1 + fi + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" "$fulldomain" + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _1984hosting_delete_txt_record "$_domain" "$_sub_domain" + return $? +} + +#################### Private functions below ################################## + +# usage _1984hosting_add_txt_record domain subdomain value +# returns 0 success +_1984hosting_add_txt_record() { + _debug "Add TXT record $1 with value '$3'" + domain="$1" + subdomain="$2" + value="$(printf '%s' "$3" | _url_encode)" + url="https://management.1984hosting.com/domains/entry/" + + postdata="entry=new" + postdata="$postdata&type=TXT" + postdata="$postdata&ttl=3600" + postdata="$postdata&zone=$domain" + postdata="$postdata&host=$subdomain" + postdata="$postdata&rdata=%22$value%22" + _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 $subdomain bad RC from _post" + return 1 + elif _contains "$response" ""; then + _err "1984Hosting failed to add TXT record for $subdomain. Check $HTTP_HEADER file" + return 1 + elif [ "$response" = '{"auth": false, "ok": false}' ]; then + _err "1984Hosting failed to add TXT record for $subdomain. Invalid or expired cookie" + return 1 + fi + + _info "Added acme challenge TXT record for $fulldomain at 1984Hosting" + return 0 +} + +# usage _1984hosting_delete_txt_record entry_id +# returns 0 success +_1984hosting_delete_txt_record() { + _debug "Delete $fulldomain TXT record" + domain="$1" + subdomain="$2" + url="https://management.1984hosting.com/domains" + + _htmlget "$url" "$domain" + _debug2 _response "$_response" + zone_id="$(echo "$_response" | _egrep_o 'zone\/[0-9]+')" + _debug2 zone_id "$zone_id" + if [ -z "$zone_id" ]; then + _err "Error getting zone_id for $1" + return 1 + fi + + _htmlget "$url/$zone_id" "$subdomain" + _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" + 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" + return 1 + fi + + _info "Deleted acme challenge TXT record for $fulldomain at 1984Hosting" + return 0 +} + +# usage: _1984hosting_login username password +# returns 0 success +_1984hosting_login() { + if ! _check_credentials; then return 1; fi + + if _check_cookie; then + _debug "Already logged in" + return 0 + fi + + _debug "Login to 1984Hosting as user $One984HOSTING_Username" + username=$(printf '%s' "$One984HOSTING_Username" | _url_encode) + password=$(printf '%s' "$One984HOSTING_Password" | _url_encode) + url="https://management.1984hosting.com/accounts/checkuserauth/" + + response="$(_post "username=$username&password=$password&otpkey=" "$url")" + response="$(echo "$response" | _normalizeJson)" + _debug2 response "$response" + + if [ "$response" = '{"loggedin": true, "ok": true}' ]; then + One984HOSTING_COOKIE="$(grep '^Set-Cookie:' "$HTTP_HEADER" | _tail_n 1 | _egrep_o 'sessionid=[^;]*;' | tr -d ';')" + export One984HOSTING_COOKIE + _saveaccountconf_mutable One984HOSTING_COOKIE "$One984HOSTING_COOKIE" + return 0 + fi + return 1 +} + +_check_credentials() { + if [ -z "$One984HOSTING_Username" ] || [ -z "$One984HOSTING_Password" ]; then + One984HOSTING_Username="" + 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 + fi + return 0 +} + +_check_cookie() { + One984HOSTING_COOKIE="${One984HOSTING_COOKIE:-$(_readaccountconf_mutable One984HOSTING_COOKIE)}" + if [ -z "$One984HOSTING_COOKIE" ]; then + _debug "No cached cookie found" + return 1 + fi + + _authget "https://management.1984hosting.com/accounts/loginstatus/" + response="$(echo "$_response" | _normalizeJson)" + if [ "$_response" = '{"ok": true}' ]; then + _debug "Cached cookie still valid" + return 0 + fi + _debug "Cached cookie no longer valid" + One984HOSTING_COOKIE="" + _saveaccountconf_mutable One984HOSTING_COOKIE "$One984HOSTING_COOKIE" + return 1 +} + +#_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 + + _authget "https://management.1984hosting.com/domains/soacheck/?zone=$h&nameserver=ns0.1984.is." + if _contains "$_response" "serial"; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain="$h" + return 0 + fi + p=$i + i=$(_math "$i" + 1) + done + return 1 +} + +# add extra headers to request +_authget() { + export _H1="Cookie: $One984HOSTING_COOKIE" + _response=$(_get "$1") +} + +# truncate huge HTML response +# echo: Argument list too long +_htmlget() { + export _H1="Cookie: $One984HOSTING_COOKIE" + _response=$(_get "$1" | grep "$2" | _head_n 1) +} + +# add extra headers to request +_authpost() { + export _H1="Cookie: $One984HOSTING_COOKIE" + _response=$(_post "$1" "$2") +} From 52a16c917f3f28d7a83e0ac368c62b28aa99174c Mon Sep 17 00:00:00 2001 From: Scott Wiersdorf Date: Sat, 11 Apr 2020 11:24:30 -0600 Subject: [PATCH 281/357] show response when unable to retrieve DNS records for a zone --- dnsapi/dns_cf.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_cf.sh b/dnsapi/dns_cf.sh index 040934e2..43bc1428 100755 --- a/dnsapi/dns_cf.sh +++ b/dnsapi/dns_cf.sh @@ -111,7 +111,7 @@ dns_cf_rm() { _cf_rest GET "zones/${_domain_id}/dns_records?type=TXT&name=$fulldomain&content=$txtvalue" if ! printf "%s" "$response" | grep \"success\":true >/dev/null; then - _err "Error" + _err "Error: $response" return 1 fi From a57ba3d81ca3986fd405a38b22c9d7ec23f10dcd Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 12 Apr 2020 10:38:31 +0800 Subject: [PATCH 282/357] update comments --- .github/auto-comment.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/auto-comment.yml b/.github/auto-comment.yml index 75e6ac5d..3ef3d9e4 100644 --- a/.github/auto-comment.yml +++ b/.github/auto-comment.yml @@ -1,13 +1,17 @@ # Comment to a new issue. issuesOpened: > If this is a bug report, please upgrade to the latest code and try again: - 请先更新到最新版再试: + + 如果有 bug, 请先更新到最新版试试: + ```sh acme.sh --upgrade ``` 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 @@ -16,3 +20,5 @@ pullRequestOpened: > Then add your usage here: https://github.com/acmesh-official/acme.sh/wiki/dnsapi + + From 5ace44493a8f6691c39f2143f8fbc2227cff9618 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 12 Apr 2020 10:47:41 +0800 Subject: [PATCH 283/357] fix comments --- .github/auto-comment.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/auto-comment.yml b/.github/auto-comment.yml index 3ef3d9e4..1e7b389e 100644 --- a/.github/auto-comment.yml +++ b/.github/auto-comment.yml @@ -7,6 +7,10 @@ issuesOpened: > ```sh acme.sh --upgrade ``` + + please also provide the log with `--debug 2`. + + see: https://github.com/acmesh-official/acme.sh/wiki/How-to-debug-acme.sh pullRequestOpened: > From 93de1e4903a975efa45da8fecbc819559e89ded7 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 12 Apr 2020 11:48:24 +0800 Subject: [PATCH 284/357] un-escape json chars fix https://github.com/acmesh-official/acme.sh/issues/2833 --- acme.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 512d57e8..f672710d 100755 --- a/acme.sh +++ b/acme.sh @@ -846,6 +846,14 @@ _json_encode() { echo "$_j_str" | _hex_dump | _lower_case | sed 's/0a/5c 6e/g' | tr -d ' ' | _h2b | tr -d "\r\n" } +#from: http:\/\/ to http:// +_json_decode() { + _j_str="$(sed 's#\\/#/#g')" + _debug3 "_json_decode" + _debug3 "_j_str" "$_j_str" + echo "$_j_str" +} + #options file _sed_i() { options="$1" @@ -4019,7 +4027,7 @@ issue() { #for dns manual mode _savedomainconf "Le_OrderFinalize" "$Le_OrderFinalize" - _authorizations_seg="$(echo "$response" | _egrep_o '"authorizations" *: *\[[^\[]*\]' | cut -d '[' -f 2 | tr -d ']' | tr -d '"')" + _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." From 4dfdfa0b7db773cc46d12c1ff107ee50fef2fb4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=96=B5=E5=96=B5=E5=9B=9B?= Date: Sun, 12 Apr 2020 12:28:07 +0800 Subject: [PATCH 285/357] Fix typo on line 27 --- dnsapi/dns_he.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index caa4d2c4..5829e00e 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -24,7 +24,7 @@ dns_he_add() { if [ -z "$HE_Username" ] || [ -z "$HE_Password" ]; then HE_Username= HE_Password= - _err "No auth details provided. Please set user credentials using the \$HE_Username and \$HE_Password envoronment variables." + _err "No auth details provided. Please set user credentials using the \$HE_Username and \$HE_Password environment variables." return 1 fi _saveaccountconf_mutable HE_Username "$HE_Username" From 2c971a25985049c928597da57e636b5487d19abf Mon Sep 17 00:00:00 2001 From: mod242 <40213799+mod242@users.noreply.github.com> Date: Thu, 16 Apr 2020 20:03:34 +0200 Subject: [PATCH 286/357] Filter out blank lines Response from the provider has changed so that there are blank lines at the end, which leads to the result can not be parsed correctly --- dnsapi/dns_ddnss.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_ddnss.sh b/dnsapi/dns_ddnss.sh index 53781d0d..ecc4f174 100644 --- a/dnsapi/dns_ddnss.sh +++ b/dnsapi/dns_ddnss.sh @@ -119,7 +119,7 @@ _ddnss_rest() { # DDNSS uses GET to update domain info if [ "$method" = "GET" ]; then - response="$(_get "$url" | sed 's/<[a-zA-Z\/][^>]*>//g' | _tail_n 1)" + response="$(_get "$url" | sed 's/<[a-zA-Z\/][^>]*>//g' | tr -s "\n" | _tail_n 1)" else _err "Unsupported method" return 1 From 2febdfc3636614a226e00fe27a419baa8ffe9d6c Mon Sep 17 00:00:00 2001 From: Simon Wydooghe Date: Fri, 17 Apr 2020 15:53:15 +0200 Subject: [PATCH 287/357] Fix: allow removal of email address as contact It seems the current code doesn't allow for removing the email address from the contact field. This fixes that. This only removes the email address if an explicit empty email address is specified on the command line or in the account.conf file. If it is left unspecified on the command line it still just uses whatever was configured in the account.conf. --- acme.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/acme.sh b/acme.sh index f672710d..763d8a1c 100755 --- a/acme.sh +++ b/acme.sh @@ -3512,6 +3512,8 @@ updateaccount() { if [ "$ACME_VERSION" = "2" ]; then if [ "$ACCOUNT_EMAIL" ]; then updjson='{"contact": ["mailto:'$ACCOUNT_EMAIL'"]}' + else + updjson='{"contact": []}' fi else # ACMEv1: Updates happen the same way a registration is done. From d842ccb287588de346c40bcc26c531e0b183e4bb Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 18 Apr 2020 18:51:08 +0800 Subject: [PATCH 288/357] fix format error --- dnsapi/dns_arvan.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_arvan.sh b/dnsapi/dns_arvan.sh index 341c8c17..edeb56ca 100644 --- a/dnsapi/dns_arvan.sh +++ b/dnsapi/dns_arvan.sh @@ -8,7 +8,7 @@ ARVAN_API_URL="https://napi.arvancloud.com/cdn/4.0/domains" #Report Bugs here: https://github.com/Neilpang/acme.sh # ######## Public functions ##################### - + #Usage: dns_arvan_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_arvan_add() { fulldomain=$1 @@ -22,7 +22,7 @@ dns_arvan_add() { _err "You can get yours from here https://npanel.arvancloud.com/profile/api-keys" return 1 fi - #save the api token to the account conf file. + #save the api token to the account conf file. _saveaccountconf_mutable Arvan_Token "$Arvan_Token" _debug "First detect the root zone" @@ -150,7 +150,7 @@ _arvan_rest() { export _H1="Authorization: $token_trimmed" if [ "$mtd" = "DELETE" ]; then - # DELETE Request shouldn't have Content-Type + #DELETE Request shouldn't have Content-Type _debug data "$data" response="$(_post "$data" "$ARVAN_API_URL/$ep" "" "$mtd")" elif [ "$mtd" = "POST" ]; then @@ -160,4 +160,4 @@ _arvan_rest() { else response="$(_get "$ARVAN_API_URL/$ep$data")" fi -} \ No newline at end of file +} From ed7a945261c96d8b721a53c10fd9eaf00ce54182 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 18 Apr 2020 18:59:33 +0800 Subject: [PATCH 289/357] add comment message. --- .github/auto-comment.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/auto-comment.yml b/.github/auto-comment.yml index 1e7b389e..1c3b746e 100644 --- a/.github/auto-comment.yml +++ b/.github/auto-comment.yml @@ -10,8 +10,14 @@ issuesOpened: > 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. From 1564742b76d2e3d20d7c55411d008aaa4cbef402 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 18 Apr 2020 19:38:38 +0800 Subject: [PATCH 290/357] add comments --- .github/auto-comment.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/auto-comment.yml b/.github/auto-comment.yml index 1c3b746e..520b3ce3 100644 --- a/.github/auto-comment.yml +++ b/.github/auto-comment.yml @@ -4,7 +4,7 @@ issuesOpened: > 如果有 bug, 请先更新到最新版试试: - ```sh + ``` acme.sh --upgrade ``` @@ -17,10 +17,10 @@ issuesOpened: > 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. + 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 @@ -29,6 +29,12 @@ pullRequestOpened: > 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 1041c9f9fc50eb6aa29de5b882dc7244e9f4024d Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 18 Apr 2020 20:03:48 +0800 Subject: [PATCH 291/357] support revoke reason. https://github.com/acmesh-official/acme.sh/issues/2856 --- acme.sh | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index 763d8a1c..18c8e007 100755 --- a/acme.sh +++ b/acme.sh @@ -138,6 +138,8 @@ _NOTIFY_WIKI="https://github.com/acmesh-official/acme.sh/wiki/notify" _SUDO_WIKI="https://github.com/acmesh-official/acme.sh/wiki/sudo" +_REVOKE_WIKI="https://github.com/acmesh-official/acme.sh/wiki/revokecert" + _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" @@ -5456,6 +5458,7 @@ uninstallcronjob() { } +#domain isECC revokeReason revoke() { Le_Domain="$1" if [ -z "$Le_Domain" ]; then @@ -5464,7 +5467,10 @@ revoke() { fi _isEcc="$2" - + _reason="$3" + if [ -z "$_reason" ]; then + _reason="0" + fi _initpath "$Le_Domain" "$_isEcc" if [ ! -f "$DOMAIN_CONF" ]; then _err "$Le_Domain is not a issued domain, skip." @@ -5486,7 +5492,7 @@ revoke() { _initAPI if [ "$ACME_VERSION" = "2" ]; then - data="{\"certificate\": \"$cert\"}" + data="{\"certificate\": \"$cert\",\"reason\":$_reason}" else data="{\"resource\": \"revoke-cert\", \"certificate\": \"$cert\"}" fi @@ -6295,6 +6301,7 @@ Parameters: 0: Bulk mode. Send all the domain's notifications in one message(mail). 1: Cert mode. Send a message for every single cert. --notify-hook [hookname] Set the notify hook + --revoke-reason [0-10] The reason for '--revoke' command. See: $_REVOKE_WIKI " } @@ -6470,6 +6477,7 @@ _process() { _notify_hook="" _notify_level="" _notify_mode="" + _revoke_reason="" while [ ${#} -gt 0 ]; do case "${1}" in @@ -6941,6 +6949,14 @@ _process() { fi _notify_mode="$_nmode" shift + ;; + --revoke-reason) + _revoke_reason="$2" + if _startswith "$_revoke_reason" "-"; then + _err "'$_revoke_reason' is not a integer for '$1'" + return 1 + fi + shift ;; *) _err "Unknown parameter : $1" @@ -7029,7 +7045,7 @@ _process() { renewAll "$_stopRenewOnError" ;; revoke) - revoke "$_domain" "$_ecc" + revoke "$_domain" "$_ecc" "$_revoke_reason" ;; remove) remove "$_domain" "$_ecc" From a995333081876b7f9a06e2c824ed1127d784ebaf Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 18 Apr 2020 22:34:32 +0800 Subject: [PATCH 292/357] fix format --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 18c8e007..57f45905 100755 --- a/acme.sh +++ b/acme.sh @@ -6950,7 +6950,7 @@ _process() { _notify_mode="$_nmode" shift ;; - --revoke-reason) + --revoke-reason) _revoke_reason="$2" if _startswith "$_revoke_reason" "-"; then _err "'$_revoke_reason' is not a integer for '$1'" From 08cc7587ab8042caf4ddab9e4d6910a62797c2ea Mon Sep 17 00:00:00 2001 From: Wolfram Webers Date: Sat, 18 Apr 2020 18:11:24 +0200 Subject: [PATCH 293/357] - Adding fix for latest "os-bind" plugin --- dnsapi/dns_opnsense.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_opnsense.sh b/dnsapi/dns_opnsense.sh index b2a3746f..ec7d2277 100755 --- a/dnsapi/dns_opnsense.sh +++ b/dnsapi/dns_opnsense.sh @@ -150,7 +150,7 @@ _get_root() { return 1 fi _debug h "$h" - id=$(echo "$_domain_response" | _egrep_o "\"[^\"]*\":{\"enabled\":\"1\",\"type\":{\"master\":{\"value\":\"master\",\"selected\":1},\"slave\":{\"value\":\"slave\",\"selected\":0}},\"masterip\":\"[^\"]*\",\"domainname\":\"${h}\"" | cut -d ':' -f 1 | cut -d '"' -f 2) + id=$(echo "$_domain_response" | _egrep_o "\"[^\"]*\":{\"enabled\":\"1\",\"type\":{\"master\":{\"value\":\"master\",\"selected\":1},\"slave\":{\"value\":\"slave\",\"selected\":0}},\"masterip\":\"[^\"]*\",\"allownotifyslave\":{\"\":{[^}]*}},\"domainname\":\"${h}\"" | cut -d ':' -f 1 | cut -d '"' -f 2) if [ -n "$id" ]; then _debug id "$id" From 3bad815982841302a9d55d073fff9d69937cf1ab Mon Sep 17 00:00:00 2001 From: Nils Sandmann Date: Sat, 18 Apr 2020 18:52:08 +0200 Subject: [PATCH 294/357] Better error handling on login, return correct return code --- dnsapi/dns_inwx.sh | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_inwx.sh b/dnsapi/dns_inwx.sh index 7c08d72e..4995ca1d 100755 --- a/dnsapi/dns_inwx.sh +++ b/dnsapi/dns_inwx.sh @@ -148,17 +148,21 @@ _inwx_login() { - ' $INWX_User $INWX_Password) + ' "$INWX_User" "$INWX_Password") response="$(_post "$xml_content" "$INWX_Api" "" "POST")" _H1=$(printf "Cookie: %s" "$(grep "domrobot=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'domrobot=[^;]*;' | tr -d ';')") export _H1 + if ! _contains "$response" "code1000"; then + _err "INWX API: Authentication error (username/password correct?)" + return 1 + fi + #https://github.com/inwx/php-client/blob/master/INWX/Domrobot.php#L71 - if _contains "$response" "code1000" \ - && _contains "$response" "tfaGOOGLE-AUTH"; then + if _contains "$response" "tfaGOOGLE-AUTH"; then if [ -z "$INWX_Shared_Secret" ]; then - _err "Mobile TAN detected." + _err "INWX API: Mobile TAN detected." _err "Please define a shared secret." return 1 fi @@ -191,6 +195,11 @@ _inwx_login() { ' "$tan") response="$(_post "$xml_content" "$INWX_Api" "" "POST")" + + if ! _contains "$response" "code1000"; then + _err "INWX API: Mobile TAN not correct." + return 1 + fi fi } From 5d00edc896dfbd09d961ea6f76843cf7c18b6083 Mon Sep 17 00:00:00 2001 From: Nils Sandmann Date: Sat, 18 Apr 2020 18:54:43 +0200 Subject: [PATCH 295/357] Fix multiple domains with 2FA, reuse session cookie --- dnsapi/dns_inwx.sh | 50 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_inwx.sh b/dnsapi/dns_inwx.sh index 4995ca1d..50b4b10c 100755 --- a/dnsapi/dns_inwx.sh +++ b/dnsapi/dns_inwx.sh @@ -34,6 +34,10 @@ dns_inwx_add() { _saveaccountconf_mutable INWX_Password "$INWX_Password" _saveaccountconf_mutable INWX_Shared_Secret "$INWX_Shared_Secret" + if ! _inwx_login; then + return 1 + fi + _debug "First detect the root zone" if ! _get_root "$fulldomain"; then _err "invalid domain" @@ -64,6 +68,10 @@ dns_inwx_rm() { return 1 fi + if ! _inwx_login; then + return 1 + fi + _debug "First detect the root zone" if ! _get_root "$fulldomain"; then _err "invalid domain" @@ -123,8 +131,42 @@ dns_inwx_rm() { #################### Private functions below ################################## +_inwx_check_cookie() { + INWX_Cookie="${INWX_Cookie:-$(_readaccountconf_mutable INWX_Cookie)}" + if [ -z "$INWX_Cookie" ]; then + _debug "No cached cookie found" + return 1 + fi + _H1="$INWX_Cookie" + export _H1 + + xml_content=$(printf ' + + account.info + ') + + response="$(_post "$xml_content" "$INWX_Api" "" "POST")" + + if _contains "$response" "code1000"; then + _debug "Cached cookie still valid" + return 0 + fi + + _debug "Cached cookie no longer valid" + _H1="" + export _H1 + INWX_Cookie="" + _saveaccountconf_mutable INWX_Cookie "$INWX_Cookie" + return 1 +} + _inwx_login() { + if _inwx_check_cookie; then + _debug "Already logged in" + return 0 + fi + xml_content=$(printf ' account.login @@ -151,8 +193,12 @@ _inwx_login() { ' "$INWX_User" "$INWX_Password") response="$(_post "$xml_content" "$INWX_Api" "" "POST")" - _H1=$(printf "Cookie: %s" "$(grep "domrobot=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'domrobot=[^;]*;' | tr -d ';')") + + INWX_Cookie=$(printf "Cookie: %s" "$(grep "domrobot=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'domrobot=[^;]*;' | tr -d ';')") + _H1=$INWX_Cookie export _H1 + export INWX_Cookie + _saveaccountconf_mutable INWX_Cookie "$INWX_Cookie" if ! _contains "$response" "code1000"; then _err "INWX API: Authentication error (username/password correct?)" @@ -212,8 +258,6 @@ _get_root() { i=2 p=1 - _inwx_login - xml_content=' nameserver.list From a9c4b8dd1a294cfd385a8cc5dd3ea47b3e98156b Mon Sep 17 00:00:00 2001 From: Honza Hommer Date: Sun, 19 Apr 2020 00:44:48 +0200 Subject: [PATCH 296/357] feat: Microsoft Teams notify --- notify/teams.sh | 79 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 notify/teams.sh diff --git a/notify/teams.sh b/notify/teams.sh new file mode 100644 index 00000000..752c24c6 --- /dev/null +++ b/notify/teams.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env sh + +#Support Microsoft Teams webhooks + +#TEAMS_WEBHOOK_URL="" +#TEAMS_THEME_COLOR="" +#TEAMS_SUCCESS_COLOR="" +#TEAMS_ERROR_COLOR="" +#TEAMS_SKIP_COLOR="" + +teams_send() { + _subject="$1" + _content="$2" + _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped + _debug "_statusCode" "$_statusCode" + + TEAMS_WEBHOOK_URL="${TEAMS_WEBHOOK_URL:-$(_readaccountconf_mutable TEAMS_WEBHOOK_URL)}" + if [ -z "$TEAMS_WEBHOOK_URL" ]; then + TEAMS_WEBHOOK_URL="" + _err "You didn't specify a Microsoft Teams webhook url TEAMS_WEBHOOK_URL yet." + return 1 + fi + _saveaccountconf_mutable TEAMS_WEBHOOK_URL "$TEAMS_WEBHOOK_URL" + + TEAMS_THEME_COLOR="${TEAMS_THEME_COLOR:-$(_readaccountconf_mutable TEAMS_THEME_COLOR)}" + if [ -n "$TEAMS_THEME_COLOR" ]; then + _saveaccountconf_mutable TEAMS_THEME_COLOR "$TEAMS_THEME_COLOR" + fi + + TEAMS_SUCCESS_COLOR="${TEAMS_SUCCESS_COLOR:-$(_readaccountconf_mutable TEAMS_SUCCESS_COLOR)}" + if [ -n "$TEAMS_SUCCESS_COLOR" ]; then + _saveaccountconf_mutable TEAMS_SUCCESS_COLOR "$TEAMS_SUCCESS_COLOR" + fi + + TEAMS_ERROR_COLOR="${TEAMS_ERROR_COLOR:-$(_readaccountconf_mutable TEAMS_ERROR_COLOR)}" + if [ -n "$TEAMS_ERROR_COLOR" ]; then + _saveaccountconf_mutable TEAMS_ERROR_COLOR "$TEAMS_ERROR_COLOR" + fi + + TEAMS_SKIP_COLOR="${TEAMS_SKIP_COLOR:-$(_readaccountconf_mutable TEAMS_SKIP_COLOR)}" + if [ -n "$TEAMS_SKIP_COLOR" ]; then + _saveaccountconf_mutable TEAMS_SKIP_COLOR "$TEAMS_SKIP_COLOR" + fi + + export _H1="Content-Type: application/json" + + _subject=$(echo "$_subject" | _json_encode) + _content=$(echo "$_content" | _json_encode) + + case "$_statusCode" in + 0) + _color="$TEAMS_SUCCESS_COLOR" + ;; + 1) + _color="$TEAMS_ERROR_COLOR" + ;; + 2) + _color="$TEAMS_SKIP_COLOR" + ;; + esac + _color="$(echo "${_color:-$TEAMS_THEME_COLOR}" | tr -cd '[:xdigit:]')" + + _data="{\"title\": \"$_subject\"," + if [ -n "$_color" ]; then + _data="$_data\"themeColor\": \"$_color\", " + fi + _data="$_data\"text\": \"$_content\"}" + + if _post "$_data" "$TEAMS_WEBHOOK_URL"; then + # shellcheck disable=SC2154 + if ! _contains "$response" error; then + _info "teams send success." + return 0 + fi + fi + _err "teams send error." + _err "$response" + return 1 +} From 74cdcde4496b17c6cc0a55d98592ce954b875b54 Mon Sep 17 00:00:00 2001 From: Honza Hommer Date: Sun, 19 Apr 2020 23:59:35 +0200 Subject: [PATCH 297/357] fix: remove :xdigit: --- notify/teams.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notify/teams.sh b/notify/teams.sh index 752c24c6..d1de1c57 100644 --- a/notify/teams.sh +++ b/notify/teams.sh @@ -58,7 +58,7 @@ teams_send() { _color="$TEAMS_SKIP_COLOR" ;; esac - _color="$(echo "${_color:-$TEAMS_THEME_COLOR}" | tr -cd '[:xdigit:]')" + _color="$(echo "${_color:-$TEAMS_THEME_COLOR}" | tr -cd 'a-fA-F0-9')" _data="{\"title\": \"$_subject\"," if [ -n "$_color" ]; then From 9bad11ec79e23cf617b9b07c91537a3f7962c4d4 Mon Sep 17 00:00:00 2001 From: wurzelpanzer <32928046+wurzelpanzer@users.noreply.github.com> Date: Mon, 20 Apr 2020 08:49:08 +0200 Subject: [PATCH 298/357] easyDNS API out of beta Added new links to API docs and API access signup --- dnsapi/dns_easydns.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_easydns.sh b/dnsapi/dns_easydns.sh index ca8faab2..f466f1e2 100644 --- a/dnsapi/dns_easydns.sh +++ b/dnsapi/dns_easydns.sh @@ -4,8 +4,7 @@ # # easyDNS REST API for acme.sh by Neilpang based on dns_cf.sh # -# Please note: # API is currently beta and subject to constant change -# http://sandbox.rest.easydns.net:3000/ +# API Documentation: https://sandbox.rest.easydns.net:3001/ # # Author: wurzelpanzer [wurzelpanzer@maximolider.net] # Report Bugs here: https://github.com/acmesh-official/acme.sh/issues/2647 @@ -25,7 +24,7 @@ dns_easydns_add() { EASYDNS_Key="${EASYDNS_Key:-$(_readaccountconf_mutable EASYDNS_Key)}" if [ -z "$EASYDNS_Token" ] || [ -z "$EASYDNS_Key" ]; then - _err "You didn't specify an easydns.net token or api key. Please sign up at http://docs.sandbox.rest.easydns.net/beta_signup.php" + _err "You didn't specify an easydns.net token or api key. Signup at https://cp.easydns.com/manage/security/api/signup.php" return 1 else _saveaccountconf_mutable EASYDNS_Token "$EASYDNS_Token" From c06db30a65d970f914a06020d872573d656cd11a Mon Sep 17 00:00:00 2001 From: Viktor G Date: Mon, 20 Apr 2020 21:05:40 +0300 Subject: [PATCH 299/357] DNS Loopia min 300 TTL --- 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 1316a274..7760b53e 100644 --- a/dnsapi/dns_loopia.sh +++ b/dnsapi/dns_loopia.sh @@ -217,7 +217,7 @@ _loopia_add_record() { ttl - 60 + 300 rdata From c49b40ee95e28a8bac57e71001f7d65715e98063 Mon Sep 17 00:00:00 2001 From: Jesai Langenbach Date: Tue, 21 Apr 2020 11:43:08 +0200 Subject: [PATCH 300/357] Allow old and new API response CLOSES #2480 --- dnsapi/dns_opnsense.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_opnsense.sh b/dnsapi/dns_opnsense.sh index ec7d2277..069f6c32 100755 --- a/dnsapi/dns_opnsense.sh +++ b/dnsapi/dns_opnsense.sh @@ -150,7 +150,7 @@ _get_root() { return 1 fi _debug h "$h" - id=$(echo "$_domain_response" | _egrep_o "\"[^\"]*\":{\"enabled\":\"1\",\"type\":{\"master\":{\"value\":\"master\",\"selected\":1},\"slave\":{\"value\":\"slave\",\"selected\":0}},\"masterip\":\"[^\"]*\",\"allownotifyslave\":{\"\":{[^}]*}},\"domainname\":\"${h}\"" | cut -d ':' -f 1 | cut -d '"' -f 2) + id=$(echo "$_domain_response" | _egrep_o "\"[^\"]*\":{\"enabled\":\"1\",\"type\":{\"master\":{\"value\":\"master\",\"selected\":1},\"slave\":{\"value\":\"slave\",\"selected\":0}},\"masterip\":\"[^\"]*\"(,\"allownotifyslave\":{\"\":{[^}]*}},|,)\"domainname\":\"${h}\"" | cut -d ':' -f 1 | cut -d '"' -f 2) if [ -n "$id" ]; then _debug id "$id" From 24925a17392147c857d20a6b0272ea7da0bf1843 Mon Sep 17 00:00:00 2001 From: Honza Hommer Date: Wed, 22 Apr 2020 21:13:52 +0200 Subject: [PATCH 301/357] feat: add default colors --- notify/teams.sh | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/notify/teams.sh b/notify/teams.sh index d1de1c57..6b360ae5 100644 --- a/notify/teams.sh +++ b/notify/teams.sh @@ -14,6 +14,10 @@ teams_send() { _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped _debug "_statusCode" "$_statusCode" + _color_success="2cbe4e" # green + _color_danger="cb2431" # red + _color_muted="586069" # gray + TEAMS_WEBHOOK_URL="${TEAMS_WEBHOOK_URL:-$(_readaccountconf_mutable TEAMS_WEBHOOK_URL)}" if [ -z "$TEAMS_WEBHOOK_URL" ]; then TEAMS_WEBHOOK_URL="" @@ -49,16 +53,20 @@ teams_send() { case "$_statusCode" in 0) - _color="$TEAMS_SUCCESS_COLOR" + _color="${TEAMS_SUCCESS_COLOR:-$_color_success}" ;; 1) - _color="$TEAMS_ERROR_COLOR" + _color="${TEAMS_ERROR_COLOR:-$_color_danger}" ;; 2) - _color="$TEAMS_SKIP_COLOR" + _color="${TEAMS_SKIP_COLOR:-$_color_muted}" ;; esac - _color="$(echo "${_color:-$TEAMS_THEME_COLOR}" | tr -cd 'a-fA-F0-9')" + + _color=$(echo "$_color" | tr -cd 'a-fA-F0-9') + if [ -z "$_color" ]; then + _color=$(echo "${TEAMS_THEME_COLOR:-$_color_muted}" | tr -cd 'a-fA-F0-9') + fi _data="{\"title\": \"$_subject\"," if [ -n "$_color" ]; then From 6ba1eda96fb9afb7382794468ee47e3baf61806e Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 25 Apr 2020 22:44:00 +0800 Subject: [PATCH 302/357] fix https://github.com/acmesh-official/acme.sh/issues/2883#issuecomment-619215961 --- acme.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 57f45905..97d71a22 100755 --- a/acme.sh +++ b/acme.sh @@ -1174,9 +1174,8 @@ _createcsr() { _info "Multi domain" "$alt" printf -- "\nsubjectAltName=$alt" >>"$csrconf" fi - if [ "$Le_OCSP_Staple" ] || [ "$Le_OCSP_Stable" ]; then + if [ "$Le_OCSP_Staple" = "1" ]; then _savedomainconf Le_OCSP_Staple "$Le_OCSP_Staple" - _cleardomainconf Le_OCSP_Stable printf -- "\nbasicConstraints = CA:FALSE\n1.3.6.1.5.5.7.1.24=DER:30:03:02:01:05" >>"$csrconf" fi From 3ff48b8559678b0e02e25871eae29694f77d26ce Mon Sep 17 00:00:00 2001 From: Bas van Ritbergen Date: Mon, 27 Apr 2020 15:34:20 +0200 Subject: [PATCH 303/357] Update dns_openprovider.sh #2104 Fix wildcard handling & custom NS config for OpenProvider DNS --- dnsapi/dns_openprovider.sh | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/dnsapi/dns_openprovider.sh b/dnsapi/dns_openprovider.sh index ad1e5838..84058f60 100755 --- a/dnsapi/dns_openprovider.sh +++ b/dnsapi/dns_openprovider.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env sh +#!/bin/bash # This is the OpenProvider API wrapper for acme.sh # @@ -59,16 +59,17 @@ dns_openprovider_add() { break fi - items="$(echo "$items" | sed "s|${item}||")" + tmpitem="$(echo "$item" | sed 's/\*/\\*/g')" + items="$(echo "$items" | sed "s|${tmpitem}||")" results_retrieved="$(_math "$results_retrieved" + 1)" new_item="$(echo "$item" | sed -n 's/.*.*\(\(.*\)\.'"$_domain_name"'\.'"$_domain_extension"'<\/name>.*\(.*<\/type>\).*\(.*<\/value>\).*\(.*<\/prio>\).*\(.*<\/ttl>\)\).*<\/item>.*/\2<\/name>\3\4\5\6<\/item>/p')" if [ -z "$new_item" ]; then - # Base record + # Domain apex new_item="$(echo "$item" | sed -n 's/.*.*\(\(.*\)'"$_domain_name"'\.'"$_domain_extension"'<\/name>.*\(.*<\/type>\).*\(.*<\/value>\).*\(.*<\/prio>\).*\(.*<\/ttl>\)\).*<\/item>.*/\2<\/name>\3\4\5\6<\/item>/p')" fi - if [ -z "$(echo "$new_item" | _egrep_o ".*(A|AAAA|CNAME|MX|SPF|SRV|TXT|TLSA|SSHFP|CAA)<\/type>.*")" ]; then + if [ -z "$(echo "$new_item" | _egrep_o ".*(A|AAAA|CNAME|MX|SPF|SRV|TXT|TLSA|SSHFP|CAA|NS)<\/type>.*")" ]; then _debug "not an allowed record type, skipping" "$new_item" continue fi @@ -86,7 +87,7 @@ dns_openprovider_add() { _debug "Creating acme record" acme_record="$(echo "$fulldomain" | sed -e "s/.$_domain_name.$_domain_extension$//")" - _openprovider_request "$(printf '%s%smaster%s%sTXT%s86400' "$_domain_name" "$_domain_extension" "$existing_items" "$acme_record" "$txtvalue")" + _openprovider_request "$(printf '%s%smaster%s%sTXT%s600' "$_domain_name" "$_domain_extension" "$existing_items" "$acme_record" "$txtvalue")" return 0 } @@ -136,7 +137,8 @@ dns_openprovider_rm() { break fi - items="$(echo "$items" | sed "s|${item}||")" + tmpitem="$(echo "$item" | sed 's/\*/\\*/g')" + items="$(echo "$items" | sed "s|${tmpitem}||")" results_retrieved="$(_math "$results_retrieved" + 1)" if ! echo "$item" | grep -v "$fulldomain"; then @@ -147,11 +149,11 @@ dns_openprovider_rm() { new_item="$(echo "$item" | sed -n 's/.*.*\(\(.*\)\.'"$_domain_name"'\.'"$_domain_extension"'<\/name>.*\(.*<\/type>\).*\(.*<\/value>\).*\(.*<\/prio>\).*\(.*<\/ttl>\)\).*<\/item>.*/\2<\/name>\3\4\5\6<\/item>/p')" if [ -z "$new_item" ]; then - # Base record + # domain apex new_item="$(echo "$item" | sed -n 's/.*.*\(\(.*\)'"$_domain_name"'\.'"$_domain_extension"'<\/name>.*\(.*<\/type>\).*\(.*<\/value>\).*\(.*<\/prio>\).*\(.*<\/ttl>\)\).*<\/item>.*/\2<\/name>\3\4\5\6<\/item>/p')" fi - if [ -z "$(echo "$new_item" | _egrep_o ".*(A|AAAA|CNAME|MX|SPF|SRV|TXT|TLSA|SSHFP|CAA)<\/type>.*")" ]; then + if [ -z "$(echo "$new_item" | _egrep_o ".*(A|AAAA|CNAME|MX|SPF|SRV|TXT|TLSA|SSHFP|CAA|NS)<\/type>.*")" ]; then _debug "not an allowed record type, skipping" "$new_item" continue fi @@ -205,7 +207,8 @@ _get_root() { break fi - items="$(echo "$items" | sed "s|${item}||")" + tmpitem="$(echo "$item" | sed 's/\*/\\*/g')" + items="$(echo "$items" | sed "s|${tmpitem}||")" results_retrieved="$(_math "$results_retrieved" + 1)" From 1bfd0f014984c47b9b97da8709628a030a580fd9 Mon Sep 17 00:00:00 2001 From: Bas van Ritbergen Date: Mon, 27 Apr 2020 15:41:50 +0200 Subject: [PATCH 304/357] Update dns_openprovider.sh fixed shebang shell to be as suggested --- dnsapi/dns_openprovider.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_openprovider.sh b/dnsapi/dns_openprovider.sh index 84058f60..0a9e5ade 100755 --- a/dnsapi/dns_openprovider.sh +++ b/dnsapi/dns_openprovider.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env sh # This is the OpenProvider API wrapper for acme.sh # From da957a3caf587ad82fd0d11b8c5078d9b31f291b Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 29 Apr 2020 10:12:29 +0800 Subject: [PATCH 305/357] fix https://github.com/acmesh-official/acme.sh/issues/2888 --- dnsapi/dns_cf.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_cf.sh b/dnsapi/dns_cf.sh index 43bc1428..3e66a585 100755 --- a/dnsapi/dns_cf.sh +++ b/dnsapi/dns_cf.sh @@ -59,7 +59,7 @@ dns_cf_add() { _debug "Getting txt records" _cf_rest GET "zones/${_domain_id}/dns_records?type=TXT&name=$fulldomain" - if ! printf "%s" "$response" | grep \"success\":true >/dev/null; then + if ! echo "$response" | tr -d " " | grep \"success\":true >/dev/null; then _err "Error" return 1 fi From 1209b9b86eb994f76582aada3083a43806170a8b Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 29 Apr 2020 10:15:13 +0800 Subject: [PATCH 306/357] fix https://github.com/acmesh-official/acme.sh/issues/2888 --- dnsapi/dns_cf.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_cf.sh b/dnsapi/dns_cf.sh index 3e66a585..8d2e23ba 100755 --- a/dnsapi/dns_cf.sh +++ b/dnsapi/dns_cf.sh @@ -110,7 +110,7 @@ dns_cf_rm() { _debug "Getting txt records" _cf_rest GET "zones/${_domain_id}/dns_records?type=TXT&name=$fulldomain&content=$txtvalue" - if ! printf "%s" "$response" | grep \"success\":true >/dev/null; then + if ! echo "$response" | tr -d " " | grep \"success\":true >/dev/null; then _err "Error: $response" return 1 fi From b19799bc72599716f2a9067ecef10f42d0d6372c Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 29 Apr 2020 10:19:35 +0800 Subject: [PATCH 307/357] fix https://github.com/acmesh-official/acme.sh/issues/2888 --- dnsapi/dns_cf.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_cf.sh b/dnsapi/dns_cf.sh index 8d2e23ba..652c3769 100755 --- a/dnsapi/dns_cf.sh +++ b/dnsapi/dns_cf.sh @@ -120,7 +120,7 @@ dns_cf_rm() { 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) + record_id=$(echo "$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." From ad9f488df60fa5ceb8f4a269f3119f378395ec46 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 29 Apr 2020 10:38:21 +0800 Subject: [PATCH 308/357] fix https://github.com/acmesh-official/acme.sh/issues/2888 --- dnsapi/dns_cf.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_cf.sh b/dnsapi/dns_cf.sh index 652c3769..b4e9f632 100755 --- a/dnsapi/dns_cf.sh +++ b/dnsapi/dns_cf.sh @@ -115,12 +115,12 @@ dns_cf_rm() { return 1 fi - count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2) + 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" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | _head_n 1) + record_id=$(echo "$response" | _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." @@ -152,7 +152,7 @@ _get_root() { return 1 else if _contains "$response" '"success":true'; then - _domain=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1) + _domain=$(echo "$response" | _egrep_o "\"name\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | _head_n 1 | tr -d " ") if [ "$_domain" ]; then _cutlength=$((${#domain} - ${#_domain} - 1)) _sub_domain=$(printf "%s" "$domain" | cut -c "1-$_cutlength") @@ -186,7 +186,7 @@ _get_root() { fi if _contains "$response" "\"name\":\"$h\"" || _contains "$response" '"total_count":1'; then - _domain_id=$(echo "$response" | _egrep_o "\[.\"id\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \") + _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 From 58c2c701468b70df258c210ad7daff4a442d57af Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 29 Apr 2020 10:42:17 +0800 Subject: [PATCH 309/357] fix https://github.com/acmesh-official/acme.sh/issues/2888 --- dnsapi/dns_cf.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_cf.sh b/dnsapi/dns_cf.sh index b4e9f632..36799dcd 100755 --- a/dnsapi/dns_cf.sh +++ b/dnsapi/dns_cf.sh @@ -130,7 +130,7 @@ dns_cf_rm() { _err "Delete record error." return 1 fi - _contains "$response" '"success":true' + echo "$response" | tr -d " " | grep \"success\":true >/dev/null fi } @@ -151,7 +151,7 @@ _get_root() { if ! _cf_rest GET "zones/$CF_Zone_ID"; then return 1 else - if _contains "$response" '"success":true'; then + if echo "$response" | tr -d " " | grep \"success\":true >/dev/null; then _domain=$(echo "$response" | _egrep_o "\"name\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | _head_n 1 | tr -d " ") if [ "$_domain" ]; then _cutlength=$((${#domain} - ${#_domain} - 1)) From 45e6000619d65f15caefa6ac738789ae68a16274 Mon Sep 17 00:00:00 2001 From: ThiloGa Date: Fri, 1 May 2020 06:25:19 +0200 Subject: [PATCH 310/357] adding support for dyndnsfree.de --- dnsapi/dns_df.sh | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 dnsapi/dns_df.sh diff --git a/dnsapi/dns_df.sh b/dnsapi/dns_df.sh new file mode 100644 index 00000000..c71f0b44 --- /dev/null +++ b/dnsapi/dns_df.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env sh + +######################################################################## +# https://dyndnsfree.de hook script for acme.sh +# +# Environment variables: +# +# - $DF_user (your dyndnsfree.de API username) +# - $DF_password (your dyndnsfree.de API password) +# +# Author: Thilo Gass +# Git repo: https://github.com/ThiloGa/acme.sh + +#-- dns_df_add() - Add TXT record -------------------------------------- +# Usage: dns_df_add _acme-challenge.subdomain.domain.com "XyZ123..." + +dyndnsfree_api="https://dynup.de/acme.php" + +dns_df_add() { + fulldomain=$1 + txt_value=$2 + _info "Using DNS-01 dyndnsfree.de hook" + + DF_user="${DF_user:-$(_readaccountconf_mutable DF_user)}" + DF_password="${DF_password:-$(_readaccountconf_mutable DF_password)}" + if [ -z "$DF_user" ] || [ -z "$DF_password" ]; then + DF_user="" + DF_password="" + _err "No auth details provided. Please set user credentials using the \$DF_user and \$DF_password environment variables." + return 1 + fi + #save the api user and sha256 password to the account conf file. + _debug "Save user and hash" + _saveaccountconf_mutable DF_user "$DF_user" + _saveaccountconf_mutable DF_password "$DF_password" + + domain="$(printf "%s" "$fulldomain" | cut -d"." -f2-)" + + get="$dyndnsfree_api?username=$DF_user&password=$DF_password&hostname=$domain&add_hostname=$fulldomain&txt=$txt_value" + + if ! erg="$(_get "$get")"; then + _err "error Adding $fulldomain TXT: $txt_value" + return 1 + fi + + if _contains "$erg" "success"; then + _info "Success, TXT Added, OK" + else + _err "error Adding $fulldomain TXT: $txt_value erg: $erg" + return 1 + fi + + _debug "ok Auto $fulldomain TXT: $txt_value erg: $erg" + return 0 +} + +dns_df_rm() { + + fulldomain=$1 + txtvalue=$2 + _info "TXT enrty in $fulldomain is deleted automatically" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + +} From c3d7f5b28b1dd5298dc398e012f2c5cc75b5af3f Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 1 May 2020 23:44:56 +0800 Subject: [PATCH 311/357] build on docker hub --- .github/workflows/dockerhub.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .github/workflows/dockerhub.yml diff --git a/.github/workflows/dockerhub.yml b/.github/workflows/dockerhub.yml new file mode 100644 index 00000000..f1c0025d --- /dev/null +++ b/.github/workflows/dockerhub.yml @@ -0,0 +1,16 @@ + +name: Build DockerHub +on: + push: + branches: [ master, dev ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: trigger + run: curl -X POST https://hub.docker.com/api/build/v1/source/1813a660-2ee5-4583-a238-dd54e9a6ebac/trigger/c8cd9f1f-f269-45bc-9750-a08327257f62/call/ + + + + From 22f8ab110e84d9d6dfbf6223afe4fecddbd4d8b9 Mon Sep 17 00:00:00 2001 From: ThiloGa <61890902+ThiloGa@users.noreply.github.com> Date: Sat, 2 May 2020 08:26:26 +0200 Subject: [PATCH 312/357] typo fixing --- dnsapi/dns_df.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_df.sh b/dnsapi/dns_df.sh index c71f0b44..d5410d95 100644 --- a/dnsapi/dns_df.sh +++ b/dnsapi/dns_df.sh @@ -5,8 +5,8 @@ # # Environment variables: # -# - $DF_user (your dyndnsfree.de API username) -# - $DF_password (your dyndnsfree.de API password) +# - $DF_user (your dyndnsfree.de username) +# - $DF_password (your dyndnsfree.de password) # # Author: Thilo Gass # Git repo: https://github.com/ThiloGa/acme.sh @@ -30,7 +30,7 @@ dns_df_add() { return 1 fi #save the api user and sha256 password to the account conf file. - _debug "Save user and hash" + _debug "Save user and password" _saveaccountconf_mutable DF_user "$DF_user" _saveaccountconf_mutable DF_password "$DF_password" From 3b0d7bc4adaf41e04e5ef78f6c69bd66864055ca Mon Sep 17 00:00:00 2001 From: ThiloGa <61890902+ThiloGa@users.noreply.github.com> Date: Sat, 2 May 2020 08:29:44 +0200 Subject: [PATCH 313/357] typo fixing --- dnsapi/dns_df.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_df.sh b/dnsapi/dns_df.sh index d5410d95..c0499ddf 100644 --- a/dnsapi/dns_df.sh +++ b/dnsapi/dns_df.sh @@ -29,7 +29,7 @@ dns_df_add() { _err "No auth details provided. Please set user credentials using the \$DF_user and \$DF_password environment variables." return 1 fi - #save the api user and sha256 password to the account conf file. + #save the api user and password to the account conf file. _debug "Save user and password" _saveaccountconf_mutable DF_user "$DF_user" _saveaccountconf_mutable DF_password "$DF_password" From cf5952f5081b8f4a1ac7e5e6f6ae993667ae369c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=BCnemann?= Date: Sat, 2 May 2020 22:14:21 +0200 Subject: [PATCH 314/357] fix haproxy deploy hook ocsp update fixes ocsp reponse update failing with `Responder Error: unauthorized (6)` by removing `-no_nonce` switch from `openssl oscp` command . --- deploy/haproxy.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/deploy/haproxy.sh b/deploy/haproxy.sh index 3cd2a80a..0a45ee07 100644 --- a/deploy/haproxy.sh +++ b/deploy/haproxy.sh @@ -233,7 +233,6 @@ haproxy_deploy() { -header Host${_header_sep}\"${_ocsp_host}\" \ -respout \"${_ocsp}\" \ -verify_other \"${_issuer}\" \ - -no_nonce \ ${_cafile_argument} \ | grep -q \"${_pem}: good\"" _debug _openssl_ocsp_cmd "${_openssl_ocsp_cmd}" From eab35605e47331d378292b0e6e32db466954b18e Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 3 May 2020 11:01:02 +0800 Subject: [PATCH 315/357] remove sudo --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 155ec64b..91da2731 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,4 @@ language: shell -sudo: required dist: trusty os: From 9044adecb58e5d7b91056688ce1ca60543d7c3d3 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 4 May 2020 08:43:47 +0800 Subject: [PATCH 316/357] start 2.8.7 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 97d71a22..dd47481d 100755 --- a/acme.sh +++ b/acme.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -VER=2.8.6 +VER=2.8.7 PROJECT_NAME="acme.sh" From 81036894c01d8a3793215f65dfd1f1d03c7d94d5 Mon Sep 17 00:00:00 2001 From: Philipp Bandow <43735306+philband@users.noreply.github.com> Date: Thu, 7 May 2020 15:28:00 +0200 Subject: [PATCH 317/357] Add new DNS Provider: Njalla --- dnsapi/dns_njalla.sh | 169 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 dnsapi/dns_njalla.sh diff --git a/dnsapi/dns_njalla.sh b/dnsapi/dns_njalla.sh new file mode 100644 index 00000000..3b8b9ac7 --- /dev/null +++ b/dnsapi/dns_njalla.sh @@ -0,0 +1,169 @@ +#!/usr/bin/env sh + +# +#NJALLA_Token="sdfsdfsdfljlbjkljlkjsdfoiwje" + +NJALLA_Api="https://njal.la/api/1/" + +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_njalla_add() { + fulldomain=$1 + txtvalue=$2 + + NJALLA_Token="${NJALLA_Token:-$(_readaccountconf_mutable NJALLA_Token)}" + + if [ "$NJALLA_Token" ]; then + _saveaccountconf_mutable NJALLA_Token "$NJALLA_Token" + else + NJALLA_Token="" + _err "You didn't specify a Njalla api token yet." + 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 _njalla_rest "{\"method\":\"add-record\",\"params\":{\"domain\":\"$_domain\",\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}}"; then + if _contains "$response" "$txtvalue"; then + _info "Added, OK" + return 0 + else + _err "Add txt record error." + return 1 + fi + fi + _err "Add txt record error." + return 1 + +} + +#fulldomain txtvalue +dns_njalla_rm() { + fulldomain=$1 + txtvalue=$2 + + NJALLA_Token="${NJALLA_Token:-$(_readaccountconf_mutable NJALLA_Token)}" + + if [ "$NJALLA_Token" ]; then + _saveaccountconf_mutable NJALLA_Token "$NJALLA_Token" + else + NJALLA_Token="" + _err "You didn't specify a Njalla api token yet." + 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" + + _debug "Getting records for domain" + if ! _njalla_rest "{\"method\":\"list-records\",\"params\":{\"domain\":\"${_domain}\"}}"; then + return 1 + fi + + if ! echo "$response" | tr -d " " | grep "\"id\":" >/dev/null; then + _err "Error: $response" + return 1 + fi + + records=$(echo "$response" | _egrep_o "\"records\":\s?\[(.*)\]\}" | _egrep_o "\[.*\]" | _egrep_o "\{[^\{\}]*\"id\":[^\{\}]*\}") + count=$(echo "$records" | wc -l) + _debug count "$count" + + if [ "$count" = "0" ]; then + _info "Don't need to remove." + else + echo "$records" | while read -r record ; do + record_name=$(echo "$record" | _egrep_o "\"name\":\s?\"[^\"]*\"" | cut -d : -f 2 | tr -d " " | tr -d \") + record_content=$(echo "$record" | _egrep_o "\"content\":\s?\"[^\"]*\"" | cut -d : -f 2 | tr -d " " | tr -d \") + record_id=$(echo "$record" | _egrep_o "\"id\":\s?[0-9]+" | cut -d : -f 2 | tr -d " " | tr -d \") + if [ "$_sub_domain" = "$record_name" ]; then + if [ "$txtvalue" = "$record_content" ]; then + _debug "record_id" "$record_id" + if ! _njalla_rest "{\"method\":\"remove-record\",\"params\":{\"domain\":\"${_domain}\",\"id\":${record_id}}}"; then + _err "Delete record error." + return 1 + fi + echo "$response" | tr -d " " | grep "\"result\"" >/dev/null + fi + fi + done + fi + +} + +#################### 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 ! _njalla_rest "{\"method\":\"get-domain\",\"params\":{\"domain\":\"${h}\"}}"; then + return 1 + fi + + if _contains "$response" "\"$h\""; then + _domain_returned=$(echo "$response" | _egrep_o "\{\"name\": *\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \" | tr -d " ") + if [ "$_domain_returned" ]; 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 +} + +_njalla_rest() { + data="$1" + + token_trimmed=$(echo "$NJALLA_Token" | tr -d '"') + + export _H1="Content-Type: application/json" + export _H2="Accept: application/json" + export _H3="Authorization: Njalla $token_trimmed" + + _debug data "$data" + response="$(_post "$data" "$NJALLA_Api" "" "POST")" + + if [ "$?" != "0" ]; then + _err "error $ep" + return 1 + fi + _debug2 response "$response" + return 0 +} From 9bbcfead67638bcd602c50a8051e042bfa02360b Mon Sep 17 00:00:00 2001 From: Philipp Bandow <43735306+philband@users.noreply.github.com> Date: Thu, 7 May 2020 15:37:59 +0200 Subject: [PATCH 318/357] Bugfix shell format error --- dnsapi/dns_njalla.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_njalla.sh b/dnsapi/dns_njalla.sh index 3b8b9ac7..f91a1ed5 100644 --- a/dnsapi/dns_njalla.sh +++ b/dnsapi/dns_njalla.sh @@ -90,7 +90,7 @@ dns_njalla_rm() { if [ "$count" = "0" ]; then _info "Don't need to remove." else - echo "$records" | while read -r record ; do + echo "$records" | while read -r record; do record_name=$(echo "$record" | _egrep_o "\"name\":\s?\"[^\"]*\"" | cut -d : -f 2 | tr -d " " | tr -d \") record_content=$(echo "$record" | _egrep_o "\"content\":\s?\"[^\"]*\"" | cut -d : -f 2 | tr -d " " | tr -d \") record_id=$(echo "$record" | _egrep_o "\"id\":\s?[0-9]+" | cut -d : -f 2 | tr -d " " | tr -d \") From d507979ec1b6ad67b82ac36cb23ed52384fae9a3 Mon Sep 17 00:00:00 2001 From: Philipp Bandow <43735306+philband@users.noreply.github.com> Date: Thu, 7 May 2020 15:41:09 +0200 Subject: [PATCH 319/357] Make CI happy: Remove extraneous new line --- dnsapi/dns_njalla.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_njalla.sh b/dnsapi/dns_njalla.sh index f91a1ed5..804b0772 100644 --- a/dnsapi/dns_njalla.sh +++ b/dnsapi/dns_njalla.sh @@ -128,7 +128,6 @@ _get_root() { return 1 fi - if ! _njalla_rest "{\"method\":\"get-domain\",\"params\":{\"domain\":\"${h}\"}}"; then return 1 fi From d904df57ca48cb01e71b0a6c86d7cb3027b8fb3d Mon Sep 17 00:00:00 2001 From: Philipp Bandow <43735306+philband@users.noreply.github.com> Date: Thu, 7 May 2020 15:45:47 +0200 Subject: [PATCH 320/357] Bugfix error message in rest function --- dnsapi/dns_njalla.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_njalla.sh b/dnsapi/dns_njalla.sh index 804b0772..e9243288 100644 --- a/dnsapi/dns_njalla.sh +++ b/dnsapi/dns_njalla.sh @@ -160,7 +160,7 @@ _njalla_rest() { response="$(_post "$data" "$NJALLA_Api" "" "POST")" if [ "$?" != "0" ]; then - _err "error $ep" + _err "error $data" return 1 fi _debug2 response "$response" From 036a37e3511f09c8fd33a18fe4fa3c589134423e Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Thu, 7 May 2020 23:19:02 +0200 Subject: [PATCH 321/357] Nullify output from lexicon_cmd to prevent getting wrong return codes --- dnsapi/dns_lexicon.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_lexicon.sh b/dnsapi/dns_lexicon.sh index 516b6eff..34a95599 100755 --- a/dnsapi/dns_lexicon.sh +++ b/dnsapi/dns_lexicon.sh @@ -92,7 +92,7 @@ dns_lexicon_add() { _savedomainconf LEXICON_OPTS "$LEXICON_OPTS" # shellcheck disable=SC2086 - $lexicon_cmd "$PROVIDER" $LEXICON_OPTS create "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}" + $lexicon_cmd "$PROVIDER" $LEXICON_OPTS create "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}" >/dev/null } @@ -108,6 +108,6 @@ dns_lexicon_rm() { domain=$(printf "%s" "$fulldomain" | cut -d . -f 2-999) # shellcheck disable=SC2086 - $lexicon_cmd "$PROVIDER" $LEXICON_OPTS delete "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}" + $lexicon_cmd "$PROVIDER" $LEXICON_OPTS delete "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}" >/dev/null } From 99793bb2c492a8fe45a6ae8789b304d06be308e0 Mon Sep 17 00:00:00 2001 From: Honza Hommer Date: Sat, 9 May 2020 12:26:16 +0200 Subject: [PATCH 322/357] chore: remove shellcheck disable --- notify/teams.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/notify/teams.sh b/notify/teams.sh index 6b360ae5..e50ea703 100644 --- a/notify/teams.sh +++ b/notify/teams.sh @@ -74,8 +74,7 @@ teams_send() { fi _data="$_data\"text\": \"$_content\"}" - if _post "$_data" "$TEAMS_WEBHOOK_URL"; then - # shellcheck disable=SC2154 + if response=$(_post "$_data" "$TEAMS_WEBHOOK_URL"); then if ! _contains "$response" error; then _info "teams send success." return 0 From 94bf54e7e0f18cbf2e00fd44348c101bd18cfbda Mon Sep 17 00:00:00 2001 From: QDaniel Date: Wed, 13 May 2020 12:14:27 +0200 Subject: [PATCH 323/357] INWX fix Domain Limit #1491 --- dnsapi/dns_inwx.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/dnsapi/dns_inwx.sh b/dnsapi/dns_inwx.sh index 50b4b10c..ba789da9 100755 --- a/dnsapi/dns_inwx.sh +++ b/dnsapi/dns_inwx.sh @@ -261,6 +261,20 @@ _get_root() { xml_content=' nameserver.list + + + + + + pagelimit + + 9999 + + + + + + ' response="$(_post "$xml_content" "$INWX_Api" "" "POST")" From a4c57ee363f253fc9104a449fac957d3ca6cc532 Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Wed, 13 May 2020 15:35:51 +0200 Subject: [PATCH 324/357] Add TransIP provider --- acme.sh | 2 +- dnsapi/dns_transip.sh | 163 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 dnsapi/dns_transip.sh diff --git a/acme.sh b/acme.sh index 97d71a22..df16c1e7 100755 --- a/acme.sh +++ b/acme.sh @@ -1003,7 +1003,7 @@ _sign() { _sign_openssl="${ACME_OPENSSL_BIN:-openssl} dgst -sign $keyfile " - if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then + if egrep -o "BEGIN( RSA)? PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then $_sign_openssl -$alg | _base64 elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then if ! _signedECText="$($_sign_openssl -sha$__ECC_KEY_LEN | ${ACME_OPENSSL_BIN:-openssl} asn1parse -inform DER)"; then diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh new file mode 100644 index 00000000..c828fa66 --- /dev/null +++ b/dnsapi/dns_transip.sh @@ -0,0 +1,163 @@ +#!/usr/bin/env sh +TRANSIP_Api_Url="https://api.transip.nl/v6" +TRANSIP_Key_File="transip2.key" +TRANSIP_Token_Read_Only="false" +TRANSIP_Token_Global_Key="false" +TRANSIP_Token_Expiration="30 minutes" +# You can't reuse a label token, so we leave this empty normally +TRANSIP_Token_Label="" + +######## Public functions ##################### +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_transip_add() { + fulldomain="$1" + _debug fulldomain="$fulldomain" + txtvalue="$2" + _debug txtvalue="$txtvalue" + _transip_setup $fulldomain || return 1 + _info "Creating TXT record." + if ! _transip_rest POST "domains/$_domain/dns" "{\"dnsEntry\":{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"expire\":300}}"; then + _err "Could not add TXT record." + return 1 + fi + return 0 +} + +dns_transip_rm() { + fulldomain=$1 + _debug fulldomain="$fulldomain" + txtvalue=$2 + _debug txtvalue="$txtvalue" + _transip_setup $fulldomain || return 1 + _info "Removing TXT record." + if ! _transip_rest DELETE "domains/$_domain/dns" "{\"dnsEntry\":{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"expire\":300}}"; then + _err "Could not remove TXT record $_sub_domain for $domain" + return 1 + fi + return 0 +} + +#################### Private functions below ################################## +#_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 + + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain="$h" + + if _transip_rest GET "domains/$h/dns" && _contains $response "dnsEntries"; then + return 0 + fi + + p=$i + i=$(_math "$i" + 1) + done + _err "Unable to parse this domain" + return 1 +} + +_transip_rest() { + m="$1" + ep="$2" + data="$3" + _debug ep "$ep" + export _H1="Accept: application/json" + export _H2="Authorization: Bearer $_token" + export _H4="Content-Type: application/json" + if [ "$m" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$TRANSIP_Api_Url/$ep" "" "$m")" + retcode=$? + else + response="$(_get "$TRANSIP_Api_Url/$ep")" + retcode=$? + fi + + if [ "$retcode" != "0" ]; then + _err "error $ep" + return 1 + fi + _debug2 response "$response" + return 0 +} + +_transip_get_token() { + nonce=$(openssl rand -hex 12) + + data="{\"login\":\"${TRANSIP_Username}\",\"nonce\":\"${nonce}\",\"read_only\":\"${TRANSIP_Token_Read_Only}\",\"expiration_time\":\"${TRANSIP_Token_Expiration}\",\"label\":\"${TRANSIP_Token_Label}\",\"global_key\":\"${TRANSIP_Token_Global_Key}\"}" + _debug data "$data" + + #_signature=$(printf "%s" "$data" | openssl dgst -sha512 -sign "$TRANSIP_Key_File" | _base64) + _signature=$(printf "%s" "$data" | _sign "$TRANSIP_Key_File" "sha512") + _debug2 _signature "$_signature" + + export _H1="Signature: $_signature" + export _H2="Content-Type: application/json" + + response="$(_post "$data" "$TRANSIP_Api_Url/auth" "" "POST")" + retcode=$? + _debug2 response "$response" + if [ "$retcode" != "0" ]; then + _err "Authentication failed." + return 1 + fi + if _contains "$response" "token"; then + _token="$(echo "$response" | _normalizeJson | sed -n 's/^{"token":"\(.*\)"}/\1/p')" + _debug _token "$_token" + return 0 + fi + return 1 +} + +_transip_setup() { + fulldomain=$1 + + # retrieve the transip creds + TRANSIP_Username="${TRANSIP_Username:-$(_readaccountconf_mutable TRANSIP_Username)}" + TRANSIP_Key_File="${TRANSIP_Key_File:-$(_readaccountconf_mutable TRANSIP_Key_File)}" + # check their vals for null + if [ -z "$TRANSIP_Username" ] || [ -z "$TRANSIP_Key_File" ]; then + TRANSIP_Username="" + TRANSIP_Key_File="" + _err "You didn't specify a TransIP username and api key file location" + _err "Please set those values and try again." + return 1 + fi + # save the username and api key to the account conf file. + _saveaccountconf_mutable TRANSIP_Username "$TRANSIP_Username" + _saveaccountconf_mutable TRANSIP_Key_File "$TRANSIP_Key_File" + + if [ -f "$TRANSIP_Key_File"]; then + if ! grep "BEGIN PRIVATE KEY" "$TRANSIP_Key_File" >/dev/null 2>&1; then + _err "Key file doesn't seem to be a valid key: ${TRANSIP_Key_File}" + return 1 + fi + else + _err "Can't read private key file: ${TRANSIP_Key_File}" + return 1 + fi + + + if [ -z "$_token" ]; then + if ! _transip_get_token; then + _err "Can not get token." + return 1 + fi + fi + + _get_root $fulldomain || return 1 + + return 0 +} From 80a636bd14f9b01aca0fb4da6867ef163932e36f Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Wed, 13 May 2020 16:08:34 +0200 Subject: [PATCH 325/357] Fix extra space --- dnsapi/dns_transip.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh index c828fa66..180b278e 100644 --- a/dnsapi/dns_transip.sh +++ b/dnsapi/dns_transip.sh @@ -139,7 +139,7 @@ _transip_setup() { _saveaccountconf_mutable TRANSIP_Username "$TRANSIP_Username" _saveaccountconf_mutable TRANSIP_Key_File "$TRANSIP_Key_File" - if [ -f "$TRANSIP_Key_File"]; then + if [ -f "$TRANSIP_Key_File" ]; then if ! grep "BEGIN PRIVATE KEY" "$TRANSIP_Key_File" >/dev/null 2>&1; then _err "Key file doesn't seem to be a valid key: ${TRANSIP_Key_File}" return 1 From 65e82b03ade1566d74058f5bcb4bcd4526668548 Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Wed, 13 May 2020 16:11:53 +0200 Subject: [PATCH 326/357] Fix CI errors --- dnsapi/dns_transip.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh index 180b278e..5403cc10 100644 --- a/dnsapi/dns_transip.sh +++ b/dnsapi/dns_transip.sh @@ -14,7 +14,7 @@ dns_transip_add() { _debug fulldomain="$fulldomain" txtvalue="$2" _debug txtvalue="$txtvalue" - _transip_setup $fulldomain || return 1 + _transip_setup "$fulldomain" || return 1 _info "Creating TXT record." if ! _transip_rest POST "domains/$_domain/dns" "{\"dnsEntry\":{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"expire\":300}}"; then _err "Could not add TXT record." @@ -28,7 +28,7 @@ dns_transip_rm() { _debug fulldomain="$fulldomain" txtvalue=$2 _debug txtvalue="$txtvalue" - _transip_setup $fulldomain || return 1 + _transip_setup "$fulldomain" || return 1 _info "Removing TXT record." if ! _transip_rest DELETE "domains/$_domain/dns" "{\"dnsEntry\":{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"expire\":300}}"; then _err "Could not remove TXT record $_sub_domain for $domain" @@ -57,7 +57,7 @@ _get_root() { _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain="$h" - if _transip_rest GET "domains/$h/dns" && _contains $response "dnsEntries"; then + if _transip_rest GET "domains/$h/dns" && _contains "$response" "dnsEntries"; then return 0 fi @@ -157,7 +157,7 @@ _transip_setup() { fi fi - _get_root $fulldomain || return 1 + _get_root "$fulldomain" || return 1 return 0 } From a102d775b25ca00b210ab25a246653be65f6ee3b Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Wed, 13 May 2020 16:49:07 +0200 Subject: [PATCH 327/357] Formatting issues --- dnsapi/dns_transip.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh index 5403cc10..1fd8e4c9 100644 --- a/dnsapi/dns_transip.sh +++ b/dnsapi/dns_transip.sh @@ -58,7 +58,7 @@ _get_root() { _domain="$h" if _transip_rest GET "domains/$h/dns" && _contains "$response" "dnsEntries"; then - return 0 + return 0 fi p=$i @@ -140,10 +140,10 @@ _transip_setup() { _saveaccountconf_mutable TRANSIP_Key_File "$TRANSIP_Key_File" if [ -f "$TRANSIP_Key_File" ]; then - if ! grep "BEGIN PRIVATE KEY" "$TRANSIP_Key_File" >/dev/null 2>&1; then - _err "Key file doesn't seem to be a valid key: ${TRANSIP_Key_File}" - return 1 - fi + if ! grep "BEGIN PRIVATE KEY" "$TRANSIP_Key_File" >/dev/null 2>&1; then + _err "Key file doesn't seem to be a valid key: ${TRANSIP_Key_File}" + return 1 + fi else _err "Can't read private key file: ${TRANSIP_Key_File}" return 1 From e768e285ce96ba10a9791485afd5a6a5886d3d4a Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Wed, 13 May 2020 16:49:42 +0200 Subject: [PATCH 328/357] Remove extra newline --- dnsapi/dns_transip.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh index 1fd8e4c9..34fbafa6 100644 --- a/dnsapi/dns_transip.sh +++ b/dnsapi/dns_transip.sh @@ -149,7 +149,6 @@ _transip_setup() { return 1 fi - if [ -z "$_token" ]; then if ! _transip_get_token; then _err "Can not get token." From d5ef3a3f8ca423688062b7177f8320f8719a828e Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Wed, 13 May 2020 17:07:19 +0200 Subject: [PATCH 329/357] Formatting issues --- dnsapi/dns_transip.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh index 34fbafa6..23a7f493 100644 --- a/dnsapi/dns_transip.sh +++ b/dnsapi/dns_transip.sh @@ -145,8 +145,8 @@ _transip_setup() { return 1 fi else - _err "Can't read private key file: ${TRANSIP_Key_File}" - return 1 + _err "Can't read private key file: ${TRANSIP_Key_File}" + return 1 fi if [ -z "$_token" ]; then From 048f754d837a85ee6e7698219f6848702c254890 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Vestergaard=20V=C3=A6rum?= Date: Thu, 14 May 2020 22:49:04 +0200 Subject: [PATCH 330/357] Bug fix: DNS TXT entries will now be removed for dns_gdnsdk.sh --- dnsapi/dns_gdnsdk.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_gdnsdk.sh b/dnsapi/dns_gdnsdk.sh index 8c4962c0..90842b25 100755 --- a/dnsapi/dns_gdnsdk.sh +++ b/dnsapi/dns_gdnsdk.sh @@ -157,9 +157,18 @@ _successful_update() { } _findentry() { + #args $1: fulldomain, $2: txtvalue #returns id of dns entry, if it exists _myget "action=dns_primary_changeDNSsetup&user_domain=$_domain" - _id=$(echo "$_result" | _egrep_o "$1\s*$2[^?]*[^&]*&id=[^&]*" | sed 's/^.*=//') + _debug3 "_result: $_result" + + _tmp_result=$(echo "$_result" | tr -d '\n\r' | _egrep_o "$1\s*$2[^?]*[^&]*&id=[^&]*") + _debug _tmp_result "$_tmp_result" + if [ -z "${_tmp_result:-}" ]; then + _debug "The variable is _tmp_result is not supposed to be empty, there may be something wrong with the script" + fi + + _id=$(echo "$_tmp_result" | sed 's/^.*=//') if [ -n "$_id" ]; then _debug "Entry found with _id=$_id" return 0 From 52b81608a1cbb51409d25e9c97d7a5087f7982c7 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Fri, 15 May 2020 23:48:50 -0600 Subject: [PATCH 331/357] need to _url_encode anything sent in GET requests Fixes issue raised by @tatablack --- deploy/synology_dsm.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 5aef3b93..279b3c4f 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -83,6 +83,9 @@ synology_dsm_deploy() { _info "Logging into $SYNO_Hostname:$SYNO_Port" response=$(_get "$_base_url/webman/login.cgi?username=$SYNO_Username&passwd=$SYNO_Password&enable_syno_token=yes&device_id=$SYNO_DID") token=$(echo "$response" | grep "SynoToken" | sed -n 's/.*"SynoToken" *: *"\([^"]*\).*/\1/p') + encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)" + encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)" + encoded_did="$(printf "%s" "$SYNO_DID" | _url_encode)" _debug3 response "$response" if [ -z "$token" ]; then From d15c14ab939682e0327202a78ef2470df7472181 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Fri, 15 May 2020 23:53:00 -0600 Subject: [PATCH 332/357] Fix support for wget I'm actually not entirely sure why/how this worked with curl but not wget, but it did. The short answer is that using a GET does not result in the HTTP_HEADER file being written, instead you must pass in the http_headers param ($2) which will return the HTTP headers as a string. Luckily, the Token is in both the body and the header. We need it and the id (and smid if 2fa) cookie to proceed. So now we parrse the response for that instead of the HTTP_HEADER file. Interesting side note: wget is fine if the URL contains a \r or \n, but curl will barf on it. So we need to make sure those are stripped from the token as it will be passed in the URL later. --- deploy/synology_dsm.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 279b3c4f..7e77344f 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -22,7 +22,7 @@ ######## Public functions ##################### _syno_get_cookie_data() { - grep "\W$1=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';' + grep "\W$1=" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';' } #domain keyfile certfile cafile fullchain @@ -81,12 +81,13 @@ synology_dsm_deploy() { # Login, get the token from JSON and session id from cookie _info "Logging into $SYNO_Hostname:$SYNO_Port" - response=$(_get "$_base_url/webman/login.cgi?username=$SYNO_Username&passwd=$SYNO_Password&enable_syno_token=yes&device_id=$SYNO_DID") - token=$(echo "$response" | grep "SynoToken" | sed -n 's/.*"SynoToken" *: *"\([^"]*\).*/\1/p') 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 "X-SYNO-TOKEN:" | sed -n 's/^X-SYNO-TOKEN: \(.*\)$/\1/p' | tr -d "\r\n") _debug3 response "$response" + _debug token "$token" if [ -z "$token" ]; then _err "Unable to authenticate to $SYNO_Hostname:$SYNO_Port using $SYNO_Scheme." @@ -94,7 +95,7 @@ synology_dsm_deploy() { return 1 fi - _H1="Cookie: $(_syno_get_cookie_data "id"); $(_syno_get_cookie_data "smid")" + _H1="Cookie: $(echo "$response" | _syno_get_cookie_data "id"); $(echo "$response" | _syno_get_cookie_data "smid")" _H2="X-SYNO-TOKEN: $token" export _H1 export _H2 @@ -105,7 +106,6 @@ synology_dsm_deploy() { _savedeployconf SYNO_Username "$SYNO_Username" _savedeployconf SYNO_Password "$SYNO_Password" _savedeployconf SYNO_DID "$SYNO_DID" - _debug token "$token" _info "Getting certificates in Synology DSM" response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1" "$_base_url/webapi/entry.cgi") From 668967a7198c583143d5c63b5aed805fd779ac8e Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sat, 16 May 2020 00:05:35 -0600 Subject: [PATCH 333/357] If SYNO_Create is not set here, print the nice message --- 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 7e77344f..b55d1286 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -113,7 +113,7 @@ synology_dsm_deploy() { id=$(echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\"id\":\"\([^\"]*\).*/\1/p") _debug2 id "$id" - if [ -z "$id" ] && [ -z "${SYNO_Create:?}" ]; then + if [ -z "$id" ] && [ -z "$SYNO_Create" ]; then _err "Unable to find certificate: $SYNO_Certificate and \$SYNO_Create is not set" return 1 fi From 3a7c7fe4e8fc663a4ec913aee1997736918493f5 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sat, 16 May 2020 00:19:18 -0600 Subject: [PATCH 334/357] Fix shellcheck issues --- deploy/synology_dsm.sh | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index b55d1286..06ee2f1e 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -40,9 +40,7 @@ synology_dsm_deploy() { _getdeployconf SYNO_Password _getdeployconf SYNO_Create _getdeployconf SYNO_DID - if [ -z "$SYNO_Username" ] || [ -z "$SYNO_Password" ]; then - SYNO_Username="" - SYNO_Password="" + if [ -z "${SYNO_Username:-}" ] || [ -z "${SYNO_Password:-}" ]; then _err "SYNO_Username & SYNO_Password must be set" return 1 fi @@ -70,7 +68,7 @@ synology_dsm_deploy() { # Get the certificate description, but don't save it until we verfiy it's real _getdeployconf SYNO_Certificate - if [ -z "${SYNO_Certificate:?}" ]; then + if [ -z "${SYNO_Certificate:-}" ]; then _err "SYNO_Certificate needs to be defined (with the Certificate description name)" return 1 fi @@ -113,7 +111,7 @@ synology_dsm_deploy() { id=$(echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\"id\":\"\([^\"]*\).*/\1/p") _debug2 id "$id" - if [ -z "$id" ] && [ -z "$SYNO_Create" ]; then + if [ -z "$id" ] && [ -z "${SYNO_Create:-}" ]; then _err "Unable to find certificate: $SYNO_Certificate and \$SYNO_Create is not set" return 1 fi From c7f61f8b804793aebcc131354b5d0978a2b397ce Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sat, 16 May 2020 01:38:44 -0600 Subject: [PATCH 335/357] Allow rotating the default certificate which has no description This means, by default, we will rotate the default certificate that comes with the DSM --- deploy/synology_dsm.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 06ee2f1e..7ca4375e 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -68,10 +68,6 @@ synology_dsm_deploy() { # Get the certificate description, but don't save it until we verfiy it's real _getdeployconf SYNO_Certificate - if [ -z "${SYNO_Certificate:-}" ]; then - _err "SYNO_Certificate needs to be defined (with the Certificate description name)" - return 1 - fi _debug SYNO_Certificate "$SYNO_Certificate" _base_url="$SYNO_Scheme://$SYNO_Hostname:$SYNO_Port" From 694194be2f1d1e98385f884b0fb0f11ace3b4a77 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sat, 16 May 2020 02:25:53 -0600 Subject: [PATCH 336/357] Shellcheck fix SYNO_Certificate gets set by _getdeployconf, so this may be an empty string but that's fine --- 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 7ca4375e..b93d0187 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -68,7 +68,7 @@ synology_dsm_deploy() { # Get the certificate description, but don't save it until we verfiy it's real _getdeployconf SYNO_Certificate - _debug SYNO_Certificate "$SYNO_Certificate" + _debug SYNO_Certificate "${SYNO_Certificate:-}" _base_url="$SYNO_Scheme://$SYNO_Hostname:$SYNO_Port" _debug _base_url "$_base_url" From 4954b44d8e818ac7b78943d5446d9a7b0aae5410 Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Sat, 16 May 2020 16:18:05 +0200 Subject: [PATCH 337/357] Remove default key file (leave it to the user to explicitly specify) --- dnsapi/dns_transip.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh index 23a7f493..b5cea51b 100644 --- a/dnsapi/dns_transip.sh +++ b/dnsapi/dns_transip.sh @@ -1,6 +1,5 @@ #!/usr/bin/env sh TRANSIP_Api_Url="https://api.transip.nl/v6" -TRANSIP_Key_File="transip2.key" TRANSIP_Token_Read_Only="false" TRANSIP_Token_Global_Key="false" TRANSIP_Token_Expiration="30 minutes" From fa91516dcec14813ad27fc158ebf3c85645d1142 Mon Sep 17 00:00:00 2001 From: Gassan Gousseinov Date: Sun, 17 May 2020 18:54:06 +0200 Subject: [PATCH 338/357] added dnsapi/dns_hetzner.sh --- dnsapi/dns_hetzner.sh | 252 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 dnsapi/dns_hetzner.sh diff --git a/dnsapi/dns_hetzner.sh b/dnsapi/dns_hetzner.sh new file mode 100644 index 00000000..9499501f --- /dev/null +++ b/dnsapi/dns_hetzner.sh @@ -0,0 +1,252 @@ +#!/usr/bin/env sh + +# +#HETZNER_Token="sdfsdfsdfljlbjkljlkjsdfoiwje" +# + +HETZNER_Api="https://dns.hetzner.com/api/v1" + +######## Public functions ##################### + +# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +# Used to add txt record +# Ref: https://dns.hetzner.com/api-docs/ +dns_hetzner_add() { + full_domain=$1 + txt_value=$2 + + HETZNER_Token="${HETZNER_Token:-$(_readaccountconf_mutable HETZNER_Token)}" + + if [ -z "$HETZNER_Token" ]; then + HETZNER_Token="" + _err "You didn't specify a Hetzner api token." + _err "You can get yours from here https://dns.hetzner.com/settings/api-token." + return 1 + fi + + #save the api key and email to the account conf file. + _saveaccountconf_mutable HETZNER_Token "$HETZNER_Token" + + _debug "First detect the root zone" + + if ! _get_root "$full_domain"; then + _err "Invalid domain" + return 1 + fi + _debug _domain_id "$_domain_id" + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting TXT records" + if ! _find_record "$_sub_domain" "$txt_value"; then + return 1 + fi + + if [ -z "$_record_id" ]; then + _info "Adding record" + if _hetzner_rest POST "records" "{\"zone_id\":\"${HETZNER_Zone_ID}\",\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":\"$txt_value\",\"ttl\":120}"; then + if _contains "$response" "$txt_value"; then + _info "Record added, OK" + _sleep 2 + return 0 + fi + fi + _err "Add txt record error${_response_error}" + return 1 + else + _info "Found record id: $_record_id." + _info "Record found, do nothing." + return 0; +# # we could modify a record, if the names for txt records for *.example.com and example.com would be not the same +# if _hetzner_rest PUT "records/${_record_id}" "{\"zone_id\":\"${HETZNER_Zone_ID}\",\"type\":\"TXT\",\"name\":\"$full_domain\",\"value\":\"$txt_value\",\"ttl\":120}"; then +# if _contains "$response" "$txt_value"; then +# _info "Modified, OK" +# return 0 +# fi +# fi +# _err "Add txt record error (modify)." +# return 1 + fi +} + +# Usage: full_domain txt_value +# Used to remove the txt record after validation +dns_hetzner_rm() { + full_domain=$1 + txt_value=$2 + + HETZNER_Token="${HETZNER_Token:-$(_readaccountconf_mutable HETZNER_Token)}" + + _debug "First detect the root zone" + if ! _get_root "$full_domain"; then + _err "Invalid domain" + return 1 + fi + _debug _domain_id "$_domain_id" + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting TXT records" + if ! _find_record "$_sub_domain" "$txt_value"; then + return 1 + fi + + if [ -z "$_record_id" ]; then + _info "Remove not needed. Record not found." + else + if ! _hetzner_rest DELETE "records/$_record_id"; then + _err "Delete record error${_response_error}" + return 1 + fi + _sleep 2 + _info "Record deleted" + fi +} + +#################### Private functions below ################################## +#returns +# _record_id=a8d58f22d6931bf830eaa0ec6464bf81 if found; or 1 if error +_find_record() { + unset _record_id; + _record_name=$1 + _record_value=$2 + + if [ -z "$_record_value" ]; then + _record_value="[^\"]*" + fi + + _debug "Getting all records" + _hetzner_rest GET "records?zone_id=${_domain_id}" + + if _response_has_error; then + _err "Error${_response_error}" + return 1 + else + _record_id=$( + echo "$response" \ + | grep -o "{[^\{\}]*\"name\":\"$_record_name\"[^\}]*}" \ + | grep "\"value\":\"$_record_value\"" \ + | while read -r record; do + # test for type and + if [ -n "$(echo "$record" | _egrep_o '"type":"TXT"')" ]; then + echo "$record" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" + break + fi + done + ) + fi +} + +#_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 + + domain_without_acme=$(echo "$domain" | cut -d . -f 2-) + domain_param_name=$(echo "HETZNER_Zone_ID_for_${domain_without_acme}" | sed 's/[\.\-]/_/g') + + _debug "Reading zone_id for '$domain_without_acme' from config..." + HETZNER_Zone_ID=$(_readdomainconf "$domain_param_name") + if [ "$HETZNER_Zone_ID" ]; then + _debug "Found, using: $HETZNER_Zone_ID" + if ! _hetzner_rest GET "zones/${HETZNER_Zone_ID}"; then + _debug "Zone with id '$HETZNER_Zone_ID' not exists." + _cleardomainconf "$domain_param_name" + unset HETZNER_Zone_ID + else + if _contains "$response" "\"id\":\"$HETZNER_Zone_ID\""; then + _domain=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1) + if [ "$_domain" ]; then + _cut_length=$((${#domain} - ${#_domain} - 1)) + _sub_domain=$(printf "%s" "$domain" | cut -c "1-$_cut_length") + _domain_id="$HETZNER_Zone_ID" + return 0 + else + return 1 + fi + else + return 1 + fi + fi + fi + + _debug "Trying to get zone id by domain name for '$domain_without_acme'." + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + if [ -z "$h" ]; then + #not valid + return 1 + fi + _debug h "$h" + + _hetzner_rest GET "zones?name=$h" + + if _contains "$response" "\"name\":\"$h\"" || _contains "$response" '"total_entries":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 + HETZNER_Zone_ID=$_domain_id + _savedomainconf "$domain_param_name" "$HETZNER_Zone_ID" + return 0 + fi + return 1 + fi + p=$i + i=$(_math "$i" + 1) + done + return 1 +} + +#returns +# _response_error +_response_has_error() { + unset _response_error + + err_part="$(echo "$response" | _egrep_o '"error":{[^}]*}')" + + if [ -n "$err_part" ]; then + err_code=$(echo "$err_part" | _egrep_o '"code":[0-9]+' | cut -d : -f 2) + err_message=$(echo "$err_part" | _egrep_o '"message":"[^"]+"' | cut -d : -f 2 | tr -d \") + + if [ -n "$err_code" ] && [ -n "$err_message" ]; then + _response_error=" - message: ${err_message}, code: ${err_code}" + return 0 + fi + fi + + return 1 +} + +#returns +# response +_hetzner_rest() { + m=$1 + ep="$2" + data="$3" + _debug "$ep" + + key_trimmed=$(echo "$HETZNER_Token" | tr -d \") + + export _H1="Content-TType: application/json" + export _H2="Auth-API-Token: $key_trimmed" + + if [ "$m" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$HETZNER_Api/$ep" "" "$m")" + else + response="$(_get "$HETZNER_Api/$ep")" + fi + + if [ "$?" != "0" ] || _response_has_error; then + _debug "Error$_response_error" + return 1 + fi + _debug2 response "$response" + return 0 +} From b82c48b66f1c75befb372316bc2cd882d9d9d3a0 Mon Sep 17 00:00:00 2001 From: Gassan Gousseinov Date: Sun, 17 May 2020 22:51:04 +0200 Subject: [PATCH 339/357] shfmt --- dnsapi/dns_hetzner.sh | 52 +++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/dnsapi/dns_hetzner.sh b/dnsapi/dns_hetzner.sh index 9499501f..d994d665 100644 --- a/dnsapi/dns_hetzner.sh +++ b/dnsapi/dns_hetzner.sh @@ -56,16 +56,16 @@ dns_hetzner_add() { else _info "Found record id: $_record_id." _info "Record found, do nothing." - return 0; -# # we could modify a record, if the names for txt records for *.example.com and example.com would be not the same -# if _hetzner_rest PUT "records/${_record_id}" "{\"zone_id\":\"${HETZNER_Zone_ID}\",\"type\":\"TXT\",\"name\":\"$full_domain\",\"value\":\"$txt_value\",\"ttl\":120}"; then -# if _contains "$response" "$txt_value"; then -# _info "Modified, OK" -# return 0 -# fi -# fi -# _err "Add txt record error (modify)." -# return 1 + return 0 + # we could modify a record, if the names for txt records for *.example.com and example.com would be not the same + #if _hetzner_rest PUT "records/${_record_id}" "{\"zone_id\":\"${HETZNER_Zone_ID}\",\"type\":\"TXT\",\"name\":\"$full_domain\",\"value\":\"$txt_value\",\"ttl\":120}"; then + # if _contains "$response" "$txt_value"; then + # _info "Modified, OK" + # return 0 + # fi + #fi + #_err "Add txt record error (modify)." + #return 1 fi } @@ -107,12 +107,12 @@ dns_hetzner_rm() { #returns # _record_id=a8d58f22d6931bf830eaa0ec6464bf81 if found; or 1 if error _find_record() { - unset _record_id; + unset _record_id _record_name=$1 _record_value=$2 if [ -z "$_record_value" ]; then - _record_value="[^\"]*" + _record_value='[^"]*' fi _debug "Getting all records" @@ -129,11 +129,11 @@ _find_record() { | while read -r record; do # test for type and if [ -n "$(echo "$record" | _egrep_o '"type":"TXT"')" ]; then - echo "$record" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" + echo "$record" | _egrep_o '"id":"[^"]*"' | cut -d : -f 2 | tr -d \" break fi done - ) + ) fi } @@ -160,7 +160,7 @@ _get_root() { unset HETZNER_Zone_ID else if _contains "$response" "\"id\":\"$HETZNER_Zone_ID\""; then - _domain=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1) + _domain=$(printf "%s\n" "$response" | _egrep_o '"name":"[^"]*"' | cut -d : -f 2 | tr -d \" | head -n 1) if [ "$_domain" ]; then _cut_length=$((${#domain} - ${#_domain} - 1)) _sub_domain=$(printf "%s" "$domain" | cut -c "1-$_cut_length") @@ -206,21 +206,21 @@ _get_root() { #returns # _response_error _response_has_error() { - unset _response_error + unset _response_error - err_part="$(echo "$response" | _egrep_o '"error":{[^}]*}')" + err_part="$(echo "$response" | _egrep_o '"error":{[^}]*}')" - if [ -n "$err_part" ]; then - err_code=$(echo "$err_part" | _egrep_o '"code":[0-9]+' | cut -d : -f 2) - err_message=$(echo "$err_part" | _egrep_o '"message":"[^"]+"' | cut -d : -f 2 | tr -d \") + if [ -n "$err_part" ]; then + err_code=$(echo "$err_part" | _egrep_o '"code":[0-9]+' | cut -d : -f 2) + err_message=$(echo "$err_part" | _egrep_o '"message":"[^"]+"' | cut -d : -f 2 | tr -d \") - if [ -n "$err_code" ] && [ -n "$err_message" ]; then - _response_error=" - message: ${err_message}, code: ${err_code}" - return 0 - fi - fi + if [ -n "$err_code" ] && [ -n "$err_message" ]; then + _response_error=" - message: ${err_message}, code: ${err_code}" + return 0 + fi + fi - return 1 + return 1 } #returns From 8b3d792bec2061fb6ad18ee5eb2f22b58b92cd54 Mon Sep 17 00:00:00 2001 From: Ian Wienand Date: Mon, 18 May 2020 15:24:54 +1000 Subject: [PATCH 340/357] dns_rackspace: search for domain The current call uses the /domains end-point which lists all domains. This only returns 100 domains at a time, so for long domain lists you may not match and find the required ID. Switch to using the search interface that only returns values matching the requested domain. This will avoid missing results. Reported by @jjamfd. Closes: #2944 --- dnsapi/dns_rackspace.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_rackspace.sh b/dnsapi/dns_rackspace.sh index 159671f9..03e1fa68 100644 --- a/dnsapi/dns_rackspace.sh +++ b/dnsapi/dns_rackspace.sh @@ -73,7 +73,7 @@ _get_root_zone() { #not valid return 1 fi - if ! _rackspace_rest GET "$RACKSPACE_Tenant/domains"; then + if ! _rackspace_rest GET "$RACKSPACE_Tenant/domains/search?name=$h"; then return 1 fi _debug2 response "$response" From 0deea5393124f4ab34822932f8cf80e464046342 Mon Sep 17 00:00:00 2001 From: kref Date: Tue, 19 May 2020 13:27:00 +0800 Subject: [PATCH 341/357] fix octal escapes for printf %b format Stop it from misinterpreting a following digit as part of the escape sequence --- 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 5aef3b93..c8458c0a 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -125,11 +125,11 @@ synology_dsm_deploy() { _debug2 default "$default" _info "Generate form POST request" - nl="\015\012" + nl="\0015\0012" delim="--------------------------$(_utc_date | tr -d -- '-: ')" - content="--$delim${nl}Content-Disposition: form-data; name=\"key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")\012" - content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"cert\"; filename=\"$(basename "$_ccert")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ccert")\012" - 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")\012" + content="--$delim${nl}Content-Disposition: form-data; name=\"key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")\0012" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"cert\"; filename=\"$(basename "$_ccert")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ccert")\0012" + 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}" From adfa1704e2188828562004e5fab05b1a731749c2 Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Tue, 19 May 2020 16:38:23 +0200 Subject: [PATCH 342/357] Update nonce calculation to use acme.sh methods instead of openssl command --- dnsapi/dns_transip.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh index b5cea51b..8764c1c4 100644 --- a/dnsapi/dns_transip.sh +++ b/dnsapi/dns_transip.sh @@ -93,7 +93,7 @@ _transip_rest() { } _transip_get_token() { - nonce=$(openssl rand -hex 12) + nonce=$(echo "TRANSIP$(_time)" | _digest sha1 hex) data="{\"login\":\"${TRANSIP_Username}\",\"nonce\":\"${nonce}\",\"read_only\":\"${TRANSIP_Token_Read_Only}\",\"expiration_time\":\"${TRANSIP_Token_Expiration}\",\"label\":\"${TRANSIP_Token_Label}\",\"global_key\":\"${TRANSIP_Token_Global_Key}\"}" _debug data "$data" From 2d5b4a00032ef6ed03f1b5b6baea3027dfef65c5 Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Tue, 19 May 2020 16:39:49 +0200 Subject: [PATCH 343/357] Change if-statement for private keys to more portable version --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index df16c1e7..80f5c241 100755 --- a/acme.sh +++ b/acme.sh @@ -1003,7 +1003,7 @@ _sign() { _sign_openssl="${ACME_OPENSSL_BIN:-openssl} dgst -sign $keyfile " - if egrep -o "BEGIN( RSA)? PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then + if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; || if grep "BEGIN PRIVATE KEY" "$keyfile" >/dev/null 2>&1; $_sign_openssl -$alg | _base64 elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then if ! _signedECText="$($_sign_openssl -sha$__ECC_KEY_LEN | ${ACME_OPENSSL_BIN:-openssl} asn1parse -inform DER)"; then From 5d2777634a05cf71391e5e168e1f382d7964fe32 Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Tue, 19 May 2020 16:43:39 +0200 Subject: [PATCH 344/357] Fix forgotten then --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 80f5c241..d3c357fc 100755 --- a/acme.sh +++ b/acme.sh @@ -1003,7 +1003,7 @@ _sign() { _sign_openssl="${ACME_OPENSSL_BIN:-openssl} dgst -sign $keyfile " - if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; || if grep "BEGIN PRIVATE KEY" "$keyfile" >/dev/null 2>&1; + if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; || if grep "BEGIN PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then $_sign_openssl -$alg | _base64 elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then if ! _signedECText="$($_sign_openssl -sha$__ECC_KEY_LEN | ${ACME_OPENSSL_BIN:-openssl} asn1parse -inform DER)"; then From 114f2a146542fe06ff7db6a763263e034debbedc Mon Sep 17 00:00:00 2001 From: neil Date: Tue, 19 May 2020 23:26:58 +0800 Subject: [PATCH 345/357] fix https://github.com/acmesh-official/acme.sh/issues/2880 --- acme.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index dd47481d..c92a9980 100755 --- a/acme.sh +++ b/acme.sh @@ -1986,7 +1986,9 @@ _send_signed_request() { continue fi if [ "$ACME_VERSION" = "2" ]; then - if [ "$url" = "$ACME_NEW_ACCOUNT" ] || [ "$url" = "$ACME_REVOKE_CERT" ]; 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}\""'}' From 63031fb278f8a627351d633a295d39432cb47b30 Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Tue, 19 May 2020 20:04:23 +0200 Subject: [PATCH 346/357] bugfixes --- acme.sh | 2 +- dnsapi/dns_transip.sh | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index d3c357fc..8a29cebf 100755 --- a/acme.sh +++ b/acme.sh @@ -1003,7 +1003,7 @@ _sign() { _sign_openssl="${ACME_OPENSSL_BIN:-openssl} dgst -sign $keyfile " - if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; || if grep "BEGIN PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then + if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1 || grep "BEGIN PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then $_sign_openssl -$alg | _base64 elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then if ! _signedECText="$($_sign_openssl -sha$__ECC_KEY_LEN | ${ACME_OPENSSL_BIN:-openssl} asn1parse -inform DER)"; then diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh index 8764c1c4..36c48ce3 100644 --- a/dnsapi/dns_transip.sh +++ b/dnsapi/dns_transip.sh @@ -94,6 +94,10 @@ _transip_rest() { _transip_get_token() { nonce=$(echo "TRANSIP$(_time)" | _digest sha1 hex) + nonce_old=$(openssl rand -hex 12) + nonce=${nonce:0:32} + _debug nonce "$nonce" + _debug nonce_old "$nonce_old" data="{\"login\":\"${TRANSIP_Username}\",\"nonce\":\"${nonce}\",\"read_only\":\"${TRANSIP_Token_Read_Only}\",\"expiration_time\":\"${TRANSIP_Token_Expiration}\",\"label\":\"${TRANSIP_Token_Label}\",\"global_key\":\"${TRANSIP_Token_Global_Key}\"}" _debug data "$data" From 70619dd0b77f33ad2358b8adcde9aee555c8e44b Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Tue, 19 May 2020 20:07:14 +0200 Subject: [PATCH 347/357] Remove debugging --- dnsapi/dns_transip.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh index 36c48ce3..2b1d2284 100644 --- a/dnsapi/dns_transip.sh +++ b/dnsapi/dns_transip.sh @@ -94,10 +94,8 @@ _transip_rest() { _transip_get_token() { nonce=$(echo "TRANSIP$(_time)" | _digest sha1 hex) - nonce_old=$(openssl rand -hex 12) nonce=${nonce:0:32} _debug nonce "$nonce" - _debug nonce_old "$nonce_old" data="{\"login\":\"${TRANSIP_Username}\",\"nonce\":\"${nonce}\",\"read_only\":\"${TRANSIP_Token_Read_Only}\",\"expiration_time\":\"${TRANSIP_Token_Expiration}\",\"label\":\"${TRANSIP_Token_Label}\",\"global_key\":\"${TRANSIP_Token_Global_Key}\"}" _debug data "$data" From 063562261e97e435e73a05ccfe7340c36b10d512 Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Tue, 19 May 2020 23:09:16 +0200 Subject: [PATCH 348/357] Fix string truncation for POSIX --- dnsapi/dns_transip.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh index 2b1d2284..23debe0d 100644 --- a/dnsapi/dns_transip.sh +++ b/dnsapi/dns_transip.sh @@ -93,8 +93,7 @@ _transip_rest() { } _transip_get_token() { - nonce=$(echo "TRANSIP$(_time)" | _digest sha1 hex) - nonce=${nonce:0:32} + nonce=$(echo "TRANSIP$(_time)" | _digest sha1 hex | cut -c 1-32) _debug nonce "$nonce" data="{\"login\":\"${TRANSIP_Username}\",\"nonce\":\"${nonce}\",\"read_only\":\"${TRANSIP_Token_Read_Only}\",\"expiration_time\":\"${TRANSIP_Token_Expiration}\",\"label\":\"${TRANSIP_Token_Label}\",\"global_key\":\"${TRANSIP_Token_Global_Key}\"}" From 59fd48cfe27219af0737b0735f66a35f209a2042 Mon Sep 17 00:00:00 2001 From: neil Date: Tue, 19 May 2020 22:34:19 +0800 Subject: [PATCH 349/357] support Retry-After header https://github.com/acmesh-official/acme.sh/issues/2939 --- acme.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/acme.sh b/acme.sh index 48c71df3..419e23df 100755 --- a/acme.sh +++ b/acme.sh @@ -4517,6 +4517,12 @@ $_authorizations_map" _info "Pending" elif [ "$status" = "processing" ]; then _info "Processing" + _retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *:" | cut -d : -f 2 | tr -d ' ') + _debug "_retryafter" "$_retryafter" + if [ "$_retryafter" ]; then + _info "Retry after: $_retryafter" + _sleep $_retryafter + fi else _err "$d:Verify error:$response" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" From a78a09f594936b503823c99f180acea79ba6355a Mon Sep 17 00:00:00 2001 From: PM Extra Date: Thu, 14 May 2020 17:15:31 +0800 Subject: [PATCH 350/357] Support multiple servers for SSH deployment. --- deploy/ssh.sh | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index d71637a1..06d4b2b4 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -33,10 +33,7 @@ ssh_deploy() { _ccert="$3" _cca="$4" _cfullchain="$5" - _err_code=0 - _cmdstr="" - _backupprefix="" - _backupdir="" + _deploy_ssh_servers="" if [ -f "$DOMAIN_CONF" ]; then # shellcheck disable=SC1090 @@ -102,6 +99,18 @@ ssh_deploy() { _cleardomainconf Le_Deploy_ssh_multi_call fi + _deploy_ssh_servers=$Le_Deploy_ssh_server + for Le_Deploy_ssh_server in $_deploy_ssh_servers; do + _ssh_deploy + done +} + +_ssh_deploy() { + _err_code=0 + _cmdstr="" + _backupprefix="" + _backupdir="" + _info "Deploy certificates to remote server $Le_Deploy_ssh_user@$Le_Deploy_ssh_server" if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then _info "Using MULTI_CALL mode... Required commands sent in multiple calls to remote host" From 427c278012cb40e9b5d5fb11f46b704941f33605 Mon Sep 17 00:00:00 2001 From: Dan Dascalescu Date: Fri, 22 May 2020 10:28:29 -0700 Subject: [PATCH 351/357] Fix sloppy English --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 419e23df..5539b32c 100755 --- a/acme.sh +++ b/acme.sh @@ -4299,7 +4299,7 @@ $_authorizations_map" if [ "$dns_entries" ]; then if [ -z "$Le_DNSSleep" ]; then - _info "Let's check each dns records now. Sleep 20 seconds first." + _info "Let's check each DNS record now. Sleep 20 seconds first." _sleep 20 if ! _check_dns_entries; then _err "check dns error." From e8defd821a9d6f838ea1591d8c719db879a726c8 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 23 May 2020 20:37:06 +0800 Subject: [PATCH 352/357] update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 249dc85f..d27a024e 100644 --- a/README.md +++ b/README.md @@ -246,7 +246,7 @@ More examples: https://github.com/acmesh-official/acme.sh/wiki/How-to-issue-a-ce **(requires you to be root/sudoer, since it is required to interact with Apache server)** -If you are running a web server, Apache or Nginx, it is recommended to use the `Webroot mode`. +If you are running a web server, it is recommended to use the `Webroot mode`. Particularly, if you are running an Apache server, you can use Apache mode instead. This mode doesn't write any files to your web root folder. @@ -266,7 +266,7 @@ More examples: https://github.com/acmesh-official/acme.sh/wiki/How-to-issue-a-ce **(requires you to be root/sudoer, since it is required to interact with Nginx server)** -If you are running a web server, Apache or Nginx, it is recommended to use the `Webroot mode`. +If you are running a web server, it is recommended to use the `Webroot mode`. Particularly, if you are running an nginx server, you can use nginx mode instead. This mode doesn't write any files to your web root folder. From 15dded712c6c255715887be7ee5b29775257c18b Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 24 May 2020 18:04:47 +0800 Subject: [PATCH 353/357] fix retry https://github.com/acmesh-official/acme.sh/issues/2939#issuecomment-632481658 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 5539b32c..682456a1 100755 --- a/acme.sh +++ b/acme.sh @@ -4517,7 +4517,7 @@ $_authorizations_map" _info "Pending" elif [ "$status" = "processing" ]; then _info "Processing" - _retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *:" | cut -d : -f 2 | tr -d ' ') + _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" From 0ab14399ae1863e949639f78e5b3ac60501c9e46 Mon Sep 17 00:00:00 2001 From: DerVerruckteFuchs Date: Mon, 25 May 2020 12:00:54 -0400 Subject: [PATCH 354/357] Fix broken grep so that One984HOSTING_COOKIE actually gets set, and isn't left empty. --- 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 b7cb36d7..d84ea1f7 100755 --- a/dnsapi/dns_1984hosting.sh +++ b/dnsapi/dns_1984hosting.sh @@ -168,7 +168,7 @@ _1984hosting_login() { _debug2 response "$response" if [ "$response" = '{"loggedin": true, "ok": true}' ]; then - One984HOSTING_COOKIE="$(grep '^Set-Cookie:' "$HTTP_HEADER" | _tail_n 1 | _egrep_o 'sessionid=[^;]*;' | tr -d ';')" + One984HOSTING_COOKIE="$(grep '^set-cookie:' "$HTTP_HEADER" | _tail_n 1 | _egrep_o 'sessionid=[^;]*;' | tr -d ';')" export One984HOSTING_COOKIE _saveaccountconf_mutable One984HOSTING_COOKIE "$One984HOSTING_COOKIE" return 0 From 1fe8235a85821561ca49e3c563410870b81ea4ca Mon Sep 17 00:00:00 2001 From: grindsa Date: Mon, 25 May 2020 20:28:05 +0200 Subject: [PATCH 355/357] Update acme.sh --- acme.sh | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/acme.sh b/acme.sh index 682456a1..0e3110a6 100755 --- a/acme.sh +++ b/acme.sh @@ -4517,12 +4517,6 @@ $_authorizations_map" _info "Pending" elif [ "$status" = "processing" ]; then _info "Processing" - _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 - fi else _err "$d:Verify error:$response" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" @@ -4574,7 +4568,14 @@ $_authorizations_map" break elif _contains "$response" "\"processing\""; then _info "Order status is processing, lets sleep and retry." - _sleep 2 + _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" _err "$response" From 025da9245039d897a46edbcb74604c029da08f91 Mon Sep 17 00:00:00 2001 From: DerVerruckteFuchs Date: Tue, 26 May 2020 02:00:05 -0400 Subject: [PATCH 356/357] Handle case insensitivity for HTTP/1.1 headers. --- 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 d84ea1f7..09f02796 100755 --- a/dnsapi/dns_1984hosting.sh +++ b/dnsapi/dns_1984hosting.sh @@ -168,7 +168,7 @@ _1984hosting_login() { _debug2 response "$response" if [ "$response" = '{"loggedin": true, "ok": true}' ]; then - One984HOSTING_COOKIE="$(grep '^set-cookie:' "$HTTP_HEADER" | _tail_n 1 | _egrep_o 'sessionid=[^;]*;' | tr -d ';')" + One984HOSTING_COOKIE="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _tail_n 1 | _egrep_o 'sessionid=[^;]*;' | tr -d ';')" export One984HOSTING_COOKIE _saveaccountconf_mutable One984HOSTING_COOKIE "$One984HOSTING_COOKIE" return 0 From f03904ebceaf77cede8bd99bee2917a334095751 Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Tue, 9 Jun 2020 09:57:36 +0200 Subject: [PATCH 357/357] change to --output QUIET --- dnsapi/dns_lexicon.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_lexicon.sh b/dnsapi/dns_lexicon.sh index 34a95599..44bfa735 100755 --- a/dnsapi/dns_lexicon.sh +++ b/dnsapi/dns_lexicon.sh @@ -92,7 +92,7 @@ dns_lexicon_add() { _savedomainconf LEXICON_OPTS "$LEXICON_OPTS" # shellcheck disable=SC2086 - $lexicon_cmd "$PROVIDER" $LEXICON_OPTS create "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}" >/dev/null + $lexicon_cmd "$PROVIDER" $LEXICON_OPTS create "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}" --output QUIET } @@ -108,6 +108,6 @@ dns_lexicon_rm() { domain=$(printf "%s" "$fulldomain" | cut -d . -f 2-999) # shellcheck disable=SC2086 - $lexicon_cmd "$PROVIDER" $LEXICON_OPTS delete "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}" >/dev/null + $lexicon_cmd "$PROVIDER" $LEXICON_OPTS delete "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}" --output QUIET }