From 841b762796d4909d0bc40cfa7e4a9147aa17e28a Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 23 Jun 2017 18:11:11 +0800 Subject: [PATCH 01/30] minor --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 09cc9fd4..70033523 100755 --- a/acme.sh +++ b/acme.sh @@ -453,7 +453,7 @@ if [ "$(printf '\x41')" != 'A' ]; then fi _ESCAPE_XARGS="" -if [ "$(printf %s '\\x41' | xargs printf)" = 'A' ]; then +if _exists xargs && [ "$(printf %s '\\x41' | xargs printf)" = 'A' ]; then _ESCAPE_XARGS=1 fi From eb0ef6bd3dd56af440628b9b0f0edeb3753cf863 Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 27 Jun 2017 19:56:43 +0800 Subject: [PATCH 02/30] fix https://github.com/Neilpang/acme.sh/issues/614#issuecomment-311160843 --- acme.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 70033523..fa969b0f 100755 --- a/acme.sh +++ b/acme.sh @@ -1138,7 +1138,12 @@ _readKeyLengthFromCSR() { echo "$_outcsr" | tr "\t" " " | _egrep_o "^ *ASN1 OID:.*" | cut -d ':' -f 2 | tr -d ' ' else _debug "RSA CSR" - echo "$_outcsr" | tr "\t" " " | (_egrep_o "^ *Public.Key:.*" || _egrep_o "RSA Public.Key:.*") | cut -d '(' -f 2 | cut -d ' ' -f 1 + _rkl="$(echo "$_outcsr" | tr "\t" " " | _egrep_o "^ *Public.Key:.*" | cut -d '(' -f 2 | cut -d ' ' -f 1)" + if [ "$_rkl" ]; then + echo "$_rkl" + else + echo "$_outcsr" | tr "\t" " " | _egrep_o "RSA Public.Key:.*" | cut -d '(' -f 2 | cut -d ' ' -f 1 + fi fi } From fa98d72f3a87cf438ba16cccccf61fc268c517df Mon Sep 17 00:00:00 2001 From: RaidenII Date: Tue, 27 Jun 2017 09:21:39 -0400 Subject: [PATCH 03/30] Added preliminary support for DuckDNS TXT record API, a free Dynamic DNS provider --- dnsapi/dns_duckdns.sh | 93 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100755 dnsapi/dns_duckdns.sh diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh new file mode 100755 index 00000000..dc0d49ca --- /dev/null +++ b/dnsapi/dns_duckdns.sh @@ -0,0 +1,93 @@ +#!/usr/bin/env sh + +#Created by RaidenII, to use DuckDNS's API to add/remove text records +#06/27/2017 + +# Currently only support single domain access + +# DuckDNS uses StartSSL as their cert provider +# Seems not supported natively on Linux +# So I fall back to HTTP for API +DuckDNS_API="http://www.duckdns.org/update" + +######## Public functions ##################### + +#Usage: dns_duckdns_add _acme-challenge.domain.duckdns.org "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_duckdns_add() { + fulldomain=$1 + txtvalue=$2 + + # We'll extract the domain/username from full domain + IFS='.' read -r -a fqdn <<< "$fulldomain" + DuckDNS_domain="${fqdn[-3]}" + + if [ -z "$DuckDNS_domain" ]; then + _err "Error extracting the domain." + return 1 + fi + + if [ -z "$DuckDNS_token" ]; then + DuckDNS_token="" + _err "The token for your DuckDNS account is necessary." + _err "You can look it up in your DuckDNS account." + return 1 + fi + + # Now save the credentials. + _saveaccountconf DuckDNS_domain "$DuckDNS_domain" + _saveaccountconf DuckDNS_token "$DuckDNS_token" + + # Unfortunately, DuckDNS does not seems to support lookup domain through API + # So I assume your credentials (which are your domain and token) are correct + # If something goes wrong, we will get a KO response from DuckDNS + + # Now add the TXT record to DuckDNS + _info "Trying to add TXT record" + if _duckdns_rest GET "domains=$DuckDNS_domain&token=$DuckDNS_token&txt=$txtvalue" && [ $response == "OK" ]; then + _info "TXT record has been successfully added to your DuckDNS domain." + _info "Note that all subdomains under this domain uses the same TXT record." + return 0 + else + _err "Errors happened during adding the TXT record." + return 1 + fi +} + +#Usage: fulldomain txtvalue +#Remove the txt record after validation. +dns_duckdns_rm() { + fulldomain=$1 + txtvalue=$2 + + # Now remove the TXT record from DuckDNS + _info "Trying to from TXT record" + if _duckdns_rest GET "domains=$DuckDNS_domain&token=$DuckDNS_token&txt=''&clear=true" && [ $response == "OK" ]; then + _info "TXT record has been successfully removed from your DuckDNS domain." + return 0 + else + _err "Errors happened during removing the TXT record." + return 1 + fi +} + +#################### Private functions below ################################## + +#Usage: method URI data +_duckdns_rest() { + method=$1 + param="$2" + _debug param "$param" + url="$DuckDNS_API?$param" + _debug url "$url" + + # DuckDNS uses GET to update domain info + if [ $method == "GET" ]; then + response="$(_get "$url")" + else + _err "Unsupported method" + return 1 + fi + + _debug response "$response" + return 0 +} From e7dff4756ffef5f14b40363cc2a888977b9d9efd Mon Sep 17 00:00:00 2001 From: RaidenII Date: Tue, 27 Jun 2017 15:28:10 -0400 Subject: [PATCH 04/30] Using HTTPS for DuckDNS API and added instruction. --- dnsapi/dns_duckdns.sh | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index dc0d49ca..847b3fc5 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -4,11 +4,10 @@ #06/27/2017 # Currently only support single domain access +# Due to the fact that DuckDNS uses StartSSL as cert provider, --insecure must be used with acme.sh -# DuckDNS uses StartSSL as their cert provider -# Seems not supported natively on Linux -# So I fall back to HTTP for API -DuckDNS_API="http://www.duckdns.org/update" +DuckDNS_API="https://www.duckdns.org/update" +API_Params="domains=$DuckDNS_domain&token=$DuckDNS_token" ######## Public functions ##################### @@ -43,7 +42,7 @@ dns_duckdns_add() { # Now add the TXT record to DuckDNS _info "Trying to add TXT record" - if _duckdns_rest GET "domains=$DuckDNS_domain&token=$DuckDNS_token&txt=$txtvalue" && [ $response == "OK" ]; then + if _duckdns_rest GET "$API_Params&txt=$txtvalue" && [ $response == "OK" ]; then _info "TXT record has been successfully added to your DuckDNS domain." _info "Note that all subdomains under this domain uses the same TXT record." return 0 @@ -60,8 +59,8 @@ dns_duckdns_rm() { txtvalue=$2 # Now remove the TXT record from DuckDNS - _info "Trying to from TXT record" - if _duckdns_rest GET "domains=$DuckDNS_domain&token=$DuckDNS_token&txt=''&clear=true" && [ $response == "OK" ]; then + _info "Trying to remove TXT record" + if _duckdns_rest GET "$API_Params&txt=''&clear=true" && [ $response == "OK" ]; then _info "TXT record has been successfully removed from your DuckDNS domain." return 0 else @@ -72,7 +71,7 @@ dns_duckdns_rm() { #################### Private functions below ################################## -#Usage: method URI data +#Usage: method URI _duckdns_rest() { method=$1 param="$2" From 9dd62ae0f8de8e125edb8396a1b25aba3d712bd3 Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 28 Jun 2017 19:21:03 +0800 Subject: [PATCH 05/30] fix https://github.com/Neilpang/acme.sh/issues/900 --- Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5254bd11..8f363852 100644 --- a/Dockerfile +++ b/Dockerfile @@ -50,9 +50,10 @@ RUN for verb in help \ RUN printf "%b" '#!'"/usr/bin/env sh\n \ if [ \"\$1\" = \"daemon\" ]; then \n \ - crond -f\n \ + trap \"echo stop && killall crond && exit 0\" SIGTERM SIGINT \n \ + crond && while true; do sleep 1; done;\n \ else \n \ - /root/.acme.sh/acme.sh --config-home /acme.sh \"\$@\"\n \ + exec -- \"\$@\"\n \ fi" >/entry.sh && chmod +x /entry.sh VOLUME /acme.sh From 7d2b6cfeaf888a34526fa291e5d9b5ad350ff6ff Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 28 Jun 2017 19:46:51 +0800 Subject: [PATCH 06/30] fix https://github.com/Neilpang/acme.sh/issues/905 --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 13188982..5b6b03ae 100644 --- a/README.md +++ b/README.md @@ -296,6 +296,9 @@ acme.sh --renew -d example.com Ok, it's finished. +**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.** # 9. Automatic DNS API integration From e64ad5176ef6e4865c0d8fd7da83e318e07ef853 Mon Sep 17 00:00:00 2001 From: RaidenII Date: Wed, 28 Jun 2017 16:15:57 -0400 Subject: [PATCH 07/30] Added Name.com API support. Minor change to DuckDNS API support. --- dnsapi/dns_duckdns.sh | 2 +- dnsapi/dns_namecom.sh | 188 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+), 1 deletion(-) create mode 100755 dnsapi/dns_namecom.sh diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index 847b3fc5..f86d516e 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -60,7 +60,7 @@ dns_duckdns_rm() { # Now remove the TXT record from DuckDNS _info "Trying to remove TXT record" - if _duckdns_rest GET "$API_Params&txt=''&clear=true" && [ $response == "OK" ]; then + if _duckdns_rest GET "$API_Params&txt=&clear=true" && [ $response == "OK" ]; then _info "TXT record has been successfully removed from your DuckDNS domain." return 0 else diff --git a/dnsapi/dns_namecom.sh b/dnsapi/dns_namecom.sh new file mode 100755 index 00000000..7a84685f --- /dev/null +++ b/dnsapi/dns_namecom.sh @@ -0,0 +1,188 @@ +#!/usr/bin/env sh + +#Author: RaidneII +#Created 06/28/2017 +#Utilize name.com API to finish dns-01 verifications. +######## Public functions ##################### + +namecom_api="https://api.name.com/api/" + +#Usage: dns_namecom_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_namecom_add() { + fulldomain=$1 + txtvalue=$2 + + # First we need name.com credentials. + if [ -z "$namecom_username" ]; then + namecom_username="" + _err "Username for name.com is missing." + _err "Please specify that in your environment variable." + return 1 + fi + + if [ -z "$namecom_token" ]; then + namecom_token="" + _err "API token for name.com is missing." + _err "Please specify that in your environment variable." + return 1 + fi + + # Save them in configuration. + _saveaccountconf namecom_username "$namecom_username" + _saveaccountconf namecom_token "$namecom_token" + + # Login in using API + _namecom_login + + # Find domain in domain list. + if ! _namecom_get_root "$fulldomain"; then + _err "Unable to find domain specified." + _namecom_logout + return 1 + fi + + # Add TXT record. + _namecom_addtxt_json="{\"hostname\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":\"300\",\"priority\":\"10\"}" + if _namecom_rest POST "dns/create/$_domain" "$_namecom_addtxt_json"; then + retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") + _debug retcode "$retcode" + if [ ! -z "$retcode" ]; then + _info "Successfully added TXT record, ready for validation." + _namecom_logout + return 0 + else + _err "Unable to add the DNS record." + _namecom_logout + return 1 + fi + fi +} + +#Usage: fulldomain txtvalue +#Remove the txt record after validation. +dns_namecom_rm() { + fulldomain=$1 + txtvalue=$2 + + _namecom_login + + # Find domain in domain list. + if ! _namecom_get_root "$fulldomain"; then + _err "Unable to find domain specified." + _namecom_logout + return 1 + fi + + # Get the record id. + if _namecom_rest GET "dns/list/$_domain"; then + retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") + _debug retcode "$retcode" + if [ ! -z "$retcode" ]; then + _record_id=$(printf "%s\n" "$response" | _egrep_o "\"record_id\":\"[0-9]+\",\"name\":\"$fulldomain\",\"type\":\"TXT\"" | cut -d : -f 2 | cut -d \" -f 2) + _debug record_id "$_record_id" + _info "Successfully retrieved the record id for ACME challenge." + else + _err "Unable to retrieve the record id." + _namecom_logout + return 1 + fi + fi + + # Remove the DNS record using record id. + _namecom_rmtxt_json="{\"record_id\":\"$_record_id\"}" + if _namecom_rest POST "dns/delete/$_domain" "$_namecom_rmtxt_json"; then + retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") + _debug retcode "$retcode" + if [ ! -z "$retcode" ]; then + _info "Successfully removed the TXT record." + _namecom_logout + return 0 + else + _err "Unable to remove the DNS record." + _namecom_logout + return 1 + fi + fi +} + +#################### Private functions below ################################## +_namecom_rest() { + method=$1 + param=$2 + data=$3 + + export _H1="Content-Type: application/json" + export _H2="Api-Session-Token: $sessionkey" + if [ "$method" != "GET" ]; then + response="$(_post "$data" "$namecom_api/$param" "" "$method")" + else + response="$(_get "$namecom_api/$param")" + fi + + if [ "$?" != "0" ]; then + _err "error $param" + return 1 + fi + + _debug response "$response" + return 0 +} + +_namecom_login() { + namecom_login_json="{\"username\":\"$namecom_username\",\"api_token\":\"$namecom_token\"}" + + if _namecom_rest POST "login" "$namecom_login_json"; then + retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") + _debug retcode "$retcode" + if [ ! -z "$retcode" ]; then + _info "Successfully logged in. Fetching session token..." + sessionkey=$(printf "%s\n" "$response" | _egrep_o "\"session_token\":\".+" | cut -d \" -f 4) + if [ ! -z "$sessionkey" ]; then + _debug sessionkey "$sessionkey" + _info "Session key obtained." + else + _err "Unable to get session key." + return 1 + fi + else + _err "Logging in failed." + return 1 + fi + fi +} + +_namecom_logout() { + if _namecom_rest GET "logout"; then + retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") + if [ ! -z "$retcode" ]; then + _info "Successfully logged out." + else + _err "Error logging out." + return 1 + fi + fi +} + +_namecom_get_root() { + domain=$1 + i=2 + p=1 + + if _namecom_rest GET "domain/list"; then + while true; do + host=$(printf "%s" "$domain" | cut -d . -f $i-100) + if [ -z "$host" ]; then + return 1 + fi + + if _contains "$response" "$host"; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain="$host" + return 0 + fi + p=$i + i=$(_math "$i" + 1) + done + fi + return 1 +} From 168d712decb687c4ac665b02df716a7de9c99b6e Mon Sep 17 00:00:00 2001 From: RaidenII Date: Thu, 29 Jun 2017 09:43:11 -0400 Subject: [PATCH 08/30] Fixed URL of Name.com API and removed useless debug for retcode. --- dnsapi/dns_namecom.sh | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/dnsapi/dns_namecom.sh b/dnsapi/dns_namecom.sh index 7a84685f..158a11b0 100755 --- a/dnsapi/dns_namecom.sh +++ b/dnsapi/dns_namecom.sh @@ -5,7 +5,7 @@ #Utilize name.com API to finish dns-01 verifications. ######## Public functions ##################### -namecom_api="https://api.name.com/api/" +namecom_api="https://api.name.com/api" #Usage: dns_namecom_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_namecom_add() { @@ -45,7 +45,6 @@ dns_namecom_add() { _namecom_addtxt_json="{\"hostname\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":\"300\",\"priority\":\"10\"}" if _namecom_rest POST "dns/create/$_domain" "$_namecom_addtxt_json"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - _debug retcode "$retcode" if [ ! -z "$retcode" ]; then _info "Successfully added TXT record, ready for validation." _namecom_logout @@ -76,7 +75,6 @@ dns_namecom_rm() { # Get the record id. if _namecom_rest GET "dns/list/$_domain"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - _debug retcode "$retcode" if [ ! -z "$retcode" ]; then _record_id=$(printf "%s\n" "$response" | _egrep_o "\"record_id\":\"[0-9]+\",\"name\":\"$fulldomain\",\"type\":\"TXT\"" | cut -d : -f 2 | cut -d \" -f 2) _debug record_id "$_record_id" @@ -92,7 +90,6 @@ dns_namecom_rm() { _namecom_rmtxt_json="{\"record_id\":\"$_record_id\"}" if _namecom_rest POST "dns/delete/$_domain" "$_namecom_rmtxt_json"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - _debug retcode "$retcode" if [ ! -z "$retcode" ]; then _info "Successfully removed the TXT record." _namecom_logout @@ -133,7 +130,6 @@ _namecom_login() { if _namecom_rest POST "login" "$namecom_login_json"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - _debug retcode "$retcode" if [ ! -z "$retcode" ]; then _info "Successfully logged in. Fetching session token..." sessionkey=$(printf "%s\n" "$response" | _egrep_o "\"session_token\":\".+" | cut -d \" -f 4) From eeda3062e1c2a79d65e01db192582586e11fb517 Mon Sep 17 00:00:00 2001 From: RaidenII Date: Thu, 29 Jun 2017 15:40:29 -0400 Subject: [PATCH 09/30] Fix against POSIX standard. --- dnsapi/dns_duckdns.sh | 9 ++-- dnsapi/dns_namecom.sh | 104 +++++++++++++++++++++--------------------- 2 files changed, 56 insertions(+), 57 deletions(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index f86d516e..a34c8d36 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -17,8 +17,7 @@ dns_duckdns_add() { txtvalue=$2 # We'll extract the domain/username from full domain - IFS='.' read -r -a fqdn <<< "$fulldomain" - DuckDNS_domain="${fqdn[-3]}" + DuckDNS_domain=$(printf "%s\n" "$fulldomain" | rev | cut -d \. -f 3 | rev) if [ -z "$DuckDNS_domain" ]; then _err "Error extracting the domain." @@ -42,7 +41,7 @@ dns_duckdns_add() { # Now add the TXT record to DuckDNS _info "Trying to add TXT record" - if _duckdns_rest GET "$API_Params&txt=$txtvalue" && [ $response == "OK" ]; then + if _duckdns_rest GET "$API_Params&txt=$txtvalue" && [ "$response" -eq "OK" ]; then _info "TXT record has been successfully added to your DuckDNS domain." _info "Note that all subdomains under this domain uses the same TXT record." return 0 @@ -60,7 +59,7 @@ dns_duckdns_rm() { # Now remove the TXT record from DuckDNS _info "Trying to remove TXT record" - if _duckdns_rest GET "$API_Params&txt=&clear=true" && [ $response == "OK" ]; then + if _duckdns_rest GET "$API_Params&txt=&clear=true" && [ "$response" -eq "OK" ]; then _info "TXT record has been successfully removed from your DuckDNS domain." return 0 else @@ -80,7 +79,7 @@ _duckdns_rest() { _debug url "$url" # DuckDNS uses GET to update domain info - if [ $method == "GET" ]; then + if [ "$method" -eq "GET" ]; then response="$(_get "$url")" else _err "Unsupported method" diff --git a/dnsapi/dns_namecom.sh b/dnsapi/dns_namecom.sh index 158a11b0..9a6e81f9 100755 --- a/dnsapi/dns_namecom.sh +++ b/dnsapi/dns_namecom.sh @@ -45,15 +45,15 @@ dns_namecom_add() { _namecom_addtxt_json="{\"hostname\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":\"300\",\"priority\":\"10\"}" if _namecom_rest POST "dns/create/$_domain" "$_namecom_addtxt_json"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - if [ ! -z "$retcode" ]; then - _info "Successfully added TXT record, ready for validation." - _namecom_logout - return 0 - else - _err "Unable to add the DNS record." - _namecom_logout - return 1 - fi + if [ ! -z "$retcode" ]; then + _info "Successfully added TXT record, ready for validation." + _namecom_logout + return 0 + else + _err "Unable to add the DNS record." + _namecom_logout + return 1 + fi fi } @@ -75,30 +75,30 @@ dns_namecom_rm() { # Get the record id. if _namecom_rest GET "dns/list/$_domain"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - if [ ! -z "$retcode" ]; then - _record_id=$(printf "%s\n" "$response" | _egrep_o "\"record_id\":\"[0-9]+\",\"name\":\"$fulldomain\",\"type\":\"TXT\"" | cut -d : -f 2 | cut -d \" -f 2) - _debug record_id "$_record_id" - _info "Successfully retrieved the record id for ACME challenge." - else - _err "Unable to retrieve the record id." - _namecom_logout - return 1 - fi + if [ ! -z "$retcode" ]; then + _record_id=$(printf "%s\n" "$response" | _egrep_o "\"record_id\":\"[0-9]+\",\"name\":\"$fulldomain\",\"type\":\"TXT\"" | cut -d : -f 2 | cut -d \" -f 2) + _debug record_id "$_record_id" + _info "Successfully retrieved the record id for ACME challenge." + else + _err "Unable to retrieve the record id." + _namecom_logout + return 1 + fi fi # Remove the DNS record using record id. _namecom_rmtxt_json="{\"record_id\":\"$_record_id\"}" if _namecom_rest POST "dns/delete/$_domain" "$_namecom_rmtxt_json"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - if [ ! -z "$retcode" ]; then - _info "Successfully removed the TXT record." - _namecom_logout - return 0 - else - _err "Unable to remove the DNS record." - _namecom_logout - return 1 - fi + if [ ! -z "$retcode" ]; then + _info "Successfully removed the TXT record." + _namecom_logout + return 0 + else + _err "Unable to remove the DNS record." + _namecom_logout + return 1 + fi fi } @@ -130,32 +130,32 @@ _namecom_login() { if _namecom_rest POST "login" "$namecom_login_json"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - if [ ! -z "$retcode" ]; then - _info "Successfully logged in. Fetching session token..." - sessionkey=$(printf "%s\n" "$response" | _egrep_o "\"session_token\":\".+" | cut -d \" -f 4) - if [ ! -z "$sessionkey" ]; then - _debug sessionkey "$sessionkey" - _info "Session key obtained." - else - _err "Unable to get session key." - return 1 - fi + if [ ! -z "$retcode" ]; then + _info "Successfully logged in. Fetching session token..." + sessionkey=$(printf "%s\n" "$response" | _egrep_o "\"session_token\":\".+" | cut -d \" -f 4) + if [ ! -z "$sessionkey" ]; then + _debug sessionkey "$sessionkey" + _info "Session key obtained." else - _err "Logging in failed." + _err "Unable to get session key." return 1 fi - fi + else + _err "Logging in failed." + return 1 + fi + fi } _namecom_logout() { if _namecom_rest GET "logout"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - if [ ! -z "$retcode" ]; then - _info "Successfully logged out." - else - _err "Error logging out." - return 1 - fi + if [ ! -z "$retcode" ]; then + _info "Successfully logged out." + else + _err "Error logging out." + return 1 + fi fi } @@ -171,13 +171,13 @@ _namecom_get_root() { return 1 fi - if _contains "$response" "$host"; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) - _domain="$host" - return 0 - fi - p=$i - i=$(_math "$i" + 1) + if _contains "$response" "$host"; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain="$host" + return 0 + fi + p=$i + i=$(_math "$i" + 1) done fi return 1 From d0f5aece5f5c1708668faed8e2a7fe5671eceea8 Mon Sep 17 00:00:00 2001 From: RaidenII Date: Thu, 29 Jun 2017 15:43:58 -0400 Subject: [PATCH 10/30] Fix SC2170. --- dnsapi/dns_duckdns.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index a34c8d36..b1937cb8 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -41,7 +41,7 @@ dns_duckdns_add() { # Now add the TXT record to DuckDNS _info "Trying to add TXT record" - if _duckdns_rest GET "$API_Params&txt=$txtvalue" && [ "$response" -eq "OK" ]; then + if _duckdns_rest GET "$API_Params&txt=$txtvalue" && [ "$response" = "OK" ]; then _info "TXT record has been successfully added to your DuckDNS domain." _info "Note that all subdomains under this domain uses the same TXT record." return 0 @@ -59,7 +59,7 @@ dns_duckdns_rm() { # Now remove the TXT record from DuckDNS _info "Trying to remove TXT record" - if _duckdns_rest GET "$API_Params&txt=&clear=true" && [ "$response" -eq "OK" ]; then + if _duckdns_rest GET "$API_Params&txt=&clear=true" && [ "$response" = "OK" ]; then _info "TXT record has been successfully removed from your DuckDNS domain." return 0 else @@ -79,7 +79,7 @@ _duckdns_rest() { _debug url "$url" # DuckDNS uses GET to update domain info - if [ "$method" -eq "GET" ]; then + if [ "$method" = "GET" ]; then response="$(_get "$url")" else _err "Unsupported method" From 17fbfd14db2b71af580afb59cc515f09299ca37e Mon Sep 17 00:00:00 2001 From: RaidenII Date: Fri, 30 Jun 2017 08:32:39 -0400 Subject: [PATCH 11/30] Minor fixes. --- dnsapi/dns_duckdns.sh | 2 +- dnsapi/dns_namecom.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index b1937cb8..cacf5a8c 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -17,7 +17,7 @@ dns_duckdns_add() { txtvalue=$2 # We'll extract the domain/username from full domain - DuckDNS_domain=$(printf "%s\n" "$fulldomain" | rev | cut -d \. -f 3 | rev) + DuckDNS_domain=$(printf "%s\n" "$fulldomain" | rev | cut -d . -f 3 | rev) if [ -z "$DuckDNS_domain" ]; then _err "Error extracting the domain." diff --git a/dnsapi/dns_namecom.sh b/dnsapi/dns_namecom.sh index 9a6e81f9..2c5a5df4 100755 --- a/dnsapi/dns_namecom.sh +++ b/dnsapi/dns_namecom.sh @@ -76,7 +76,7 @@ dns_namecom_rm() { if _namecom_rest GET "dns/list/$_domain"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") if [ ! -z "$retcode" ]; then - _record_id=$(printf "%s\n" "$response" | _egrep_o "\"record_id\":\"[0-9]+\",\"name\":\"$fulldomain\",\"type\":\"TXT\"" | cut -d : -f 2 | cut -d \" -f 2) + _record_id=$(printf "%s\n" "$response" | _egrep_o "\"record_id\":\"[0-9]+\",\"name\":\"$fulldomain\",\"type\":\"TXT\"" | cut -d \" -f 4) _debug record_id "$_record_id" _info "Successfully retrieved the record id for ACME challenge." else From d04434e3ecd286c2109afd313aecf31d2cc7ec49 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 1 Jul 2017 10:54:14 +0800 Subject: [PATCH 12/30] fix alias --- acme.sh | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/acme.sh b/acme.sh index fa969b0f..1f1071d1 100755 --- a/acme.sh +++ b/acme.sh @@ -4679,6 +4679,8 @@ _installalias() { _setopt "$_envfile" "export LE_WORKING_DIR" "=" "\"$LE_WORKING_DIR\"" if [ "$_c_home" ]; then _setopt "$_envfile" "export LE_CONFIG_HOME" "=" "\"$LE_CONFIG_HOME\"" + else + _sed_i "/^export LE_CONFIG_HOME/d" "$_envfile" fi _setopt "$_envfile" "alias $PROJECT_ENTRY" "=" "\"$LE_WORKING_DIR/$PROJECT_ENTRY$_c_entry\"" @@ -4700,6 +4702,8 @@ _installalias() { _setopt "$_cshfile" "setenv LE_WORKING_DIR" " " "\"$LE_WORKING_DIR\"" if [ "$_c_home" ]; then _setopt "$_cshfile" "setenv LE_CONFIG_HOME" " " "\"$LE_CONFIG_HOME\"" + else + _sed_i "/^setenv LE_CONFIG_HOME/d" "$_cshfile" fi _setopt "$_cshfile" "alias $PROJECT_ENTRY" " " "\"$LE_WORKING_DIR/$PROJECT_ENTRY$_c_entry\"" _setopt "$_csh_profile" "source \"$_cshfile\"" @@ -4764,20 +4768,24 @@ install() { _info "Installing to $LE_WORKING_DIR" - if ! mkdir -p "$LE_WORKING_DIR"; then - _err "Can not create working dir: $LE_WORKING_DIR" - return 1 + if [ ! -d "$LE_WORKING_DIR" ]; then + if ! mkdir -p "$LE_WORKING_DIR"; then + _err "Can not create working dir: $LE_WORKING_DIR" + return 1 + fi + + chmod 700 "$LE_WORKING_DIR" fi - chmod 700 "$LE_WORKING_DIR" + if [ ! -d "$LE_CONFIG_HOME" ]; then + if ! mkdir -p "$LE_CONFIG_HOME"; then + _err "Can not create config dir: $LE_CONFIG_HOME" + return 1 + fi - if ! mkdir -p "$LE_CONFIG_HOME"; then - _err "Can not create config dir: $LE_CONFIG_HOME" - return 1 + chmod 700 "$LE_CONFIG_HOME" fi - chmod 700 "$LE_CONFIG_HOME" - cp "$PROJECT_ENTRY" "$LE_WORKING_DIR/" && chmod +x "$LE_WORKING_DIR/$PROJECT_ENTRY" if [ "$?" != "0" ]; then From 63c6ed3fd06263a5ad8ebb2788807bda13237f42 Mon Sep 17 00:00:00 2001 From: RaidenII Date: Sat, 1 Jul 2017 05:14:52 -0700 Subject: [PATCH 13/30] Fixes to follow coding standards. --- dnsapi/dns_duckdns.sh | 16 ++++++++-------- dnsapi/dns_namecom.sh | 32 ++++++++++++++++---------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index cacf5a8c..95df4c21 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -7,7 +7,7 @@ # Due to the fact that DuckDNS uses StartSSL as cert provider, --insecure must be used with acme.sh DuckDNS_API="https://www.duckdns.org/update" -API_Params="domains=$DuckDNS_domain&token=$DuckDNS_token" +API_Params="domains=$DuckDNS_Domain&token=$DuckDNS_Token" ######## Public functions ##################### @@ -17,23 +17,23 @@ dns_duckdns_add() { txtvalue=$2 # We'll extract the domain/username from full domain - DuckDNS_domain=$(printf "%s\n" "$fulldomain" | rev | cut -d . -f 3 | rev) + DuckDNS_Domain=$(echo $fulldomain | _lower_case | _egrep_o '.[^.]*.duckdns.org' | cut -d . -f 2) - if [ -z "$DuckDNS_domain" ]; then + if [ -z "$DuckDNS_Domain" ]; then _err "Error extracting the domain." return 1 fi - if [ -z "$DuckDNS_token" ]; then - DuckDNS_token="" + if [ -z "$DuckDNS_Token" ]; then + DuckDNS_Token="" _err "The token for your DuckDNS account is necessary." _err "You can look it up in your DuckDNS account." return 1 fi # Now save the credentials. - _saveaccountconf DuckDNS_domain "$DuckDNS_domain" - _saveaccountconf DuckDNS_token "$DuckDNS_token" + _saveaccountconf DuckDNS_Domain "$DuckDNS_Domain" + _saveaccountconf DuckDNS_Token "$DuckDNS_Token" # Unfortunately, DuckDNS does not seems to support lookup domain through API # So I assume your credentials (which are your domain and token) are correct @@ -86,6 +86,6 @@ _duckdns_rest() { return 1 fi - _debug response "$response" + _debug2 response "$response" return 0 } diff --git a/dnsapi/dns_namecom.sh b/dnsapi/dns_namecom.sh index 2c5a5df4..15eae6c2 100755 --- a/dnsapi/dns_namecom.sh +++ b/dnsapi/dns_namecom.sh @@ -5,7 +5,7 @@ #Utilize name.com API to finish dns-01 verifications. ######## Public functions ##################### -namecom_api="https://api.name.com/api" +Namecom_API="https://api.name.com/api" #Usage: dns_namecom_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_namecom_add() { @@ -13,23 +13,23 @@ dns_namecom_add() { txtvalue=$2 # First we need name.com credentials. - if [ -z "$namecom_username" ]; then - namecom_username="" + if [ -z "$Namecom_Username" ]; then + Namecom_Username="" _err "Username for name.com is missing." _err "Please specify that in your environment variable." return 1 fi - if [ -z "$namecom_token" ]; then - namecom_token="" + if [ -z "$Namecom_Token" ]; then + Namecom_Token="" _err "API token for name.com is missing." _err "Please specify that in your environment variable." return 1 fi # Save them in configuration. - _saveaccountconf namecom_username "$namecom_username" - _saveaccountconf namecom_token "$namecom_token" + _saveaccountconf Namecom_Username "$Namecom_Username" + _saveaccountconf Namecom_Token "$Namecom_Token" # Login in using API _namecom_login @@ -45,7 +45,7 @@ dns_namecom_add() { _namecom_addtxt_json="{\"hostname\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":\"300\",\"priority\":\"10\"}" if _namecom_rest POST "dns/create/$_domain" "$_namecom_addtxt_json"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - if [ ! -z "$retcode" ]; then + if [ "$retcode" ]; then _info "Successfully added TXT record, ready for validation." _namecom_logout return 0 @@ -75,7 +75,7 @@ dns_namecom_rm() { # Get the record id. if _namecom_rest GET "dns/list/$_domain"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - if [ ! -z "$retcode" ]; then + if [ "$retcode" ]; then _record_id=$(printf "%s\n" "$response" | _egrep_o "\"record_id\":\"[0-9]+\",\"name\":\"$fulldomain\",\"type\":\"TXT\"" | cut -d \" -f 4) _debug record_id "$_record_id" _info "Successfully retrieved the record id for ACME challenge." @@ -90,7 +90,7 @@ dns_namecom_rm() { _namecom_rmtxt_json="{\"record_id\":\"$_record_id\"}" if _namecom_rest POST "dns/delete/$_domain" "$_namecom_rmtxt_json"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - if [ ! -z "$retcode" ]; then + if [ "$retcode" ]; then _info "Successfully removed the TXT record." _namecom_logout return 0 @@ -111,9 +111,9 @@ _namecom_rest() { export _H1="Content-Type: application/json" export _H2="Api-Session-Token: $sessionkey" if [ "$method" != "GET" ]; then - response="$(_post "$data" "$namecom_api/$param" "" "$method")" + response="$(_post "$data" "$Namecom_API/$param" "" "$method")" else - response="$(_get "$namecom_api/$param")" + response="$(_get "$Namecom_API/$param")" fi if [ "$?" != "0" ]; then @@ -121,16 +121,16 @@ _namecom_rest() { return 1 fi - _debug response "$response" + _debug2 response "$response" return 0 } _namecom_login() { - namecom_login_json="{\"username\":\"$namecom_username\",\"api_token\":\"$namecom_token\"}" + namecom_login_json="{\"username\":\"$Namecom_Username\",\"api_token\":\"$Namecom_Token\"}" if _namecom_rest POST "login" "$namecom_login_json"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - if [ ! -z "$retcode" ]; then + if [ "$retcode" ]; then _info "Successfully logged in. Fetching session token..." sessionkey=$(printf "%s\n" "$response" | _egrep_o "\"session_token\":\".+" | cut -d \" -f 4) if [ ! -z "$sessionkey" ]; then @@ -150,7 +150,7 @@ _namecom_login() { _namecom_logout() { if _namecom_rest GET "logout"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - if [ ! -z "$retcode" ]; then + if [ "$retcode" ]; then _info "Successfully logged out." else _err "Error logging out." From 9aed1e2d17331e4c2eeb8ed9f48aa132bdbf07ae Mon Sep 17 00:00:00 2001 From: RaidenII Date: Sat, 1 Jul 2017 05:18:12 -0700 Subject: [PATCH 14/30] Argh. Double quotes. --- dnsapi/dns_duckdns.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index 95df4c21..d6987352 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -17,7 +17,7 @@ dns_duckdns_add() { txtvalue=$2 # We'll extract the domain/username from full domain - DuckDNS_Domain=$(echo $fulldomain | _lower_case | _egrep_o '.[^.]*.duckdns.org' | cut -d . -f 2) + DuckDNS_Domain=$(echo "$fulldomain" | _lower_case | _egrep_o '.[^.]*.duckdns.org' | cut -d . -f 2) if [ -z "$DuckDNS_Domain" ]; then _err "Error extracting the domain." From ea722da3deecf510c64e53df7b7ec4abe8c38123 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 1 Jul 2017 20:31:42 +0800 Subject: [PATCH 15/30] add debug info --- acme.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index 1f1071d1..76509af0 100755 --- a/acme.sh +++ b/acme.sh @@ -2999,9 +2999,9 @@ _on_issue_err() { fi #trigger the validation to flush the pending authz + _debug2 "_chk_vlist" "$_chk_vlist" if [ "$_chk_vlist" ]; then ( - _debug2 "_chk_vlist" "$_chk_vlist" _debug2 "start to deactivate authz" ventries=$(echo "$_chk_vlist" | tr "$dvsep" ' ') for ventry in $ventries; do @@ -3498,7 +3498,7 @@ issue() { if [ "$?" != "0" ]; then _clearup - _on_issue_err "$_post_hook" + _on_issue_err "$_post_hook" "$vlist" return 1 fi dnsadded='1' @@ -3510,7 +3510,7 @@ issue() { _debug "Dns record not added yet, so, save to $DOMAIN_CONF and exit." _err "Please add the TXT records to the domains, and retry again." _clearup - _on_issue_err "$_post_hook" + _on_issue_err "$_post_hook" "$vlist" return 1 fi From 14d7bfdab2c3f16c64080aec0dccd0fc9437288c Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 1 Jul 2017 21:47:30 +0800 Subject: [PATCH 16/30] fix deactivate for lower rate limit --- acme.sh | 69 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 22 deletions(-) diff --git a/acme.sh b/acme.sh index 76509af0..6590a00a 100755 --- a/acme.sh +++ b/acme.sh @@ -1152,7 +1152,7 @@ _ss() { if _exists "ss"; then _debug "Using: ss" - ss -ntpl | grep ":$_port " + ss -ntpl 2>/dev/null | grep ":$_port " return 0 fi @@ -4479,26 +4479,51 @@ _deactivate() { _d_type="$2" _initpath + if ! __get_domain_new_authz "$_d_domain"; then + _err "Can not get domain new authz token." + return 1 + fi + + authzUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ' ' -f 2 | tr -d "\r\n")" + _debug "authzUri" "$authzUri" + + if [ "$code" ] && [ ! "$code" = '201' ]; then + _err "new-authz error: $response" + return 1 + fi + + entries="$(echo "$response" | _egrep_o '{ *"type":"[^"]*", *"status": *"valid", *"uri"[^}]*')" + if [ -z "$entries" ]; then + _info "No valid entries found." + if [ -z "$thumbprint" ]; then + thumbprint="$(__calc_account_thumbprint)" + fi + _debug "Trigger validation." + vtype="$VTYPE_HTTP" + entry="$(printf "%s\n" "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')" + _debug entry "$entry" + if [ -z "$entry" ]; then + _err "Error, can not get domain token $d" + return 1 + fi + token="$(printf "%s\n" "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')" + _debug token "$token" + + uri="$(printf "%s\n" "$entry" | _egrep_o '"uri":"[^"]*' | cut -d : -f 2,3 | tr -d '"')" + _debug uri "$uri" + + keyauthorization="$token.$thumbprint" + _debug keyauthorization "$keyauthorization" + __trigger_validation "$uri" "$keyauthorization" + + fi + _d_i=0 - _d_max_retry=9 + _d_max_retry=$(echo "$entries" | wc -l) while [ "$_d_i" -lt "$_d_max_retry" ]; do _info "Deactivate: $_d_domain" _d_i="$(_math $_d_i + 1)" - - if ! __get_domain_new_authz "$_d_domain"; then - _err "Can not get domain new authz token." - return 1 - fi - - authzUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ' ' -f 2 | tr -d "\r\n")" - _debug "authzUri" "$authzUri" - - if [ ! -z "$code" ] && [ ! "$code" = '201' ]; then - _err "new-authz error: $response" - return 1 - fi - - entry="$(printf "%s\n" "$response" | _egrep_o '{"type":"[^"]*","status":"valid","uri"[^}]*')" + entry="$(echo "$entries" | sed -n "${_d_i}p")" _debug entry "$entry" if [ -z "$entry" ]; then @@ -4520,16 +4545,16 @@ _deactivate() { _info "Deactivate: $_vtype" - if ! _send_signed_request "$authzUri" "{\"resource\": \"authz\", \"status\":\"deactivated\"}"; then + if _send_signed_request "$authzUri" "{\"resource\": \"authz\", \"status\":\"deactivated\"}" && _contains "$response" '"deactivated"'; then + _info "Deactivate: $_vtype success." + else _err "Can not deactivate $_vtype." - return 1 + break fi - _info "Deactivate: $_vtype success." - done _debug "$_d_i" - if [ "$_d_i" -lt "$_d_max_retry" ]; then + if [ "$_d_i" -eq "$_d_max_retry" ]; then _info "Deactivated success!" else _err "Deactivate failed." From 1be222f6ed23e5c793f7a6be834f5c96871d6ffe Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 2 Jul 2017 13:38:44 +0800 Subject: [PATCH 17/30] minor --- acme.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index 6590a00a..95964984 100755 --- a/acme.sh +++ b/acme.sh @@ -4614,9 +4614,7 @@ _detect_profile() { fi fi - if [ ! -z "$DETECTED_PROFILE" ]; then - echo "$DETECTED_PROFILE" - fi + echo "$DETECTED_PROFILE" } _initconf() { From c4b2e5829e7ad66941c60e4aa146f227f7df8cb9 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 2 Jul 2017 15:25:35 +0800 Subject: [PATCH 18/30] add always-force-new-domain-key. fix https://github.com/Neilpang/acme.sh/issues/914 --- acme.sh | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index 95964984..e8e04e7c 100755 --- a/acme.sh +++ b/acme.sh @@ -1281,7 +1281,7 @@ createDomainKey() { _initpath "$domain" "$_cdl" - if [ ! -f "$CERT_KEY_PATH" ] || ([ "$FORCE" ] && ! [ "$IS_RENEW" ]); then + if [ ! -f "$CERT_KEY_PATH" ] || ([ "$FORCE" ] && ! [ "$IS_RENEW" ]) || [ "$Le_ForceNewDomainKey" = "1" ] ; then if _createkey "$_cdl" "$CERT_KEY_PATH"; then _savedomainconf Le_Keylength "$_cdl" _info "The domain key is here: $(__green $CERT_KEY_PATH)" @@ -3148,7 +3148,7 @@ _regAccount() { return 1 fi if [ "$code" = '202' ]; then - _info "Update success." + _info "Update account tos info success." CA_KEY_HASH="$(__calcAccountKeyHash)" _debug "Calc CA_KEY_HASH" "$CA_KEY_HASH" @@ -3355,7 +3355,7 @@ issue() { else _key=$(_readdomainconf Le_Keylength) _debug "Read key length:$_key" - if [ ! -f "$CERT_KEY_PATH" ] || [ "$_key_length" != "$_key" ]; then + if [ ! -f "$CERT_KEY_PATH" ] || [ "$_key_length" != "$_key" ] || [ "$Le_ForceNewDomainKey" = "1" ]; then if ! createDomainKey "$_main_domain" "$_key_length"; then _err "Create domain key error." _clearup @@ -3885,6 +3885,12 @@ issue() { _cleardomainconf Le_Listen_V4 fi + if [ "$Le_ForceNewDomainKey" = "1" ]; then + _savedomainconf "Le_ForceNewDomainKey" "$Le_ForceNewDomainKey" + else + _cleardomainconf Le_ForceNewDomainKey + fi + Le_NextRenewTime=$(_math "$Le_CertCreateTime" + "$Le_RenewalDays" \* 24 \* 60 \* 60) Le_NextRenewTimeStr=$(_time2str "$Le_NextRenewTime") @@ -5026,6 +5032,7 @@ Parameters: --renew-hook Command to be run once for each successfully renewed certificate. --deploy-hook The hook file to deploy cert --ocsp-must-staple, --ocsp Generate ocsp must Staple extension. + --always-force-new-domain-key Generate new domain key when renewal. Otherwise, the domain key is not changed by default. --auto-upgrade [0|1] Valid for '--upgrade' command, indicating whether to upgrade automatically in future. --listen-v4 Force standalone/tls server to listen at ipv4. --listen-v6 Force standalone/tls server to listen at ipv6. @@ -5506,6 +5513,14 @@ _process() { --ocsp-must-staple | --ocsp) Le_OCSP_Staple="1" ;; + --always-force-new-domain-key) + if [ -z "$2" ] || _startswith "$2" "-"; then + Le_ForceNewDomainKey=1 + else + Le_ForceNewDomainKey="$2" + shift + fi + ;; --log | --logfile) _log="1" _logfile="$2" From 422dd1fa4f57c977ccb4083be9463500b544d293 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 2 Jul 2017 17:02:54 +0800 Subject: [PATCH 19/30] Implement deactivate account: --deactivate-account --- acme.sh | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index e8e04e7c..99c83a04 100755 --- a/acme.sh +++ b/acme.sh @@ -366,6 +366,7 @@ _hasfield() { return 1 #not contains } +# str index [sep] _getfield() { _str="$1" _findex="$2" @@ -3127,7 +3128,7 @@ _regAccount() { _accUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ' ' -f 2 | tr -d "\r\n")" _debug "_accUri" "$_accUri" - + _savecaconf "ACCOUNT_URL" "$_accUri" _tos="$(echo "$responseHeaders" | grep "^Link:.*rel=\"terms-of-service\"" | _head_n 1 | _egrep_o "<.*>" | tr -d '<>')" _debug "_tos" "$_tos" if [ -z "$_tos" ]; then @@ -3153,6 +3154,9 @@ _regAccount() { CA_KEY_HASH="$(__calcAccountKeyHash)" _debug "Calc CA_KEY_HASH" "$CA_KEY_HASH" _savecaconf CA_KEY_HASH "$CA_KEY_HASH" + elif [ "$code" = '403' ]; then + _err "It seems that the account key is already deactivated, please use a new account key." + return 1 else _err "Update account error." return 1 @@ -3165,6 +3169,71 @@ _regAccount() { } + +#Implement deactivate account +deactivateaccount() { + _initpath + + if [ ! -f "$ACCOUNT_KEY_PATH" ] && [ -f "$_OLD_ACCOUNT_KEY" ]; then + mkdir -p "$CA_DIR" + _info "mv $_OLD_ACCOUNT_KEY to $ACCOUNT_KEY_PATH" + mv "$_OLD_ACCOUNT_KEY" "$ACCOUNT_KEY_PATH" + fi + + if [ ! -f "$ACCOUNT_JSON_PATH" ] && [ -f "$_OLD_ACCOUNT_JSON" ]; then + mkdir -p "$CA_DIR" + _info "mv $_OLD_ACCOUNT_JSON to $ACCOUNT_JSON_PATH" + mv "$_OLD_ACCOUNT_JSON" "$ACCOUNT_JSON_PATH" + fi + + if [ ! -f "$ACCOUNT_KEY_PATH" ]; then + _err "Account key is not found at: $ACCOUNT_KEY_PATH" + return 1 + fi + + _accUri=$(_readcaconf "ACCOUNT_URL") + _debug _accUri "$_accUri" + + if [ -z "$_accUri" ]; then + _err "The account url is empty, please run '--update-account' first to update the account info first," + _err "Then try again." + return 1 + fi + + if ! _calcjwk "$ACCOUNT_KEY_PATH"; then + return 1 + fi + _initAPI + + if _send_signed_request "$_accUri" "{\"resource\": \"reg\", \"status\":\"deactivated\"}" && _contains "$response" '"deactivated"'; then + _info "Deactivate account success for $_accUri." + _accid=$(echo "$response" | _egrep_o "\"id\" *: *[^,]*," | cut -d : -f 2 | tr -d ' ,') + elif [ "$code" = "403" ]; then + _info "The account is already deactivated." + _accid=$(_getfield "$_accUri" "999" "/") + else + _err "Deactivate: account failed for $_accUri." + return 1 + fi + + _debug "Account id: $_accid" + if [ "$_accid" ]; then + _deactivated_account_path="$CA_DIR/deactivated/$_accid" + _debug _deactivated_account_path "$_deactivated_account_path" + if mkdir -p "$_deactivated_account_path"; then + _info "Moving deactivated account info to $_deactivated_account_path/" + mv "$CA_CONF" "$_deactivated_account_path/" + mv "$ACCOUNT_JSON_PATH" "$_deactivated_account_path/" + mv "$ACCOUNT_KEY_PATH" "$_deactivated_account_path/" + else + _err "Can not create dir: $_deactivated_account_path, try to remove the deactivated account key." + rm -f "$CA_CONF" + rm -f "$ACCOUNT_JSON_PATH" + rm -f "$ACCOUNT_KEY_PATH" + fi + fi +} + # domain folder file _findHook() { _hookdomain="$1" @@ -4972,6 +5041,7 @@ Commands: --toPkcs8 Convert to pkcs8 format. --update-account Update account info. --register-account Register account key. + --deactivate-account Deactivate the account. --create-account-key Create an account private key, professional use. --create-domain-key Create an domain private key, professional use. --createCSR, -ccsr Create CSR , professional use. @@ -5252,6 +5322,9 @@ _process() { --registeraccount | --register-account) _CMD="registeraccount" ;; + --deactivate-account) + _CMD="deactivateaccount" + ;; --domain | -d) _dvalue="$2" @@ -5667,6 +5740,9 @@ _process() { updateaccount) updateaccount ;; + deactivateaccount) + deactivateaccount + ;; list) list "$_listraw" ;; From a71eba07a1530aba3d6c2a454e40f1436a64996e Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 2 Jul 2017 18:05:55 +0800 Subject: [PATCH 20/30] minor, fix resource name --- acme.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 99c83a04..41818c75 100755 --- a/acme.sh +++ b/acme.sh @@ -2197,7 +2197,9 @@ _initAPI() { export ACME_KEY_CHANGE="https://acme-v01.api.letsencrypt.org/acme/key-change" export ACME_NEW_AUTHZ="https://acme-v01.api.letsencrypt.org/acme/new-authz" export ACME_NEW_ORDER="https://acme-v01.api.letsencrypt.org/acme/new-cert" + export ACME_NEW_ORDER_RES="new-cert" export ACME_NEW_ACCOUNT="https://acme-v01.api.letsencrypt.org/acme/new-reg" + export ACME_NEW_ACCOUNT_RES="new-reg" export ACME_REVOKE_CERT="https://acme-v01.api.letsencrypt.org/acme/revoke-cert" fi @@ -2217,16 +2219,22 @@ _initAPI() { export ACME_NEW_AUTHZ ACME_NEW_ORDER=$(echo "$response" | _egrep_o 'new-cert" *: *"[^"]*"' | cut -d '"' -f 3) + ACME_NEW_ORDER_RES="new-cert" if [ -z "$ACME_NEW_ORDER" ]; then ACME_NEW_ORDER=$(echo "$response" | _egrep_o 'new-order" *: *"[^"]*"' | cut -d '"' -f 3) + ACME_NEW_ORDER_RES="new-order" fi export ACME_NEW_ORDER + export ACME_NEW_ORDER_RES ACME_NEW_ACCOUNT=$(echo "$response" | _egrep_o 'new-reg" *: *"[^"]*"' | cut -d '"' -f 3) + ACME_NEW_ACCOUNT_RES="new-reg" if [ -z "$ACME_NEW_ACCOUNT" ]; then ACME_NEW_ACCOUNT=$(echo "$response" | _egrep_o 'new-account" *: *"[^"]*"' | cut -d '"' -f 3) + ACME_NEW_ACCOUNT_RES="new-account" fi export ACME_NEW_ACCOUNT + export ACME_NEW_ACCOUNT_RES ACME_REVOKE_CERT=$(echo "$response" | _egrep_o 'revoke-cert" *: *"[^"]*"' | cut -d '"' -f 3) export ACME_REVOKE_CERT @@ -3098,7 +3106,7 @@ _regAccount() { fi _initAPI _updateTos="" - _reg_res="new-reg" + _reg_res="$ACME_NEW_ACCOUNT_RES" while true; do _debug AGREEMENT "$AGREEMENT" @@ -3830,7 +3838,7 @@ issue() { _info "Verify finished, start to sign." der="$(_getfile "${CSR_PATH}" "${BEGIN_CSR}" "${END_CSR}" | tr -d "\r\n" | _url_replace)" - if ! _send_signed_request "${ACME_NEW_ORDER}" "{\"resource\": \"new-cert\", \"csr\": \"$der\"}" "needbase64"; then + if ! _send_signed_request "${ACME_NEW_ORDER}" "{\"resource\": \"$ACME_NEW_ORDER_RES\", \"csr\": \"$der\"}" "needbase64"; then _err "Sign failed." _on_issue_err "$_post_hook" return 1 From 1bbc33a0cf2d46067c6d0901e8c94aa7f7749ebf Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 2 Jul 2017 18:24:55 +0800 Subject: [PATCH 21/30] minor fix CA_DIR --- acme.sh | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/acme.sh b/acme.sh index 41818c75..4d272750 100755 --- a/acme.sh +++ b/acme.sh @@ -3082,14 +3082,13 @@ _regAccount() { _initpath _reg_length="$1" + mkdir -p "$CA_DIR" if [ ! -f "$ACCOUNT_KEY_PATH" ] && [ -f "$_OLD_ACCOUNT_KEY" ]; then - mkdir -p "$CA_DIR" _info "mv $_OLD_ACCOUNT_KEY to $ACCOUNT_KEY_PATH" mv "$_OLD_ACCOUNT_KEY" "$ACCOUNT_KEY_PATH" fi if [ ! -f "$ACCOUNT_JSON_PATH" ] && [ -f "$_OLD_ACCOUNT_JSON" ]; then - mkdir -p "$CA_DIR" _info "mv $_OLD_ACCOUNT_JSON to $ACCOUNT_JSON_PATH" mv "$_OLD_ACCOUNT_JSON" "$ACCOUNT_JSON_PATH" fi @@ -3183,13 +3182,11 @@ deactivateaccount() { _initpath if [ ! -f "$ACCOUNT_KEY_PATH" ] && [ -f "$_OLD_ACCOUNT_KEY" ]; then - mkdir -p "$CA_DIR" _info "mv $_OLD_ACCOUNT_KEY to $ACCOUNT_KEY_PATH" mv "$_OLD_ACCOUNT_KEY" "$ACCOUNT_KEY_PATH" fi if [ ! -f "$ACCOUNT_JSON_PATH" ] && [ -f "$_OLD_ACCOUNT_JSON" ]; then - mkdir -p "$CA_DIR" _info "mv $_OLD_ACCOUNT_JSON to $ACCOUNT_JSON_PATH" mv "$_OLD_ACCOUNT_JSON" "$ACCOUNT_JSON_PATH" fi From 6b185d20c0be746632fa621a0fee762b65ea9cf9 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 2 Jul 2017 18:40:11 +0800 Subject: [PATCH 22/30] fix format --- acme.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 4d272750..fa090cdf 100755 --- a/acme.sh +++ b/acme.sh @@ -1282,7 +1282,7 @@ createDomainKey() { _initpath "$domain" "$_cdl" - if [ ! -f "$CERT_KEY_PATH" ] || ([ "$FORCE" ] && ! [ "$IS_RENEW" ]) || [ "$Le_ForceNewDomainKey" = "1" ] ; then + if [ ! -f "$CERT_KEY_PATH" ] || ([ "$FORCE" ] && ! [ "$IS_RENEW" ]) || [ "$Le_ForceNewDomainKey" = "1" ]; then if _createkey "$_cdl" "$CERT_KEY_PATH"; then _savedomainconf Le_Keylength "$_cdl" _info "The domain key is here: $(__green $CERT_KEY_PATH)" @@ -3176,7 +3176,6 @@ _regAccount() { } - #Implement deactivate account deactivateaccount() { _initpath From 2e602ef6b078543c79b9c86a179ed039bad30ce6 Mon Sep 17 00:00:00 2001 From: RaidenII Date: Sun, 2 Jul 2017 04:45:07 -0700 Subject: [PATCH 23/30] Added ret value verification. --- dnsapi/dns_namecom.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_namecom.sh b/dnsapi/dns_namecom.sh index 15eae6c2..146db4f6 100755 --- a/dnsapi/dns_namecom.sh +++ b/dnsapi/dns_namecom.sh @@ -32,7 +32,9 @@ dns_namecom_add() { _saveaccountconf Namecom_Token "$Namecom_Token" # Login in using API - _namecom_login + if ! _namecom_login; then + return 1 + fi # Find domain in domain list. if ! _namecom_get_root "$fulldomain"; then @@ -63,7 +65,9 @@ dns_namecom_rm() { fulldomain=$1 txtvalue=$2 - _namecom_login + if ! _namecom_login; then + return 1 + fi # Find domain in domain list. if ! _namecom_get_root "$fulldomain"; then From 1a504118e56dd73ae1fe7b2fb16b58fd76e68765 Mon Sep 17 00:00:00 2001 From: RaidenII Date: Sun, 2 Jul 2017 04:55:06 -0700 Subject: [PATCH 24/30] Updated DNS API support list. --- README.md | 3 ++- dnsapi/README.md | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5b6b03ae..7780b9ab 100644 --- a/README.md +++ b/README.md @@ -334,7 +334,8 @@ You don't have to do anything manually! 1. Dynu API (https://www.dynu.com) 1. DNSimple API 1. NS1.com API - +1. DuckDNS.org API +1. Name.com API And: diff --git a/dnsapi/README.md b/dnsapi/README.md index 5dca829a..7584b31e 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -505,6 +505,37 @@ Ok, let's issue a cert now: acme.sh --issue --dns dns_nsone -d example.com -d www.example.com ``` +## 27. Use DuckDNS.org API + +``` +export DuckDNS_Token="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" +``` + +Please note that since DuckDNS uses StartSSL as their cert provider, thus +--insecure must be used when issuing certs: +``` +acme.sh --insecure --issue --dns dns_duckdns -d mydomain.duckdns.org +``` + +Also, DuckDNS uses the domain name as username for recording changing, so the +account file will always store the lastly used domain name. + +For issues, please report to https://github.com/raidenii/acme.sh/issues. + +## 28. Use Name.com API + +``` +export Namecom_Username="testuser" +export Namecom_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +``` + +And now you can issue certs with: +``` +acme.sh --issue --dns dns_namecom -d example.com -d www.example.com +``` + +For issues, please report to https://github.com/raidenii/acme.sh/issues. + # Use custom API If your API is not supported yet, you can write your own DNS API. From 3002f6dfd5f2324fba4ee9fef1cf8ee8b896b8a9 Mon Sep 17 00:00:00 2001 From: RaidenII Date: Sun, 2 Jul 2017 06:02:44 -0700 Subject: [PATCH 25/30] Updated README.md for Name.com API application. --- dnsapi/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dnsapi/README.md b/dnsapi/README.md index 7584b31e..e956b355 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -525,6 +525,10 @@ For issues, please report to https://github.com/raidenii/acme.sh/issues. ## 28. Use Name.com API ``` +You'll need to fill out the form at https://www.name.com/reseller/apply to apply +for API username and token. +``` + export Namecom_Username="testuser" export Namecom_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` From 333090a96733f6701453ab3f5a1281ed99ff1ab5 Mon Sep 17 00:00:00 2001 From: RaidenII Date: Sun, 2 Jul 2017 06:38:25 -0700 Subject: [PATCH 26/30] Fix README.md for DNS API. --- dnsapi/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/README.md b/dnsapi/README.md index e956b355..57c360b7 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -524,16 +524,16 @@ For issues, please report to https://github.com/raidenii/acme.sh/issues. ## 28. Use Name.com API -``` You'll need to fill out the form at https://www.name.com/reseller/apply to apply for API username and token. -``` +``` export Namecom_Username="testuser" export Namecom_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` And now you can issue certs with: + ``` acme.sh --issue --dns dns_namecom -d example.com -d www.example.com ``` From 6963f3880d1e06211bc8c631154868efa8c6bafb Mon Sep 17 00:00:00 2001 From: RaidenII Date: Mon, 3 Jul 2017 03:28:28 -0700 Subject: [PATCH 27/30] Fixes the get_root function so that when domain doesn't exist it will correctly return error. --- dnsapi/dns_namecom.sh | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/dnsapi/dns_namecom.sh b/dnsapi/dns_namecom.sh index 146db4f6..fae56d65 100755 --- a/dnsapi/dns_namecom.sh +++ b/dnsapi/dns_namecom.sh @@ -168,21 +168,26 @@ _namecom_get_root() { i=2 p=1 - if _namecom_rest GET "domain/list"; then - while true; do - host=$(printf "%s" "$domain" | cut -d . -f $i-100) - if [ -z "$host" ]; then - return 1 - fi - - if _contains "$response" "$host"; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) - _domain="$host" - return 0 - fi - p=$i - i=$(_math "$i" + 1) - done + if ! _namecom_rest GET "domain/list"; then + return 1 fi + + # Need to exclude the last field (tld) + numfields=$(echo "$domain" | _egrep_o "\." | wc -l) + while [ $i -le $numfields ]; do + host=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug host "$host" + if [ -z "$host" ]; then + return 1 + fi + + if _contains "$response" "$host"; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain="$host" + return 0 + fi + p=$i + i=$(_math "$i" + 1) + done return 1 } From 7b32bbfc266015b69a3dfc316e03097add2bdd3e Mon Sep 17 00:00:00 2001 From: RaidenII Date: Mon, 3 Jul 2017 08:22:16 -0400 Subject: [PATCH 28/30] Fix for SC2086. --- dnsapi/dns_namecom.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_namecom.sh b/dnsapi/dns_namecom.sh index fae56d65..3af8bf4c 100755 --- a/dnsapi/dns_namecom.sh +++ b/dnsapi/dns_namecom.sh @@ -174,7 +174,7 @@ _namecom_get_root() { # Need to exclude the last field (tld) numfields=$(echo "$domain" | _egrep_o "\." | wc -l) - while [ $i -le $numfields ]; do + while [ $i -le "$numfields" ]; do host=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug host "$host" if [ -z "$host" ]; then From 5f8b60a0e5653595689703fe68d9b3e99d14d1ab Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 4 Jul 2017 08:23:09 +0800 Subject: [PATCH 29/30] fix https://github.com/Neilpang/acme.sh/issues/926 don't trigger validation for dns manually mode --- acme.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/acme.sh b/acme.sh index fa090cdf..ef468a45 100755 --- a/acme.sh +++ b/acme.sh @@ -3543,11 +3543,11 @@ issue() { if [ "$d_api" ]; then _info "Found domain api file: $d_api" else - _err "Add the following TXT record:" - _err "Domain: '$(__green "$txtdomain")'" - _err "TXT value: '$(__green "$txt")'" - _err "Please be aware that you prepend _acme-challenge. before your domain" - _err "so the resulting subdomain will be: $txtdomain" + _info "$(__red "Add the following TXT record:")" + _info "$(__red "Domain: '$(__green "$txtdomain")'")" + _info "$(__red "TXT value: '$(__green "$txt")'")" + _info "$(__red "Please be aware that you prepend _acme-challenge. before your domain")" + _info "$(__red "so the resulting subdomain will be: $txtdomain")" continue fi @@ -3583,7 +3583,7 @@ issue() { _debug "Dns record not added yet, so, save to $DOMAIN_CONF and exit." _err "Please add the TXT records to the domains, and retry again." _clearup - _on_issue_err "$_post_hook" "$vlist" + _on_issue_err "$_post_hook" return 1 fi From 81772fb703af18f7d7f8d7b7b7e3a6d61be14554 Mon Sep 17 00:00:00 2001 From: neil Date: Tue, 4 Jul 2017 09:08:54 +0800 Subject: [PATCH 30/30] minor, fix format --- acme.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/acme.sh b/acme.sh index ef468a45..35842f4e 100755 --- a/acme.sh +++ b/acme.sh @@ -3544,10 +3544,10 @@ issue() { _info "Found domain api file: $d_api" else _info "$(__red "Add the following TXT record:")" - _info "$(__red "Domain: '$(__green "$txtdomain")'")" - _info "$(__red "TXT value: '$(__green "$txt")'")" - _info "$(__red "Please be aware that you prepend _acme-challenge. before your domain")" - _info "$(__red "so the resulting subdomain will be: $txtdomain")" + _info "$(__red "Domain: '$(__green "$txtdomain")'")" + _info "$(__red "TXT value: '$(__green "$txt")'")" + _info "$(__red "Please be aware that you prepend _acme-challenge. before your domain")" + _info "$(__red "so the resulting subdomain will be: $txtdomain")" continue fi