From de692d3dcce6743641236fa0b720fbaea93648a4 Mon Sep 17 00:00:00 2001 From: Sergey Pashinin Date: Tue, 18 Aug 2020 13:14:00 +0300 Subject: [PATCH 001/383] Vault deploy hook --- Dockerfile | 1 + deploy/vault.sh | 62 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 deploy/vault.sh diff --git a/Dockerfile b/Dockerfile index f00d03bd..3109ffd2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,6 +7,7 @@ RUN apk update -f \ coreutils \ bind-tools \ curl \ + sed \ socat \ tzdata \ oath-toolkit-oathtool \ diff --git a/deploy/vault.sh b/deploy/vault.sh new file mode 100644 index 00000000..ae771967 --- /dev/null +++ b/deploy/vault.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env sh + +# Here is a script to deploy cert to hashicorp vault using curl +# (https://www.vaultproject.io/) +# +# it requires following environment variables: +# +# VAULT_PREFIX - this contains the prefix path in vault +# VAULT_ADDR - vault requires this to find your vault server +# +# additionally, you need to ensure that VAULT_TOKEN is avialable +# to access the vault server + +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +vault_deploy() { + + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + + # validate required env vars + if [ -z "$VAULT_PREFIX" ]; then + _err "VAULT_PREFIX needs to be defined (contains prefix path in vault)" + return 1 + fi + + if [ -z "$VAULT_ADDR" ]; then + _err "VAULT_ADDR needs to be defined (contains vault connection address)" + return 1 + fi + + # JSON does not allow multiline strings. + # So replacing new-lines with "\n" here + _ckey=$(sed -z 's/\n/\\n/g' <"$2") + _ccert=$(sed -z 's/\n/\\n/g' <"$3") + _cca=$(sed -z 's/\n/\\n/g' <"$4") + _cfullchain=$(sed -z 's/\n/\\n/g' <"$5") + + URL="$VAULT_ADDR/v1/$VAULT_PREFIX/$_cdomain" + + if [ -n "$FABIO" ]; then + curl --silent -H "X-Vault-Token: $VAULT_TOKEN" --request POST --data "{\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"}" "$URL" || return 1 + else + curl --silent -H "X-Vault-Token: $VAULT_TOKEN" --request POST --data "{\"value\": \"$_ccert\"}" "$URL/cert.pem" || return 1 + curl --silent -H "X-Vault-Token: $VAULT_TOKEN" --request POST --data "{\"value\": \"$_ckey\"}" "$URL/cert.key" || return 1 + curl --silent -H "X-Vault-Token: $VAULT_TOKEN" --request POST --data "{\"value\": \"$_cca\"}" "$URL/chain.pem" || return 1 + curl --silent -H "X-Vault-Token: $VAULT_TOKEN" --request POST --data "{\"value\": \"$_cfullchain\"}" "$URL/fullchain.pem" || return 1 + fi + +} From a674e410e0ec9de7a5f98e2be103b0c53307908a Mon Sep 17 00:00:00 2001 From: Ed Lynes Date: Fri, 21 Aug 2020 17:15:18 -0400 Subject: [PATCH 002/383] initial commit --- dnsapi/dns_edgedns.sh | 379 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 379 insertions(+) create mode 100755 dnsapi/dns_edgedns.sh diff --git a/dnsapi/dns_edgedns.sh b/dnsapi/dns_edgedns.sh new file mode 100755 index 00000000..75ef4f9b --- /dev/null +++ b/dnsapi/dns_edgedns.sh @@ -0,0 +1,379 @@ +#!/usr/bin/env sh + +# Akamai Edge DNS v2 API +# User must provide Open Edgegrid API credentials to the EdgeDNS installation. The remote user in EdgeDNS must have CRUD access to +# Edge DNS Zones and Recordsets, e.g. DNS—Zone Record Management authorization + +# Report bugs to https://control.akamai.com/apps/support-ui/#/contact-support + +# Values to export: +# --EITHER-- +# *** NOT IMPLEMENTED YET *** +# specify Edgegrid credentials file and section +# AKAMAI_EDGERC= +# AKAMAI_EDGERC_SECTION="default" +## --OR-- +# specify indiviual credentials +# export AKAMAI_HOST = +# export AKAMAI_ACCESS_TOKEN = +# export AKAMAI_CLIENT_TOKEN = +# export AKAMAI_CLIENT_SECRET = + +ACME_EDGEDNS_VERSION="0.1.0" + +######## Public functions ##################### + +# Usage: dns_edgedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +# Used to add txt record +# +dns_edgedns_add() { + fulldomain=$1 + txtvalue=$2 + + _debug "ENTERING DNS_EDGEDNS_ADD" + + _debug2 "fulldomain" "$fulldomain" + _debug2 "txtvalue" "$txtvalue" + + if ! _EDGEDNS_credentials; then + _err "$@" + return 1 + fi + + if ! _EDGEDNS_getZoneInfo "$fulldomain"; then + _err "Invalid domain" + return 1 + fi + _debug2 "Add: zone" "${zone}" + acmeRecordURI=$(printf "%s/%s/names/%s/type/TXT" "${edge_endpoint}" "${zone}" "${fulldomain}") + _debug3 "Add URL" "$acmeRecordURI" + # Get existing TXT record + _edge_result=$(_edgedns_rest GET "$acmeRecordURI") + _api_status="$?" + if [ "$_api_status" -ne 0 ] && [ "$_edge_result" != "404" ]; then + _err "$(printf "Failure accessing Akamai Edge DNS API Server. Error: %s" "$_edge_result")" + return 1 + fi + rdata="\"$txtvalue\"" + record_op="POST" + if [ "$_api_status" -eq 0 ]; then + # record already exists. Get existing record data and update + record_op="PUT" + rdlist=$(echo -n "$response" | _egrep_o "\"rdata\"\\s*:\\s*\\[\\s*\"[^\"]*\"\\s*]" | cut -d : -f 2 | tr -d "[]\"") + _debug2 "existing TXT found" + _debug2 "record data" "$rdlist" + # value already there? + if _contains "$rdlist" "$txtvalue" ; then + return 0 + fi + comma="," + rdata="$rdata$comma\"${txtvalue}\"" + fi + _debug2 "new/updated rdata: " "${rdata}" + # Add the txtvalue TXT Record + body="{\"name\":\"$fulldomain\",\"type\":\"TXT\",\"ttl\":600, \"rdata\":"[${rdata}]"}" + _debug3 "Add body '${body}'" + _edge_result=$(_edgedns_rest "$record_op" "$acmeRecordURI" "$body") + _api_status="$?" + if [ "$_api_status" -eq 0 ]; then + _log "$(printf "Text value %s added to recordset %s" "${txtvalue}" "${fulldomain}")" + return 0 + else + _err "$(printf "error adding TXT record for validation. Error: %s" "$_edge_result")" + return 1 + fi +} + +# Usage: dns_edgedns_rm _acme-challenge.www.domain.com +# Used to delete txt record +# +dns_edgedns_rm() { + fulldomain=$1 +} + +#################### Private functions below ################################## + +_EDGEDNS_credentials() { + _debug "GettingEdge DNS credentials" + _log $(printf "ACME DNSAPI Edge DNS version %s" ${ACME_EDGEDNS_VERSION}) + args_missing=0 + if [ -z "${AKAMAI_ACCESS_TOKEN}" ]; then + AKAMAI_ACCESS_TOKEN="" + AKAMAI_CLIENT_TOKEN="" + AKAMAI_HOST="" + AKAMAI_CLIENT_SECRET="" + _err "AKAMAI_ACCESS_TOKEN is missing" + args_missing=1 + fi + if [ -z "$AKAMAI_CLIENT_TOKEN" ]; then + AKAMAI_ACCESS_TOKEN="" + AKAMAI_CLIENT_TOKEN="" + AKAMAI_HOST="" + AKAMAI_CLIENT_SECRET="" + _err "AKAMAI_CLIENT_TOKEN is missing" + args_missing=1 + fi + if [ -z "${AKAMAI_HOST}" ]; then + AKAMAI_ACCESS_TOKEN="" + AKAMAI_CLIENT_TOKEN="" + AKAMAI_HOST="" + AKAMAI_CLIENT_SECRET="" + _err "AKAMAI_HOST is missing" + args_missing=1 + fi + if [ -z "${AKAMAI_CLIENT_SECRET}" ]; then + AKAMAI_ACCESS_TOKEN="" + AKAMAI_CLIENT_TOKEN="" + AKAMAI_HOST="" + AKAMAI_CLIENT_SECRET="" + _err "AKAMAI_CLIENT_SECRET is missing" + args_missing=1 + fi + + if [ "${args_missing}" = 1 ]; then + _err "You have not properly specified the EdgeDNS Open Edgegrid API credentials. Please try again." + return 1 + else + _saveaccountconf_mutable AKAMAI_ACCESS_TOKEN "${AKAMAI_ACCESS_TOKEN}" + _saveaccountconf_mutable AKAMAI_CLIENT_TOKEN "${AKAMAI_CLIENT_TOKEN}" + _saveaccountconf_mutable AKAMAI_HOST "${AKAMAI_HOST}" + _saveaccountconf_mutable AKAMAI_CLIENT_SECRET "${AKAMAI_CLIENT_SECRET}" + # Set whether curl should use secure or insecure mode + fi + export HTTPS_INSECURE=0 # All Edgegrid API calls are secure + edge_endpoint=$(printf "https://%s/config-dns/v2/zones" "${AKAMAI_HOST}") + _debug3 "Edge API Endpoint:" "${edge_endpoint}" + +} + +_EDGEDNS_getZoneInfo() { + _debug "Getting Zoneinfo" + zoneEnd=false + curZone=$1 + while [ -n "${zoneEnd}" ]; do + # we can strip the first part of the fulldomain, since its just the _acme-challenge string + curZone="${curZone#*.}" + # suffix . needed for zone -> domain.tld. + # create zone get url + get_zone_url=$(printf "%s/%s" "${edge_endpoint}" "${curZone}") + _debug3 "Zone Get: " "${get_zone_url}" + curResult=$(_edgedns_rest GET "$get_zone_url") + retVal=$? + if [ $retVal -ne 0 ]; then + if ["$curResult" != "404" ]; then + _err "$(printf "Managed zone validation failed. Error response: %s" "$retVal")" + return 1 + fi + fi + + if _contains "${curResult}" "\"zone\":" ; then + _debug2 "Zone data" "${curResult}" + zone=$(echo -n "${curResult}" | _egrep_o "\"zone\"\\s*:\\s*\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d "\"") + _debug2 "Zone" "${zone}" + zoneFound="" + zoneEnd="" + return 0 + fi + + if [ "${curZone#*.}" != "$curZone" ]; then + _debug2 $(printf "%s still contains a '.' - so we can check next higher level" "$curZone") + else + zoneEnd=true + _err "Couldn't retrieve zone data." + return 1 + fi + done + _err "Failed to retrieve zone data." + return 2 +} + +_edgedns_headers="" + +_edgedns_rest() { + _debug "Handling API Request" + m=$1 + # Assume endpoint is complete path, including query args if applicable + ep=$2 + body_data=$3 + _edgedns_content_type="" + _request_url_path="$ep" + _request_body="$body_data" + _request_method="$m" + _edgedns_headers="" + tab="" + _edgedns_headers="${_edgedns_headers}${tab}Host: ${AKAMAI_HOST}" + tab="\t" + # Set in acme.sh _post/_get + #_edgedns_headers="${_edgedns_headers}${tab}User-Agent:ACME DNSAPI Edge DNS version ${ACME_EDGEDNS_VERSION}" + _edgedns_headers="${_edgedns_headers}${tab}Accept: application/json" + if [ "$m" != "GET" ] && [ "$m" != "DELETE" ] ; then + _edgedns_content_type="application/json;charset=UTF-8" + _utf8_body_data="$(echo -n "$ _request_body" | iconv -t utf-8)" + _utf8_body_len="$(echo -n "$_utf8_body_data" | awk '{print length}')" + _edgedns_headers="${_edgedns_headers}${tab}Content-Length: ${_utf8_body_len}" + fi + _made_auth_header=$(_edgedns_make_auth_header) + _edgedns_headers="${_edgedns_headers}${tab}Authorization: ${_made_auth_header}" + _secure_debug2 "Made Auth Header" "${_made_auth_header}" + hdr_indx=1 + work_header="${_edgedns_headers}${tab}" + _debug3 "work_header" "${work_header}" + while [ "${work_header}" ]; do + entry="${work_header%%\\t*}"; work_header="${work_header#*\\t}" + export "$(printf "_H%s=%s" "${hdr_indx}" "${entry}")" + _debug2 "Request Header " "${entry}" + hdr_indx=$(( hdr_indx + 1 )) + done + + # clear headers from previous request to avoid getting wrong http code on timeouts + :>"$HTTP_HEADER" + _debug "$ep" + if [ "$m" != "GET" ]; then + _debug "Method data" "$data" + # body url [needbase64] [POST|PUT|DELETE] [ContentType] + response="$(_post "$_utf8_body_data" "$ep" false "$m")" + else + response="$(_get "$ep")" + fi + + _ret="$?" + _debug "response" "$response" + _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" + _debug2 "http response code" "$_code" + + if [ "$_code" = "200" ] || [ "$_code" = "201" ]; then + # All good + response="$(echo "$response" | _normalizeJson)" + echo -n "${response}" + return 0 + fi + + if [ "$_code" = "204" ]; then + # Success, no body + echo -n "" + return 0 + fi + + if [ "$_code" = "400" ]; then + _err "Bad request presented" + _log "$(printf "Headers: %s" "$_edgedns_headers")" + _log "$(printf "Method: %s" "$_request_method")" + _log "$(printf "URL: %s" "$ep")" + _log "$(printf "Data: %s" "$data")" + fi + + if [ "$_code" = "403" ]; then + _err "access denied make sure your Edgegrid cedentials are correct." + fi + + echo "$_code" + return 1 +} + +_edgedns_eg_timestamp() { + _eg_timestamp=$(date -u "+%Y%m%dT%H:%M:%S+0000") +} + +_edgedns_new_nonce() { + _nonce=$(uuidgen -r) +} + +_edgedns_make_auth_header() { + _debug "Constructing Auth Header" + _edgedns_eg_timestamp + _edgedns_new_nonce + # "Unsigned authorization header: 'EG1-HMAC-SHA256 client_token=block;access_token=block;timestamp=20200806T14:16:33+0000;nonce=72cde72c-82d9-4721-9854-2ba057929d67;'" + _auth_header="$(printf "EG1-HMAC-SHA256 client_token=%s;access_token=%s;timestamp=%s;nonce=%s;" "${AKAMAI_CLIENT_TOKEN}" "${AKAMAI_ACCESS_TOKEN}" "${_eg_timestamp}" "${_nonce}")" + _secure_debug2 "Unsigned Auth Header: " "$_auth_header" + + _sig="$(_edgedns_sign_request)" + _signed_auth_header="$(printf "%ssignature=%s" "${_auth_header}" "${_sig}")" + _secure_debug2 "Signed Auth Header: " "${_signed_auth_header}" + echo -n "${_signed_auth_header}" +} + +_edgedns_sign_request() { + _debug2 "Signing http request" + _signed_data=$(_edgedns_make_data_to_sign "${_auth_header}") + _secure_debug2 "Returned signed data" "$_signed_data" + _key=$(_edgedns_make_signing_key "${_eg_timestamp}") + _signed_req=$(_edgedns_base64_hmac_sha256 "$_signed_data" "$_key") + _secure_debug2 "Signed Request" "${_signed_req}" + echo -n "${_signed_req}" +} + +_edgedns_make_signing_key() { + _debug2 "Creating sigining key" + ts=$1 + _signing_key=$(_edgedns_base64_hmac_sha256 "$ts" "${AKAMAI_CLIENT_SECRET}") + _secure_debug2 "Signing Key" "${_signing_key}" + echo -n "${_signing_key}" + +} + +_edgedns_make_data_to_sign() { + _debug2 "Processing data to sign" + hdr=$1 + _secure_debug2 "hdr" "$hdr" + content_hash=$(_edgedns_make_content_hash) + path="$(echo -n "${_request_url_path}" |sed 's/https\?:\/\///')" + path="${path#*$AKAMAI_HOST}" + _debug "hier path" "${path}" + # dont expose headers to sign so use MT string + data="$(printf "%s\thttps\t%s\t%s\t%s\t%s\t%s" "${_request_method}" "${AKAMAI_HOST}" "${path}" "" "${content_hash}" "$hdr")" + _secure_debug2 "Data to Sign" "${data}" + echo -n "${data}" +} + +_edgedns_make_content_hash() { + _debug2 "Generating content hash" + prep_body="" + _hash="" + _debug2 "Request method" "${_request_method}" + if [ "${_request_method}" != "POST" ] || [ -z "${_request_body}" ]; then + echo -n "${prep_body}" + return 0 + fi + prep_body="$(echo -n "${_request_body}")" + _debug2 "Req body" "${prep_body}" + _hash=$(_edgedns_base64_sha256 "${prep_body}") + _debug2 "Content hash" "${_hash}" + echo -n "${_hash}" +} + +_edgedns_base64_hmac_sha256() { + _debug2 "Generating hmac" + data=$1 + key=$2 + encoded_data="$(echo -n "${data}" | iconv -t utf-8)" + encoded_key="$(echo -n "${key}" | iconv -t utf-8)" + _secure_debug2 "encoded data" "${encoded_data}" + _secure_debug2 "encoded key" "${encoded_key}" + #key_hex="$(_durl_replace_base64 "$key" | _dbase64 | _hex_dump | tr -d ' ')" + #data_sig="$(printf "%s" "$encoded_data" | _hmac sha256 "${key_hex}" | _base64 | _url_replace)" + + data_sig="$(echo -n "$encoded_data" | ${ACME_OPENSSL_BIN:-openssl} dgst -sha256 -hmac $encoded_key -binary | _base64)" + _secure_debug2 "data_sig:" "${data_sig}" + out="$(echo -n "${data_sig}" | iconv -f utf-8)" + _secure_debug2 "hmac" "${out}" + echo -n "${out}" +} + +_edgedns_base64_sha256() { + _debug2 "Creating sha256 digest" + trg=$1 + utf8_str="$(echo -n "${trg}" | iconv -t utf-8)" + _secure_debug2 "digest data" "$trg" + _secure_debug2 "encoded digest data" "${utf8_str}" + digest="$(echo -n "${trg}" | ${ACME_OPENSSL_BIN:-openssl} dgst -sha256 -binary | _base64)" + out="$(echo -n "${digest}" | iconv -f utf-8)" + _secure_debug2 "digest decode" "${out}" + echo -n "${out}" +} + +#_edgedns_parse_edgerc() { +# filepath=$1 +# section=$2 +#} + + From f511a5270590a7fc834df02470b4709629768bb7 Mon Sep 17 00:00:00 2001 From: Sergey Pashinin Date: Mon, 24 Aug 2020 00:05:21 +0300 Subject: [PATCH 003/383] Using _post function --- deploy/vault.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/deploy/vault.sh b/deploy/vault.sh index ae771967..c51ceb0f 100644 --- a/deploy/vault.sh +++ b/deploy/vault.sh @@ -49,14 +49,15 @@ vault_deploy() { _cfullchain=$(sed -z 's/\n/\\n/g' <"$5") URL="$VAULT_ADDR/v1/$VAULT_PREFIX/$_cdomain" + export _H1="X-Vault-Token: $VAULT_TOKEN" if [ -n "$FABIO" ]; then - curl --silent -H "X-Vault-Token: $VAULT_TOKEN" --request POST --data "{\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"}" "$URL" || return 1 + _post "{\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"}" "$URL" else - curl --silent -H "X-Vault-Token: $VAULT_TOKEN" --request POST --data "{\"value\": \"$_ccert\"}" "$URL/cert.pem" || return 1 - curl --silent -H "X-Vault-Token: $VAULT_TOKEN" --request POST --data "{\"value\": \"$_ckey\"}" "$URL/cert.key" || return 1 - curl --silent -H "X-Vault-Token: $VAULT_TOKEN" --request POST --data "{\"value\": \"$_cca\"}" "$URL/chain.pem" || return 1 - curl --silent -H "X-Vault-Token: $VAULT_TOKEN" --request POST --data "{\"value\": \"$_cfullchain\"}" "$URL/fullchain.pem" || return 1 + _post "{\"value\": \"$_ccert\"}" "$URL/cert.pem" + _post "{\"value\": \"$_ckey\"}" "$URL/cert.key" + _post "{\"value\": \"$_cca\"}" "$URL/chain.pem" + _post "{\"value\": \"$_cfullchain\"}" "$URL/fullchain.pem" fi } From d66c430e46fdaa7b7180cf619361d2d96da5262c Mon Sep 17 00:00:00 2001 From: Ed Lynes Date: Wed, 26 Aug 2020 16:11:11 -0400 Subject: [PATCH 004/383] debugging and cleanup --- dnsapi/dns_edgedns.sh | 283 ++++++++++++++++++++++++++---------------- 1 file changed, 176 insertions(+), 107 deletions(-) diff --git a/dnsapi/dns_edgedns.sh b/dnsapi/dns_edgedns.sh index 75ef4f9b..7be49761 100755 --- a/dnsapi/dns_edgedns.sh +++ b/dnsapi/dns_edgedns.sh @@ -29,9 +29,7 @@ ACME_EDGEDNS_VERSION="0.1.0" dns_edgedns_add() { fulldomain=$1 txtvalue=$2 - _debug "ENTERING DNS_EDGEDNS_ADD" - _debug2 "fulldomain" "$fulldomain" _debug2 "txtvalue" "$txtvalue" @@ -39,44 +37,53 @@ dns_edgedns_add() { _err "$@" return 1 fi - if ! _EDGEDNS_getZoneInfo "$fulldomain"; then _err "Invalid domain" return 1 fi - _debug2 "Add: zone" "${zone}" - acmeRecordURI=$(printf "%s/%s/names/%s/type/TXT" "${edge_endpoint}" "${zone}" "${fulldomain}") + _debug2 "Add: zone" "$zone" + acmeRecordURI=$(printf "%s/%s/names/%s/types/TXT" "$edge_endpoint" "$zone" "$fulldomain") _debug3 "Add URL" "$acmeRecordURI" # Get existing TXT record _edge_result=$(_edgedns_rest GET "$acmeRecordURI") _api_status="$?" - if [ "$_api_status" -ne 0 ] && [ "$_edge_result" != "404" ]; then - _err "$(printf "Failure accessing Akamai Edge DNS API Server. Error: %s" "$_edge_result")" - return 1 + _debug3 "_edge_result" "$_edge_result" + if [ "$_api_status" -ne 0 ]; then + if [ "$curResult" = "FATAL" ]; then + _err "$(printf "Fatal error: acme API function call : %s" "$retVal")" + fi + if [ "$_edge_result" != "404" ]; then + _err "$(printf "Failure accessing Akamai Edge DNS API Server. Error: %s" "$_edge_result")" + return 1 + fi fi - rdata="\"$txtvalue\"" + rdata="\"${txtvalue}\"" record_op="POST" if [ "$_api_status" -eq 0 ]; then # record already exists. Get existing record data and update record_op="PUT" - rdlist=$(echo -n "$response" | _egrep_o "\"rdata\"\\s*:\\s*\\[\\s*\"[^\"]*\"\\s*]" | cut -d : -f 2 | tr -d "[]\"") - _debug2 "existing TXT found" - _debug2 "record data" "$rdlist" + rdlist="${_edge_result#*\"rdata\":[}" + rdlist="${rdlist%%]*}" + rdlist=$(echo "$rdlist" | tr -d '"' | tr -d "\\") + _debug3 "existing TXT found" + _debug3 "record data" "$rdlist" # value already there? if _contains "$rdlist" "$txtvalue" ; then return 0 fi - comma="," - rdata="$rdata$comma\"${txtvalue}\"" + _txt_val="" + while [ "$_txt_val" != "$rdlist" ] && [ "${rdlist}" ]; do + _txt_val="${rdlist%%,*}"; rdlist="${rdlist#*,}" + rdata="${rdata},\"${_txt_val}\"" + done fi - _debug2 "new/updated rdata: " "${rdata}" # Add the txtvalue TXT Record body="{\"name\":\"$fulldomain\",\"type\":\"TXT\",\"ttl\":600, \"rdata\":"[${rdata}]"}" _debug3 "Add body '${body}'" _edge_result=$(_edgedns_rest "$record_op" "$acmeRecordURI" "$body") _api_status="$?" if [ "$_api_status" -eq 0 ]; then - _log "$(printf "Text value %s added to recordset %s" "${txtvalue}" "${fulldomain}")" + _log "$(printf "Text value %s added to recordset %s" "$txtvalue" "$fulldomain")" return 0 else _err "$(printf "error adding TXT record for validation. Error: %s" "$_edge_result")" @@ -84,20 +91,89 @@ dns_edgedns_add() { fi } -# Usage: dns_edgedns_rm _acme-challenge.www.domain.com +# Usage: dns_edgedns_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" # Used to delete txt record # dns_edgedns_rm() { fulldomain=$1 + txtvalue=$2 + _debug "ENTERING DNS_EDGEDNS_RM" + _debug2 "fulldomain" "$fulldomain" + _debug2 "txtvalue" "$txtvalue" + + if ! _EDGEDNS_credentials; then + _err "$@" + return 1 + fi + if ! _EDGEDNS_getZoneInfo "$fulldomain"; then + _err "Invalid domain" + return 1 + fi + _debug2 "RM: zone" "${zone}" + acmeRecordURI=$(printf "%s/%s/names/%s/types/TXT" "${edge_endpoint}" "$zone" "$fulldomain") + _debug3 "RM URL" "$acmeRecordURI" + # Get existing TXT record + _edge_result=$(_edgedns_rest GET "$acmeRecordURI") + _api_status="$?" + if [ "$_api_status" -ne 0 ]; then + if [ "$curResult" = "FATAL" ]; then + _err "$(printf "Fatal error: acme API function call : %s" "$retVal")" + fi + if [ "$_edge_result" != "404" ]; then + _err "$(printf "Failure accessing Akamai Edge DNS API Server. Error: %s" "$_edge_result")" + return 1 + fi + fi + _debug3 "_edge_result" "$_edge_result" + record_op="DELETE" + body="" + if [ "$_api_status" -eq 0 ]; then + # record already exists. Get existing record data and update + rdlist="${_edge_result#*\"rdata\":[}" + rdlist="${rdlist%%]*}" + rdlist=$(echo "$rdlist" | tr -d '"' | tr -d "\\") + _debug3 "rdlist" "$rdlist" + if [ -n "$rdlist" ]; then + record_op="PUT" + comma="" + rdata="" + _txt_val="" + while [ "$_txt_val" != "$rdlist" ] && [ "$rdlist" ]; do + _txt_val="${rdlist%%,*}"; rdlist="${rdlist#*,}" + _debug3 "_txt_val" "$_txt_val" + _debug3 "txtvalue" "$txtvalue" + if ! _contains "$_txt_val" "$txtvalue" ; then + rdata="${rdata}${comma}\"${_txt_val}\"" + comma="," + fi + done + if [ -z "$rdata" ]; then + record_op="DELETE" + else + # Recreate the txtvalue TXT Record + body="{\"name\":\"$fulldomain\",\"type\":\"TXT\",\"ttl\":600, \"rdata\":"[${rdata}]"}" + _debug3 "body" "$body" + fi + fi + fi + _edge_result=$(_edgedns_rest "$record_op" "$acmeRecordURI" "$body") + _api_status="$?" + if [ "$_api_status" -eq 0 ]; then + _log "$(printf "Text value %s removed from recordset %s" "$txtvalue" "$fulldomain")" + return 0 + else + _err "$(printf "error removing TXT record for validation. Error: %s" "$_edge_result")" + return 1 + fi } #################### Private functions below ################################## _EDGEDNS_credentials() { _debug "GettingEdge DNS credentials" - _log $(printf "ACME DNSAPI Edge DNS version %s" ${ACME_EDGEDNS_VERSION}) + _log "$(printf "ACME DNSAPI Edge DNS version %s" ${ACME_EDGEDNS_VERSION})" args_missing=0 - if [ -z "${AKAMAI_ACCESS_TOKEN}" ]; then + if [ -z "$AKAMAI_ACCESS_TOKEN" ]; then AKAMAI_ACCESS_TOKEN="" AKAMAI_CLIENT_TOKEN="" AKAMAI_HOST="" @@ -113,7 +189,7 @@ _EDGEDNS_credentials() { _err "AKAMAI_CLIENT_TOKEN is missing" args_missing=1 fi - if [ -z "${AKAMAI_HOST}" ]; then + if [ -z "$AKAMAI_HOST" ]; then AKAMAI_ACCESS_TOKEN="" AKAMAI_CLIENT_TOKEN="" AKAMAI_HOST="" @@ -121,7 +197,7 @@ _EDGEDNS_credentials() { _err "AKAMAI_HOST is missing" args_missing=1 fi - if [ -z "${AKAMAI_CLIENT_SECRET}" ]; then + if [ -z "$AKAMAI_CLIENT_SECRET" ]; then AKAMAI_ACCESS_TOKEN="" AKAMAI_CLIENT_TOKEN="" AKAMAI_HOST="" @@ -130,19 +206,19 @@ _EDGEDNS_credentials() { args_missing=1 fi - if [ "${args_missing}" = 1 ]; then + if [ "$args_missing" = 1 ]; then _err "You have not properly specified the EdgeDNS Open Edgegrid API credentials. Please try again." return 1 else - _saveaccountconf_mutable AKAMAI_ACCESS_TOKEN "${AKAMAI_ACCESS_TOKEN}" - _saveaccountconf_mutable AKAMAI_CLIENT_TOKEN "${AKAMAI_CLIENT_TOKEN}" - _saveaccountconf_mutable AKAMAI_HOST "${AKAMAI_HOST}" - _saveaccountconf_mutable AKAMAI_CLIENT_SECRET "${AKAMAI_CLIENT_SECRET}" + _saveaccountconf_mutable AKAMAI_ACCESS_TOKEN "$AKAMAI_ACCESS_TOKEN" + _saveaccountconf_mutable AKAMAI_CLIENT_TOKEN "$AKAMAI_CLIENT_TOKEN" + _saveaccountconf_mutable AKAMAI_HOST "$AKAMAI_HOST" + _saveaccountconf_mutable AKAMAI_CLIENT_SECRET "$AKAMAI_CLIENT_SECRET" # Set whether curl should use secure or insecure mode fi export HTTPS_INSECURE=0 # All Edgegrid API calls are secure - edge_endpoint=$(printf "https://%s/config-dns/v2/zones" "${AKAMAI_HOST}") - _debug3 "Edge API Endpoint:" "${edge_endpoint}" + edge_endpoint=$(printf "https://%s/config-dns/v2/zones" "$AKAMAI_HOST") + _debug3 "Edge API Endpoint:" "$edge_endpoint" } @@ -150,33 +226,34 @@ _EDGEDNS_getZoneInfo() { _debug "Getting Zoneinfo" zoneEnd=false curZone=$1 - while [ -n "${zoneEnd}" ]; do + while [ -n "$zoneEnd" ]; do # we can strip the first part of the fulldomain, since its just the _acme-challenge string curZone="${curZone#*.}" # suffix . needed for zone -> domain.tld. # create zone get url - get_zone_url=$(printf "%s/%s" "${edge_endpoint}" "${curZone}") + get_zone_url=$(printf "%s/%s" "$edge_endpoint" "$curZone") _debug3 "Zone Get: " "${get_zone_url}" curResult=$(_edgedns_rest GET "$get_zone_url") retVal=$? - if [ $retVal -ne 0 ]; then - if ["$curResult" != "404" ]; then - _err "$(printf "Managed zone validation failed. Error response: %s" "$retVal")" + if [ "$retVal" -ne 0 ]; then + if [ "$curResult" = "FATAL" ]; then + _err "$(printf "Fatal error: acme API function call : %s" "$retVal")" + fi + if [ "$curResult" != "404" ]; then + err "$(printf "Managed zone validation failed. Error response: %s" "$retVal")" return 1 fi fi - - if _contains "${curResult}" "\"zone\":" ; then + if _contains "$curResult" "\"zone\":" ; then _debug2 "Zone data" "${curResult}" - zone=$(echo -n "${curResult}" | _egrep_o "\"zone\"\\s*:\\s*\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d "\"") - _debug2 "Zone" "${zone}" - zoneFound="" + zone=$(echo "${curResult}" | _egrep_o "\"zone\"\\s*:\\s*\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d "\"") + _debug3 "Zone" "${zone}" zoneEnd="" return 0 fi if [ "${curZone#*.}" != "$curZone" ]; then - _debug2 $(printf "%s still contains a '.' - so we can check next higher level" "$curZone") + _debug3 "$(printf "%s still contains a '.' - so we can check next higher level" "$curZone")" else zoneEnd=true _err "Couldn't retrieve zone data." @@ -205,52 +282,55 @@ _edgedns_rest() { tab="\t" # Set in acme.sh _post/_get #_edgedns_headers="${_edgedns_headers}${tab}User-Agent:ACME DNSAPI Edge DNS version ${ACME_EDGEDNS_VERSION}" - _edgedns_headers="${_edgedns_headers}${tab}Accept: application/json" + _edgedns_headers="${_edgedns_headers}${tab}Accept: application/json,*/*" if [ "$m" != "GET" ] && [ "$m" != "DELETE" ] ; then - _edgedns_content_type="application/json;charset=UTF-8" - _utf8_body_data="$(echo -n "$ _request_body" | iconv -t utf-8)" - _utf8_body_len="$(echo -n "$_utf8_body_data" | awk '{print length}')" - _edgedns_headers="${_edgedns_headers}${tab}Content-Length: ${_utf8_body_len}" + _edgedns_content_type="application/json" + _debug3 "_request_body" "$_request_body" + _body_len=$(echo "$_request_body" | tr -d "\n\r" | awk '{print length}') + _edgedns_headers="${_edgedns_headers}${tab}Content-Length: ${_body_len}" fi - _made_auth_header=$(_edgedns_make_auth_header) - _edgedns_headers="${_edgedns_headers}${tab}Authorization: ${_made_auth_header}" - _secure_debug2 "Made Auth Header" "${_made_auth_header}" + _edgedns_make_auth_header + _edgedns_headers="${_edgedns_headers}${tab}Authorization: ${_signed_auth_header}" + _secure_debug2 "Made Auth Header" "$_signed_auth_header" hdr_indx=1 work_header="${_edgedns_headers}${tab}" - _debug3 "work_header" "${work_header}" - while [ "${work_header}" ]; do + _debug3 "work_header" "$work_header" + while [ "$work_header" ]; do entry="${work_header%%\\t*}"; work_header="${work_header#*\\t}" - export "$(printf "_H%s=%s" "${hdr_indx}" "${entry}")" - _debug2 "Request Header " "${entry}" + export "$(printf "_H%s=%s" "$hdr_indx" "$entry")" + _debug2 "Request Header " "$entry" hdr_indx=$(( hdr_indx + 1 )) done # clear headers from previous request to avoid getting wrong http code on timeouts - :>"$HTTP_HEADER" - _debug "$ep" + : >"$HTTP_HEADER" + _debug2 "$ep" if [ "$m" != "GET" ]; then - _debug "Method data" "$data" + _debug3 "Method data" "$data" # body url [needbase64] [POST|PUT|DELETE] [ContentType] - response="$(_post "$_utf8_body_data" "$ep" false "$m")" + response=$(_post "$_request_body" "$ep" false "$m" "$_edgedns_content_type") else - response="$(_get "$ep")" + response=$(_get "$ep") fi - _ret="$?" - _debug "response" "$response" + if [ "$_ret" -ne 0 ]; then + _err "$(printf "acme.sh API function call failed. Error: %s" "$_ret")" + echo "FATAL" + return "$_ret" + fi + _debug2 "response" "${response}" _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" _debug2 "http response code" "$_code" - if [ "$_code" = "200" ] || [ "$_code" = "201" ]; then # All good - response="$(echo "$response" | _normalizeJson)" - echo -n "${response}" + response="$(echo "${response}" | _normalizeJson)" + echo "$response" return 0 fi if [ "$_code" = "204" ]; then # Success, no body - echo -n "" + echo "$_code" return 0 fi @@ -283,31 +363,30 @@ _edgedns_make_auth_header() { _edgedns_eg_timestamp _edgedns_new_nonce # "Unsigned authorization header: 'EG1-HMAC-SHA256 client_token=block;access_token=block;timestamp=20200806T14:16:33+0000;nonce=72cde72c-82d9-4721-9854-2ba057929d67;'" - _auth_header="$(printf "EG1-HMAC-SHA256 client_token=%s;access_token=%s;timestamp=%s;nonce=%s;" "${AKAMAI_CLIENT_TOKEN}" "${AKAMAI_ACCESS_TOKEN}" "${_eg_timestamp}" "${_nonce}")" + _auth_header="$(printf "EG1-HMAC-SHA256 client_token=%s;access_token=%s;timestamp=%s;nonce=%s;" "$AKAMAI_CLIENT_TOKEN" "$AKAMAI_ACCESS_TOKEN" "$_eg_timestamp" "$_nonce")" _secure_debug2 "Unsigned Auth Header: " "$_auth_header" - _sig="$(_edgedns_sign_request)" - _signed_auth_header="$(printf "%ssignature=%s" "${_auth_header}" "${_sig}")" + _edgedns_sign_request + _signed_auth_header="$(printf "%ssignature=%s" "$_auth_header" "$_signed_req")" _secure_debug2 "Signed Auth Header: " "${_signed_auth_header}" - echo -n "${_signed_auth_header}" } _edgedns_sign_request() { _debug2 "Signing http request" - _signed_data=$(_edgedns_make_data_to_sign "${_auth_header}") - _secure_debug2 "Returned signed data" "$_signed_data" - _key=$(_edgedns_make_signing_key "${_eg_timestamp}") - _signed_req=$(_edgedns_base64_hmac_sha256 "$_signed_data" "$_key") - _secure_debug2 "Signed Request" "${_signed_req}" - echo -n "${_signed_req}" + _edgedns_make_data_to_sign "$_auth_header" + _secure_debug2 "Returned signed data" "$_mdata" + _edgedns_make_signing_key "$_eg_timestamp" + _edgedns_base64_hmac_sha256 "$_mdata" "$_signing_key" + _signed_req="$_hmac_out" + _secure_debug2 "Signed Request" "$_signed_req" } _edgedns_make_signing_key() { _debug2 "Creating sigining key" ts=$1 - _signing_key=$(_edgedns_base64_hmac_sha256 "$ts" "${AKAMAI_CLIENT_SECRET}") - _secure_debug2 "Signing Key" "${_signing_key}" - echo -n "${_signing_key}" + _edgedns_base64_hmac_sha256 "$ts" "$AKAMAI_CLIENT_SECRET" + _signing_key="$_hmac_out" + _secure_debug2 "Signing Key" "$_signing_key" } @@ -315,60 +394,50 @@ _edgedns_make_data_to_sign() { _debug2 "Processing data to sign" hdr=$1 _secure_debug2 "hdr" "$hdr" - content_hash=$(_edgedns_make_content_hash) - path="$(echo -n "${_request_url_path}" |sed 's/https\?:\/\///')" + _edgedns_make_content_hash + path="$(echo "$_request_url_path" | tr -d "\n\r" | sed 's/https\?:\/\///')" path="${path#*$AKAMAI_HOST}" - _debug "hier path" "${path}" + _debug "hier path" "$path" # dont expose headers to sign so use MT string - data="$(printf "%s\thttps\t%s\t%s\t%s\t%s\t%s" "${_request_method}" "${AKAMAI_HOST}" "${path}" "" "${content_hash}" "$hdr")" - _secure_debug2 "Data to Sign" "${data}" - echo -n "${data}" + _mdata="$(printf "%s\thttps\t%s\t%s\t%s\t%s\t%s" "$_request_method" "$AKAMAI_HOST" "$path" "" "$_hash" "$hdr")" + _secure_debug2 "Data to Sign" "$_mdata" } _edgedns_make_content_hash() { _debug2 "Generating content hash" - prep_body="" _hash="" _debug2 "Request method" "${_request_method}" - if [ "${_request_method}" != "POST" ] || [ -z "${_request_body}" ]; then - echo -n "${prep_body}" + if [ "$_request_method" != "POST" ] || [ -z "$_request_body" ]; then return 0 fi - prep_body="$(echo -n "${_request_body}")" - _debug2 "Req body" "${prep_body}" - _hash=$(_edgedns_base64_sha256 "${prep_body}") - _debug2 "Content hash" "${_hash}" - echo -n "${_hash}" + _debug2 "Req body" "$_request_body" + _edgedns_base64_sha256 "$_request_body" + _hash="$_sha256_out" + _debug2 "Content hash" "$_hash" } _edgedns_base64_hmac_sha256() { _debug2 "Generating hmac" data=$1 key=$2 - encoded_data="$(echo -n "${data}" | iconv -t utf-8)" - encoded_key="$(echo -n "${key}" | iconv -t utf-8)" - _secure_debug2 "encoded data" "${encoded_data}" - _secure_debug2 "encoded key" "${encoded_key}" - #key_hex="$(_durl_replace_base64 "$key" | _dbase64 | _hex_dump | tr -d ' ')" - #data_sig="$(printf "%s" "$encoded_data" | _hmac sha256 "${key_hex}" | _base64 | _url_replace)" - - data_sig="$(echo -n "$encoded_data" | ${ACME_OPENSSL_BIN:-openssl} dgst -sha256 -hmac $encoded_key -binary | _base64)" - _secure_debug2 "data_sig:" "${data_sig}" - out="$(echo -n "${data_sig}" | iconv -f utf-8)" - _secure_debug2 "hmac" "${out}" - echo -n "${out}" + encoded_data="$(echo "$data" | iconv -t utf-8)" + encoded_key="$(echo "$key" | iconv -t utf-8)" + _secure_debug2 "encoded data" "$encoded_data" + _secure_debug2 "encoded key" "$encoded_key" + + data_sig="$(echo "$encoded_data" | tr -d "\n\r" | ${ACME_OPENSSL_BIN:-openssl} dgst -sha256 -hmac "$encoded_key" -binary | _base64)" + _secure_debug2 "data_sig:" "$data_sig" + _hmac_out="$(echo "$data_sig" | tr -d "\n\r" | iconv -f utf-8)" + _secure_debug2 "hmac" "$_hmac_out" } _edgedns_base64_sha256() { _debug2 "Creating sha256 digest" trg=$1 - utf8_str="$(echo -n "${trg}" | iconv -t utf-8)" _secure_debug2 "digest data" "$trg" - _secure_debug2 "encoded digest data" "${utf8_str}" - digest="$(echo -n "${trg}" | ${ACME_OPENSSL_BIN:-openssl} dgst -sha256 -binary | _base64)" - out="$(echo -n "${digest}" | iconv -f utf-8)" - _secure_debug2 "digest decode" "${out}" - echo -n "${out}" + digest="$(echo "$trg" | tr -d "\n\r" | ${ACME_OPENSSL_BIN:-openssl} dgst -sha256 -binary | _base64)" + _sha256_out="$(echo "$digest" | tr -d "\n\r" | iconv -f utf-8)" + _secure_debug2 "digest decode" "$_sha256_out" } #_edgedns_parse_edgerc() { From 281ee1a853936e6decbc755c5298f7551c8b52ac Mon Sep 17 00:00:00 2001 From: Ed Lynes Date: Wed, 26 Aug 2020 18:07:46 -0400 Subject: [PATCH 005/383] vetted by shfmt --- dnsapi/dns_edgedns.sh | 49 ++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/dnsapi/dns_edgedns.sh b/dnsapi/dns_edgedns.sh index 7be49761..2072637a 100755 --- a/dnsapi/dns_edgedns.sh +++ b/dnsapi/dns_edgedns.sh @@ -7,15 +7,15 @@ # Report bugs to https://control.akamai.com/apps/support-ui/#/contact-support # Values to export: -# --EITHER-- +# --EITHER-- # *** NOT IMPLEMENTED YET *** # specify Edgegrid credentials file and section -# AKAMAI_EDGERC= +# AKAMAI_EDGERC= # AKAMAI_EDGERC_SECTION="default" ## --OR-- # specify indiviual credentials # export AKAMAI_HOST = -# export AKAMAI_ACCESS_TOKEN = +# export AKAMAI_ACCESS_TOKEN = # export AKAMAI_CLIENT_TOKEN = # export AKAMAI_CLIENT_SECRET = @@ -32,7 +32,7 @@ dns_edgedns_add() { _debug "ENTERING DNS_EDGEDNS_ADD" _debug2 "fulldomain" "$fulldomain" _debug2 "txtvalue" "$txtvalue" - + if ! _EDGEDNS_credentials; then _err "$@" return 1 @@ -42,7 +42,7 @@ dns_edgedns_add() { return 1 fi _debug2 "Add: zone" "$zone" - acmeRecordURI=$(printf "%s/%s/names/%s/types/TXT" "$edge_endpoint" "$zone" "$fulldomain") + acmeRecordURI=$(printf "%s/%s/names/%s/types/TXT" "$edge_endpoint" "$zone" "$fulldomain") _debug3 "Add URL" "$acmeRecordURI" # Get existing TXT record _edge_result=$(_edgedns_rest GET "$acmeRecordURI") @@ -68,13 +68,14 @@ dns_edgedns_add() { _debug3 "existing TXT found" _debug3 "record data" "$rdlist" # value already there? - if _contains "$rdlist" "$txtvalue" ; then + if _contains "$rdlist" "$txtvalue"; then return 0 fi _txt_val="" while [ "$_txt_val" != "$rdlist" ] && [ "${rdlist}" ]; do - _txt_val="${rdlist%%,*}"; rdlist="${rdlist#*,}" - rdata="${rdata},\"${_txt_val}\"" + _txt_val="${rdlist%%,*}" + rdlist="${rdlist#*,}" + rdata="${rdata},\"${_txt_val}\"" done fi # Add the txtvalue TXT Record @@ -139,10 +140,11 @@ dns_edgedns_rm() { rdata="" _txt_val="" while [ "$_txt_val" != "$rdlist" ] && [ "$rdlist" ]; do - _txt_val="${rdlist%%,*}"; rdlist="${rdlist#*,}" + _txt_val="${rdlist%%,*}" + rdlist="${rdlist#*,}" _debug3 "_txt_val" "$_txt_val" _debug3 "txtvalue" "$txtvalue" - if ! _contains "$_txt_val" "$txtvalue" ; then + if ! _contains "$_txt_val" "$txtvalue"; then rdata="${rdata}${comma}\"${_txt_val}\"" comma="," fi @@ -170,7 +172,7 @@ dns_edgedns_rm() { #################### Private functions below ################################## _EDGEDNS_credentials() { - _debug "GettingEdge DNS credentials" + _debug "GettingEdge DNS credentials" _log "$(printf "ACME DNSAPI Edge DNS version %s" ${ACME_EDGEDNS_VERSION})" args_missing=0 if [ -z "$AKAMAI_ACCESS_TOKEN" ]; then @@ -216,7 +218,7 @@ _EDGEDNS_credentials() { _saveaccountconf_mutable AKAMAI_CLIENT_SECRET "$AKAMAI_CLIENT_SECRET" # Set whether curl should use secure or insecure mode fi - export HTTPS_INSECURE=0 # All Edgegrid API calls are secure + export HTTPS_INSECURE=0 # All Edgegrid API calls are secure edge_endpoint=$(printf "https://%s/config-dns/v2/zones" "$AKAMAI_HOST") _debug3 "Edge API Endpoint:" "$edge_endpoint" @@ -244,7 +246,7 @@ _EDGEDNS_getZoneInfo() { return 1 fi fi - if _contains "$curResult" "\"zone\":" ; then + if _contains "$curResult" "\"zone\":"; then _debug2 "Zone data" "${curResult}" zone=$(echo "${curResult}" | _egrep_o "\"zone\"\\s*:\\s*\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d "\"") _debug3 "Zone" "${zone}" @@ -283,7 +285,7 @@ _edgedns_rest() { # Set in acme.sh _post/_get #_edgedns_headers="${_edgedns_headers}${tab}User-Agent:ACME DNSAPI Edge DNS version ${ACME_EDGEDNS_VERSION}" _edgedns_headers="${_edgedns_headers}${tab}Accept: application/json,*/*" - if [ "$m" != "GET" ] && [ "$m" != "DELETE" ] ; then + if [ "$m" != "GET" ] && [ "$m" != "DELETE" ]; then _edgedns_content_type="application/json" _debug3 "_request_body" "$_request_body" _body_len=$(echo "$_request_body" | tr -d "\n\r" | awk '{print length}') @@ -295,13 +297,14 @@ _edgedns_rest() { hdr_indx=1 work_header="${_edgedns_headers}${tab}" _debug3 "work_header" "$work_header" - while [ "$work_header" ]; do - entry="${work_header%%\\t*}"; work_header="${work_header#*\\t}" + while [ "$work_header" ]; do + entry="${work_header%%\\t*}" + work_header="${work_header#*\\t}" export "$(printf "_H%s=%s" "$hdr_indx" "$entry")" _debug2 "Request Header " "$entry" - hdr_indx=$(( hdr_indx + 1 )) + hdr_indx=$((hdr_indx + 1)) done - + # clear headers from previous request to avoid getting wrong http code on timeouts : >"$HTTP_HEADER" _debug2 "$ep" @@ -360,15 +363,15 @@ _edgedns_new_nonce() { _edgedns_make_auth_header() { _debug "Constructing Auth Header" - _edgedns_eg_timestamp - _edgedns_new_nonce + _edgedns_eg_timestamp + _edgedns_new_nonce # "Unsigned authorization header: 'EG1-HMAC-SHA256 client_token=block;access_token=block;timestamp=20200806T14:16:33+0000;nonce=72cde72c-82d9-4721-9854-2ba057929d67;'" - _auth_header="$(printf "EG1-HMAC-SHA256 client_token=%s;access_token=%s;timestamp=%s;nonce=%s;" "$AKAMAI_CLIENT_TOKEN" "$AKAMAI_ACCESS_TOKEN" "$_eg_timestamp" "$_nonce")" + _auth_header="$(printf "EG1-HMAC-SHA256 client_token=%s;access_token=%s;timestamp=%s;nonce=%s;" "$AKAMAI_CLIENT_TOKEN" "$AKAMAI_ACCESS_TOKEN" "$_eg_timestamp" "$_nonce")" _secure_debug2 "Unsigned Auth Header: " "$_auth_header" _edgedns_sign_request _signed_auth_header="$(printf "%ssignature=%s" "$_auth_header" "$_signed_req")" - _secure_debug2 "Signed Auth Header: " "${_signed_auth_header}" + _secure_debug2 "Signed Auth Header: " "${_signed_auth_header}" } _edgedns_sign_request() { @@ -444,5 +447,3 @@ _edgedns_base64_sha256() { # filepath=$1 # section=$2 #} - - From cf7334eb7dc8293f321ebf5bb7123764d28279e0 Mon Sep 17 00:00:00 2001 From: Ed Lynes Date: Thu, 27 Aug 2020 17:40:07 -0400 Subject: [PATCH 006/383] add alt nonce generation logic --- dnsapi/dns_edgedns.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_edgedns.sh b/dnsapi/dns_edgedns.sh index 2072637a..f5705ee8 100755 --- a/dnsapi/dns_edgedns.sh +++ b/dnsapi/dns_edgedns.sh @@ -64,7 +64,7 @@ dns_edgedns_add() { record_op="PUT" rdlist="${_edge_result#*\"rdata\":[}" rdlist="${rdlist%%]*}" - rdlist=$(echo "$rdlist" | tr -d '"' | tr -d "\\") + rdlist=$(echo "$rdlist" | tr -d '"' | tr -d "\\\\") _debug3 "existing TXT found" _debug3 "record data" "$rdlist" # value already there? @@ -132,7 +132,7 @@ dns_edgedns_rm() { # record already exists. Get existing record data and update rdlist="${_edge_result#*\"rdata\":[}" rdlist="${rdlist%%]*}" - rdlist=$(echo "$rdlist" | tr -d '"' | tr -d "\\") + rdlist=$(echo "$rdlist" | tr -d '"' | tr -d "\\\\") _debug3 "rdlist" "$rdlist" if [ -n "$rdlist" ]; then record_op="PUT" @@ -355,10 +355,16 @@ _edgedns_rest() { _edgedns_eg_timestamp() { _eg_timestamp=$(date -u "+%Y%m%dT%H:%M:%S+0000") + _debug3 "_eg_timestamp" "$_eg_timestamp" } _edgedns_new_nonce() { _nonce=$(uuidgen -r) + _ret="$?" + if [ "$_ret" -ne 0 ]; then + _nonce=$(echo "EDGEDNS$(_time)" | _digest sha1 hex | cut -c 1-32) + fi + _debug3 "_nonce" "$_nonce" } _edgedns_make_auth_header() { From e4e6173efff2aa880eecb37509602c12eeac367e Mon Sep 17 00:00:00 2001 From: Jan-Philipp Benecke Date: Fri, 28 Aug 2020 11:21:20 +0200 Subject: [PATCH 007/383] CleverReach Deploy API --- deploy/cleverreach.sh | 70 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 deploy/cleverreach.sh diff --git a/deploy/cleverreach.sh b/deploy/cleverreach.sh new file mode 100644 index 00000000..bf16ed34 --- /dev/null +++ b/deploy/cleverreach.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env sh +# Here is the script to deploy the cert to your CleverReach Account using the CleverReach REST API. +# Your OAuth needs the right scope, please contact CleverReach support for that. +# +# It requires that jq are in the $PATH. +# +# Written by Jan-Philipp Benecke +# Public domain, 2020 +# +# Following environment variables must be set: +# +#export DEPLOY_CLEVERREACH_CLIENT_ID=myid +#export DEPLOY_CLEVERREACH_CLIENT_SECRET=mysecret + +cleverreach_deploy() { + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + + _cleverreach_client_id="${DEPLOY_CLEVERREACH_CLIENT_ID}" + _cleverreach_client_secret="${DEPLOY_CLEVERREACH_CLIENT_SECRET}" + + if [ -z "$_cleverreach_client_id" ]; then + _err "CleverReach Client ID is not found, please define DEPLOY_CLEVERREACH_CLIENT_ID." + return 1 + fi + if [ -z "$_cleverreach_client_secret" ]; then + _err "CleverReach client secret is not found, please define DEPLOY_CLEVERREACH_CLIENT_SECRET." + return 1 + fi + + _saveaccountconf DEPLOY_CLEVERREACH_CLIENT_ID "${_cleverreach_client_id}" + _saveaccountconf DEPLOY_CLEVERREACH_CLIENT_SECRET "${_cleverreach_client_secret}" + + _info "Obtaining a CleverReach access token" + + _data="{\"grant_type\": \"client_credentials\", \"client_id\": \"${_cleverreach_client_id}\", \"client_secret\": \"${_cleverreach_client_secret}\"}" + _auth_result="$(_post "$_data" "https://rest.cleverreach.com/oauth/token.php" "" "POST" "application/json")" + + _debug _data "$_data" + _debug _auth_result "$_auth_result" + + _access_token=$(echo "$_auth_result" | _json_decode | jq -r .access_token) + + _info "Uploading certificate and key to CleverReach" + + _certData="{\"cert\":\"$(cat $_cfullchain | _json_encode)\", \"key\":\"$(cat $_ckey | _json_encode)\"}" + export _H1="Authorization: Bearer ${_access_token}" + _add_cert_result="$(_post "$_certData" "https://rest.cleverreach.com/v3/ssl/${_cdomain}" "" "POST" "application/json")" + + _debug "Destroying token at CleverReach" + _post "" "https://rest.cleverreach.com/v3/oauth/token.json" "" "DELETE" "application/json" + + if ! echo "$_add_cert_result" | grep '"error":' >/dev/null; then + _info "Uploaded certificate successfully" + return 0 + else + _debug _add_cert_result "$_add_cert_result" + _err "Unable to update certificate" + return 1 + fi +} From 39a56884646f0a4038547037050cc8e14d560360 Mon Sep 17 00:00:00 2001 From: Jan-Philipp Benecke Date: Fri, 28 Aug 2020 11:28:06 +0200 Subject: [PATCH 008/383] Make CI happy --- deploy/cleverreach.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/cleverreach.sh b/deploy/cleverreach.sh index bf16ed34..c22e69e1 100644 --- a/deploy/cleverreach.sh +++ b/deploy/cleverreach.sh @@ -52,12 +52,12 @@ cleverreach_deploy() { _info "Uploading certificate and key to CleverReach" - _certData="{\"cert\":\"$(cat $_cfullchain | _json_encode)\", \"key\":\"$(cat $_ckey | _json_encode)\"}" + _certData="{\"cert\":\"$(_json_encode < "$_cfullchain")\", \"key\":\"$(_json_encode < "$_ckey")\"}" export _H1="Authorization: Bearer ${_access_token}" _add_cert_result="$(_post "$_certData" "https://rest.cleverreach.com/v3/ssl/${_cdomain}" "" "POST" "application/json")" _debug "Destroying token at CleverReach" - _post "" "https://rest.cleverreach.com/v3/oauth/token.json" "" "DELETE" "application/json" + _post "" "https://rest.cleverreach.com/v3/oauth/token.json" "" "DELETE" "application/json" if ! echo "$_add_cert_result" | grep '"error":' >/dev/null; then _info "Uploaded certificate successfully" From 2a9c56d9e328716dd90503760a5834488a76c3a6 Mon Sep 17 00:00:00 2001 From: Jan-Philipp Benecke Date: Fri, 28 Aug 2020 11:30:23 +0200 Subject: [PATCH 009/383] Formatting for CI --- deploy/cleverreach.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/cleverreach.sh b/deploy/cleverreach.sh index c22e69e1..d212846b 100644 --- a/deploy/cleverreach.sh +++ b/deploy/cleverreach.sh @@ -52,7 +52,7 @@ cleverreach_deploy() { _info "Uploading certificate and key to CleverReach" - _certData="{\"cert\":\"$(_json_encode < "$_cfullchain")\", \"key\":\"$(_json_encode < "$_ckey")\"}" + _certData="{\"cert\":\"$(_json_encode <"$_cfullchain")\", \"key\":\"$(_json_encode <"$_ckey")\"}" export _H1="Authorization: Bearer ${_access_token}" _add_cert_result="$(_post "$_certData" "https://rest.cleverreach.com/v3/ssl/${_cdomain}" "" "POST" "application/json")" From 339218508d2fd6ef34a2db283c0dea4dc123e8f4 Mon Sep 17 00:00:00 2001 From: Ed Lynes Date: Fri, 28 Aug 2020 09:55:20 -0400 Subject: [PATCH 010/383] shfmt fixes --- dnsapi/dns_edgedns.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_edgedns.sh b/dnsapi/dns_edgedns.sh index f5705ee8..94cf809c 100755 --- a/dnsapi/dns_edgedns.sh +++ b/dnsapi/dns_edgedns.sh @@ -361,9 +361,9 @@ _edgedns_eg_timestamp() { _edgedns_new_nonce() { _nonce=$(uuidgen -r) _ret="$?" - if [ "$_ret" -ne 0 ]; then + if [ "$_ret" -ne 0 ]; then _nonce=$(echo "EDGEDNS$(_time)" | _digest sha1 hex | cut -c 1-32) - fi + fi _debug3 "_nonce" "$_nonce" } From c8ee9e64478b0ef5b0cc02402c8406e0051ff974 Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 11 Sep 2020 23:11:26 +0800 Subject: [PATCH 011/383] add dns api check --- .github/workflows/DNS.yml | 132 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 .github/workflows/DNS.yml diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml new file mode 100644 index 00000000..eb6600f4 --- /dev/null +++ b/.github/workflows/DNS.yml @@ -0,0 +1,132 @@ +name: DNS +on: + push: + branches: + - 'dev' + paths: + - 'dnsapi/*.sh' + - '.github/workflows/DNS.yml' + pull_request: + branches: + - 'dev' + paths: + - 'dnsapi/*.sh' + - '.github/workflows/DNS.yml' + + +jobs: + CheckToken: + runs-on: ubuntu-latest + outputs: + hasToken: ${{ steps.step_one.outputs.hasToken }} + env: + ${{ secrets.TokenName1 }} : ${{ secrets.TokenValue1 }} + steps: + - name: Set the value + id: step_one + run: | + if [ "$${{ secrets.TokenName1 }}" ] ; then + echo "::set-output name=hasToken::true" + else + echo "::set-output name=hasToken::false" + fi + - name: Check the value + run: echo ${{ steps.step_one.outputs.hasToken }} + + Fail: + runs-on: ubuntu-latest + needs: CheckToken + if: "${{needs.CheckToken.outputs.hasToken}} == 'false'" + steps: + - name: Show help page + run: | + echo "Plese see this page to fix the error: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test" + - name: Fail + if: "github.actor != 'Neilpang'" + run: false + + Docker: + runs-on: ubuntu-latest + needs: CheckToken + if: "contains(needs.CheckToken.outputs.hasToken, 'true')" + env: + ${{ secrets.TokenName1 }} : ${{ secrets.TokenValue1 }} + ${{ secrets.TokenName2 }} : ${{ secrets.TokenValue2 }} + TEST_DNS : ${{ secrets.TEST_DNS }} + TestingDomain: ${{ secrets.TestingDomain }} + + TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }} + TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }} + CASE: le_test_dnsapi + TEST_LOCAL: 1 + DEBUG: 1 + steps: + - uses: actions/checkout@v2 + - name: Clone acmetest + run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ + - name: Set env file + run: cd ../acmetest && echo "${{ secrets.TokenName1 }}" >> env.list && echo "${{ secrets.TokenName2 }}" >> env.list && echo "TEST_DNS_NO_WILDCARD" >> env.list && echo "TEST_DNS_SLEEP" >> env.list + - name: Run acmetest + run: cd ../acmetest && ./rundocker.sh _cron + + MacOS: + runs-on: macos-latest + needs: Docker + env: + ${{ secrets.TokenName1 }} : ${{ secrets.TokenValue1 }} + ${{ secrets.TokenName2 }} : ${{ secrets.TokenValue2 }} + TEST_DNS : ${{ secrets.TEST_DNS }} + TestingDomain: ${{ secrets.TestingDomain }} + + TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }} + TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }} + CASE: le_test_dnsapi + TEST_LOCAL: 1 + DEBUG: 1 + steps: + - uses: actions/checkout@v2 + - name: Install tools + run: brew update && brew install socat; + - name: Clone acmetest + run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ + - name: Run acmetest + run: cd ../acmetest && ./letest.sh + + Windows: + runs-on: windows-latest + needs: MacOS + env: + ${{ secrets.TokenName1 }} : ${{ secrets.TokenValue1 }} + ${{ secrets.TokenName2 }} : ${{ secrets.TokenValue2 }} + TEST_DNS : ${{ secrets.TEST_DNS }} + TestingDomain: ${{ secrets.TestingDomain }} + + TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }} + TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }} + CASE: le_test_dnsapi + TEST_LOCAL: 1 + DEBUG: 1 + steps: + - name: Set git to use LF + run: | + git config --global core.autocrlf false + - uses: actions/checkout@v2 + - name: Install cygwin base packages with chocolatey + run: | + choco config get cacheLocation + choco install --no-progress cygwin + shell: cmd + - name: Install cygwin additional packages + run: | + C:\tools\cygwin\cygwinsetup.exe -qgnNdO -R C:/tools/cygwin -s http://mirrors.kernel.org/sourceware/cygwin/ -P socat,curl,cron,unzip,git + shell: cmd + - name: Set ENV + run: | + echo '::set-env name=PATH::C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin' + - name: Clone acmetest + run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ + - name: Run acmetest + shell: cmd + run: cd ../acmetest && bash.exe -c ./letest.sh + + From e7a6c17260731cf659c55cad9378d2187d846f2e Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 11 Sep 2020 23:35:27 +0800 Subject: [PATCH 012/383] fix dns check --- .github/workflows/DNS.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index eb6600f4..0f60ace2 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -20,12 +20,12 @@ jobs: outputs: hasToken: ${{ steps.step_one.outputs.hasToken }} env: - ${{ secrets.TokenName1 }} : ${{ secrets.TokenValue1 }} + _ACME_CHECK_TOKEN_${{ secrets.TokenName1 }} : ${{ secrets.TokenValue1 }} steps: - name: Set the value id: step_one run: | - if [ "$${{ secrets.TokenName1 }}" ] ; then + if [ "$_ACME_CHECK_TOKEN_${{ secrets.TokenName1}}" ] ; then echo "::set-output name=hasToken::true" else echo "::set-output name=hasToken::false" @@ -36,9 +36,9 @@ jobs: Fail: runs-on: ubuntu-latest needs: CheckToken - if: "${{needs.CheckToken.outputs.hasToken}} == 'false'" + if: "contains(needs.CheckToken.outputs.hasToken, 'false')" steps: - - name: Show help page + - name: "Read this: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test" run: | echo "Plese see this page to fix the error: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test" - name: Fail From b561666d803fadf8e226400d7115e92d8c43f1f6 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 12 Sep 2020 08:47:46 +0800 Subject: [PATCH 013/383] fix https://github.com/acmesh-official/acme.sh/issues/3159 --- dnsapi/dns_ovh.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_ovh.sh b/dnsapi/dns_ovh.sh index dda47dda..f6f9689a 100755 --- a/dnsapi/dns_ovh.sh +++ b/dnsapi/dns_ovh.sh @@ -248,7 +248,7 @@ _ovh_authentication() { # _domain=domain.com _get_root() { domain=$1 - i=2 + i=1 p=1 while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) From b147195189bc258d9fcf7b623f0154c8009c2741 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 12 Sep 2020 14:22:18 +0800 Subject: [PATCH 014/383] use testall target --- .github/workflows/DNS.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 0f60ace2..0274afcf 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -67,7 +67,7 @@ jobs: - name: Set env file run: cd ../acmetest && echo "${{ secrets.TokenName1 }}" >> env.list && echo "${{ secrets.TokenName2 }}" >> env.list && echo "TEST_DNS_NO_WILDCARD" >> env.list && echo "TEST_DNS_SLEEP" >> env.list - name: Run acmetest - run: cd ../acmetest && ./rundocker.sh _cron + run: cd ../acmetest && ./rundocker.sh testall MacOS: runs-on: macos-latest From 490a7d4a78b6b9282cf5769aa7cad44b54952c28 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 13 Sep 2020 00:16:04 +0800 Subject: [PATCH 015/383] support more dns tokens --- .github/workflows/DNS.yml | 71 ++++++++++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 0274afcf..ae71d594 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -19,13 +19,11 @@ jobs: runs-on: ubuntu-latest outputs: hasToken: ${{ steps.step_one.outputs.hasToken }} - env: - _ACME_CHECK_TOKEN_${{ secrets.TokenName1 }} : ${{ secrets.TokenValue1 }} steps: - name: Set the value id: step_one run: | - if [ "$_ACME_CHECK_TOKEN_${{ secrets.TokenName1}}" ] ; then + if [ "${{secrets.TokenName1}}" ] ; then echo "::set-output name=hasToken::true" else echo "::set-output name=hasToken::false" @@ -50,11 +48,8 @@ jobs: needs: CheckToken if: "contains(needs.CheckToken.outputs.hasToken, 'true')" env: - ${{ secrets.TokenName1 }} : ${{ secrets.TokenValue1 }} - ${{ secrets.TokenName2 }} : ${{ secrets.TokenValue2 }} TEST_DNS : ${{ secrets.TEST_DNS }} TestingDomain: ${{ secrets.TestingDomain }} - TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }} TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }} CASE: le_test_dnsapi @@ -65,7 +60,25 @@ jobs: - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - name: Set env file - run: cd ../acmetest && echo "${{ secrets.TokenName1 }}" >> env.list && echo "${{ secrets.TokenName2 }}" >> env.list && echo "TEST_DNS_NO_WILDCARD" >> env.list && echo "TEST_DNS_SLEEP" >> env.list + run: | + cd ../acmetest + if [ "${{ secrets.TokenName1}}" ] ; then + echo "${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}" >> env.list + fi + if [ "${{ secrets.TokenName2}}" ] ; then + echo "${{ secrets.TokenName2}}=${{ secrets.TokenValue2}}" >> env.list + fi + if [ "${{ secrets.TokenName3}}" ] ; then + echo "${{ secrets.TokenName3}}=${{ secrets.TokenValue3}}" >> env.list + fi + if [ "${{ secrets.TokenName4}}" ] ; then + echo "${{ secrets.TokenName4}}=${{ secrets.TokenValue4}}" >> env.list + fi + if [ "${{ secrets.TokenName5}}" ] ; then + echo "${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}" >> env.list + fi + echo "TEST_DNS_NO_WILDCARD" >> env.list + echo "TEST_DNS_SLEEP" >> env.list - name: Run acmetest run: cd ../acmetest && ./rundocker.sh testall @@ -73,11 +86,8 @@ jobs: runs-on: macos-latest needs: Docker env: - ${{ secrets.TokenName1 }} : ${{ secrets.TokenValue1 }} - ${{ secrets.TokenName2 }} : ${{ secrets.TokenValue2 }} TEST_DNS : ${{ secrets.TEST_DNS }} TestingDomain: ${{ secrets.TestingDomain }} - TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }} TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }} CASE: le_test_dnsapi @@ -90,17 +100,31 @@ jobs: - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - name: Run acmetest - run: cd ../acmetest && ./letest.sh + run: | + if [ "${{ secrets.TokenName1}}" ] ; then + export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}} + fi + if [ "${{ secrets.TokenName2}}" ] ; then + export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}} + fi + if [ "${{ secrets.TokenName3}}" ] ; then + export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}} + fi + if [ "${{ secrets.TokenName4}}" ] ; then + export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}} + fi + if [ "${{ secrets.TokenName5}}" ] ; then + export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}} + fi + cd ../acmetest + ./letest.sh Windows: runs-on: windows-latest needs: MacOS env: - ${{ secrets.TokenName1 }} : ${{ secrets.TokenValue1 }} - ${{ secrets.TokenName2 }} : ${{ secrets.TokenValue2 }} TEST_DNS : ${{ secrets.TEST_DNS }} TestingDomain: ${{ secrets.TestingDomain }} - TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }} TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }} CASE: le_test_dnsapi @@ -127,6 +151,23 @@ jobs: run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - name: Run acmetest shell: cmd - run: cd ../acmetest && bash.exe -c ./letest.sh + run: | + if [ "${{ secrets.TokenName1}}" ] ; then + set ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}} + fi + if [ "${{ secrets.TokenName2}}" ] ; then + set ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}} + fi + if [ "${{ secrets.TokenName3}}" ] ; then + set ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}} + fi + if [ "${{ secrets.TokenName4}}" ] ; then + set ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}} + fi + if [ "${{ secrets.TokenName5}}" ] ; then + set ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}} + fi + cd ../acmetest + bash.exe -c ./letest.sh From b74a501fac2a8503e8d14a06d0ba6d966355ff56 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 14 Sep 2020 21:51:21 +0800 Subject: [PATCH 016/383] fix for Windows --- .github/workflows/DNS.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index ae71d594..5591b8f1 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -150,24 +150,24 @@ jobs: - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - name: Run acmetest - shell: cmd + shell: bash run: | if [ "${{ secrets.TokenName1}}" ] ; then - set ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}} + export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}} fi if [ "${{ secrets.TokenName2}}" ] ; then - set ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}} + export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}} fi if [ "${{ secrets.TokenName3}}" ] ; then - set ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}} + export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}} fi if [ "${{ secrets.TokenName4}}" ] ; then - set ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}} + export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}} fi if [ "${{ secrets.TokenName5}}" ] ; then - set ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}} + export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}} fi cd ../acmetest - bash.exe -c ./letest.sh + ./letest.sh From 5e3aa2db1d6af012d574cc5c71ee5a247b0c54e9 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 14 Sep 2020 22:22:36 +0800 Subject: [PATCH 017/383] add debug info for duckdns --- dnsapi/dns_duckdns.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index 11b685c0..7c2ecfb2 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -112,6 +112,9 @@ _duckdns_rest() { param="$2" _debug param "$param" url="$DuckDNS_API?$param" + if [ "$DEBUG" -gt 0 ]; then + url="$url&verbose=true" + fi _debug url "$url" # DuckDNS uses GET to update domain info From db24ca3dc19e246c7952ea5b8120dff14fc3acca Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 14 Sep 2020 22:29:23 +0800 Subject: [PATCH 018/383] fix debug info --- dnsapi/dns_duckdns.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index 7c2ecfb2..f0af2741 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -120,11 +120,13 @@ _duckdns_rest() { # DuckDNS uses GET to update domain info if [ "$method" = "GET" ]; then response="$(_get "$url")" + _debug2 response "$response" + if [ "$DEBUG" -gt 0 ] && _contains "$response" "UPDATED" && _contains "$response" "OK"; then + response="OK" + fi else _err "Unsupported method" return 1 fi - - _debug2 response "$response" return 0 } From 60fe987a5f8d43a6c67d048b79839200d7de5cf1 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 21 Sep 2020 19:57:10 +0800 Subject: [PATCH 019/383] enable for any branches. --- .github/workflows/DNS.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 5591b8f1..3ad9506b 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -1,8 +1,6 @@ name: DNS on: push: - branches: - - 'dev' paths: - 'dnsapi/*.sh' - '.github/workflows/DNS.yml' From 8694e0ad19f3320ab677cc72678a220d5b112b73 Mon Sep 17 00:00:00 2001 From: neil Date: Thu, 24 Sep 2020 21:37:51 +0800 Subject: [PATCH 020/383] add freebsd --- .github/workflows/LetsEncrypt.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 9a0175b5..69ff35ff 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -96,4 +96,20 @@ jobs: shell: cmd run: cd ../acmetest && bash.exe -c ./letest.sh + FreeBSD: + runs-on: macos-latest + needs: Windows + env: + NGROK_TOKEN : ${{ secrets.NGROK_TOKEN }} + TEST_LOCAL: 1 + steps: + - uses: actions/checkout@v2 + - name: Clone acmetest + run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ + - uses: vmactions/freebsd@main + with: + envs: 'NGROK_TOKEN TEST_LOCAL' + prepare: pkg install -y socat + run: | + cd ../acmetest && ./letest.sh From 9073c4554f93dc0e934f206555e1b9b45fd59763 Mon Sep 17 00:00:00 2001 From: neil Date: Thu, 24 Sep 2020 22:18:38 +0800 Subject: [PATCH 021/383] add curl to freebsd --- .github/workflows/LetsEncrypt.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 69ff35ff..4a8d4336 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -109,7 +109,7 @@ jobs: - uses: vmactions/freebsd@main with: envs: 'NGROK_TOKEN TEST_LOCAL' - prepare: pkg install -y socat + prepare: pkg install -y socat curl run: | cd ../acmetest && ./letest.sh From 07979a13fb2d30c967111d93211ddbaa986171ca Mon Sep 17 00:00:00 2001 From: neil Date: Thu, 24 Sep 2020 22:57:26 +0800 Subject: [PATCH 022/383] add FreeBSD --- .github/workflows/DNS.yml | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 3ad9506b..fd9a98b3 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -168,4 +168,42 @@ jobs: cd ../acmetest ./letest.sh + FreeBSD: + runs-on: macos-latest + needs: Windows + env: + TEST_DNS : ${{ secrets.TEST_DNS }} + TestingDomain: ${{ secrets.TestingDomain }} + TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }} + TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }} + CASE: le_test_dnsapi + TEST_LOCAL: 1 + DEBUG: 1 + steps: + - uses: actions/checkout@v2 + - name: Clone acmetest + run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ + - uses: vmactions/freebsd@main + with: + envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' + prepare: pkg install -y socat curl + run: | + if [ "${{ secrets.TokenName1}}" ] ; then + export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}} + fi + if [ "${{ secrets.TokenName2}}" ] ; then + export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}} + fi + if [ "${{ secrets.TokenName3}}" ] ; then + export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}} + fi + if [ "${{ secrets.TokenName4}}" ] ; then + export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}} + fi + if [ "${{ secrets.TokenName5}}" ] ; then + export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}} + fi + cd ../acmetest + ./letest.sh + From be7b87cda32fb022d903e5c049ac02cf1a71d444 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 28 Sep 2020 21:50:20 +0800 Subject: [PATCH 023/383] fix message --- .github/workflows/DNS.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index fd9a98b3..191ae8c9 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -36,10 +36,10 @@ jobs: steps: - name: "Read this: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test" run: | - echo "Plese see this page to fix the error: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test" - - name: Fail - if: "github.actor != 'Neilpang'" - run: false + echo "Read this: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test" + if [ "${{github.actor}}" != "Neilpang" ]; then + false + fi Docker: runs-on: ubuntu-latest From f7e12b629f7bdf3b5f637189fafef0af37994f98 Mon Sep 17 00:00:00 2001 From: Jan-Philipp Benecke Date: Thu, 1 Oct 2020 11:26:29 +0200 Subject: [PATCH 024/383] Update CleverReach REST Endpoint --- deploy/cleverreach.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/cleverreach.sh b/deploy/cleverreach.sh index d212846b..0fa07f4a 100644 --- a/deploy/cleverreach.sh +++ b/deploy/cleverreach.sh @@ -54,7 +54,7 @@ cleverreach_deploy() { _certData="{\"cert\":\"$(_json_encode <"$_cfullchain")\", \"key\":\"$(_json_encode <"$_ckey")\"}" export _H1="Authorization: Bearer ${_access_token}" - _add_cert_result="$(_post "$_certData" "https://rest.cleverreach.com/v3/ssl/${_cdomain}" "" "POST" "application/json")" + _add_cert_result="$(_post "$_certData" "https://rest.cleverreach.com/v3/ssl" "" "POST" "application/json")" _debug "Destroying token at CleverReach" _post "" "https://rest.cleverreach.com/v3/oauth/token.json" "" "DELETE" "application/json" From 238efb02c6c743a24142f724f0cee0223b66e033 Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 2 Oct 2020 16:17:16 +0800 Subject: [PATCH 025/383] update freebsd-vm --- .github/workflows/DNS.yml | 2 +- .github/workflows/LetsEncrypt.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 191ae8c9..1c0165c0 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -183,7 +183,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd@main + - uses: vmactions/freebsd-vm@v0.0.4 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkg install -y socat curl diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 4a8d4336..ba5e933d 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -106,7 +106,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd@main + - uses: vmactions/freebsd-vm@v0.0.4 with: envs: 'NGROK_TOKEN TEST_LOCAL' prepare: pkg install -y socat curl From c9ff536e245e17765a95bd06f41676536268cc23 Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 2 Oct 2020 16:20:27 +0800 Subject: [PATCH 026/383] minor --- .github/workflows/DNS.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 1c0165c0..976aff56 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -206,4 +206,5 @@ jobs: cd ../acmetest ./letest.sh + From a017fbadd3b4debd2d605e35de883f5f39215b57 Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 2 Oct 2020 17:11:04 +0800 Subject: [PATCH 027/383] update badge --- README.md | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 953c44a5..6fb88daf 100644 --- a/README.md +++ b/README.md @@ -57,26 +57,26 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa) | NO | Status| Platform| |----|-------|---------| -|1|[![](https://acmesh-official.github.io/acmetest/status/ubuntu-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)| Ubuntu -|2|[![](https://acmesh-official.github.io/acmetest/status/debian-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)| Debian -|3|[![](https://acmesh-official.github.io/acmetest/status/centos-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|CentOS -|4|[![](https://acmesh-official.github.io/acmetest/status/windows-cygwin.svg)](https://github.com/acmesh-official/acmetest#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/acmetest#here-are-the-latest-status)|FreeBSD -|6|[![](https://acmesh-official.github.io/acmetest/status/pfsense.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|pfsense -|7|[![](https://acmesh-official.github.io/acmetest/status/opensuse-leap-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|openSUSE -|8|[![](https://acmesh-official.github.io/acmetest/status/alpine-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Alpine Linux (with curl) -|9|[![](https://acmesh-official.github.io/acmetest/status/archlinux-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Archlinux -|10|[![](https://acmesh-official.github.io/acmetest/status/fedora-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|fedora -|11|[![](https://acmesh-official.github.io/acmetest/status/kalilinux-kali.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Kali Linux -|12|[![](https://acmesh-official.github.io/acmetest/status/oraclelinux-latest.svg)](https://github.com/acmesh-official/acmetest#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: See Proxmox VE Wiki. Version [4.x, 5.0, 5.1](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x,_5.0_and_5.1)#Let.27s_Encrypt_using_acme.sh), version [5.2 and up](https://pve.proxmox.com/wiki/Certificate_Management) -|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/acmetest#here-are-the-latest-status)|OpenBSD -|16|[![](https://acmesh-official.github.io/acmetest/status/mageia.svg)](https://github.com/acmesh-official/acmetest#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/acmetest#here-are-the-latest-status)|SunOS/Solaris -|19|[![](https://acmesh-official.github.io/acmetest/status/gentoo-stage3-amd64.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Gentoo Linux -|20|[![Build Status](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|Mac OSX +|1|[![MacOS](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|Mac OSX +|2|[![Windows](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|Windows (cygwin with curl, openssl and crontab included) +|3|[![FreeBSD](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|FreeBSD +|4|[![](https://acmesh-official.github.io/acmetest/status/pfsense.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|pfsense +|5|[![](https://acmesh-official.github.io/acmetest/status/openbsd.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|OpenBSD +|6|[![](https://acmesh-official.github.io/acmetest/status/solaris.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|SunOS/Solaris +|7|[![](https://acmesh-official.github.io/acmetest/status/ubuntu-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)| Ubuntu +|8|[![](https://acmesh-official.github.io/acmetest/status/debian-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)| Debian +|9|[![](https://acmesh-official.github.io/acmetest/status/centos-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|CentOS +|10|[![](https://acmesh-official.github.io/acmetest/status/opensuse-leap-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|openSUSE +|11|[![](https://acmesh-official.github.io/acmetest/status/alpine-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Alpine Linux (with curl) +|12|[![](https://acmesh-official.github.io/acmetest/status/archlinux-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Archlinux +|13|[![](https://acmesh-official.github.io/acmetest/status/fedora-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|fedora +|14|[![](https://acmesh-official.github.io/acmetest/status/kalilinux-kali.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Kali Linux +|15|[![](https://acmesh-official.github.io/acmetest/status/oraclelinux-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Oracle Linux +|16|[![](https://acmesh-official.github.io/acmetest/status/proxmox.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Proxmox: See Proxmox VE Wiki. Version [4.x, 5.0, 5.1](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x,_5.0_and_5.1)#Let.27s_Encrypt_using_acme.sh), version [5.2 and up](https://pve.proxmox.com/wiki/Certificate_Management) +|17|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111 +|18|[![](https://acmesh-official.github.io/acmetest/status/mageia.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Mageia +|19|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT) +|20|[![](https://acmesh-official.github.io/acmetest/status/gentoo-stage3-amd64.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Gentoo Linux |21|[![](https://acmesh-official.github.io/acmetest/status/clearlinux-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|ClearLinux For all build statuses, check our [weekly build project](https://github.com/acmesh-official/acmetest): From 4db7f6f59c64dcd3045365ef83629ea09b68337a Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 2 Oct 2020 17:17:31 +0800 Subject: [PATCH 028/383] update badge --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6fb88daf..7215785c 100644 --- a/README.md +++ b/README.md @@ -60,10 +60,10 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa) |1|[![MacOS](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|Mac OSX |2|[![Windows](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|Windows (cygwin with curl, openssl and crontab included) |3|[![FreeBSD](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|FreeBSD -|4|[![](https://acmesh-official.github.io/acmetest/status/pfsense.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|pfsense -|5|[![](https://acmesh-official.github.io/acmetest/status/openbsd.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|OpenBSD -|6|[![](https://acmesh-official.github.io/acmetest/status/solaris.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|SunOS/Solaris -|7|[![](https://acmesh-official.github.io/acmetest/status/ubuntu-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)| Ubuntu +|4|[![Ubuntu](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)| Ubuntu +|5|[![](https://acmesh-official.github.io/acmetest/status/pfsense.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|pfsense +|6|[![](https://acmesh-official.github.io/acmetest/status/openbsd.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|OpenBSD +|7|[![](https://acmesh-official.github.io/acmetest/status/solaris.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|SunOS/Solaris |8|[![](https://acmesh-official.github.io/acmetest/status/debian-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)| Debian |9|[![](https://acmesh-official.github.io/acmetest/status/centos-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|CentOS |10|[![](https://acmesh-official.github.io/acmetest/status/opensuse-leap-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|openSUSE From 784b914e0741099feb1ccd22d2f09a91f09a0ded Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 9 Oct 2020 22:33:21 +0800 Subject: [PATCH 029/383] update freebsd --- .github/workflows/DNS.yml | 3 ++- .github/workflows/LetsEncrypt.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 976aff56..b06db229 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -183,10 +183,11 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.0.4 + - uses: vmactions/freebsd-vm@v0.0.5 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkg install -y socat curl + usesh: true run: | if [ "${{ secrets.TokenName1}}" ] ; then export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}} diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index ba5e933d..d71f3ac1 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -106,10 +106,11 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.0.4 + - uses: vmactions/freebsd-vm@v0.0.5 with: envs: 'NGROK_TOKEN TEST_LOCAL' prepare: pkg install -y socat curl + usesh: true run: | cd ../acmetest && ./letest.sh From 05141b4f527d8aaacf75b9762e82affa1acac07c Mon Sep 17 00:00:00 2001 From: Rene Luria Date: Mon, 21 Sep 2020 14:17:23 +0200 Subject: [PATCH 030/383] Added dnsapi/dns_infomaniak.sh --- dnsapi/dns_infomaniak.sh | 199 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100755 dnsapi/dns_infomaniak.sh diff --git a/dnsapi/dns_infomaniak.sh b/dnsapi/dns_infomaniak.sh new file mode 100755 index 00000000..e2328a36 --- /dev/null +++ b/dnsapi/dns_infomaniak.sh @@ -0,0 +1,199 @@ +#!/usr/bin/env sh + +############################################################################### +# Infomaniak API integration +# +# To use this API you need visit the API dashboard of your account +# once logged into https://manager.infomaniak.com add /api/dashboard to the URL +# +# Please report bugs to +# https://github.com/acmesh-official/acme.sh/issues/3188 +# +# Note: the URL looks like this: +# https://manager.infomaniak.com/v3//api/dashboard +# Then generate a token with the scope Domain +# this is given as an environment variable INFOMANIAK_API_TOKEN +############################################################################### + +# base variables + +DEFAULT_INFOMANIAK_API_URL="https://api.infomaniak.com" +DEFAULT_INFOMANIAK_TTL=300 + +######## Public functions ##################### + +#Usage: dns_infomaniak_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_infomaniak_add() { + + INFOMANIAK_API_TOKEN="${INFOMANIAK_API_TOKEN:-$(_readaccountconf_mutable INFOMANIAK_API_TOKEN)}" + INFOMANIAK_API_URL="${INFOMANIAK_API_URL:-$(_readaccountconf_mutable INFOMANIAK_API_URL)}" + INFOMANIAK_TTL="${INFOMANIAK_TTL:-$(_readaccountconf_mutable INFOMANIAK_TTL)}" + + if [ -z "$INFOMANIAK_API_TOKEN" ]; then + INFOMANIAK_API_TOKEN="" + _err "Please provide a valid Infomaniak API token in variable INFOMANIAK_API_TOKEN" + return 1 + fi + + if [ -z "$INFOMANIAK_API_URL" ]; then + INFOMANIAK_API_URL="$DEFAULT_INFOMANIAK_API_URL" + fi + + if [ -z "$INFOMANIAK_TTL" ]; then + INFOMANIAK_TTL="$DEFAULT_INFOMANIAK_TTL" + fi + + #save the token to the account conf file. + _saveaccountconf_mutable INFOMANIAK_API_TOKEN "$INFOMANIAK_API_TOKEN" + + if [ "$INFOMANIAK_API_URL" != "$DEFAULT_INFOMANIAK_API_URL" ]; then + _saveaccountconf_mutable INFOMANIAK_API_URL "$INFOMANIAK_API_URL" + fi + + if [ "$INFOMANIAK_TTL" != "$DEFAULT_INFOMANIAK_TTL" ]; then + _saveaccountconf_mutable INFOMANIAK_TTL "$INFOMANIAK_TTL" + fi + + export _H1="Authorization: Bearer $INFOMANIAK_API_TOKEN" + export _H2="Content-Type: application/json" + + fulldomain="$1" + txtvalue="$2" + + _info "Infomaniak DNS API" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + fqdn=${fulldomain#_acme-challenge.} + + # guess which base domain to add record to + zone_and_id=$(_find_zone "$fqdn") + if [ -z "$zone_and_id" ]; then + _err "cannot find zone to modify" + return 1 + fi + zone=${zone_and_id% *} + domain_id=${zone_and_id#* } + + # extract first part of domain + key=${fulldomain%.$zone} + + _debug "zone:$zone id:$domain_id key:$key" + + # payload + data="{\"type\": \"TXT\", \"source\": \"$key\", \"target\": \"$txtvalue\", \"ttl\": $INFOMANIAK_TTL}" + + # API call + response=$(_post "$data" "${INFOMANIAK_API_URL}/1/domain/$domain_id/dns/record") + if [ -n "$response" ] && echo "$response" | grep -qF '"result":"success"'; then + _info "Record added" + _debug "Response: $response" + return 0 + fi + _err "could not create record" + _debug "Response: $response" + return 1 +} + +#Usage: fulldomain txtvalue +#Remove the txt record after validation. +dns_infomaniak_rm() { + + INFOMANIAK_API_TOKEN="${INFOMANIAK_API_TOKEN:-$(_readaccountconf_mutable INFOMANIAK_API_TOKEN)}" + INFOMANIAK_API_URL="${INFOMANIAK_API_URL:-$(_readaccountconf_mutable INFOMANIAK_API_URL)}" + INFOMANIAK_TTL="${INFOMANIAK_TTL:-$(_readaccountconf_mutable INFOMANIAK_TTL)}" + + if [ -z "$INFOMANIAK_API_TOKEN" ]; then + INFOMANIAK_API_TOKEN="" + _err "Please provide a valid Infomaniak API token in variable INFOMANIAK_API_TOKEN" + return 1 + fi + + if [ -z "$INFOMANIAK_API_URL" ]; then + INFOMANIAK_API_URL="$DEFAULT_INFOMANIAK_API_URL" + fi + + if [ -z "$INFOMANIAK_TTL" ]; then + INFOMANIAK_TTL="$DEFAULT_INFOMANIAK_TTL" + fi + + #save the token to the account conf file. + _saveaccountconf_mutable INFOMANIAK_API_TOKEN "$INFOMANIAK_API_TOKEN" + + if [ "$INFOMANIAK_API_URL" != "$DEFAULT_INFOMANIAK_API_URL" ]; then + _saveaccountconf_mutable INFOMANIAK_API_URL "$INFOMANIAK_API_URL" + fi + + if [ "$INFOMANIAK_TTL" != "$DEFAULT_INFOMANIAK_TTL" ]; then + _saveaccountconf_mutable INFOMANIAK_TTL "$INFOMANIAK_TTL" + fi + + export _H1="Authorization: Bearer $INFOMANIAK_API_TOKEN" + export _H2="ContentType: application/json" + + fulldomain=$1 + txtvalue=$2 + _info "Infomaniak DNS API" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + fqdn=${fulldomain#_acme-challenge.} + + # guess which base domain to add record to + zone_and_id=$(_find_zone "$fqdn") + if [ -z "$zone_and_id" ]; then + _err "cannot find zone to modify" + return 1 + fi + zone=${zone_and_id% *} + domain_id=${zone_and_id#* } + + # extract first part of domain + key=${fulldomain%.$zone} + + _debug "zone:$zone id:$domain_id key:$key" + + # find previous record + # shellcheck disable=SC1004 + record_id=$(_get "${INFOMANIAK_API_URL}/1/domain/$domain_id/dns/record" | sed 's/.*"data":\[\(.*\)\]}/\1/; s/},{/}\ +{/g' | sed -n 's/.*"id":"*\([0-9]*\)"*.*"source_idn":"'"$fulldomain"'".*"target_idn":"'"$txtvalue"'".*/\1/p') + if [ -z "$record_id" ]; then + _err "could not find record to delete" + return 1 + fi + _debug "record_id: $record_id" + + # API call + response=$(_post "" "${INFOMANIAK_API_URL}/1/domain/$domain_id/dns/record/$record_id" "" DELETE) + if [ -n "$response" ] && echo "$response" | grep -qF '"result":"success"'; then + _info "Record deleted" + return 0 + fi + _err "could not delete record" + return 1 +} + +#################### Private functions below ################################## + +_get_domain_id() { + domain="$1" + + # shellcheck disable=SC1004 + _get "${INFOMANIAK_API_URL}/1/product?service_name=domain&customer_name=$domain" | sed 's/.*"data":\[{\(.*\)}\]}/\1/; s/,/\ +/g' | sed -n 's/^"id":\(.*\)/\1/p' +} + +_find_zone() { + zone="$1" + + # find domain in list, removing . parts sequentialy + while echo "$zone" | grep -q '\.'; do + _debug "testing $zone" + id=$(_get_domain_id "$zone") + if [ -n "$id" ]; then + echo "$zone $id" + return + fi + zone=${zone#*.} + done +} From 472dbd641ca9e545523ab059fc8316885906b482 Mon Sep 17 00:00:00 2001 From: Rene Luria Date: Fri, 2 Oct 2020 12:47:33 +0200 Subject: [PATCH 031/383] dnsapi/dns_infomaniak.sh: Replace grep by _contains --- dnsapi/dns_infomaniak.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_infomaniak.sh b/dnsapi/dns_infomaniak.sh index e2328a36..765cf39d 100755 --- a/dnsapi/dns_infomaniak.sh +++ b/dnsapi/dns_infomaniak.sh @@ -85,7 +85,7 @@ dns_infomaniak_add() { # API call response=$(_post "$data" "${INFOMANIAK_API_URL}/1/domain/$domain_id/dns/record") - if [ -n "$response" ] && echo "$response" | grep -qF '"result":"success"'; then + if [ -n "$response" ] && echo "$response" | _contains '"result":"success"'; then _info "Record added" _debug "Response: $response" return 0 @@ -165,7 +165,7 @@ dns_infomaniak_rm() { # API call response=$(_post "" "${INFOMANIAK_API_URL}/1/domain/$domain_id/dns/record/$record_id" "" DELETE) - if [ -n "$response" ] && echo "$response" | grep -qF '"result":"success"'; then + if [ -n "$response" ] && echo "$response" | _contains '"result":"success"'; then _info "Record deleted" return 0 fi @@ -187,7 +187,7 @@ _find_zone() { zone="$1" # find domain in list, removing . parts sequentialy - while echo "$zone" | grep -q '\.'; do + while _contains "$zone" '\.'; do _debug "testing $zone" id=$(_get_domain_id "$zone") if [ -n "$id" ]; then From f864416e39753b66f26d8d3fa19cbb094493731a Mon Sep 17 00:00:00 2001 From: Rene Luria Date: Thu, 8 Oct 2020 23:42:05 +0200 Subject: [PATCH 032/383] Fix DNS workflow use variables TEST_DNS_SLEEP and TEST_DNS_NO_WILDCARD --- .github/workflows/DNS.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index b06db229..1909cb03 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -75,8 +75,8 @@ jobs: if [ "${{ secrets.TokenName5}}" ] ; then echo "${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}" >> env.list fi - echo "TEST_DNS_NO_WILDCARD" >> env.list - echo "TEST_DNS_SLEEP" >> env.list + echo "TEST_DNS_NO_WILDCARD=$TEST_DNS_NO_WILDCARD" >> env.list + echo "TEST_DNS_SLEEP=$TEST_DNS_SLEEP" >> env.list - name: Run acmetest run: cd ../acmetest && ./rundocker.sh testall From e05dc99006f5548c20f5caec8b1a89a23ed492a0 Mon Sep 17 00:00:00 2001 From: Rene Luria Date: Sat, 10 Oct 2020 18:20:26 +0200 Subject: [PATCH 033/383] Revert "Fix DNS workflow use variables TEST_DNS_SLEEP and TEST_DNS_NO_WILDCARD" This reverts commit f864416e39753b66f26d8d3fa19cbb094493731a. --- .github/workflows/DNS.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 1909cb03..b06db229 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -75,8 +75,8 @@ jobs: if [ "${{ secrets.TokenName5}}" ] ; then echo "${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}" >> env.list fi - echo "TEST_DNS_NO_WILDCARD=$TEST_DNS_NO_WILDCARD" >> env.list - echo "TEST_DNS_SLEEP=$TEST_DNS_SLEEP" >> env.list + echo "TEST_DNS_NO_WILDCARD" >> env.list + echo "TEST_DNS_SLEEP" >> env.list - name: Run acmetest run: cd ../acmetest && ./rundocker.sh testall From ea3e6dae93e76dfe79272c6cb9dd0c6b9acbb297 Mon Sep 17 00:00:00 2001 From: Ed Lynes Date: Wed, 14 Oct 2020 14:49:09 -0400 Subject: [PATCH 034/383] remove uuidgen --- dnsapi/dns_edgedns.sh | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/dnsapi/dns_edgedns.sh b/dnsapi/dns_edgedns.sh index 94cf809c..89e77936 100755 --- a/dnsapi/dns_edgedns.sh +++ b/dnsapi/dns_edgedns.sh @@ -359,11 +359,7 @@ _edgedns_eg_timestamp() { } _edgedns_new_nonce() { - _nonce=$(uuidgen -r) - _ret="$?" - if [ "$_ret" -ne 0 ]; then - _nonce=$(echo "EDGEDNS$(_time)" | _digest sha1 hex | cut -c 1-32) - fi + _nonce=$(echo "EDGEDNS$(_time)" | _digest sha1 hex | cut -c 1-32) _debug3 "_nonce" "$_nonce" } From 6bc00fc5e51c9cfa9319e4e44265b52d059230e2 Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 16 Oct 2020 18:47:02 +0800 Subject: [PATCH 035/383] Update DNS.yml --- .github/workflows/DNS.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index b06db229..25d92137 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -183,7 +183,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.0.5 + - uses: vmactions/freebsd-vm@v0.0.7 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkg install -y socat curl From 348bae53fe04ce0723adba6921ea74292cd9af7a Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 16 Oct 2020 18:47:27 +0800 Subject: [PATCH 036/383] Update LetsEncrypt.yml --- .github/workflows/LetsEncrypt.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index d71f3ac1..39e91161 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -106,7 +106,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.0.5 + - uses: vmactions/freebsd-vm@v0.0.7 with: envs: 'NGROK_TOKEN TEST_LOCAL' prepare: pkg install -y socat curl From 6ad5ea169679e22de4f0314b312e886b03ac6bc7 Mon Sep 17 00:00:00 2001 From: Ed Lynes Date: Fri, 16 Oct 2020 10:16:25 -0400 Subject: [PATCH 037/383] use _digest instead of openssl --- dnsapi/dns_edgedns.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_edgedns.sh b/dnsapi/dns_edgedns.sh index 89e77936..7ab448d2 100755 --- a/dnsapi/dns_edgedns.sh +++ b/dnsapi/dns_edgedns.sh @@ -440,7 +440,7 @@ _edgedns_base64_sha256() { _debug2 "Creating sha256 digest" trg=$1 _secure_debug2 "digest data" "$trg" - digest="$(echo "$trg" | tr -d "\n\r" | ${ACME_OPENSSL_BIN:-openssl} dgst -sha256 -binary | _base64)" + digest="$(echo "$trg" | tr -d "\n\r" | _digest "sha256")" _sha256_out="$(echo "$digest" | tr -d "\n\r" | iconv -f utf-8)" _secure_debug2 "digest decode" "$_sha256_out" } From c61495df5239f7034531fc787bcd91d5deb42372 Mon Sep 17 00:00:00 2001 From: Ed Lynes Date: Fri, 16 Oct 2020 10:32:01 -0400 Subject: [PATCH 038/383] fix format --- dnsapi/dns_edgedns.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_edgedns.sh b/dnsapi/dns_edgedns.sh index 7ab448d2..05c8e886 100755 --- a/dnsapi/dns_edgedns.sh +++ b/dnsapi/dns_edgedns.sh @@ -440,7 +440,7 @@ _edgedns_base64_sha256() { _debug2 "Creating sha256 digest" trg=$1 _secure_debug2 "digest data" "$trg" - digest="$(echo "$trg" | tr -d "\n\r" | _digest "sha256")" + digest="$(echo "$trg" | tr -d "\n\r" | _digest "sha256")" _sha256_out="$(echo "$digest" | tr -d "\n\r" | iconv -f utf-8)" _secure_debug2 "digest decode" "$_sha256_out" } From 5dbfc2786d9a5eb6018dadbd4d834b58fef21087 Mon Sep 17 00:00:00 2001 From: Adrian Fedoreanu Date: Mon, 19 Oct 2020 20:45:52 +0200 Subject: [PATCH 039/383] fix dnsapi/dns_1984hosting --- dnsapi/dns_1984hosting.sh | 84 +++++++++++++++------------------------ 1 file changed, 33 insertions(+), 51 deletions(-) diff --git a/dnsapi/dns_1984hosting.sh b/dnsapi/dns_1984hosting.sh index bcb675ab..d720c1c5 100755 --- a/dnsapi/dns_1984hosting.sh +++ b/dnsapi/dns_1984hosting.sh @@ -40,8 +40,35 @@ dns_1984hosting_add() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - _1984hosting_add_txt_record "$_domain" "$_sub_domain" "$txtvalue" - return $? + _debug "Add TXT record $fulldomain with value '$txtvalue'" + value="$(printf '%s' "$txtvalue" | _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=$_sub_domain" + 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 $_sub_domain bad RC from _post" + return 1 + elif _contains "$response" ""; then + _err "1984Hosting failed to add TXT record for $_sub_domain. Check $HTTP_HEADER file" + return 1 + elif _contains "$response" '"auth": false'; then + _err "1984Hosting failed to add TXT record for $_sub_domain. Invalid or expired cookie" + return 1 + fi + + _info "Added acme challenge TXT record for $fulldomain at 1984Hosting" + return 0 } #Usage: fulldomain txtvalue @@ -67,57 +94,10 @@ dns_1984hosting_rm() { _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 _contains "$response" '"auth": 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" + _htmlget "$url" "$_domain" _debug2 _response "$_response" zone_id="$(echo "$_response" | _egrep_o 'zone\/[0-9]+')" _debug2 zone_id "$zone_id" @@ -126,7 +106,7 @@ _1984hosting_delete_txt_record() { return 1 fi - _htmlget "$url/$zone_id" "$subdomain" + _htmlget "$url/$zone_id" "$_sub_domain" _debug2 _response "$_response" entry_id="$(echo "$_response" | _egrep_o 'entry_[0-9]+' | sed 's/entry_//')" _debug2 entry_id "$entry_id" @@ -148,6 +128,8 @@ _1984hosting_delete_txt_record() { return 0 } +#################### Private functions below ################################## + # usage: _1984hosting_login username password # returns 0 success _1984hosting_login() { From 23eccb2f20f4c2f3d5350d268fb94226b34712d7 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 21 Oct 2020 15:00:33 +0800 Subject: [PATCH 040/383] Update LetsEncrypt.yml --- .github/workflows/LetsEncrypt.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 39e91161..5f0bba72 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -58,7 +58,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Install tools - run: brew update && brew install socat; + run: brew install socat - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - name: Run acmetest From 5fd0e5add2b29c6e05b482c3c49bf82b9a905e22 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 21 Oct 2020 15:07:25 +0800 Subject: [PATCH 041/383] Update DNS.yml --- .github/workflows/DNS.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 25d92137..b7153506 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -94,7 +94,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Install tools - run: brew update && brew install socat; + run: brew install socat - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - name: Run acmetest From d5674c85d7735f2f3cdf6e44c2f9f1059d844d20 Mon Sep 17 00:00:00 2001 From: Ed Lynes Date: Fri, 21 Aug 2020 17:15:18 -0400 Subject: [PATCH 042/383] initial commit --- dnsapi/dns_edgedns.sh | 379 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 379 insertions(+) create mode 100755 dnsapi/dns_edgedns.sh diff --git a/dnsapi/dns_edgedns.sh b/dnsapi/dns_edgedns.sh new file mode 100755 index 00000000..75ef4f9b --- /dev/null +++ b/dnsapi/dns_edgedns.sh @@ -0,0 +1,379 @@ +#!/usr/bin/env sh + +# Akamai Edge DNS v2 API +# User must provide Open Edgegrid API credentials to the EdgeDNS installation. The remote user in EdgeDNS must have CRUD access to +# Edge DNS Zones and Recordsets, e.g. DNS—Zone Record Management authorization + +# Report bugs to https://control.akamai.com/apps/support-ui/#/contact-support + +# Values to export: +# --EITHER-- +# *** NOT IMPLEMENTED YET *** +# specify Edgegrid credentials file and section +# AKAMAI_EDGERC= +# AKAMAI_EDGERC_SECTION="default" +## --OR-- +# specify indiviual credentials +# export AKAMAI_HOST = +# export AKAMAI_ACCESS_TOKEN = +# export AKAMAI_CLIENT_TOKEN = +# export AKAMAI_CLIENT_SECRET = + +ACME_EDGEDNS_VERSION="0.1.0" + +######## Public functions ##################### + +# Usage: dns_edgedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +# Used to add txt record +# +dns_edgedns_add() { + fulldomain=$1 + txtvalue=$2 + + _debug "ENTERING DNS_EDGEDNS_ADD" + + _debug2 "fulldomain" "$fulldomain" + _debug2 "txtvalue" "$txtvalue" + + if ! _EDGEDNS_credentials; then + _err "$@" + return 1 + fi + + if ! _EDGEDNS_getZoneInfo "$fulldomain"; then + _err "Invalid domain" + return 1 + fi + _debug2 "Add: zone" "${zone}" + acmeRecordURI=$(printf "%s/%s/names/%s/type/TXT" "${edge_endpoint}" "${zone}" "${fulldomain}") + _debug3 "Add URL" "$acmeRecordURI" + # Get existing TXT record + _edge_result=$(_edgedns_rest GET "$acmeRecordURI") + _api_status="$?" + if [ "$_api_status" -ne 0 ] && [ "$_edge_result" != "404" ]; then + _err "$(printf "Failure accessing Akamai Edge DNS API Server. Error: %s" "$_edge_result")" + return 1 + fi + rdata="\"$txtvalue\"" + record_op="POST" + if [ "$_api_status" -eq 0 ]; then + # record already exists. Get existing record data and update + record_op="PUT" + rdlist=$(echo -n "$response" | _egrep_o "\"rdata\"\\s*:\\s*\\[\\s*\"[^\"]*\"\\s*]" | cut -d : -f 2 | tr -d "[]\"") + _debug2 "existing TXT found" + _debug2 "record data" "$rdlist" + # value already there? + if _contains "$rdlist" "$txtvalue" ; then + return 0 + fi + comma="," + rdata="$rdata$comma\"${txtvalue}\"" + fi + _debug2 "new/updated rdata: " "${rdata}" + # Add the txtvalue TXT Record + body="{\"name\":\"$fulldomain\",\"type\":\"TXT\",\"ttl\":600, \"rdata\":"[${rdata}]"}" + _debug3 "Add body '${body}'" + _edge_result=$(_edgedns_rest "$record_op" "$acmeRecordURI" "$body") + _api_status="$?" + if [ "$_api_status" -eq 0 ]; then + _log "$(printf "Text value %s added to recordset %s" "${txtvalue}" "${fulldomain}")" + return 0 + else + _err "$(printf "error adding TXT record for validation. Error: %s" "$_edge_result")" + return 1 + fi +} + +# Usage: dns_edgedns_rm _acme-challenge.www.domain.com +# Used to delete txt record +# +dns_edgedns_rm() { + fulldomain=$1 +} + +#################### Private functions below ################################## + +_EDGEDNS_credentials() { + _debug "GettingEdge DNS credentials" + _log $(printf "ACME DNSAPI Edge DNS version %s" ${ACME_EDGEDNS_VERSION}) + args_missing=0 + if [ -z "${AKAMAI_ACCESS_TOKEN}" ]; then + AKAMAI_ACCESS_TOKEN="" + AKAMAI_CLIENT_TOKEN="" + AKAMAI_HOST="" + AKAMAI_CLIENT_SECRET="" + _err "AKAMAI_ACCESS_TOKEN is missing" + args_missing=1 + fi + if [ -z "$AKAMAI_CLIENT_TOKEN" ]; then + AKAMAI_ACCESS_TOKEN="" + AKAMAI_CLIENT_TOKEN="" + AKAMAI_HOST="" + AKAMAI_CLIENT_SECRET="" + _err "AKAMAI_CLIENT_TOKEN is missing" + args_missing=1 + fi + if [ -z "${AKAMAI_HOST}" ]; then + AKAMAI_ACCESS_TOKEN="" + AKAMAI_CLIENT_TOKEN="" + AKAMAI_HOST="" + AKAMAI_CLIENT_SECRET="" + _err "AKAMAI_HOST is missing" + args_missing=1 + fi + if [ -z "${AKAMAI_CLIENT_SECRET}" ]; then + AKAMAI_ACCESS_TOKEN="" + AKAMAI_CLIENT_TOKEN="" + AKAMAI_HOST="" + AKAMAI_CLIENT_SECRET="" + _err "AKAMAI_CLIENT_SECRET is missing" + args_missing=1 + fi + + if [ "${args_missing}" = 1 ]; then + _err "You have not properly specified the EdgeDNS Open Edgegrid API credentials. Please try again." + return 1 + else + _saveaccountconf_mutable AKAMAI_ACCESS_TOKEN "${AKAMAI_ACCESS_TOKEN}" + _saveaccountconf_mutable AKAMAI_CLIENT_TOKEN "${AKAMAI_CLIENT_TOKEN}" + _saveaccountconf_mutable AKAMAI_HOST "${AKAMAI_HOST}" + _saveaccountconf_mutable AKAMAI_CLIENT_SECRET "${AKAMAI_CLIENT_SECRET}" + # Set whether curl should use secure or insecure mode + fi + export HTTPS_INSECURE=0 # All Edgegrid API calls are secure + edge_endpoint=$(printf "https://%s/config-dns/v2/zones" "${AKAMAI_HOST}") + _debug3 "Edge API Endpoint:" "${edge_endpoint}" + +} + +_EDGEDNS_getZoneInfo() { + _debug "Getting Zoneinfo" + zoneEnd=false + curZone=$1 + while [ -n "${zoneEnd}" ]; do + # we can strip the first part of the fulldomain, since its just the _acme-challenge string + curZone="${curZone#*.}" + # suffix . needed for zone -> domain.tld. + # create zone get url + get_zone_url=$(printf "%s/%s" "${edge_endpoint}" "${curZone}") + _debug3 "Zone Get: " "${get_zone_url}" + curResult=$(_edgedns_rest GET "$get_zone_url") + retVal=$? + if [ $retVal -ne 0 ]; then + if ["$curResult" != "404" ]; then + _err "$(printf "Managed zone validation failed. Error response: %s" "$retVal")" + return 1 + fi + fi + + if _contains "${curResult}" "\"zone\":" ; then + _debug2 "Zone data" "${curResult}" + zone=$(echo -n "${curResult}" | _egrep_o "\"zone\"\\s*:\\s*\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d "\"") + _debug2 "Zone" "${zone}" + zoneFound="" + zoneEnd="" + return 0 + fi + + if [ "${curZone#*.}" != "$curZone" ]; then + _debug2 $(printf "%s still contains a '.' - so we can check next higher level" "$curZone") + else + zoneEnd=true + _err "Couldn't retrieve zone data." + return 1 + fi + done + _err "Failed to retrieve zone data." + return 2 +} + +_edgedns_headers="" + +_edgedns_rest() { + _debug "Handling API Request" + m=$1 + # Assume endpoint is complete path, including query args if applicable + ep=$2 + body_data=$3 + _edgedns_content_type="" + _request_url_path="$ep" + _request_body="$body_data" + _request_method="$m" + _edgedns_headers="" + tab="" + _edgedns_headers="${_edgedns_headers}${tab}Host: ${AKAMAI_HOST}" + tab="\t" + # Set in acme.sh _post/_get + #_edgedns_headers="${_edgedns_headers}${tab}User-Agent:ACME DNSAPI Edge DNS version ${ACME_EDGEDNS_VERSION}" + _edgedns_headers="${_edgedns_headers}${tab}Accept: application/json" + if [ "$m" != "GET" ] && [ "$m" != "DELETE" ] ; then + _edgedns_content_type="application/json;charset=UTF-8" + _utf8_body_data="$(echo -n "$ _request_body" | iconv -t utf-8)" + _utf8_body_len="$(echo -n "$_utf8_body_data" | awk '{print length}')" + _edgedns_headers="${_edgedns_headers}${tab}Content-Length: ${_utf8_body_len}" + fi + _made_auth_header=$(_edgedns_make_auth_header) + _edgedns_headers="${_edgedns_headers}${tab}Authorization: ${_made_auth_header}" + _secure_debug2 "Made Auth Header" "${_made_auth_header}" + hdr_indx=1 + work_header="${_edgedns_headers}${tab}" + _debug3 "work_header" "${work_header}" + while [ "${work_header}" ]; do + entry="${work_header%%\\t*}"; work_header="${work_header#*\\t}" + export "$(printf "_H%s=%s" "${hdr_indx}" "${entry}")" + _debug2 "Request Header " "${entry}" + hdr_indx=$(( hdr_indx + 1 )) + done + + # clear headers from previous request to avoid getting wrong http code on timeouts + :>"$HTTP_HEADER" + _debug "$ep" + if [ "$m" != "GET" ]; then + _debug "Method data" "$data" + # body url [needbase64] [POST|PUT|DELETE] [ContentType] + response="$(_post "$_utf8_body_data" "$ep" false "$m")" + else + response="$(_get "$ep")" + fi + + _ret="$?" + _debug "response" "$response" + _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" + _debug2 "http response code" "$_code" + + if [ "$_code" = "200" ] || [ "$_code" = "201" ]; then + # All good + response="$(echo "$response" | _normalizeJson)" + echo -n "${response}" + return 0 + fi + + if [ "$_code" = "204" ]; then + # Success, no body + echo -n "" + return 0 + fi + + if [ "$_code" = "400" ]; then + _err "Bad request presented" + _log "$(printf "Headers: %s" "$_edgedns_headers")" + _log "$(printf "Method: %s" "$_request_method")" + _log "$(printf "URL: %s" "$ep")" + _log "$(printf "Data: %s" "$data")" + fi + + if [ "$_code" = "403" ]; then + _err "access denied make sure your Edgegrid cedentials are correct." + fi + + echo "$_code" + return 1 +} + +_edgedns_eg_timestamp() { + _eg_timestamp=$(date -u "+%Y%m%dT%H:%M:%S+0000") +} + +_edgedns_new_nonce() { + _nonce=$(uuidgen -r) +} + +_edgedns_make_auth_header() { + _debug "Constructing Auth Header" + _edgedns_eg_timestamp + _edgedns_new_nonce + # "Unsigned authorization header: 'EG1-HMAC-SHA256 client_token=block;access_token=block;timestamp=20200806T14:16:33+0000;nonce=72cde72c-82d9-4721-9854-2ba057929d67;'" + _auth_header="$(printf "EG1-HMAC-SHA256 client_token=%s;access_token=%s;timestamp=%s;nonce=%s;" "${AKAMAI_CLIENT_TOKEN}" "${AKAMAI_ACCESS_TOKEN}" "${_eg_timestamp}" "${_nonce}")" + _secure_debug2 "Unsigned Auth Header: " "$_auth_header" + + _sig="$(_edgedns_sign_request)" + _signed_auth_header="$(printf "%ssignature=%s" "${_auth_header}" "${_sig}")" + _secure_debug2 "Signed Auth Header: " "${_signed_auth_header}" + echo -n "${_signed_auth_header}" +} + +_edgedns_sign_request() { + _debug2 "Signing http request" + _signed_data=$(_edgedns_make_data_to_sign "${_auth_header}") + _secure_debug2 "Returned signed data" "$_signed_data" + _key=$(_edgedns_make_signing_key "${_eg_timestamp}") + _signed_req=$(_edgedns_base64_hmac_sha256 "$_signed_data" "$_key") + _secure_debug2 "Signed Request" "${_signed_req}" + echo -n "${_signed_req}" +} + +_edgedns_make_signing_key() { + _debug2 "Creating sigining key" + ts=$1 + _signing_key=$(_edgedns_base64_hmac_sha256 "$ts" "${AKAMAI_CLIENT_SECRET}") + _secure_debug2 "Signing Key" "${_signing_key}" + echo -n "${_signing_key}" + +} + +_edgedns_make_data_to_sign() { + _debug2 "Processing data to sign" + hdr=$1 + _secure_debug2 "hdr" "$hdr" + content_hash=$(_edgedns_make_content_hash) + path="$(echo -n "${_request_url_path}" |sed 's/https\?:\/\///')" + path="${path#*$AKAMAI_HOST}" + _debug "hier path" "${path}" + # dont expose headers to sign so use MT string + data="$(printf "%s\thttps\t%s\t%s\t%s\t%s\t%s" "${_request_method}" "${AKAMAI_HOST}" "${path}" "" "${content_hash}" "$hdr")" + _secure_debug2 "Data to Sign" "${data}" + echo -n "${data}" +} + +_edgedns_make_content_hash() { + _debug2 "Generating content hash" + prep_body="" + _hash="" + _debug2 "Request method" "${_request_method}" + if [ "${_request_method}" != "POST" ] || [ -z "${_request_body}" ]; then + echo -n "${prep_body}" + return 0 + fi + prep_body="$(echo -n "${_request_body}")" + _debug2 "Req body" "${prep_body}" + _hash=$(_edgedns_base64_sha256 "${prep_body}") + _debug2 "Content hash" "${_hash}" + echo -n "${_hash}" +} + +_edgedns_base64_hmac_sha256() { + _debug2 "Generating hmac" + data=$1 + key=$2 + encoded_data="$(echo -n "${data}" | iconv -t utf-8)" + encoded_key="$(echo -n "${key}" | iconv -t utf-8)" + _secure_debug2 "encoded data" "${encoded_data}" + _secure_debug2 "encoded key" "${encoded_key}" + #key_hex="$(_durl_replace_base64 "$key" | _dbase64 | _hex_dump | tr -d ' ')" + #data_sig="$(printf "%s" "$encoded_data" | _hmac sha256 "${key_hex}" | _base64 | _url_replace)" + + data_sig="$(echo -n "$encoded_data" | ${ACME_OPENSSL_BIN:-openssl} dgst -sha256 -hmac $encoded_key -binary | _base64)" + _secure_debug2 "data_sig:" "${data_sig}" + out="$(echo -n "${data_sig}" | iconv -f utf-8)" + _secure_debug2 "hmac" "${out}" + echo -n "${out}" +} + +_edgedns_base64_sha256() { + _debug2 "Creating sha256 digest" + trg=$1 + utf8_str="$(echo -n "${trg}" | iconv -t utf-8)" + _secure_debug2 "digest data" "$trg" + _secure_debug2 "encoded digest data" "${utf8_str}" + digest="$(echo -n "${trg}" | ${ACME_OPENSSL_BIN:-openssl} dgst -sha256 -binary | _base64)" + out="$(echo -n "${digest}" | iconv -f utf-8)" + _secure_debug2 "digest decode" "${out}" + echo -n "${out}" +} + +#_edgedns_parse_edgerc() { +# filepath=$1 +# section=$2 +#} + + From 8e09e1b248ec77ae4954e6928b22dc083c9174be Mon Sep 17 00:00:00 2001 From: Ed Lynes Date: Wed, 26 Aug 2020 16:11:11 -0400 Subject: [PATCH 043/383] debugging and cleanup --- dnsapi/dns_edgedns.sh | 283 ++++++++++++++++++++++++++---------------- 1 file changed, 176 insertions(+), 107 deletions(-) diff --git a/dnsapi/dns_edgedns.sh b/dnsapi/dns_edgedns.sh index 75ef4f9b..7be49761 100755 --- a/dnsapi/dns_edgedns.sh +++ b/dnsapi/dns_edgedns.sh @@ -29,9 +29,7 @@ ACME_EDGEDNS_VERSION="0.1.0" dns_edgedns_add() { fulldomain=$1 txtvalue=$2 - _debug "ENTERING DNS_EDGEDNS_ADD" - _debug2 "fulldomain" "$fulldomain" _debug2 "txtvalue" "$txtvalue" @@ -39,44 +37,53 @@ dns_edgedns_add() { _err "$@" return 1 fi - if ! _EDGEDNS_getZoneInfo "$fulldomain"; then _err "Invalid domain" return 1 fi - _debug2 "Add: zone" "${zone}" - acmeRecordURI=$(printf "%s/%s/names/%s/type/TXT" "${edge_endpoint}" "${zone}" "${fulldomain}") + _debug2 "Add: zone" "$zone" + acmeRecordURI=$(printf "%s/%s/names/%s/types/TXT" "$edge_endpoint" "$zone" "$fulldomain") _debug3 "Add URL" "$acmeRecordURI" # Get existing TXT record _edge_result=$(_edgedns_rest GET "$acmeRecordURI") _api_status="$?" - if [ "$_api_status" -ne 0 ] && [ "$_edge_result" != "404" ]; then - _err "$(printf "Failure accessing Akamai Edge DNS API Server. Error: %s" "$_edge_result")" - return 1 + _debug3 "_edge_result" "$_edge_result" + if [ "$_api_status" -ne 0 ]; then + if [ "$curResult" = "FATAL" ]; then + _err "$(printf "Fatal error: acme API function call : %s" "$retVal")" + fi + if [ "$_edge_result" != "404" ]; then + _err "$(printf "Failure accessing Akamai Edge DNS API Server. Error: %s" "$_edge_result")" + return 1 + fi fi - rdata="\"$txtvalue\"" + rdata="\"${txtvalue}\"" record_op="POST" if [ "$_api_status" -eq 0 ]; then # record already exists. Get existing record data and update record_op="PUT" - rdlist=$(echo -n "$response" | _egrep_o "\"rdata\"\\s*:\\s*\\[\\s*\"[^\"]*\"\\s*]" | cut -d : -f 2 | tr -d "[]\"") - _debug2 "existing TXT found" - _debug2 "record data" "$rdlist" + rdlist="${_edge_result#*\"rdata\":[}" + rdlist="${rdlist%%]*}" + rdlist=$(echo "$rdlist" | tr -d '"' | tr -d "\\") + _debug3 "existing TXT found" + _debug3 "record data" "$rdlist" # value already there? if _contains "$rdlist" "$txtvalue" ; then return 0 fi - comma="," - rdata="$rdata$comma\"${txtvalue}\"" + _txt_val="" + while [ "$_txt_val" != "$rdlist" ] && [ "${rdlist}" ]; do + _txt_val="${rdlist%%,*}"; rdlist="${rdlist#*,}" + rdata="${rdata},\"${_txt_val}\"" + done fi - _debug2 "new/updated rdata: " "${rdata}" # Add the txtvalue TXT Record body="{\"name\":\"$fulldomain\",\"type\":\"TXT\",\"ttl\":600, \"rdata\":"[${rdata}]"}" _debug3 "Add body '${body}'" _edge_result=$(_edgedns_rest "$record_op" "$acmeRecordURI" "$body") _api_status="$?" if [ "$_api_status" -eq 0 ]; then - _log "$(printf "Text value %s added to recordset %s" "${txtvalue}" "${fulldomain}")" + _log "$(printf "Text value %s added to recordset %s" "$txtvalue" "$fulldomain")" return 0 else _err "$(printf "error adding TXT record for validation. Error: %s" "$_edge_result")" @@ -84,20 +91,89 @@ dns_edgedns_add() { fi } -# Usage: dns_edgedns_rm _acme-challenge.www.domain.com +# Usage: dns_edgedns_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" # Used to delete txt record # dns_edgedns_rm() { fulldomain=$1 + txtvalue=$2 + _debug "ENTERING DNS_EDGEDNS_RM" + _debug2 "fulldomain" "$fulldomain" + _debug2 "txtvalue" "$txtvalue" + + if ! _EDGEDNS_credentials; then + _err "$@" + return 1 + fi + if ! _EDGEDNS_getZoneInfo "$fulldomain"; then + _err "Invalid domain" + return 1 + fi + _debug2 "RM: zone" "${zone}" + acmeRecordURI=$(printf "%s/%s/names/%s/types/TXT" "${edge_endpoint}" "$zone" "$fulldomain") + _debug3 "RM URL" "$acmeRecordURI" + # Get existing TXT record + _edge_result=$(_edgedns_rest GET "$acmeRecordURI") + _api_status="$?" + if [ "$_api_status" -ne 0 ]; then + if [ "$curResult" = "FATAL" ]; then + _err "$(printf "Fatal error: acme API function call : %s" "$retVal")" + fi + if [ "$_edge_result" != "404" ]; then + _err "$(printf "Failure accessing Akamai Edge DNS API Server. Error: %s" "$_edge_result")" + return 1 + fi + fi + _debug3 "_edge_result" "$_edge_result" + record_op="DELETE" + body="" + if [ "$_api_status" -eq 0 ]; then + # record already exists. Get existing record data and update + rdlist="${_edge_result#*\"rdata\":[}" + rdlist="${rdlist%%]*}" + rdlist=$(echo "$rdlist" | tr -d '"' | tr -d "\\") + _debug3 "rdlist" "$rdlist" + if [ -n "$rdlist" ]; then + record_op="PUT" + comma="" + rdata="" + _txt_val="" + while [ "$_txt_val" != "$rdlist" ] && [ "$rdlist" ]; do + _txt_val="${rdlist%%,*}"; rdlist="${rdlist#*,}" + _debug3 "_txt_val" "$_txt_val" + _debug3 "txtvalue" "$txtvalue" + if ! _contains "$_txt_val" "$txtvalue" ; then + rdata="${rdata}${comma}\"${_txt_val}\"" + comma="," + fi + done + if [ -z "$rdata" ]; then + record_op="DELETE" + else + # Recreate the txtvalue TXT Record + body="{\"name\":\"$fulldomain\",\"type\":\"TXT\",\"ttl\":600, \"rdata\":"[${rdata}]"}" + _debug3 "body" "$body" + fi + fi + fi + _edge_result=$(_edgedns_rest "$record_op" "$acmeRecordURI" "$body") + _api_status="$?" + if [ "$_api_status" -eq 0 ]; then + _log "$(printf "Text value %s removed from recordset %s" "$txtvalue" "$fulldomain")" + return 0 + else + _err "$(printf "error removing TXT record for validation. Error: %s" "$_edge_result")" + return 1 + fi } #################### Private functions below ################################## _EDGEDNS_credentials() { _debug "GettingEdge DNS credentials" - _log $(printf "ACME DNSAPI Edge DNS version %s" ${ACME_EDGEDNS_VERSION}) + _log "$(printf "ACME DNSAPI Edge DNS version %s" ${ACME_EDGEDNS_VERSION})" args_missing=0 - if [ -z "${AKAMAI_ACCESS_TOKEN}" ]; then + if [ -z "$AKAMAI_ACCESS_TOKEN" ]; then AKAMAI_ACCESS_TOKEN="" AKAMAI_CLIENT_TOKEN="" AKAMAI_HOST="" @@ -113,7 +189,7 @@ _EDGEDNS_credentials() { _err "AKAMAI_CLIENT_TOKEN is missing" args_missing=1 fi - if [ -z "${AKAMAI_HOST}" ]; then + if [ -z "$AKAMAI_HOST" ]; then AKAMAI_ACCESS_TOKEN="" AKAMAI_CLIENT_TOKEN="" AKAMAI_HOST="" @@ -121,7 +197,7 @@ _EDGEDNS_credentials() { _err "AKAMAI_HOST is missing" args_missing=1 fi - if [ -z "${AKAMAI_CLIENT_SECRET}" ]; then + if [ -z "$AKAMAI_CLIENT_SECRET" ]; then AKAMAI_ACCESS_TOKEN="" AKAMAI_CLIENT_TOKEN="" AKAMAI_HOST="" @@ -130,19 +206,19 @@ _EDGEDNS_credentials() { args_missing=1 fi - if [ "${args_missing}" = 1 ]; then + if [ "$args_missing" = 1 ]; then _err "You have not properly specified the EdgeDNS Open Edgegrid API credentials. Please try again." return 1 else - _saveaccountconf_mutable AKAMAI_ACCESS_TOKEN "${AKAMAI_ACCESS_TOKEN}" - _saveaccountconf_mutable AKAMAI_CLIENT_TOKEN "${AKAMAI_CLIENT_TOKEN}" - _saveaccountconf_mutable AKAMAI_HOST "${AKAMAI_HOST}" - _saveaccountconf_mutable AKAMAI_CLIENT_SECRET "${AKAMAI_CLIENT_SECRET}" + _saveaccountconf_mutable AKAMAI_ACCESS_TOKEN "$AKAMAI_ACCESS_TOKEN" + _saveaccountconf_mutable AKAMAI_CLIENT_TOKEN "$AKAMAI_CLIENT_TOKEN" + _saveaccountconf_mutable AKAMAI_HOST "$AKAMAI_HOST" + _saveaccountconf_mutable AKAMAI_CLIENT_SECRET "$AKAMAI_CLIENT_SECRET" # Set whether curl should use secure or insecure mode fi export HTTPS_INSECURE=0 # All Edgegrid API calls are secure - edge_endpoint=$(printf "https://%s/config-dns/v2/zones" "${AKAMAI_HOST}") - _debug3 "Edge API Endpoint:" "${edge_endpoint}" + edge_endpoint=$(printf "https://%s/config-dns/v2/zones" "$AKAMAI_HOST") + _debug3 "Edge API Endpoint:" "$edge_endpoint" } @@ -150,33 +226,34 @@ _EDGEDNS_getZoneInfo() { _debug "Getting Zoneinfo" zoneEnd=false curZone=$1 - while [ -n "${zoneEnd}" ]; do + while [ -n "$zoneEnd" ]; do # we can strip the first part of the fulldomain, since its just the _acme-challenge string curZone="${curZone#*.}" # suffix . needed for zone -> domain.tld. # create zone get url - get_zone_url=$(printf "%s/%s" "${edge_endpoint}" "${curZone}") + get_zone_url=$(printf "%s/%s" "$edge_endpoint" "$curZone") _debug3 "Zone Get: " "${get_zone_url}" curResult=$(_edgedns_rest GET "$get_zone_url") retVal=$? - if [ $retVal -ne 0 ]; then - if ["$curResult" != "404" ]; then - _err "$(printf "Managed zone validation failed. Error response: %s" "$retVal")" + if [ "$retVal" -ne 0 ]; then + if [ "$curResult" = "FATAL" ]; then + _err "$(printf "Fatal error: acme API function call : %s" "$retVal")" + fi + if [ "$curResult" != "404" ]; then + err "$(printf "Managed zone validation failed. Error response: %s" "$retVal")" return 1 fi fi - - if _contains "${curResult}" "\"zone\":" ; then + if _contains "$curResult" "\"zone\":" ; then _debug2 "Zone data" "${curResult}" - zone=$(echo -n "${curResult}" | _egrep_o "\"zone\"\\s*:\\s*\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d "\"") - _debug2 "Zone" "${zone}" - zoneFound="" + zone=$(echo "${curResult}" | _egrep_o "\"zone\"\\s*:\\s*\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d "\"") + _debug3 "Zone" "${zone}" zoneEnd="" return 0 fi if [ "${curZone#*.}" != "$curZone" ]; then - _debug2 $(printf "%s still contains a '.' - so we can check next higher level" "$curZone") + _debug3 "$(printf "%s still contains a '.' - so we can check next higher level" "$curZone")" else zoneEnd=true _err "Couldn't retrieve zone data." @@ -205,52 +282,55 @@ _edgedns_rest() { tab="\t" # Set in acme.sh _post/_get #_edgedns_headers="${_edgedns_headers}${tab}User-Agent:ACME DNSAPI Edge DNS version ${ACME_EDGEDNS_VERSION}" - _edgedns_headers="${_edgedns_headers}${tab}Accept: application/json" + _edgedns_headers="${_edgedns_headers}${tab}Accept: application/json,*/*" if [ "$m" != "GET" ] && [ "$m" != "DELETE" ] ; then - _edgedns_content_type="application/json;charset=UTF-8" - _utf8_body_data="$(echo -n "$ _request_body" | iconv -t utf-8)" - _utf8_body_len="$(echo -n "$_utf8_body_data" | awk '{print length}')" - _edgedns_headers="${_edgedns_headers}${tab}Content-Length: ${_utf8_body_len}" + _edgedns_content_type="application/json" + _debug3 "_request_body" "$_request_body" + _body_len=$(echo "$_request_body" | tr -d "\n\r" | awk '{print length}') + _edgedns_headers="${_edgedns_headers}${tab}Content-Length: ${_body_len}" fi - _made_auth_header=$(_edgedns_make_auth_header) - _edgedns_headers="${_edgedns_headers}${tab}Authorization: ${_made_auth_header}" - _secure_debug2 "Made Auth Header" "${_made_auth_header}" + _edgedns_make_auth_header + _edgedns_headers="${_edgedns_headers}${tab}Authorization: ${_signed_auth_header}" + _secure_debug2 "Made Auth Header" "$_signed_auth_header" hdr_indx=1 work_header="${_edgedns_headers}${tab}" - _debug3 "work_header" "${work_header}" - while [ "${work_header}" ]; do + _debug3 "work_header" "$work_header" + while [ "$work_header" ]; do entry="${work_header%%\\t*}"; work_header="${work_header#*\\t}" - export "$(printf "_H%s=%s" "${hdr_indx}" "${entry}")" - _debug2 "Request Header " "${entry}" + export "$(printf "_H%s=%s" "$hdr_indx" "$entry")" + _debug2 "Request Header " "$entry" hdr_indx=$(( hdr_indx + 1 )) done # clear headers from previous request to avoid getting wrong http code on timeouts - :>"$HTTP_HEADER" - _debug "$ep" + : >"$HTTP_HEADER" + _debug2 "$ep" if [ "$m" != "GET" ]; then - _debug "Method data" "$data" + _debug3 "Method data" "$data" # body url [needbase64] [POST|PUT|DELETE] [ContentType] - response="$(_post "$_utf8_body_data" "$ep" false "$m")" + response=$(_post "$_request_body" "$ep" false "$m" "$_edgedns_content_type") else - response="$(_get "$ep")" + response=$(_get "$ep") fi - _ret="$?" - _debug "response" "$response" + if [ "$_ret" -ne 0 ]; then + _err "$(printf "acme.sh API function call failed. Error: %s" "$_ret")" + echo "FATAL" + return "$_ret" + fi + _debug2 "response" "${response}" _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" _debug2 "http response code" "$_code" - if [ "$_code" = "200" ] || [ "$_code" = "201" ]; then # All good - response="$(echo "$response" | _normalizeJson)" - echo -n "${response}" + response="$(echo "${response}" | _normalizeJson)" + echo "$response" return 0 fi if [ "$_code" = "204" ]; then # Success, no body - echo -n "" + echo "$_code" return 0 fi @@ -283,31 +363,30 @@ _edgedns_make_auth_header() { _edgedns_eg_timestamp _edgedns_new_nonce # "Unsigned authorization header: 'EG1-HMAC-SHA256 client_token=block;access_token=block;timestamp=20200806T14:16:33+0000;nonce=72cde72c-82d9-4721-9854-2ba057929d67;'" - _auth_header="$(printf "EG1-HMAC-SHA256 client_token=%s;access_token=%s;timestamp=%s;nonce=%s;" "${AKAMAI_CLIENT_TOKEN}" "${AKAMAI_ACCESS_TOKEN}" "${_eg_timestamp}" "${_nonce}")" + _auth_header="$(printf "EG1-HMAC-SHA256 client_token=%s;access_token=%s;timestamp=%s;nonce=%s;" "$AKAMAI_CLIENT_TOKEN" "$AKAMAI_ACCESS_TOKEN" "$_eg_timestamp" "$_nonce")" _secure_debug2 "Unsigned Auth Header: " "$_auth_header" - _sig="$(_edgedns_sign_request)" - _signed_auth_header="$(printf "%ssignature=%s" "${_auth_header}" "${_sig}")" + _edgedns_sign_request + _signed_auth_header="$(printf "%ssignature=%s" "$_auth_header" "$_signed_req")" _secure_debug2 "Signed Auth Header: " "${_signed_auth_header}" - echo -n "${_signed_auth_header}" } _edgedns_sign_request() { _debug2 "Signing http request" - _signed_data=$(_edgedns_make_data_to_sign "${_auth_header}") - _secure_debug2 "Returned signed data" "$_signed_data" - _key=$(_edgedns_make_signing_key "${_eg_timestamp}") - _signed_req=$(_edgedns_base64_hmac_sha256 "$_signed_data" "$_key") - _secure_debug2 "Signed Request" "${_signed_req}" - echo -n "${_signed_req}" + _edgedns_make_data_to_sign "$_auth_header" + _secure_debug2 "Returned signed data" "$_mdata" + _edgedns_make_signing_key "$_eg_timestamp" + _edgedns_base64_hmac_sha256 "$_mdata" "$_signing_key" + _signed_req="$_hmac_out" + _secure_debug2 "Signed Request" "$_signed_req" } _edgedns_make_signing_key() { _debug2 "Creating sigining key" ts=$1 - _signing_key=$(_edgedns_base64_hmac_sha256 "$ts" "${AKAMAI_CLIENT_SECRET}") - _secure_debug2 "Signing Key" "${_signing_key}" - echo -n "${_signing_key}" + _edgedns_base64_hmac_sha256 "$ts" "$AKAMAI_CLIENT_SECRET" + _signing_key="$_hmac_out" + _secure_debug2 "Signing Key" "$_signing_key" } @@ -315,60 +394,50 @@ _edgedns_make_data_to_sign() { _debug2 "Processing data to sign" hdr=$1 _secure_debug2 "hdr" "$hdr" - content_hash=$(_edgedns_make_content_hash) - path="$(echo -n "${_request_url_path}" |sed 's/https\?:\/\///')" + _edgedns_make_content_hash + path="$(echo "$_request_url_path" | tr -d "\n\r" | sed 's/https\?:\/\///')" path="${path#*$AKAMAI_HOST}" - _debug "hier path" "${path}" + _debug "hier path" "$path" # dont expose headers to sign so use MT string - data="$(printf "%s\thttps\t%s\t%s\t%s\t%s\t%s" "${_request_method}" "${AKAMAI_HOST}" "${path}" "" "${content_hash}" "$hdr")" - _secure_debug2 "Data to Sign" "${data}" - echo -n "${data}" + _mdata="$(printf "%s\thttps\t%s\t%s\t%s\t%s\t%s" "$_request_method" "$AKAMAI_HOST" "$path" "" "$_hash" "$hdr")" + _secure_debug2 "Data to Sign" "$_mdata" } _edgedns_make_content_hash() { _debug2 "Generating content hash" - prep_body="" _hash="" _debug2 "Request method" "${_request_method}" - if [ "${_request_method}" != "POST" ] || [ -z "${_request_body}" ]; then - echo -n "${prep_body}" + if [ "$_request_method" != "POST" ] || [ -z "$_request_body" ]; then return 0 fi - prep_body="$(echo -n "${_request_body}")" - _debug2 "Req body" "${prep_body}" - _hash=$(_edgedns_base64_sha256 "${prep_body}") - _debug2 "Content hash" "${_hash}" - echo -n "${_hash}" + _debug2 "Req body" "$_request_body" + _edgedns_base64_sha256 "$_request_body" + _hash="$_sha256_out" + _debug2 "Content hash" "$_hash" } _edgedns_base64_hmac_sha256() { _debug2 "Generating hmac" data=$1 key=$2 - encoded_data="$(echo -n "${data}" | iconv -t utf-8)" - encoded_key="$(echo -n "${key}" | iconv -t utf-8)" - _secure_debug2 "encoded data" "${encoded_data}" - _secure_debug2 "encoded key" "${encoded_key}" - #key_hex="$(_durl_replace_base64 "$key" | _dbase64 | _hex_dump | tr -d ' ')" - #data_sig="$(printf "%s" "$encoded_data" | _hmac sha256 "${key_hex}" | _base64 | _url_replace)" - - data_sig="$(echo -n "$encoded_data" | ${ACME_OPENSSL_BIN:-openssl} dgst -sha256 -hmac $encoded_key -binary | _base64)" - _secure_debug2 "data_sig:" "${data_sig}" - out="$(echo -n "${data_sig}" | iconv -f utf-8)" - _secure_debug2 "hmac" "${out}" - echo -n "${out}" + encoded_data="$(echo "$data" | iconv -t utf-8)" + encoded_key="$(echo "$key" | iconv -t utf-8)" + _secure_debug2 "encoded data" "$encoded_data" + _secure_debug2 "encoded key" "$encoded_key" + + data_sig="$(echo "$encoded_data" | tr -d "\n\r" | ${ACME_OPENSSL_BIN:-openssl} dgst -sha256 -hmac "$encoded_key" -binary | _base64)" + _secure_debug2 "data_sig:" "$data_sig" + _hmac_out="$(echo "$data_sig" | tr -d "\n\r" | iconv -f utf-8)" + _secure_debug2 "hmac" "$_hmac_out" } _edgedns_base64_sha256() { _debug2 "Creating sha256 digest" trg=$1 - utf8_str="$(echo -n "${trg}" | iconv -t utf-8)" _secure_debug2 "digest data" "$trg" - _secure_debug2 "encoded digest data" "${utf8_str}" - digest="$(echo -n "${trg}" | ${ACME_OPENSSL_BIN:-openssl} dgst -sha256 -binary | _base64)" - out="$(echo -n "${digest}" | iconv -f utf-8)" - _secure_debug2 "digest decode" "${out}" - echo -n "${out}" + digest="$(echo "$trg" | tr -d "\n\r" | ${ACME_OPENSSL_BIN:-openssl} dgst -sha256 -binary | _base64)" + _sha256_out="$(echo "$digest" | tr -d "\n\r" | iconv -f utf-8)" + _secure_debug2 "digest decode" "$_sha256_out" } #_edgedns_parse_edgerc() { From 596a1764ef799eb08f8004f0ea68a15fc977376e Mon Sep 17 00:00:00 2001 From: Ed Lynes Date: Wed, 26 Aug 2020 18:07:46 -0400 Subject: [PATCH 044/383] vetted by shfmt --- dnsapi/dns_edgedns.sh | 49 ++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/dnsapi/dns_edgedns.sh b/dnsapi/dns_edgedns.sh index 7be49761..2072637a 100755 --- a/dnsapi/dns_edgedns.sh +++ b/dnsapi/dns_edgedns.sh @@ -7,15 +7,15 @@ # Report bugs to https://control.akamai.com/apps/support-ui/#/contact-support # Values to export: -# --EITHER-- +# --EITHER-- # *** NOT IMPLEMENTED YET *** # specify Edgegrid credentials file and section -# AKAMAI_EDGERC= +# AKAMAI_EDGERC= # AKAMAI_EDGERC_SECTION="default" ## --OR-- # specify indiviual credentials # export AKAMAI_HOST = -# export AKAMAI_ACCESS_TOKEN = +# export AKAMAI_ACCESS_TOKEN = # export AKAMAI_CLIENT_TOKEN = # export AKAMAI_CLIENT_SECRET = @@ -32,7 +32,7 @@ dns_edgedns_add() { _debug "ENTERING DNS_EDGEDNS_ADD" _debug2 "fulldomain" "$fulldomain" _debug2 "txtvalue" "$txtvalue" - + if ! _EDGEDNS_credentials; then _err "$@" return 1 @@ -42,7 +42,7 @@ dns_edgedns_add() { return 1 fi _debug2 "Add: zone" "$zone" - acmeRecordURI=$(printf "%s/%s/names/%s/types/TXT" "$edge_endpoint" "$zone" "$fulldomain") + acmeRecordURI=$(printf "%s/%s/names/%s/types/TXT" "$edge_endpoint" "$zone" "$fulldomain") _debug3 "Add URL" "$acmeRecordURI" # Get existing TXT record _edge_result=$(_edgedns_rest GET "$acmeRecordURI") @@ -68,13 +68,14 @@ dns_edgedns_add() { _debug3 "existing TXT found" _debug3 "record data" "$rdlist" # value already there? - if _contains "$rdlist" "$txtvalue" ; then + if _contains "$rdlist" "$txtvalue"; then return 0 fi _txt_val="" while [ "$_txt_val" != "$rdlist" ] && [ "${rdlist}" ]; do - _txt_val="${rdlist%%,*}"; rdlist="${rdlist#*,}" - rdata="${rdata},\"${_txt_val}\"" + _txt_val="${rdlist%%,*}" + rdlist="${rdlist#*,}" + rdata="${rdata},\"${_txt_val}\"" done fi # Add the txtvalue TXT Record @@ -139,10 +140,11 @@ dns_edgedns_rm() { rdata="" _txt_val="" while [ "$_txt_val" != "$rdlist" ] && [ "$rdlist" ]; do - _txt_val="${rdlist%%,*}"; rdlist="${rdlist#*,}" + _txt_val="${rdlist%%,*}" + rdlist="${rdlist#*,}" _debug3 "_txt_val" "$_txt_val" _debug3 "txtvalue" "$txtvalue" - if ! _contains "$_txt_val" "$txtvalue" ; then + if ! _contains "$_txt_val" "$txtvalue"; then rdata="${rdata}${comma}\"${_txt_val}\"" comma="," fi @@ -170,7 +172,7 @@ dns_edgedns_rm() { #################### Private functions below ################################## _EDGEDNS_credentials() { - _debug "GettingEdge DNS credentials" + _debug "GettingEdge DNS credentials" _log "$(printf "ACME DNSAPI Edge DNS version %s" ${ACME_EDGEDNS_VERSION})" args_missing=0 if [ -z "$AKAMAI_ACCESS_TOKEN" ]; then @@ -216,7 +218,7 @@ _EDGEDNS_credentials() { _saveaccountconf_mutable AKAMAI_CLIENT_SECRET "$AKAMAI_CLIENT_SECRET" # Set whether curl should use secure or insecure mode fi - export HTTPS_INSECURE=0 # All Edgegrid API calls are secure + export HTTPS_INSECURE=0 # All Edgegrid API calls are secure edge_endpoint=$(printf "https://%s/config-dns/v2/zones" "$AKAMAI_HOST") _debug3 "Edge API Endpoint:" "$edge_endpoint" @@ -244,7 +246,7 @@ _EDGEDNS_getZoneInfo() { return 1 fi fi - if _contains "$curResult" "\"zone\":" ; then + if _contains "$curResult" "\"zone\":"; then _debug2 "Zone data" "${curResult}" zone=$(echo "${curResult}" | _egrep_o "\"zone\"\\s*:\\s*\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d "\"") _debug3 "Zone" "${zone}" @@ -283,7 +285,7 @@ _edgedns_rest() { # Set in acme.sh _post/_get #_edgedns_headers="${_edgedns_headers}${tab}User-Agent:ACME DNSAPI Edge DNS version ${ACME_EDGEDNS_VERSION}" _edgedns_headers="${_edgedns_headers}${tab}Accept: application/json,*/*" - if [ "$m" != "GET" ] && [ "$m" != "DELETE" ] ; then + if [ "$m" != "GET" ] && [ "$m" != "DELETE" ]; then _edgedns_content_type="application/json" _debug3 "_request_body" "$_request_body" _body_len=$(echo "$_request_body" | tr -d "\n\r" | awk '{print length}') @@ -295,13 +297,14 @@ _edgedns_rest() { hdr_indx=1 work_header="${_edgedns_headers}${tab}" _debug3 "work_header" "$work_header" - while [ "$work_header" ]; do - entry="${work_header%%\\t*}"; work_header="${work_header#*\\t}" + while [ "$work_header" ]; do + entry="${work_header%%\\t*}" + work_header="${work_header#*\\t}" export "$(printf "_H%s=%s" "$hdr_indx" "$entry")" _debug2 "Request Header " "$entry" - hdr_indx=$(( hdr_indx + 1 )) + hdr_indx=$((hdr_indx + 1)) done - + # clear headers from previous request to avoid getting wrong http code on timeouts : >"$HTTP_HEADER" _debug2 "$ep" @@ -360,15 +363,15 @@ _edgedns_new_nonce() { _edgedns_make_auth_header() { _debug "Constructing Auth Header" - _edgedns_eg_timestamp - _edgedns_new_nonce + _edgedns_eg_timestamp + _edgedns_new_nonce # "Unsigned authorization header: 'EG1-HMAC-SHA256 client_token=block;access_token=block;timestamp=20200806T14:16:33+0000;nonce=72cde72c-82d9-4721-9854-2ba057929d67;'" - _auth_header="$(printf "EG1-HMAC-SHA256 client_token=%s;access_token=%s;timestamp=%s;nonce=%s;" "$AKAMAI_CLIENT_TOKEN" "$AKAMAI_ACCESS_TOKEN" "$_eg_timestamp" "$_nonce")" + _auth_header="$(printf "EG1-HMAC-SHA256 client_token=%s;access_token=%s;timestamp=%s;nonce=%s;" "$AKAMAI_CLIENT_TOKEN" "$AKAMAI_ACCESS_TOKEN" "$_eg_timestamp" "$_nonce")" _secure_debug2 "Unsigned Auth Header: " "$_auth_header" _edgedns_sign_request _signed_auth_header="$(printf "%ssignature=%s" "$_auth_header" "$_signed_req")" - _secure_debug2 "Signed Auth Header: " "${_signed_auth_header}" + _secure_debug2 "Signed Auth Header: " "${_signed_auth_header}" } _edgedns_sign_request() { @@ -444,5 +447,3 @@ _edgedns_base64_sha256() { # filepath=$1 # section=$2 #} - - From 9c28a04c65435b6f801f313b26c4633791d5cb94 Mon Sep 17 00:00:00 2001 From: Ed Lynes Date: Thu, 27 Aug 2020 17:40:07 -0400 Subject: [PATCH 045/383] add alt nonce generation logic --- dnsapi/dns_edgedns.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_edgedns.sh b/dnsapi/dns_edgedns.sh index 2072637a..f5705ee8 100755 --- a/dnsapi/dns_edgedns.sh +++ b/dnsapi/dns_edgedns.sh @@ -64,7 +64,7 @@ dns_edgedns_add() { record_op="PUT" rdlist="${_edge_result#*\"rdata\":[}" rdlist="${rdlist%%]*}" - rdlist=$(echo "$rdlist" | tr -d '"' | tr -d "\\") + rdlist=$(echo "$rdlist" | tr -d '"' | tr -d "\\\\") _debug3 "existing TXT found" _debug3 "record data" "$rdlist" # value already there? @@ -132,7 +132,7 @@ dns_edgedns_rm() { # record already exists. Get existing record data and update rdlist="${_edge_result#*\"rdata\":[}" rdlist="${rdlist%%]*}" - rdlist=$(echo "$rdlist" | tr -d '"' | tr -d "\\") + rdlist=$(echo "$rdlist" | tr -d '"' | tr -d "\\\\") _debug3 "rdlist" "$rdlist" if [ -n "$rdlist" ]; then record_op="PUT" @@ -355,10 +355,16 @@ _edgedns_rest() { _edgedns_eg_timestamp() { _eg_timestamp=$(date -u "+%Y%m%dT%H:%M:%S+0000") + _debug3 "_eg_timestamp" "$_eg_timestamp" } _edgedns_new_nonce() { _nonce=$(uuidgen -r) + _ret="$?" + if [ "$_ret" -ne 0 ]; then + _nonce=$(echo "EDGEDNS$(_time)" | _digest sha1 hex | cut -c 1-32) + fi + _debug3 "_nonce" "$_nonce" } _edgedns_make_auth_header() { From 9801876a2f3d07f2fa7eba0f7e8cc07a09fe7ef4 Mon Sep 17 00:00:00 2001 From: Ed Lynes Date: Fri, 28 Aug 2020 09:55:20 -0400 Subject: [PATCH 046/383] shfmt fixes --- dnsapi/dns_edgedns.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_edgedns.sh b/dnsapi/dns_edgedns.sh index f5705ee8..94cf809c 100755 --- a/dnsapi/dns_edgedns.sh +++ b/dnsapi/dns_edgedns.sh @@ -361,9 +361,9 @@ _edgedns_eg_timestamp() { _edgedns_new_nonce() { _nonce=$(uuidgen -r) _ret="$?" - if [ "$_ret" -ne 0 ]; then + if [ "$_ret" -ne 0 ]; then _nonce=$(echo "EDGEDNS$(_time)" | _digest sha1 hex | cut -c 1-32) - fi + fi _debug3 "_nonce" "$_nonce" } From 491842ea3431d645dae2022999a9a953385d3748 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 12 Sep 2020 08:47:46 +0800 Subject: [PATCH 047/383] fix https://github.com/acmesh-official/acme.sh/issues/3159 --- dnsapi/dns_ovh.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_ovh.sh b/dnsapi/dns_ovh.sh index dda47dda..f6f9689a 100755 --- a/dnsapi/dns_ovh.sh +++ b/dnsapi/dns_ovh.sh @@ -248,7 +248,7 @@ _ovh_authentication() { # _domain=domain.com _get_root() { domain=$1 - i=2 + i=1 p=1 while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) From 369cfc24138be9a0fb0c1227d17f4922e6043831 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 12 Sep 2020 14:22:18 +0800 Subject: [PATCH 048/383] use testall target --- .github/workflows/DNS.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 0f60ace2..0274afcf 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -67,7 +67,7 @@ jobs: - name: Set env file run: cd ../acmetest && echo "${{ secrets.TokenName1 }}" >> env.list && echo "${{ secrets.TokenName2 }}" >> env.list && echo "TEST_DNS_NO_WILDCARD" >> env.list && echo "TEST_DNS_SLEEP" >> env.list - name: Run acmetest - run: cd ../acmetest && ./rundocker.sh _cron + run: cd ../acmetest && ./rundocker.sh testall MacOS: runs-on: macos-latest From 4875ef045af0c2ef1d8f8442a12821df404ca16c Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 13 Sep 2020 00:16:04 +0800 Subject: [PATCH 049/383] support more dns tokens --- .github/workflows/DNS.yml | 71 ++++++++++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 0274afcf..ae71d594 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -19,13 +19,11 @@ jobs: runs-on: ubuntu-latest outputs: hasToken: ${{ steps.step_one.outputs.hasToken }} - env: - _ACME_CHECK_TOKEN_${{ secrets.TokenName1 }} : ${{ secrets.TokenValue1 }} steps: - name: Set the value id: step_one run: | - if [ "$_ACME_CHECK_TOKEN_${{ secrets.TokenName1}}" ] ; then + if [ "${{secrets.TokenName1}}" ] ; then echo "::set-output name=hasToken::true" else echo "::set-output name=hasToken::false" @@ -50,11 +48,8 @@ jobs: needs: CheckToken if: "contains(needs.CheckToken.outputs.hasToken, 'true')" env: - ${{ secrets.TokenName1 }} : ${{ secrets.TokenValue1 }} - ${{ secrets.TokenName2 }} : ${{ secrets.TokenValue2 }} TEST_DNS : ${{ secrets.TEST_DNS }} TestingDomain: ${{ secrets.TestingDomain }} - TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }} TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }} CASE: le_test_dnsapi @@ -65,7 +60,25 @@ jobs: - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - name: Set env file - run: cd ../acmetest && echo "${{ secrets.TokenName1 }}" >> env.list && echo "${{ secrets.TokenName2 }}" >> env.list && echo "TEST_DNS_NO_WILDCARD" >> env.list && echo "TEST_DNS_SLEEP" >> env.list + run: | + cd ../acmetest + if [ "${{ secrets.TokenName1}}" ] ; then + echo "${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}" >> env.list + fi + if [ "${{ secrets.TokenName2}}" ] ; then + echo "${{ secrets.TokenName2}}=${{ secrets.TokenValue2}}" >> env.list + fi + if [ "${{ secrets.TokenName3}}" ] ; then + echo "${{ secrets.TokenName3}}=${{ secrets.TokenValue3}}" >> env.list + fi + if [ "${{ secrets.TokenName4}}" ] ; then + echo "${{ secrets.TokenName4}}=${{ secrets.TokenValue4}}" >> env.list + fi + if [ "${{ secrets.TokenName5}}" ] ; then + echo "${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}" >> env.list + fi + echo "TEST_DNS_NO_WILDCARD" >> env.list + echo "TEST_DNS_SLEEP" >> env.list - name: Run acmetest run: cd ../acmetest && ./rundocker.sh testall @@ -73,11 +86,8 @@ jobs: runs-on: macos-latest needs: Docker env: - ${{ secrets.TokenName1 }} : ${{ secrets.TokenValue1 }} - ${{ secrets.TokenName2 }} : ${{ secrets.TokenValue2 }} TEST_DNS : ${{ secrets.TEST_DNS }} TestingDomain: ${{ secrets.TestingDomain }} - TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }} TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }} CASE: le_test_dnsapi @@ -90,17 +100,31 @@ jobs: - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - name: Run acmetest - run: cd ../acmetest && ./letest.sh + run: | + if [ "${{ secrets.TokenName1}}" ] ; then + export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}} + fi + if [ "${{ secrets.TokenName2}}" ] ; then + export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}} + fi + if [ "${{ secrets.TokenName3}}" ] ; then + export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}} + fi + if [ "${{ secrets.TokenName4}}" ] ; then + export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}} + fi + if [ "${{ secrets.TokenName5}}" ] ; then + export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}} + fi + cd ../acmetest + ./letest.sh Windows: runs-on: windows-latest needs: MacOS env: - ${{ secrets.TokenName1 }} : ${{ secrets.TokenValue1 }} - ${{ secrets.TokenName2 }} : ${{ secrets.TokenValue2 }} TEST_DNS : ${{ secrets.TEST_DNS }} TestingDomain: ${{ secrets.TestingDomain }} - TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }} TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }} CASE: le_test_dnsapi @@ -127,6 +151,23 @@ jobs: run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - name: Run acmetest shell: cmd - run: cd ../acmetest && bash.exe -c ./letest.sh + run: | + if [ "${{ secrets.TokenName1}}" ] ; then + set ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}} + fi + if [ "${{ secrets.TokenName2}}" ] ; then + set ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}} + fi + if [ "${{ secrets.TokenName3}}" ] ; then + set ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}} + fi + if [ "${{ secrets.TokenName4}}" ] ; then + set ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}} + fi + if [ "${{ secrets.TokenName5}}" ] ; then + set ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}} + fi + cd ../acmetest + bash.exe -c ./letest.sh From 69c5291e52c7fe59721e5224f69cab9df12ac41e Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 14 Sep 2020 21:51:21 +0800 Subject: [PATCH 050/383] fix for Windows --- .github/workflows/DNS.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index ae71d594..5591b8f1 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -150,24 +150,24 @@ jobs: - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - name: Run acmetest - shell: cmd + shell: bash run: | if [ "${{ secrets.TokenName1}}" ] ; then - set ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}} + export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}} fi if [ "${{ secrets.TokenName2}}" ] ; then - set ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}} + export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}} fi if [ "${{ secrets.TokenName3}}" ] ; then - set ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}} + export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}} fi if [ "${{ secrets.TokenName4}}" ] ; then - set ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}} + export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}} fi if [ "${{ secrets.TokenName5}}" ] ; then - set ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}} + export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}} fi cd ../acmetest - bash.exe -c ./letest.sh + ./letest.sh From 576a146ed223f06cdf5dcbd3c984a6ae2cfe1873 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 14 Sep 2020 22:22:36 +0800 Subject: [PATCH 051/383] add debug info for duckdns --- dnsapi/dns_duckdns.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index 11b685c0..7c2ecfb2 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -112,6 +112,9 @@ _duckdns_rest() { param="$2" _debug param "$param" url="$DuckDNS_API?$param" + if [ "$DEBUG" -gt 0 ]; then + url="$url&verbose=true" + fi _debug url "$url" # DuckDNS uses GET to update domain info From 85736d697cf9068fb79fd53fdb67519b24c13b08 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 14 Sep 2020 22:29:23 +0800 Subject: [PATCH 052/383] fix debug info --- dnsapi/dns_duckdns.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index 7c2ecfb2..f0af2741 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -120,11 +120,13 @@ _duckdns_rest() { # DuckDNS uses GET to update domain info if [ "$method" = "GET" ]; then response="$(_get "$url")" + _debug2 response "$response" + if [ "$DEBUG" -gt 0 ] && _contains "$response" "UPDATED" && _contains "$response" "OK"; then + response="OK" + fi else _err "Unsupported method" return 1 fi - - _debug2 response "$response" return 0 } From ea724e343bab76850d8d3f5a76d700af451864b7 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 21 Sep 2020 19:57:10 +0800 Subject: [PATCH 053/383] enable for any branches. --- .github/workflows/DNS.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 5591b8f1..3ad9506b 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -1,8 +1,6 @@ name: DNS on: push: - branches: - - 'dev' paths: - 'dnsapi/*.sh' - '.github/workflows/DNS.yml' From 098ef976f7ce3c99052c0984359515ab95fde04e Mon Sep 17 00:00:00 2001 From: neil Date: Thu, 24 Sep 2020 21:37:51 +0800 Subject: [PATCH 054/383] add freebsd --- .github/workflows/LetsEncrypt.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 9a0175b5..69ff35ff 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -96,4 +96,20 @@ jobs: shell: cmd run: cd ../acmetest && bash.exe -c ./letest.sh + FreeBSD: + runs-on: macos-latest + needs: Windows + env: + NGROK_TOKEN : ${{ secrets.NGROK_TOKEN }} + TEST_LOCAL: 1 + steps: + - uses: actions/checkout@v2 + - name: Clone acmetest + run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ + - uses: vmactions/freebsd@main + with: + envs: 'NGROK_TOKEN TEST_LOCAL' + prepare: pkg install -y socat + run: | + cd ../acmetest && ./letest.sh From 182d150eaa0a48b1ebe5b0d1fd13bd175d16eee9 Mon Sep 17 00:00:00 2001 From: neil Date: Thu, 24 Sep 2020 22:18:38 +0800 Subject: [PATCH 055/383] add curl to freebsd --- .github/workflows/LetsEncrypt.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 69ff35ff..4a8d4336 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -109,7 +109,7 @@ jobs: - uses: vmactions/freebsd@main with: envs: 'NGROK_TOKEN TEST_LOCAL' - prepare: pkg install -y socat + prepare: pkg install -y socat curl run: | cd ../acmetest && ./letest.sh From 27ec69fb97260b180ab919314d8cced1d062a2ab Mon Sep 17 00:00:00 2001 From: neil Date: Thu, 24 Sep 2020 22:57:26 +0800 Subject: [PATCH 056/383] add FreeBSD --- .github/workflows/DNS.yml | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 3ad9506b..fd9a98b3 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -168,4 +168,42 @@ jobs: cd ../acmetest ./letest.sh + FreeBSD: + runs-on: macos-latest + needs: Windows + env: + TEST_DNS : ${{ secrets.TEST_DNS }} + TestingDomain: ${{ secrets.TestingDomain }} + TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }} + TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }} + CASE: le_test_dnsapi + TEST_LOCAL: 1 + DEBUG: 1 + steps: + - uses: actions/checkout@v2 + - name: Clone acmetest + run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ + - uses: vmactions/freebsd@main + with: + envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' + prepare: pkg install -y socat curl + run: | + if [ "${{ secrets.TokenName1}}" ] ; then + export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}} + fi + if [ "${{ secrets.TokenName2}}" ] ; then + export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}} + fi + if [ "${{ secrets.TokenName3}}" ] ; then + export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}} + fi + if [ "${{ secrets.TokenName4}}" ] ; then + export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}} + fi + if [ "${{ secrets.TokenName5}}" ] ; then + export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}} + fi + cd ../acmetest + ./letest.sh + From 7616e94fd313025cc6c0386ee0997b1e1981cd76 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 28 Sep 2020 21:50:20 +0800 Subject: [PATCH 057/383] fix message --- .github/workflows/DNS.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index fd9a98b3..191ae8c9 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -36,10 +36,10 @@ jobs: steps: - name: "Read this: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test" run: | - echo "Plese see this page to fix the error: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test" - - name: Fail - if: "github.actor != 'Neilpang'" - run: false + echo "Read this: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test" + if [ "${{github.actor}}" != "Neilpang" ]; then + false + fi Docker: runs-on: ubuntu-latest From 967096f01ce2daa819ae082c2d9fba098af8a752 Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 2 Oct 2020 16:17:16 +0800 Subject: [PATCH 058/383] update freebsd-vm --- .github/workflows/DNS.yml | 2 +- .github/workflows/LetsEncrypt.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 191ae8c9..1c0165c0 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -183,7 +183,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd@main + - uses: vmactions/freebsd-vm@v0.0.4 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkg install -y socat curl diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 4a8d4336..ba5e933d 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -106,7 +106,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd@main + - uses: vmactions/freebsd-vm@v0.0.4 with: envs: 'NGROK_TOKEN TEST_LOCAL' prepare: pkg install -y socat curl From 71f00a9efd5d458b03a96a98f5718bd9d12899b3 Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 2 Oct 2020 16:20:27 +0800 Subject: [PATCH 059/383] minor --- .github/workflows/DNS.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 1c0165c0..976aff56 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -206,4 +206,5 @@ jobs: cd ../acmetest ./letest.sh + From a160b798cac43e8cc7cda355b3ef5e58b9e56b28 Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 2 Oct 2020 17:11:04 +0800 Subject: [PATCH 060/383] update badge --- README.md | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 953c44a5..6fb88daf 100644 --- a/README.md +++ b/README.md @@ -57,26 +57,26 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa) | NO | Status| Platform| |----|-------|---------| -|1|[![](https://acmesh-official.github.io/acmetest/status/ubuntu-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)| Ubuntu -|2|[![](https://acmesh-official.github.io/acmetest/status/debian-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)| Debian -|3|[![](https://acmesh-official.github.io/acmetest/status/centos-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|CentOS -|4|[![](https://acmesh-official.github.io/acmetest/status/windows-cygwin.svg)](https://github.com/acmesh-official/acmetest#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/acmetest#here-are-the-latest-status)|FreeBSD -|6|[![](https://acmesh-official.github.io/acmetest/status/pfsense.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|pfsense -|7|[![](https://acmesh-official.github.io/acmetest/status/opensuse-leap-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|openSUSE -|8|[![](https://acmesh-official.github.io/acmetest/status/alpine-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Alpine Linux (with curl) -|9|[![](https://acmesh-official.github.io/acmetest/status/archlinux-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Archlinux -|10|[![](https://acmesh-official.github.io/acmetest/status/fedora-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|fedora -|11|[![](https://acmesh-official.github.io/acmetest/status/kalilinux-kali.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Kali Linux -|12|[![](https://acmesh-official.github.io/acmetest/status/oraclelinux-latest.svg)](https://github.com/acmesh-official/acmetest#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: See Proxmox VE Wiki. Version [4.x, 5.0, 5.1](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x,_5.0_and_5.1)#Let.27s_Encrypt_using_acme.sh), version [5.2 and up](https://pve.proxmox.com/wiki/Certificate_Management) -|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/acmetest#here-are-the-latest-status)|OpenBSD -|16|[![](https://acmesh-official.github.io/acmetest/status/mageia.svg)](https://github.com/acmesh-official/acmetest#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/acmetest#here-are-the-latest-status)|SunOS/Solaris -|19|[![](https://acmesh-official.github.io/acmetest/status/gentoo-stage3-amd64.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Gentoo Linux -|20|[![Build Status](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|Mac OSX +|1|[![MacOS](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|Mac OSX +|2|[![Windows](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|Windows (cygwin with curl, openssl and crontab included) +|3|[![FreeBSD](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|FreeBSD +|4|[![](https://acmesh-official.github.io/acmetest/status/pfsense.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|pfsense +|5|[![](https://acmesh-official.github.io/acmetest/status/openbsd.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|OpenBSD +|6|[![](https://acmesh-official.github.io/acmetest/status/solaris.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|SunOS/Solaris +|7|[![](https://acmesh-official.github.io/acmetest/status/ubuntu-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)| Ubuntu +|8|[![](https://acmesh-official.github.io/acmetest/status/debian-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)| Debian +|9|[![](https://acmesh-official.github.io/acmetest/status/centos-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|CentOS +|10|[![](https://acmesh-official.github.io/acmetest/status/opensuse-leap-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|openSUSE +|11|[![](https://acmesh-official.github.io/acmetest/status/alpine-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Alpine Linux (with curl) +|12|[![](https://acmesh-official.github.io/acmetest/status/archlinux-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Archlinux +|13|[![](https://acmesh-official.github.io/acmetest/status/fedora-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|fedora +|14|[![](https://acmesh-official.github.io/acmetest/status/kalilinux-kali.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Kali Linux +|15|[![](https://acmesh-official.github.io/acmetest/status/oraclelinux-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Oracle Linux +|16|[![](https://acmesh-official.github.io/acmetest/status/proxmox.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Proxmox: See Proxmox VE Wiki. Version [4.x, 5.0, 5.1](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x,_5.0_and_5.1)#Let.27s_Encrypt_using_acme.sh), version [5.2 and up](https://pve.proxmox.com/wiki/Certificate_Management) +|17|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111 +|18|[![](https://acmesh-official.github.io/acmetest/status/mageia.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Mageia +|19|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT) +|20|[![](https://acmesh-official.github.io/acmetest/status/gentoo-stage3-amd64.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Gentoo Linux |21|[![](https://acmesh-official.github.io/acmetest/status/clearlinux-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|ClearLinux For all build statuses, check our [weekly build project](https://github.com/acmesh-official/acmetest): From 13c1f4ab19c1f2ff6f9f8335425de8d18861ad45 Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 2 Oct 2020 17:17:31 +0800 Subject: [PATCH 061/383] update badge --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6fb88daf..7215785c 100644 --- a/README.md +++ b/README.md @@ -60,10 +60,10 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa) |1|[![MacOS](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|Mac OSX |2|[![Windows](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|Windows (cygwin with curl, openssl and crontab included) |3|[![FreeBSD](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|FreeBSD -|4|[![](https://acmesh-official.github.io/acmetest/status/pfsense.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|pfsense -|5|[![](https://acmesh-official.github.io/acmetest/status/openbsd.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|OpenBSD -|6|[![](https://acmesh-official.github.io/acmetest/status/solaris.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|SunOS/Solaris -|7|[![](https://acmesh-official.github.io/acmetest/status/ubuntu-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)| Ubuntu +|4|[![Ubuntu](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)| Ubuntu +|5|[![](https://acmesh-official.github.io/acmetest/status/pfsense.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|pfsense +|6|[![](https://acmesh-official.github.io/acmetest/status/openbsd.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|OpenBSD +|7|[![](https://acmesh-official.github.io/acmetest/status/solaris.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|SunOS/Solaris |8|[![](https://acmesh-official.github.io/acmetest/status/debian-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)| Debian |9|[![](https://acmesh-official.github.io/acmetest/status/centos-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|CentOS |10|[![](https://acmesh-official.github.io/acmetest/status/opensuse-leap-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|openSUSE From 2340c55d762269c06cae13f310649c758d739729 Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 9 Oct 2020 22:33:21 +0800 Subject: [PATCH 062/383] update freebsd --- .github/workflows/DNS.yml | 3 ++- .github/workflows/LetsEncrypt.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 976aff56..b06db229 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -183,10 +183,11 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.0.4 + - uses: vmactions/freebsd-vm@v0.0.5 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkg install -y socat curl + usesh: true run: | if [ "${{ secrets.TokenName1}}" ] ; then export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}} diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index ba5e933d..d71f3ac1 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -106,10 +106,11 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.0.4 + - uses: vmactions/freebsd-vm@v0.0.5 with: envs: 'NGROK_TOKEN TEST_LOCAL' prepare: pkg install -y socat curl + usesh: true run: | cd ../acmetest && ./letest.sh From 25468f55ffbca9a78330221404571786f9f229a5 Mon Sep 17 00:00:00 2001 From: Rene Luria Date: Mon, 21 Sep 2020 14:17:23 +0200 Subject: [PATCH 063/383] Added dnsapi/dns_infomaniak.sh --- dnsapi/dns_infomaniak.sh | 199 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100755 dnsapi/dns_infomaniak.sh diff --git a/dnsapi/dns_infomaniak.sh b/dnsapi/dns_infomaniak.sh new file mode 100755 index 00000000..e2328a36 --- /dev/null +++ b/dnsapi/dns_infomaniak.sh @@ -0,0 +1,199 @@ +#!/usr/bin/env sh + +############################################################################### +# Infomaniak API integration +# +# To use this API you need visit the API dashboard of your account +# once logged into https://manager.infomaniak.com add /api/dashboard to the URL +# +# Please report bugs to +# https://github.com/acmesh-official/acme.sh/issues/3188 +# +# Note: the URL looks like this: +# https://manager.infomaniak.com/v3//api/dashboard +# Then generate a token with the scope Domain +# this is given as an environment variable INFOMANIAK_API_TOKEN +############################################################################### + +# base variables + +DEFAULT_INFOMANIAK_API_URL="https://api.infomaniak.com" +DEFAULT_INFOMANIAK_TTL=300 + +######## Public functions ##################### + +#Usage: dns_infomaniak_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_infomaniak_add() { + + INFOMANIAK_API_TOKEN="${INFOMANIAK_API_TOKEN:-$(_readaccountconf_mutable INFOMANIAK_API_TOKEN)}" + INFOMANIAK_API_URL="${INFOMANIAK_API_URL:-$(_readaccountconf_mutable INFOMANIAK_API_URL)}" + INFOMANIAK_TTL="${INFOMANIAK_TTL:-$(_readaccountconf_mutable INFOMANIAK_TTL)}" + + if [ -z "$INFOMANIAK_API_TOKEN" ]; then + INFOMANIAK_API_TOKEN="" + _err "Please provide a valid Infomaniak API token in variable INFOMANIAK_API_TOKEN" + return 1 + fi + + if [ -z "$INFOMANIAK_API_URL" ]; then + INFOMANIAK_API_URL="$DEFAULT_INFOMANIAK_API_URL" + fi + + if [ -z "$INFOMANIAK_TTL" ]; then + INFOMANIAK_TTL="$DEFAULT_INFOMANIAK_TTL" + fi + + #save the token to the account conf file. + _saveaccountconf_mutable INFOMANIAK_API_TOKEN "$INFOMANIAK_API_TOKEN" + + if [ "$INFOMANIAK_API_URL" != "$DEFAULT_INFOMANIAK_API_URL" ]; then + _saveaccountconf_mutable INFOMANIAK_API_URL "$INFOMANIAK_API_URL" + fi + + if [ "$INFOMANIAK_TTL" != "$DEFAULT_INFOMANIAK_TTL" ]; then + _saveaccountconf_mutable INFOMANIAK_TTL "$INFOMANIAK_TTL" + fi + + export _H1="Authorization: Bearer $INFOMANIAK_API_TOKEN" + export _H2="Content-Type: application/json" + + fulldomain="$1" + txtvalue="$2" + + _info "Infomaniak DNS API" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + fqdn=${fulldomain#_acme-challenge.} + + # guess which base domain to add record to + zone_and_id=$(_find_zone "$fqdn") + if [ -z "$zone_and_id" ]; then + _err "cannot find zone to modify" + return 1 + fi + zone=${zone_and_id% *} + domain_id=${zone_and_id#* } + + # extract first part of domain + key=${fulldomain%.$zone} + + _debug "zone:$zone id:$domain_id key:$key" + + # payload + data="{\"type\": \"TXT\", \"source\": \"$key\", \"target\": \"$txtvalue\", \"ttl\": $INFOMANIAK_TTL}" + + # API call + response=$(_post "$data" "${INFOMANIAK_API_URL}/1/domain/$domain_id/dns/record") + if [ -n "$response" ] && echo "$response" | grep -qF '"result":"success"'; then + _info "Record added" + _debug "Response: $response" + return 0 + fi + _err "could not create record" + _debug "Response: $response" + return 1 +} + +#Usage: fulldomain txtvalue +#Remove the txt record after validation. +dns_infomaniak_rm() { + + INFOMANIAK_API_TOKEN="${INFOMANIAK_API_TOKEN:-$(_readaccountconf_mutable INFOMANIAK_API_TOKEN)}" + INFOMANIAK_API_URL="${INFOMANIAK_API_URL:-$(_readaccountconf_mutable INFOMANIAK_API_URL)}" + INFOMANIAK_TTL="${INFOMANIAK_TTL:-$(_readaccountconf_mutable INFOMANIAK_TTL)}" + + if [ -z "$INFOMANIAK_API_TOKEN" ]; then + INFOMANIAK_API_TOKEN="" + _err "Please provide a valid Infomaniak API token in variable INFOMANIAK_API_TOKEN" + return 1 + fi + + if [ -z "$INFOMANIAK_API_URL" ]; then + INFOMANIAK_API_URL="$DEFAULT_INFOMANIAK_API_URL" + fi + + if [ -z "$INFOMANIAK_TTL" ]; then + INFOMANIAK_TTL="$DEFAULT_INFOMANIAK_TTL" + fi + + #save the token to the account conf file. + _saveaccountconf_mutable INFOMANIAK_API_TOKEN "$INFOMANIAK_API_TOKEN" + + if [ "$INFOMANIAK_API_URL" != "$DEFAULT_INFOMANIAK_API_URL" ]; then + _saveaccountconf_mutable INFOMANIAK_API_URL "$INFOMANIAK_API_URL" + fi + + if [ "$INFOMANIAK_TTL" != "$DEFAULT_INFOMANIAK_TTL" ]; then + _saveaccountconf_mutable INFOMANIAK_TTL "$INFOMANIAK_TTL" + fi + + export _H1="Authorization: Bearer $INFOMANIAK_API_TOKEN" + export _H2="ContentType: application/json" + + fulldomain=$1 + txtvalue=$2 + _info "Infomaniak DNS API" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + fqdn=${fulldomain#_acme-challenge.} + + # guess which base domain to add record to + zone_and_id=$(_find_zone "$fqdn") + if [ -z "$zone_and_id" ]; then + _err "cannot find zone to modify" + return 1 + fi + zone=${zone_and_id% *} + domain_id=${zone_and_id#* } + + # extract first part of domain + key=${fulldomain%.$zone} + + _debug "zone:$zone id:$domain_id key:$key" + + # find previous record + # shellcheck disable=SC1004 + record_id=$(_get "${INFOMANIAK_API_URL}/1/domain/$domain_id/dns/record" | sed 's/.*"data":\[\(.*\)\]}/\1/; s/},{/}\ +{/g' | sed -n 's/.*"id":"*\([0-9]*\)"*.*"source_idn":"'"$fulldomain"'".*"target_idn":"'"$txtvalue"'".*/\1/p') + if [ -z "$record_id" ]; then + _err "could not find record to delete" + return 1 + fi + _debug "record_id: $record_id" + + # API call + response=$(_post "" "${INFOMANIAK_API_URL}/1/domain/$domain_id/dns/record/$record_id" "" DELETE) + if [ -n "$response" ] && echo "$response" | grep -qF '"result":"success"'; then + _info "Record deleted" + return 0 + fi + _err "could not delete record" + return 1 +} + +#################### Private functions below ################################## + +_get_domain_id() { + domain="$1" + + # shellcheck disable=SC1004 + _get "${INFOMANIAK_API_URL}/1/product?service_name=domain&customer_name=$domain" | sed 's/.*"data":\[{\(.*\)}\]}/\1/; s/,/\ +/g' | sed -n 's/^"id":\(.*\)/\1/p' +} + +_find_zone() { + zone="$1" + + # find domain in list, removing . parts sequentialy + while echo "$zone" | grep -q '\.'; do + _debug "testing $zone" + id=$(_get_domain_id "$zone") + if [ -n "$id" ]; then + echo "$zone $id" + return + fi + zone=${zone#*.} + done +} From 15fa0c264f7cfd8bc9542ec18a1c7cb407e7404e Mon Sep 17 00:00:00 2001 From: Rene Luria Date: Fri, 2 Oct 2020 12:47:33 +0200 Subject: [PATCH 064/383] dnsapi/dns_infomaniak.sh: Replace grep by _contains --- dnsapi/dns_infomaniak.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_infomaniak.sh b/dnsapi/dns_infomaniak.sh index e2328a36..765cf39d 100755 --- a/dnsapi/dns_infomaniak.sh +++ b/dnsapi/dns_infomaniak.sh @@ -85,7 +85,7 @@ dns_infomaniak_add() { # API call response=$(_post "$data" "${INFOMANIAK_API_URL}/1/domain/$domain_id/dns/record") - if [ -n "$response" ] && echo "$response" | grep -qF '"result":"success"'; then + if [ -n "$response" ] && echo "$response" | _contains '"result":"success"'; then _info "Record added" _debug "Response: $response" return 0 @@ -165,7 +165,7 @@ dns_infomaniak_rm() { # API call response=$(_post "" "${INFOMANIAK_API_URL}/1/domain/$domain_id/dns/record/$record_id" "" DELETE) - if [ -n "$response" ] && echo "$response" | grep -qF '"result":"success"'; then + if [ -n "$response" ] && echo "$response" | _contains '"result":"success"'; then _info "Record deleted" return 0 fi @@ -187,7 +187,7 @@ _find_zone() { zone="$1" # find domain in list, removing . parts sequentialy - while echo "$zone" | grep -q '\.'; do + while _contains "$zone" '\.'; do _debug "testing $zone" id=$(_get_domain_id "$zone") if [ -n "$id" ]; then From c6617ebc9faf47e08ee21f23dee9ce839974af27 Mon Sep 17 00:00:00 2001 From: Rene Luria Date: Thu, 8 Oct 2020 23:42:05 +0200 Subject: [PATCH 065/383] Fix DNS workflow use variables TEST_DNS_SLEEP and TEST_DNS_NO_WILDCARD --- .github/workflows/DNS.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index b06db229..1909cb03 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -75,8 +75,8 @@ jobs: if [ "${{ secrets.TokenName5}}" ] ; then echo "${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}" >> env.list fi - echo "TEST_DNS_NO_WILDCARD" >> env.list - echo "TEST_DNS_SLEEP" >> env.list + echo "TEST_DNS_NO_WILDCARD=$TEST_DNS_NO_WILDCARD" >> env.list + echo "TEST_DNS_SLEEP=$TEST_DNS_SLEEP" >> env.list - name: Run acmetest run: cd ../acmetest && ./rundocker.sh testall From ff8fe7e01857afd3c18d94e4a529ddefac85da4e Mon Sep 17 00:00:00 2001 From: Rene Luria Date: Sat, 10 Oct 2020 18:20:26 +0200 Subject: [PATCH 066/383] Revert "Fix DNS workflow use variables TEST_DNS_SLEEP and TEST_DNS_NO_WILDCARD" This reverts commit f864416e39753b66f26d8d3fa19cbb094493731a. --- .github/workflows/DNS.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 1909cb03..b06db229 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -75,8 +75,8 @@ jobs: if [ "${{ secrets.TokenName5}}" ] ; then echo "${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}" >> env.list fi - echo "TEST_DNS_NO_WILDCARD=$TEST_DNS_NO_WILDCARD" >> env.list - echo "TEST_DNS_SLEEP=$TEST_DNS_SLEEP" >> env.list + echo "TEST_DNS_NO_WILDCARD" >> env.list + echo "TEST_DNS_SLEEP" >> env.list - name: Run acmetest run: cd ../acmetest && ./rundocker.sh testall From 5aff548794a9569a38a439014cc36073c0ff38b8 Mon Sep 17 00:00:00 2001 From: Ed Lynes Date: Wed, 14 Oct 2020 14:49:09 -0400 Subject: [PATCH 067/383] remove uuidgen --- dnsapi/dns_edgedns.sh | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/dnsapi/dns_edgedns.sh b/dnsapi/dns_edgedns.sh index 94cf809c..89e77936 100755 --- a/dnsapi/dns_edgedns.sh +++ b/dnsapi/dns_edgedns.sh @@ -359,11 +359,7 @@ _edgedns_eg_timestamp() { } _edgedns_new_nonce() { - _nonce=$(uuidgen -r) - _ret="$?" - if [ "$_ret" -ne 0 ]; then - _nonce=$(echo "EDGEDNS$(_time)" | _digest sha1 hex | cut -c 1-32) - fi + _nonce=$(echo "EDGEDNS$(_time)" | _digest sha1 hex | cut -c 1-32) _debug3 "_nonce" "$_nonce" } From 054a62de6073492457bf35e406f743d2c1eb5477 Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 16 Oct 2020 18:47:02 +0800 Subject: [PATCH 068/383] Update DNS.yml --- .github/workflows/DNS.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index b06db229..25d92137 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -183,7 +183,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.0.5 + - uses: vmactions/freebsd-vm@v0.0.7 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkg install -y socat curl From 23088bc89778d48b183a9c26789b4d4f4ee53b4c Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 16 Oct 2020 18:47:27 +0800 Subject: [PATCH 069/383] Update LetsEncrypt.yml --- .github/workflows/LetsEncrypt.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index d71f3ac1..39e91161 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -106,7 +106,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.0.5 + - uses: vmactions/freebsd-vm@v0.0.7 with: envs: 'NGROK_TOKEN TEST_LOCAL' prepare: pkg install -y socat curl From 9ab16bdbb36462db2b63b0a2362369e1d1f5e91b Mon Sep 17 00:00:00 2001 From: Ed Lynes Date: Fri, 16 Oct 2020 10:16:25 -0400 Subject: [PATCH 070/383] use _digest instead of openssl --- dnsapi/dns_edgedns.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_edgedns.sh b/dnsapi/dns_edgedns.sh index 89e77936..7ab448d2 100755 --- a/dnsapi/dns_edgedns.sh +++ b/dnsapi/dns_edgedns.sh @@ -440,7 +440,7 @@ _edgedns_base64_sha256() { _debug2 "Creating sha256 digest" trg=$1 _secure_debug2 "digest data" "$trg" - digest="$(echo "$trg" | tr -d "\n\r" | ${ACME_OPENSSL_BIN:-openssl} dgst -sha256 -binary | _base64)" + digest="$(echo "$trg" | tr -d "\n\r" | _digest "sha256")" _sha256_out="$(echo "$digest" | tr -d "\n\r" | iconv -f utf-8)" _secure_debug2 "digest decode" "$_sha256_out" } From 6b20993d2a54b30642ef4987a0370307c4d6dfd4 Mon Sep 17 00:00:00 2001 From: Ed Lynes Date: Fri, 16 Oct 2020 10:32:01 -0400 Subject: [PATCH 071/383] fix format --- dnsapi/dns_edgedns.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_edgedns.sh b/dnsapi/dns_edgedns.sh index 7ab448d2..05c8e886 100755 --- a/dnsapi/dns_edgedns.sh +++ b/dnsapi/dns_edgedns.sh @@ -440,7 +440,7 @@ _edgedns_base64_sha256() { _debug2 "Creating sha256 digest" trg=$1 _secure_debug2 "digest data" "$trg" - digest="$(echo "$trg" | tr -d "\n\r" | _digest "sha256")" + digest="$(echo "$trg" | tr -d "\n\r" | _digest "sha256")" _sha256_out="$(echo "$digest" | tr -d "\n\r" | iconv -f utf-8)" _secure_debug2 "digest decode" "$_sha256_out" } From 27a54bcbaa666da69eea8256d73fe6ce4648ba64 Mon Sep 17 00:00:00 2001 From: Adrian Fedoreanu Date: Mon, 19 Oct 2020 20:45:52 +0200 Subject: [PATCH 072/383] fix dnsapi/dns_1984hosting --- dnsapi/dns_1984hosting.sh | 84 +++++++++++++++------------------------ 1 file changed, 33 insertions(+), 51 deletions(-) diff --git a/dnsapi/dns_1984hosting.sh b/dnsapi/dns_1984hosting.sh index bcb675ab..d720c1c5 100755 --- a/dnsapi/dns_1984hosting.sh +++ b/dnsapi/dns_1984hosting.sh @@ -40,8 +40,35 @@ dns_1984hosting_add() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - _1984hosting_add_txt_record "$_domain" "$_sub_domain" "$txtvalue" - return $? + _debug "Add TXT record $fulldomain with value '$txtvalue'" + value="$(printf '%s' "$txtvalue" | _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=$_sub_domain" + 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 $_sub_domain bad RC from _post" + return 1 + elif _contains "$response" ""; then + _err "1984Hosting failed to add TXT record for $_sub_domain. Check $HTTP_HEADER file" + return 1 + elif _contains "$response" '"auth": false'; then + _err "1984Hosting failed to add TXT record for $_sub_domain. Invalid or expired cookie" + return 1 + fi + + _info "Added acme challenge TXT record for $fulldomain at 1984Hosting" + return 0 } #Usage: fulldomain txtvalue @@ -67,57 +94,10 @@ dns_1984hosting_rm() { _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 _contains "$response" '"auth": 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" + _htmlget "$url" "$_domain" _debug2 _response "$_response" zone_id="$(echo "$_response" | _egrep_o 'zone\/[0-9]+')" _debug2 zone_id "$zone_id" @@ -126,7 +106,7 @@ _1984hosting_delete_txt_record() { return 1 fi - _htmlget "$url/$zone_id" "$subdomain" + _htmlget "$url/$zone_id" "$_sub_domain" _debug2 _response "$_response" entry_id="$(echo "$_response" | _egrep_o 'entry_[0-9]+' | sed 's/entry_//')" _debug2 entry_id "$entry_id" @@ -148,6 +128,8 @@ _1984hosting_delete_txt_record() { return 0 } +#################### Private functions below ################################## + # usage: _1984hosting_login username password # returns 0 success _1984hosting_login() { From b025ed60579e194140a75062e8bb6ef5d42b6c00 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 21 Oct 2020 15:00:33 +0800 Subject: [PATCH 073/383] Update LetsEncrypt.yml --- .github/workflows/LetsEncrypt.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 39e91161..5f0bba72 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -58,7 +58,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Install tools - run: brew update && brew install socat; + run: brew install socat - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - name: Run acmetest From 1db963361c4b832c048b8d85fe302d37b5d41cec Mon Sep 17 00:00:00 2001 From: Jan-Philipp Benecke Date: Wed, 28 Oct 2020 13:50:40 +0100 Subject: [PATCH 074/383] Rework based on review from Neilpang --- deploy/cleverreach.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/deploy/cleverreach.sh b/deploy/cleverreach.sh index 0fa07f4a..552d8149 100644 --- a/deploy/cleverreach.sh +++ b/deploy/cleverreach.sh @@ -2,8 +2,6 @@ # Here is the script to deploy the cert to your CleverReach Account using the CleverReach REST API. # Your OAuth needs the right scope, please contact CleverReach support for that. # -# It requires that jq are in the $PATH. -# # Written by Jan-Philipp Benecke # Public domain, 2020 # @@ -25,30 +23,32 @@ cleverreach_deploy() { _debug _cca "$_cca" _debug _cfullchain "$_cfullchain" - _cleverreach_client_id="${DEPLOY_CLEVERREACH_CLIENT_ID}" - _cleverreach_client_secret="${DEPLOY_CLEVERREACH_CLIENT_SECRET}" + _getdeployconf DEPLOY_CLEVERREACH_CLIENT_ID + _getdeployconf DEPLOY_CLEVERREACH_CLIENT_SECRET - if [ -z "$_cleverreach_client_id" ]; then + if [ -z "${DEPLOY_CLEVERREACH_CLIENT_ID}" ]; then _err "CleverReach Client ID is not found, please define DEPLOY_CLEVERREACH_CLIENT_ID." return 1 fi - if [ -z "$_cleverreach_client_secret" ]; then + if [ -z "${DEPLOY_CLEVERREACH_CLIENT_SECRET}" ]; then _err "CleverReach client secret is not found, please define DEPLOY_CLEVERREACH_CLIENT_SECRET." return 1 fi - _saveaccountconf DEPLOY_CLEVERREACH_CLIENT_ID "${_cleverreach_client_id}" - _saveaccountconf DEPLOY_CLEVERREACH_CLIENT_SECRET "${_cleverreach_client_secret}" + _savedeployconf DEPLOY_CLEVERREACH_CLIENT_ID "${DEPLOY_CLEVERREACH_CLIENT_ID}" + _savedeployconf DEPLOY_CLEVERREACH_CLIENT_SECRET "${DEPLOY_CLEVERREACH_CLIENT_SECRET}" _info "Obtaining a CleverReach access token" - _data="{\"grant_type\": \"client_credentials\", \"client_id\": \"${_cleverreach_client_id}\", \"client_secret\": \"${_cleverreach_client_secret}\"}" + _data="{\"grant_type\": \"client_credentials\", \"client_id\": \"${DEPLOY_CLEVERREACH_CLIENT_ID}\", \"client_secret\": \"${DEPLOY_CLEVERREACH_CLIENT_SECRET}\"}" _auth_result="$(_post "$_data" "https://rest.cleverreach.com/oauth/token.php" "" "POST" "application/json")" _debug _data "$_data" _debug _auth_result "$_auth_result" - _access_token=$(echo "$_auth_result" | _json_decode | jq -r .access_token) + _regex=".*\"access_token\":\"\([-._0-9A-Za-z]*\)\".*$" + _debug _regex "$_regex" + _access_token=$(echo "$_auth_result" | _json_decode | sed -n "s/$_regex/\1/p") _info "Uploading certificate and key to CleverReach" From aa85d0ffeba66fd438a2f1d5312b919e731cb8be Mon Sep 17 00:00:00 2001 From: Ed Lynes Date: Wed, 28 Oct 2020 09:05:14 -0400 Subject: [PATCH 075/383] trigger commit --- dnsapi/dns_edgedns.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_edgedns.sh b/dnsapi/dns_edgedns.sh index 05c8e886..1b3996cf 100755 --- a/dnsapi/dns_edgedns.sh +++ b/dnsapi/dns_edgedns.sh @@ -8,7 +8,7 @@ # Values to export: # --EITHER-- -# *** NOT IMPLEMENTED YET *** +# *** TBD. NOT IMPLEMENTED YET *** # specify Edgegrid credentials file and section # AKAMAI_EDGERC= # AKAMAI_EDGERC_SECTION="default" From df60a2248a6ce4f1f3c7675be0305feb3b88cf7d Mon Sep 17 00:00:00 2001 From: Ed Lynes Date: Wed, 28 Oct 2020 15:20:24 -0400 Subject: [PATCH 076/383] fix typo --- dnsapi/dns_edgedns.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_edgedns.sh b/dnsapi/dns_edgedns.sh index 1b3996cf..8ed6e5d2 100755 --- a/dnsapi/dns_edgedns.sh +++ b/dnsapi/dns_edgedns.sh @@ -242,7 +242,7 @@ _EDGEDNS_getZoneInfo() { _err "$(printf "Fatal error: acme API function call : %s" "$retVal")" fi if [ "$curResult" != "404" ]; then - err "$(printf "Managed zone validation failed. Error response: %s" "$retVal")" + _err "$(printf "Managed zone validation failed. Error response: %s" "$retVal")" return 1 fi fi From 7cc30c268b6c1f79be55fa3a8d31ec50892a4a78 Mon Sep 17 00:00:00 2001 From: ma331 <59875686+ma331@users.noreply.github.com> Date: Thu, 29 Oct 2020 11:14:44 +0100 Subject: [PATCH 077/383] Script to use with Anexia CloudDNS --- dnsapi/dns_anx.sh | 157 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 dnsapi/dns_anx.sh diff --git a/dnsapi/dns_anx.sh b/dnsapi/dns_anx.sh new file mode 100644 index 00000000..9865adc2 --- /dev/null +++ b/dnsapi/dns_anx.sh @@ -0,0 +1,157 @@ +#!/usr/bin/env sh + +#ANX_Token="xxxx" + +ANX_API='https://engine.anexia-it.com/api/clouddns/v1' + +######## Public functions ##################### + +dns_anx_add() { + fulldomain=$1 + txtvalue=$2 + + _info "Using ANX CDNS API" + + ANX_Token="${ANX_Token:-$(_readaccountconf_mutable ANX_Token)}" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + if [ "$ANX_Token" ]; then + _saveaccountconf_mutable ANX_Token "$ANX_Token" + else + _err "You didn't specify a ANEXIA Engine API token." + return 1 + fi + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + # Always add records, wildcard need two records with the same name + _anx_rest POST "zone.json/${_domain}/records" "{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"rdata\":\"$txtvalue\"}" + if _contains "$response" "$txtvalue"; then + return 0 + else + return 1 + fi +} + +dns_anx_rm() { + fulldomain=$1 + txtvalue=$2 + + _info "Using ANX CDNS API" + + ANX_Token="${ANX_Token:-$(_readaccountconf_mutable ANX_Token)}" + + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + _get_record_id + + if _is_uuid "$_record_id"; then + if ! _anx_rest DELETE "zone.json/${_domain}/records/$_record_id"; then + _err "Delete record" + return 1 + fi + else + _info "No record found." + fi + echo "$response" | tr -d " " | grep \"status\":\"OK\" >/dev/null +} + +#################### Private functions below ################################## + +_is_uuid() { + pattern='^\{?[A-Z0-9a-z]{8}-[A-Z0-9a-z]{4}-[A-Z0-9a-z]{4}-[A-Z0-9a-z]{4}-[A-Z0-9a-z]{12}\}?$' + if echo "$1" | _egrep_o "$pattern" >/dev/null; then + return 0 + fi + return 1 +} + +_get_record_id() { + _debug subdomain "$_sub_domain" + _debug domain "$_domain" + + if _anx_rest GET "zone.json/${_domain}/records?name=$_sub_domain&type=TXT"; then + _debug response "$response" + if _contains "$response" "\"name\":\"$_sub_domain\"" >/dev/null; then + _record_id=$(printf "%s\n" "$response" | _egrep_o "\[.\"identifier\":\"[^\"]*\"" | head -n 1 | cut -d : -f 2 | tr -d \") + else + _record_id='' + fi + else + _err "Search existing record" + fi +} + +_anx_rest() { + m=$1 + ep="$2" + data="$3" + _debug "$ep" + + export _H1="Content-Type: application/json" + export _H2="Authorization: Token $ANX_Token" + + if [ "$m" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "${ANX_API}/$ep" "" "$m")" + else + response="$(_get "${ANX_API}/$ep")" + fi + + # shellcheck disable=SC2181 + if [ "$?" != "0" ]; then + _err "error $ep" + return 1 + fi + _debug response "$response" + return 0 +} + + +#_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 + + # Does a zone with that name exist? + _anx_rest GET "zone.json/$h" + # shellcheck disable=SC2154 + if [ "$code" -ne 200 ]; then + continue + 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 +} From fe54d5b8aeef06a7244e08c380af68eaea9884bc Mon Sep 17 00:00:00 2001 From: ma331 <59875686+ma331@users.noreply.github.com> Date: Thu, 29 Oct 2020 12:51:49 +0100 Subject: [PATCH 078/383] fixed spacing in two lines --- dnsapi/dns_anx.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_anx.sh b/dnsapi/dns_anx.sh index 9865adc2..66430d3e 100644 --- a/dnsapi/dns_anx.sh +++ b/dnsapi/dns_anx.sh @@ -19,8 +19,8 @@ dns_anx_add() { if [ "$ANX_Token" ]; then _saveaccountconf_mutable ANX_Token "$ANX_Token" else - _err "You didn't specify a ANEXIA Engine API token." - return 1 + _err "You didn't specify a ANEXIA Engine API token." + return 1 fi _debug "First detect the root zone" From bc62d49fc900e2f5b31881e02c432433435ae245 Mon Sep 17 00:00:00 2001 From: ma331 <59875686+ma331@users.noreply.github.com> Date: Thu, 29 Oct 2020 13:04:29 +0100 Subject: [PATCH 079/383] removed empty line to make shfmt happy --- dnsapi/dns_anx.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_anx.sh b/dnsapi/dns_anx.sh index 66430d3e..b84fac8c 100644 --- a/dnsapi/dns_anx.sh +++ b/dnsapi/dns_anx.sh @@ -119,7 +119,6 @@ _anx_rest() { return 0 } - #_acme-challenge.www.domain.com #returns # _sub_domain=_acme-challenge.www From 92bbdce4351028909e83c189dc77ab313b3684d4 Mon Sep 17 00:00:00 2001 From: ma331 <59875686+ma331@users.noreply.github.com> Date: Thu, 29 Oct 2020 13:35:53 +0100 Subject: [PATCH 080/383] changed comment --- dnsapi/dns_anx.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/dnsapi/dns_anx.sh b/dnsapi/dns_anx.sh index b84fac8c..027f6820 100644 --- a/dnsapi/dns_anx.sh +++ b/dnsapi/dns_anx.sh @@ -1,5 +1,6 @@ #!/usr/bin/env sh +### Anexia CloudDNS acme.sh hook #ANX_Token="xxxx" ANX_API='https://engine.anexia-it.com/api/clouddns/v1' From 812333e9aef404d3b5e7b5f0cdfa935b20c3895c Mon Sep 17 00:00:00 2001 From: ma331 <59875686+ma331@users.noreply.github.com> Date: Thu, 29 Oct 2020 14:01:08 +0100 Subject: [PATCH 081/383] Changed comment once more --- dnsapi/dns_anx.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_anx.sh b/dnsapi/dns_anx.sh index 027f6820..8c46e405 100644 --- a/dnsapi/dns_anx.sh +++ b/dnsapi/dns_anx.sh @@ -1,6 +1,8 @@ #!/usr/bin/env sh -### Anexia CloudDNS acme.sh hook +# Anexia CloudDNS acme.sh hook +# Author: MA + #ANX_Token="xxxx" ANX_API='https://engine.anexia-it.com/api/clouddns/v1' From d58fb2bbc01f8d2596c5365db9e644d1fc99773a Mon Sep 17 00:00:00 2001 From: ma331 <59875686+ma331@users.noreply.github.com> Date: Fri, 30 Oct 2020 14:13:32 +0100 Subject: [PATCH 082/383] Speedup for _get_root function --- dnsapi/dns_anx.sh | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/dnsapi/dns_anx.sh b/dnsapi/dns_anx.sh index 8c46e405..c1a1130a 100644 --- a/dnsapi/dns_anx.sh +++ b/dnsapi/dns_anx.sh @@ -122,15 +122,13 @@ _anx_rest() { return 0 } -#_acme-challenge.www.domain.com -#returns -# _sub_domain=_acme-challenge.www -# _domain=domain.com _get_root() { domain=$1 i=1 p=1 + _anx_rest GET "zone.json" + while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug h "$h" @@ -139,13 +137,6 @@ _get_root() { return 1 fi - # Does a zone with that name exist? - _anx_rest GET "zone.json/$h" - # shellcheck disable=SC2154 - if [ "$code" -ne 200 ]; then - continue - fi - if _contains "$response" "\"name\":\"$h\""; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain=$h From cc40110d7e339fe2d314776142266bda7d870ba5 Mon Sep 17 00:00:00 2001 From: Ed Lynes Date: Fri, 30 Oct 2020 13:12:45 -0400 Subject: [PATCH 083/383] refactored sig timestamp generation --- dnsapi/dns_edgedns.sh | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_edgedns.sh b/dnsapi/dns_edgedns.sh index 8ed6e5d2..7c47cc0b 100755 --- a/dnsapi/dns_edgedns.sh +++ b/dnsapi/dns_edgedns.sh @@ -41,6 +41,7 @@ dns_edgedns_add() { _err "Invalid domain" return 1 fi + _debug2 "Add: zone" "$zone" acmeRecordURI=$(printf "%s/%s/names/%s/types/TXT" "$edge_endpoint" "$zone" "$fulldomain") _debug3 "Add URL" "$acmeRecordURI" @@ -354,19 +355,31 @@ _edgedns_rest() { } _edgedns_eg_timestamp() { - _eg_timestamp=$(date -u "+%Y%m%dT%H:%M:%S+0000") - _debug3 "_eg_timestamp" "$_eg_timestamp" + _debug "Generating signature Timestamp" + _debug3 "Retriving ntp time" + _timeheaders="$(_get "https://www.ntp.org" "onlyheader")" + _debug3 "_timeheaders" "$_timeheaders" + _ntpdate="$(echo "$_timeheaders" | grep -i "Date:" | _head_n 1 | cut -d ':' -f 2- | tr -d "\r\n")" + _debug3 "_ntpdate" "$_ntpdate" + _ntpdate="$(echo "${_ntpdate}" | sed -e 's/^[[:space:]]*//')" + _debug3 "_NTPDATE" "$_ntpdate" + _ntptime="$(echo "${_ntpdate}" | _head_n 1 | cut -d " " -f 5 | tr -d "\r\n")" + _debug3 "_ntptime" "$_ntptime" + _eg_timestamp=$(date -u "+%Y%m%dT") + _eg_timestamp="$(printf "%s%s+0000" "$_eg_timestamp" "$_ntptime")" + _debug "_eg_timestamp" "$_eg_timestamp" } _edgedns_new_nonce() { + _debug "Generating Nonce" _nonce=$(echo "EDGEDNS$(_time)" | _digest sha1 hex | cut -c 1-32) _debug3 "_nonce" "$_nonce" } _edgedns_make_auth_header() { _debug "Constructing Auth Header" - _edgedns_eg_timestamp _edgedns_new_nonce + _edgedns_eg_timestamp # "Unsigned authorization header: 'EG1-HMAC-SHA256 client_token=block;access_token=block;timestamp=20200806T14:16:33+0000;nonce=72cde72c-82d9-4721-9854-2ba057929d67;'" _auth_header="$(printf "EG1-HMAC-SHA256 client_token=%s;access_token=%s;timestamp=%s;nonce=%s;" "$AKAMAI_CLIENT_TOKEN" "$AKAMAI_ACCESS_TOKEN" "$_eg_timestamp" "$_nonce")" _secure_debug2 "Unsigned Auth Header: " "$_auth_header" From 9fcd1040650b80e2799e048e7089882f48a804a7 Mon Sep 17 00:00:00 2001 From: Sergey Pashinin Date: Mon, 2 Nov 2020 13:35:12 +0300 Subject: [PATCH 084/383] Use _getdeployconf for env vars --- deploy/vault.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deploy/vault.sh b/deploy/vault.sh index c51ceb0f..e742b0fb 100644 --- a/deploy/vault.sh +++ b/deploy/vault.sh @@ -31,11 +31,13 @@ vault_deploy() { _debug _cfullchain "$_cfullchain" # validate required env vars + _getdeployconf VAULT_PREFIX if [ -z "$VAULT_PREFIX" ]; then _err "VAULT_PREFIX needs to be defined (contains prefix path in vault)" return 1 fi + _getdeployconf VAULT_ADDR if [ -z "$VAULT_ADDR" ]; then _err "VAULT_ADDR needs to be defined (contains vault connection address)" return 1 From e203e9837577cf2b8f976baf19a29a1ed1ef2654 Mon Sep 17 00:00:00 2001 From: Sergey Pashinin Date: Mon, 2 Nov 2020 16:46:09 +0300 Subject: [PATCH 085/383] Use _savedeployconf --- deploy/vault.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deploy/vault.sh b/deploy/vault.sh index e742b0fb..70c80444 100644 --- a/deploy/vault.sh +++ b/deploy/vault.sh @@ -36,12 +36,14 @@ vault_deploy() { _err "VAULT_PREFIX needs to be defined (contains prefix path in vault)" return 1 fi + _savedeployconf VAULT_PREFIX "$VAULT_PREFIX" _getdeployconf VAULT_ADDR if [ -z "$VAULT_ADDR" ]; then _err "VAULT_ADDR needs to be defined (contains vault connection address)" return 1 fi + _savedeployconf VAULT_ADDR "$VAULT_ADDR" # JSON does not allow multiline strings. # So replacing new-lines with "\n" here From 075dc1e4e95f3668eeee94ad916a3e7142e7282e Mon Sep 17 00:00:00 2001 From: MaxPeal <30347730+MaxPeal@users.noreply.github.com> Date: Thu, 5 Nov 2020 01:25:07 +0100 Subject: [PATCH 086/383] add linux/ppc64le and linux/s390x --- .github/workflows/dockerhub.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dockerhub.yml b/.github/workflows/dockerhub.yml index 92308218..89915af7 100644 --- a/.github/workflows/dockerhub.yml +++ b/.github/workflows/dockerhub.yml @@ -63,4 +63,4 @@ jobs: --tag ${DOCKER_IMAGE}:${DOCKER_IMAGE_TAG} \ --output "type=image,push=true" \ --build-arg AUTO_UPGRADE=${AUTO_UPGRADE} \ - --platform linux/arm64/v8,linux/amd64,linux/arm/v6,linux/arm/v7,linux/386 . + --platform linux/arm64/v8,linux/amd64,linux/arm/v6,linux/arm/v7,linux/386,linux/ppc64le,linux/s390x . From 7530266330afcf09f2cebfc8b8775dec5dbe8f03 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 9 Nov 2020 20:14:22 +0800 Subject: [PATCH 087/383] remove dependency to md5 and awk --- deploy/fritzbox.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index 21ea6cfd..89b19806 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -64,9 +64,9 @@ fritzbox_deploy() { _info "Log in to the FRITZ!Box" _fritzbox_challenge="$(_get "${_fritzbox_url}/login_sid.lua" | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" if _exists iconv; then - _fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" + _fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | iconv -f ASCII -t UTF16LE | _digest md5 hex)" else - _fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | perl -p -e 'use Encode qw/encode/; print encode("UTF-16LE","$_"); $_="";' | md5sum | awk '{print $1}')" + _fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | perl -p -e 'use Encode qw/encode/; print encode("UTF-16LE","$_"); $_="";' | _digest md5 hex)" fi _fritzbox_sid="$(_get "${_fritzbox_url}/login_sid.lua?sid=0000000000000000&username=${_fritzbox_username}&response=${_fritzbox_challenge}-${_fritzbox_hash}" | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" From d866b3df1f1342794e428975e489a7a942ab6941 Mon Sep 17 00:00:00 2001 From: Ed Lynes Date: Mon, 9 Nov 2020 10:16:57 -0500 Subject: [PATCH 088/383] convert key to hex before calling _hmac --- dnsapi/dns_edgedns.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_edgedns.sh b/dnsapi/dns_edgedns.sh index 7c47cc0b..3b9e0032 100755 --- a/dnsapi/dns_edgedns.sh +++ b/dnsapi/dns_edgedns.sh @@ -443,7 +443,9 @@ _edgedns_base64_hmac_sha256() { _secure_debug2 "encoded data" "$encoded_data" _secure_debug2 "encoded key" "$encoded_key" - data_sig="$(echo "$encoded_data" | tr -d "\n\r" | ${ACME_OPENSSL_BIN:-openssl} dgst -sha256 -hmac "$encoded_key" -binary | _base64)" + encoded_key_hex=$(printf "%s" "$encoded_key" | _hex_dump | tr -d ' ') + data_sig="$(echo "$encoded_data" | tr -d "\n\r" | _hmac sha256 $encoded_key_hex | _base64)" + _secure_debug2 "data_sig:" "$data_sig" _hmac_out="$(echo "$data_sig" | tr -d "\n\r" | iconv -f utf-8)" _secure_debug2 "hmac" "$_hmac_out" From c490dd1563d9d069221a0bcf946722cb9a5038a0 Mon Sep 17 00:00:00 2001 From: Ed Lynes Date: Mon, 9 Nov 2020 10:36:12 -0500 Subject: [PATCH 089/383] add quotes to resolve shell check failure --- dnsapi/dns_edgedns.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_edgedns.sh b/dnsapi/dns_edgedns.sh index 3b9e0032..2e5c7d30 100755 --- a/dnsapi/dns_edgedns.sh +++ b/dnsapi/dns_edgedns.sh @@ -444,7 +444,7 @@ _edgedns_base64_hmac_sha256() { _secure_debug2 "encoded key" "$encoded_key" encoded_key_hex=$(printf "%s" "$encoded_key" | _hex_dump | tr -d ' ') - data_sig="$(echo "$encoded_data" | tr -d "\n\r" | _hmac sha256 $encoded_key_hex | _base64)" + data_sig="$(echo "$encoded_data" | tr -d "\n\r" | _hmac sha256 "$encoded_key_hex" | _base64)" _secure_debug2 "data_sig:" "$data_sig" _hmac_out="$(echo "$data_sig" | tr -d "\n\r" | iconv -f utf-8)" From a077132d825e6176add7b87f3abf66f81fe48b7f Mon Sep 17 00:00:00 2001 From: tsoybe <51762970+tsoybe@users.noreply.github.com> Date: Thu, 12 Nov 2020 22:04:05 +0100 Subject: [PATCH 090/383] Update dns_desec.sh ttl must be greater than or equal 3600, see https://desec.readthedocs.io/en/latest/dns/domains.html#domain-object --- dnsapi/dns_desec.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_desec.sh b/dnsapi/dns_desec.sh index 61d080bd..a2e4d887 100644 --- a/dnsapi/dns_desec.sh +++ b/dnsapi/dns_desec.sh @@ -61,7 +61,7 @@ dns_desec_add() { fi _debug txtvalues "$txtvalues" _info "Adding record" - body="[{\"subname\":\"$_sub_domain\", \"type\":\"TXT\", \"records\":[$txtvalues], \"ttl\":60}]" + body="[{\"subname\":\"$_sub_domain\", \"type\":\"TXT\", \"records\":[$txtvalues], \"ttl\":3600}]" if _desec_rest PUT "$REST_API/$DEDYN_NAME/rrsets/" "$body"; then if _contains "$response" "$txtvalue"; then From 7dfc5a78bae3f4da640c3cb53b3eedd588c04837 Mon Sep 17 00:00:00 2001 From: tsoybe <51762970+tsoybe@users.noreply.github.com> Date: Thu, 12 Nov 2020 22:09:31 +0100 Subject: [PATCH 091/383] Update dns_desec.sh Deletion to --- dnsapi/dns_desec.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_desec.sh b/dnsapi/dns_desec.sh index a2e4d887..f64660a8 100644 --- a/dnsapi/dns_desec.sh +++ b/dnsapi/dns_desec.sh @@ -130,7 +130,7 @@ dns_desec_rm() { _debug txtvalues "$txtvalues" _info "Deleting record" - body="[{\"subname\":\"$_sub_domain\", \"type\":\"TXT\", \"records\":[$txtvalues], \"ttl\":60}]" + body="[{\"subname\":\"$_sub_domain\", \"type\":\"TXT\", \"records\":[$txtvalues], \"ttl\":3600}]" _desec_rest PUT "$REST_API/$DEDYN_NAME/rrsets/" "$body" if [ "$_code" = "200" ]; then _info "Deleted, OK" From b19cb0805cfe72aec1cea8b1f4fc9e5921cf0d4e Mon Sep 17 00:00:00 2001 From: jakelamotta Date: Tue, 17 Nov 2020 13:19:55 +0100 Subject: [PATCH 092/383] Adds dnsapi support for Simply.com --- dnsapi/dns_simply.sh | 240 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100644 dnsapi/dns_simply.sh diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh new file mode 100644 index 00000000..25dd9ff3 --- /dev/null +++ b/dnsapi/dns_simply.sh @@ -0,0 +1,240 @@ +#!/usr/bin/env sh + +# +#SIMPLY_AccountName="accountname" +# +#SIMPLY_ApiKey="apikey" +# +#SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]" + +SIMPLY_Api="https://api.simply.com/1" +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_simply_add() { + fulldomain=$1 + txtvalue=$2 + + if ! _simply_load_config; then + return 1 + fi + + _simply_save_config + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _info "Adding record" + + if ! _simply_add_record "$_domain" "$_sub_domain" "$txtvalue"; then + _err "Could not add DNS record" + return 1 + fi + + return 0 +} + +dns_simply_rm() { + fulldomain=$1 + txtvalue=$2 + + if ! _simply_load_config; then + return 1 + fi + + _simply_save_config + + _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 "$txtvalue" + + _debug "Getting existing records" + + if ! _simply_get_all_records "$_domain"; then + _err "invalid domain" + return 1 + fi + + records=$(echo "$response" | tr '{' "\n" | grep 'record_id\|type\|data\|\name' | sed 's/\"record_id/;\"record_id/') + record_array=(`echo $records |tr -d ' ' | tr ';' ' '`) + nr_of_deleted_records=0 + + for (( i=0; i<=${#record_array[@]}; i++ )); do + + record="${record_array[$i]}" + + if [[ "$record" == *"$txtvalue"* && "$record" == *"TXT"* ]]; then + + _info "Deleting record: $record" + + record_id=`echo $record | cut -d "," -f 1 | grep "record_id" | cut -d ":" -f 2` + + if [[ $record_id -gt 0 ]]; then + + if ! _simply_delete_record "$_domain" "$_sub_domain" "$record_id"; then + _err "Record with id $record_id could not be deleted" + return 1 + fi + + nr_of_deleted_records=1 + break + else + _err "Fetching record_id could not be done, this should not happen, exiting function. Failing record is $record" + break + fi + fi + + done + + if [[ $nr_of_deleted_records -eq 0 ]]; then + _err "No record deleted, the DNS record needs to be removed manually." + else + _info "Deleted $nr_of_deleted_records record" + fi + + return 0 +} + +#################### Private functions below ################################## + +_simply_load_config() { + SIMPLY_Api="${SIMPLY_Api:-$(_readaccountconf_mutable SIMPLY_Api)}" + SIMPLY_AccountName="${SIMPLY_AccountName:-$(_readaccountconf_mutable SIMPLY_AccountName)}" + SIMPLY_ApiKey="${SIMPLY_ApiKey:-$(_readaccountconf_mutable SIMPLY_ApiKey)}" + + if [ -z "$SIMPLY_Api" ]; then + SIMPLY_Api="$SIMPLY_Api_Default" + fi + + if [ -z "$SIMPLY_AccountName" ] || [ -z "$SIMPLY_ApiKey" ]; then + SIMPLY_AccountName="" + SIMPLY_ApiKey="" + + _err "A valid Simply API account and apikey not provided." + _err "Please provide a valid API user and try again." + + return 1 + fi + + return 0 +} + +_simply_save_config() { + if [ "$SIMPLY_Api" != "$SIMPLY_Api_Default" ]; then + _saveaccountconf_mutable SIMPLY_Api "$SIMPLY_Api" + fi + _saveaccountconf_mutable SIMPLY_AccountName "$SIMPLY_AccountName" + _saveaccountconf_mutable SIMPLY_ApiKey "$SIMPLY_ApiKey" +} + +_simply_get_all_records() { + domain=$1 + + if ! _simply_rest GET "my/products/$domain/dns/records"; then + return 1 + fi + + return 0 +} + +_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 + + if ! _simply_rest GET "my/products/$h/dns"; then + return 1 + fi + + if _contains "$response" '"code":"NOT_FOUND"'; then + _debug "$h not found" + else + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain="$h" + return 0 + fi + p="$i" + i=$(_math "$i" + 1) + done + return 1 +} + +_simply_add_record() { + domain=$1 + sub_domain=$2 + txtval=$3 + + data="{\"name\": \"$sub_domain\", \"type\":\"TXT\", \"data\": \"$txtval\", \"priority\":0, \"ttl\": 3600}" + + if ! _simply_rest POST "my/products/$domain/dns/records" "$data"; then + _err "Adding record not successfull!" + return 1 + fi + + return 0 +} + +_simply_delete_record() { + domain=$1 + sub_domain=$2 + record_id=$3 + + _debug "Delete record with id $record_id" + + if ! _simply_rest DELETE "my/products/$domain/dns/records/$record_id"; then + _err "Deleting record not successfull!" + return 1 + fi + + return 0 +} + +_simply_rest() { + m=$1 + ep="$2" + data="$3" + + _debug "Data: $data" + _debug "Methodcall: $ep" + _debug "Call type: $m" + + export _H1="Content-Type: application/json" + + if [ "$m" != "GET" ]; then + response="$(_post "$data" "$SIMPLY_Api/$SIMPLY_AccountName/$SIMPLY_ApiKey/$ep" "" "$m")" + else + response="$(_get "$SIMPLY_Api/$SIMPLY_AccountName/$SIMPLY_ApiKey/$ep")" + fi + + if [ "$?" != "0" ]; then + _err "error $ep" + return 1 + fi + + _debug2 response "$response" + + if _contains "$response" "Invalid account authorization"; then + _err "It seems that your api key or accountnumber is not correct." + return 1 + fi + return 0 +} From bcc1b7b48a1c848bf675e1757f896f7a18a7776e Mon Sep 17 00:00:00 2001 From: jakelamotta Date: Tue, 17 Nov 2020 13:49:32 +0100 Subject: [PATCH 093/383] Fix comments --- dnsapi/dns_simply.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index 25dd9ff3..3914e1ab 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -59,7 +59,7 @@ dns_simply_rm() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - _debug "$txtvalue" + _debug txtvalue "$txtvalue" _debug "Getting existing records" @@ -78,9 +78,9 @@ dns_simply_rm() { if [[ "$record" == *"$txtvalue"* && "$record" == *"TXT"* ]]; then - _info "Deleting record: $record" - record_id=`echo $record | cut -d "," -f 1 | grep "record_id" | cut -d ":" -f 2` + + _info "Deleting record $record" if [[ $record_id -gt 0 ]]; then @@ -198,7 +198,7 @@ _simply_delete_record() { sub_domain=$2 record_id=$3 - _debug "Delete record with id $record_id" + _debug record_id "Delete record with id $record_id" if ! _simply_rest DELETE "my/products/$domain/dns/records/$record_id"; then _err "Deleting record not successfull!" @@ -213,9 +213,9 @@ _simply_rest() { ep="$2" data="$3" - _debug "Data: $data" - _debug "Methodcall: $ep" - _debug "Call type: $m" + _debug2 data "$data" + _debug2 ep "$ep" + _debug2 m "$m" export _H1="Content-Type: application/json" From c60613fbcbea3c9518df45ff6ec99ef5de5266f4 Mon Sep 17 00:00:00 2001 From: jakelamotta Date: Tue, 17 Nov 2020 14:20:45 +0100 Subject: [PATCH 094/383] Fix indentation and added some debug messages --- dnsapi/dns_simply.sh | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index 3914e1ab..8fb56585 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -61,7 +61,7 @@ dns_simply_rm() { _debug _domain "$_domain" _debug txtvalue "$txtvalue" - _debug "Getting existing records" + _info "Getting all existing records" if ! _simply_get_all_records "$_domain"; then _err "invalid domain" @@ -71,31 +71,34 @@ dns_simply_rm() { records=$(echo "$response" | tr '{' "\n" | grep 'record_id\|type\|data\|\name' | sed 's/\"record_id/;\"record_id/') record_array=(`echo $records |tr -d ' ' | tr ';' ' '`) nr_of_deleted_records=0 + + _info "Fetching txt record.." for (( i=0; i<=${#record_array[@]}; i++ )); do - record="${record_array[$i]}" + record="${record_array[$i]}" + _debug record "$record" - if [[ "$record" == *"$txtvalue"* && "$record" == *"TXT"* ]]; then + if [[ "$record" == *"$txtvalue"* && "$record" == *"TXT"* ]]; then - record_id=`echo $record | cut -d "," -f 1 | grep "record_id" | cut -d ":" -f 2` + record_id=`echo $record | cut -d "," -f 1 | grep "record_id" | cut -d ":" -f 2` - _info "Deleting record $record" + _info "Deleting record $record" - if [[ $record_id -gt 0 ]]; then + if [[ $record_id -gt 0 ]]; then - if ! _simply_delete_record "$_domain" "$_sub_domain" "$record_id"; then - _err "Record with id $record_id could not be deleted" - return 1 - fi + if ! _simply_delete_record "$_domain" "$_sub_domain" "$record_id"; then + _err "Record with id $record_id could not be deleted" + return 1 + fi - nr_of_deleted_records=1 - break - else - _err "Fetching record_id could not be done, this should not happen, exiting function. Failing record is $record" - break + nr_of_deleted_records=1 + break + else + _err "Fetching record_id could not be done, this should not happen, exiting function. Failing record is $record" + break + fi fi - fi done From 6ee38ceaba06e3ba9da63bb480f4b53cc4c76aa5 Mon Sep 17 00:00:00 2001 From: neil Date: Tue, 17 Nov 2020 22:50:40 +0800 Subject: [PATCH 095/383] fix https://github.com/acmesh-official/acme.sh/issues/3252 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 3be3849d..456383bd 100755 --- a/acme.sh +++ b/acme.sh @@ -3993,7 +3993,7 @@ _check_dns_entries() { #file _get_cert_issuers() { _cfile="$1" - if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7"; then + if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 else ${ACME_OPENSSL_BIN:-openssl} x509 -in $_cfile -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 From c349e9aabe5a3affa35d8c18292427edb0067b9d Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 18 Nov 2020 21:19:10 +0800 Subject: [PATCH 096/383] fix set-env --- .github/workflows/LetsEncrypt.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 5f0bba72..c4d3167c 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -88,7 +88,7 @@ jobs: shell: cmd - name: Set ENV run: | - echo '::set-env name=PATH::C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin' + echo "PATH=C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin" >> $GITHUB_ENV - name: Clone acmetest shell: cmd run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ From 6cf0eb9e1d5b8f831c44b93adfcb8b9d5fe1d405 Mon Sep 17 00:00:00 2001 From: jakelamotta Date: Wed, 18 Nov 2020 14:52:32 +0100 Subject: [PATCH 097/383] Fix CI-errors --- dnsapi/dns_simply.sh | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index 8fb56585..9deceb25 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -7,7 +7,7 @@ # #SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]" -SIMPLY_Api="https://api.simply.com/1" +SIMPLY_Api_Default="https://api.simply.com/1" ######## Public functions ##################### #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" @@ -22,6 +22,7 @@ dns_simply_add() { _simply_save_config _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then _err "invalid domain" return 1 @@ -69,23 +70,28 @@ dns_simply_rm() { fi records=$(echo "$response" | tr '{' "\n" | grep 'record_id\|type\|data\|\name' | sed 's/\"record_id/;\"record_id/') - record_array=(`echo $records |tr -d ' ' | tr ';' ' '`) + record_array=$(echo $records |tr -d ' ' | tr ';' ' ') + nr_of_deleted_records=0 - - _info "Fetching txt record.." + _info "Fetching txt record" - for (( i=0; i<=${#record_array[@]}; i++ )); do - - record="${record_array[$i]}" + for record in $record_array; do _debug record "$record" + + record_data=$(echo $record | cut -d "," -f 3 | sed 's/"//g' | grep "data" | cut -d ":" -f 2) + record_type=$(echo $record | cut -d "," -f 4 | sed 's/"//g' | grep "type" | cut -d ":" -f 2) + + _debug2 record_data "$record_data" + _debug2 record_type "$record_type" + + if [ "$record_data" = "$txtvalue" ] && [ "$record_type" = "TXT" ]; then - if [[ "$record" == *"$txtvalue"* && "$record" == *"TXT"* ]]; then - - record_id=`echo $record | cut -d "," -f 1 | grep "record_id" | cut -d ":" -f 2` + record_id=$(echo $record | cut -d "," -f 1 | grep "record_id" | cut -d ":" -f 2) _info "Deleting record $record" - - if [[ $record_id -gt 0 ]]; then + _debug2 record_id "$record_id" + + if [ "$record_id" -gt 0 ]; then if ! _simply_delete_record "$_domain" "$_sub_domain" "$record_id"; then _err "Record with id $record_id could not be deleted" @@ -102,7 +108,7 @@ dns_simply_rm() { done - if [[ $nr_of_deleted_records -eq 0 ]]; then + if [ "$nr_of_deleted_records" -eq 0 ]; then _err "No record deleted, the DNS record needs to be removed manually." else _info "Deleted $nr_of_deleted_records record" From b20d8f195ba879c4af5f35f2910541d8bbf58383 Mon Sep 17 00:00:00 2001 From: jakelamotta Date: Wed, 18 Nov 2020 15:12:22 +0100 Subject: [PATCH 098/383] Add double quotes to variables --- dnsapi/dns_simply.sh | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index 9deceb25..30211f7a 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -69,26 +69,25 @@ dns_simply_rm() { return 1 fi - records=$(echo "$response" | tr '{' "\n" | grep 'record_id\|type\|data\|\name' | sed 's/\"record_id/;\"record_id/') - record_array=$(echo $records |tr -d ' ' | tr ';' ' ') + records=$(echo "$response" | tr '{' "\n" | grep 'record_id\|type\|data\|\name' | sed 's/\"record_id/;\"record_id/' | tr "\n" ' '| tr -d ' ' | tr ';' ' ') nr_of_deleted_records=0 _info "Fetching txt record" - for record in $record_array; do + for record in $records; do _debug record "$record" - record_data=$(echo $record | cut -d "," -f 3 | sed 's/"//g' | grep "data" | cut -d ":" -f 2) - record_type=$(echo $record | cut -d "," -f 4 | sed 's/"//g' | grep "type" | cut -d ":" -f 2) + record_data=$(echo "$record" | cut -d "," -f 3 | sed 's/"//g' | grep "data" | cut -d ":" -f 2) + record_type=$(echo "$record" | cut -d "," -f 4 | sed 's/"//g' | grep "type" | cut -d ":" -f 2) _debug2 record_data "$record_data" _debug2 record_type "$record_type" if [ "$record_data" = "$txtvalue" ] && [ "$record_type" = "TXT" ]; then - record_id=$(echo $record | cut -d "," -f 1 | grep "record_id" | cut -d ":" -f 2) + record_id=$(echo "$record" | cut -d "," -f 1 | grep "record_id" | cut -d ":" -f 2) - _info "Deleting record $record" + _info "Deleting record $record" _debug2 record_id "$record_id" if [ "$record_id" -gt 0 ]; then From 2b8561f27d2376f4e7b1a8f45783e62227cadf35 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 18 Nov 2020 22:23:36 +0800 Subject: [PATCH 099/383] fix set-env --- .github/workflows/DNS.yml | 2 +- .github/workflows/LetsEncrypt.yml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index b7153506..c41851b8 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -144,7 +144,7 @@ jobs: shell: cmd - name: Set ENV run: | - echo '::set-env name=PATH::C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin' + echo "PATH=C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin" >> $GITHUB_ENV - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - name: Run acmetest diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index c4d3167c..b5468ff6 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -89,6 +89,9 @@ jobs: - name: Set ENV run: | echo "PATH=C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin" >> $GITHUB_ENV + - name: Check ENV + run: | + echo "PATH=$PATH" - name: Clone acmetest shell: cmd run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ From 6ef66399f8accca401e0c55d24cb74624617bea6 Mon Sep 17 00:00:00 2001 From: jakelamotta Date: Wed, 18 Nov 2020 15:37:26 +0100 Subject: [PATCH 100/383] Removed spaces on empty lines --- dnsapi/dns_simply.sh | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index 30211f7a..6f2464ef 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -21,8 +21,7 @@ dns_simply_add() { _simply_save_config - _debug "First detect the root zone" - + _debug "First detect the root zone" if ! _get_root "$fulldomain"; then _err "invalid domain" return 1 @@ -36,8 +35,7 @@ dns_simply_add() { if ! _simply_add_record "$_domain" "$_sub_domain" "$txtvalue"; then _err "Could not add DNS record" return 1 - fi - + fi return 0 } @@ -126,7 +124,7 @@ _simply_load_config() { if [ -z "$SIMPLY_Api" ]; then SIMPLY_Api="$SIMPLY_Api_Default" fi - + if [ -z "$SIMPLY_AccountName" ] || [ -z "$SIMPLY_ApiKey" ]; then SIMPLY_AccountName="" SIMPLY_ApiKey="" @@ -149,8 +147,8 @@ _simply_save_config() { } _simply_get_all_records() { - domain=$1 - + domain=$1 + if ! _simply_rest GET "my/products/$domain/dns/records"; then return 1 fi @@ -190,14 +188,14 @@ _simply_add_record() { domain=$1 sub_domain=$2 txtval=$3 - + data="{\"name\": \"$sub_domain\", \"type\":\"TXT\", \"data\": \"$txtval\", \"priority\":0, \"ttl\": 3600}" if ! _simply_rest POST "my/products/$domain/dns/records" "$data"; then _err "Adding record not successfull!" return 1 fi - + return 0 } @@ -205,14 +203,14 @@ _simply_delete_record() { domain=$1 sub_domain=$2 record_id=$3 - + _debug record_id "Delete record with id $record_id" - + if ! _simply_rest DELETE "my/products/$domain/dns/records/$record_id"; then _err "Deleting record not successfull!" return 1 fi - + return 0 } @@ -220,7 +218,7 @@ _simply_rest() { m=$1 ep="$2" data="$3" - + _debug2 data "$data" _debug2 ep "$ep" _debug2 m "$m" @@ -237,12 +235,13 @@ _simply_rest() { _err "error $ep" return 1 fi - + _debug2 response "$response" - + if _contains "$response" "Invalid account authorization"; then _err "It seems that your api key or accountnumber is not correct." return 1 fi + return 0 } From c7116d40caf9e3b9bc48e77b34bcc255b0609083 Mon Sep 17 00:00:00 2001 From: jakelamotta Date: Wed, 18 Nov 2020 15:46:16 +0100 Subject: [PATCH 101/383] Removes tabs and trailing spaces --- dnsapi/dns_simply.sh | 45 ++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index 6f2464ef..bf383019 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -21,28 +21,29 @@ dns_simply_add() { _simply_save_config - _debug "First detect the root zone" + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then _err "invalid domain" return 1 fi - + _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" _info "Adding record" - if ! _simply_add_record "$_domain" "$_sub_domain" "$txtvalue"; then + if ! _simply_add_record "$_domain" "$_sub_domain" "$txtvalue"; then _err "Could not add DNS record" return 1 - fi + fi return 0 } dns_simply_rm() { fulldomain=$1 txtvalue=$2 - + if ! _simply_load_config; then return 1 fi @@ -61,12 +62,12 @@ dns_simply_rm() { _debug txtvalue "$txtvalue" _info "Getting all existing records" - + if ! _simply_get_all_records "$_domain"; then _err "invalid domain" return 1 fi - + records=$(echo "$response" | tr '{' "\n" | grep 'record_id\|type\|data\|\name' | sed 's/\"record_id/;\"record_id/' | tr "\n" ' '| tr -d ' ' | tr ';' ' ') nr_of_deleted_records=0 @@ -74,27 +75,27 @@ dns_simply_rm() { for record in $records; do _debug record "$record" - - record_data=$(echo "$record" | cut -d "," -f 3 | sed 's/"//g' | grep "data" | cut -d ":" -f 2) - record_type=$(echo "$record" | cut -d "," -f 4 | sed 's/"//g' | grep "type" | cut -d ":" -f 2) - - _debug2 record_data "$record_data" - _debug2 record_type "$record_type" - - if [ "$record_data" = "$txtvalue" ] && [ "$record_type" = "TXT" ]; then + record_data=$(echo "$record" | cut -d "," -f 3 | sed 's/"//g' | grep "data" | cut -d ":" -f 2) + record_type=$(echo "$record" | cut -d "," -f 4 | sed 's/"//g' | grep "type" | cut -d ":" -f 2) + + _debug2 record_data "$record_data" + _debug2 record_type "$record_type" + + if [ "$record_data" = "$txtvalue" ] && [ "$record_type" = "TXT" ]; then + record_id=$(echo "$record" | cut -d "," -f 1 | grep "record_id" | cut -d ":" -f 2) - + _info "Deleting record $record" _debug2 record_id "$record_id" - + if [ "$record_id" -gt 0 ]; then - + if ! _simply_delete_record "$_domain" "$_sub_domain" "$record_id"; then _err "Record with id $record_id could not be deleted" return 1 fi - + nr_of_deleted_records=1 break else @@ -102,7 +103,7 @@ dns_simply_rm() { break fi fi - + done if [ "$nr_of_deleted_records" -eq 0 ]; then @@ -110,7 +111,7 @@ dns_simply_rm() { else _info "Deleted $nr_of_deleted_records record" fi - + return 0 } @@ -242,6 +243,6 @@ _simply_rest() { _err "It seems that your api key or accountnumber is not correct." return 1 fi - + return 0 } From f90f8824bb6034d90c47e6dae7acad54ffa0a056 Mon Sep 17 00:00:00 2001 From: jakelamotta Date: Wed, 18 Nov 2020 15:52:46 +0100 Subject: [PATCH 102/383] Fix code style problems --- dnsapi/dns_simply.sh | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index bf383019..379f1b42 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -22,7 +22,6 @@ dns_simply_add() { _simply_save_config _debug "First detect the root zone" - if ! _get_root "$fulldomain"; then _err "invalid domain" return 1 @@ -68,19 +67,19 @@ dns_simply_rm() { return 1 fi - records=$(echo "$response" | tr '{' "\n" | grep 'record_id\|type\|data\|\name' | sed 's/\"record_id/;\"record_id/' | tr "\n" ' '| tr -d ' ' | tr ';' ' ') + records=$(echo "$response" | tr '{' "\n" | grep 'record_id\|type\|data\|\name' | sed 's/\"record_id/;\"record_id/' | tr "\n" ' ' | tr -d ' ' | tr ';' ' ') nr_of_deleted_records=0 _info "Fetching txt record" - for record in $records; do + for record in $records; do _debug record "$record" - - record_data=$(echo "$record" | cut -d "," -f 3 | sed 's/"//g' | grep "data" | cut -d ":" -f 2) - record_type=$(echo "$record" | cut -d "," -f 4 | sed 's/"//g' | grep "type" | cut -d ":" -f 2) - _debug2 record_data "$record_data" - _debug2 record_type "$record_type" + record_data=$(echo "$record" | cut -d "," -f 3 | sed 's/"//g' | grep "data" | cut -d ":" -f 2) + record_type=$(echo "$record" | cut -d "," -f 4 | sed 's/"//g' | grep "type" | cut -d ":" -f 2) + + _debug2 record_data "$record_data" + _debug2 record_type "$record_type" if [ "$record_data" = "$txtvalue" ] && [ "$record_type" = "TXT" ]; then @@ -98,7 +97,7 @@ dns_simply_rm() { nr_of_deleted_records=1 break - else + else _err "Fetching record_id could not be done, this should not happen, exiting function. Failing record is $record" break fi @@ -107,7 +106,7 @@ dns_simply_rm() { done if [ "$nr_of_deleted_records" -eq 0 ]; then - _err "No record deleted, the DNS record needs to be removed manually." + _err "No record deleted, the DNS record needs to be removed manually." else _info "Deleted $nr_of_deleted_records record" fi From 3274f9f155acb6f5ec13b9b56c8166c0fb6cc537 Mon Sep 17 00:00:00 2001 From: jakelamotta Date: Wed, 18 Nov 2020 15:55:02 +0100 Subject: [PATCH 103/383] Fix code style problems --- dnsapi/dns_simply.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index 379f1b42..9a9133e6 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -50,7 +50,7 @@ dns_simply_rm() { _simply_save_config _debug "First detect the root zone" - + if ! _get_root "$fulldomain"; then _err "invalid domain" return 1 @@ -80,7 +80,7 @@ dns_simply_rm() { _debug2 record_data "$record_data" _debug2 record_type "$record_type" - + if [ "$record_data" = "$txtvalue" ] && [ "$record_type" = "TXT" ]; then record_id=$(echo "$record" | cut -d "," -f 1 | grep "record_id" | cut -d ":" -f 2) From 11b980f574c567361d720ea3421b68b668240b39 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 18 Nov 2020 23:16:36 +0800 Subject: [PATCH 104/383] fix set-env --- .github/workflows/DNS.yml | 3 ++- .github/workflows/LetsEncrypt.yml | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index c41851b8..748628dd 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -143,8 +143,9 @@ jobs: C:\tools\cygwin\cygwinsetup.exe -qgnNdO -R C:/tools/cygwin -s http://mirrors.kernel.org/sourceware/cygwin/ -P socat,curl,cron,unzip,git shell: cmd - name: Set ENV + shell: cmd run: | - echo "PATH=C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin" >> $GITHUB_ENV + echo PATH=C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin >> %GITHUB_ENV% - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - name: Run acmetest diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index b5468ff6..16b7e779 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -87,11 +87,13 @@ jobs: C:\tools\cygwin\cygwinsetup.exe -qgnNdO -R C:/tools/cygwin -s http://mirrors.kernel.org/sourceware/cygwin/ -P socat,curl,cron,unzip,git shell: cmd - name: Set ENV + shell: cmd run: | - echo "PATH=C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin" >> $GITHUB_ENV + echo PATH=C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin >> %GITHUB_ENV% - name: Check ENV + shell: cmd run: | - echo "PATH=$PATH" + echo "PATH=%PATH%" - name: Clone acmetest shell: cmd run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ From 1e2d2abbdf668a2d307a07363d5e6e265d2dbee2 Mon Sep 17 00:00:00 2001 From: jakelamotta Date: Wed, 18 Nov 2020 18:01:02 +0100 Subject: [PATCH 105/383] Fix comment --- dnsapi/dns_simply.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index 9a9133e6..d053dcf6 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -8,8 +8,8 @@ #SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]" SIMPLY_Api_Default="https://api.simply.com/1" -######## Public functions ##################### +######## Public functions ##################### #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_simply_add() { fulldomain=$1 From 199ca77c2a07dc6821df516f8cba7662c018ba4e Mon Sep 17 00:00:00 2001 From: neil Date: Thu, 19 Nov 2020 20:14:28 +0800 Subject: [PATCH 106/383] fix for PebbleStrict mode test. --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 456383bd..1e4b1152 100755 --- a/acme.sh +++ b/acme.sh @@ -5823,7 +5823,7 @@ _deactivate() { _URL_NAME="uri" fi - entries="$(echo "$response" | _egrep_o "[^{]*\"type\":\"[^\"]*\", *\"status\": *\"valid\", *\"$_URL_NAME\"[^}]*")" + entries="$(echo "$response" | tr '][' '=' | _egrep_o "challenges\": *=[^=]*=" | tr '}{' '\n' | grep "\"status\": *\"valid\"")" if [ -z "$entries" ]; then _info "No valid entries found." if [ -z "$thumbprint" ]; then @@ -5866,7 +5866,7 @@ _deactivate() { _debug _vtype "$_vtype" _info "Found $_vtype" - uri="$(echo "$entry" | _egrep_o "\"$_URL_NAME\":\"[^\"]*" | cut -d : -f 2,3 | tr -d '"')" + uri="$(echo "$entry" | _egrep_o "\"$_URL_NAME\":\"[^\"]*\"" | tr -d '" ' | cut -d : -f 2-)" _debug uri "$uri" if [ "$_d_type" ] && [ "$_d_type" != "$_vtype" ]; then From 1a163243ec280f0d776d838ddfebac57db5c75b5 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 22 Nov 2020 12:19:52 +0800 Subject: [PATCH 107/383] fix https://github.com/acmesh-official/acme.sh/issues/3259 --- dnsapi/dns_dpi.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_dpi.sh b/dnsapi/dns_dpi.sh index 831150a9..9cbf4d51 100755 --- a/dnsapi/dns_dpi.sh +++ b/dnsapi/dns_dpi.sh @@ -75,7 +75,7 @@ dns_dpi_rm() { return 1 fi - _contains "$response" "Action completed successful" + _contains "$response" "Operation successful" } @@ -93,7 +93,7 @@ add_record() { return 1 fi - _contains "$response" "Action completed successful" || _contains "$response" "Domain record already exists" + _contains "$response" "Operation successful" || _contains "$response" "Domain record already exists" } #################### Private functions below ################################## @@ -117,7 +117,7 @@ _get_root() { return 1 fi - if _contains "$response" "Action completed successful"; then + if _contains "$response" "Operation 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 2e97b20f94bff7bd1e464ed49e95ba8c3f3c2618 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 22 Nov 2020 11:22:54 +0100 Subject: [PATCH 108/383] Added World4You DNS API --- dnsapi/dns_world4you.sh | 159 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 dnsapi/dns_world4you.sh diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh new file mode 100644 index 00000000..ec5a0e47 --- /dev/null +++ b/dnsapi/dns_world4you.sh @@ -0,0 +1,159 @@ +#!/usr/bin/env sh + +# World4You - www.world4you.com +# Lorenz Stechauner, 2020 - https://www.github.com/NerLOR + +WORLD4YOU_API="https://my.world4you.com/en" + +################ Public functions ################ + +# Usage: dns_world4you_add +dns_world4you_add() { + fqdn="$1" + value="$2" + _info "Using world4you" + _debug fulldomain "$fqdn" + _debug txtvalue "$value" + + tld=$(echo "$fqdn" | grep -o '[^.]*\.[^.]*$') + record=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#tld} - 1))") + + _login + if [ "$?" != 0 ]; then + return 1 + fi + + export _H1="Cookie: W4YSESSID=$sessid" + paketnr=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht" | grep -B 3 "^\\s*$tld\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\)<.*$/\1/') + if [ -z "$paketnr" ]; then + _err "Unable to parse paketnr" + return 3 + fi + _debug paketnr "$paketnr" + + export _H1="Cookie: W4YSESSID=$sessid" + form=$(_get "$WORLD4YOU_API/$paketnr/dns") + formiddp=$(echo "$form" | grep 'AddDnsRecordForm\[uniqueFormIdDP\]' | sed 's/^.*name="AddDnsRecordForm\[uniqueFormIdDP\]" value="\([^"]*\)".*$/\1/') + formidttl=$(echo "$form" | grep 'AddDnsRecordForm\[uniqueFormIdTTL\]' | sed 's/^.*name="AddDnsRecordForm\[uniqueFormIdTTL\]" value="\([^"]*\)".*$/\1/') + form_token=$(echo "$form" | grep 'AddDnsRecordForm\[_token\]' | sed 's/^.*name="AddDnsRecordForm\[_token\]" value="\([^"]*\)".*$/\1/') + if [ -z "$formiddp" ]; then + _err "Unable to parse form" + return 3 + fi + + _ORIG_ACME_CURL="$_ACME_CURL" + _ACME_CURL=$(echo "$_ACME_CURL" | sed 's/ -L / /') + + body="AddDnsRecordForm[name]=$record&AddDnsRecordForm[dnsType][type]=TXT&\ +AddDnsRecordForm[value]=$value&AddDnsRecordForm[aktivPaket]=$paketnr&AddDnsRecordForm[uniqueFormIdDP]=$formiddp&\ +AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_token" + _info "Adding record..." + ret=$(_post "$body" "$WORLD4YOU_API/$paketnr/dns" '' POST 'application/x-www-form-urlencoded') + + _ACME_CURL="$_ORIG_ACME_CURL" + + success=$(grep '302\|200' <"$HTTP_HEADER") + if [ "$success" ]; then + return 0 + else + _err "$(head -n 1 <"$HTTP_HEADER")" + return 2 + fi +} + +# Usage: dns_world4you_rm +dns_world4you_rm() { + fqdn="$1" + value="$2" + _info "Using world4you" + _debug fulldomain "$fqdn" + _debug txtvalue "$value" + + tld=$(echo "$fqdn" | grep -o '[^.]*\.[^.]*$') + record=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#tld} - 1))") + + _login + if [ "$?" != 0 ]; then + return 1 + fi + + export _H1="Cookie: W4YSESSID=$sessid" + paketnr=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht" | grep -B 3 "^\\s*$tld\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\).*$/\1/') + if [ -z "$paketnr" ]; then + _err "Unable to parse paketnr" + return 3 + fi + _debug paketnr "$paketnr" + + form=$(_get "$WORLD4YOU_API/$paketnr/dns") + formiddp=$(echo "$form" | grep 'DeleteDnsRecordForm\[uniqueFormIdDP\]' | sed 's/^.*name="DeleteDnsRecordForm\[uniqueFormIdDP\]" value="\([^"]*\)".*$/\1/') + formidttl=$(echo "$form" | grep 'DeleteDnsRecordForm\[uniqueFormIdTTL\]' | sed 's/^.*name="DeleteDnsRecordForm\[uniqueFormIdTTL\]" value="\([^"]*\)".*$/\1/') + form_token=$(echo "$form" | grep 'DeleteDnsRecordForm\[_token\]' | sed 's/^.*name="DeleteDnsRecordForm\[_token\]" value="\([^"]*\)".*$/\1/') + if [ -z "$formiddp" ]; then + _err "Unable to parse form" + return 3 + fi + + recordid=$(printf "TXT:%s.:\"%s\"" "$fqdn" "$value" | _base64) + _debug recordid "$recordid" + + _ORIG_ACME_CURL="$_ACME_CURL" + _ACME_CURL=$(echo "$_ACME_CURL" | sed 's/ -L / /') + + body="DeleteDnsRecordForm[recordId]=$recordid&DeleteDnsRecordForm[aktivPaket]=$paketnr&\ +DeleteDnsRecordForm[uniqueFormIdDP]=$formiddp&DeleteDnsRecordForm[uniqueFormIdTTL]=$formidttl&\ +DeleteDnsRecordForm[_token]=$form_token" + _info "Removing record..." + ret=$(_post "$body" "$WORLD4YOU_API/$paketnr/deleteRecord" '' POST 'application/x-www-form-urlencoded') + + _ACME_CURL="$_ORIG_ACME_CURL" + + success=$(grep '302\|200' <"$HTTP_HEADER") + if [ "$success" ]; then + return 0 + else + _err "$(head -n 1 <"$HTTP_HEADER")" + return 2 + fi +} + +################ Private functions ################ + +# Usage: _login +_login() { + WORLD4YOU_USERNAME="${WORLD4YOU_USERNAME:-$(_readaccountconf_mutable WORLD4YOU_USERNAME)}" + WORLD4YOU_PASSWORD="${WORLD4YOU_PASSWORD:-$(_readaccountconf_mutable WORLD4YOU_PASSWORD)}" + + if [ -z "$WORLD4YOU_USERNAME" ] || [ -z "$WORLD4YOU_PASSWORD" ]; then + WORLD4YOU_USERNAME="" + WORLD4YOU_PASSWORD="" + _err "You don't specified world4you username and password yet." + _err "Usage: export WORLD4YOU_USERNAME=" + _err "Usage: export WORLD4YOU_PASSWORD=" + return 2 + fi + + _saveaccountconf_mutable WORLD4YOU_USERNAME "$WORLD4YOU_USERNAME" + _saveaccountconf_mutable WORLD4YOU_PASSWORD "$WORLD4YOU_PASSWORD" + + _info "Logging in..." + + username="$WORLD4YOU_USERNAME" + password="$WORLD4YOU_PASSWORD" + csrf_token=$(_get "$WORLD4YOU_API/login" | grep '_csrf_token' | sed 's/^.*]*value=\"\([^"]*\)\".*$/\1/') + sessid=$(grep 'W4YSESSID' <"$HTTP_HEADER" | sed 's/^.*W4YSESSID=\([^;]*\);.*$/\1/') + + export _H1="Cookie: W4YSESSID=$sessid" + export _H2="X-Requested-With: XMLHttpRequest" + body="_username=$username&_password=$password&_csrf_token=$csrf_token" + ret=$(_post "$body" "$WORLD4YOU_API/login" '' POST 'application/x-www-form-urlencoded') + unset _H2 + _debug ret "$ret" + if _contains "$ret" "\"success\":true"; then + _info "Successfully logged in" + sessid=$(grep 'W4YSESSID' <"$HTTP_HEADER" | sed 's/^.*W4YSESSID=\([^;]*\);.*$/\1/') + else + _err "Unable to log in: $(echo "$ret" | sed 's/^.*"message":"\([^\"]*\)".*$/\1/')" + return 1 + fi +} From cc8f2afce9ed2009565f65fa81369d7a96f18d74 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 22 Nov 2020 21:41:22 +0800 Subject: [PATCH 109/383] fix for Solaris, and add Solaris to Github actions --- .github/workflows/DNS.yml | 37 +++++++++++++++++++++++++++++++ .github/workflows/LetsEncrypt.yml | 26 ++++++++++++++++++++++ acme.sh | 4 ++-- 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 748628dd..5dc2d453 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -208,5 +208,42 @@ jobs: cd ../acmetest ./letest.sh + Solaris: + runs-on: macos-latest + needs: FreeBSD + env: + TEST_DNS : ${{ secrets.TEST_DNS }} + TestingDomain: ${{ secrets.TestingDomain }} + TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }} + TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }} + CASE: le_test_dnsapi + TEST_LOCAL: 1 + DEBUG: 1 + steps: + - uses: actions/checkout@v2 + - name: Clone acmetest + run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ + - uses: vmactions/solaris-vm@v0.0.1 + with: + envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' + prepare: pkgutil -y -i socat curl + run: | + if [ "${{ secrets.TokenName1}}" ] ; then + export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}} + fi + if [ "${{ secrets.TokenName2}}" ] ; then + export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}} + fi + if [ "${{ secrets.TokenName3}}" ] ; then + export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}} + fi + if [ "${{ secrets.TokenName4}}" ] ; then + export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}} + fi + if [ "${{ secrets.TokenName5}}" ] ; then + export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}} + fi + cd ../acmetest + ./letest.sh diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 16b7e779..8d0c4eb0 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -119,3 +119,29 @@ jobs: run: | cd ../acmetest && ./letest.sh + Solaris: + runs-on: macos-latest + needs: FreeBSD + env: + NGROK_TOKEN : ${{ secrets.NGROK_TOKEN }} + TEST_LOCAL: 1 + steps: + - uses: actions/checkout@v2 + - uses: vmactions/ngrok-tunnel@v0.0.1 + id: ngrok + with: + protocol: http + port: 8080 + - name: Set envs + run: echo "TestingDomain=${{steps.ngrok.outputs.server}}" >> $GITHUB_ENV + - name: Clone acmetest + run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ + - uses: vmactions/solaris-vm@v0.0.1 + with: + envs: 'TEST_LOCAL TestingDomain' + nat: | + "8080": "80" + prepare: pkgutil -y -i socat curl + run: | + cd ../acmetest && ./letest.sh + diff --git a/acme.sh b/acme.sh index 1e4b1152..e549f7c8 100755 --- a/acme.sh +++ b/acme.sh @@ -2086,7 +2086,7 @@ _send_signed_request() { _debug2 original "$response" if echo "$responseHeaders" | grep -i "Content-Type: *application/json" >/dev/null 2>&1; then - response="$(echo "$response" | _normalizeJson | _json_decode)" + response="$(echo "$response" | _json_decode | _normalizeJson)" fi _debug2 response "$response" @@ -5823,7 +5823,7 @@ _deactivate() { _URL_NAME="uri" fi - entries="$(echo "$response" | tr '][' '=' | _egrep_o "challenges\": *=[^=]*=" | tr '}{' '\n' | grep "\"status\": *\"valid\"")" + entries="$(echo "$response" | tr '][' '==' | _egrep_o "challenges\": *=[^=]*=" | tr '}{' '\n' | grep "\"status\": *\"valid\"")" if [ -z "$entries" ]; then _info "No valid entries found." if [ -z "$thumbprint" ]; then From 349429b76e534313a4989794707fc1463399cfb2 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 22 Nov 2020 21:55:55 +0800 Subject: [PATCH 110/383] fix solaris badge --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7215785c..cd747666 100644 --- a/README.md +++ b/README.md @@ -60,10 +60,10 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa) |1|[![MacOS](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|Mac OSX |2|[![Windows](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|Windows (cygwin with curl, openssl and crontab included) |3|[![FreeBSD](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|FreeBSD -|4|[![Ubuntu](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)| Ubuntu -|5|[![](https://acmesh-official.github.io/acmetest/status/pfsense.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|pfsense -|6|[![](https://acmesh-official.github.io/acmetest/status/openbsd.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|OpenBSD -|7|[![](https://acmesh-official.github.io/acmetest/status/solaris.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|SunOS/Solaris +|4|[![Solaris](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|Solaris +|5|[![Ubuntu](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)| Ubuntu +|6|[![](https://acmesh-official.github.io/acmetest/status/pfsense.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|pfsense +|7|[![](https://acmesh-official.github.io/acmetest/status/openbsd.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|OpenBSD |8|[![](https://acmesh-official.github.io/acmetest/status/debian-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)| Debian |9|[![](https://acmesh-official.github.io/acmetest/status/centos-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|CentOS |10|[![](https://acmesh-official.github.io/acmetest/status/opensuse-leap-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|openSUSE From b8e5c0d8988522acbad8e0346d8a69fe024fcdd1 Mon Sep 17 00:00:00 2001 From: Easton Man Date: Sun, 22 Nov 2020 22:34:21 +0800 Subject: [PATCH 111/383] feat: Add huaweicloud intl dnsapi --- dnsapi/dns_huaweicloud.sh | 199 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 dnsapi/dns_huaweicloud.sh diff --git a/dnsapi/dns_huaweicloud.sh b/dnsapi/dns_huaweicloud.sh new file mode 100644 index 00000000..69ab14be --- /dev/null +++ b/dnsapi/dns_huaweicloud.sh @@ -0,0 +1,199 @@ +#!/usr/bin/env sh + +# HUAWEICLOUD_Username +# HUAWEICLOUD_Password +# HUAWEICLOUD_ProjectID + +iam_api="https://iam.myhuaweicloud.com" +dns_api="https://dns.ap-southeast-1.myhuaweicloud.com" + +######## Public functions ##################### + +# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +# Used to add txt record +# +# Ref: https://support.huaweicloud.com/intl/zh-cn/api-dns/zh-cn_topic_0132421999.html +# + +dns_huaweicloud_add() { + fulldomain=$1 + txtvalue=$2 + + HUAWEICLOUD_Username="${HUAWEICLOUD_Username:-$(_readaccountconf_mutable HUAWEICLOUD_Username)}" + HUAWEICLOUD_Password="${HUAWEICLOUD_Password:-$(_readaccountconf_mutable HUAWEICLOUD_Password)}" + HUAWEICLOUD_ProjectID="${HUAWEICLOUD_ProjectID:-$(_readaccountconf_mutable HUAWEICLOUD_ProjectID)}" + + token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_ProjectID}")" + _debug2 "${token}" + zoneid="$(_get_zoneid "${token}" "${fulldomain}")" + _debug "${zoneid}" + + _debug "Adding Record" + _add_record "${token}" "${fulldomain}" "${txtvalue}" + ret="$?" + if [ "${ret}" != "0" ]; then + _err "dns_huaweicloud: Error adding record." + return 1 + fi + + # Do saving work if all succeeded + _saveaccountconf_mutable HUAWEICLOUD_Username "${HUAWEICLOUD_Username}" + _saveaccountconf_mutable HUAWEICLOUD_Password "${HUAWEICLOUD_Password}" + _saveaccountconf_mutable HUAWEICLOUD_ProjectID "${HUAWEICLOUD_ProjectID}" + return 0 +} + +# Usage: fulldomain txtvalue +# Used to remove the txt record after validation +# +# Ref: https://support.huaweicloud.com/intl/zh-cn/api-dns/dns_api_64005.html +# + +dns_huaweicloud_rm() { + fulldomain=$1 + txtvalue=$2 + + HUAWEICLOUD_Username="${HUAWEICLOUD_Username:-$(_readaccountconf_mutable HUAWEICLOUD_Username)}" + HUAWEICLOUD_Password="${HUAWEICLOUD_Password:-$(_readaccountconf_mutable HUAWEICLOUD_Password)}" + HUAWEICLOUD_ProjectID="${HUAWEICLOUD_ProjectID:-$(_readaccountconf_mutable HUAWEICLOUD_ProjectID)}" + + token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_ProjectID}")" + _debug2 "${token}" + zoneid="$(_get_zoneid "${token}" "${fulldomain}")" + _debug "${zoneid}" + record_id="$(_get_recordset_id "${token}" "${fulldomain}" "${zoneid}")" + _debug "Record Set ID is: ${record_id}" + while [ "${record_id}" != "0" ]; do + _debug "Adding Record" + _rm_record "${token}" "${zoneid}" "${record_id}" + record_id="$(_get_recordset_id "${token}" "${fulldomain}" "${zoneid}")" + done + return 0 +} + +################### Private functions below ################################## + +# _get_zoneid +# +# _token=$1 +# _domain_string=$2 +# +# printf "%s" "${_zoneid}" +_get_zoneid() { + _token=$1 + _domain_string=$2 + export _H1="X-Auth-Token: ${_token}" + + i=1 + while true; do + h=$(printf "%s" "${_domain_string}" | cut -d . -f $i-100) + if [ -z "$h" ]; then + #not valid + return 1 + fi + _debug "$h" + response=$(_get "${dns_api}/v2/zones?name=${h}") + + if _contains "${response}" "id"; then + _debug "Get Zone ID Success." + _zoneid=$(echo "${response}" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ") + printf "%s" "${_zoneid}" + return 0 + fi + + i=$(_math "$i" + 1) + done + return 1 +} + +_get_recordset_id() { + _token=$1 + _domain=$2 + _zoneid=$3 + export _H1="X-Auth-Token: ${_token}" + + response=$(_get "${dns_api}/v2/zones/${_zoneid}/recordsets?name=${_domain}") + if _contains "${response}" "id"; then + _id="$(echo "${response}" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")" + printf "%s" "${_id}" + return 0 + fi + printf "%s" "0" + return 1 +} + +_add_record() { + _token=$1 + _domain=$2 + _txtvalue=$3 + body="{ + \"name\": \"${_domain}.\", + \"description\": \"ACME Challenge\", + \"type\": \"TXT\", + \"ttl\": 1, + \"records\": [ + \"\\\"${_txtvalue}\\\"\" + ] + }" + _debug2 "${body}" + export _H2="Content-Type: application/json" + export _H1="X-Auth-Token: ${_token}" + + _post "${body}" "${dns_api}/v2/zones/${zoneid}/recordsets" >/dev/null + _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" + if [ "$_code" != "202" ]; then + _err "dns_huaweicloud: http code ${_code}" + return 1 + fi + return 0 +} + +_rm_record() { + _token=$1 + _zone_id=$2 + _record_id=$3 + + export _H2="Content-Type: application/json" + export _H1="X-Auth-Token: ${_token}" + + _post "${body}" "${dns_api}/v2/zones/${_zone_id}/recordsets/${_record_id}" false "DELETE" + return 0 +} + +_get_token() { + _username=$1 + _password=$2 + _project=$3 + + _debug "Getting Token" + body="{ + \"auth\": { + \"identity\": { + \"methods\": [ + \"password\" + ], + \"password\": { + \"user\": { + \"name\": \"${_username}\", + \"password\": \"${_password}\", + \"domain\": { + \"name\": \"${_username}\" + } + } + } + }, + \"scope\": { + \"project\": { + \"id\": \"${_project}\" + } + } + } + }" + export _H1="Content-Type: application/json;charset=utf8" + _post "${body}" "${iam_api}/v3/auth/tokens" >/dev/null + _code=$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n") + _token=$(grep "^X-Subject-Token" "$HTTP_HEADER" | cut -d " " -f 2-) + _debug2 "${_code}" + printf "%s" "${_token}" + return 0 +} From 7db592d27a7be071033d221cb57cf33bb5ae206a Mon Sep 17 00:00:00 2001 From: Easton Man Date: Sun, 22 Nov 2020 22:56:47 +0800 Subject: [PATCH 112/383] fix: fix failing ci test --- dnsapi/dns_huaweicloud.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dnsapi/dns_huaweicloud.sh b/dnsapi/dns_huaweicloud.sh index 69ab14be..4aee6410 100644 --- a/dnsapi/dns_huaweicloud.sh +++ b/dnsapi/dns_huaweicloud.sh @@ -63,6 +63,8 @@ dns_huaweicloud_rm() { _debug "${zoneid}" record_id="$(_get_recordset_id "${token}" "${fulldomain}" "${zoneid}")" _debug "Record Set ID is: ${record_id}" + + # Remove all records while [ "${record_id}" != "0" ]; do _debug "Adding Record" _rm_record "${token}" "${zoneid}" "${record_id}" From 28ce1c1249bc2297d3588adfa49c2974d0353c3d Mon Sep 17 00:00:00 2001 From: Easton Man Date: Mon, 23 Nov 2020 00:20:38 +0800 Subject: [PATCH 113/383] fix: fix wrong debug output --- dnsapi/dns_huaweicloud.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_huaweicloud.sh b/dnsapi/dns_huaweicloud.sh index 4aee6410..56ba19ef 100644 --- a/dnsapi/dns_huaweicloud.sh +++ b/dnsapi/dns_huaweicloud.sh @@ -66,7 +66,7 @@ dns_huaweicloud_rm() { # Remove all records while [ "${record_id}" != "0" ]; do - _debug "Adding Record" + _debug "Removing Record" _rm_record "${token}" "${zoneid}" "${record_id}" record_id="$(_get_recordset_id "${token}" "${fulldomain}" "${zoneid}")" done @@ -158,7 +158,7 @@ _rm_record() { export _H2="Content-Type: application/json" export _H1="X-Auth-Token: ${_token}" - _post "${body}" "${dns_api}/v2/zones/${_zone_id}/recordsets/${_record_id}" false "DELETE" + _post "${body}" "${dns_api}/v2/zones/${_zone_id}/recordsets/${_record_id}" false "DELETE" >/dev/null return 0 } From e01fb503592f4c9fd4a58edfc8aa1b445396cf2e Mon Sep 17 00:00:00 2001 From: Easton Man Date: Mon, 23 Nov 2020 00:32:50 +0800 Subject: [PATCH 114/383] feat: add env var check --- dnsapi/dns_huaweicloud.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dnsapi/dns_huaweicloud.sh b/dnsapi/dns_huaweicloud.sh index 56ba19ef..0f08bcdf 100644 --- a/dnsapi/dns_huaweicloud.sh +++ b/dnsapi/dns_huaweicloud.sh @@ -57,6 +57,11 @@ dns_huaweicloud_rm() { HUAWEICLOUD_Password="${HUAWEICLOUD_Password:-$(_readaccountconf_mutable HUAWEICLOUD_Password)}" HUAWEICLOUD_ProjectID="${HUAWEICLOUD_ProjectID:-$(_readaccountconf_mutable HUAWEICLOUD_ProjectID)}" + if [ -z "${HUAWEICLOUD_Username}" ] || [ -z "${HUAWEICLOUD_Username}" ] || [ -z "${HUAWEICLOUD_Username}" ]; then + _err "Please provide enough information" + return 1 + fi + token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_ProjectID}")" _debug2 "${token}" zoneid="$(_get_zoneid "${token}" "${fulldomain}")" From f6f6550bfbf19c0b3554d531787a33b20b9ddd83 Mon Sep 17 00:00:00 2001 From: Easton Man Date: Mon, 23 Nov 2020 14:25:48 +0800 Subject: [PATCH 115/383] feat: add very tricky method to adapt to non-intuitive huaweicloud api --- dnsapi/dns_huaweicloud.sh | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/dnsapi/dns_huaweicloud.sh b/dnsapi/dns_huaweicloud.sh index 0f08bcdf..2b891b38 100644 --- a/dnsapi/dns_huaweicloud.sh +++ b/dnsapi/dns_huaweicloud.sh @@ -23,6 +23,11 @@ dns_huaweicloud_add() { HUAWEICLOUD_Password="${HUAWEICLOUD_Password:-$(_readaccountconf_mutable HUAWEICLOUD_Password)}" HUAWEICLOUD_ProjectID="${HUAWEICLOUD_ProjectID:-$(_readaccountconf_mutable HUAWEICLOUD_ProjectID)}" + if [ -z "${HUAWEICLOUD_Username}" ] || [ -z "${HUAWEICLOUD_Username}" ] || [ -z "${HUAWEICLOUD_Username}" ]; then + _err "Not enough info provided to dns_huaweicloud!" + return 1 + fi + token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_ProjectID}")" _debug2 "${token}" zoneid="$(_get_zoneid "${token}" "${fulldomain}")" @@ -133,15 +138,36 @@ _add_record() { _token=$1 _domain=$2 _txtvalue=$3 + + # Get Existing Records + export _H1="X-Auth-Token: ${_token}" + response=$(_get "${dns_api}/v2/zones/${_zoneid}/recordsets?name=${_domain}") + _exist_record=$(echo "${response}" | sed ':a;N;$!ba;s/\n/ /g' | grep -o '"records":[^]]*' | sed 's/\"records\"\: \[//g') + _debug "${_exist_record}" + + # Check if record exist + # Generate body data body="{ \"name\": \"${_domain}.\", \"description\": \"ACME Challenge\", \"type\": \"TXT\", \"ttl\": 1, \"records\": [ + ${_exist_record}, \"\\\"${_txtvalue}\\\"\" ] }" + if [ -z "${_exist_record}" ]; then + body="{ + \"name\": \"${_domain}.\", + \"description\": \"ACME Challenge\", + \"type\": \"TXT\", + \"ttl\": 1, + \"records\": [ + \"\\\"${_txtvalue}\\\"\" + ] + }" + fi _debug2 "${body}" export _H2="Content-Type: application/json" export _H1="X-Auth-Token: ${_token}" From 5d0657c49a0d2ac6f50981f91c6a95cfe490ae15 Mon Sep 17 00:00:00 2001 From: Easton Man Date: Mon, 23 Nov 2020 14:57:33 +0800 Subject: [PATCH 116/383] fix: fix adding record before removing --- dnsapi/dns_huaweicloud.sh | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_huaweicloud.sh b/dnsapi/dns_huaweicloud.sh index 2b891b38..625588d1 100644 --- a/dnsapi/dns_huaweicloud.sh +++ b/dnsapi/dns_huaweicloud.sh @@ -141,13 +141,15 @@ _add_record() { # Get Existing Records export _H1="X-Auth-Token: ${_token}" - response=$(_get "${dns_api}/v2/zones/${_zoneid}/recordsets?name=${_domain}") - _exist_record=$(echo "${response}" | sed ':a;N;$!ba;s/\n/ /g' | grep -o '"records":[^]]*' | sed 's/\"records\"\: \[//g') + response=$(_get "${dns_api}/v2/zones/${zoneid}/recordsets?name=${_domain}") + + _debug "${response}" + _exist_record=$(echo "${response}" | sed ':a;N;$!ba;s/\n/ /g' | grep -o '"records":[^]]*' | sed 's/\"records\"\:\[//g') _debug "${_exist_record}" # Check if record exist # Generate body data - body="{ + _post_body="{ \"name\": \"${_domain}.\", \"description\": \"ACME Challenge\", \"type\": \"TXT\", @@ -158,7 +160,7 @@ _add_record() { ] }" if [ -z "${_exist_record}" ]; then - body="{ + _post_body="{ \"name\": \"${_domain}.\", \"description\": \"ACME Challenge\", \"type\": \"TXT\", @@ -168,19 +170,38 @@ _add_record() { ] }" fi - _debug2 "${body}" + + _record_id="$(_get_recordset_id "${_token}" "${_domain}" "${zoneid}")" + _debug "Record Set ID is: ${_record_id}" + + # Remove all records + while [ "${_record_id}" != "0" ]; do + _debug "Removing Record" + _rm_record "${_token}" "${zoneid}" "${_record_id}" + _record_id="$(_get_recordset_id "${_token}" "${_domain}" "${zoneid}")" + _debug "${_record_id}" + done + + # Add brand new records with all old and new records export _H2="Content-Type: application/json" export _H1="X-Auth-Token: ${_token}" - _post "${body}" "${dns_api}/v2/zones/${zoneid}/recordsets" >/dev/null + _debug "${_post_body}" + sleep 2 + _post "${_post_body}" "${dns_api}/v2/zones/${zoneid}/recordsets" >/dev/null _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" if [ "$_code" != "202" ]; then _err "dns_huaweicloud: http code ${_code}" + sleep 60 return 1 fi return 0 } +# _rm_record $token $zoneid $recordid +# assume ${dns_api} exist +# no output +# return 0 _rm_record() { _token=$1 _zone_id=$2 @@ -189,8 +210,8 @@ _rm_record() { export _H2="Content-Type: application/json" export _H1="X-Auth-Token: ${_token}" - _post "${body}" "${dns_api}/v2/zones/${_zone_id}/recordsets/${_record_id}" false "DELETE" >/dev/null - return 0 + _post "" "${dns_api}/v2/zones/${_zone_id}/recordsets/${_record_id}" false "DELETE" >/dev/null + return $? } _get_token() { From 65c06da275c49b1675d46af91d8e0e0e366cf29e Mon Sep 17 00:00:00 2001 From: jakelamotta Date: Tue, 17 Nov 2020 13:19:55 +0100 Subject: [PATCH 117/383] Adds dnsapi support for Simply.com --- dnsapi/dns_simply.sh | 240 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100644 dnsapi/dns_simply.sh diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh new file mode 100644 index 00000000..25dd9ff3 --- /dev/null +++ b/dnsapi/dns_simply.sh @@ -0,0 +1,240 @@ +#!/usr/bin/env sh + +# +#SIMPLY_AccountName="accountname" +# +#SIMPLY_ApiKey="apikey" +# +#SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]" + +SIMPLY_Api="https://api.simply.com/1" +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_simply_add() { + fulldomain=$1 + txtvalue=$2 + + if ! _simply_load_config; then + return 1 + fi + + _simply_save_config + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _info "Adding record" + + if ! _simply_add_record "$_domain" "$_sub_domain" "$txtvalue"; then + _err "Could not add DNS record" + return 1 + fi + + return 0 +} + +dns_simply_rm() { + fulldomain=$1 + txtvalue=$2 + + if ! _simply_load_config; then + return 1 + fi + + _simply_save_config + + _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 "$txtvalue" + + _debug "Getting existing records" + + if ! _simply_get_all_records "$_domain"; then + _err "invalid domain" + return 1 + fi + + records=$(echo "$response" | tr '{' "\n" | grep 'record_id\|type\|data\|\name' | sed 's/\"record_id/;\"record_id/') + record_array=(`echo $records |tr -d ' ' | tr ';' ' '`) + nr_of_deleted_records=0 + + for (( i=0; i<=${#record_array[@]}; i++ )); do + + record="${record_array[$i]}" + + if [[ "$record" == *"$txtvalue"* && "$record" == *"TXT"* ]]; then + + _info "Deleting record: $record" + + record_id=`echo $record | cut -d "," -f 1 | grep "record_id" | cut -d ":" -f 2` + + if [[ $record_id -gt 0 ]]; then + + if ! _simply_delete_record "$_domain" "$_sub_domain" "$record_id"; then + _err "Record with id $record_id could not be deleted" + return 1 + fi + + nr_of_deleted_records=1 + break + else + _err "Fetching record_id could not be done, this should not happen, exiting function. Failing record is $record" + break + fi + fi + + done + + if [[ $nr_of_deleted_records -eq 0 ]]; then + _err "No record deleted, the DNS record needs to be removed manually." + else + _info "Deleted $nr_of_deleted_records record" + fi + + return 0 +} + +#################### Private functions below ################################## + +_simply_load_config() { + SIMPLY_Api="${SIMPLY_Api:-$(_readaccountconf_mutable SIMPLY_Api)}" + SIMPLY_AccountName="${SIMPLY_AccountName:-$(_readaccountconf_mutable SIMPLY_AccountName)}" + SIMPLY_ApiKey="${SIMPLY_ApiKey:-$(_readaccountconf_mutable SIMPLY_ApiKey)}" + + if [ -z "$SIMPLY_Api" ]; then + SIMPLY_Api="$SIMPLY_Api_Default" + fi + + if [ -z "$SIMPLY_AccountName" ] || [ -z "$SIMPLY_ApiKey" ]; then + SIMPLY_AccountName="" + SIMPLY_ApiKey="" + + _err "A valid Simply API account and apikey not provided." + _err "Please provide a valid API user and try again." + + return 1 + fi + + return 0 +} + +_simply_save_config() { + if [ "$SIMPLY_Api" != "$SIMPLY_Api_Default" ]; then + _saveaccountconf_mutable SIMPLY_Api "$SIMPLY_Api" + fi + _saveaccountconf_mutable SIMPLY_AccountName "$SIMPLY_AccountName" + _saveaccountconf_mutable SIMPLY_ApiKey "$SIMPLY_ApiKey" +} + +_simply_get_all_records() { + domain=$1 + + if ! _simply_rest GET "my/products/$domain/dns/records"; then + return 1 + fi + + return 0 +} + +_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 + + if ! _simply_rest GET "my/products/$h/dns"; then + return 1 + fi + + if _contains "$response" '"code":"NOT_FOUND"'; then + _debug "$h not found" + else + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain="$h" + return 0 + fi + p="$i" + i=$(_math "$i" + 1) + done + return 1 +} + +_simply_add_record() { + domain=$1 + sub_domain=$2 + txtval=$3 + + data="{\"name\": \"$sub_domain\", \"type\":\"TXT\", \"data\": \"$txtval\", \"priority\":0, \"ttl\": 3600}" + + if ! _simply_rest POST "my/products/$domain/dns/records" "$data"; then + _err "Adding record not successfull!" + return 1 + fi + + return 0 +} + +_simply_delete_record() { + domain=$1 + sub_domain=$2 + record_id=$3 + + _debug "Delete record with id $record_id" + + if ! _simply_rest DELETE "my/products/$domain/dns/records/$record_id"; then + _err "Deleting record not successfull!" + return 1 + fi + + return 0 +} + +_simply_rest() { + m=$1 + ep="$2" + data="$3" + + _debug "Data: $data" + _debug "Methodcall: $ep" + _debug "Call type: $m" + + export _H1="Content-Type: application/json" + + if [ "$m" != "GET" ]; then + response="$(_post "$data" "$SIMPLY_Api/$SIMPLY_AccountName/$SIMPLY_ApiKey/$ep" "" "$m")" + else + response="$(_get "$SIMPLY_Api/$SIMPLY_AccountName/$SIMPLY_ApiKey/$ep")" + fi + + if [ "$?" != "0" ]; then + _err "error $ep" + return 1 + fi + + _debug2 response "$response" + + if _contains "$response" "Invalid account authorization"; then + _err "It seems that your api key or accountnumber is not correct." + return 1 + fi + return 0 +} From 81c496d96c4fe5b4aa4de3e47cc7d40f017af194 Mon Sep 17 00:00:00 2001 From: jakelamotta Date: Tue, 17 Nov 2020 13:49:32 +0100 Subject: [PATCH 118/383] Fix comments --- dnsapi/dns_simply.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index 25dd9ff3..3914e1ab 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -59,7 +59,7 @@ dns_simply_rm() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - _debug "$txtvalue" + _debug txtvalue "$txtvalue" _debug "Getting existing records" @@ -78,9 +78,9 @@ dns_simply_rm() { if [[ "$record" == *"$txtvalue"* && "$record" == *"TXT"* ]]; then - _info "Deleting record: $record" - record_id=`echo $record | cut -d "," -f 1 | grep "record_id" | cut -d ":" -f 2` + + _info "Deleting record $record" if [[ $record_id -gt 0 ]]; then @@ -198,7 +198,7 @@ _simply_delete_record() { sub_domain=$2 record_id=$3 - _debug "Delete record with id $record_id" + _debug record_id "Delete record with id $record_id" if ! _simply_rest DELETE "my/products/$domain/dns/records/$record_id"; then _err "Deleting record not successfull!" @@ -213,9 +213,9 @@ _simply_rest() { ep="$2" data="$3" - _debug "Data: $data" - _debug "Methodcall: $ep" - _debug "Call type: $m" + _debug2 data "$data" + _debug2 ep "$ep" + _debug2 m "$m" export _H1="Content-Type: application/json" From 4284777556d11747015273051f260a60b539e392 Mon Sep 17 00:00:00 2001 From: jakelamotta Date: Tue, 17 Nov 2020 14:20:45 +0100 Subject: [PATCH 119/383] Fix indentation and added some debug messages --- dnsapi/dns_simply.sh | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index 3914e1ab..8fb56585 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -61,7 +61,7 @@ dns_simply_rm() { _debug _domain "$_domain" _debug txtvalue "$txtvalue" - _debug "Getting existing records" + _info "Getting all existing records" if ! _simply_get_all_records "$_domain"; then _err "invalid domain" @@ -71,31 +71,34 @@ dns_simply_rm() { records=$(echo "$response" | tr '{' "\n" | grep 'record_id\|type\|data\|\name' | sed 's/\"record_id/;\"record_id/') record_array=(`echo $records |tr -d ' ' | tr ';' ' '`) nr_of_deleted_records=0 + + _info "Fetching txt record.." for (( i=0; i<=${#record_array[@]}; i++ )); do - record="${record_array[$i]}" + record="${record_array[$i]}" + _debug record "$record" - if [[ "$record" == *"$txtvalue"* && "$record" == *"TXT"* ]]; then + if [[ "$record" == *"$txtvalue"* && "$record" == *"TXT"* ]]; then - record_id=`echo $record | cut -d "," -f 1 | grep "record_id" | cut -d ":" -f 2` + record_id=`echo $record | cut -d "," -f 1 | grep "record_id" | cut -d ":" -f 2` - _info "Deleting record $record" + _info "Deleting record $record" - if [[ $record_id -gt 0 ]]; then + if [[ $record_id -gt 0 ]]; then - if ! _simply_delete_record "$_domain" "$_sub_domain" "$record_id"; then - _err "Record with id $record_id could not be deleted" - return 1 - fi + if ! _simply_delete_record "$_domain" "$_sub_domain" "$record_id"; then + _err "Record with id $record_id could not be deleted" + return 1 + fi - nr_of_deleted_records=1 - break - else - _err "Fetching record_id could not be done, this should not happen, exiting function. Failing record is $record" - break + nr_of_deleted_records=1 + break + else + _err "Fetching record_id could not be done, this should not happen, exiting function. Failing record is $record" + break + fi fi - fi done From 8e64329d05edf4035460f08aacf244d5f68dbb44 Mon Sep 17 00:00:00 2001 From: jakelamotta Date: Wed, 18 Nov 2020 14:52:32 +0100 Subject: [PATCH 120/383] Fix CI-errors --- dnsapi/dns_simply.sh | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index 8fb56585..9deceb25 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -7,7 +7,7 @@ # #SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]" -SIMPLY_Api="https://api.simply.com/1" +SIMPLY_Api_Default="https://api.simply.com/1" ######## Public functions ##################### #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" @@ -22,6 +22,7 @@ dns_simply_add() { _simply_save_config _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then _err "invalid domain" return 1 @@ -69,23 +70,28 @@ dns_simply_rm() { fi records=$(echo "$response" | tr '{' "\n" | grep 'record_id\|type\|data\|\name' | sed 's/\"record_id/;\"record_id/') - record_array=(`echo $records |tr -d ' ' | tr ';' ' '`) + record_array=$(echo $records |tr -d ' ' | tr ';' ' ') + nr_of_deleted_records=0 - - _info "Fetching txt record.." + _info "Fetching txt record" - for (( i=0; i<=${#record_array[@]}; i++ )); do - - record="${record_array[$i]}" + for record in $record_array; do _debug record "$record" + + record_data=$(echo $record | cut -d "," -f 3 | sed 's/"//g' | grep "data" | cut -d ":" -f 2) + record_type=$(echo $record | cut -d "," -f 4 | sed 's/"//g' | grep "type" | cut -d ":" -f 2) + + _debug2 record_data "$record_data" + _debug2 record_type "$record_type" + + if [ "$record_data" = "$txtvalue" ] && [ "$record_type" = "TXT" ]; then - if [[ "$record" == *"$txtvalue"* && "$record" == *"TXT"* ]]; then - - record_id=`echo $record | cut -d "," -f 1 | grep "record_id" | cut -d ":" -f 2` + record_id=$(echo $record | cut -d "," -f 1 | grep "record_id" | cut -d ":" -f 2) _info "Deleting record $record" - - if [[ $record_id -gt 0 ]]; then + _debug2 record_id "$record_id" + + if [ "$record_id" -gt 0 ]; then if ! _simply_delete_record "$_domain" "$_sub_domain" "$record_id"; then _err "Record with id $record_id could not be deleted" @@ -102,7 +108,7 @@ dns_simply_rm() { done - if [[ $nr_of_deleted_records -eq 0 ]]; then + if [ "$nr_of_deleted_records" -eq 0 ]; then _err "No record deleted, the DNS record needs to be removed manually." else _info "Deleted $nr_of_deleted_records record" From 449f00f9606268112c215450ef233bc051767db1 Mon Sep 17 00:00:00 2001 From: jakelamotta Date: Wed, 18 Nov 2020 15:12:22 +0100 Subject: [PATCH 121/383] Add double quotes to variables --- dnsapi/dns_simply.sh | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index 9deceb25..30211f7a 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -69,26 +69,25 @@ dns_simply_rm() { return 1 fi - records=$(echo "$response" | tr '{' "\n" | grep 'record_id\|type\|data\|\name' | sed 's/\"record_id/;\"record_id/') - record_array=$(echo $records |tr -d ' ' | tr ';' ' ') + records=$(echo "$response" | tr '{' "\n" | grep 'record_id\|type\|data\|\name' | sed 's/\"record_id/;\"record_id/' | tr "\n" ' '| tr -d ' ' | tr ';' ' ') nr_of_deleted_records=0 _info "Fetching txt record" - for record in $record_array; do + for record in $records; do _debug record "$record" - record_data=$(echo $record | cut -d "," -f 3 | sed 's/"//g' | grep "data" | cut -d ":" -f 2) - record_type=$(echo $record | cut -d "," -f 4 | sed 's/"//g' | grep "type" | cut -d ":" -f 2) + record_data=$(echo "$record" | cut -d "," -f 3 | sed 's/"//g' | grep "data" | cut -d ":" -f 2) + record_type=$(echo "$record" | cut -d "," -f 4 | sed 's/"//g' | grep "type" | cut -d ":" -f 2) _debug2 record_data "$record_data" _debug2 record_type "$record_type" if [ "$record_data" = "$txtvalue" ] && [ "$record_type" = "TXT" ]; then - record_id=$(echo $record | cut -d "," -f 1 | grep "record_id" | cut -d ":" -f 2) + record_id=$(echo "$record" | cut -d "," -f 1 | grep "record_id" | cut -d ":" -f 2) - _info "Deleting record $record" + _info "Deleting record $record" _debug2 record_id "$record_id" if [ "$record_id" -gt 0 ]; then From 9ad05e640d83ae368ff690c14306e0cad085c338 Mon Sep 17 00:00:00 2001 From: jakelamotta Date: Wed, 18 Nov 2020 15:37:26 +0100 Subject: [PATCH 122/383] Removed spaces on empty lines --- dnsapi/dns_simply.sh | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index 30211f7a..6f2464ef 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -21,8 +21,7 @@ dns_simply_add() { _simply_save_config - _debug "First detect the root zone" - + _debug "First detect the root zone" if ! _get_root "$fulldomain"; then _err "invalid domain" return 1 @@ -36,8 +35,7 @@ dns_simply_add() { if ! _simply_add_record "$_domain" "$_sub_domain" "$txtvalue"; then _err "Could not add DNS record" return 1 - fi - + fi return 0 } @@ -126,7 +124,7 @@ _simply_load_config() { if [ -z "$SIMPLY_Api" ]; then SIMPLY_Api="$SIMPLY_Api_Default" fi - + if [ -z "$SIMPLY_AccountName" ] || [ -z "$SIMPLY_ApiKey" ]; then SIMPLY_AccountName="" SIMPLY_ApiKey="" @@ -149,8 +147,8 @@ _simply_save_config() { } _simply_get_all_records() { - domain=$1 - + domain=$1 + if ! _simply_rest GET "my/products/$domain/dns/records"; then return 1 fi @@ -190,14 +188,14 @@ _simply_add_record() { domain=$1 sub_domain=$2 txtval=$3 - + data="{\"name\": \"$sub_domain\", \"type\":\"TXT\", \"data\": \"$txtval\", \"priority\":0, \"ttl\": 3600}" if ! _simply_rest POST "my/products/$domain/dns/records" "$data"; then _err "Adding record not successfull!" return 1 fi - + return 0 } @@ -205,14 +203,14 @@ _simply_delete_record() { domain=$1 sub_domain=$2 record_id=$3 - + _debug record_id "Delete record with id $record_id" - + if ! _simply_rest DELETE "my/products/$domain/dns/records/$record_id"; then _err "Deleting record not successfull!" return 1 fi - + return 0 } @@ -220,7 +218,7 @@ _simply_rest() { m=$1 ep="$2" data="$3" - + _debug2 data "$data" _debug2 ep "$ep" _debug2 m "$m" @@ -237,12 +235,13 @@ _simply_rest() { _err "error $ep" return 1 fi - + _debug2 response "$response" - + if _contains "$response" "Invalid account authorization"; then _err "It seems that your api key or accountnumber is not correct." return 1 fi + return 0 } From fcb97f802f8c19852bb56216716d17395f4441cf Mon Sep 17 00:00:00 2001 From: jakelamotta Date: Wed, 18 Nov 2020 15:46:16 +0100 Subject: [PATCH 123/383] Removes tabs and trailing spaces --- dnsapi/dns_simply.sh | 45 ++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index 6f2464ef..bf383019 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -21,28 +21,29 @@ dns_simply_add() { _simply_save_config - _debug "First detect the root zone" + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then _err "invalid domain" return 1 fi - + _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" _info "Adding record" - if ! _simply_add_record "$_domain" "$_sub_domain" "$txtvalue"; then + if ! _simply_add_record "$_domain" "$_sub_domain" "$txtvalue"; then _err "Could not add DNS record" return 1 - fi + fi return 0 } dns_simply_rm() { fulldomain=$1 txtvalue=$2 - + if ! _simply_load_config; then return 1 fi @@ -61,12 +62,12 @@ dns_simply_rm() { _debug txtvalue "$txtvalue" _info "Getting all existing records" - + if ! _simply_get_all_records "$_domain"; then _err "invalid domain" return 1 fi - + records=$(echo "$response" | tr '{' "\n" | grep 'record_id\|type\|data\|\name' | sed 's/\"record_id/;\"record_id/' | tr "\n" ' '| tr -d ' ' | tr ';' ' ') nr_of_deleted_records=0 @@ -74,27 +75,27 @@ dns_simply_rm() { for record in $records; do _debug record "$record" - - record_data=$(echo "$record" | cut -d "," -f 3 | sed 's/"//g' | grep "data" | cut -d ":" -f 2) - record_type=$(echo "$record" | cut -d "," -f 4 | sed 's/"//g' | grep "type" | cut -d ":" -f 2) - - _debug2 record_data "$record_data" - _debug2 record_type "$record_type" - - if [ "$record_data" = "$txtvalue" ] && [ "$record_type" = "TXT" ]; then + record_data=$(echo "$record" | cut -d "," -f 3 | sed 's/"//g' | grep "data" | cut -d ":" -f 2) + record_type=$(echo "$record" | cut -d "," -f 4 | sed 's/"//g' | grep "type" | cut -d ":" -f 2) + + _debug2 record_data "$record_data" + _debug2 record_type "$record_type" + + if [ "$record_data" = "$txtvalue" ] && [ "$record_type" = "TXT" ]; then + record_id=$(echo "$record" | cut -d "," -f 1 | grep "record_id" | cut -d ":" -f 2) - + _info "Deleting record $record" _debug2 record_id "$record_id" - + if [ "$record_id" -gt 0 ]; then - + if ! _simply_delete_record "$_domain" "$_sub_domain" "$record_id"; then _err "Record with id $record_id could not be deleted" return 1 fi - + nr_of_deleted_records=1 break else @@ -102,7 +103,7 @@ dns_simply_rm() { break fi fi - + done if [ "$nr_of_deleted_records" -eq 0 ]; then @@ -110,7 +111,7 @@ dns_simply_rm() { else _info "Deleted $nr_of_deleted_records record" fi - + return 0 } @@ -242,6 +243,6 @@ _simply_rest() { _err "It seems that your api key or accountnumber is not correct." return 1 fi - + return 0 } From 29d0a1714e3d7a33e55617c1f11573b2a44eafef Mon Sep 17 00:00:00 2001 From: jakelamotta Date: Wed, 18 Nov 2020 15:52:46 +0100 Subject: [PATCH 124/383] Fix code style problems --- dnsapi/dns_simply.sh | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index bf383019..379f1b42 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -22,7 +22,6 @@ dns_simply_add() { _simply_save_config _debug "First detect the root zone" - if ! _get_root "$fulldomain"; then _err "invalid domain" return 1 @@ -68,19 +67,19 @@ dns_simply_rm() { return 1 fi - records=$(echo "$response" | tr '{' "\n" | grep 'record_id\|type\|data\|\name' | sed 's/\"record_id/;\"record_id/' | tr "\n" ' '| tr -d ' ' | tr ';' ' ') + records=$(echo "$response" | tr '{' "\n" | grep 'record_id\|type\|data\|\name' | sed 's/\"record_id/;\"record_id/' | tr "\n" ' ' | tr -d ' ' | tr ';' ' ') nr_of_deleted_records=0 _info "Fetching txt record" - for record in $records; do + for record in $records; do _debug record "$record" - - record_data=$(echo "$record" | cut -d "," -f 3 | sed 's/"//g' | grep "data" | cut -d ":" -f 2) - record_type=$(echo "$record" | cut -d "," -f 4 | sed 's/"//g' | grep "type" | cut -d ":" -f 2) - _debug2 record_data "$record_data" - _debug2 record_type "$record_type" + record_data=$(echo "$record" | cut -d "," -f 3 | sed 's/"//g' | grep "data" | cut -d ":" -f 2) + record_type=$(echo "$record" | cut -d "," -f 4 | sed 's/"//g' | grep "type" | cut -d ":" -f 2) + + _debug2 record_data "$record_data" + _debug2 record_type "$record_type" if [ "$record_data" = "$txtvalue" ] && [ "$record_type" = "TXT" ]; then @@ -98,7 +97,7 @@ dns_simply_rm() { nr_of_deleted_records=1 break - else + else _err "Fetching record_id could not be done, this should not happen, exiting function. Failing record is $record" break fi @@ -107,7 +106,7 @@ dns_simply_rm() { done if [ "$nr_of_deleted_records" -eq 0 ]; then - _err "No record deleted, the DNS record needs to be removed manually." + _err "No record deleted, the DNS record needs to be removed manually." else _info "Deleted $nr_of_deleted_records record" fi From 30f359e6427f289c0181375f4f2b9300c1e27a09 Mon Sep 17 00:00:00 2001 From: jakelamotta Date: Wed, 18 Nov 2020 15:55:02 +0100 Subject: [PATCH 125/383] Fix code style problems --- dnsapi/dns_simply.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index 379f1b42..9a9133e6 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -50,7 +50,7 @@ dns_simply_rm() { _simply_save_config _debug "First detect the root zone" - + if ! _get_root "$fulldomain"; then _err "invalid domain" return 1 @@ -80,7 +80,7 @@ dns_simply_rm() { _debug2 record_data "$record_data" _debug2 record_type "$record_type" - + if [ "$record_data" = "$txtvalue" ] && [ "$record_type" = "TXT" ]; then record_id=$(echo "$record" | cut -d "," -f 1 | grep "record_id" | cut -d ":" -f 2) From 69bdbaed410c8bb38ed5a67f031b30e8420ab6bc Mon Sep 17 00:00:00 2001 From: jakelamotta Date: Wed, 18 Nov 2020 18:01:02 +0100 Subject: [PATCH 126/383] Fix comment --- dnsapi/dns_simply.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index 9a9133e6..d053dcf6 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -8,8 +8,8 @@ #SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]" SIMPLY_Api_Default="https://api.simply.com/1" -######## Public functions ##################### +######## Public functions ##################### #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_simply_add() { fulldomain=$1 From e35ef7594993665e8f472a99e0a6d392cc80e44d Mon Sep 17 00:00:00 2001 From: Easton Man Date: Mon, 23 Nov 2020 22:18:57 +0800 Subject: [PATCH 127/383] fix: fix solaris sed and grep issue --- dnsapi/dns_huaweicloud.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_huaweicloud.sh b/dnsapi/dns_huaweicloud.sh index 625588d1..11f231bc 100644 --- a/dnsapi/dns_huaweicloud.sh +++ b/dnsapi/dns_huaweicloud.sh @@ -144,7 +144,7 @@ _add_record() { response=$(_get "${dns_api}/v2/zones/${zoneid}/recordsets?name=${_domain}") _debug "${response}" - _exist_record=$(echo "${response}" | sed ':a;N;$!ba;s/\n/ /g' | grep -o '"records":[^]]*' | sed 's/\"records\"\:\[//g') + _exist_record=$(echo "${response}" | sed -e ':a' -e 'N;$!ba;' -e 's/\n/ /g' | _egrep_o '"records":[^]]*' | sed 's/\"records\"\:\[//g') _debug "${_exist_record}" # Check if record exist From 83a4db3b31f7fb91c4a6c9a3fed447c92d486092 Mon Sep 17 00:00:00 2001 From: Easton Man Date: Mon, 23 Nov 2020 23:46:06 +0800 Subject: [PATCH 128/383] fix: remove sed before grep, but lead to less robusty --- dnsapi/dns_huaweicloud.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_huaweicloud.sh b/dnsapi/dns_huaweicloud.sh index 11f231bc..36be21a3 100644 --- a/dnsapi/dns_huaweicloud.sh +++ b/dnsapi/dns_huaweicloud.sh @@ -144,7 +144,7 @@ _add_record() { response=$(_get "${dns_api}/v2/zones/${zoneid}/recordsets?name=${_domain}") _debug "${response}" - _exist_record=$(echo "${response}" | sed -e ':a' -e 'N;$!ba;' -e 's/\n/ /g' | _egrep_o '"records":[^]]*' | sed 's/\"records\"\:\[//g') + _exist_record=$(echo "${response}" | _egrep_o '"records":[^]]*' | sed 's/\"records\"\:\[//g') _debug "${_exist_record}" # Check if record exist From c4ddddd4344e728e3273634cb58583fe62e4022f Mon Sep 17 00:00:00 2001 From: Easton Man Date: Tue, 24 Nov 2020 10:05:34 +0800 Subject: [PATCH 129/383] refactor: remove dirty debug code - add tr to replace sed for robusty - add comments --- dnsapi/dns_huaweicloud.sh | 42 ++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/dnsapi/dns_huaweicloud.sh b/dnsapi/dns_huaweicloud.sh index 36be21a3..a7ca619f 100644 --- a/dnsapi/dns_huaweicloud.sh +++ b/dnsapi/dns_huaweicloud.sh @@ -23,8 +23,9 @@ dns_huaweicloud_add() { HUAWEICLOUD_Password="${HUAWEICLOUD_Password:-$(_readaccountconf_mutable HUAWEICLOUD_Password)}" HUAWEICLOUD_ProjectID="${HUAWEICLOUD_ProjectID:-$(_readaccountconf_mutable HUAWEICLOUD_ProjectID)}" - if [ -z "${HUAWEICLOUD_Username}" ] || [ -z "${HUAWEICLOUD_Username}" ] || [ -z "${HUAWEICLOUD_Username}" ]; then - _err "Not enough info provided to dns_huaweicloud!" + # Check information + if [ -z "${HUAWEICLOUD_Username}" ] || [ -z "${HUAWEICLOUD_Password}" ] || [ -z "${HUAWEICLOUD_ProjectID}" ]; then + _err "Not enough information provided to dns_huaweicloud!" return 1 fi @@ -62,8 +63,9 @@ dns_huaweicloud_rm() { HUAWEICLOUD_Password="${HUAWEICLOUD_Password:-$(_readaccountconf_mutable HUAWEICLOUD_Password)}" HUAWEICLOUD_ProjectID="${HUAWEICLOUD_ProjectID:-$(_readaccountconf_mutable HUAWEICLOUD_ProjectID)}" - if [ -z "${HUAWEICLOUD_Username}" ] || [ -z "${HUAWEICLOUD_Username}" ] || [ -z "${HUAWEICLOUD_Username}" ]; then - _err "Please provide enough information" + # Check information + if [ -z "${HUAWEICLOUD_Username}" ] || [ -z "${HUAWEICLOUD_Password}" ] || [ -z "${HUAWEICLOUD_ProjectID}" ]; then + _err "Not enough information provided to dns_huaweicloud!" return 1 fi @@ -75,6 +77,8 @@ dns_huaweicloud_rm() { _debug "Record Set ID is: ${record_id}" # Remove all records + # Therotically HuaweiCloud does not allow more than one record set + # But remove them recurringly to increase robusty while [ "${record_id}" != "0" ]; do _debug "Removing Record" _rm_record "${token}" "${zoneid}" "${record_id}" @@ -143,22 +147,12 @@ _add_record() { export _H1="X-Auth-Token: ${_token}" response=$(_get "${dns_api}/v2/zones/${zoneid}/recordsets?name=${_domain}") - _debug "${response}" - _exist_record=$(echo "${response}" | _egrep_o '"records":[^]]*' | sed 's/\"records\"\:\[//g') + _debug2 "${response}" + _exist_record=$(echo "${response}" | tr -d "\\r\\n" | _egrep_o '"records":[^]]*' | sed 's/\"records\"\:\[//g') _debug "${_exist_record}" # Check if record exist # Generate body data - _post_body="{ - \"name\": \"${_domain}.\", - \"description\": \"ACME Challenge\", - \"type\": \"TXT\", - \"ttl\": 1, - \"records\": [ - ${_exist_record}, - \"\\\"${_txtvalue}\\\"\" - ] - }" if [ -z "${_exist_record}" ]; then _post_body="{ \"name\": \"${_domain}.\", @@ -169,6 +163,17 @@ _add_record() { \"\\\"${_txtvalue}\\\"\" ] }" + else + _post_body="{ + \"name\": \"${_domain}.\", + \"description\": \"ACME Challenge\", + \"type\": \"TXT\", + \"ttl\": 1, + \"records\": [ + ${_exist_record}, + \"\\\"${_txtvalue}\\\"\" + ] + }" fi _record_id="$(_get_recordset_id "${_token}" "${_domain}" "${zoneid}")" @@ -179,20 +184,17 @@ _add_record() { _debug "Removing Record" _rm_record "${_token}" "${zoneid}" "${_record_id}" _record_id="$(_get_recordset_id "${_token}" "${_domain}" "${zoneid}")" - _debug "${_record_id}" done # Add brand new records with all old and new records export _H2="Content-Type: application/json" export _H1="X-Auth-Token: ${_token}" - _debug "${_post_body}" - sleep 2 + _debug2 "${_post_body}" _post "${_post_body}" "${dns_api}/v2/zones/${zoneid}/recordsets" >/dev/null _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" if [ "$_code" != "202" ]; then _err "dns_huaweicloud: http code ${_code}" - sleep 60 return 1 fi return 0 From fd511966a75e416a1c8cd00783305228e960bc37 Mon Sep 17 00:00:00 2001 From: Easton Man Date: Tue, 24 Nov 2020 12:58:16 +0800 Subject: [PATCH 130/383] fix: revert adding tr to replace sed --- dnsapi/dns_huaweicloud.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_huaweicloud.sh b/dnsapi/dns_huaweicloud.sh index a7ca619f..74fec2a9 100644 --- a/dnsapi/dns_huaweicloud.sh +++ b/dnsapi/dns_huaweicloud.sh @@ -148,7 +148,7 @@ _add_record() { response=$(_get "${dns_api}/v2/zones/${zoneid}/recordsets?name=${_domain}") _debug2 "${response}" - _exist_record=$(echo "${response}" | tr -d "\\r\\n" | _egrep_o '"records":[^]]*' | sed 's/\"records\"\:\[//g') + _exist_record=$(echo "${response}" | _egrep_o '"records":[^]]*' | sed 's/\"records\"\:\[//g') _debug "${_exist_record}" # Check if record exist From 996f53373e490fc37e9373b1ff575f42cae5b7f0 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 13 Nov 2020 19:58:21 +0800 Subject: [PATCH 131/383] fix https://github.com/acmesh-official/acme.sh/issues/3250 --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index e549f7c8..b234fb26 100755 --- a/acme.sh +++ b/acme.sh @@ -6649,8 +6649,8 @@ _checkSudo() { return 0 fi if [ -n "$SUDO_COMMAND" ]; then - #it's a normal user doing "sudo su", or `sudo -i` or `sudo -s` - _endswith "$SUDO_COMMAND" /bin/su || grep "^$SUDO_COMMAND\$" /etc/shells >/dev/null 2>&1 + #it's a normal user doing "sudo su", or `sudo -i` or `sudo -s`, or `sudo su acmeuser1` + _endswith "$SUDO_COMMAND" /bin/su || _contains "$SUDO_COMMAND" "/bin/su " || grep "^$SUDO_COMMAND\$" /etc/shells >/dev/null 2>&1 return $? fi #otherwise From d7cafe25ff642ca6e32da27992e2e0e9a4017e14 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Thu, 26 Nov 2020 13:59:18 +0100 Subject: [PATCH 132/383] World4You using _egrep_o --- dnsapi/dns_world4you.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index ec5a0e47..b58ea89a 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -15,7 +15,7 @@ dns_world4you_add() { _debug fulldomain "$fqdn" _debug txtvalue "$value" - tld=$(echo "$fqdn" | grep -o '[^.]*\.[^.]*$') + tld=$(echo "$fqdn" | _egrep_o '[^.]*\.[^.]*$') record=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#tld} - 1))") _login @@ -69,7 +69,7 @@ dns_world4you_rm() { _debug fulldomain "$fqdn" _debug txtvalue "$value" - tld=$(echo "$fqdn" | grep -o '[^.]*\.[^.]*$') + tld=$(echo "$fqdn" | _egrep_o '[^.]*\.[^.]*$') record=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#tld} - 1))") _login From d639c7be392206e8cbcfd6215166450dc5b554c8 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 22 Nov 2020 11:22:54 +0100 Subject: [PATCH 133/383] Added World4You DNS API --- dnsapi/dns_world4you.sh | 159 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 dnsapi/dns_world4you.sh diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh new file mode 100644 index 00000000..ec5a0e47 --- /dev/null +++ b/dnsapi/dns_world4you.sh @@ -0,0 +1,159 @@ +#!/usr/bin/env sh + +# World4You - www.world4you.com +# Lorenz Stechauner, 2020 - https://www.github.com/NerLOR + +WORLD4YOU_API="https://my.world4you.com/en" + +################ Public functions ################ + +# Usage: dns_world4you_add +dns_world4you_add() { + fqdn="$1" + value="$2" + _info "Using world4you" + _debug fulldomain "$fqdn" + _debug txtvalue "$value" + + tld=$(echo "$fqdn" | grep -o '[^.]*\.[^.]*$') + record=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#tld} - 1))") + + _login + if [ "$?" != 0 ]; then + return 1 + fi + + export _H1="Cookie: W4YSESSID=$sessid" + paketnr=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht" | grep -B 3 "^\\s*$tld\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\)<.*$/\1/') + if [ -z "$paketnr" ]; then + _err "Unable to parse paketnr" + return 3 + fi + _debug paketnr "$paketnr" + + export _H1="Cookie: W4YSESSID=$sessid" + form=$(_get "$WORLD4YOU_API/$paketnr/dns") + formiddp=$(echo "$form" | grep 'AddDnsRecordForm\[uniqueFormIdDP\]' | sed 's/^.*name="AddDnsRecordForm\[uniqueFormIdDP\]" value="\([^"]*\)".*$/\1/') + formidttl=$(echo "$form" | grep 'AddDnsRecordForm\[uniqueFormIdTTL\]' | sed 's/^.*name="AddDnsRecordForm\[uniqueFormIdTTL\]" value="\([^"]*\)".*$/\1/') + form_token=$(echo "$form" | grep 'AddDnsRecordForm\[_token\]' | sed 's/^.*name="AddDnsRecordForm\[_token\]" value="\([^"]*\)".*$/\1/') + if [ -z "$formiddp" ]; then + _err "Unable to parse form" + return 3 + fi + + _ORIG_ACME_CURL="$_ACME_CURL" + _ACME_CURL=$(echo "$_ACME_CURL" | sed 's/ -L / /') + + body="AddDnsRecordForm[name]=$record&AddDnsRecordForm[dnsType][type]=TXT&\ +AddDnsRecordForm[value]=$value&AddDnsRecordForm[aktivPaket]=$paketnr&AddDnsRecordForm[uniqueFormIdDP]=$formiddp&\ +AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_token" + _info "Adding record..." + ret=$(_post "$body" "$WORLD4YOU_API/$paketnr/dns" '' POST 'application/x-www-form-urlencoded') + + _ACME_CURL="$_ORIG_ACME_CURL" + + success=$(grep '302\|200' <"$HTTP_HEADER") + if [ "$success" ]; then + return 0 + else + _err "$(head -n 1 <"$HTTP_HEADER")" + return 2 + fi +} + +# Usage: dns_world4you_rm +dns_world4you_rm() { + fqdn="$1" + value="$2" + _info "Using world4you" + _debug fulldomain "$fqdn" + _debug txtvalue "$value" + + tld=$(echo "$fqdn" | grep -o '[^.]*\.[^.]*$') + record=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#tld} - 1))") + + _login + if [ "$?" != 0 ]; then + return 1 + fi + + export _H1="Cookie: W4YSESSID=$sessid" + paketnr=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht" | grep -B 3 "^\\s*$tld\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\).*$/\1/') + if [ -z "$paketnr" ]; then + _err "Unable to parse paketnr" + return 3 + fi + _debug paketnr "$paketnr" + + form=$(_get "$WORLD4YOU_API/$paketnr/dns") + formiddp=$(echo "$form" | grep 'DeleteDnsRecordForm\[uniqueFormIdDP\]' | sed 's/^.*name="DeleteDnsRecordForm\[uniqueFormIdDP\]" value="\([^"]*\)".*$/\1/') + formidttl=$(echo "$form" | grep 'DeleteDnsRecordForm\[uniqueFormIdTTL\]' | sed 's/^.*name="DeleteDnsRecordForm\[uniqueFormIdTTL\]" value="\([^"]*\)".*$/\1/') + form_token=$(echo "$form" | grep 'DeleteDnsRecordForm\[_token\]' | sed 's/^.*name="DeleteDnsRecordForm\[_token\]" value="\([^"]*\)".*$/\1/') + if [ -z "$formiddp" ]; then + _err "Unable to parse form" + return 3 + fi + + recordid=$(printf "TXT:%s.:\"%s\"" "$fqdn" "$value" | _base64) + _debug recordid "$recordid" + + _ORIG_ACME_CURL="$_ACME_CURL" + _ACME_CURL=$(echo "$_ACME_CURL" | sed 's/ -L / /') + + body="DeleteDnsRecordForm[recordId]=$recordid&DeleteDnsRecordForm[aktivPaket]=$paketnr&\ +DeleteDnsRecordForm[uniqueFormIdDP]=$formiddp&DeleteDnsRecordForm[uniqueFormIdTTL]=$formidttl&\ +DeleteDnsRecordForm[_token]=$form_token" + _info "Removing record..." + ret=$(_post "$body" "$WORLD4YOU_API/$paketnr/deleteRecord" '' POST 'application/x-www-form-urlencoded') + + _ACME_CURL="$_ORIG_ACME_CURL" + + success=$(grep '302\|200' <"$HTTP_HEADER") + if [ "$success" ]; then + return 0 + else + _err "$(head -n 1 <"$HTTP_HEADER")" + return 2 + fi +} + +################ Private functions ################ + +# Usage: _login +_login() { + WORLD4YOU_USERNAME="${WORLD4YOU_USERNAME:-$(_readaccountconf_mutable WORLD4YOU_USERNAME)}" + WORLD4YOU_PASSWORD="${WORLD4YOU_PASSWORD:-$(_readaccountconf_mutable WORLD4YOU_PASSWORD)}" + + if [ -z "$WORLD4YOU_USERNAME" ] || [ -z "$WORLD4YOU_PASSWORD" ]; then + WORLD4YOU_USERNAME="" + WORLD4YOU_PASSWORD="" + _err "You don't specified world4you username and password yet." + _err "Usage: export WORLD4YOU_USERNAME=" + _err "Usage: export WORLD4YOU_PASSWORD=" + return 2 + fi + + _saveaccountconf_mutable WORLD4YOU_USERNAME "$WORLD4YOU_USERNAME" + _saveaccountconf_mutable WORLD4YOU_PASSWORD "$WORLD4YOU_PASSWORD" + + _info "Logging in..." + + username="$WORLD4YOU_USERNAME" + password="$WORLD4YOU_PASSWORD" + csrf_token=$(_get "$WORLD4YOU_API/login" | grep '_csrf_token' | sed 's/^.*]*value=\"\([^"]*\)\".*$/\1/') + sessid=$(grep 'W4YSESSID' <"$HTTP_HEADER" | sed 's/^.*W4YSESSID=\([^;]*\);.*$/\1/') + + export _H1="Cookie: W4YSESSID=$sessid" + export _H2="X-Requested-With: XMLHttpRequest" + body="_username=$username&_password=$password&_csrf_token=$csrf_token" + ret=$(_post "$body" "$WORLD4YOU_API/login" '' POST 'application/x-www-form-urlencoded') + unset _H2 + _debug ret "$ret" + if _contains "$ret" "\"success\":true"; then + _info "Successfully logged in" + sessid=$(grep 'W4YSESSID' <"$HTTP_HEADER" | sed 's/^.*W4YSESSID=\([^;]*\);.*$/\1/') + else + _err "Unable to log in: $(echo "$ret" | sed 's/^.*"message":"\([^\"]*\)".*$/\1/')" + return 1 + fi +} From 95235d69c20484d340d44d21950a76f6492e3c7e Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Thu, 26 Nov 2020 13:59:18 +0100 Subject: [PATCH 134/383] World4You using _egrep_o --- dnsapi/dns_world4you.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index ec5a0e47..b58ea89a 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -15,7 +15,7 @@ dns_world4you_add() { _debug fulldomain "$fqdn" _debug txtvalue "$value" - tld=$(echo "$fqdn" | grep -o '[^.]*\.[^.]*$') + tld=$(echo "$fqdn" | _egrep_o '[^.]*\.[^.]*$') record=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#tld} - 1))") _login @@ -69,7 +69,7 @@ dns_world4you_rm() { _debug fulldomain "$fqdn" _debug txtvalue "$value" - tld=$(echo "$fqdn" | grep -o '[^.]*\.[^.]*$') + tld=$(echo "$fqdn" | _egrep_o '[^.]*\.[^.]*$') record=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#tld} - 1))") _login From bb3cc1130b22335f5664878635db43293b367194 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Fri, 27 Nov 2020 19:34:16 +0100 Subject: [PATCH 135/383] World4You using ggrep in solaris --- dnsapi/dns_world4you.sh | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index b58ea89a..db52cda1 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -24,7 +24,7 @@ dns_world4you_add() { fi export _H1="Cookie: W4YSESSID=$sessid" - paketnr=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht" | grep -B 3 "^\\s*$tld\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\)<.*$/\1/') + paketnr=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht" | _ggrep -B 3 "^\\s*$tld\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\)<.*$/\1/') if [ -z "$paketnr" ]; then _err "Unable to parse paketnr" return 3 @@ -78,7 +78,7 @@ dns_world4you_rm() { fi export _H1="Cookie: W4YSESSID=$sessid" - paketnr=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht" | grep -B 3 "^\\s*$tld\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\).*$/\1/') + paketnr=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht" | _ggrep -B 3 "^\\s*$tld\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\).*$/\1/') if [ -z "$paketnr" ]; then _err "Unable to parse paketnr" return 3 @@ -157,3 +157,13 @@ _login() { return 1 fi } + +_ggrep() { + if _exists "ggrep"; then + ggrep $@ + return $? + else + grep $@ + return $? + fi +} From 268eaddad8845ed35af46a4f7ac36d2859a8d074 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Fri, 27 Nov 2020 19:35:53 +0100 Subject: [PATCH 136/383] World4You shellcheck --- dnsapi/dns_world4you.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index db52cda1..fbc5fe40 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -160,10 +160,10 @@ _login() { _ggrep() { if _exists "ggrep"; then - ggrep $@ + ggrep "$@" return $? else - grep $@ + grep "$@" return $? fi } From 339ff8ca773e196613db5ca29f651893c3227682 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Fri, 27 Nov 2020 22:12:11 +0100 Subject: [PATCH 137/383] World4You domain root fix --- dnsapi/dns_world4you.sh | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index fbc5fe40..502e8631 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -4,6 +4,7 @@ # Lorenz Stechauner, 2020 - https://www.github.com/NerLOR WORLD4YOU_API="https://my.world4you.com/en" +PAKETNR='' ################ Public functions ################ @@ -24,7 +25,9 @@ dns_world4you_add() { fi export _H1="Cookie: W4YSESSID=$sessid" - paketnr=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht" | _ggrep -B 3 "^\\s*$tld\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\)<.*$/\1/') + form=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht") + _get_paketnr "$tld" "$form" + paketnr="$PAKETNR" if [ -z "$paketnr" ]; then _err "Unable to parse paketnr" return 3 @@ -78,7 +81,9 @@ dns_world4you_rm() { fi export _H1="Cookie: W4YSESSID=$sessid" - paketnr=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht" | _ggrep -B 3 "^\\s*$tld\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\).*$/\1/') + form=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht") + _get_paketnr "$tld" "$form" + paketnr="$PAKETNR" if [ -z "$paketnr" ]; then _err "Unable to parse paketnr" return 3 @@ -158,6 +163,25 @@ _login() { fi } +# Usage _get_paketnr
+_get_paketnr() { + tld="$1" + form="$2" + + domains=($(echo "$form" | _ggrep -E '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/')) + paketnrs=($(echo "$form" | _ggrep -B 3 -E '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed -n '1~5p' | sed 's/^.*>\([0-9][0-9]*\).*$/\1/')) + + total="${#domains[*]}" + for (( i=0; i<=$(( $total - 1 )); i++ )); do + domain="${domains[$i]}" + if [ $(echo "$domain" | grep "$tld\$") ]; then + PAKETNR="${paketnrs[$i]}" + return 0 + fi + done + return 1 +} + _ggrep() { if _exists "ggrep"; then ggrep "$@" From 2e15371d616a3b83c4cdc3b51176edf2d1d2966d Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Fri, 27 Nov 2020 22:22:50 +0100 Subject: [PATCH 138/383] World4You posix shell --- dnsapi/dns_world4you.sh | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 502e8631..8e12dd5f 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -168,18 +168,19 @@ _get_paketnr() { tld="$1" form="$2" - domains=($(echo "$form" | _ggrep -E '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/')) - paketnrs=($(echo "$form" | _ggrep -B 3 -E '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed -n '1~5p' | sed 's/^.*>\([0-9][0-9]*\).*$/\1/')) - - total="${#domains[*]}" - for (( i=0; i<=$(( $total - 1 )); i++ )); do - domain="${domains[$i]}" + domains=$(echo "$form" | _ggrep -E '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/') + domain='' + for domain in $domains; do if [ $(echo "$domain" | grep "$tld\$") ]; then - PAKETNR="${paketnrs[$i]}" - return 0 + break fi done - return 1 + if [ -z "$domain" ]; then + return 1 + fi + + PAKETNR=$(echo "$form" | _ggrep -B 3 "^\\s*$domain\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\).*$/\1/') + return 0 } _ggrep() { From 42583cf3bb6d4ea091491533d33d1717f746065f Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Fri, 27 Nov 2020 22:25:29 +0100 Subject: [PATCH 139/383] World4You Shellcheck --- dnsapi/dns_world4you.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 8e12dd5f..e1585801 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -171,7 +171,7 @@ _get_paketnr() { domains=$(echo "$form" | _ggrep -E '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/') domain='' for domain in $domains; do - if [ $(echo "$domain" | grep "$tld\$") ]; then + if [ "$(echo "$domain" | grep -q "$tld\$")" ]; then break fi done From 198b8400597881a82bf8c3cc1f14edf32068862a Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Fri, 27 Nov 2020 22:27:10 +0100 Subject: [PATCH 140/383] World4You grep -q --- dnsapi/dns_world4you.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index e1585801..2be5a6b9 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -171,7 +171,7 @@ _get_paketnr() { domains=$(echo "$form" | _ggrep -E '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/') domain='' for domain in $domains; do - if [ "$(echo "$domain" | grep -q "$tld\$")" ]; then + if $(echo "$domain" | grep -q "$tld\$"; then break fi done From dcb4cb3a1e439661b4f0fd2d1b63fa61c78b0f1a Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Fri, 27 Nov 2020 22:28:25 +0100 Subject: [PATCH 141/383] World4You Bugfix --- dnsapi/dns_world4you.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 2be5a6b9..e1ced163 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -171,7 +171,7 @@ _get_paketnr() { domains=$(echo "$form" | _ggrep -E '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/') domain='' for domain in $domains; do - if $(echo "$domain" | grep -q "$tld\$"; then + if $(echo "$domain" | grep -q "$tld\$"); then break fi done From f3987b453c4115fb19a565dfe4850fd2dff0d595 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Fri, 27 Nov 2020 22:29:31 +0100 Subject: [PATCH 142/383] World4You Bugfix 2 --- dnsapi/dns_world4you.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index e1ced163..4c0be782 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -171,7 +171,7 @@ _get_paketnr() { domains=$(echo "$form" | _ggrep -E '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/') domain='' for domain in $domains; do - if $(echo "$domain" | grep -q "$tld\$"); then + if echo "$domain" | grep -q "$tld\$"; then break fi done From 9474933070bf18c5cfc0a298f3da54790be141af Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sat, 28 Nov 2020 08:50:47 +0100 Subject: [PATCH 143/383] World4You dns root parsing --- dnsapi/dns_world4you.sh | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 4c0be782..455418a5 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -5,6 +5,8 @@ WORLD4YOU_API="https://my.world4you.com/en" PAKETNR='' +TLD='' +RECORD='' ################ Public functions ################ @@ -16,9 +18,6 @@ dns_world4you_add() { _debug fulldomain "$fqdn" _debug txtvalue "$value" - tld=$(echo "$fqdn" | _egrep_o '[^.]*\.[^.]*$') - record=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#tld} - 1))") - _login if [ "$?" != 0 ]; then return 1 @@ -26,8 +25,10 @@ dns_world4you_add() { export _H1="Cookie: W4YSESSID=$sessid" form=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht") - _get_paketnr "$tld" "$form" + _get_paketnr "$fqdn" "$form" paketnr="$PAKETNR" + tld="$TLD" + record="$RECORD" if [ -z "$paketnr" ]; then _err "Unable to parse paketnr" return 3 @@ -82,8 +83,10 @@ dns_world4you_rm() { export _H1="Cookie: W4YSESSID=$sessid" form=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht") - _get_paketnr "$tld" "$form" + _get_paketnr "$fqdn" "$form" paketnr="$PAKETNR" + tld="$TLD" + record="$RECORD" if [ -z "$paketnr" ]; then _err "Unable to parse paketnr" return 3 @@ -163,22 +166,25 @@ _login() { fi } -# Usage _get_paketnr +# Usage _get_paketnr _get_paketnr() { - tld="$1" + fqdn="$1" form="$2" domains=$(echo "$form" | _ggrep -E '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/') domain='' for domain in $domains; do - if echo "$domain" | grep -q "$tld\$"; then + if echo "$fqdn" | grep -q "$domain\$"; then break fi + domain='' done if [ -z "$domain" ]; then return 1 fi + TLD="$domain" + RECORD=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#TLD} - 1))") PAKETNR=$(echo "$form" | _ggrep -B 3 "^\\s*$domain\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\).*$/\1/') return 0 } From ed01fd4edfd76fe96a1d38af3731f6efb46c904c Mon Sep 17 00:00:00 2001 From: Moritz H Date: Sat, 28 Nov 2020 15:22:14 +0100 Subject: [PATCH 144/383] uconv as fallback for iconv --- deploy/fritzbox.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index 89b19806..2ca7ab7d 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -28,9 +28,11 @@ fritzbox_deploy() { _debug _cfullchain "$_cfullchain" if ! _exists iconv; then - if ! _exists perl; then - _err "iconv or perl not found" - return 1 + if ! _exists uconv; then + if ! _exists perl; then + _err "iconv or uconv or perl not found" + return 1 + fi fi fi @@ -65,6 +67,8 @@ fritzbox_deploy() { _fritzbox_challenge="$(_get "${_fritzbox_url}/login_sid.lua" | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" if _exists iconv; then _fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | iconv -f ASCII -t UTF16LE | _digest md5 hex)" + elif _exists uconv; then + _fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | uconv -f ASCII -t UTF16LE | _digest md5 hex)" else _fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | perl -p -e 'use Encode qw/encode/; print encode("UTF-16LE","$_"); $_="";' | _digest md5 hex)" fi From 0ed2659698ac08a175eb50ad1c5c27d69346bd2c Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sat, 28 Nov 2020 17:27:50 +0100 Subject: [PATCH 145/383] World4You using ggrep more often --- dnsapi/dns_world4you.sh | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 455418a5..10c1628b 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -56,8 +56,7 @@ AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_toke _ACME_CURL="$_ORIG_ACME_CURL" - success=$(grep '302\|200' <"$HTTP_HEADER") - if [ "$success" ]; then + if _ggrep -q '302\|200' <"$HTTP_HEADER"; then return 0 else _err "$(head -n 1 <"$HTTP_HEADER")" @@ -116,8 +115,7 @@ DeleteDnsRecordForm[_token]=$form_token" _ACME_CURL="$_ORIG_ACME_CURL" - success=$(grep '302\|200' <"$HTTP_HEADER") - if [ "$success" ]; then + if _ggrep -q '302\|200' <"$HTTP_HEADER"; then return 0 else _err "$(head -n 1 <"$HTTP_HEADER")" From 1987c32761cc8ae20263400ccbe8822c8f9911e3 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 29 Nov 2020 09:34:52 +0100 Subject: [PATCH 146/383] World4You using _egrep_o instead of grep -E --- dnsapi/dns_world4you.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 10c1628b..bcb01619 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -169,7 +169,7 @@ _get_paketnr() { fqdn="$1" form="$2" - domains=$(echo "$form" | _ggrep -E '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/') + domains=$(echo "$form" | _egrep_o '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/') domain='' for domain in $domains; do if echo "$fqdn" | grep -q "$domain\$"; then From 9fee0805c41539d8cec2a56a694882b36141432d Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 29 Nov 2020 09:40:35 +0100 Subject: [PATCH 147/383] World4You using /dev/null instead of grep -q --- dnsapi/dns_world4you.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index bcb01619..fff8089d 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -56,7 +56,7 @@ AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_toke _ACME_CURL="$_ORIG_ACME_CURL" - if _ggrep -q '302\|200' <"$HTTP_HEADER"; then + if _ggrep '302\|200' >/dev/null <"$HTTP_HEADER"; then return 0 else _err "$(head -n 1 <"$HTTP_HEADER")" @@ -115,7 +115,7 @@ DeleteDnsRecordForm[_token]=$form_token" _ACME_CURL="$_ORIG_ACME_CURL" - if _ggrep -q '302\|200' <"$HTTP_HEADER"; then + if _ggrep '302\|200' >/dev/null <"$HTTP_HEADER"; then return 0 else _err "$(head -n 1 <"$HTTP_HEADER")" @@ -172,7 +172,7 @@ _get_paketnr() { domains=$(echo "$form" | _egrep_o '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/') domain='' for domain in $domains; do - if echo "$fqdn" | grep -q "$domain\$"; then + if echo "$fqdn" | grep "$domain\$" >/dev/null; then break fi domain='' From 2dd8527566fb37431abb84c52d526a7069345bea Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 29 Nov 2020 10:33:46 +0100 Subject: [PATCH 148/383] World4You success on 302 instead of 302 or 200 --- dnsapi/dns_world4you.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index fff8089d..76acacf8 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -56,7 +56,7 @@ AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_toke _ACME_CURL="$_ORIG_ACME_CURL" - if _ggrep '302\|200' >/dev/null <"$HTTP_HEADER"; then + if grep '302' >/dev/null <"$HTTP_HEADER"; then return 0 else _err "$(head -n 1 <"$HTTP_HEADER")" @@ -115,7 +115,7 @@ DeleteDnsRecordForm[_token]=$form_token" _ACME_CURL="$_ORIG_ACME_CURL" - if _ggrep '302\|200' >/dev/null <"$HTTP_HEADER"; then + if grep '302' >/dev/null <"$HTTP_HEADER"; then return 0 else _err "$(head -n 1 <"$HTTP_HEADER")" From 6c039d2ad080c58d36ea6775bbf2fbffa269a7cb Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 29 Nov 2020 10:43:25 +0100 Subject: [PATCH 149/383] World4You removed _ggrep --- dnsapi/dns_world4you.sh | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 76acacf8..573c5ee6 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -183,16 +183,6 @@ _get_paketnr() { TLD="$domain" RECORD=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#TLD} - 1))") - PAKETNR=$(echo "$form" | _ggrep -B 3 "^\\s*$domain\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\).*$/\1/') + PAKETNR=$(echo "$form" | _egrep_o "data-textfilter=\" $domain .* [0-9]*" | head -n 1 | _egrep_o "[0-9]*") return 0 } - -_ggrep() { - if _exists "ggrep"; then - ggrep "$@" - return $? - else - grep "$@" - return $? - fi -} From effa7fd57d2a36233f8c3f3d29bac0789a9a12b4 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 29 Nov 2020 18:39:11 +0800 Subject: [PATCH 150/383] add ACME_HTTP_NO_REDIRECTS and _resethttp to make http requests not follow redirects --- acme.sh | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index b234fb26..dcbe3c9d 100755 --- a/acme.sh +++ b/acme.sh @@ -1722,6 +1722,14 @@ _mktemp() { _err "Can not create temp file." } +#clear all the https envs to cause _inithttp() to run next time. +_resethttp() { + __HTTP_INITIALIZED="" + _ACME_CURL="" + _ACME_WGET="" + ACME_HTTP_NO_REDIRECTS="" +} + _inithttp() { if [ -z "$HTTP_HEADER" ] || ! touch "$HTTP_HEADER"; then @@ -1737,7 +1745,10 @@ _inithttp() { fi if [ -z "$_ACME_CURL" ] && _exists "curl"; then - _ACME_CURL="curl -L --silent --dump-header $HTTP_HEADER " + _ACME_CURL="curl --silent --dump-header $HTTP_HEADER " + if [ -z "$ACME_HTTP_NO_REDIRECTS" ]; then + _ACME_CURL="$_ACME_CURL -L " + fi if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then _CURL_DUMP="$(_mktemp)" _ACME_CURL="$_ACME_CURL --trace-ascii $_CURL_DUMP " @@ -1756,6 +1767,9 @@ _inithttp() { if [ -z "$_ACME_WGET" ] && _exists "wget"; then _ACME_WGET="wget -q" + if [ "$ACME_HTTP_NO_REDIRECTS" ]; then + _ACME_WGET="$_ACME_WGET --max-redirect 0 " + fi if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then _ACME_WGET="$_ACME_WGET -d " fi From 8ee5726e0cc1b3cf7e106363b958ed22472c8237 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 22 Nov 2020 11:22:54 +0100 Subject: [PATCH 151/383] Added World4You DNS API --- dnsapi/dns_world4you.sh | 159 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 dnsapi/dns_world4you.sh diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh new file mode 100644 index 00000000..ec5a0e47 --- /dev/null +++ b/dnsapi/dns_world4you.sh @@ -0,0 +1,159 @@ +#!/usr/bin/env sh + +# World4You - www.world4you.com +# Lorenz Stechauner, 2020 - https://www.github.com/NerLOR + +WORLD4YOU_API="https://my.world4you.com/en" + +################ Public functions ################ + +# Usage: dns_world4you_add +dns_world4you_add() { + fqdn="$1" + value="$2" + _info "Using world4you" + _debug fulldomain "$fqdn" + _debug txtvalue "$value" + + tld=$(echo "$fqdn" | grep -o '[^.]*\.[^.]*$') + record=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#tld} - 1))") + + _login + if [ "$?" != 0 ]; then + return 1 + fi + + export _H1="Cookie: W4YSESSID=$sessid" + paketnr=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht" | grep -B 3 "^\\s*$tld\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\)<.*$/\1/') + if [ -z "$paketnr" ]; then + _err "Unable to parse paketnr" + return 3 + fi + _debug paketnr "$paketnr" + + export _H1="Cookie: W4YSESSID=$sessid" + form=$(_get "$WORLD4YOU_API/$paketnr/dns") + formiddp=$(echo "$form" | grep 'AddDnsRecordForm\[uniqueFormIdDP\]' | sed 's/^.*name="AddDnsRecordForm\[uniqueFormIdDP\]" value="\([^"]*\)".*$/\1/') + formidttl=$(echo "$form" | grep 'AddDnsRecordForm\[uniqueFormIdTTL\]' | sed 's/^.*name="AddDnsRecordForm\[uniqueFormIdTTL\]" value="\([^"]*\)".*$/\1/') + form_token=$(echo "$form" | grep 'AddDnsRecordForm\[_token\]' | sed 's/^.*name="AddDnsRecordForm\[_token\]" value="\([^"]*\)".*$/\1/') + if [ -z "$formiddp" ]; then + _err "Unable to parse form" + return 3 + fi + + _ORIG_ACME_CURL="$_ACME_CURL" + _ACME_CURL=$(echo "$_ACME_CURL" | sed 's/ -L / /') + + body="AddDnsRecordForm[name]=$record&AddDnsRecordForm[dnsType][type]=TXT&\ +AddDnsRecordForm[value]=$value&AddDnsRecordForm[aktivPaket]=$paketnr&AddDnsRecordForm[uniqueFormIdDP]=$formiddp&\ +AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_token" + _info "Adding record..." + ret=$(_post "$body" "$WORLD4YOU_API/$paketnr/dns" '' POST 'application/x-www-form-urlencoded') + + _ACME_CURL="$_ORIG_ACME_CURL" + + success=$(grep '302\|200' <"$HTTP_HEADER") + if [ "$success" ]; then + return 0 + else + _err "$(head -n 1 <"$HTTP_HEADER")" + return 2 + fi +} + +# Usage: dns_world4you_rm +dns_world4you_rm() { + fqdn="$1" + value="$2" + _info "Using world4you" + _debug fulldomain "$fqdn" + _debug txtvalue "$value" + + tld=$(echo "$fqdn" | grep -o '[^.]*\.[^.]*$') + record=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#tld} - 1))") + + _login + if [ "$?" != 0 ]; then + return 1 + fi + + export _H1="Cookie: W4YSESSID=$sessid" + paketnr=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht" | grep -B 3 "^\\s*$tld\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\).*$/\1/') + if [ -z "$paketnr" ]; then + _err "Unable to parse paketnr" + return 3 + fi + _debug paketnr "$paketnr" + + form=$(_get "$WORLD4YOU_API/$paketnr/dns") + formiddp=$(echo "$form" | grep 'DeleteDnsRecordForm\[uniqueFormIdDP\]' | sed 's/^.*name="DeleteDnsRecordForm\[uniqueFormIdDP\]" value="\([^"]*\)".*$/\1/') + formidttl=$(echo "$form" | grep 'DeleteDnsRecordForm\[uniqueFormIdTTL\]' | sed 's/^.*name="DeleteDnsRecordForm\[uniqueFormIdTTL\]" value="\([^"]*\)".*$/\1/') + form_token=$(echo "$form" | grep 'DeleteDnsRecordForm\[_token\]' | sed 's/^.*name="DeleteDnsRecordForm\[_token\]" value="\([^"]*\)".*$/\1/') + if [ -z "$formiddp" ]; then + _err "Unable to parse form" + return 3 + fi + + recordid=$(printf "TXT:%s.:\"%s\"" "$fqdn" "$value" | _base64) + _debug recordid "$recordid" + + _ORIG_ACME_CURL="$_ACME_CURL" + _ACME_CURL=$(echo "$_ACME_CURL" | sed 's/ -L / /') + + body="DeleteDnsRecordForm[recordId]=$recordid&DeleteDnsRecordForm[aktivPaket]=$paketnr&\ +DeleteDnsRecordForm[uniqueFormIdDP]=$formiddp&DeleteDnsRecordForm[uniqueFormIdTTL]=$formidttl&\ +DeleteDnsRecordForm[_token]=$form_token" + _info "Removing record..." + ret=$(_post "$body" "$WORLD4YOU_API/$paketnr/deleteRecord" '' POST 'application/x-www-form-urlencoded') + + _ACME_CURL="$_ORIG_ACME_CURL" + + success=$(grep '302\|200' <"$HTTP_HEADER") + if [ "$success" ]; then + return 0 + else + _err "$(head -n 1 <"$HTTP_HEADER")" + return 2 + fi +} + +################ Private functions ################ + +# Usage: _login +_login() { + WORLD4YOU_USERNAME="${WORLD4YOU_USERNAME:-$(_readaccountconf_mutable WORLD4YOU_USERNAME)}" + WORLD4YOU_PASSWORD="${WORLD4YOU_PASSWORD:-$(_readaccountconf_mutable WORLD4YOU_PASSWORD)}" + + if [ -z "$WORLD4YOU_USERNAME" ] || [ -z "$WORLD4YOU_PASSWORD" ]; then + WORLD4YOU_USERNAME="" + WORLD4YOU_PASSWORD="" + _err "You don't specified world4you username and password yet." + _err "Usage: export WORLD4YOU_USERNAME=" + _err "Usage: export WORLD4YOU_PASSWORD=" + return 2 + fi + + _saveaccountconf_mutable WORLD4YOU_USERNAME "$WORLD4YOU_USERNAME" + _saveaccountconf_mutable WORLD4YOU_PASSWORD "$WORLD4YOU_PASSWORD" + + _info "Logging in..." + + username="$WORLD4YOU_USERNAME" + password="$WORLD4YOU_PASSWORD" + csrf_token=$(_get "$WORLD4YOU_API/login" | grep '_csrf_token' | sed 's/^.*]*value=\"\([^"]*\)\".*$/\1/') + sessid=$(grep 'W4YSESSID' <"$HTTP_HEADER" | sed 's/^.*W4YSESSID=\([^;]*\);.*$/\1/') + + export _H1="Cookie: W4YSESSID=$sessid" + export _H2="X-Requested-With: XMLHttpRequest" + body="_username=$username&_password=$password&_csrf_token=$csrf_token" + ret=$(_post "$body" "$WORLD4YOU_API/login" '' POST 'application/x-www-form-urlencoded') + unset _H2 + _debug ret "$ret" + if _contains "$ret" "\"success\":true"; then + _info "Successfully logged in" + sessid=$(grep 'W4YSESSID' <"$HTTP_HEADER" | sed 's/^.*W4YSESSID=\([^;]*\);.*$/\1/') + else + _err "Unable to log in: $(echo "$ret" | sed 's/^.*"message":"\([^\"]*\)".*$/\1/')" + return 1 + fi +} From f3b5d5ab7b7dcebc595ce281f13827f7d051dfbf Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Thu, 26 Nov 2020 13:59:18 +0100 Subject: [PATCH 152/383] World4You using _egrep_o --- dnsapi/dns_world4you.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index ec5a0e47..b58ea89a 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -15,7 +15,7 @@ dns_world4you_add() { _debug fulldomain "$fqdn" _debug txtvalue "$value" - tld=$(echo "$fqdn" | grep -o '[^.]*\.[^.]*$') + tld=$(echo "$fqdn" | _egrep_o '[^.]*\.[^.]*$') record=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#tld} - 1))") _login @@ -69,7 +69,7 @@ dns_world4you_rm() { _debug fulldomain "$fqdn" _debug txtvalue "$value" - tld=$(echo "$fqdn" | grep -o '[^.]*\.[^.]*$') + tld=$(echo "$fqdn" | _egrep_o '[^.]*\.[^.]*$') record=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#tld} - 1))") _login From 9449501537a84385f9431f411ecb8e0e41c8670a Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Fri, 27 Nov 2020 19:34:16 +0100 Subject: [PATCH 153/383] World4You using ggrep in solaris --- dnsapi/dns_world4you.sh | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index b58ea89a..db52cda1 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -24,7 +24,7 @@ dns_world4you_add() { fi export _H1="Cookie: W4YSESSID=$sessid" - paketnr=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht" | grep -B 3 "^\\s*$tld\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\)<.*$/\1/') + paketnr=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht" | _ggrep -B 3 "^\\s*$tld\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\)<.*$/\1/') if [ -z "$paketnr" ]; then _err "Unable to parse paketnr" return 3 @@ -78,7 +78,7 @@ dns_world4you_rm() { fi export _H1="Cookie: W4YSESSID=$sessid" - paketnr=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht" | grep -B 3 "^\\s*$tld\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\).*$/\1/') + paketnr=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht" | _ggrep -B 3 "^\\s*$tld\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\).*$/\1/') if [ -z "$paketnr" ]; then _err "Unable to parse paketnr" return 3 @@ -157,3 +157,13 @@ _login() { return 1 fi } + +_ggrep() { + if _exists "ggrep"; then + ggrep $@ + return $? + else + grep $@ + return $? + fi +} From f9dfd3b3485c03b3fae9e975dec50112fde26e57 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Fri, 27 Nov 2020 19:35:53 +0100 Subject: [PATCH 154/383] World4You shellcheck --- dnsapi/dns_world4you.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index db52cda1..fbc5fe40 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -160,10 +160,10 @@ _login() { _ggrep() { if _exists "ggrep"; then - ggrep $@ + ggrep "$@" return $? else - grep $@ + grep "$@" return $? fi } From abe05456f785c222fd06a4062a2533b72f73a058 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Fri, 27 Nov 2020 22:12:11 +0100 Subject: [PATCH 155/383] World4You domain root fix --- dnsapi/dns_world4you.sh | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index fbc5fe40..502e8631 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -4,6 +4,7 @@ # Lorenz Stechauner, 2020 - https://www.github.com/NerLOR WORLD4YOU_API="https://my.world4you.com/en" +PAKETNR='' ################ Public functions ################ @@ -24,7 +25,9 @@ dns_world4you_add() { fi export _H1="Cookie: W4YSESSID=$sessid" - paketnr=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht" | _ggrep -B 3 "^\\s*$tld\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\)<.*$/\1/') + form=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht") + _get_paketnr "$tld" "$form" + paketnr="$PAKETNR" if [ -z "$paketnr" ]; then _err "Unable to parse paketnr" return 3 @@ -78,7 +81,9 @@ dns_world4you_rm() { fi export _H1="Cookie: W4YSESSID=$sessid" - paketnr=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht" | _ggrep -B 3 "^\\s*$tld\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\).*$/\1/') + form=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht") + _get_paketnr "$tld" "$form" + paketnr="$PAKETNR" if [ -z "$paketnr" ]; then _err "Unable to parse paketnr" return 3 @@ -158,6 +163,25 @@ _login() { fi } +# Usage _get_paketnr +_get_paketnr() { + tld="$1" + form="$2" + + domains=($(echo "$form" | _ggrep -E '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/')) + paketnrs=($(echo "$form" | _ggrep -B 3 -E '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed -n '1~5p' | sed 's/^.*>\([0-9][0-9]*\).*$/\1/')) + + total="${#domains[*]}" + for (( i=0; i<=$(( $total - 1 )); i++ )); do + domain="${domains[$i]}" + if [ $(echo "$domain" | grep "$tld\$") ]; then + PAKETNR="${paketnrs[$i]}" + return 0 + fi + done + return 1 +} + _ggrep() { if _exists "ggrep"; then ggrep "$@" From ef9147512b20499ac57442f58d3d1bcfdbd9c9bf Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Fri, 27 Nov 2020 22:22:50 +0100 Subject: [PATCH 156/383] World4You posix shell --- dnsapi/dns_world4you.sh | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 502e8631..8e12dd5f 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -168,18 +168,19 @@ _get_paketnr() { tld="$1" form="$2" - domains=($(echo "$form" | _ggrep -E '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/')) - paketnrs=($(echo "$form" | _ggrep -B 3 -E '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed -n '1~5p' | sed 's/^.*>\([0-9][0-9]*\).*$/\1/')) - - total="${#domains[*]}" - for (( i=0; i<=$(( $total - 1 )); i++ )); do - domain="${domains[$i]}" + domains=$(echo "$form" | _ggrep -E '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/') + domain='' + for domain in $domains; do if [ $(echo "$domain" | grep "$tld\$") ]; then - PAKETNR="${paketnrs[$i]}" - return 0 + break fi done - return 1 + if [ -z "$domain" ]; then + return 1 + fi + + PAKETNR=$(echo "$form" | _ggrep -B 3 "^\\s*$domain\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\).*$/\1/') + return 0 } _ggrep() { From 895da5cbf07eb333610a9b4acaf39e536ae7a9d9 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Fri, 27 Nov 2020 22:25:29 +0100 Subject: [PATCH 157/383] World4You Shellcheck --- dnsapi/dns_world4you.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 8e12dd5f..e1585801 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -171,7 +171,7 @@ _get_paketnr() { domains=$(echo "$form" | _ggrep -E '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/') domain='' for domain in $domains; do - if [ $(echo "$domain" | grep "$tld\$") ]; then + if [ "$(echo "$domain" | grep -q "$tld\$")" ]; then break fi done From 46611857195f9c53286738f44c11ed42a65805cc Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Fri, 27 Nov 2020 22:27:10 +0100 Subject: [PATCH 158/383] World4You grep -q --- dnsapi/dns_world4you.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index e1585801..2be5a6b9 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -171,7 +171,7 @@ _get_paketnr() { domains=$(echo "$form" | _ggrep -E '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/') domain='' for domain in $domains; do - if [ "$(echo "$domain" | grep -q "$tld\$")" ]; then + if $(echo "$domain" | grep -q "$tld\$"; then break fi done From 2edc4a79b9ff3c8668220b4d2a80624320c3b0fa Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Fri, 27 Nov 2020 22:28:25 +0100 Subject: [PATCH 159/383] World4You Bugfix --- dnsapi/dns_world4you.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 2be5a6b9..e1ced163 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -171,7 +171,7 @@ _get_paketnr() { domains=$(echo "$form" | _ggrep -E '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/') domain='' for domain in $domains; do - if $(echo "$domain" | grep -q "$tld\$"; then + if $(echo "$domain" | grep -q "$tld\$"); then break fi done From 13f6ec04d55b15f0620ee30d4f370c017425715a Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Fri, 27 Nov 2020 22:29:31 +0100 Subject: [PATCH 160/383] World4You Bugfix 2 --- dnsapi/dns_world4you.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index e1ced163..4c0be782 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -171,7 +171,7 @@ _get_paketnr() { domains=$(echo "$form" | _ggrep -E '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/') domain='' for domain in $domains; do - if $(echo "$domain" | grep -q "$tld\$"); then + if echo "$domain" | grep -q "$tld\$"; then break fi done From 5cfe5e312b15846ed1711b6da35ca5c6f47c11b8 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sat, 28 Nov 2020 08:50:47 +0100 Subject: [PATCH 161/383] World4You dns root parsing --- dnsapi/dns_world4you.sh | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 4c0be782..455418a5 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -5,6 +5,8 @@ WORLD4YOU_API="https://my.world4you.com/en" PAKETNR='' +TLD='' +RECORD='' ################ Public functions ################ @@ -16,9 +18,6 @@ dns_world4you_add() { _debug fulldomain "$fqdn" _debug txtvalue "$value" - tld=$(echo "$fqdn" | _egrep_o '[^.]*\.[^.]*$') - record=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#tld} - 1))") - _login if [ "$?" != 0 ]; then return 1 @@ -26,8 +25,10 @@ dns_world4you_add() { export _H1="Cookie: W4YSESSID=$sessid" form=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht") - _get_paketnr "$tld" "$form" + _get_paketnr "$fqdn" "$form" paketnr="$PAKETNR" + tld="$TLD" + record="$RECORD" if [ -z "$paketnr" ]; then _err "Unable to parse paketnr" return 3 @@ -82,8 +83,10 @@ dns_world4you_rm() { export _H1="Cookie: W4YSESSID=$sessid" form=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht") - _get_paketnr "$tld" "$form" + _get_paketnr "$fqdn" "$form" paketnr="$PAKETNR" + tld="$TLD" + record="$RECORD" if [ -z "$paketnr" ]; then _err "Unable to parse paketnr" return 3 @@ -163,22 +166,25 @@ _login() { fi } -# Usage _get_paketnr +# Usage _get_paketnr _get_paketnr() { - tld="$1" + fqdn="$1" form="$2" domains=$(echo "$form" | _ggrep -E '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/') domain='' for domain in $domains; do - if echo "$domain" | grep -q "$tld\$"; then + if echo "$fqdn" | grep -q "$domain\$"; then break fi + domain='' done if [ -z "$domain" ]; then return 1 fi + TLD="$domain" + RECORD=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#TLD} - 1))") PAKETNR=$(echo "$form" | _ggrep -B 3 "^\\s*$domain\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\).*$/\1/') return 0 } From a0edb8f2ad8bbc193e52c10e052fbdf4541dcf80 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sat, 28 Nov 2020 17:27:50 +0100 Subject: [PATCH 162/383] World4You using ggrep more often --- dnsapi/dns_world4you.sh | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 455418a5..10c1628b 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -56,8 +56,7 @@ AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_toke _ACME_CURL="$_ORIG_ACME_CURL" - success=$(grep '302\|200' <"$HTTP_HEADER") - if [ "$success" ]; then + if _ggrep -q '302\|200' <"$HTTP_HEADER"; then return 0 else _err "$(head -n 1 <"$HTTP_HEADER")" @@ -116,8 +115,7 @@ DeleteDnsRecordForm[_token]=$form_token" _ACME_CURL="$_ORIG_ACME_CURL" - success=$(grep '302\|200' <"$HTTP_HEADER") - if [ "$success" ]; then + if _ggrep -q '302\|200' <"$HTTP_HEADER"; then return 0 else _err "$(head -n 1 <"$HTTP_HEADER")" From 35cab4ee7398edd9547acabeabc6937fec153ccf Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 29 Nov 2020 09:34:52 +0100 Subject: [PATCH 163/383] World4You using _egrep_o instead of grep -E --- dnsapi/dns_world4you.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 10c1628b..bcb01619 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -169,7 +169,7 @@ _get_paketnr() { fqdn="$1" form="$2" - domains=$(echo "$form" | _ggrep -E '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/') + domains=$(echo "$form" | _egrep_o '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/') domain='' for domain in $domains; do if echo "$fqdn" | grep -q "$domain\$"; then From 3d79d78134dd6f19be2e7f6f11be06c08450de79 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 29 Nov 2020 09:40:35 +0100 Subject: [PATCH 164/383] World4You using /dev/null instead of grep -q --- dnsapi/dns_world4you.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index bcb01619..fff8089d 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -56,7 +56,7 @@ AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_toke _ACME_CURL="$_ORIG_ACME_CURL" - if _ggrep -q '302\|200' <"$HTTP_HEADER"; then + if _ggrep '302\|200' >/dev/null <"$HTTP_HEADER"; then return 0 else _err "$(head -n 1 <"$HTTP_HEADER")" @@ -115,7 +115,7 @@ DeleteDnsRecordForm[_token]=$form_token" _ACME_CURL="$_ORIG_ACME_CURL" - if _ggrep -q '302\|200' <"$HTTP_HEADER"; then + if _ggrep '302\|200' >/dev/null <"$HTTP_HEADER"; then return 0 else _err "$(head -n 1 <"$HTTP_HEADER")" @@ -172,7 +172,7 @@ _get_paketnr() { domains=$(echo "$form" | _egrep_o '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/') domain='' for domain in $domains; do - if echo "$fqdn" | grep -q "$domain\$"; then + if echo "$fqdn" | grep "$domain\$" >/dev/null; then break fi domain='' From faf6c1671739af4ac9414423231da34ed6c6465c Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 29 Nov 2020 10:33:46 +0100 Subject: [PATCH 165/383] World4You success on 302 instead of 302 or 200 --- dnsapi/dns_world4you.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index fff8089d..76acacf8 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -56,7 +56,7 @@ AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_toke _ACME_CURL="$_ORIG_ACME_CURL" - if _ggrep '302\|200' >/dev/null <"$HTTP_HEADER"; then + if grep '302' >/dev/null <"$HTTP_HEADER"; then return 0 else _err "$(head -n 1 <"$HTTP_HEADER")" @@ -115,7 +115,7 @@ DeleteDnsRecordForm[_token]=$form_token" _ACME_CURL="$_ORIG_ACME_CURL" - if _ggrep '302\|200' >/dev/null <"$HTTP_HEADER"; then + if grep '302' >/dev/null <"$HTTP_HEADER"; then return 0 else _err "$(head -n 1 <"$HTTP_HEADER")" From c3d7f2f1708d13eb4d434fc27830a99f268e724a Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 29 Nov 2020 10:43:25 +0100 Subject: [PATCH 166/383] World4You removed _ggrep --- dnsapi/dns_world4you.sh | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 76acacf8..573c5ee6 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -183,16 +183,6 @@ _get_paketnr() { TLD="$domain" RECORD=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#TLD} - 1))") - PAKETNR=$(echo "$form" | _ggrep -B 3 "^\\s*$domain\$" | head -n 1 | sed 's/^.*>\([0-9][0-9]*\).*$/\1/') + PAKETNR=$(echo "$form" | _egrep_o "data-textfilter=\" $domain .* [0-9]*" | head -n 1 | _egrep_o "[0-9]*") return 0 } - -_ggrep() { - if _exists "ggrep"; then - ggrep "$@" - return $? - else - grep "$@" - return $? - fi -} From 0dcf6771e736c6587d3dc064c95ad07059cbf2f6 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 29 Nov 2020 11:51:16 +0100 Subject: [PATCH 167/383] World4you grammar --- dnsapi/dns_world4you.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 573c5ee6..87f6885f 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -133,7 +133,7 @@ _login() { if [ -z "$WORLD4YOU_USERNAME" ] || [ -z "$WORLD4YOU_PASSWORD" ]; then WORLD4YOU_USERNAME="" WORLD4YOU_PASSWORD="" - _err "You don't specified world4you username and password yet." + _err "You didn't specify world4you username and password yet." _err "Usage: export WORLD4YOU_USERNAME=" _err "Usage: export WORLD4YOU_PASSWORD=" return 2 From 1e3bb1f02b674e37d6dd15096782eea2e3cafb0a Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 29 Nov 2020 11:51:59 +0100 Subject: [PATCH 168/383] World4You head_n --- dnsapi/dns_world4you.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 87f6885f..3db6db72 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -59,7 +59,7 @@ AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_toke if grep '302' >/dev/null <"$HTTP_HEADER"; then return 0 else - _err "$(head -n 1 <"$HTTP_HEADER")" + _err "$(head_n 1 <"$HTTP_HEADER")" return 2 fi } @@ -118,7 +118,7 @@ DeleteDnsRecordForm[_token]=$form_token" if grep '302' >/dev/null <"$HTTP_HEADER"; then return 0 else - _err "$(head -n 1 <"$HTTP_HEADER")" + _err "$(head_n 1 <"$HTTP_HEADER")" return 2 fi } @@ -183,6 +183,6 @@ _get_paketnr() { TLD="$domain" RECORD=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#TLD} - 1))") - PAKETNR=$(echo "$form" | _egrep_o "data-textfilter=\" $domain .* [0-9]*" | head -n 1 | _egrep_o "[0-9]*") + PAKETNR=$(echo "$form" | _egrep_o "data-textfilter=\" $domain .* [0-9]*" | head_n 1 | _egrep_o "[0-9]*") return 0 } From bfccf29ccf9605df86f74a19b6d8156da590e2f1 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 29 Nov 2020 11:55:22 +0100 Subject: [PATCH 169/383] World4You redirect fix --- dnsapi/dns_world4you.sh | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 3db6db72..c8ad43c2 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -45,8 +45,8 @@ dns_world4you_add() { return 3 fi - _ORIG_ACME_CURL="$_ACME_CURL" - _ACME_CURL=$(echo "$_ACME_CURL" | sed 's/ -L / /') + ACME_HTTP_NO_REDIRECTS=1 + _resethttp body="AddDnsRecordForm[name]=$record&AddDnsRecordForm[dnsType][type]=TXT&\ AddDnsRecordForm[value]=$value&AddDnsRecordForm[aktivPaket]=$paketnr&AddDnsRecordForm[uniqueFormIdDP]=$formiddp&\ @@ -54,7 +54,8 @@ AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_toke _info "Adding record..." ret=$(_post "$body" "$WORLD4YOU_API/$paketnr/dns" '' POST 'application/x-www-form-urlencoded') - _ACME_CURL="$_ORIG_ACME_CURL" + unset ACME_HTTP_NO_REDIRECTS + _resethttp if grep '302' >/dev/null <"$HTTP_HEADER"; then return 0 @@ -104,8 +105,8 @@ dns_world4you_rm() { recordid=$(printf "TXT:%s.:\"%s\"" "$fqdn" "$value" | _base64) _debug recordid "$recordid" - _ORIG_ACME_CURL="$_ACME_CURL" - _ACME_CURL=$(echo "$_ACME_CURL" | sed 's/ -L / /') + ACME_HTTP_NO_REDIRECTS=1 + _resethttp body="DeleteDnsRecordForm[recordId]=$recordid&DeleteDnsRecordForm[aktivPaket]=$paketnr&\ DeleteDnsRecordForm[uniqueFormIdDP]=$formiddp&DeleteDnsRecordForm[uniqueFormIdTTL]=$formidttl&\ @@ -113,7 +114,8 @@ DeleteDnsRecordForm[_token]=$form_token" _info "Removing record..." ret=$(_post "$body" "$WORLD4YOU_API/$paketnr/deleteRecord" '' POST 'application/x-www-form-urlencoded') - _ACME_CURL="$_ORIG_ACME_CURL" + unset ACME_HTTP_NO_REDIRECTS + _resethttp if grep '302' >/dev/null <"$HTTP_HEADER"; then return 0 From 5f3e7f02ccb720a6367ce320b7b754842da4d9e6 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 29 Nov 2020 11:55:49 +0100 Subject: [PATCH 170/383] World4You _head_n fix --- dnsapi/dns_world4you.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index c8ad43c2..2fcdc114 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -60,7 +60,7 @@ AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_toke if grep '302' >/dev/null <"$HTTP_HEADER"; then return 0 else - _err "$(head_n 1 <"$HTTP_HEADER")" + _err "$(_head_n 1 <"$HTTP_HEADER")" return 2 fi } @@ -120,7 +120,7 @@ DeleteDnsRecordForm[_token]=$form_token" if grep '302' >/dev/null <"$HTTP_HEADER"; then return 0 else - _err "$(head_n 1 <"$HTTP_HEADER")" + _err "$(_head_n 1 <"$HTTP_HEADER")" return 2 fi } @@ -185,6 +185,6 @@ _get_paketnr() { TLD="$domain" RECORD=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#TLD} - 1))") - PAKETNR=$(echo "$form" | _egrep_o "data-textfilter=\" $domain .* [0-9]*" | head_n 1 | _egrep_o "[0-9]*") + PAKETNR=$(echo "$form" | _egrep_o "data-textfilter=\" $domain .* [0-9]*" | _head_n 1 | _egrep_o "[0-9]*") return 0 } From 342b48105fcd32048cb7a893fc9aa03f6308f0d7 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 29 Nov 2020 12:02:05 +0100 Subject: [PATCH 171/383] World4You fix for no redirects --- dnsapi/dns_world4you.sh | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 2fcdc114..0ea969a1 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -45,8 +45,8 @@ dns_world4you_add() { return 3 fi - ACME_HTTP_NO_REDIRECTS=1 _resethttp + ACME_HTTP_NO_REDIRECTS=1 body="AddDnsRecordForm[name]=$record&AddDnsRecordForm[dnsType][type]=TXT&\ AddDnsRecordForm[value]=$value&AddDnsRecordForm[aktivPaket]=$paketnr&AddDnsRecordForm[uniqueFormIdDP]=$formiddp&\ @@ -54,7 +54,6 @@ AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_toke _info "Adding record..." ret=$(_post "$body" "$WORLD4YOU_API/$paketnr/dns" '' POST 'application/x-www-form-urlencoded') - unset ACME_HTTP_NO_REDIRECTS _resethttp if grep '302' >/dev/null <"$HTTP_HEADER"; then @@ -105,8 +104,8 @@ dns_world4you_rm() { recordid=$(printf "TXT:%s.:\"%s\"" "$fqdn" "$value" | _base64) _debug recordid "$recordid" - ACME_HTTP_NO_REDIRECTS=1 _resethttp + ACME_HTTP_NO_REDIRECTS=1 body="DeleteDnsRecordForm[recordId]=$recordid&DeleteDnsRecordForm[aktivPaket]=$paketnr&\ DeleteDnsRecordForm[uniqueFormIdDP]=$formiddp&DeleteDnsRecordForm[uniqueFormIdTTL]=$formidttl&\ @@ -114,7 +113,6 @@ DeleteDnsRecordForm[_token]=$form_token" _info "Removing record..." ret=$(_post "$body" "$WORLD4YOU_API/$paketnr/deleteRecord" '' POST 'application/x-www-form-urlencoded') - unset ACME_HTTP_NO_REDIRECTS _resethttp if grep '302' >/dev/null <"$HTTP_HEADER"; then From fbcbc10174d325d7bafd7d37a686a8f05cdc37e3 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 29 Nov 2020 12:03:51 +0100 Subject: [PATCH 172/383] World4You Shellcheck --- dnsapi/dns_world4you.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 0ea969a1..04d40945 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -46,7 +46,7 @@ dns_world4you_add() { fi _resethttp - ACME_HTTP_NO_REDIRECTS=1 + export ACME_HTTP_NO_REDIRECTS=1 body="AddDnsRecordForm[name]=$record&AddDnsRecordForm[dnsType][type]=TXT&\ AddDnsRecordForm[value]=$value&AddDnsRecordForm[aktivPaket]=$paketnr&AddDnsRecordForm[uniqueFormIdDP]=$formiddp&\ @@ -105,7 +105,7 @@ dns_world4you_rm() { _debug recordid "$recordid" _resethttp - ACME_HTTP_NO_REDIRECTS=1 + export ACME_HTTP_NO_REDIRECTS=1 body="DeleteDnsRecordForm[recordId]=$recordid&DeleteDnsRecordForm[aktivPaket]=$paketnr&\ DeleteDnsRecordForm[uniqueFormIdDP]=$formiddp&DeleteDnsRecordForm[uniqueFormIdTTL]=$formidttl&\ From 48942de75e82210135e2b6c7c8bf8c57b9e698d5 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 29 Nov 2020 13:59:33 +0100 Subject: [PATCH 173/383] World4You cleaning --- dnsapi/dns_world4you.sh | 7 ------- 1 file changed, 7 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 04d40945..bed8db81 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -47,13 +47,11 @@ dns_world4you_add() { _resethttp export ACME_HTTP_NO_REDIRECTS=1 - body="AddDnsRecordForm[name]=$record&AddDnsRecordForm[dnsType][type]=TXT&\ AddDnsRecordForm[value]=$value&AddDnsRecordForm[aktivPaket]=$paketnr&AddDnsRecordForm[uniqueFormIdDP]=$formiddp&\ AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_token" _info "Adding record..." ret=$(_post "$body" "$WORLD4YOU_API/$paketnr/dns" '' POST 'application/x-www-form-urlencoded') - _resethttp if grep '302' >/dev/null <"$HTTP_HEADER"; then @@ -72,9 +70,6 @@ dns_world4you_rm() { _debug fulldomain "$fqdn" _debug txtvalue "$value" - tld=$(echo "$fqdn" | _egrep_o '[^.]*\.[^.]*$') - record=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#tld} - 1))") - _login if [ "$?" != 0 ]; then return 1 @@ -106,13 +101,11 @@ dns_world4you_rm() { _resethttp export ACME_HTTP_NO_REDIRECTS=1 - body="DeleteDnsRecordForm[recordId]=$recordid&DeleteDnsRecordForm[aktivPaket]=$paketnr&\ DeleteDnsRecordForm[uniqueFormIdDP]=$formiddp&DeleteDnsRecordForm[uniqueFormIdTTL]=$formidttl&\ DeleteDnsRecordForm[_token]=$form_token" _info "Removing record..." ret=$(_post "$body" "$WORLD4YOU_API/$paketnr/deleteRecord" '' POST 'application/x-www-form-urlencoded') - _resethttp if grep '302' >/dev/null <"$HTTP_HEADER"; then From b7e6d98647b0006249973902980ee0bb20f82c5b Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 29 Nov 2020 14:38:04 +0100 Subject: [PATCH 174/383] World4You grep fix --- dnsapi/dns_world4you.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index bed8db81..8254663a 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -162,7 +162,7 @@ _get_paketnr() { fqdn="$1" form="$2" - domains=$(echo "$form" | _egrep_o '^\s*([A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/') + domains=$(echo "$form" | grep '^ *[A-Za-z0-9_\.-]*\.[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/') domain='' for domain in $domains; do if echo "$fqdn" | grep "$domain\$" >/dev/null; then @@ -176,6 +176,6 @@ _get_paketnr() { TLD="$domain" RECORD=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#TLD} - 1))") - PAKETNR=$(echo "$form" | _egrep_o "data-textfilter=\" $domain .* [0-9]*" | _head_n 1 | _egrep_o "[0-9]*") + PAKETNR=$(echo "$form" | grep "data-textfilter=\" $domain " | _head_n 1 | sed 's/^.* \([0-9]*\) .*$/\1/') return 0 } From 3c309df6dd4d8975165d8e8555d4e5b938ea3c78 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 29 Nov 2020 14:42:55 +0100 Subject: [PATCH 175/383] World4You shellcheck cleaning --- dnsapi/dns_world4you.sh | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 8254663a..64491d08 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -27,8 +27,6 @@ dns_world4you_add() { form=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht") _get_paketnr "$fqdn" "$form" paketnr="$PAKETNR" - tld="$TLD" - record="$RECORD" if [ -z "$paketnr" ]; then _err "Unable to parse paketnr" return 3 @@ -47,7 +45,7 @@ dns_world4you_add() { _resethttp export ACME_HTTP_NO_REDIRECTS=1 - body="AddDnsRecordForm[name]=$record&AddDnsRecordForm[dnsType][type]=TXT&\ + body="AddDnsRecordForm[name]=$RECORD&AddDnsRecordForm[dnsType][type]=TXT&\ AddDnsRecordForm[value]=$value&AddDnsRecordForm[aktivPaket]=$paketnr&AddDnsRecordForm[uniqueFormIdDP]=$formiddp&\ AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_token" _info "Adding record..." @@ -79,8 +77,6 @@ dns_world4you_rm() { form=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht") _get_paketnr "$fqdn" "$form" paketnr="$PAKETNR" - tld="$TLD" - record="$RECORD" if [ -z "$paketnr" ]; then _err "Unable to parse paketnr" return 3 From f665c73bb19d256bebfeed129813eb021e816ded Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 29 Nov 2020 15:03:54 +0100 Subject: [PATCH 176/383] World4You fixed return value --- dnsapi/dns_world4you.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 64491d08..a89b029b 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -56,7 +56,7 @@ AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_toke return 0 else _err "$(_head_n 1 <"$HTTP_HEADER")" - return 2 + return 1 fi } @@ -108,7 +108,7 @@ DeleteDnsRecordForm[_token]=$form_token" return 0 else _err "$(_head_n 1 <"$HTTP_HEADER")" - return 2 + return 1 fi } @@ -125,7 +125,7 @@ _login() { _err "You didn't specify world4you username and password yet." _err "Usage: export WORLD4YOU_USERNAME=" _err "Usage: export WORLD4YOU_PASSWORD=" - return 2 + return 1 fi _saveaccountconf_mutable WORLD4YOU_USERNAME "$WORLD4YOU_USERNAME" From 40631f465eee608f4121177721c705157f29d84b Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 29 Nov 2020 15:22:41 +0100 Subject: [PATCH 177/383] World4You updated info strings --- dnsapi/dns_world4you.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index a89b029b..54cc1511 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -14,7 +14,7 @@ RECORD='' dns_world4you_add() { fqdn="$1" value="$2" - _info "Using world4you" + _info "Using world4you to add record" _debug fulldomain "$fqdn" _debug txtvalue "$value" @@ -64,7 +64,7 @@ AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_toke dns_world4you_rm() { fqdn="$1" value="$2" - _info "Using world4you" + _info "Using world4you to remove record" _debug fulldomain "$fqdn" _debug txtvalue "$value" From da839aae668227aa8d27e3a23ce2acfe5146de79 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Mon, 30 Nov 2020 17:57:25 +0100 Subject: [PATCH 178/383] World4You check response message --- dnsapi/dns_world4you.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 54cc1511..b35df75b 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -53,7 +53,13 @@ AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_toke _resethttp if grep '302' >/dev/null <"$HTTP_HEADER"; then - return 0 + msg=$(_get "$WORLD4YOU_API/$paketnr/dns" | tr '\n' '\t' | sed 's/^.*

[^\t]*\t *\([^\t]*\)\t.*/\1\n/') + if _contains "$msg" "successfully"; then + return 0 + else + _err "Unable to add record: $msg" + return 1 + fi else _err "$(_head_n 1 <"$HTTP_HEADER")" return 1 @@ -105,7 +111,13 @@ DeleteDnsRecordForm[_token]=$form_token" _resethttp if grep '302' >/dev/null <"$HTTP_HEADER"; then - return 0 + msg=$(_get "$WORLD4YOU_API/$paketnr/dns" | tr '\n' '\t' | sed 's/^.*

[^\t]*\t *\([^\t]*\)\t.*/\1\n/') + if _contains "$msg" "successfully"; then + return 0 + else + _err "Unable to remove record: $msg" + return 1 + fi else _err "$(_head_n 1 <"$HTTP_HEADER")" return 1 From f38317d01f6805e5256a811e076f1c45c990a2e8 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Mon, 30 Nov 2020 19:56:48 +0100 Subject: [PATCH 179/383] World4You Mac debug --- dnsapi/dns_world4you.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index b35df75b..8b7f2eed 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -53,7 +53,7 @@ AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_toke _resethttp if grep '302' >/dev/null <"$HTTP_HEADER"; then - msg=$(_get "$WORLD4YOU_API/$paketnr/dns" | tr '\n' '\t' | sed 's/^.*

[^\t]*\t *\([^\t]*\)\t.*/\1\n/') + msg=$(_get "$WORLD4YOU_API/$paketnr/dns" | tr '\n' '\t' | sed 's/.*

[^\t]*\t *\([^\t]*\)\t.*/\1/') if _contains "$msg" "successfully"; then return 0 else @@ -111,7 +111,7 @@ DeleteDnsRecordForm[_token]=$form_token" _resethttp if grep '302' >/dev/null <"$HTTP_HEADER"; then - msg=$(_get "$WORLD4YOU_API/$paketnr/dns" | tr '\n' '\t' | sed 's/^.*

[^\t]*\t *\([^\t]*\)\t.*/\1\n/') + msg=$(_get "$WORLD4YOU_API/$paketnr/dns" | tr '\n' '\t' | sed 's/.*

[^\t]*\t *\([^\t]*\)\t.*/\1/') if _contains "$msg" "successfully"; then return 0 else From be43cebf7de68575dcf96f7bdb609b53d9dfa5dc Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Mon, 30 Nov 2020 20:01:43 +0100 Subject: [PATCH 180/383] World4You Mac fix --- dnsapi/dns_world4you.sh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 8b7f2eed..24b8dd68 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -53,10 +53,11 @@ AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_toke _resethttp if grep '302' >/dev/null <"$HTTP_HEADER"; then - msg=$(_get "$WORLD4YOU_API/$paketnr/dns" | tr '\n' '\t' | sed 's/.*

[^\t]*\t *\([^\t]*\)\t.*/\1/') - if _contains "$msg" "successfully"; then + res=$(_get "$WORLD4YOU_API/$paketnr/dns") + if _contains "$res" "successfully"; then return 0 else + msg=$(echo "$res" | tr '\n' '\t' | sed 's/.*

[^\t]*\t *\([^\t]*\)\t.*/\1/') _err "Unable to add record: $msg" return 1 fi @@ -111,10 +112,11 @@ DeleteDnsRecordForm[_token]=$form_token" _resethttp if grep '302' >/dev/null <"$HTTP_HEADER"; then - msg=$(_get "$WORLD4YOU_API/$paketnr/dns" | tr '\n' '\t' | sed 's/.*

[^\t]*\t *\([^\t]*\)\t.*/\1/') - if _contains "$msg" "successfully"; then + res=$(_get "$WORLD4YOU_API/$paketnr/dns") + if _contains "$res" "successfully"; then return 0 else + msg=$(echo "$res" | tr '\n' '\t' | sed 's/.*

[^\t]*\t *\([^\t]*\)\t.*/\1/') _err "Unable to remove record: $msg" return 1 fi From 2bc627970ed38fbccd7316e7e4a868eb33cff94c Mon Sep 17 00:00:00 2001 From: Christian Burmeister Date: Tue, 1 Dec 2020 20:30:56 +0100 Subject: [PATCH 181/383] Update mailcow.sh I have modified the following things: Originally, "/data/assets/ssl/" is always appended to the varialbe ${_mailcow_path}. Since I use acme.sh as docker container, I only want to include the mailcow-ssl directory in the acem.sh container and not the complete mailcow directory. So now it is checked if the file generate_config.sh is in the directory (then it is the mailcow root directory, see https://github.com/mailcow/mailcow-dockerized) and only then "/data/assets/ssl/" is appended, in all other cases the passed variable is taken over unchanged. Because of the RP mailcow/mailcow-dockerized#2443 I have extended the script with ECC certificates. I adapted the reboot commands as described in the mailcow manual (https://mailcow.github.io/mailcow-dockerized-docs/firststeps-ssl/#how-to-use-your-own-certificate). --- deploy/mailcow.sh | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/deploy/mailcow.sh b/deploy/mailcow.sh index 3a806e83..830bec04 100644 --- a/deploy/mailcow.sh +++ b/deploy/mailcow.sh @@ -27,26 +27,46 @@ mailcow_deploy() { return 1 fi - _ssl_path="${_mailcow_path}/data/assets/ssl/" + #Tests if _ssl_path is the mailcow root directory. + if [ -f "${_mailcow_path}/generate_config.sh" ]; then + _ssl_path="${_mailcow_path}/data/assets/ssl/" + else + _ssl_path="${_mailcow_path}" + fi + if [ ! -d "$_ssl_path" ]; then _err "Cannot find mailcow ssl path: $_ssl_path" return 1 fi + # ECC or RSA + if [ -z "${Le_Keylength}" ]; then + Le_Keylength="" + fi + if _isEccKey "${Le_Keylength}"; then + _info "ECC key type detected" + _cert_type="ecdsa" + _cert_name_prefix="ecdsa-" + else + _info "RSA key type detected" + _cert_type="rsa" + _cert_name_prefix="" + + fi _info "Copying key and cert" - _real_key="$_ssl_path/key.pem" + _real_key="$_ssl_path/${_cert_name_prefix}key.pem" if ! cat "$_ckey" >"$_real_key"; then _err "Error: write key file to: $_real_key" return 1 fi - _real_fullchain="$_ssl_path/cert.pem" + _real_fullchain="$_ssl_path/${_cert_name_prefix}cert.pem" if ! cat "$_cfullchain" >"$_real_fullchain"; then _err "Error: write cert file to: $_real_fullchain" return 1 fi - DEFAULT_MAILCOW_RELOAD="cd ${_mailcow_path} && docker-compose restart postfix-mailcow dovecot-mailcow nginx-mailcow" + DEFAULT_MAILCOW_RELOAD="docker restart $(docker ps -qaf name=postfix-mailcow); docker restart $(docker ps -qaf name=nginx-mailcow); docker restart $(docker ps -qaf name=dovecot-mailcow)" _reload="${DEPLOY_MAILCOW_RELOAD:-$DEFAULT_MAILCOW_RELOAD}" _info "Run reload: $_reload" From 94bba4ac9c977194209b3829bc83f4b3b783aa9f Mon Sep 17 00:00:00 2001 From: Nate Date: Sun, 6 Dec 2020 22:45:42 +0700 Subject: [PATCH 182/383] Correct sed regex Corrects issue #3285. The '?' character after a group is not supported in POSIX Basic Regular Expressions. Replacing it with '\{0,1\}' retains the same functionality and also works on non-GNU systems. --- dnsapi/dns_duckdns.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index f0af2741..41685147 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -96,7 +96,7 @@ dns_duckdns_rm() { _duckdns_get_domain() { # We'll extract the domain/username from full domain - _duckdns_domain="$(printf "%s" "$fulldomain" | _lower_case | _egrep_o '^(_acme-challenge\.)?[a-z0-9-]*\.duckdns\.org' | sed 's/^\(_acme-challenge\.\)\?\([a-z0-9-]*\)\.duckdns\.org/\2/')" + _duckdns_domain="$(printf "%s" "$fulldomain" | _lower_case | _egrep_o '^(_acme-challenge\.)?[a-z0-9-]*\.duckdns\.org' | sed 's/^\(_acme-challenge\.\)\{0,1\}\([a-z0-9-]*\)\.duckdns\.org/\2/')" if [ -z "$_duckdns_domain" ]; then _err "Error extracting the domain." From 671bd1022e92009873e596ab341d1cd3b1ec1c24 Mon Sep 17 00:00:00 2001 From: Van Hau TRAN Date: Sun, 6 Dec 2020 22:59:36 +0100 Subject: [PATCH 183/383] feat: add scaleway provider --- dnsapi/dns_scaleway.sh | 162 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100755 dnsapi/dns_scaleway.sh diff --git a/dnsapi/dns_scaleway.sh b/dnsapi/dns_scaleway.sh new file mode 100755 index 00000000..20397096 --- /dev/null +++ b/dnsapi/dns_scaleway.sh @@ -0,0 +1,162 @@ +#!/usr/bin/env sh + +# Scaleway API +# https://developers.scaleway.com/en/products/domain/dns/api/ +# +# Requires Scaleway API token set in SCALEWAY_API_TOKEN + +######## Public functions ##################### + +SCALEWAY_API="https://api.scaleway.com/domain/v2beta1" + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_scaleway_add() { + fulldomain=$1 + txtvalue=$2 + + if ! _scaleway_check_config; then + return 1 + fi + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _info "Adding record" + _scaleway_create_TXT_record "$_domain" "$_sub_domain" "$txtvalue" + _info "Record added." + + return 0 +} + +dns_scaleway_rm() { + fulldomain=$1 + txtvalue=$2 + + if ! _scaleway_check_config; then + return 1 + fi + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _info "Deleting record" + _scaleway_create_TXT_record "$_domain" "$_sub_domain" "$txtvalue" + _info "Record deleted." + + return 0 +} + +#################### Private functions below ################################## + +_scaleway_check_config() { + SCALEWAY_API_TOKEN="${SCALEWAY_API_TOKEN:-$(_readaccountconf_mutable SCALEWAY_API_TOKEN)}" + if [ -z "$SCALEWAY_API_TOKEN" ]; then + _err "No API key specified for Scaleway API." + _err "Create your key and export it as SCALEWAY_API_TOKEN" + return 1 + fi + if ! _scaleway_rest GET "dns-zones"; then + _err "Invalid API key specified for Scaleway API." + return 1 + fi + + _saveaccountconf_mutable SCALEWAY_API_TOKEN "$SCALEWAY_API_TOKEN" + + return 0 +} + +#_acme-challenge.www.domain.com +#returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +_get_root() { + domain=$1 + i=2 + p=1 + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + if [ -z "$h" ]; then + #not valid + return 1 + fi + + _scaleway_rest GET "dns-zones/$h/records" + + if ! _contains "$response" "subdomain not found" >/dev/null; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain="$h" + return 0 + fi + p=$i + i=$(_math "$i" + 1) + done + _err "Unable to retrive DNS zone matching this domain" + return 1 +} + +_scaleway_create_TXT_record() { + txt_zone=$1 + txt_name=$2 + txt_value=$3 + + _scaleway_rest PATCH "dns-zones/$txt_zone/records" "{\"return_all_records\":false,\"changes\":[{\"add\":{\"records\":[{\"name\":\"$txt_name\",\"data\":\"$txt_value\",\"type\":\"TXT\",\"ttl\":60}]}}]}" + + if [ _contains "$response" "records"; then + return 0 + else + _err "error1 $response" + return 1 + fi +} + +_scaleway_delete_TXT_record() { + txt_zone=$1 + txt_name=$2 + txt_value=$3 + + _scaleway_rest PATCH "dns-zones/$txt_zone/records" "{\"return_all_records\":false,\"changes\":[{\"delete\":{\"id_fields\":{\"name\":\"$txt_name\",\"data\":\"$txt_value\",\"type\":\"TXT\"}}}]}" + + if [ _contains "$response" "records"; then + return 0 + else + _err "error2 $response" + return 1 + fi +} + +_scaleway_rest() { + m=$1 + ep="$2" + data="$3" + _debug "$ep" + _scaleway_url="$SCALEWAY_API/$ep" + _debug2 _scaleway_url "$_scaleway_url" + export _H1="x-auth-token: $SCALEWAY_API_TOKEN" + export _H2="Accept: application/json" + export _H3="Content-Type: application/json" + + if [ "$data" ] || [ "$m" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$_scaleway_url" "" "$m")" + else + response="$(_get "$_scaleway_url")" + fi + if [ "$?" != "0" ] || _contains "$response" "denied_authentication" || _contains "$response" "Method not allowed" || _contains "$response" "json parse error: unexpected EOF"; then + _err "error $response" + return 1 + fi + _debug2 response "$response" + return 0 +} From b5653a1c06e93f745e716a8860897b15a481affc Mon Sep 17 00:00:00 2001 From: Van Hau TRAN Date: Sun, 6 Dec 2020 23:14:25 +0100 Subject: [PATCH 184/383] feat: add comment and configure workflow ci test --- dnsapi/dns_scaleway.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dnsapi/dns_scaleway.sh b/dnsapi/dns_scaleway.sh index 20397096..abca5125 100755 --- a/dnsapi/dns_scaleway.sh +++ b/dnsapi/dns_scaleway.sh @@ -106,6 +106,7 @@ _get_root() { return 1 } +# this function add a TXT record _scaleway_create_TXT_record() { txt_zone=$1 txt_name=$2 @@ -121,6 +122,7 @@ _scaleway_create_TXT_record() { fi } +# this function delete a TXT record based on name and content _scaleway_delete_TXT_record() { txt_zone=$1 txt_name=$2 From 5127a9ae3cbc611047a42d041b8e5da50906d1da Mon Sep 17 00:00:00 2001 From: Van Hau TRAN Date: Sun, 6 Dec 2020 23:20:41 +0100 Subject: [PATCH 185/383] fix: shell if --- dnsapi/dns_scaleway.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_scaleway.sh b/dnsapi/dns_scaleway.sh index abca5125..778738f4 100755 --- a/dnsapi/dns_scaleway.sh +++ b/dnsapi/dns_scaleway.sh @@ -114,7 +114,7 @@ _scaleway_create_TXT_record() { _scaleway_rest PATCH "dns-zones/$txt_zone/records" "{\"return_all_records\":false,\"changes\":[{\"add\":{\"records\":[{\"name\":\"$txt_name\",\"data\":\"$txt_value\",\"type\":\"TXT\",\"ttl\":60}]}}]}" - if [ _contains "$response" "records"; then + if _contains "$response" "records"; then return 0 else _err "error1 $response" @@ -130,7 +130,7 @@ _scaleway_delete_TXT_record() { _scaleway_rest PATCH "dns-zones/$txt_zone/records" "{\"return_all_records\":false,\"changes\":[{\"delete\":{\"id_fields\":{\"name\":\"$txt_name\",\"data\":\"$txt_value\",\"type\":\"TXT\"}}}]}" - if [ _contains "$response" "records"; then + if _contains "$response" "records"; then return 0 else _err "error2 $response" From a0c2d312e9e1698076bbacf010c37d933427c2f0 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 7 Dec 2020 21:31:02 +0800 Subject: [PATCH 186/383] start 2.8.9 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index dcbe3c9d..ae387535 100755 --- a/acme.sh +++ b/acme.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -VER=2.8.8 +VER=2.8.9 PROJECT_NAME="acme.sh" From 32b62d6d4f3424b0212ce1bf196c04353a23c838 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 7 Dec 2020 21:41:08 +0800 Subject: [PATCH 187/383] fix --- deploy/mailcow.sh | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/deploy/mailcow.sh b/deploy/mailcow.sh index 830bec04..babd5d28 100644 --- a/deploy/mailcow.sh +++ b/deploy/mailcow.sh @@ -27,11 +27,11 @@ mailcow_deploy() { return 1 fi - #Tests if _ssl_path is the mailcow root directory. + #Tests if _ssl_path is the mailcow root directory. if [ -f "${_mailcow_path}/generate_config.sh" ]; then _ssl_path="${_mailcow_path}/data/assets/ssl/" else - _ssl_path="${_mailcow_path}" + _ssl_path="${_mailcow_path}" fi if [ ! -d "$_ssl_path" ]; then @@ -41,17 +41,16 @@ mailcow_deploy() { # ECC or RSA if [ -z "${Le_Keylength}" ]; then - Le_Keylength="" + Le_Keylength="" fi if _isEccKey "${Le_Keylength}"; then - _info "ECC key type detected" - _cert_type="ecdsa" - _cert_name_prefix="ecdsa-" + _info "ECC key type detected" + _cert_type="ecdsa" + _cert_name_prefix="ecdsa-" else - _info "RSA key type detected" - _cert_type="rsa" - _cert_name_prefix="" - + _info "RSA key type detected" + _cert_type="rsa" + _cert_name_prefix="" fi _info "Copying key and cert" _real_key="$_ssl_path/${_cert_name_prefix}key.pem" From 174c87a192cb86749d83697a347624f33797e874 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 7 Dec 2020 21:42:31 +0800 Subject: [PATCH 188/383] fix --- deploy/mailcow.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/deploy/mailcow.sh b/deploy/mailcow.sh index babd5d28..932956c0 100644 --- a/deploy/mailcow.sh +++ b/deploy/mailcow.sh @@ -49,7 +49,6 @@ mailcow_deploy() { _cert_name_prefix="ecdsa-" else _info "RSA key type detected" - _cert_type="rsa" _cert_name_prefix="" fi _info "Copying key and cert" From 8440d013f8cfd678c3a03677b949e18459920827 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 7 Dec 2020 22:01:30 +0800 Subject: [PATCH 189/383] fix --- deploy/mailcow.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/deploy/mailcow.sh b/deploy/mailcow.sh index 932956c0..c3535e7e 100644 --- a/deploy/mailcow.sh +++ b/deploy/mailcow.sh @@ -45,7 +45,6 @@ mailcow_deploy() { fi if _isEccKey "${Le_Keylength}"; then _info "ECC key type detected" - _cert_type="ecdsa" _cert_name_prefix="ecdsa-" else _info "RSA key type detected" From 9b532584d6f3e33bf4c548f2f035799779a2c895 Mon Sep 17 00:00:00 2001 From: Van Hau TRAN Date: Tue, 8 Dec 2020 16:32:31 +0100 Subject: [PATCH 190/383] fix: fix delete txt record and error mngtt --- dnsapi/dns_scaleway.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_scaleway.sh b/dnsapi/dns_scaleway.sh index 778738f4..a0a0f318 100755 --- a/dnsapi/dns_scaleway.sh +++ b/dnsapi/dns_scaleway.sh @@ -29,6 +29,12 @@ dns_scaleway_add() { _info "Adding record" _scaleway_create_TXT_record "$_domain" "$_sub_domain" "$txtvalue" + if _contains "$response" "records"; then + return 0 + else + _err error "$response" + return 1 + fi _info "Record added." return 0 @@ -52,7 +58,13 @@ dns_scaleway_rm() { _debug _domain "$_domain" _info "Deleting record" - _scaleway_create_TXT_record "$_domain" "$_sub_domain" "$txtvalue" + _scaleway_delete_TXT_record "$_domain" "$_sub_domain" "$txtvalue" + if _contains "$response" "records"; then + return 0 + else + _err error "$response" + return 1 + fi _info "Record deleted." return 0 @@ -83,7 +95,7 @@ _scaleway_check_config() { # _domain=domain.com _get_root() { domain=$1 - i=2 + i=1 p=1 while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) From 99d3a283efd9a6a6a5c6e5812aa829984cbb8cff Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sat, 26 Sep 2020 19:38:18 -0600 Subject: [PATCH 191/383] Use POST for login This allows us to get the cookie and the token (as it appears to be only in the body in DSM 7.) HTTP_HEADERS is only guarenteed to be output with POST for both wget and curl. --- deploy/synology_dsm.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 2ec0ceb3..53ab5dd9 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -22,7 +22,7 @@ ######## Public functions ##################### _syno_get_cookie_data() { - grep -i "\W$1=" | grep -i "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';' + grep -i "\W$1=" "$HTTP_HEADER" | grep -i "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';' } #domain keyfile certfile cafile fullchain @@ -78,8 +78,8 @@ synology_dsm_deploy() { encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)" encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)" encoded_did="$(printf "%s" "$SYNO_DID" | _url_encode)" - response=$(_get "$_base_url/webman/login.cgi?username=$encoded_username&passwd=$encoded_password&enable_syno_token=yes&device_id=$encoded_did" 1) - token=$(echo "$response" | grep -i "X-SYNO-TOKEN:" | sed -n 's/^X-SYNO-TOKEN: \(.*\)$/\1/pI' | tr -d "\r\n") + response=$(_post "username=$encoded_username&passwd=$encoded_password&device_id=$encoded_did" "$_base_url/webman/login.cgi?enable_syno_token=yes") + token=$(echo "$response" | grep "SynoToken" | sed -n 's/.*"SynoToken" *: *"\([^"]*\).*/\1/p') _debug3 response "$response" _debug token "$token" @@ -89,7 +89,7 @@ synology_dsm_deploy() { return 1 fi - _H1="Cookie: $(echo "$response" | _syno_get_cookie_data "id"); $(echo "$response" | _syno_get_cookie_data "smid")" + _H1="Cookie: $(_syno_get_cookie_data "id"); $(_syno_get_cookie_data "smid")" _H2="X-SYNO-TOKEN: $token" export _H1 export _H2 From cc69285420a49f118acb37c77e3c8f9f73c19f7f Mon Sep 17 00:00:00 2001 From: Thijn Date: Wed, 9 Dec 2020 11:45:25 +0100 Subject: [PATCH 192/383] Fix synology_dsm deployhook for DSM 7 --- deploy/synology_dsm.sh | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 53ab5dd9..bca12d8d 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -73,13 +73,25 @@ synology_dsm_deploy() { _base_url="$SYNO_Scheme://$SYNO_Hostname:$SYNO_Port" _debug _base_url "$_base_url" + _debug "Getting API version" + response=$(_get "$_base_url/webapi/query.cgi?api=SYNO.API.Info&version=1&method=query&query=SYNO.API.Auth") + api_version=$(echo "$response" | grep "SYNO.API.Auth" | sed -n 's/.*"maxVersion" *: *\([0-9]*\).*/\1/p') + _debug3 response "$response" + _debug3 api_version "$api_version" + # Login, get the token from JSON and session id from cookie _info "Logging into $SYNO_Hostname:$SYNO_Port" encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)" encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)" - encoded_did="$(printf "%s" "$SYNO_DID" | _url_encode)" - response=$(_post "username=$encoded_username&passwd=$encoded_password&device_id=$encoded_did" "$_base_url/webman/login.cgi?enable_syno_token=yes") - token=$(echo "$response" | grep "SynoToken" | sed -n 's/.*"SynoToken" *: *"\([^"]*\).*/\1/p') + + if [ ! -z "$SYNO_DID" ]; then + _H1="Cookie: did=$SYNO_DID" + export _H1 + _debug3 H1 "${_H1}" + fi + + response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&enable_device_token=yes&enable_syno_token=yes" "$_base_url/webapi/entry.cgi?api=SYNO.API.Auth&version=$api_version") + token=$(echo "$response" | grep "synotoken" | sed -n 's/.*"synotoken" *: *"\([^"]*\).*/\1/p') _debug3 response "$response" _debug token "$token" @@ -88,13 +100,11 @@ synology_dsm_deploy() { _err "Check your username and password." return 1 fi + sid=$(echo "$response" | grep "sid" | sed -n 's/.*"sid" *: *"\([^"]*\).*/\1/p') - _H1="Cookie: $(_syno_get_cookie_data "id"); $(_syno_get_cookie_data "smid")" - _H2="X-SYNO-TOKEN: $token" + _H1="X-SYNO-TOKEN: $token" export _H1 - export _H2 _debug2 H1 "${_H1}" - _debug2 H2 "${_H2}" # Now that we know the username and password are good, save them _savedeployconf SYNO_Username "$SYNO_Username" @@ -102,7 +112,7 @@ synology_dsm_deploy() { _savedeployconf SYNO_DID "$SYNO_DID" _info "Getting certificates in Synology DSM" - response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1" "$_base_url/webapi/entry.cgi") + response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1&_sid=$sid" "$_base_url/webapi/entry.cgi") _debug3 response "$response" id=$(echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\"id\":\"\([^\"]*\).*/\1/p") _debug2 id "$id" @@ -135,7 +145,7 @@ synology_dsm_deploy() { content="${content%_}" # protect trailing \n _info "Upload certificate to the Synology DSM" - response=$(_post "$content" "$_base_url/webapi/entry.cgi?api=SYNO.Core.Certificate&method=import&version=1&SynoToken=$token" "" "POST" "multipart/form-data; boundary=${delim}") + response=$(_post "$content" "$_base_url/webapi/entry.cgi?api=SYNO.Core.Certificate&method=import&version=1&SynoToken=$token&_sid=$sid" "" "POST" "multipart/form-data; boundary=${delim}") _debug3 response "$response" if ! echo "$response" | grep '"error":' >/dev/null; then From 7d7789ae96ef4061dfb97c41d45a7b017626d305 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Wed, 9 Dec 2020 20:35:50 -0700 Subject: [PATCH 193/383] Support DSM 6 and 7 Small changes for DSM 6: All fields (except enable_syno_token as explained below) must either be in the GET params or the POST params, you can't mix GET and POST params enable_syno_token=yes must be in both the GET and POST params. If enable_syno_token=yes is only in the POST fields, then DSM6 returns a synotoken of --------. If enable_syno_token=yes is only in the GET params, then it returns no synotoken at all. It must be in both to work. Need to use /webapi/auth.cgi instead of /webapi/entry.cgi Verified with DSM 6.2.3-25426 Update 2 and DSM 7.0-40850 --- deploy/synology_dsm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index bca12d8d..edbc1e3e 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -90,7 +90,7 @@ synology_dsm_deploy() { _debug3 H1 "${_H1}" fi - response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&enable_device_token=yes&enable_syno_token=yes" "$_base_url/webapi/entry.cgi?api=SYNO.API.Auth&version=$api_version") + response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&api=SYNO.API.Auth&version=$api_version&enable_syno_token=yes" "$_base_url/webapi/auth.cgi?enable_syno_token=yes") token=$(echo "$response" | grep "synotoken" | sed -n 's/.*"synotoken" *: *"\([^"]*\).*/\1/p') _debug3 response "$response" _debug token "$token" From 2635dfef9659a69d003cc2cb1f108a6c7de044a1 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Wed, 9 Dec 2020 21:01:44 -0700 Subject: [PATCH 194/383] Shellcheck linting Also removed unused code --- deploy/synology_dsm.sh | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index edbc1e3e..35d33209 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -21,10 +21,6 @@ ######## Public functions ##################### -_syno_get_cookie_data() { - grep -i "\W$1=" "$HTTP_HEADER" | grep -i "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';' -} - #domain keyfile certfile cafile fullchain synology_dsm_deploy() { @@ -84,7 +80,7 @@ synology_dsm_deploy() { encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)" encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)" - if [ ! -z "$SYNO_DID" ]; then + if [ -n "$SYNO_DID" ]; then _H1="Cookie: did=$SYNO_DID" export _H1 _debug3 H1 "${_H1}" From 15fb47cb3d0220de6db1c5cf41ecffd03f532275 Mon Sep 17 00:00:00 2001 From: neil Date: Thu, 10 Dec 2020 20:21:57 +0800 Subject: [PATCH 195/383] fix https://github.com/acmesh-official/acme.sh/issues/3300 --- deploy/docker.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/deploy/docker.sh b/deploy/docker.sh index 451d5d00..3aa1b2cd 100755 --- a/deploy/docker.sh +++ b/deploy/docker.sh @@ -275,6 +275,7 @@ _check_curl_version() { if [ "$_major$_minor" -lt "740" ]; then _err "curl v$_cversion doesn't support unit socket" + _err "Please upgrade to curl 7.40 or later." return 1 fi if [ "$_major$_minor" -lt "750" ]; then From cee20c4eb96ec8ec3ad789ae5e3902689598b0ee Mon Sep 17 00:00:00 2001 From: jimp100 <35727302+jimp100@users.noreply.github.com> Date: Wed, 16 Dec 2020 10:11:43 +0000 Subject: [PATCH 196/383] Corrected regex for subdomains A fix to handle subdomains of a duckdns domain. I.e. subdomain.mydomain.duckdns.org Handles n number of subdomains --- dnsapi/dns_duckdns.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index 41685147..618e12c6 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -96,7 +96,7 @@ dns_duckdns_rm() { _duckdns_get_domain() { # We'll extract the domain/username from full domain - _duckdns_domain="$(printf "%s" "$fulldomain" | _lower_case | _egrep_o '^(_acme-challenge\.)?[a-z0-9-]*\.duckdns\.org' | sed 's/^\(_acme-challenge\.\)\{0,1\}\([a-z0-9-]*\)\.duckdns\.org/\2/')" + _duckdns_domain="$(printf "%s" "$fulldomain" | _lower_case | _egrep_o '^(_acme-challenge\.)?([a-z0-9-]+\.)+duckdns\.org' | sed -n 's/^\([^.]\{1,\}\.\)*\([a-z0-9-]\{1,\}\)\.duckdns\.org$/\2/p;')" if [ -z "$_duckdns_domain" ]; then _err "Error extracting the domain." From 48b2a271cc81a7ab8bf2bc229aa59d58f88c493e Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sun, 20 Dec 2020 20:17:05 +0100 Subject: [PATCH 197/383] World4You Bugfix unable to parse paketnr --- dnsapi/dns_world4you.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 24b8dd68..9d36f84d 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -185,7 +185,8 @@ _get_paketnr() { fi TLD="$domain" + _debug domain "$domain" RECORD=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#TLD} - 1))") - PAKETNR=$(echo "$form" | grep "data-textfilter=\" $domain " | _head_n 1 | sed 's/^.* \([0-9]*\) .*$/\1/') + PAKETNR=$(echo "$form" | grep "data-textfilter=\".* $domain " | _head_n 1 | sed 's/^.* \([0-9]*\) .*$/\1/') return 0 } From ac4ae85a4a5c07b4124da3a2e3efce1747db45c7 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Mon, 21 Dec 2020 09:39:09 +0100 Subject: [PATCH 198/383] World4You code refactor --- dnsapi/dns_world4you.sh | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 9d36f84d..6baccbd0 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -52,17 +52,26 @@ AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_toke ret=$(_post "$body" "$WORLD4YOU_API/$paketnr/dns" '' POST 'application/x-www-form-urlencoded') _resethttp - if grep '302' >/dev/null <"$HTTP_HEADER"; then + if _contains "$(_head_n 3 <"$HTTP_HEADER")" '302'; then res=$(_get "$WORLD4YOU_API/$paketnr/dns") if _contains "$res" "successfully"; then return 0 else msg=$(echo "$res" | tr '\n' '\t' | sed 's/.*

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

[^\t]*\t *\([^\t]*\)\t.*/\1/') + if _contains "$msg" '^<\!DOCTYPE html>'; then + msg='Unknown error' + fi _err "Unable to remove record: $msg" + if _contains "$msg" '^<\!DOCTYPE html>'; then + echo "$ret" > 'error-01.html' + echo "$res" > 'error-02.html' + _err "View error-01.html and error-02.html for debugging" + fi return 1 fi else - _err "$(_head_n 1 <"$HTTP_HEADER")" + _err "$(_head_n 3 <"$HTTP_HEADER")" + _err "View $HTTP_HEADER for debugging" return 1 fi } @@ -175,7 +193,7 @@ _get_paketnr() { domains=$(echo "$form" | grep '^ *[A-Za-z0-9_\.-]*\.[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/') domain='' for domain in $domains; do - if echo "$fqdn" | grep "$domain\$" >/dev/null; then + if _contains "$fqdn" "$domain\$"; then break fi domain='' From cb90167c76fa2a88eea8d16c463b2e674d02c009 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Mon, 21 Dec 2020 09:41:05 +0100 Subject: [PATCH 199/383] World4You shellcheck --- dnsapi/dns_world4you.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_world4you.sh b/dnsapi/dns_world4you.sh index 6baccbd0..9ab406f6 100644 --- a/dnsapi/dns_world4you.sh +++ b/dnsapi/dns_world4you.sh @@ -63,8 +63,8 @@ AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_toke fi _err "Unable to add record: $msg" if _contains "$msg" '^<\!DOCTYPE html>'; then - echo "$ret" > 'error-01.html' - echo "$res" > 'error-02.html' + echo "$ret" >'error-01.html' + echo "$res" >'error-02.html' _err "View error-01.html and error-02.html for debugging" fi return 1 @@ -131,8 +131,8 @@ DeleteDnsRecordForm[_token]=$form_token" fi _err "Unable to remove record: $msg" if _contains "$msg" '^<\!DOCTYPE html>'; then - echo "$ret" > 'error-01.html' - echo "$res" > 'error-02.html' + echo "$ret" >'error-01.html' + echo "$res" >'error-02.html' _err "View error-01.html and error-02.html for debugging" fi return 1 From 8a24275ba929d55ab3c3060b3c54239c2e2855ec Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 23 Dec 2020 20:45:43 +0800 Subject: [PATCH 200/383] add dns check wiki --- acme.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/acme.sh b/acme.sh index ae387535..e78744c9 100755 --- a/acme.sh +++ b/acme.sh @@ -160,6 +160,8 @@ _SERVER_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Server" _PREFERRED_CHAIN_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Preferred-Chain" +_DNSCHECK_WIKI="https://github.com/acmesh-official/acme.sh/wiki/dnscheck" + _DNS_MANUAL_ERR="The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead." _DNS_MANUAL_WARN="It seems that you are using dns manual mode. please take care: $_DNS_MANUAL_ERR" @@ -3958,6 +3960,8 @@ _check_dns_entries() { _end_time="$(_math "$_end_time" + 1200)" #let's check no more than 20 minutes. while [ "$(_time)" -le "$_end_time" ]; do + _info "You can use '--dnssleep' to disable public dns checks." + _info "See: $_DNSCHECK_WIKI" _left="" for entry in $dns_entries; do d=$(_getfield "$entry" 1) From a00046f9b299b1cff24dcdfeedfab2426100c144 Mon Sep 17 00:00:00 2001 From: Lukas Brocke Date: Thu, 24 Dec 2020 11:03:25 +0100 Subject: [PATCH 201/383] dnsapi/ionos: Add API support for IONOS DNS API The IONOS DNS API is in beta state, please read [1] on how to get started. PLEASE NOTE: The v2 wildcard certification creation [2] is not yet supported as the IONOS API doesn't allow the creation of multiple TXT records with the same domain name. [1] https://beta.developer.hosting.ionos.de/docs/getstarted [2] https://github.com/acmesh-official/acme.sh/issues/1261 --- dnsapi/dns_ionos.sh | 157 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100755 dnsapi/dns_ionos.sh diff --git a/dnsapi/dns_ionos.sh b/dnsapi/dns_ionos.sh new file mode 100755 index 00000000..4d33e019 --- /dev/null +++ b/dnsapi/dns_ionos.sh @@ -0,0 +1,157 @@ +#!/usr/bin/env sh + +# Supports IONOS DNS API Beta v1.0.0 +# +# Usage: +# Export IONOS_PREFIX and IONOS_SECRET before calling acme.sh: +# +# $ export IONOS_PREFIX="..." +# $ export IONOS_SECRET="..." +# +# $ acme.sh --issue --dns dns_ionos ... + +IONOS_API="https://api.hosting.ionos.com/dns" +IONOS_ROUTE_ZONES="/v1/zones" + +IONOS_TXT_TTL=60 # minumum accepted by API +IONOS_TXT_PRIO=10 + +dns_ionos_add() { + fulldomain=$1 + txtvalue=$2 + + _ionos_init + + _body="{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}" + + if _ionos_rest PATCH "$IONOS_ROUTE_ZONES/$_zone_id" "$_body" && [ -z "$response" ]; then + _info "TXT record for _sub_domain.$_domain has been created successfully." + return 0 + fi + + return 1 +} + +dns_ionos_rm() { + fulldomain=$1 + txtvalue=$2 + + _ionos_init + + if ! _ionos_get_record "$fulldomain" "$_zone_id"; then + _err "Could not find _acme-challenge TXT record." + return 1 + fi + + if _ionos_rest DELETE "$IONOS_ROUTE_ZONES/$_zone_id/records/$_record_id" && [ -z "$response" ]; then + _info "TXT record for _sub_domain.$_domain has been deleted successfully." + return 0 + fi + + return 1 +} + +_ionos_init() { + IONOS_PREFIX="${IONOS_PREFIX:-$(_readaccountconf_mutable IONOS_PREFIX)}" + IONOS_SECRET="${IONOS_SECRET:-$(_readaccountconf_mutable IONOS_SECRET)}" + + if [ -z "$IONOS_PREFIX" ] || [ -z "$IONOS_SECRET" ]; then + _err "You didn't specify an IONOS api prefix and secret yet." + _err "Read https://beta.developer.hosting.ionos.de/docs/getstarted to learn how to get a prefix and secret." + _err "" + _err "Then set them before calling acme.sh:" + _err "\$ export IONOS_PREFIX=\"...\"" + _err "\$ export IONOS_SECRET=\"...\"" + _err "\$ acme.sh --issue -d ... --dns dns_ionos" + return 1 + fi + + _saveaccountconf_mutable IONOS_PREFIX "$IONOS_PREFIX" + _saveaccountconf_mutable IONOS_SECRET "$IONOS_SECRET" + + if ! _get_root "$fulldomain"; then + _err "Cannot find this domain in your IONOS account." + return 1 + fi +} + +_get_root() { + domain=$1 + i=2 + p=1 + + if _ionos_rest GET "$IONOS_ROUTE_ZONES"; then + response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" + + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + if [ -z "$h" ]; then + return 1 + fi + + _zone="$(echo "$response" | _egrep_o "{.*\"name\":\s*\"$h\".*}")" + if [ "$_zone" ]; then + _zone_id=$(printf "%s\n" "$_zone" | _egrep_o "\"id\":\s*\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"' ) + if [ "$_zone_id" ]; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain=$h + + return 0 + fi + + return 1 + fi + + p=$i + i=$(_math "$i" + 1) + done + fi + + return 1 +} + +_ionos_get_record() { + fulldomain=$1 + zone_id=$2 + + if _ionos_rest GET "$IONOS_ROUTE_ZONES/$zone_id?recordName=$fulldomain&recordType=TXT"; then + response="$(echo "$response" | tr -d "\n" )" + + _record="$(echo "$response" | _egrep_o "{\"name\":\s*\"$fulldomain\".*}")" + if [ "$_record" ]; then + _record_id=$(printf "%s\n" "$_record" | _egrep_o "\"id\":\s*\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"' ) + + return 0 + fi + fi + + return 1 +} + +_ionos_rest() { + method="$1" + route="$2" + data="$3" + + IONOS_API_KEY="$(printf "%s.%s" "$IONOS_PREFIX" "$IONOS_SECRET")" + + export _H1="X-API-Key: $IONOS_API_KEY" + + if [ "$method" != "GET" ]; then + export _H2="Accept: application/json" + export _H3="Content-Type: application/json" + + response="$(_post "$data" "$IONOS_API$route" "" "$method")" + else + export _H2="Accept: */*" + + response="$(_get "$IONOS_API$route")" + fi + + if [ "$?" != "0" ]; then + _err "Error $route" + return 1 + fi + + return 0 +} From 22f7ac22d528a0efbaa6326d9812ffde6884f4bc Mon Sep 17 00:00:00 2001 From: Lukas Brocke Date: Thu, 24 Dec 2020 13:06:07 +0100 Subject: [PATCH 202/383] dnsapi/ionos: Run shfmt --- dnsapi/dns_ionos.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/dnsapi/dns_ionos.sh b/dnsapi/dns_ionos.sh index 4d33e019..fb6ba3f8 100755 --- a/dnsapi/dns_ionos.sh +++ b/dnsapi/dns_ionos.sh @@ -13,7 +13,7 @@ IONOS_API="https://api.hosting.ionos.com/dns" IONOS_ROUTE_ZONES="/v1/zones" -IONOS_TXT_TTL=60 # minumum accepted by API +IONOS_TXT_TTL=60 # minimum accepted by API IONOS_TXT_PRIO=10 dns_ionos_add() { @@ -25,7 +25,7 @@ dns_ionos_add() { _body="{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}" if _ionos_rest PATCH "$IONOS_ROUTE_ZONES/$_zone_id" "$_body" && [ -z "$response" ]; then - _info "TXT record for _sub_domain.$_domain has been created successfully." + _info "TXT record has been created successfully." return 0 fi @@ -44,7 +44,7 @@ dns_ionos_rm() { fi if _ionos_rest DELETE "$IONOS_ROUTE_ZONES/$_zone_id/records/$_record_id" && [ -z "$response" ]; then - _info "TXT record for _sub_domain.$_domain has been deleted successfully." + _info "TXT record has been deleted successfully." return 0 fi @@ -54,7 +54,7 @@ dns_ionos_rm() { _ionos_init() { IONOS_PREFIX="${IONOS_PREFIX:-$(_readaccountconf_mutable IONOS_PREFIX)}" IONOS_SECRET="${IONOS_SECRET:-$(_readaccountconf_mutable IONOS_SECRET)}" - + if [ -z "$IONOS_PREFIX" ] || [ -z "$IONOS_SECRET" ]; then _err "You didn't specify an IONOS api prefix and secret yet." _err "Read https://beta.developer.hosting.ionos.de/docs/getstarted to learn how to get a prefix and secret." @@ -91,7 +91,7 @@ _get_root() { _zone="$(echo "$response" | _egrep_o "{.*\"name\":\s*\"$h\".*}")" if [ "$_zone" ]; then - _zone_id=$(printf "%s\n" "$_zone" | _egrep_o "\"id\":\s*\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"' ) + _zone_id=$(printf "%s\n" "$_zone" | _egrep_o "\"id\":\s*\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') if [ "$_zone_id" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain=$h @@ -115,13 +115,13 @@ _ionos_get_record() { zone_id=$2 if _ionos_rest GET "$IONOS_ROUTE_ZONES/$zone_id?recordName=$fulldomain&recordType=TXT"; then - response="$(echo "$response" | tr -d "\n" )" + response="$(echo "$response" | tr -d "\n")" _record="$(echo "$response" | _egrep_o "{\"name\":\s*\"$fulldomain\".*}")" if [ "$_record" ]; then - _record_id=$(printf "%s\n" "$_record" | _egrep_o "\"id\":\s*\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"' ) - - return 0 + _record_id=$(printf "%s\n" "$_record" | _egrep_o "\"id\":\s*\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') + + return 0 fi fi From d6083c68fd3d174fb2ae6025d19965dcf332ac52 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 28 Dec 2020 21:10:22 +0800 Subject: [PATCH 203/383] add libidn --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 6b382242..4618efaf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,6 +12,7 @@ RUN apk update -f \ tzdata \ oath-toolkit-oathtool \ tar \ + libidn \ && rm -rf /var/cache/apk/* ENV LE_CONFIG_HOME /acme.sh From 10de4b6b7bc5f3c9d40214afb62d232b53ee7f89 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Mon, 4 Jan 2021 18:41:02 +1300 Subject: [PATCH 204/383] Add Telegram notification script Requires: - API Token for a bot created with the Telegram Bot Father. - A Chat ID for a user/group that the bot has permission to post to. --- notify/telegram.sh | 49 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 notify/telegram.sh diff --git a/notify/telegram.sh b/notify/telegram.sh new file mode 100644 index 00000000..ee2d93e2 --- /dev/null +++ b/notify/telegram.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +#Support Telegram Bots + +#TELEGRAM_BOT_APITOKEN="" +#TELEGRAM_BOT_CHATID="" + +telegram_send() { + _subject="$1" + _content="$2" + _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped + _debug "_statusCode" "$_statusCode" + + TELEGRAM_BOT_APITOKEN="${TELEGRAM_BOT_APITOKEN:-$(_readaccountconf_mutable TELEGRAM_BOT_APITOKEN)}" + if [ -z "$TELEGRAM_BOT_APITOKEN" ]; then + TELEGRAM_BOT_APITOKEN="" + _err "You didn't specify a Telegram BOT API Token TELEGRAM_BOT_APITOKEN yet." + return 1 + fi + _saveaccountconf_mutable TELEGRAM_BOT_APITOKEN "$TELEGRAM_BOT_APITOKEN" + + TELEGRAM_BOT_CHATID="${TELEGRAM_BOT_CHATID:-$(_readaccountconf_mutable TELEGRAM_BOT_CHATID)}" + if [ -z "$TELEGRAM_BOT_CHATID" ]; then + TELEGRAM_BOT_CHATID="" + _err "You didn't specify a Telegram Chat id TELEGRAM_BOT_CHATID yet." + return 1 + fi + _saveaccountconf_mutable TELEGRAM_BOT_CHATID "$TELEGRAM_BOT_CHATID" + + _content="$(printf "*%s*\n%s" "$_subject" "$_content" | _json_encode)" + _data="{\"text\": \"$_content\", " + _data="$_data\"chat_id\": \"$TELEGRAM_BOT_CHATID\", " + _data="$_data\"parse_mode\": \"markdown\", " + _data="$_data\"disable_web_page_preview\": \"1\"}" + + export _H1="Content-Type: application/json" + _telegram_bot_url="https://api.telegram.org/bot${TELEGRAM_BOT_APITOKEN}/sendMessage" + if _post "$_data" "$_telegram_bot_url"; then + # shellcheck disable=SC2154 + _message=$(printf "%s\n" "$response" | sed -ne 's/.*"ok":\([^,]*\).*/\1/p') + if [ "$_message" = "true" ]; then + _info "telegram send success." + return 0 + fi + fi + _err "telegram send error." + _err "$response" + return 1 +} From c59a8c9644b366f9c8ca17d7bd28a25de66a1799 Mon Sep 17 00:00:00 2001 From: Vahid Fardi Date: Tue, 5 Jan 2021 15:29:08 +0330 Subject: [PATCH 205/383] change arvan api script --- dnsapi/dns_arvan.sh | 43 +++++++++++++++---------------------------- 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/dnsapi/dns_arvan.sh b/dnsapi/dns_arvan.sh index ca1f56c7..3c4ced15 100644 --- a/dnsapi/dns_arvan.sh +++ b/dnsapi/dns_arvan.sh @@ -3,7 +3,6 @@ #Arvan_Token="xxxx" ARVAN_API_URL="https://napi.arvancloud.com/cdn/4.0/domains" - #Author: Ehsan Aliakbar #Report Bugs here: https://github.com/Neilpang/acme.sh # @@ -38,6 +37,7 @@ dns_arvan_add() { _info "Adding record" if _arvan_rest POST "$_domain/dns-records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":{\"text\":\"$txtvalue\"},\"ttl\":120}"; then if _contains "$response" "$txtvalue"; then + _info "response id is $response" _info "Added, OK" return 0 elif _contains "$response" "Record Data is Duplicated"; then @@ -49,7 +49,7 @@ dns_arvan_add() { fi fi _err "Add txt record error." - return 1 + return 0 } #Usage: fulldomain txtvalue @@ -73,33 +73,21 @@ dns_arvan_rm() { _debug _domain "$_domain" _debug "Getting txt records" - shorted_txtvalue=$(printf "%s" "$txtvalue" | cut -d "-" -d "_" -f1) - _arvan_rest GET "${_domain}/dns-records?search=$shorted_txtvalue" - + _arvan_rest GET "${_domain}/dns-records" if ! printf "%s" "$response" | grep \"current_page\":1 >/dev/null; then _err "Error on Arvan Api" _err "Please create a github issue with debbug log" return 1 fi - count=$(printf "%s\n" "$response" | _egrep_o "\"total\":[^,]*" | cut -d : -f 2) - _debug count "$count" - if [ "$count" = "0" ]; then - _info "Don't need to remove." - else - record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1) - _debug "record_id" "$record_id" - if [ -z "$record_id" ]; then - _err "Can not get record id to remove." - return 1 - fi - if ! _arvan_rest "DELETE" "${_domain}/dns-records/$record_id"; then - _err "Delete record error." - return 1 - fi - _debug "$response" - _contains "$response" 'dns record deleted' + _record_id=$(echo "$response" | _egrep_o ".\"id\":\"[^\"]*\",\"type\":\"txt\",\"name\":\"_acme-challenge\",\"value\":{\"text\":\"$txtvalue\"}" | cut -d : -f 2 | cut -d , -f 1 | tr -d \") + if ! _arvan_rest "DELETE" "${_domain}/dns-records/${_record_id}"; then + _err "Error on Arvan Api" + return 1 fi + _debug "$response" + _contains "$response" 'dns record deleted' + return 0 } #################### Private functions below ################################## @@ -111,7 +99,7 @@ dns_arvan_rm() { # _domain_id=sdjkglgdfewsdfg _get_root() { domain=$1 - i=1 + i=2 p=1 while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) @@ -121,12 +109,11 @@ _get_root() { return 1 fi - if ! _arvan_rest GET "?search=$h"; then + if ! _arvan_rest GET "$h"; then return 1 fi - - if _contains "$response" "\"domain\":\"$h\"" || _contains "$response" '"total":1'; then - _domain_id=$(echo "$response" | _egrep_o "\[.\"id\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \") + if _contains "$response" "\"domain\":\"$h\""; then + _domain_id=$(echo "$response" | cut -d : -f 3 | cut -d , -f 1 | tr -d \") if [ "$_domain_id" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain=$h @@ -146,7 +133,6 @@ _arvan_rest() { data="$3" token_trimmed=$(echo "$Arvan_Token" | tr -d '"') - export _H1="Authorization: $token_trimmed" if [ "$mtd" = "DELETE" ]; then @@ -160,4 +146,5 @@ _arvan_rest() { else response="$(_get "$ARVAN_API_URL/$ep$data")" fi + return 0 } From 2ec6215b1cbac352c006797ac8ed25f5cf7b50ac Mon Sep 17 00:00:00 2001 From: Vahid Fardi Date: Tue, 5 Jan 2021 17:10:41 +0330 Subject: [PATCH 206/383] change Author name --- dnsapi/dns_arvan.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_arvan.sh b/dnsapi/dns_arvan.sh index 3c4ced15..a33504d0 100644 --- a/dnsapi/dns_arvan.sh +++ b/dnsapi/dns_arvan.sh @@ -1,10 +1,10 @@ #!/usr/bin/env sh -#Arvan_Token="xxxx" +#Arvan_Token="Apikey xxxx" ARVAN_API_URL="https://napi.arvancloud.com/cdn/4.0/domains" -#Author: Ehsan Aliakbar -#Report Bugs here: https://github.com/Neilpang/acme.sh +#Author: Vahid Fardi +#Report Bugs here: https://github.com/fvahid/acme.sh # ######## Public functions ##################### From d9a8b057c39baeb89d257484d867112fc09db0b6 Mon Sep 17 00:00:00 2001 From: Vahid Fardi Date: Tue, 5 Jan 2021 21:31:31 +0330 Subject: [PATCH 207/383] change name actor --- dnsapi/dns_arvan.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_arvan.sh b/dnsapi/dns_arvan.sh index a33504d0..4c9217e5 100644 --- a/dnsapi/dns_arvan.sh +++ b/dnsapi/dns_arvan.sh @@ -4,7 +4,7 @@ ARVAN_API_URL="https://napi.arvancloud.com/cdn/4.0/domains" #Author: Vahid Fardi -#Report Bugs here: https://github.com/fvahid/acme.sh +#Report Bugs here: https://github.com/Neilpang/acme.sh # ######## Public functions ##################### From ab6b9006b7bdf42ee270646da58658a3762a617d Mon Sep 17 00:00:00 2001 From: James Edington Date: Fri, 8 Jan 2021 11:14:39 -0700 Subject: [PATCH 208/383] This is a general-purpose ACME client. We should be proud of this. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index cd747666..f53578d4 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,7 @@ https://github.com/acmesh-official/acmetest - [ZeroSSL.com CA](https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA) - [BuyPass.com CA](https://github.com/acmesh-official/acme.sh/wiki/BuyPass.com-CA) - [Pebble strict Mode](https://github.com/letsencrypt/pebble) +- Any other [RFC8555](https://tools.ietf.org/html/rfc8555)-compliant CA # Supported modes From c3a3d02beaaec48cf3caa041659c2390613c7503 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 10 Jan 2021 11:47:54 +0800 Subject: [PATCH 209/383] fix https://github.com/acmesh-official/acme.sh/issues/3156 --- dnsapi/dns_linode_v4.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_linode_v4.sh b/dnsapi/dns_linode_v4.sh index c2bebc57..9504afbf 100755 --- a/dnsapi/dns_linode_v4.sh +++ b/dnsapi/dns_linode_v4.sh @@ -106,6 +106,7 @@ dns_linode_v4_rm() { #################### Private functions below ################################## _Linode_API() { + LINODE_V4_API_KEY="${LINODE_V4_API_KEY:-$(_readaccountconf_mutable LINODE_V4_API_KEY)}" if [ -z "$LINODE_V4_API_KEY" ]; then LINODE_V4_API_KEY="" @@ -115,7 +116,7 @@ _Linode_API() { return 1 fi - _saveaccountconf LINODE_V4_API_KEY "$LINODE_V4_API_KEY" + _saveaccountconf_mutable LINODE_V4_API_KEY "$LINODE_V4_API_KEY" } #################### Private functions below ################################## From 1fff8dd30691e4808cded2e84ce0a3f41e89281b Mon Sep 17 00:00:00 2001 From: tyahin Date: Sun, 10 Jan 2021 12:39:12 +0300 Subject: [PATCH 210/383] deploy gcore_cdn fix auth --- deploy/gcore_cdn.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/gcore_cdn.sh b/deploy/gcore_cdn.sh index a2a35f7b..738f8561 100644 --- a/deploy/gcore_cdn.sh +++ b/deploy/gcore_cdn.sh @@ -56,9 +56,9 @@ gcore_cdn_deploy() { _request="{\"username\":\"$Le_Deploy_gcore_cdn_username\",\"password\":\"$Le_Deploy_gcore_cdn_password\"}" _debug _request "$_request" export _H1="Content-Type:application/json" - _response=$(_post "$_request" "https://api.gcdn.co/auth/signin") + _response=$(_post "$_request" "https://api.gcdn.co/auth/jwt/login") _debug _response "$_response" - _regex=".*\"token\":\"\([-._0-9A-Za-z]*\)\".*$" + _regex=".*\"access\":\"\([-._0-9A-Za-z]*\)\".*$" _debug _regex "$_regex" _token=$(echo "$_response" | sed -n "s/$_regex/\1/p") _debug _token "$_token" From 1eaf7c89b7c11703c9f49df91c85fe0f3b537225 Mon Sep 17 00:00:00 2001 From: tyahin Date: Sun, 10 Jan 2021 12:39:20 +0300 Subject: [PATCH 211/383] deploy gcore_cdn fix api --- deploy/gcore_cdn.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/deploy/gcore_cdn.sh b/deploy/gcore_cdn.sh index 738f8561..929a4d53 100644 --- a/deploy/gcore_cdn.sh +++ b/deploy/gcore_cdn.sh @@ -72,12 +72,15 @@ gcore_cdn_deploy() { export _H2="Authorization:Token $_token" _response=$(_get "https://api.gcdn.co/resources") _debug _response "$_response" - _regex=".*(\"id\".*?\"cname\":\"$_cdomain\".*?})" + _regex="\"primary_resource\":null}," + _debug _regex "$_regex" + _response=$(echo "$_response" | sed 's/$_regex/$_regex\n/g') + _debug _response "$_response" _regex="^.*\"cname\":\"$_cdomain\".*$" _debug _regex "$_regex" - _resource=$(echo "$_response" | sed 's/},{/},\n{/g' | _egrep_o "$_regex") + _resource=$(echo "$_response" | _egrep_o "$_regex") _debug _resource "$_resource" - _regex=".*\"id\":\([0-9]*\).*\"rules\".*$" + _regex=".*\"id\":\([0-9]*\).*$" _debug _regex "$_regex" _resourceId=$(echo "$_resource" | sed -n "s/$_regex/\1/p") _debug _resourceId "$_resourceId" From 7ed7a57d926c913adc7f05905ffb5412d170e09b Mon Sep 17 00:00:00 2001 From: tyahin Date: Sun, 10 Jan 2021 12:44:56 +0300 Subject: [PATCH 212/383] deploy gcore_cdn fix syntax --- deploy/gcore_cdn.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/gcore_cdn.sh b/deploy/gcore_cdn.sh index 929a4d53..f573a3aa 100644 --- a/deploy/gcore_cdn.sh +++ b/deploy/gcore_cdn.sh @@ -74,7 +74,7 @@ gcore_cdn_deploy() { _debug _response "$_response" _regex="\"primary_resource\":null}," _debug _regex "$_regex" - _response=$(echo "$_response" | sed 's/$_regex/$_regex\n/g') + _response=$(echo "$_response" | sed "s/$_regex/$_regex\n/g") _debug _response "$_response" _regex="^.*\"cname\":\"$_cdomain\".*$" _debug _regex "$_regex" From b79f63db7841d7344a7360b1c7068d98b6419c9b Mon Sep 17 00:00:00 2001 From: Stephen Dendtler Date: Sun, 10 Jan 2021 11:19:16 +0000 Subject: [PATCH 213/383] Added RackCorp API Integration --- dnsapi/dns_rackcorp.sh | 156 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 dnsapi/dns_rackcorp.sh diff --git a/dnsapi/dns_rackcorp.sh b/dnsapi/dns_rackcorp.sh new file mode 100644 index 00000000..7323473d --- /dev/null +++ b/dnsapi/dns_rackcorp.sh @@ -0,0 +1,156 @@ +#!/usr/bin/env sh + +# Provider: RackCorp (www.rackcorp.com) +# Author: Stephen Dendtler (sdendtler@rackcorp.com) +# Report Bugs here: https://github.com/senjoo/acme.sh +# Alternate email contact: support@rackcorp.com +# +# You'll need an API key (Portal: ADMINISTRATION -> API) +# Set the environment variables as below: +# +# export RACKCORP_APIUUID="UUIDHERE" +# export RACKCORP_APISECRET="SECRETHERE" +# + +RACKCORP_API_ENDPOINT="https://api.rackcorp.net/api/rest/v2.4/json.php" + +######## Public functions ##################### + +dns_rackcorp_add() { + fulldomain="$1" + txtvalue="$2" + + _debug fulldomain="$fulldomain" + _debug txtvalue="$txtvalue" + + if ! _rackcorp_validate; then + return 1 + fi + + _debug "Searching for root zone" + if ! _get_root "$fulldomain"; then + return 1 + fi + _debug _lookup "$_lookup" + _debug _domain "$_domain" + + _info "Creating TXT record." + + if ! _rackcorp_api dns.record.create "\"name\":\"$_domain\",\"type\":\"TXT\",\"lookup\":\"$_lookup\",\"data\":\"$txtvalue\",\"ttl\":300"; then + return 1 + fi + + return 0 +} + +#Usage: fulldomain txtvalue +#Remove the txt record after validation. +dns_rackcorp_rm() { + fulldomain=$1 + txtvalue=$2 + + _debug fulldomain="$fulldomain" + _debug txtvalue="$txtvalue" + + if ! _rackcorp_validate; then + return 1 + fi + + _debug "Searching for root zone" + if ! _get_root "$fulldomain"; then + return 1 + fi + _debug _lookup "$_lookup" + _debug _domain "$_domain" + + _info "Creating TXT record." + + if ! _rackcorp_api dns.record.delete "\"name\":\"$_domain\",\"type\":\"TXT\",\"lookup\":\"$_lookup\",\"data\":\"$txtvalue\""; then + return 1 + fi + + return 0 +} + +#################### Private functions below ################################## +#_acme-challenge.domain.com +#returns +# _lookup=_acme-challenge +# _domain=domain.com +_get_root() { + domain=$1 + i=2 + p=1 + if ! _rackcorp_api dns.domain.getall "\"name\":\"$domain\""; then + return 1 + fi + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug searchhost "$h" + if [ -z "$h" ]; then + _err "Could not find domain for record $domain in RackCorp using the provided credentials" + #not valid + return 1 + fi + + _rackcorp_api dns.domain.getall "\"exactName\":\"$h\"" + + if _contains "$response" "\"matches\":1"; then + if _contains "$response" "\"name\":\"$h\""; then + _lookup=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain="$h" + return 0 + fi + fi + p=$i + i=$(_math "$i" + 1) + done + + return 1 +} + +_rackcorp_validate() { + RACKCORP_APIUUID="${RACKCORP_APIUUID:-$(_readaccountconf_mutable RACKCORP_APIUUID)}" + if [ -z "$RACKCORP_APIUUID" ]; then + RACKCORP_APIUUID="" + _err "You require a RackCorp API UUID (export RACKCORP_APIUUID=\"\")" + _err "Please login to the portal and create an API key and try again." + return 1 + fi + + _saveaccountconf_mutable RACKCORP_APIUUID "$RACKCORP_APIUUID" + + RACKCORP_APISECRET="${RACKCORP_APISECRET:-$(_readaccountconf_mutable RACKCORP_APISECRET)}" + if [ -z "$RACKCORP_APISECRET" ]; then + RACKCORP_APISECRET="" + _err "You require a RackCorp API secret (export RACKCORP_APISECRET=\"\")" + _err "Please login to the portal and create an API key and try again." + return 1 + fi + + _saveaccountconf_mutable RACKCORP_APISECRET "$RACKCORP_APISECRET" + + return 0 +} +_rackcorp_api() { + _rackcorpcmd=$1 + _rackcorpinputdata=$2 + _debug cmd "$_rackcorpcmd $_rackcorpinputdata" + + export _H1="Accept: application/json" + response="$(_post "{\"APIUUID\":\"$RACKCORP_APIUUID\",\"APISECRET\":\"$RACKCORP_APISECRET\",\"cmd\":\"$_rackcorpcmd\",$_rackcorpinputdata}" "$RACKCORP_API_ENDPOINT" "" "POST")" + + if [ "$?" != "0" ]; then + _err "error $response" + return 1 + fi + _debug2 response "$response" + if _contains "$response" "\"code\":\"OK\""; then + _debug code "OK" + else + _debug code "FAILED" + response="" + return 1 + fi + return 0 +} From 2e5a6e21cf27533fc772ca525c8a900e0c20f04c Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Mon, 11 Jan 2021 11:21:46 +1300 Subject: [PATCH 214/383] Correct shebang --- notify/telegram.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notify/telegram.sh b/notify/telegram.sh index ee2d93e2..2806206d 100644 --- a/notify/telegram.sh +++ b/notify/telegram.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env sh #Support Telegram Bots From 584cc6de2e0b465749eaf477c2a33f6843e2840a Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Mon, 11 Jan 2021 11:27:39 +1300 Subject: [PATCH 215/383] Avoid usage of sed -e --- notify/telegram.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notify/telegram.sh b/notify/telegram.sh index 2806206d..b1306ee1 100644 --- a/notify/telegram.sh +++ b/notify/telegram.sh @@ -37,7 +37,7 @@ telegram_send() { _telegram_bot_url="https://api.telegram.org/bot${TELEGRAM_BOT_APITOKEN}/sendMessage" if _post "$_data" "$_telegram_bot_url"; then # shellcheck disable=SC2154 - _message=$(printf "%s\n" "$response" | sed -ne 's/.*"ok":\([^,]*\).*/\1/p') + _message=$(printf "%s\n" "$response" | sed -n 's/.*"ok":\([^,]*\).*/\1/p') if [ "$_message" = "true" ]; then _info "telegram send success." return 0 From 500a005aacdee63d7fec6b1b78e97493657fa9ba Mon Sep 17 00:00:00 2001 From: Stephen Dendtler Date: Mon, 11 Jan 2021 13:03:42 +0000 Subject: [PATCH 216/383] _get_root now does not skip the first label of the domain --- dnsapi/dns_rackcorp.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_rackcorp.sh b/dnsapi/dns_rackcorp.sh index 7323473d..6aabfddc 100644 --- a/dnsapi/dns_rackcorp.sh +++ b/dnsapi/dns_rackcorp.sh @@ -79,7 +79,7 @@ dns_rackcorp_rm() { # _domain=domain.com _get_root() { domain=$1 - i=2 + i=1 p=1 if ! _rackcorp_api dns.domain.getall "\"name\":\"$domain\""; then return 1 From 61549b4a745f45ec44335d9d2074b043acf8a559 Mon Sep 17 00:00:00 2001 From: Mark Challoner Date: Wed, 6 Jan 2021 20:20:21 +0000 Subject: [PATCH 217/383] Add Peplink deploy hook --- deploy/peplink.sh | 123 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 deploy/peplink.sh diff --git a/deploy/peplink.sh b/deploy/peplink.sh new file mode 100644 index 00000000..c4bd6242 --- /dev/null +++ b/deploy/peplink.sh @@ -0,0 +1,123 @@ +#!/usr/bin/env sh + +# Script to deploy cert to Peplink Routers +# +# The following environment variables must be set: +# +# PEPLINK_Hostname - Peplink hostname +# PEPLINK_Username - Peplink username to login +# PEPLINK_Password - Peplink password to login +# +# The following environmental variables may be set if you don't like their +# default values: +# +# PEPLINK_Certtype - Certificate type to target for replacement +# defaults to "webadmin", can be one of: +# * "chub" (ContentHub) +# * "openvpn" (OpenVPN CA) +# * "portal" (Captive Portal SSL) +# * "webadmin" (Web Admin SSL) +# * "webproxy" (Proxy Root CA) +# * "wwan_ca" (Wi-Fi WAN CA) +# * "wwan_client" (Wi-Fi WAN Client) +# PEPLINK_Scheme - defaults to "https" +# PEPLINK_Port - defaults to "443" +# +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +_peplink_get_cookie_data() { + grep -i "\W$1=" | grep -i "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';' +} + +#domain keyfile certfile cafile fullchain +peplink_deploy() { + + _cdomain="$1" + _ckey="$2" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug _cfullchain "$_cfullchain" + _debug _ckey "$_ckey" + + # Get Hostname, Username and Password, but don't save until we successfully authenticate + _getdeployconf PEPLINK_Hostname + _getdeployconf PEPLINK_Username + _getdeployconf PEPLINK_Password + if [ -z "${PEPLINK_Hostname:-}" ] || [ -z "${PEPLINK_Username:-}" ] || [ -z "${PEPLINK_Password:-}" ]; then + _err "PEPLINK_Hostname & PEPLINK_Username & PEPLINK_Password must be set" + return 1 + fi + _debug2 PEPLINK_Hostname "$PEPLINK_Hostname" + _debug2 PEPLINK_Username "$PEPLINK_Username" + _secure_debug2 PEPLINK_Password "$PEPLINK_Password" + + # Optional certificate type, scheme, and port for Peplink + _getdeployconf PEPLINK_Certtype + _getdeployconf PEPLINK_Scheme + _getdeployconf PEPLINK_Port + + # Don't save the certificate type until we verify it exists and is supported + _savedeployconf PEPLINK_Scheme "$PEPLINK_Scheme" + _savedeployconf PEPLINK_Port "$PEPLINK_Port" + + # Default vaules for certificate type, scheme, and port + [ -n "${PEPLINK_Certtype}" ] || PEPLINK_Certtype="webadmin" + [ -n "${PEPLINK_Scheme}" ] || PEPLINK_Scheme="https" + [ -n "${PEPLINK_Port}" ] || PEPLINK_Port="443" + + _debug2 PEPLINK_Certtype "$PEPLINK_Certtype" + _debug2 PEPLINK_Scheme "$PEPLINK_Scheme" + _debug2 PEPLINK_Port "$PEPLINK_Port" + + _base_url="$PEPLINK_Scheme://$PEPLINK_Hostname:$PEPLINK_Port" + _debug _base_url "$_base_url" + + # Login, get the auth token from the cookie + _info "Logging into $PEPLINK_Hostname:$PEPLINK_Port" + encoded_username="$(printf "%s" "$PEPLINK_Username" | _url_encode)" + encoded_password="$(printf "%s" "$PEPLINK_Password" | _url_encode)" + response=$(_post "func=login&username=$encoded_username&password=$encoded_password" "$_base_url/cgi-bin/MANGA/api.cgi") + auth_token=$(_peplink_get_cookie_data "bauth" <"$HTTP_HEADER") + _debug3 response "$response" + _debug auth_token "$auth_token" + + if [ -z "$auth_token" ]; then + _err "Unable to authenticate to $PEPLINK_Hostname:$PEPLINK_Port using $PEPLINK_Scheme." + _err "Check your username and password." + return 1 + fi + + _H1="Cookie: $auth_token" + export _H1 + _debug2 H1 "${_H1}" + + # Now that we know the hostnameusername and password are good, save them + _savedeployconf PEPLINK_Hostname "$PEPLINK_Hostname" + _savedeployconf PEPLINK_Username "$PEPLINK_Username" + _savedeployconf PEPLINK_Password "$PEPLINK_Password" + + _info "Generate form POST request" + + encoded_key="$(_url_encode <"$_ckey")" + encoded_fullchain="$(_url_encode <"$_cfullchain")" + body="cert_type=$PEPLINK_Certtype&cert_uid=§ion=CERT_modify&key_pem=$encoded_key&key_pem_passphrase=&key_pem_passphrase_confirm=&cert_pem=$encoded_fullchain" + _debug3 body "$body" + + _info "Upload $PEPLINK_Certtype certificate to the Peplink" + + response=$(_post "$body" "$_base_url/cgi-bin/MANGA/admin.cgi") + _debug3 response "$response" + + if echo "$response" | grep 'Success' >/dev/null; then + # We've verified this certificate type is valid, so save it + _savedeployconf PEPLINK_Certtype "$PEPLINK_Certtype" + _info "Certificate was updated" + return 0 + else + _err "Unable to update certificate, error code $response" + return 1 + fi +} From 464022bea23fd5d8bdd219f5e033a86ab918c966 Mon Sep 17 00:00:00 2001 From: pssara Date: Fri, 15 Jan 2021 15:12:53 +0100 Subject: [PATCH 218/383] Fixed issue with ISP config where the Client ID was asumed to be the same as the SYS User ID --- dnsapi/dns_ispconfig.sh | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/dnsapi/dns_ispconfig.sh b/dnsapi/dns_ispconfig.sh index bd1e0391..8be47f60 100755 --- a/dnsapi/dns_ispconfig.sh +++ b/dnsapi/dns_ispconfig.sh @@ -75,7 +75,7 @@ _ISPC_getZoneInfo() { # suffix . needed for zone -> domain.tld. curData="{\"session_id\":\"${sessionID}\",\"primary_id\":{\"origin\":\"${curZone}.\"}}" curResult="$(_post "${curData}" "${ISPC_Api}?dns_zone_get")" - _debug "Calling _ISPC_getZoneInfo: '${curData}' '${ISPC_Api}?login'" + _debug "Calling _ISPC_getZoneInfo: '${curData}' '${ISPC_Api}?dns_zone_get'" _debug "Result of _ISPC_getZoneInfo: '$curResult'" if _contains "${curResult}" '"id":"'; then zoneFound=true @@ -110,18 +110,32 @@ _ISPC_getZoneInfo() { ;; *) _info "Retrieved Zone ID" ;; esac - client_id=$(echo "${curResult}" | _egrep_o "sys_userid.*" | cut -d ':' -f 2 | cut -d '"' -f 2) - _debug "Client ID: '${client_id}'" - case "${client_id}" in + sys_userid=$(echo "${curResult}" | _egrep_o "sys_userid.*" | cut -d ':' -f 2 | cut -d '"' -f 2) + _debug "SYS User ID: '${sys_userid}'" + case "${sys_userid}" in '' | *[!0-9]*) - _err "Client ID is not numeric." + _err "SYS User ID is not numeric." return 1 ;; - *) _info "Retrieved Client ID." ;; + *) _info "Retrieved SYS User ID." ;; esac zoneFound="" zoneEnd="" fi + # Need to get client_id as it is different from sys_userid + curData="{\"session_id\":\"${sessionID}\",\"sys_userid\":\"${sys_userid}\"}" + curResult="$(_post "${curData}" "${ISPC_Api}?client_get_id")" + _debug "Calling _ISPC_ClientGetID: '${curData}' '${ISPC_Api}?client_get_id'" + _debug "Result of _ISPC_ClientGetID: '$curResult'" + client_id=$(echo "${curResult}" | _egrep_o "response.*" | cut -d ':' -f 2 | cut -d '"' -f 2 | tr -d '{}') + _debug "Client ID: '${client_id}'" + case "${client_id}" in + '' | *[!0-9]*) + _err "Client ID is not numeric." + return 1 + ;; + *) _info "Retrieved Client ID." ;; + esac } _ISPC_addTxt() { From 289f79bbb0dda768ec23e89e178adbf8af43112f Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 16 Jan 2021 23:50:57 +0800 Subject: [PATCH 219/383] fix format --- dnsapi/dns_ispconfig.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_ispconfig.sh b/dnsapi/dns_ispconfig.sh index 8be47f60..e68ddd49 100755 --- a/dnsapi/dns_ispconfig.sh +++ b/dnsapi/dns_ispconfig.sh @@ -130,11 +130,11 @@ _ISPC_getZoneInfo() { client_id=$(echo "${curResult}" | _egrep_o "response.*" | cut -d ':' -f 2 | cut -d '"' -f 2 | tr -d '{}') _debug "Client ID: '${client_id}'" case "${client_id}" in - '' | *[!0-9]*) + '' | *[!0-9]*) _err "Client ID is not numeric." return 1 ;; - *) _info "Retrieved Client ID." ;; + *) _info "Retrieved Client ID." ;; esac } From d21e6235ad9df9df9452c08617728aaf55fae559 Mon Sep 17 00:00:00 2001 From: Lukas Brocke Date: Mon, 18 Jan 2021 14:35:08 +0100 Subject: [PATCH 220/383] dnsapi/ionos: Add support for v2 wildcard certificates --- dnsapi/dns_ionos.sh | 45 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/dnsapi/dns_ionos.sh b/dnsapi/dns_ionos.sh index fb6ba3f8..a8cc36cf 100755 --- a/dnsapi/dns_ionos.sh +++ b/dnsapi/dns_ionos.sh @@ -20,9 +20,22 @@ dns_ionos_add() { fulldomain=$1 txtvalue=$2 - _ionos_init + if ! _ionos_init; then + return 1 + fi + + _new_record="{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}" + + # As no POST route is supported by the API, check for existing records and include them in the PATCH request in order not delete them. + # This is required to support ACME v2 wildcard certificate creation, where two TXT records for the same domain name are created. + + _ionos_get_existing_records "$fulldomain" "$_zone_id" - _body="{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}" + if [ "$_existing_records" ]; then + _body="[$_new_record,$_existing_records]" + else + _body="[$_new_record]" + fi if _ionos_rest PATCH "$IONOS_ROUTE_ZONES/$_zone_id" "$_body" && [ -z "$response" ]; then _info "TXT record has been created successfully." @@ -36,9 +49,11 @@ dns_ionos_rm() { fulldomain=$1 txtvalue=$2 - _ionos_init + if ! _ionos_init; then + return 1 + fi - if ! _ionos_get_record "$fulldomain" "$_zone_id"; then + if ! _ionos_get_record "$fulldomain" "$_zone_id" "$txtvalue"; then _err "Could not find _acme-challenge TXT record." return 1 fi @@ -81,7 +96,7 @@ _get_root() { p=1 if _ionos_rest GET "$IONOS_ROUTE_ZONES"; then - response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" + response="$(echo "$response" | tr -d "\n")" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) @@ -89,9 +104,9 @@ _get_root() { return 1 fi - _zone="$(echo "$response" | _egrep_o "{.*\"name\":\s*\"$h\".*}")" + _zone="$(echo "$response" | _egrep_o "\"name\":\"$h\".*?}")" if [ "$_zone" ]; then - _zone_id=$(printf "%s\n" "$_zone" | _egrep_o "\"id\":\s*\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') + _zone_id=$(printf "%s\n" "$_zone" | _egrep_o "\"id\":\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') if [ "$_zone_id" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain=$h @@ -110,16 +125,28 @@ _get_root() { return 1 } +_ionos_get_existing_records() { + fulldomain=$1 + zone_id=$2 + + if _ionos_rest GET "$IONOS_ROUTE_ZONES/$zone_id?recordName=$fulldomain&recordType=TXT"; then + response="$(echo "$response" | tr -d "\n")" + + _existing_records="$(printf "%s\n" "$response" | _egrep_o "\"records\":\[.*?\]" | _head_n 1 | cut -d '[' -f 2 | sed 's/]//')" + fi +} + _ionos_get_record() { fulldomain=$1 zone_id=$2 + txtrecord=$3 if _ionos_rest GET "$IONOS_ROUTE_ZONES/$zone_id?recordName=$fulldomain&recordType=TXT"; then response="$(echo "$response" | tr -d "\n")" - _record="$(echo "$response" | _egrep_o "{\"name\":\s*\"$fulldomain\".*}")" + _record="$(echo "$response" | _egrep_o "\{\"name\":\"$fulldomain\"[^\}]*?\"type\":\"TXT\"[^\}]*?\"content\":\"\\\\\"$txtrecord\\\\\"\".*?\}")" if [ "$_record" ]; then - _record_id=$(printf "%s\n" "$_record" | _egrep_o "\"id\":\s*\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') + _record_id=$(printf "%s\n" "$_record" | _egrep_o "\"id\":\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') return 0 fi From a9d88301064698558ebecc7d45b6e7edad61945a Mon Sep 17 00:00:00 2001 From: Lukas Brocke Date: Wed, 20 Jan 2021 21:08:58 +0100 Subject: [PATCH 221/383] dnsapi/ionos: Fixes for Solaris --- dnsapi/dns_ionos.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dnsapi/dns_ionos.sh b/dnsapi/dns_ionos.sh index a8cc36cf..54696d5d 100755 --- a/dnsapi/dns_ionos.sh +++ b/dnsapi/dns_ionos.sh @@ -104,9 +104,9 @@ _get_root() { return 1 fi - _zone="$(echo "$response" | _egrep_o "\"name\":\"$h\".*?}")" + _zone="$(echo "$response" | _egrep_o "\"name\":\"$h\".*\}")" if [ "$_zone" ]; then - _zone_id=$(printf "%s\n" "$_zone" | _egrep_o "\"id\":\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') + _zone_id=$(printf "%s\n" "$_zone" | _egrep_o "\"id\":\"[a-fA-F0-9\-]*\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') if [ "$_zone_id" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain=$h @@ -132,7 +132,7 @@ _ionos_get_existing_records() { if _ionos_rest GET "$IONOS_ROUTE_ZONES/$zone_id?recordName=$fulldomain&recordType=TXT"; then response="$(echo "$response" | tr -d "\n")" - _existing_records="$(printf "%s\n" "$response" | _egrep_o "\"records\":\[.*?\]" | _head_n 1 | cut -d '[' -f 2 | sed 's/]//')" + _existing_records="$(printf "%s\n" "$response" | _egrep_o "\"records\":\[.*\]" | _head_n 1 | cut -d '[' -f 2 | sed 's/]//')" fi } @@ -144,9 +144,9 @@ _ionos_get_record() { if _ionos_rest GET "$IONOS_ROUTE_ZONES/$zone_id?recordName=$fulldomain&recordType=TXT"; then response="$(echo "$response" | tr -d "\n")" - _record="$(echo "$response" | _egrep_o "\{\"name\":\"$fulldomain\"[^\}]*?\"type\":\"TXT\"[^\}]*?\"content\":\"\\\\\"$txtrecord\\\\\"\".*?\}")" + _record="$(echo "$response" | _egrep_o "\"name\":\"$fulldomain\"[^\}]*\"type\":\"TXT\"[^\}]*\"content\":\"\\\\\"$txtrecord\\\\\"\".*\}")" if [ "$_record" ]; then - _record_id=$(printf "%s\n" "$_record" | _egrep_o "\"id\":\"[a-fA-F0-9-]+\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') + _record_id=$(printf "%s\n" "$_record" | _egrep_o "\"id\":\"[a-fA-F0-9\-]*\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') return 0 fi From 5fbbc17376e7a248f35e191cca8053ca521ce88c Mon Sep 17 00:00:00 2001 From: MaysWind Date: Thu, 21 Jan 2021 22:15:23 +0800 Subject: [PATCH 222/383] update dnspod.com api --- dnsapi/dns_dpi.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dnsapi/dns_dpi.sh b/dnsapi/dns_dpi.sh index 9cbf4d51..2955effd 100755 --- a/dnsapi/dns_dpi.sh +++ b/dnsapi/dns_dpi.sh @@ -53,7 +53,7 @@ dns_dpi_rm() { return 1 fi - if ! _rest POST "Record.List" "user_token=$DPI_Id,$DPI_Key&format=json&domain_id=$_domain_id&sub_domain=$_sub_domain"; then + if ! _rest POST "Record.List" "login_token=$DPI_Id,$DPI_Key&format=json&domain_id=$_domain_id&sub_domain=$_sub_domain"; then _err "Record.Lis error." return 1 fi @@ -63,14 +63,14 @@ dns_dpi_rm() { return 0 fi - record_id=$(echo "$response" | _egrep_o '{[^{]*"value":"'"$txtvalue"'"' | cut -d , -f 1 | cut -d : -f 2 | tr -d \") + record_id=$(echo "$response" | tr "{" "\n" | grep -- "$txtvalue" | grep '^"id"' | cut -d : -f 2 | cut -d '"' -f 2) _debug record_id "$record_id" if [ -z "$record_id" ]; then _err "Can not get record id." return 1 fi - if ! _rest POST "Record.Remove" "user_token=$DPI_Id,$DPI_Key&format=json&domain_id=$_domain_id&record_id=$record_id"; then + if ! _rest POST "Record.Remove" "login_token=$DPI_Id,$DPI_Key&format=json&domain_id=$_domain_id&record_id=$record_id"; then _err "Record.Remove error." return 1 fi @@ -89,7 +89,7 @@ add_record() { _info "Adding record" - if ! _rest POST "Record.Create" "user_token=$DPI_Id,$DPI_Key&format=json&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=default"; then + if ! _rest POST "Record.Create" "login_token=$DPI_Id,$DPI_Key&format=json&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=default"; then return 1 fi @@ -113,7 +113,7 @@ _get_root() { return 1 fi - if ! _rest POST "Domain.Info" "user_token=$DPI_Id,$DPI_Key&format=json&domain=$h"; then + if ! _rest POST "Domain.Info" "login_token=$DPI_Id,$DPI_Key&format=json&domain=$h"; then return 1 fi From f06aee21ebf9af3cfd49deb8a61f875eb3839738 Mon Sep 17 00:00:00 2001 From: Lukas Brocke Date: Thu, 21 Jan 2021 16:10:10 +0100 Subject: [PATCH 223/383] dnsapi/ionos: Change to root zone finding algorithm --- dnsapi/dns_ionos.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_ionos.sh b/dnsapi/dns_ionos.sh index 54696d5d..e6bd5000 100755 --- a/dnsapi/dns_ionos.sh +++ b/dnsapi/dns_ionos.sh @@ -92,7 +92,7 @@ _ionos_init() { _get_root() { domain=$1 - i=2 + i=1 p=1 if _ionos_rest GET "$IONOS_ROUTE_ZONES"; then From f49e8ec5adb392f5abf1b7f60039cc80eac3f8f8 Mon Sep 17 00:00:00 2001 From: dgasaway Date: Mon, 25 Jan 2021 11:46:52 -0800 Subject: [PATCH 224/383] Change ipconfig.co to ifconfig.co URL https://ipconfig.co/ip does not currently work, and since https://ifconfig.co/ip is mentioned on the DNS API wiki page, I assume these messages were a typo. --- dnsapi/dns_namecheap.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index 2e389265..7ce39fa9 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -157,7 +157,7 @@ _namecheap_set_publicip() { if [ -z "$NAMECHEAP_SOURCEIP" ]; then _err "No Source IP specified for Namecheap API." - _err "Use your public ip address or an url to retrieve it (e.g. https://ipconfig.co/ip) and export it as NAMECHEAP_SOURCEIP" + _err "Use your public ip address or an url to retrieve it (e.g. https://ifconfig.co/ip) and export it as NAMECHEAP_SOURCEIP" return 1 else _saveaccountconf NAMECHEAP_SOURCEIP "$NAMECHEAP_SOURCEIP" @@ -175,7 +175,7 @@ _namecheap_set_publicip() { _publicip=$(_get "$addr") else _err "No Source IP specified for Namecheap API." - _err "Use your public ip address or an url to retrieve it (e.g. https://ipconfig.co/ip) and export it as NAMECHEAP_SOURCEIP" + _err "Use your public ip address or an url to retrieve it (e.g. https://ifconfig.co/ip) and export it as NAMECHEAP_SOURCEIP" return 1 fi fi From 9366f4b40e2d2d557e458e98ecd0407edc381678 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Mon, 25 Jan 2021 21:55:07 +0100 Subject: [PATCH 225/383] Test original implementation by trgosk --- dnsapi/dns_websupport.sh | 208 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 dnsapi/dns_websupport.sh diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh new file mode 100644 index 00000000..1332a0aa --- /dev/null +++ b/dnsapi/dns_websupport.sh @@ -0,0 +1,208 @@ +#!/usr/bin/env sh + +#This is the websupport.sk api wrapper for acme.sh +# +#Author: trgo.sk +#Report Bugs here: https://github.com/trgosk/acme.sh + +#WS_ApiKey="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +#WS_ApiSecret="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + +WS_Api="https://rest.websupport.sk" + +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_websupport_add() { + fulldomain=$1 + txtvalue=$2 + + WS_ApiKey="${WS_ApiKey:-$(_readaccountconf_mutable WS_ApiKey)}" + WS_ApiSecret="${WS_ApiSecret:-$(_readaccountconf_mutable WS_ApiSecret)}" + + if [ "$WS_ApiKey" ] && [ "$WS_ApiSecret" ]; then + _saveaccountconf_mutable WS_ApiKey "$WS_ApiKey" + _saveaccountconf_mutable WS_ApiSecret "$WS_ApiSecret" + else + WS_ApiKey="" + WS_ApiSecret="" + _err "You didn't specify a api key and/or api secret yet." + _err "You can get yours from here https://admin.websupport.sk/en/auth/apiKey" + return 1 + fi + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + # For wildcard cert, the main root domain and the wildcard domain have the same txt subdomain name, so + # we can not use updating anymore. + # count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2) + # _debug count "$count" + # if [ "$count" = "0" ]; then + _info "Adding record" + if _ws_rest POST "/v1/user/self/zone/$_domain/record" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then + if _contains "$response" "$txtvalue"; then + _info "Added, OK" + return 0 + elif _contains "$response" "The record already exists"; then + _info "Already exists, OK" + return 0 + else + _err "Add txt record error." + return 1 + fi + fi + _err "Add txt record error." + return 1 + +} + +#fulldomain txtvalue +dns_websupport_rm() { + fulldomain=$1 + txtvalue=$2 + + _debug2 fulldomain "$fulldomain" + _debug2 txtvalue "$txtvalue" + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting txt records" + _ws_rest GET "/v1/user/self/zone/$_domain/record" + + if [ "$(printf "%s" "$response" | tr -d " " | grep -c \"items\")" -lt "1" ]; then + _err "Error: $response" + return 1 + fi + + record_line="$(_get_from_array "$response" "$txtvalue")" + _debug record_line "$record_line" + if [ -z "$record_line" ]; then + _info "Don't need to remove." + else + record_id=$(echo "$record_line" | _egrep_o "\"id\": *[^,]*" | _head_n 1 | cut -d : -f 2 | tr -d \" | tr -d " ") + _debug "record_id" "$record_id" + if [ -z "$record_id" ]; then + _err "Can not get record id to remove." + return 1 + fi + if ! _ws_rest DELETE "/v1/user/self/zone/$_domain/record/$record_id"; then + _err "Delete record error." + return 1 + fi + if [ "$(printf "%s" "$response" | tr -d " " | grep -c \"success\")" -lt "1" ]; then + return 1 + else + return 0 + fi + fi + +} + +#################### Private functions below ################################## +#_acme-challenge.www.domain.com +#returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +_get_root() { + domain=$1 + i=1 + p=1 + + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug h "$h" + if [ -z "$h" ]; then + #not valid + return 1 + fi + + if ! _ws_rest GET "/v1/user/self/zone"; then + return 1 + fi + + if _contains "$response" "\"name\":\"$h\""; then + _domain_id=$(echo "$response" | _egrep_o "\[.\"id\": *[^,]*" | _head_n 1 | cut -d : -f 2 | tr -d \" | tr -d " ") + if [ "$_domain_id" ]; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain=$h + return 0 + fi + return 1 + fi + p=$i + i=$(_math "$i" + 1) + done + return 1 +} + +_ws_rest() { + me=$1 + pa="$2" + da="$3" + + _debug2 api_key "$WS_ApiKey" + _debug2 api_secret "$WS_ApiSecret" + + timestamp="$(date +%s)" + datez=$(date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || date -u -d@"$timestamp" +%Y-%m-%dT%H:%M:%S%z) + canonical_request="${me} ${pa} ${timestamp}" + alg="sha1" + signature_hash=$( (printf "%s" "$canonical_request" | ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -mac HMAC -macopt "key:$WS_ApiSecret" 2>/dev/null || printf "%s" "$canonical_request" | ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -hmac "$(printf "%s" "$WS_ApiSecret" | _h2b)") | cut -d = -f 2 | tr -d ' ') + basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" + + _debug2 method "$me" + _debug2 path "$pa" + _debug2 data "$da" + _debug2 timestamp "$timestamp" + _debug2 datez "$datez" + _debug2 canonical_request "$canonical_request" + _debug2 alg "$alg" + _debug2 signature_hash "$signature_hash" + _debug2 basicauth "$basicauth" + + export _H1="Accept: application/json" + export _H2="Content-Type: application/json" + export _H3="Authorization: Basic ${basicauth}" + export _H4="Date: ${datez}" + + _debug2 H1 "$_H1" + _debug2 H2 "$_H2" + _debug2 H3 "$_H3" + _debug2 H4 "$_H4" + + if [ "$me" != "GET" ]; then + _debug2 "${me} $WS_Api${pa}" + _debug data "$da" + response="$(_post "$da" "${WS_Api}${pa}" "" "$me")" + else + _debug2 "GET $WS_Api${pa}" + response="$(_get "$WS_Api${pa}")" + fi + + _debug2 response "$response" + return "$?" +} + +_get_from_array() { + va="$1" + fi="$2" + for i in $(echo "$va" | sed "s/{/ /g"); do + if _contains "$i" "$fi"; then + echo "$i" + break + fi + done +} From 92332fc385e288cd478218b7969238151cf4bcec Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Mon, 25 Jan 2021 22:01:41 +0100 Subject: [PATCH 226/383] Update dns_websupport.sh --- dnsapi/dns_websupport.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 1332a0aa..407e3485 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -206,3 +206,4 @@ _get_from_array() { fi done } + From 4956a580266240090ee777f9ffc5fd7a07991dca Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Mon, 25 Jan 2021 22:10:27 +0100 Subject: [PATCH 227/383] Update dns_websupport.sh --- dnsapi/dns_websupport.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 407e3485..1332a0aa 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -206,4 +206,3 @@ _get_from_array() { fi done } - From 77e8008752b02c2bcb3b8387df7975aef0748207 Mon Sep 17 00:00:00 2001 From: neil Date: Tue, 26 Jan 2021 22:10:53 +0800 Subject: [PATCH 228/383] fix docker build (#3383) * fix dockerhub * fix Co-authored-by: neil --- .github/workflows/dockerhub.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/dockerhub.yml b/.github/workflows/dockerhub.yml index 89915af7..238fde3a 100644 --- a/.github/workflows/dockerhub.yml +++ b/.github/workflows/dockerhub.yml @@ -33,12 +33,10 @@ jobs: steps: - name: checkout code uses: actions/checkout@v2 - - name: install buildx - id: buildx - uses: crazy-max/ghaction-docker-buildx@v3 - with: - buildx-version: latest - qemu-version: latest + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 - name: login to docker hub run: | echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin From 58c4eaaf861fe6909b2ed766a8cd1c2be2b6e8d4 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 30 Jan 2021 11:27:18 +0800 Subject: [PATCH 229/383] fix online install (#3385) --- acme.sh | 59 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/acme.sh b/acme.sh index e78744c9..0d3a9e8c 100755 --- a/acme.sh +++ b/acme.sh @@ -6105,7 +6105,7 @@ _installalias() { } -# nocron confighome noprofile +# nocron confighome noprofile accountemail install() { if [ -z "$LE_WORKING_DIR" ]; then @@ -6115,6 +6115,8 @@ install() { _nocron="$1" _c_home="$2" _noprofile="$3" + _accountemail="$4" + if ! _initpath; then _err "Install failed." return 1 @@ -6233,6 +6235,10 @@ install() { fi fi + if [ "$_accountemail" ]; then + _saveaccountconf "ACCOUNT_EMAIL" "$_accountemail" + fi + _info OK } @@ -6511,7 +6517,7 @@ Parameters: --cert-home Specifies the home dir to save all the certs, only valid for '--install' command. --config-home Specifies the home dir to save all the configurations. --useragent Specifies the user agent string. it will be saved for future use too. - -m, --accountemail Specifies the account email, only valid for the '--install' and '--update-account' command. + -m, --email Specifies the account email, only valid for the '--install' and '--update-account' command. --accountkey Specifies the account key path, only valid for the '--install' command. --days Specifies the days to renew the cert when using '--issue' command. The default value is $DEFAULT_RENEW days. --httpport Specifies the standalone listening port. Only valid if the server is behind a reverse proxy or load balancer. @@ -6522,9 +6528,9 @@ Parameters: --insecure Do not check the server certificate, in some devices, the api server's certificate may not be trusted. --ca-bundle Specifies the path to the CA certificate bundle to verify api server's certificate. --ca-path Specifies directory containing CA certificates in PEM format, used by wget or curl. - --nocron Only valid for '--install' command, which means: do not install the default cron job. + --no-cron Only valid for '--install' command, which means: do not install the default cron job. In this case, the certs will not be renewed automatically. - --noprofile Only valid for '--install' command, which means: do not install aliases to user profile. + --no-profile Only valid for '--install' command, which means: do not install aliases to user profile. --no-color Do not output color text. --force-color Force output of color text. Useful for non-interactive use with the aha tool for HTML E-Mails. --ecc Specifies to use the ECC cert. Valid for '--install-cert', '--renew', '--revoke', '--to-pkcs12' and '--create-csr' @@ -6562,18 +6568,18 @@ Parameters: " } -# nocron noprofile -_installOnline() { + +installOnline() { _info "Installing from online archive." - _nocron="$1" - _noprofile="$2" - if [ ! "$BRANCH" ]; then - BRANCH="master" + + _branch="$BRANCH" + if [ -z "$_branch" ]; then + _branch="master" fi - target="$PROJECT/archive/$BRANCH.tar.gz" + target="$PROJECT/archive/$_branch.tar.gz" _info "Downloading $target" - localname="$BRANCH.tar.gz" + localname="$_branch.tar.gz" if ! _get "$target" >$localname; then _err "Download error." return 1 @@ -6585,9 +6591,9 @@ _installOnline() { exit 1 fi - cd "$PROJECT_NAME-$BRANCH" + cd "$PROJECT_NAME-$_branch" chmod +x $PROJECT_ENTRY - if ./$PROJECT_ENTRY install "$_nocron" "" "$_noprofile"; then + if ./$PROJECT_ENTRY --install "$@"; then _info "Install success!" _initpath _saveaccountconf "UPGRADE_HASH" "$(_getUpgradeHash)" @@ -6595,7 +6601,7 @@ _installOnline() { cd .. - rm -rf "$PROJECT_NAME-$BRANCH" + rm -rf "$PROJECT_NAME-$_branch" rm -f "$localname" ) } @@ -6623,7 +6629,7 @@ upgrade() { [ -z "$FORCE" ] && [ "$(_getUpgradeHash)" = "$(_readaccountconf "UPGRADE_HASH")" ] && _info "Already uptodate!" && exit 0 export LE_WORKING_DIR cd "$LE_WORKING_DIR" - _installOnline "nocron" "noprofile" + installOnline "--nocron" "--noprofile" ); then _info "Upgrade success!" exit 0 @@ -6803,6 +6809,11 @@ _process() { --install) _CMD="install" ;; + --install-online) + shift + installOnline "$@" + return + ;; --uninstall) _CMD="uninstall" ;; @@ -7077,9 +7088,9 @@ _process() { USER_AGENT="$_useragent" shift ;; - -m | --accountemail) + -m | --email | --accountemail) _accountemail="$2" - ACCOUNT_EMAIL="$_accountemail" + export ACCOUNT_EMAIL="$_accountemail" shift ;; --accountkey) @@ -7122,10 +7133,10 @@ _process() { CA_PATH="$_ca_path" shift ;; - --nocron) + --no-cron | --nocron) _nocron="1" ;; - --noprofile) + --no-profile | --noprofile) _noprofile="1" ;; --no-color) @@ -7345,7 +7356,7 @@ _process() { fi _debug "Running cmd: ${_CMD}" case "${_CMD}" in - install) install "$_nocron" "$_confighome" "$_noprofile" ;; + install) install "$_nocron" "$_confighome" "$_noprofile" "$_accountemail" ;; uninstall) uninstall "$_nocron" ;; upgrade) upgrade ;; issue) @@ -7458,12 +7469,6 @@ _process() { } -if [ "$INSTALLONLINE" ]; then - INSTALLONLINE="" - _installOnline - exit -fi - main() { [ -z "$1" ] && showhelp && return if _startswith "$1" '-'; then _process "$@"; else "$@"; fi From 565ca81b30bd5a586f438035a0c7f2ff008714ce Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 30 Jan 2021 11:44:42 +0800 Subject: [PATCH 230/383] update readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f53578d4..edd6442f 100644 --- a/README.md +++ b/README.md @@ -110,13 +110,13 @@ https://github.com/acmesh-official/acmetest Check this project: https://github.com/acmesh-official/get.acme.sh ```bash -curl https://get.acme.sh | sh +curl https://get.acme.sh | sh -s email=my@example.com ``` Or: ```bash -wget -O - https://get.acme.sh | sh +wget -O - https://get.acme.sh | sh -s email=my@example.com ``` @@ -127,7 +127,7 @@ Clone this project and launch installation: ```bash git clone https://github.com/acmesh-official/acme.sh.git cd ./acme.sh -./acme.sh --install +./acme.sh --install -m my@example.com ``` You `don't have to be root` then, although `it is recommended`. From e6dea4c92c58886106661f0e56035560b1fccb19 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 30 Jan 2021 12:05:23 +0800 Subject: [PATCH 231/383] fix format --- acme.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/acme.sh b/acme.sh index 0d3a9e8c..a1ad4195 100755 --- a/acme.sh +++ b/acme.sh @@ -6568,7 +6568,6 @@ Parameters: " } - installOnline() { _info "Installing from online archive." From dadc70630b3b1fd1fc93805dde5b929e2e5b1f06 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Sun, 31 Jan 2021 22:02:11 +0100 Subject: [PATCH 232/383] Testing HMAC --- dnsapi/dns_websupport.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 1332a0aa..5136a8e1 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -156,11 +156,11 @@ _ws_rest() { _debug2 api_key "$WS_ApiKey" _debug2 api_secret "$WS_ApiSecret" - timestamp="$(date +%s)" + timestamp=$(_time) datez=$(date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || date -u -d@"$timestamp" +%Y-%m-%dT%H:%M:%S%z) canonical_request="${me} ${pa} ${timestamp}" alg="sha1" - signature_hash=$( (printf "%s" "$canonical_request" | ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -mac HMAC -macopt "key:$WS_ApiSecret" 2>/dev/null || printf "%s" "$canonical_request" | ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -hmac "$(printf "%s" "$WS_ApiSecret" | _h2b)") | cut -d = -f 2 | tr -d ' ') + signature_hash=$( (printf "%s" "$canonical_request" | _hmac "$alg" "$WS_ApiSecret" 2>/dev/null || printf "%s" "$canonical_request" | _hmac "$alg" "$WS_ApiSecret") basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" _debug2 method "$me" From 7924e01b155b4b0ee0170c209687c3c68cdfdb76 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Sun, 31 Jan 2021 22:04:53 +0100 Subject: [PATCH 233/383] Added a forgotten ")" --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 5136a8e1..ca6b8a06 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -160,7 +160,7 @@ _ws_rest() { datez=$(date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || date -u -d@"$timestamp" +%Y-%m-%dT%H:%M:%S%z) canonical_request="${me} ${pa} ${timestamp}" alg="sha1" - signature_hash=$( (printf "%s" "$canonical_request" | _hmac "$alg" "$WS_ApiSecret" 2>/dev/null || printf "%s" "$canonical_request" | _hmac "$alg" "$WS_ApiSecret") + signature_hash=$( (printf "%s" "$canonical_request" | _hmac "$alg" "$WS_ApiSecret" 2>/dev/null || printf "%s" "$canonical_request" | _hmac "$alg" "$WS_ApiSecret")) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" _debug2 method "$me" From 84dd864886c2bccacec04697abfe7a7d594b9705 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Sun, 31 Jan 2021 22:16:00 +0100 Subject: [PATCH 234/383] Simplified approach for the HMAC method --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index ca6b8a06..2ff93a5d 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -160,7 +160,7 @@ _ws_rest() { datez=$(date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || date -u -d@"$timestamp" +%Y-%m-%dT%H:%M:%S%z) canonical_request="${me} ${pa} ${timestamp}" alg="sha1" - signature_hash=$( (printf "%s" "$canonical_request" | _hmac "$alg" "$WS_ApiSecret" 2>/dev/null || printf "%s" "$canonical_request" | _hmac "$alg" "$WS_ApiSecret")) + signature_hash=$(printf "%s" "$canonical_request" | _hmac "$alg" "$WS_ApiSecret") basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" _debug2 method "$me" From 76309601eb20222cab6a48b3dacbb9c07e39c709 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Sun, 31 Jan 2021 22:25:13 +0100 Subject: [PATCH 235/383] Update dns_websupport.sh --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 2ff93a5d..4b0026f8 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -160,7 +160,7 @@ _ws_rest() { datez=$(date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || date -u -d@"$timestamp" +%Y-%m-%dT%H:%M:%S%z) canonical_request="${me} ${pa} ${timestamp}" alg="sha1" - signature_hash=$(printf "%s" "$canonical_request" | _hmac "$alg" "$WS_ApiSecret") + signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" _debug2 method "$me" From 0481f20c6b6acbe590f54194c4e709f3b159cb1a Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Mon, 1 Feb 2021 00:30:36 +0100 Subject: [PATCH 236/383] "datez" var and comments --- dnsapi/dns_websupport.sh | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 4b0026f8..731da0a6 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -1,18 +1,24 @@ #!/usr/bin/env sh -#This is the websupport.sk api wrapper for acme.sh +# This is the websupport.sk api wrapper for acme.sh # -#Author: trgo.sk -#Report Bugs here: https://github.com/trgosk/acme.sh - -#WS_ApiKey="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -#WS_ApiSecret="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +# Original author: trgo.sk (https://github.com/trgosk) +# Tweaks by: akulumbeg (https://github.com/akulumbeg) +# +# Report Bugs here: https://github.com/akulumbeg/acme.sh +# +# Requirements: API Key and Secret from https://admin.websupport.sk/en/auth/apiKey +# +# WS_ApiKey="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +# (called "Identifier" in the WS Admin) +# +# WS_ApiSecret="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +# (called "Secret key" in the WS Admin) WS_Api="https://rest.websupport.sk" ######## Public functions ##################### -#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_websupport_add() { fulldomain=$1 txtvalue=$2 @@ -26,7 +32,7 @@ dns_websupport_add() { else WS_ApiKey="" WS_ApiSecret="" - _err "You didn't specify a api key and/or api secret yet." + _err "You did not specify the API Key and/or API Secret" _err "You can get yours from here https://admin.websupport.sk/en/auth/apiKey" return 1 fi @@ -62,7 +68,6 @@ dns_websupport_add() { } -#fulldomain txtvalue dns_websupport_rm() { fulldomain=$1 txtvalue=$2 @@ -111,11 +116,8 @@ dns_websupport_rm() { } -#################### Private functions below ################################## -#_acme-challenge.www.domain.com -#returns -# _sub_domain=_acme-challenge.www -# _domain=domain.com +#################### Private Functions ################################## + _get_root() { domain=$1 i=1 @@ -157,9 +159,8 @@ _ws_rest() { _debug2 api_secret "$WS_ApiSecret" timestamp=$(_time) - datez=$(date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || date -u -d@"$timestamp" +%Y-%m-%dT%H:%M:%S%z) + datez=$(printf "%s" "$(date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || date -u -d@"$timestamp" +%Y-%m-%dT%H:%M:%S%z)") canonical_request="${me} ${pa} ${timestamp}" - alg="sha1" signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" @@ -169,7 +170,6 @@ _ws_rest() { _debug2 timestamp "$timestamp" _debug2 datez "$datez" _debug2 canonical_request "$canonical_request" - _debug2 alg "$alg" _debug2 signature_hash "$signature_hash" _debug2 basicauth "$basicauth" From 3014955ecec9a71a0db59b83641484bea71e7c0e Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Mon, 1 Feb 2021 18:16:15 +0100 Subject: [PATCH 237/383] Fix comments, error msg and time formatting --- dnsapi/dns_websupport.sh | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 731da0a6..8950970b 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -1,12 +1,11 @@ #!/usr/bin/env sh -# This is the websupport.sk api wrapper for acme.sh +# Acme.sh DNS API wrapper for websupport.sk # # Original author: trgo.sk (https://github.com/trgosk) # Tweaks by: akulumbeg (https://github.com/akulumbeg) -# # Report Bugs here: https://github.com/akulumbeg/acme.sh -# + # Requirements: API Key and Secret from https://admin.websupport.sk/en/auth/apiKey # # WS_ApiKey="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" @@ -33,7 +32,7 @@ dns_websupport_add() { WS_ApiKey="" WS_ApiSecret="" _err "You did not specify the API Key and/or API Secret" - _err "You can get yours from here https://admin.websupport.sk/en/auth/apiKey" + _err "You can get the credentials from here https://admin.websupport.sk/en/auth/apiKey" return 1 fi @@ -159,7 +158,7 @@ _ws_rest() { _debug2 api_secret "$WS_ApiSecret" timestamp=$(_time) - datez=$(printf "%s" "$(date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || date -u -d@"$timestamp" +%Y-%m-%dT%H:%M:%S%z)") + datez=$(printf "%s" "$(date -u -r "$timestamp" "+%Y-%m-%dT%H:%M:%S%z" 2>/dev/null || date -u -d@"$timestamp" "+%Y-%m-%dT%H:%M:%S%z")") canonical_request="${me} ${pa} ${timestamp}" signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" From 5d4d53c3a10c7fdfe76c01f1270d40550d260ebc Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Mon, 1 Feb 2021 18:37:17 +0100 Subject: [PATCH 238/383] Testing datez change for Solaris --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 8950970b..c3a43f1e 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -158,7 +158,7 @@ _ws_rest() { _debug2 api_secret "$WS_ApiSecret" timestamp=$(_time) - datez=$(printf "%s" "$(date -u -r "$timestamp" "+%Y-%m-%dT%H:%M:%S%z" 2>/dev/null || date -u -d@"$timestamp" "+%Y-%m-%dT%H:%M:%S%z")") + datez=$(printf "%s" "$(date -u -d@"$timestamp" "+%Y-%m-%dT%H:%M:%S%z" 2>/dev/null || date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z)") canonical_request="${me} ${pa} ${timestamp}" signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" From 783a6110eff2bbb85c4ad7082ec43490a32eaeb2 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Mon, 1 Feb 2021 20:31:05 +0100 Subject: [PATCH 239/383] Yet another Solaris test --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index c3a43f1e..73543ea5 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -158,7 +158,7 @@ _ws_rest() { _debug2 api_secret "$WS_ApiSecret" timestamp=$(_time) - datez=$(printf "%s" "$(date -u -d@"$timestamp" "+%Y-%m-%dT%H:%M:%S%z" 2>/dev/null || date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z)") + datez=$(date -u -d@"$timestamp" "+%Y-%m-%dT%H:%M:%S%z" 1>/dev/null 2>&1 || date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z) canonical_request="${me} ${pa} ${timestamp}" signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" From 7984d8cdfb41a65f37940c0fe14502660b2f33a1 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Mon, 1 Feb 2021 20:43:22 +0100 Subject: [PATCH 240/383] And again --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 73543ea5..b145dc3e 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -158,7 +158,7 @@ _ws_rest() { _debug2 api_secret "$WS_ApiSecret" timestamp=$(_time) - datez=$(date -u -d@"$timestamp" "+%Y-%m-%dT%H:%M:%S%z" 1>/dev/null 2>&1 || date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z) + datez=$(date -u -d@"$timestamp" "+%Y-%m-%dT%H:%M:%S%z" 2>/dev/null || date -u -r "$timestamp" "+%Y-%m-%dT%H:%M:%S%z") canonical_request="${me} ${pa} ${timestamp}" signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" From 631398f700dfc41414862b1bee4b33ff4c0b3d7a Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 00:21:08 +0100 Subject: [PATCH 241/383] sed workaround for "datez" --- dnsapi/dns_websupport.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index b145dc3e..b30ac994 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -1,3 +1,4 @@ + #!/usr/bin/env sh # Acme.sh DNS API wrapper for websupport.sk @@ -158,7 +159,7 @@ _ws_rest() { _debug2 api_secret "$WS_ApiSecret" timestamp=$(_time) - datez=$(date -u -d@"$timestamp" "+%Y-%m-%dT%H:%M:%S%z" 2>/dev/null || date -u -r "$timestamp" "+%Y-%m-%dT%H:%M:%S%z") + datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/")" canonical_request="${me} ${pa} ${timestamp}" signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" From 3d338bba3c8e9b5f3fad16316264a8e91ac51d7d Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 00:31:46 +0100 Subject: [PATCH 242/383] Fixing the shebang accident --- dnsapi/dns_websupport.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index b30ac994..922e6819 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -1,4 +1,3 @@ - #!/usr/bin/env sh # Acme.sh DNS API wrapper for websupport.sk From 8dc55f417d9244ff5a3b81cc396308d43a57528b Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 10:13:36 +0100 Subject: [PATCH 243/383] Extra test - adding date -u -d Adding this to at least partially prevent the virtually nonexistent possibility of timestamp and _utc_date() mismatch. If the normal date -u -d does not get converted (looking at you Solaris!), the poor man's method with manipulating the _utc_date() string output kicks in. --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 922e6819..d69a6c00 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -158,7 +158,7 @@ _ws_rest() { _debug2 api_secret "$WS_ApiSecret" timestamp=$(_time) - datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/")" + datez="$(date -u -d @"$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null/ || _utc_date | sed "s/ /T/" | sed "s/$/+0000/")" canonical_request="${me} ${pa} ${timestamp}" signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" From ced6852735ffb77a215f94022f3835be9196b369 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 11:15:13 +0100 Subject: [PATCH 244/383] 2>/dev/null/ to 2>/dev/null Silly mistake with a "/" -.- --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index d69a6c00..143b07b2 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -158,7 +158,7 @@ _ws_rest() { _debug2 api_secret "$WS_ApiSecret" timestamp=$(_time) - datez="$(date -u -d @"$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null/ || _utc_date | sed "s/ /T/" | sed "s/$/+0000/")" + datez="$(date -u -d @"$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || _utc_date | sed "s/ /T/" | sed "s/$/+0000/")" canonical_request="${me} ${pa} ${timestamp}" signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" From 94917e315e50e001d55c539d6d2e9f79669679f6 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 11:18:22 +0100 Subject: [PATCH 245/383] Testing double 2>/dev/null into _utc_date with sed --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 143b07b2..797c1b57 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -158,7 +158,7 @@ _ws_rest() { _debug2 api_secret "$WS_ApiSecret" timestamp=$(_time) - datez="$(date -u -d @"$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || _utc_date | sed "s/ /T/" | sed "s/$/+0000/")" + datez="$(date -u -d @"$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || _utc_date | sed "s/ /T/" | sed "s/$/+0000/")" canonical_request="${me} ${pa} ${timestamp}" signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" From 433d9bfb020ad00c27e305e31499f718fe4ec9e4 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 15:11:53 +0100 Subject: [PATCH 246/383] Implementing/testing Neil's suggestions --- dnsapi/dns_websupport.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 797c1b57..5089d7c3 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -158,9 +158,9 @@ _ws_rest() { _debug2 api_secret "$WS_ApiSecret" timestamp=$(_time) - datez="$(date -u -d @"$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || date -u -r "$timestamp" +%Y-%m-%dT%H:%M:%S%z 2>/dev/null || _utc_date | sed "s/ /T/" | sed "s/$/+0000/")" + datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/") canonical_request="${me} ${pa} ${timestamp}" - signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) + signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$WS_ApiSecret") basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" _debug2 method "$me" From 9e146a8a5a80004ca65d08b30e977d0c135ed25c Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 15:15:17 +0100 Subject: [PATCH 247/383] Typo Forgot a quotation mark on line 161 --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 5089d7c3..de3d8b71 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -158,7 +158,7 @@ _ws_rest() { _debug2 api_secret "$WS_ApiSecret" timestamp=$(_time) - datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/") + datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/")" canonical_request="${me} ${pa} ${timestamp}" signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$WS_ApiSecret") basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" From 6c9845b9f3838d56aaa76bcab4e9986334ca1432 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 15:18:39 +0100 Subject: [PATCH 248/383] adding the hex parameter to _hmac call --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index de3d8b71..e40a3729 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -160,7 +160,7 @@ _ws_rest() { timestamp=$(_time) datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/")" canonical_request="${me} ${pa} ${timestamp}" - signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$WS_ApiSecret") + signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$WS_ApiSecret" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" _debug2 method "$me" From 3a383589465cadb87e72ade8c0755a1deb483b4c Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 15:22:53 +0100 Subject: [PATCH 249/383] Trying the original solution _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index e40a3729..922e6819 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -160,7 +160,7 @@ _ws_rest() { timestamp=$(_time) datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/")" canonical_request="${me} ${pa} ${timestamp}" - signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$WS_ApiSecret" hex) + signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" _debug2 method "$me" From 2eda03f5dea919930d156c2cc8d6e976d173ec78 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 15:32:51 +0100 Subject: [PATCH 250/383] Changing the _hmac call into Neil's suggestion --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 922e6819..06ed9c78 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -160,7 +160,7 @@ _ws_rest() { timestamp=$(_time) datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/")" canonical_request="${me} ${pa} ${timestamp}" - signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) + signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$WS_ApiSecret" | _hex_dump | tr -d " ") basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" _debug2 method "$me" From b8494ab3cca644039bfda425e12d1f5079cfeace Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 17:15:22 +0100 Subject: [PATCH 251/383] Update dns_websupport.sh --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 06ed9c78..ed14a279 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -160,7 +160,7 @@ _ws_rest() { timestamp=$(_time) datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/")" canonical_request="${me} ${pa} ${timestamp}" - signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$WS_ApiSecret" | _hex_dump | tr -d " ") + signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$("$WS_ApiSecret" | _hex_dump | tr -d " ")") basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" _debug2 method "$me" From c8c727e6c652d45c826b05d783d695f2d066857d Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 17:21:33 +0100 Subject: [PATCH 252/383] added hex param to _hmac but removed "printf "s%" ... --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index ed14a279..773d693d 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -160,7 +160,7 @@ _ws_rest() { timestamp=$(_time) datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/")" canonical_request="${me} ${pa} ${timestamp}" - signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$("$WS_ApiSecret" | _hex_dump | tr -d " ")") + signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$("$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" _debug2 method "$me" From 0021fb8a33df61c7578df4ff61a836eee16283a4 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Thu, 4 Feb 2021 17:27:39 +0100 Subject: [PATCH 253/383] Changing the _hmac auth back It only works this way, apparently --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 773d693d..922e6819 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -160,7 +160,7 @@ _ws_rest() { timestamp=$(_time) datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/")" canonical_request="${me} ${pa} ${timestamp}" - signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$("$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) + signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" _debug2 method "$me" From 987571ce91179ee33f5af0eac4bc49053312ce3b Mon Sep 17 00:00:00 2001 From: Gnought <1684105+gnought@users.noreply.github.com> Date: Thu, 11 Feb 2021 01:08:08 +0800 Subject: [PATCH 256/383] Updated --preferred-chain to issue ISRG properly To support different openssl crl2pkcs7 help cli format --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index a1ad4195..749400e2 100755 --- a/acme.sh +++ b/acme.sh @@ -4011,7 +4011,7 @@ _check_dns_entries() { #file _get_cert_issuers() { _cfile="$1" - if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then + if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -help 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 else ${ACME_OPENSSL_BIN:-openssl} x509 -in $_cfile -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 From 8636d3139e34b245a512c56ff6a58a4e697241c3 Mon Sep 17 00:00:00 2001 From: manuel Date: Thu, 11 Feb 2021 11:20:18 +0100 Subject: [PATCH 257/383] dnsapi/pdns: also normalize json response in detecting root zone --- dnsapi/dns_pdns.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_pdns.sh b/dnsapi/dns_pdns.sh index 8f07e8c4..28b35492 100755 --- a/dnsapi/dns_pdns.sh +++ b/dnsapi/dns_pdns.sh @@ -175,13 +175,13 @@ _get_root() { i=1 if _pdns_rest "GET" "/api/v1/servers/$PDNS_ServerId/zones"; then - _zones_response="$response" + _zones_response=$(echo "$response" | _normalizeJson) fi while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) - if _contains "$_zones_response" "\"name\": \"$h.\""; then + if _contains "$_zones_response" "\"name\":\"$h.\""; then _domain="$h." if [ -z "$h" ]; then _domain="=2E" From 12b1916599aa4e58fa4c74aa6d454a7f144eb1f5 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 13 Feb 2021 16:22:31 +0800 Subject: [PATCH 258/383] Chain (#3408) * fix https://github.com/acmesh-official/acme.sh/issues/3384 match the issuer to the root CA cert subject * fix format * fix https://github.com/acmesh-official/acme.sh/issues/3384 * remove the alt files. https://github.com/acmesh-official/acme.sh/issues/3384 --- acme.sh | 58 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/acme.sh b/acme.sh index 749400e2..a9301e10 100755 --- a/acme.sh +++ b/acme.sh @@ -4009,12 +4009,42 @@ _check_dns_entries() { } #file -_get_cert_issuers() { +_get_chain_issuers() { _cfile="$1" if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -help 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then - ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 + ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep -i 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 else - ${ACME_OPENSSL_BIN:-openssl} x509 -in $_cfile -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 + _cindex=1 + for _startn in $(grep -n -- "$BEGIN_CERT" "$_cfile" | cut -d : -f 1); do + _endn="$(grep -n -- "$END_CERT" "$_cfile" | cut -d : -f 1 | _head_n $_cindex | _tail_n 1)" + _debug2 "_startn" "$_startn" + _debug2 "_endn" "$_endn" + if [ "$DEBUG" ]; then + _debug2 "cert$_cindex" "$(sed -n "$_startn,${_endn}p" "$_cfile")" + fi + sed -n "$_startn,${_endn}p" "$_cfile" | ${ACME_OPENSSL_BIN:-openssl} x509 -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 | sed "s/ *\(.*\)/\1/" + _cindex=$(_math $_cindex + 1) + done + fi +} + +# +_get_chain_subjects() { + _cfile="$1" + if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -help 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then + ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep -i 'Subject:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 + else + _cindex=1 + for _startn in $(grep -n -- "$BEGIN_CERT" "$_cfile" | cut -d : -f 1); do + _endn="$(grep -n -- "$END_CERT" "$_cfile" | cut -d : -f 1 | _head_n $_cindex | _tail_n 1)" + _debug2 "_startn" "$_startn" + _debug2 "_endn" "$_endn" + if [ "$DEBUG" ]; then + _debug2 "cert$_cindex" "$(sed -n "$_startn,${_endn}p" "$_cfile")" + fi + sed -n "$_startn,${_endn}p" "$_cfile" | ${ACME_OPENSSL_BIN:-openssl} x509 -text -noout | grep -i 'Subject:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 | sed "s/ *\(.*\)/\1/" + _cindex=$(_math $_cindex + 1) + done fi } @@ -4022,14 +4052,12 @@ _get_cert_issuers() { _match_issuer() { _cfile="$1" _missuer="$2" - _fissuers="$(_get_cert_issuers $_cfile)" + _fissuers="$(_get_chain_issuers $_cfile)" _debug2 _fissuers "$_fissuers" - if _contains "$_fissuers" "$_missuer"; then - return 0 - fi - _fissuers="$(echo "$_fissuers" | _lower_case)" + _rootissuer="$(echo "$_fissuers" | _lower_case | _tail_n 1)" + _debug2 _rootissuer "$_rootissuer" _missuer="$(echo "$_missuer" | _lower_case)" - _contains "$_fissuers" "$_missuer" + _contains "$_rootissuer" "$_missuer" } #webroot, domain domainlist keylength @@ -4803,6 +4831,9 @@ $_authorizations_map" _split_cert_chain "$CERT_PATH" "$CERT_FULLCHAIN_PATH" "$CA_CERT_PATH" if [ "$_preferred_chain" ] && [ -f "$CERT_FULLCHAIN_PATH" ]; then + if [ "$DEBUG" ]; then + _debug "default chain issuers: " "$(_get_chain_issuers "$CERT_FULLCHAIN_PATH")" + fi if ! _match_issuer "$CERT_FULLCHAIN_PATH" "$_preferred_chain"; then rels="$(echo "$responseHeaders" | tr -d ' <>' | grep -i "^link:" | grep -i 'rel="alternate"' | cut -d : -f 2- | cut -d ';' -f 1)" _debug2 "rels" "$rels" @@ -4818,13 +4849,22 @@ $_authorizations_map" _relca="$CA_CERT_PATH.alt" echo "$response" >"$_relcert" _split_cert_chain "$_relcert" "$_relfullchain" "$_relca" + if [ "$DEBUG" ]; then + _debug "rel chain issuers: " "$(_get_chain_issuers "$_relfullchain")" + fi if _match_issuer "$_relfullchain" "$_preferred_chain"; then _info "Matched issuer in: $rel" cat $_relcert >"$CERT_PATH" cat $_relfullchain >"$CERT_FULLCHAIN_PATH" cat $_relca >"$CA_CERT_PATH" + rm -f "$_relcert" + rm -f "$_relfullchain" + rm -f "$_relca" break fi + rm -f "$_relcert" + rm -f "$_relfullchain" + rm -f "$_relca" done fi fi From d8163e9835e2587793b51cc07b5e81aff3f2da8c Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 13 Feb 2021 17:27:22 +0800 Subject: [PATCH 259/383] upgrade freebsd and solaris --- .github/workflows/LetsEncrypt.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 8d0c4eb0..7c398c09 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -111,7 +111,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.0.7 + - uses: vmactions/freebsd-vm@v0.1.2 with: envs: 'NGROK_TOKEN TEST_LOCAL' prepare: pkg install -y socat curl @@ -136,7 +136,7 @@ jobs: run: echo "TestingDomain=${{steps.ngrok.outputs.server}}" >> $GITHUB_ENV - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/solaris-vm@v0.0.1 + - uses: vmactions/solaris-vm@v0.0.3 with: envs: 'TEST_LOCAL TestingDomain' nat: | From b7c3e6099cf3cdf9ed7d0c46d3a1aa0858c7cf02 Mon Sep 17 00:00:00 2001 From: jerrm Date: Sat, 13 Feb 2021 05:58:44 -0500 Subject: [PATCH 260/383] duckdns - fix "integer expression expected" errors (#3397) * fix "integer expression expected" errors * duckdns fix * Update dns_duckdns.sh * Update dns_duckdns.sh --- dnsapi/dns_duckdns.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index 618e12c6..d6e1dbdc 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -12,7 +12,7 @@ DuckDNS_API="https://www.duckdns.org/update" -######## Public functions ##################### +######## Public functions ###################### #Usage: dns_duckdns_add _acme-challenge.domain.duckdns.org "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_duckdns_add() { @@ -112,7 +112,7 @@ _duckdns_rest() { param="$2" _debug param "$param" url="$DuckDNS_API?$param" - if [ "$DEBUG" -gt 0 ]; then + if [ -n "$DEBUG" ] && [ "$DEBUG" -gt 0 ]; then url="$url&verbose=true" fi _debug url "$url" @@ -121,7 +121,7 @@ _duckdns_rest() { if [ "$method" = "GET" ]; then response="$(_get "$url")" _debug2 response "$response" - if [ "$DEBUG" -gt 0 ] && _contains "$response" "UPDATED" && _contains "$response" "OK"; then + if [ -n "$DEBUG" ] && [ "$DEBUG" -gt 0 ] && _contains "$response" "UPDATED" && _contains "$response" "OK"; then response="OK" fi else From 1de9ffacb0e38a6a26291b088645638d0a3a890c Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 29 Dec 2020 16:28:38 -0800 Subject: [PATCH 261/383] Implement smtp notify hook Support notifications via direct SMTP server connection. Uses Python (2.7.x or 3.4+) to communicate with SMTP server. --- notify/smtp.sh | 185 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 183 insertions(+), 2 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 6aa37ca3..367021c8 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -2,7 +2,103 @@ # support smtp +# This implementation uses Python (2 or 3), which is available in many environments. +# If you don't have Python, try "mail" notification instead of "smtp". + +# SMTP_FROM="from@example.com" # required +# SMTP_TO="to@example.com" # required +# SMTP_HOST="smtp.example.com" # required +# SMTP_PORT="25" # defaults to 25, 465 or 587 depending on SMTP_SECURE +# SMTP_SECURE="none" # one of "none", "ssl" (implicit TLS, TLS Wrapper), "tls" (explicit TLS, STARTTLS) +# SMTP_USERNAME="" # set if SMTP server requires login +# SMTP_PASSWORD="" # set if SMTP server requires login +# SMTP_TIMEOUT="15" # seconds for SMTP operations to timeout +# SMTP_PYTHON="/path/to/python" # defaults to system python3 or python + smtp_send() { + # Find a Python interpreter: + SMTP_PYTHON="${SMTP_PYTHON:-$(_readaccountconf_mutable SMTP_PYTHON)}" + if [ "$SMTP_PYTHON" ]; then + if _exists "$SMTP_PYTHON"; then + _saveaccountconf_mutable SMTP_PYTHON "$SMTP_PYTHON" + else + _err "SMTP_PYTHON '$SMTP_PYTHON' does not exist." + return 1 + fi + else + # No SMTP_PYTHON setting; try to run default Python. + # (This is not saved with the conf.) + if _exists python3; then + SMTP_PYTHON="python3" + elif _exists python; then + SMTP_PYTHON="python" + else + _err "Can't locate Python interpreter; please define SMTP_PYTHON." + return 1 + fi + fi + _debug "SMTP_PYTHON" "$SMTP_PYTHON" + _debug "Python version" "$($SMTP_PYTHON --version 2>&1)" + + # Validate other settings: + SMTP_FROM="${SMTP_FROM:-$(_readaccountconf_mutable SMTP_FROM)}" + if [ -z "$SMTP_FROM" ]; then + _err "You must define SMTP_FROM as the sender email address." + return 1 + fi + + SMTP_TO="${SMTP_TO:-$(_readaccountconf_mutable SMTP_TO)}" + if [ -z "$SMTP_TO" ]; then + _err "You must define SMTP_TO as the recipient email address." + return 1 + fi + + SMTP_HOST="${SMTP_HOST:-$(_readaccountconf_mutable SMTP_HOST)}" + if [ -z "$SMTP_HOST" ]; then + _err "You must define SMTP_HOST as the SMTP server hostname." + return 1 + fi + SMTP_PORT="${SMTP_PORT:-$(_readaccountconf_mutable SMTP_PORT)}" + + SMTP_SECURE="${SMTP_SECURE:-$(_readaccountconf_mutable SMTP_SECURE)}" + SMTP_SECURE="${SMTP_SECURE:-none}" + case "$SMTP_SECURE" in + "none") SMTP_DEFAULT_PORT="25";; + "ssl") SMTP_DEFAULT_PORT="465";; + "tls") SMTP_DEFAULT_PORT="587";; + *) + _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." + return 1 + ;; + esac + + SMTP_USERNAME="${SMTP_USERNAME:-$(_readaccountconf_mutable SMTP_USERNAME)}" + SMTP_PASSWORD="${SMTP_PASSWORD:-$(_readaccountconf_mutable SMTP_PASSWORD)}" + + SMTP_TIMEOUT="${SMTP_TIMEOUT:-$(_readaccountconf_mutable SMTP_TIMEOUT)}" + SMTP_DEFAULT_TIMEOUT="15" + + _saveaccountconf_mutable SMTP_FROM "$SMTP_FROM" + _saveaccountconf_mutable SMTP_TO "$SMTP_TO" + _saveaccountconf_mutable SMTP_HOST "$SMTP_HOST" + _saveaccountconf_mutable SMTP_PORT "$SMTP_PORT" + _saveaccountconf_mutable SMTP_SECURE "$SMTP_SECURE" + _saveaccountconf_mutable SMTP_USERNAME "$SMTP_USERNAME" + _saveaccountconf_mutable SMTP_PASSWORD "$SMTP_PASSWORD" + _saveaccountconf_mutable SMTP_TIMEOUT "$SMTP_TIMEOUT" + + # Send the message: + if ! _smtp_send "$@"; then + _err "$smtp_send_output" + return 1 + fi + + return 0 +} + +# _send subject content statuscode +# Send the message via Python using SMTP_* settings +_smtp_send() { _subject="$1" _content="$2" _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped @@ -10,6 +106,91 @@ smtp_send() { _debug "_content" "$_content" _debug "_statusCode" "$_statusCode" - _err "Not implemented yet." - return 1 + _debug "SMTP_FROM" "$SMTP_FROM" + _debug "SMTP_TO" "$SMTP_TO" + _debug "SMTP_HOST" "$SMTP_HOST" + _debug "SMTP_PORT" "$SMTP_PORT" + _debug "SMTP_DEFAULT_PORT" "$SMTP_DEFAULT_PORT" + _debug "SMTP_SECURE" "$SMTP_SECURE" + _debug "SMTP_USERNAME" "$SMTP_USERNAME" + _secure_debug "SMTP_PASSWORD" "$SMTP_PASSWORD" + _debug "SMTP_TIMEOUT" "$SMTP_TIMEOUT" + _debug "SMTP_DEFAULT_TIMEOUT" "$SMTP_DEFAULT_TIMEOUT" + + if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then + # Output the SMTP server dialogue. (Note this will include SMTP_PASSWORD!) + smtp_debug="True" + else + smtp_debug="" + fi + + # language=Python + smtp_send_output="$($SMTP_PYTHON < Date: Tue, 29 Dec 2020 17:10:36 -0800 Subject: [PATCH 262/383] Make shfmt happy (I'm open to better ways of formatting the heredoc that embeds the Python script.) --- notify/smtp.sh | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 367021c8..6171cb9b 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -63,13 +63,13 @@ smtp_send() { SMTP_SECURE="${SMTP_SECURE:-$(_readaccountconf_mutable SMTP_SECURE)}" SMTP_SECURE="${SMTP_SECURE:-none}" case "$SMTP_SECURE" in - "none") SMTP_DEFAULT_PORT="25";; - "ssl") SMTP_DEFAULT_PORT="465";; - "tls") SMTP_DEFAULT_PORT="587";; - *) - _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." - return 1 - ;; + "none") SMTP_DEFAULT_PORT="25" ;; + "ssl") SMTP_DEFAULT_PORT="465" ;; + "tls") SMTP_DEFAULT_PORT="587" ;; + *) + _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." + return 1 + ;; esac SMTP_USERNAME="${SMTP_USERNAME:-$(_readaccountconf_mutable SMTP_USERNAME)}" @@ -125,7 +125,8 @@ _smtp_send() { fi # language=Python - smtp_send_output="$($SMTP_PYTHON < Date: Mon, 11 Jan 2021 11:46:26 -0800 Subject: [PATCH 263/383] Only save config if send is successful --- notify/smtp.sh | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 6171cb9b..092bb2b9 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -78,6 +78,13 @@ smtp_send() { SMTP_TIMEOUT="${SMTP_TIMEOUT:-$(_readaccountconf_mutable SMTP_TIMEOUT)}" SMTP_DEFAULT_TIMEOUT="15" + # Send the message: + if ! _smtp_send "$@"; then + _err "$smtp_send_output" + return 1 + fi + + # Save remaining config if successful. (SMTP_PYTHON is saved earlier.) _saveaccountconf_mutable SMTP_FROM "$SMTP_FROM" _saveaccountconf_mutable SMTP_TO "$SMTP_TO" _saveaccountconf_mutable SMTP_HOST "$SMTP_HOST" @@ -87,12 +94,6 @@ smtp_send() { _saveaccountconf_mutable SMTP_PASSWORD "$SMTP_PASSWORD" _saveaccountconf_mutable SMTP_TIMEOUT "$SMTP_TIMEOUT" - # Send the message: - if ! _smtp_send "$@"; then - _err "$smtp_send_output" - return 1 - fi - return 0 } From fe273b3829511febe42f9b854ba921213f7bedbb Mon Sep 17 00:00:00 2001 From: medmunds Date: Mon, 11 Jan 2021 12:59:51 -0800 Subject: [PATCH 264/383] Add instructions for reporting bugs --- notify/smtp.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/notify/smtp.sh b/notify/smtp.sh index 092bb2b9..a74ce092 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -2,6 +2,8 @@ # support smtp +# Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3358 + # This implementation uses Python (2 or 3), which is available in many environments. # If you don't have Python, try "mail" notification instead of "smtp". From 557a747d55a91eb7f1ac97028decc5d141fb2466 Mon Sep 17 00:00:00 2001 From: medmunds Date: Sun, 14 Feb 2021 15:47:51 -0800 Subject: [PATCH 265/383] Prep for curl or Python; clean up SMTP_* variable usage --- notify/smtp.sh | 203 ++++++++++++++++++++++++++++--------------------- 1 file changed, 118 insertions(+), 85 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index a74ce092..cb29d0f7 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -4,8 +4,8 @@ # Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3358 -# This implementation uses Python (2 or 3), which is available in many environments. -# If you don't have Python, try "mail" notification instead of "smtp". +# This implementation uses either curl or Python (3 or 2.7). +# (See also the "mail" notify hook, which supports other ways to send mail.) # SMTP_FROM="from@example.com" # required # SMTP_TO="to@example.com" # required @@ -14,79 +14,132 @@ # SMTP_SECURE="none" # one of "none", "ssl" (implicit TLS, TLS Wrapper), "tls" (explicit TLS, STARTTLS) # SMTP_USERNAME="" # set if SMTP server requires login # SMTP_PASSWORD="" # set if SMTP server requires login -# SMTP_TIMEOUT="15" # seconds for SMTP operations to timeout -# SMTP_PYTHON="/path/to/python" # defaults to system python3 or python +# SMTP_TIMEOUT="30" # seconds for SMTP operations to timeout +# SMTP_BIN="/path/to/curl_or_python" # default finds first of curl, python3, or python on PATH +# subject content statuscode smtp_send() { - # Find a Python interpreter: - SMTP_PYTHON="${SMTP_PYTHON:-$(_readaccountconf_mutable SMTP_PYTHON)}" - if [ "$SMTP_PYTHON" ]; then - if _exists "$SMTP_PYTHON"; then - _saveaccountconf_mutable SMTP_PYTHON "$SMTP_PYTHON" - else - _err "SMTP_PYTHON '$SMTP_PYTHON' does not exist." - return 1 - fi - else - # No SMTP_PYTHON setting; try to run default Python. - # (This is not saved with the conf.) - if _exists python3; then - SMTP_PYTHON="python3" - elif _exists python; then - SMTP_PYTHON="python" - else - _err "Can't locate Python interpreter; please define SMTP_PYTHON." + _SMTP_SUBJECT="$1" + _SMTP_CONTENT="$2" + # UNUSED: _statusCode="$3" # 0: success, 1: error 2($RENEW_SKIP): skipped + + # Load config: + SMTP_FROM="${SMTP_FROM:-$(_readaccountconf_mutable SMTP_FROM)}" + SMTP_TO="${SMTP_TO:-$(_readaccountconf_mutable SMTP_TO)}" + SMTP_HOST="${SMTP_HOST:-$(_readaccountconf_mutable SMTP_HOST)}" + SMTP_PORT="${SMTP_PORT:-$(_readaccountconf_mutable SMTP_PORT)}" + SMTP_SECURE="${SMTP_SECURE:-$(_readaccountconf_mutable SMTP_SECURE)}" + SMTP_USERNAME="${SMTP_USERNAME:-$(_readaccountconf_mutable SMTP_USERNAME)}" + SMTP_PASSWORD="${SMTP_PASSWORD:-$(_readaccountconf_mutable SMTP_PASSWORD)}" + SMTP_TIMEOUT="${SMTP_TIMEOUT:-$(_readaccountconf_mutable SMTP_TIMEOUT)}" + SMTP_BIN="${SMTP_BIN:-$(_readaccountconf_mutable SMTP_BIN)}" + + _debug "SMTP_FROM" "$SMTP_FROM" + _debug "SMTP_TO" "$SMTP_TO" + _debug "SMTP_HOST" "$SMTP_HOST" + _debug "SMTP_PORT" "$SMTP_PORT" + _debug "SMTP_SECURE" "$SMTP_SECURE" + _debug "SMTP_USERNAME" "$SMTP_USERNAME" + _secure_debug "SMTP_PASSWORD" "$SMTP_PASSWORD" + _debug "SMTP_TIMEOUT" "$SMTP_TIMEOUT" + _debug "SMTP_BIN" "$SMTP_BIN" + + _debug "_SMTP_SUBJECT" "$_SMTP_SUBJECT" + _debug "_SMTP_CONTENT" "$_SMTP_CONTENT" + + # Validate config and apply defaults: + # _SMTP_* variables are the resolved (with defaults) versions of SMTP_*. + # (The _SMTP_* versions will not be stored in account conf.) + + if [ -n "$SMTP_BIN" ] && ! _exists "$SMTP_BIN"; then + _err "SMTP_BIN '$SMTP_BIN' does not exist." + return 1 + fi + _SMTP_BIN="$SMTP_BIN" + if [ -z "$_SMTP_BIN" ]; then + # Look for a command that can communicate with an SMTP server. + # (Please don't add sendmail, ssmtp, mutt, mail, or msmtp here. + # Those are already handled by the "mail" notify hook.) + for cmd in curl python3 python2.7 python pypy3 pypy; do + if _exists "$cmd"; then + _SMTP_BIN="$cmd" + break + fi + done + if [ -z "$_SMTP_BIN" ]; then + _err "The smtp notify-hook requires curl or Python, but can't find any." + _err 'If you have one of them, define SMTP_BIN="/path/to/curl_or_python".' + _err 'Otherwise, see if you can use the "mail" notify-hook instead.' return 1 fi + _debug "_SMTP_BIN" "$_SMTP_BIN" fi - _debug "SMTP_PYTHON" "$SMTP_PYTHON" - _debug "Python version" "$($SMTP_PYTHON --version 2>&1)" - # Validate other settings: - SMTP_FROM="${SMTP_FROM:-$(_readaccountconf_mutable SMTP_FROM)}" if [ -z "$SMTP_FROM" ]; then _err "You must define SMTP_FROM as the sender email address." return 1 fi + _SMTP_FROM="$SMTP_FROM" - SMTP_TO="${SMTP_TO:-$(_readaccountconf_mutable SMTP_TO)}" if [ -z "$SMTP_TO" ]; then _err "You must define SMTP_TO as the recipient email address." return 1 fi + _SMTP_TO="$SMTP_TO" - SMTP_HOST="${SMTP_HOST:-$(_readaccountconf_mutable SMTP_HOST)}" if [ -z "$SMTP_HOST" ]; then _err "You must define SMTP_HOST as the SMTP server hostname." return 1 fi - SMTP_PORT="${SMTP_PORT:-$(_readaccountconf_mutable SMTP_PORT)}" + _SMTP_HOST="$SMTP_HOST" - SMTP_SECURE="${SMTP_SECURE:-$(_readaccountconf_mutable SMTP_SECURE)}" - SMTP_SECURE="${SMTP_SECURE:-none}" - case "$SMTP_SECURE" in - "none") SMTP_DEFAULT_PORT="25" ;; - "ssl") SMTP_DEFAULT_PORT="465" ;; - "tls") SMTP_DEFAULT_PORT="587" ;; + _SMTP_SECURE="${SMTP_SECURE:-none}" + case "$_SMTP_SECURE" in + "none") smtp_default_port="25" ;; + "ssl") smtp_default_port="465" ;; + "tls") smtp_default_port="587" ;; *) _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." return 1 ;; esac - SMTP_USERNAME="${SMTP_USERNAME:-$(_readaccountconf_mutable SMTP_USERNAME)}" - SMTP_PASSWORD="${SMTP_PASSWORD:-$(_readaccountconf_mutable SMTP_PASSWORD)}" + _SMTP_PORT="${SMTP_PORT:-$smtp_default_port}" + if [ -z "$SMTP_PORT" ]; then + _debug "_SMTP_PORT" "$_SMTP_PORT" + fi - SMTP_TIMEOUT="${SMTP_TIMEOUT:-$(_readaccountconf_mutable SMTP_TIMEOUT)}" - SMTP_DEFAULT_TIMEOUT="15" + _SMTP_USERNAME="$SMTP_USERNAME" + _SMTP_PASSWORD="$SMTP_PASSWORD" + _SMTP_TIMEOUT="${SMTP_TIMEOUT:-30}" + + # Run with --debug 2 (or above) to echo the transcript of the SMTP session. + # Careful: this may include SMTP_PASSWORD in plaintext! + if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then + _SMTP_SHOW_TRANSCRIPT="True" + else + _SMTP_SHOW_TRANSCRIPT="" + fi # Send the message: - if ! _smtp_send "$@"; then - _err "$smtp_send_output" + case "$(basename "$_SMTP_BIN")" in + curl) _smtp_send=_smtp_send_curl ;; + py*) _smtp_send=_smtp_send_python ;; + *) + _err "Can't figure out how to invoke $_SMTP_BIN." + _err "Please re-run with --debug and report a bug." + return 1 + ;; + esac + + if ! smtp_output="$($_smtp_send)"; then + _err "Error sending message with $_SMTP_BIN." + _err "${smtp_output:-(No additional details; try --debug or --debug 2)}" return 1 fi - # Save remaining config if successful. (SMTP_PYTHON is saved earlier.) + # Save config only if send was successful: + _saveaccountconf_mutable SMTP_BIN "$SMTP_BIN" _saveaccountconf_mutable SMTP_FROM "$SMTP_FROM" _saveaccountconf_mutable SMTP_TO "$SMTP_TO" _saveaccountconf_mutable SMTP_HOST "$SMTP_HOST" @@ -99,37 +152,21 @@ smtp_send() { return 0 } -# _send subject content statuscode -# Send the message via Python using SMTP_* settings -_smtp_send() { - _subject="$1" - _content="$2" - _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped - _debug "_subject" "$_subject" - _debug "_content" "$_content" - _debug "_statusCode" "$_statusCode" - _debug "SMTP_FROM" "$SMTP_FROM" - _debug "SMTP_TO" "$SMTP_TO" - _debug "SMTP_HOST" "$SMTP_HOST" - _debug "SMTP_PORT" "$SMTP_PORT" - _debug "SMTP_DEFAULT_PORT" "$SMTP_DEFAULT_PORT" - _debug "SMTP_SECURE" "$SMTP_SECURE" - _debug "SMTP_USERNAME" "$SMTP_USERNAME" - _secure_debug "SMTP_PASSWORD" "$SMTP_PASSWORD" - _debug "SMTP_TIMEOUT" "$SMTP_TIMEOUT" - _debug "SMTP_DEFAULT_TIMEOUT" "$SMTP_DEFAULT_TIMEOUT" +# Send the message via curl using _SMTP_* variables +_smtp_send_curl() { + # TODO: implement + echo "_smtp_send_curl not implemented" + return 1 +} - if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then - # Output the SMTP server dialogue. (Note this will include SMTP_PASSWORD!) - smtp_debug="True" - else - smtp_debug="" - fi + +# Send the message via Python using _SMTP_* variables +_smtp_send_python() { + _debug "Python version" "$("$_SMTP_BIN" --version 2>&1)" # language=Python - smtp_send_output="$( - $SMTP_PYTHON < Date: Sun, 14 Feb 2021 19:56:23 -0800 Subject: [PATCH 266/383] Implement curl version of smtp notify-hook --- notify/smtp.sh | 111 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 105 insertions(+), 6 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index cb29d0f7..44a5821f 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -127,14 +127,16 @@ smtp_send() { py*) _smtp_send=_smtp_send_python ;; *) _err "Can't figure out how to invoke $_SMTP_BIN." - _err "Please re-run with --debug and report a bug." + _err "Check your SMTP_BIN setting." return 1 ;; esac if ! smtp_output="$($_smtp_send)"; then _err "Error sending message with $_SMTP_BIN." - _err "${smtp_output:-(No additional details; try --debug or --debug 2)}" + if [ -n "$smtp_output" ]; then + _err "$smtp_output" + fi return 1 fi @@ -152,12 +154,109 @@ smtp_send() { return 0 } - # Send the message via curl using _SMTP_* variables _smtp_send_curl() { - # TODO: implement - echo "_smtp_send_curl not implemented" - return 1 + # curl passes --mail-from and --mail-rcpt directly to the SMTP protocol without + # additional parsing, and SMTP requires addr-spec only (no display names). + # In the future, maybe try to parse the addr-spec out for curl args (non-trivial). + if _email_has_display_name "$_SMTP_FROM"; then + _err "curl smtp only allows a simple email address in SMTP_FROM." + _err "Change your SMTP_FROM='$SMTP_FROM' to remove the display name." + return 1 + fi + if _email_has_display_name "$_SMTP_TO"; then + _err "curl smtp only allows simple email addresses in SMTP_TO." + _err "Change your SMTP_TO='$SMTP_TO' to remove the display name(s)." + return 1 + fi + + # Build curl args in $@ + + case "$_SMTP_SECURE" in + none) + set -- --url "smtp://${_SMTP_HOST}:${_SMTP_PORT}" + ;; + ssl) + set -- --url "smtps://${_SMTP_HOST}:${_SMTP_PORT}" + ;; + tls) + set -- --url "smtp://${_SMTP_HOST}:${_SMTP_PORT}" --ssl-reqd + ;; + *) + # This will only occur if someone adds a new SMTP_SECURE option above + # without updating this code for it. + _err "Unhandled _SMTP_SECURE='$_SMTP_SECURE' in _smtp_send_curl" + _err "Please re-run with --debug and report a bug." + return 1 + ;; + esac + + set -- "$@" \ + --upload-file - \ + --mail-from "$_SMTP_FROM" \ + --max-time "$_SMTP_TIMEOUT" + + # Burst comma-separated $_SMTP_TO into individual --mail-rcpt args. + _to="${_SMTP_TO}," + while [ -n "$_to" ]; do + _rcpt="${_to%%,*}" + _to="${_to#*,}" + set -- "$@" --mail-rcpt "$_rcpt" + done + + _smtp_login="${_SMTP_USERNAME}:${_SMTP_PASSWORD}" + if [ "$_smtp_login" != ":" ]; then + set -- "$@" --user "$_smtp_login" + fi + + if [ "$_SMTP_SHOW_TRANSCRIPT" = "True" ]; then + set -- "$@" --verbose + else + set -- "$@" --silent --show-error + fi + + raw_message="$(_smtp_raw_message)" + + _debug2 "curl command:" "$_SMTP_BIN" "$*" + _debug2 "raw_message:\n$raw_message" + + echo "$raw_message" | "$_SMTP_BIN" "$@" +} + +# Output an RFC-822 / RFC-5322 email message using _SMTP_* variables +_smtp_raw_message() { + echo "From: $_SMTP_FROM" + echo "To: $_SMTP_TO" + echo "Subject: $(_mime_encoded_word "$_SMTP_SUBJECT")" + if _exists date; then + echo "Date: $(date +'%a, %-d %b %Y %H:%M:%S %z')" + fi + echo "Content-Type: text/plain; charset=utf-8" + echo "X-Mailer: acme.sh --notify-hook smtp" + echo + echo "$_SMTP_CONTENT" +} + +# Convert text to RFC-2047 MIME "encoded word" format if it contains non-ASCII chars +# text +_mime_encoded_word() { + _text="$1" + # (regex character ranges like [a-z] can be locale-dependent; enumerate ASCII chars to avoid that) + _ascii='] $`"'"[!#%&'()*+,./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ~^_abcdefghijklmnopqrstuvwxyz{|}~-" + if expr "$_text" : "^.*[^$_ascii]" >/dev/null; then + # At least one non-ASCII char; convert entire thing to encoded word + printf "%s" "=?UTF-8?B?$(printf "%s" "$_text" | _base64)?=" + else + # Just printable ASCII, no conversion needed + printf "%s" "$_text" + fi +} + +# Simple check for display name in an email address (< > or ") +# email +_email_has_display_name() { + _email="$1" + expr "$_email" : '^.*[<>"]' > /dev/null } From ffe7ef476439df04e1878ea08f0c6b3eb91653c6 Mon Sep 17 00:00:00 2001 From: medmunds Date: Sun, 14 Feb 2021 20:06:07 -0800 Subject: [PATCH 267/383] More than one blank line is an abomination, apparently I will not try to use whitespace to group code visually --- notify/smtp.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 44a5821f..c9927e3e 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -256,10 +256,9 @@ _mime_encoded_word() { # email _email_has_display_name() { _email="$1" - expr "$_email" : '^.*[<>"]' > /dev/null + expr "$_email" : '^.*[<>"]' >/dev/null } - # Send the message via Python using _SMTP_* variables _smtp_send_python() { _debug "Python version" "$("$_SMTP_BIN" --version 2>&1)" From bf8c33703c3b69de79a992f1ca84748fa4bc1707 Mon Sep 17 00:00:00 2001 From: Mike Edmunds Date: Sun, 14 Feb 2021 23:01:21 -0800 Subject: [PATCH 268/383] Fix: Unifi deploy hook support Unifi Cloud Key (#3327) * fix: unifi deploy hook also update Cloud Key nginx certs When running on a Unifi Cloud Key device, also deploy to /etc/ssl/private/cloudkey.{crt,key} and reload nginx. This makes the new cert available for the Cloud Key management app running via nginx on port 443 (as well as the port 8443 Unifi Controller app the deploy hook already supported). Fixes #3326 * Improve settings documentation comments * Improve Cloud Key pre-flight error messaging * Fix typo * Add support for UnifiOS (Cloud Key Gen2) Since UnifiOS does not use the Java keystore (like a Unifi Controller or Cloud Key Gen1 deploy), this also reworks the settings validation and error messaging somewhat. * PR review fixes * Detect unsupported Cloud Key java keystore location * Don't try to restart inactive services (and remove extra spaces from reload command) * Clean up error messages and internal variables * Change to _getdeployconf/_savedeployconf * Switch from cp to cat to preserve file permissions --- deploy/unifi.sh | 220 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 167 insertions(+), 53 deletions(-) diff --git a/deploy/unifi.sh b/deploy/unifi.sh index 184aa62e..a864135e 100644 --- a/deploy/unifi.sh +++ b/deploy/unifi.sh @@ -1,12 +1,43 @@ #!/usr/bin/env sh -#Here is a script to deploy cert to unifi server. +# Here is a script to deploy cert on a Unifi Controller or Cloud Key device. +# It supports: +# - self-hosted Unifi Controller +# - Unifi Cloud Key (Gen1/2/2+) +# - Unifi Cloud Key running UnifiOS (v2.0.0+, Gen2/2+ only) +# Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3359 #returns 0 means success, otherwise error. +# The deploy-hook automatically detects standard Unifi installations +# for each of the supported environments. Most users should not need +# to set any of these variables, but if you are running a self-hosted +# Controller with custom locations, set these as necessary before running +# the deploy hook. (Defaults shown below.) +# +# Settings for Unifi Controller: +# Location of Java keystore or unifi.keystore.jks file: #DEPLOY_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore" +# Keystore password (built into Unifi Controller, not a user-set password): #DEPLOY_UNIFI_KEYPASS="aircontrolenterprise" +# Command to restart Unifi Controller: #DEPLOY_UNIFI_RELOAD="service unifi restart" +# +# Settings for Unifi Cloud Key Gen1 (nginx admin pages): +# Directory where cloudkey.crt and cloudkey.key live: +#DEPLOY_UNIFI_CLOUDKEY_CERTDIR="/etc/ssl/private" +# Command to restart maintenance pages and Controller +# (same setting as above, default is updated when running on Cloud Key Gen1): +#DEPLOY_UNIFI_RELOAD="service nginx restart && service unifi restart" +# +# Settings for UnifiOS (Cloud Key Gen2): +# Directory where unifi-core.crt and unifi-core.key live: +#DEPLOY_UNIFI_CORE_CONFIG="/data/unifi-core/config/" +# Command to restart unifi-core: +#DEPLOY_UNIFI_RELOAD="systemctl restart unifi-core" +# +# At least one of DEPLOY_UNIFI_KEYSTORE, DEPLOY_UNIFI_CLOUDKEY_CERTDIR, +# or DEPLOY_UNIFI_CORE_CONFIG must exist to receive the deployed certs. ######## Public functions ##################### @@ -24,77 +55,160 @@ unifi_deploy() { _debug _cca "$_cca" _debug _cfullchain "$_cfullchain" - if ! _exists keytool; then - _err "keytool not found" - return 1 - fi + _getdeployconf DEPLOY_UNIFI_KEYSTORE + _getdeployconf DEPLOY_UNIFI_KEYPASS + _getdeployconf DEPLOY_UNIFI_CLOUDKEY_CERTDIR + _getdeployconf DEPLOY_UNIFI_CORE_CONFIG + _getdeployconf DEPLOY_UNIFI_RELOAD + + _debug2 DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" + _debug2 DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" + _debug2 DEPLOY_UNIFI_CLOUDKEY_CERTDIR "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" + _debug2 DEPLOY_UNIFI_CORE_CONFIG "$DEPLOY_UNIFI_CORE_CONFIG" + _debug2 DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" + + # Space-separated list of environments detected and installed: + _services_updated="" + + # Default reload commands accumulated as we auto-detect environments: + _reload_cmd="" + + # Unifi Controller environment (self hosted or any Cloud Key) -- + # auto-detect by file /usr/lib/unifi/data/keystore: + _unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-/usr/lib/unifi/data/keystore}" + if [ -f "$_unifi_keystore" ]; then + _info "Installing certificate for Unifi Controller (Java keystore)" + _debug _unifi_keystore "$_unifi_keystore" + if ! _exists keytool; then + _err "keytool not found" + return 1 + fi + if [ ! -w "$_unifi_keystore" ]; then + _err "The file $_unifi_keystore is not writable, please change the permission." + return 1 + fi + + _unifi_keypass="${DEPLOY_UNIFI_KEYPASS:-aircontrolenterprise}" - DEFAULT_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore" - _unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-$DEFAULT_UNIFI_KEYSTORE}" - DEFAULT_UNIFI_KEYPASS="aircontrolenterprise" - _unifi_keypass="${DEPLOY_UNIFI_KEYPASS:-$DEFAULT_UNIFI_KEYPASS}" - DEFAULT_UNIFI_RELOAD="service unifi restart" - _reload="${DEPLOY_UNIFI_RELOAD:-$DEFAULT_UNIFI_RELOAD}" - - _debug _unifi_keystore "$_unifi_keystore" - if [ ! -f "$_unifi_keystore" ]; then - if [ -z "$DEPLOY_UNIFI_KEYSTORE" ]; then - _err "unifi keystore is not found, please define DEPLOY_UNIFI_KEYSTORE" + _debug "Generate import pkcs12" + _import_pkcs12="$(_mktemp)" + _toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root + # shellcheck disable=SC2181 + if [ "$?" != "0" ]; then + _err "Error generating pkcs12. Please re-run with --debug and report a bug." return 1 + fi + + _debug "Import into keystore: $_unifi_keystore" + if keytool -importkeystore \ + -deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \ + -srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \ + -alias unifi -noprompt; then + _debug "Import keystore success!" + rm "$_import_pkcs12" else - _err "It seems that the specified unifi keystore is not valid, please check." + _err "Error importing into Unifi Java keystore." + _err "Please re-run with --debug and report a bug." + rm "$_import_pkcs12" return 1 fi + + if systemctl -q is-active unifi; then + _reload_cmd="${_reload_cmd:+$_reload_cmd && }service unifi restart" + fi + _services_updated="${_services_updated} unifi" + _info "Install Unifi Controller certificate success!" + elif [ "$DEPLOY_UNIFI_KEYSTORE" ]; then + _err "The specified DEPLOY_UNIFI_KEYSTORE='$DEPLOY_UNIFI_KEYSTORE' is not valid, please check." + return 1 fi - if [ ! -w "$_unifi_keystore" ]; then - _err "The file $_unifi_keystore is not writable, please change the permission." + + # Cloud Key environment (non-UnifiOS -- nginx serves admin pages) -- + # auto-detect by file /etc/ssl/private/cloudkey.key: + _cloudkey_certdir="${DEPLOY_UNIFI_CLOUDKEY_CERTDIR:-/etc/ssl/private}" + if [ -f "${_cloudkey_certdir}/cloudkey.key" ]; then + _info "Installing certificate for Cloud Key Gen1 (nginx admin pages)" + _debug _cloudkey_certdir "$_cloudkey_certdir" + if [ ! -w "$_cloudkey_certdir" ]; then + _err "The directory $_cloudkey_certdir is not writable; please check permissions." + return 1 + fi + # Cloud Key expects to load the keystore from /etc/ssl/private/unifi.keystore.jks. + # Normally /usr/lib/unifi/data/keystore is a symlink there (so the keystore was + # updated above), but if not, we don't know how to handle this installation: + if ! cmp -s "$_unifi_keystore" "${_cloudkey_certdir}/unifi.keystore.jks"; then + _err "Unsupported Cloud Key configuration: keystore not found at '${_cloudkey_certdir}/unifi.keystore.jks'" + return 1 + fi + + cat "$_cfullchain" >"${_cloudkey_certdir}/cloudkey.crt" + cat "$_ckey" >"${_cloudkey_certdir}/cloudkey.key" + (cd "$_cloudkey_certdir" && tar -cf cert.tar cloudkey.crt cloudkey.key unifi.keystore.jks) + + if systemctl -q is-active nginx; then + _reload_cmd="${_reload_cmd:+$_reload_cmd && }service nginx restart" + fi + _info "Install Cloud Key Gen1 certificate success!" + _services_updated="${_services_updated} nginx" + elif [ "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" ]; then + _err "The specified DEPLOY_UNIFI_CLOUDKEY_CERTDIR='$DEPLOY_UNIFI_CLOUDKEY_CERTDIR' is not valid, please check." return 1 fi - _info "Generate import pkcs12" - _import_pkcs12="$(_mktemp)" - _toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root - if [ "$?" != "0" ]; then - _err "Oops, error creating import pkcs12, please report bug to us." + # UnifiOS environment -- auto-detect by /data/unifi-core/config/unifi-core.key: + _unifi_core_config="${DEPLOY_UNIFI_CORE_CONFIG:-/data/unifi-core/config}" + if [ -f "${_unifi_core_config}/unifi-core.key" ]; then + _info "Installing certificate for UnifiOS" + _debug _unifi_core_config "$_unifi_core_config" + if [ ! -w "$_unifi_core_config" ]; then + _err "The directory $_unifi_core_config is not writable; please check permissions." + return 1 + fi + + cat "$_cfullchain" >"${_unifi_core_config}/unifi-core.crt" + cat "$_ckey" >"${_unifi_core_config}/unifi-core.key" + + if systemctl -q is-active unifi-core; then + _reload_cmd="${_reload_cmd:+$_reload_cmd && }systemctl restart unifi-core" + fi + _info "Install UnifiOS certificate success!" + _services_updated="${_services_updated} unifi-core" + elif [ "$DEPLOY_UNIFI_CORE_CONFIG" ]; then + _err "The specified DEPLOY_UNIFI_CORE_CONFIG='$DEPLOY_UNIFI_CORE_CONFIG' is not valid, please check." return 1 fi - _info "Modify unifi keystore: $_unifi_keystore" - if keytool -importkeystore \ - -deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \ - -srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \ - -alias unifi -noprompt; then - _info "Import keystore success!" - rm "$_import_pkcs12" - else - _err "Import unifi keystore error, please report bug to us." - rm "$_import_pkcs12" + if [ -z "$_services_updated" ]; then + # None of the Unifi environments were auto-detected, so no deployment has occurred + # (and none of DEPLOY_UNIFI_{KEYSTORE,CLOUDKEY_CERTDIR,CORE_CONFIG} were set). + _err "Unable to detect Unifi environment in standard location." + _err "(This deploy hook must be run on the Unifi device, not a remote machine.)" + _err "For non-standard Unifi installations, set DEPLOY_UNIFI_KEYSTORE," + _err "DEPLOY_UNIFI_CLOUDKEY_CERTDIR, and/or DEPLOY_UNIFI_CORE_CONFIG as appropriate." return 1 fi - _info "Run reload: $_reload" - if eval "$_reload"; then + _reload_cmd="${DEPLOY_UNIFI_RELOAD:-$_reload_cmd}" + if [ -z "$_reload_cmd" ]; then + _err "Certificates were installed for services:${_services_updated}," + _err "but none appear to be active. Please set DEPLOY_UNIFI_RELOAD" + _err "to a command that will restart the necessary services." + return 1 + fi + _info "Reload services (this may take some time): $_reload_cmd" + if eval "$_reload_cmd"; then _info "Reload success!" - if [ "$DEPLOY_UNIFI_KEYSTORE" ]; then - _savedomainconf DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" - else - _cleardomainconf DEPLOY_UNIFI_KEYSTORE - fi - if [ "$DEPLOY_UNIFI_KEYPASS" ]; then - _savedomainconf DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" - else - _cleardomainconf DEPLOY_UNIFI_KEYPASS - fi - if [ "$DEPLOY_UNIFI_RELOAD" ]; then - _savedomainconf DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" - else - _cleardomainconf DEPLOY_UNIFI_RELOAD - fi - return 0 else _err "Reload error" return 1 fi - return 0 + # Successful, so save all (non-default) config: + _savedeployconf DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" + _savedeployconf DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" + _savedeployconf DEPLOY_UNIFI_CLOUDKEY_CERTDIR "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" + _savedeployconf DEPLOY_UNIFI_CORE_CONFIG "$DEPLOY_UNIFI_CORE_CONFIG" + _savedeployconf DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" + + return 0 } From 86639dbc026157aecf6652345b7461c5d18a4647 Mon Sep 17 00:00:00 2001 From: Easton Man Date: Mon, 15 Feb 2021 15:18:49 +0800 Subject: [PATCH 269/383] feat: add huaweicloud error handling --- dnsapi/dns_huaweicloud.sh | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_huaweicloud.sh b/dnsapi/dns_huaweicloud.sh index 74fec2a9..f7192725 100644 --- a/dnsapi/dns_huaweicloud.sh +++ b/dnsapi/dns_huaweicloud.sh @@ -5,7 +5,7 @@ # HUAWEICLOUD_ProjectID iam_api="https://iam.myhuaweicloud.com" -dns_api="https://dns.ap-southeast-1.myhuaweicloud.com" +dns_api="https://dns.ap-southeast-1.myhuaweicloud.com" # Should work ######## Public functions ##################### @@ -29,16 +29,27 @@ dns_huaweicloud_add() { return 1 fi + unset token # Clear token token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_ProjectID}")" - _debug2 "${token}" + if [ -z "${token}" ]; then # Check token + _err "dns_api(dns_huaweicloud): Error getting token." + return 1 + fi + _debug "Access token is: ${token}" + + unset zoneid zoneid="$(_get_zoneid "${token}" "${fulldomain}")" - _debug "${zoneid}" + if [ -z "${zoneid}" ]; then + _err "dns_api(dns_huaweicloud): Error getting zone id." + return 1 + fi + _debug "Zone ID is: ${zoneid}" _debug "Adding Record" _add_record "${token}" "${fulldomain}" "${txtvalue}" ret="$?" if [ "${ret}" != "0" ]; then - _err "dns_huaweicloud: Error adding record." + _err "dns_api(dns_huaweicloud): Error adding record." return 1 fi @@ -69,12 +80,21 @@ dns_huaweicloud_rm() { return 1 fi + unset token # Clear token token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_ProjectID}")" - _debug2 "${token}" + if [ -z "${token}" ]; then # Check token + _err "dns_api(dns_huaweicloud): Error getting token." + return 1 + fi + _debug "Access token is: ${token}" + + unset zoneid zoneid="$(_get_zoneid "${token}" "${fulldomain}")" - _debug "${zoneid}" - record_id="$(_get_recordset_id "${token}" "${fulldomain}" "${zoneid}")" - _debug "Record Set ID is: ${record_id}" + if [ -z "${zoneid}" ]; then + _err "dns_api(dns_huaweicloud): Error getting zone id." + return 1 + fi + _debug "Zone ID is: ${zoneid}" # Remove all records # Therotically HuaweiCloud does not allow more than one record set From 31f65b89bb5cfd3604ff2fd386e515e325560a0d Mon Sep 17 00:00:00 2001 From: Easton Man Date: Mon, 15 Feb 2021 15:19:18 +0800 Subject: [PATCH 270/383] fix: fix freebsd and solaris --- .github/workflows/DNS.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 5dc2d453..ed0426ad 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -184,7 +184,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.0.7 + - uses: vmactions/freebsd-vm@v0.1.2 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkg install -y socat curl @@ -223,7 +223,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/solaris-vm@v0.0.1 + - uses: vmactions/solaris-vm@v0.0.3 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkgutil -y -i socat curl From 4528957235ce99809841f078d997558bf4f339da Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 15 Feb 2021 21:25:27 +0800 Subject: [PATCH 271/383] support openssl 3.0 fix https://github.com/acmesh-official/acme.sh/issues/3399 --- acme.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index a9301e10..2cb9dd00 100755 --- a/acme.sh +++ b/acme.sh @@ -1122,9 +1122,14 @@ _createkey() { fi fi + __traditional="" + if _contains "$(${ACME_OPENSSL_BIN:-openssl} help genrsa 2>&1)" "-traditional"; then + __traditional="-traditional" + fi + if _isEccKey "$length"; then _debug "Using ec name: $eccname" - if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -genkey 2>/dev/null)"; then + if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam $__traditional -name "$eccname" -genkey 2>/dev/null)"; then echo "$_opkey" >"$f" else _err "error ecc key name: $eccname" @@ -1132,7 +1137,7 @@ _createkey() { fi else _debug "Using RSA: $length" - if _opkey="$(${ACME_OPENSSL_BIN:-openssl} genrsa "$length" 2>/dev/null)"; then + if _opkey="$(${ACME_OPENSSL_BIN:-openssl} genrsa $__traditional "$length" 2>/dev/null)"; then echo "$_opkey" >"$f" else _err "error rsa key: $length" From 906ef43c00129d07540cb712f035b844ced69cfc Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 15 Feb 2021 21:35:59 +0800 Subject: [PATCH 272/383] make the fix for rsa key only --- acme.sh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/acme.sh b/acme.sh index 2cb9dd00..5e9829a4 100755 --- a/acme.sh +++ b/acme.sh @@ -1122,14 +1122,9 @@ _createkey() { fi fi - __traditional="" - if _contains "$(${ACME_OPENSSL_BIN:-openssl} help genrsa 2>&1)" "-traditional"; then - __traditional="-traditional" - fi - if _isEccKey "$length"; then _debug "Using ec name: $eccname" - if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam $__traditional -name "$eccname" -genkey 2>/dev/null)"; then + if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -genkey 2>/dev/null)"; then echo "$_opkey" >"$f" else _err "error ecc key name: $eccname" @@ -1137,6 +1132,10 @@ _createkey() { fi else _debug "Using RSA: $length" + __traditional="" + if _contains "$(${ACME_OPENSSL_BIN:-openssl} help genrsa 2>&1)" "-traditional"; then + __traditional="-traditional" + fi if _opkey="$(${ACME_OPENSSL_BIN:-openssl} genrsa $__traditional "$length" 2>/dev/null)"; then echo "$_opkey" >"$f" else From 6ff75f9a9fe906ed1c1b9cbf637b0e749ba9e127 Mon Sep 17 00:00:00 2001 From: medmunds Date: Mon, 15 Feb 2021 12:23:48 -0800 Subject: [PATCH 273/383] Use PROJECT_NAME and VER for X-Mailer header Also add X-Mailer header to Python version --- notify/smtp.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index c9927e3e..bb71a563 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -112,6 +112,7 @@ smtp_send() { _SMTP_USERNAME="$SMTP_USERNAME" _SMTP_PASSWORD="$SMTP_PASSWORD" _SMTP_TIMEOUT="${SMTP_TIMEOUT:-30}" + _SMTP_X_MAILER="${PROJECT_NAME} ${VER} --notify-hook smtp" # Run with --debug 2 (or above) to echo the transcript of the SMTP session. # Careful: this may include SMTP_PASSWORD in plaintext! @@ -232,7 +233,7 @@ _smtp_raw_message() { echo "Date: $(date +'%a, %-d %b %Y %H:%M:%S %z')" fi echo "Content-Type: text/plain; charset=utf-8" - echo "X-Mailer: acme.sh --notify-hook smtp" + echo "X-Mailer: $_SMTP_X_MAILER" echo echo "$_SMTP_CONTENT" } @@ -286,6 +287,7 @@ smtp_secure = """$_SMTP_SECURE""" username = """$_SMTP_USERNAME""" password = """$_SMTP_PASSWORD""" timeout=int("""$_SMTP_TIMEOUT""") # seconds +x_mailer="""$_SMTP_X_MAILER""" from_email="""$_SMTP_FROM""" to_emails="""$_SMTP_TO""" # can be comma-separated @@ -301,6 +303,7 @@ except (AttributeError, TypeError): msg["Subject"] = subject msg["From"] = from_email msg["To"] = to_emails +msg["X-Mailer"] = x_mailer smtp = None try: From 585c0c381852ebc796018a79d02fdac3f5666773 Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 16 Feb 2021 09:33:39 -0800 Subject: [PATCH 274/383] Add _clearaccountconf_mutable() --- acme.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/acme.sh b/acme.sh index a9301e10..bb4134de 100755 --- a/acme.sh +++ b/acme.sh @@ -2279,6 +2279,13 @@ _clearaccountconf() { _clear_conf "$ACCOUNT_CONF_PATH" "$1" } +#key +_clearaccountconf_mutable() { + _clearaccountconf "SAVED_$1" + #remove later + _clearaccountconf "$1" +} + #_savecaconf key value _savecaconf() { _save_conf "$CA_CONF" "$1" "$2" From 6e77756d6a0b3d71f0ecc014d6336a8e6b025db1 Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 16 Feb 2021 12:49:27 -0800 Subject: [PATCH 275/383] Rework read/save config to not save default values Add and use _readaccountconf_mutable_default and _saveaccountconf_mutable_default helpers to capture common default value handling. New approach also eliminates need for separate underscore-prefixed version of each conf var. --- notify/smtp.sh | 255 +++++++++++++++++++++++++++++-------------------- 1 file changed, 149 insertions(+), 106 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index bb71a563..85801604 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -17,155 +17,150 @@ # SMTP_TIMEOUT="30" # seconds for SMTP operations to timeout # SMTP_BIN="/path/to/curl_or_python" # default finds first of curl, python3, or python on PATH +SMTP_SECURE_DEFAULT="none" +SMTP_TIMEOUT_DEFAULT="30" + # subject content statuscode smtp_send() { - _SMTP_SUBJECT="$1" - _SMTP_CONTENT="$2" + SMTP_SUBJECT="$1" + SMTP_CONTENT="$2" # UNUSED: _statusCode="$3" # 0: success, 1: error 2($RENEW_SKIP): skipped - # Load config: - SMTP_FROM="${SMTP_FROM:-$(_readaccountconf_mutable SMTP_FROM)}" - SMTP_TO="${SMTP_TO:-$(_readaccountconf_mutable SMTP_TO)}" - SMTP_HOST="${SMTP_HOST:-$(_readaccountconf_mutable SMTP_HOST)}" - SMTP_PORT="${SMTP_PORT:-$(_readaccountconf_mutable SMTP_PORT)}" - SMTP_SECURE="${SMTP_SECURE:-$(_readaccountconf_mutable SMTP_SECURE)}" - SMTP_USERNAME="${SMTP_USERNAME:-$(_readaccountconf_mutable SMTP_USERNAME)}" - SMTP_PASSWORD="${SMTP_PASSWORD:-$(_readaccountconf_mutable SMTP_PASSWORD)}" - SMTP_TIMEOUT="${SMTP_TIMEOUT:-$(_readaccountconf_mutable SMTP_TIMEOUT)}" - SMTP_BIN="${SMTP_BIN:-$(_readaccountconf_mutable SMTP_BIN)}" - - _debug "SMTP_FROM" "$SMTP_FROM" - _debug "SMTP_TO" "$SMTP_TO" - _debug "SMTP_HOST" "$SMTP_HOST" - _debug "SMTP_PORT" "$SMTP_PORT" - _debug "SMTP_SECURE" "$SMTP_SECURE" - _debug "SMTP_USERNAME" "$SMTP_USERNAME" - _secure_debug "SMTP_PASSWORD" "$SMTP_PASSWORD" - _debug "SMTP_TIMEOUT" "$SMTP_TIMEOUT" - _debug "SMTP_BIN" "$SMTP_BIN" - - _debug "_SMTP_SUBJECT" "$_SMTP_SUBJECT" - _debug "_SMTP_CONTENT" "$_SMTP_CONTENT" - - # Validate config and apply defaults: - # _SMTP_* variables are the resolved (with defaults) versions of SMTP_*. - # (The _SMTP_* versions will not be stored in account conf.) - + # Load and validate config: + SMTP_BIN="$(_readaccountconf_mutable_default SMTP_BIN)" if [ -n "$SMTP_BIN" ] && ! _exists "$SMTP_BIN"; then _err "SMTP_BIN '$SMTP_BIN' does not exist." return 1 fi - _SMTP_BIN="$SMTP_BIN" - if [ -z "$_SMTP_BIN" ]; then + if [ -z "$SMTP_BIN" ]; then # Look for a command that can communicate with an SMTP server. # (Please don't add sendmail, ssmtp, mutt, mail, or msmtp here. # Those are already handled by the "mail" notify hook.) for cmd in curl python3 python2.7 python pypy3 pypy; do if _exists "$cmd"; then - _SMTP_BIN="$cmd" + SMTP_BIN="$cmd" break fi done - if [ -z "$_SMTP_BIN" ]; then + if [ -z "$SMTP_BIN" ]; then _err "The smtp notify-hook requires curl or Python, but can't find any." _err 'If you have one of them, define SMTP_BIN="/path/to/curl_or_python".' _err 'Otherwise, see if you can use the "mail" notify-hook instead.' return 1 fi - _debug "_SMTP_BIN" "$_SMTP_BIN" fi + _debug SMTP_BIN "$SMTP_BIN" + _saveaccountconf_mutable_default SMTP_BIN "$SMTP_BIN" + SMTP_FROM="$(_readaccountconf_mutable_default SMTP_FROM)" if [ -z "$SMTP_FROM" ]; then _err "You must define SMTP_FROM as the sender email address." return 1 fi - _SMTP_FROM="$SMTP_FROM" + _debug SMTP_FROM "$SMTP_FROM" + _saveaccountconf_mutable_default SMTP_FROM "$SMTP_FROM" + SMTP_TO="$(_readaccountconf_mutable_default SMTP_TO)" if [ -z "$SMTP_TO" ]; then _err "You must define SMTP_TO as the recipient email address." return 1 fi - _SMTP_TO="$SMTP_TO" + _debug SMTP_TO "$SMTP_TO" + _saveaccountconf_mutable_default SMTP_TO "$SMTP_TO" + SMTP_HOST="$(_readaccountconf_mutable_default SMTP_HOST)" if [ -z "$SMTP_HOST" ]; then _err "You must define SMTP_HOST as the SMTP server hostname." return 1 fi - _SMTP_HOST="$SMTP_HOST" - - _SMTP_SECURE="${SMTP_SECURE:-none}" - case "$_SMTP_SECURE" in - "none") smtp_default_port="25" ;; - "ssl") smtp_default_port="465" ;; - "tls") smtp_default_port="587" ;; + _debug SMTP_HOST "$SMTP_HOST" + _saveaccountconf_mutable_default SMTP_HOST "$SMTP_HOST" + + SMTP_SECURE="$(_readaccountconf_mutable_default SMTP_SECURE "$SMTP_SECURE_DEFAULT")" + case "$SMTP_SECURE" in + "none") smtp_port_default="25" ;; + "ssl") smtp_port_default="465" ;; + "tls") smtp_port_default="587" ;; *) _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." return 1 ;; esac + _debug SMTP_SECURE "$SMTP_SECURE" + _saveaccountconf_mutable_default SMTP_SECURE "$SMTP_SECURE" "$SMTP_SECURE_DEFAULT" - _SMTP_PORT="${SMTP_PORT:-$smtp_default_port}" - if [ -z "$SMTP_PORT" ]; then - _debug "_SMTP_PORT" "$_SMTP_PORT" - fi + SMTP_PORT="$(_readaccountconf_mutable_default SMTP_PORT "$smtp_port_default")" + case "$SMTP_PORT" in + *[!0-9]*) + _err "Invalid SMTP_PORT='$SMTP_PORT'. It must be a port number." + return 1 + ;; + esac + _debug SMTP_PORT "$SMTP_PORT" + _saveaccountconf_mutable_default SMTP_PORT "$SMTP_PORT" "$smtp_port_default" + + SMTP_USERNAME="$(_readaccountconf_mutable_default SMTP_USERNAME)" + _debug SMTP_USERNAME "$SMTP_USERNAME" + _saveaccountconf_mutable_default SMTP_USERNAME "$SMTP_USERNAME" + + SMTP_PASSWORD="$(_readaccountconf_mutable_default SMTP_PASSWORD)" + _secure_debug SMTP_PASSWORD "$SMTP_PASSWORD" + _saveaccountconf_mutable_default SMTP_PASSWORD "$SMTP_PASSWORD" - _SMTP_USERNAME="$SMTP_USERNAME" - _SMTP_PASSWORD="$SMTP_PASSWORD" - _SMTP_TIMEOUT="${SMTP_TIMEOUT:-30}" - _SMTP_X_MAILER="${PROJECT_NAME} ${VER} --notify-hook smtp" + SMTP_TIMEOUT="$(_readaccountconf_mutable_default SMTP_TIMEOUT "$SMTP_TIMEOUT_DEFAULT")" + _debug SMTP_TIMEOUT "$SMTP_TIMEOUT" + _saveaccountconf_mutable_default SMTP_TIMEOUT "$SMTP_TIMEOUT" "$SMTP_TIMEOUT_DEFAULT" + + SMTP_X_MAILER="${PROJECT_NAME} ${VER} --notify-hook smtp" # Run with --debug 2 (or above) to echo the transcript of the SMTP session. # Careful: this may include SMTP_PASSWORD in plaintext! if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then - _SMTP_SHOW_TRANSCRIPT="True" + SMTP_SHOW_TRANSCRIPT="True" else - _SMTP_SHOW_TRANSCRIPT="" + SMTP_SHOW_TRANSCRIPT="" fi + _debug SMTP_SUBJECT "$SMTP_SUBJECT" + _debug SMTP_CONTENT "$SMTP_CONTENT" + # Send the message: - case "$(basename "$_SMTP_BIN")" in + case "$(basename "$SMTP_BIN")" in curl) _smtp_send=_smtp_send_curl ;; py*) _smtp_send=_smtp_send_python ;; *) - _err "Can't figure out how to invoke $_SMTP_BIN." + _err "Can't figure out how to invoke '$SMTP_BIN'." _err "Check your SMTP_BIN setting." return 1 ;; esac if ! smtp_output="$($_smtp_send)"; then - _err "Error sending message with $_SMTP_BIN." + _err "Error sending message with $SMTP_BIN." if [ -n "$smtp_output" ]; then _err "$smtp_output" fi return 1 fi - # Save config only if send was successful: - _saveaccountconf_mutable SMTP_BIN "$SMTP_BIN" - _saveaccountconf_mutable SMTP_FROM "$SMTP_FROM" - _saveaccountconf_mutable SMTP_TO "$SMTP_TO" - _saveaccountconf_mutable SMTP_HOST "$SMTP_HOST" - _saveaccountconf_mutable SMTP_PORT "$SMTP_PORT" - _saveaccountconf_mutable SMTP_SECURE "$SMTP_SECURE" - _saveaccountconf_mutable SMTP_USERNAME "$SMTP_USERNAME" - _saveaccountconf_mutable SMTP_PASSWORD "$SMTP_PASSWORD" - _saveaccountconf_mutable SMTP_TIMEOUT "$SMTP_TIMEOUT" - return 0 } -# Send the message via curl using _SMTP_* variables +## +## curl smtp sending +## + +# Send the message via curl using SMTP_* variables _smtp_send_curl() { # curl passes --mail-from and --mail-rcpt directly to the SMTP protocol without # additional parsing, and SMTP requires addr-spec only (no display names). # In the future, maybe try to parse the addr-spec out for curl args (non-trivial). - if _email_has_display_name "$_SMTP_FROM"; then + if _email_has_display_name "$SMTP_FROM"; then _err "curl smtp only allows a simple email address in SMTP_FROM." _err "Change your SMTP_FROM='$SMTP_FROM' to remove the display name." return 1 fi - if _email_has_display_name "$_SMTP_TO"; then + if _email_has_display_name "$SMTP_TO"; then _err "curl smtp only allows simple email addresses in SMTP_TO." _err "Change your SMTP_TO='$SMTP_TO' to remove the display name(s)." return 1 @@ -173,20 +168,20 @@ _smtp_send_curl() { # Build curl args in $@ - case "$_SMTP_SECURE" in + case "$SMTP_SECURE" in none) - set -- --url "smtp://${_SMTP_HOST}:${_SMTP_PORT}" + set -- --url "smtp://${SMTP_HOST}:${SMTP_PORT}" ;; ssl) - set -- --url "smtps://${_SMTP_HOST}:${_SMTP_PORT}" + set -- --url "smtps://${SMTP_HOST}:${SMTP_PORT}" ;; tls) - set -- --url "smtp://${_SMTP_HOST}:${_SMTP_PORT}" --ssl-reqd + set -- --url "smtp://${SMTP_HOST}:${SMTP_PORT}" --ssl-reqd ;; *) # This will only occur if someone adds a new SMTP_SECURE option above # without updating this code for it. - _err "Unhandled _SMTP_SECURE='$_SMTP_SECURE' in _smtp_send_curl" + _err "Unhandled SMTP_SECURE='$SMTP_SECURE' in _smtp_send_curl" _err "Please re-run with --debug and report a bug." return 1 ;; @@ -194,23 +189,23 @@ _smtp_send_curl() { set -- "$@" \ --upload-file - \ - --mail-from "$_SMTP_FROM" \ - --max-time "$_SMTP_TIMEOUT" + --mail-from "$SMTP_FROM" \ + --max-time "$SMTP_TIMEOUT" - # Burst comma-separated $_SMTP_TO into individual --mail-rcpt args. - _to="${_SMTP_TO}," + # Burst comma-separated $SMTP_TO into individual --mail-rcpt args. + _to="${SMTP_TO}," while [ -n "$_to" ]; do _rcpt="${_to%%,*}" _to="${_to#*,}" set -- "$@" --mail-rcpt "$_rcpt" done - _smtp_login="${_SMTP_USERNAME}:${_SMTP_PASSWORD}" + _smtp_login="${SMTP_USERNAME}:${SMTP_PASSWORD}" if [ "$_smtp_login" != ":" ]; then set -- "$@" --user "$_smtp_login" fi - if [ "$_SMTP_SHOW_TRANSCRIPT" = "True" ]; then + if [ "$SMTP_SHOW_TRANSCRIPT" = "True" ]; then set -- "$@" --verbose else set -- "$@" --silent --show-error @@ -218,24 +213,24 @@ _smtp_send_curl() { raw_message="$(_smtp_raw_message)" - _debug2 "curl command:" "$_SMTP_BIN" "$*" + _debug2 "curl command:" "$SMTP_BIN" "$*" _debug2 "raw_message:\n$raw_message" - echo "$raw_message" | "$_SMTP_BIN" "$@" + echo "$raw_message" | "$SMTP_BIN" "$@" } -# Output an RFC-822 / RFC-5322 email message using _SMTP_* variables +# Output an RFC-822 / RFC-5322 email message using SMTP_* variables _smtp_raw_message() { - echo "From: $_SMTP_FROM" - echo "To: $_SMTP_TO" - echo "Subject: $(_mime_encoded_word "$_SMTP_SUBJECT")" + echo "From: $SMTP_FROM" + echo "To: $SMTP_TO" + echo "Subject: $(_mime_encoded_word "$SMTP_SUBJECT")" if _exists date; then echo "Date: $(date +'%a, %-d %b %Y %H:%M:%S %z')" fi echo "Content-Type: text/plain; charset=utf-8" - echo "X-Mailer: $_SMTP_X_MAILER" + echo "X-Mailer: $SMTP_X_MAILER" echo - echo "$_SMTP_CONTENT" + echo "$SMTP_CONTENT" } # Convert text to RFC-2047 MIME "encoded word" format if it contains non-ASCII chars @@ -260,12 +255,16 @@ _email_has_display_name() { expr "$_email" : '^.*[<>"]' >/dev/null } -# Send the message via Python using _SMTP_* variables +## +## Python smtp sending +## + +# Send the message via Python using SMTP_* variables _smtp_send_python() { - _debug "Python version" "$("$_SMTP_BIN" --version 2>&1)" + _debug "Python version" "$("$SMTP_BIN" --version 2>&1)" # language=Python - "$_SMTP_BIN" < Date: Tue, 16 Feb 2021 13:13:26 -0800 Subject: [PATCH 276/383] Implement _rfc2822_date helper --- notify/smtp.sh | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 85801604..43536cd2 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -224,9 +224,7 @@ _smtp_raw_message() { echo "From: $SMTP_FROM" echo "To: $SMTP_TO" echo "Subject: $(_mime_encoded_word "$SMTP_SUBJECT")" - if _exists date; then - echo "Date: $(date +'%a, %-d %b %Y %H:%M:%S %z')" - fi + echo "Date: $(_rfc2822_date)" echo "Content-Type: text/plain; charset=utf-8" echo "X-Mailer: $SMTP_X_MAILER" echo @@ -248,6 +246,19 @@ _mime_encoded_word() { fi } +# Output current date in RFC-2822 Section 3.3 format as required in email headers +# (e.g., "Mon, 15 Feb 2021 14:22:01 -0800") +_rfc2822_date() { + # Notes: + # - this is deliberately not UTC, because it "SHOULD express local time" per spec + # - the spec requires weekday and month in the C locale (English), not localized + # - this date format specifier has been tested on Linux, Mac, Solaris and FreeBSD + _old_lc_time="$LC_TIME" + LC_TIME=C + date +'%a, %-d %b %Y %H:%M:%S %z' + LC_TIME="$_old_lc_time" +} + # Simple check for display name in an email address (< > or ") # email _email_has_display_name() { From 4b615cb3a92fad0d65e8868408debbd82ca0f32e Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 16 Feb 2021 14:02:09 -0800 Subject: [PATCH 277/383] Clean email headers and warn on unsupported address format Just in case, make sure CR or NL don't end up in an email header. --- notify/smtp.sh | 55 +++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 43536cd2..42c1487c 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -53,16 +53,28 @@ smtp_send() { _saveaccountconf_mutable_default SMTP_BIN "$SMTP_BIN" SMTP_FROM="$(_readaccountconf_mutable_default SMTP_FROM)" + SMTP_FROM="$(_clean_email_header "$SMTP_FROM")" if [ -z "$SMTP_FROM" ]; then _err "You must define SMTP_FROM as the sender email address." return 1 fi + if _email_has_display_name "$SMTP_FROM"; then + _err "SMTP_FROM must be only a simple email address (sender@example.com)." + _err "Change your SMTP_FROM='$SMTP_FROM' to remove the display name." + return 1 + fi _debug SMTP_FROM "$SMTP_FROM" _saveaccountconf_mutable_default SMTP_FROM "$SMTP_FROM" SMTP_TO="$(_readaccountconf_mutable_default SMTP_TO)" + SMTP_TO="$(_clean_email_header "$SMTP_TO")" if [ -z "$SMTP_TO" ]; then - _err "You must define SMTP_TO as the recipient email address." + _err "You must define SMTP_TO as the recipient email address(es)." + return 1 + fi + if _email_has_display_name "$SMTP_TO"; then + _err "SMTP_TO must be only simple email addresses (to@example.com,to2@example.com)." + _err "Change your SMTP_TO='$SMTP_TO' to remove the display name(s)." return 1 fi _debug SMTP_TO "$SMTP_TO" @@ -111,7 +123,7 @@ smtp_send() { _debug SMTP_TIMEOUT "$SMTP_TIMEOUT" _saveaccountconf_mutable_default SMTP_TIMEOUT "$SMTP_TIMEOUT" "$SMTP_TIMEOUT_DEFAULT" - SMTP_X_MAILER="${PROJECT_NAME} ${VER} --notify-hook smtp" + SMTP_X_MAILER="$(_clean_email_header "$PROJECT_NAME $VER --notify-hook smtp")" # Run with --debug 2 (or above) to echo the transcript of the SMTP session. # Careful: this may include SMTP_PASSWORD in plaintext! @@ -121,6 +133,7 @@ smtp_send() { SMTP_SHOW_TRANSCRIPT="" fi + SMTP_SUBJECT=$(_clean_email_header "$SMTP_SUBJECT") _debug SMTP_SUBJECT "$SMTP_SUBJECT" _debug SMTP_CONTENT "$SMTP_CONTENT" @@ -146,28 +159,26 @@ smtp_send() { return 0 } +# Strip CR and NL from text to prevent MIME header injection +# text +_clean_email_header() { + printf "%s" "$(echo "$1" | tr -d "\r\n")" +} + +# Simple check for display name in an email address (< > or ") +# email +_email_has_display_name() { + _email="$1" + expr "$_email" : '^.*[<>"]' >/dev/null +} + ## ## curl smtp sending ## # Send the message via curl using SMTP_* variables _smtp_send_curl() { - # curl passes --mail-from and --mail-rcpt directly to the SMTP protocol without - # additional parsing, and SMTP requires addr-spec only (no display names). - # In the future, maybe try to parse the addr-spec out for curl args (non-trivial). - if _email_has_display_name "$SMTP_FROM"; then - _err "curl smtp only allows a simple email address in SMTP_FROM." - _err "Change your SMTP_FROM='$SMTP_FROM' to remove the display name." - return 1 - fi - if _email_has_display_name "$SMTP_TO"; then - _err "curl smtp only allows simple email addresses in SMTP_TO." - _err "Change your SMTP_TO='$SMTP_TO' to remove the display name(s)." - return 1 - fi - # Build curl args in $@ - case "$SMTP_SECURE" in none) set -- --url "smtp://${SMTP_HOST}:${SMTP_PORT}" @@ -219,7 +230,8 @@ _smtp_send_curl() { echo "$raw_message" | "$SMTP_BIN" "$@" } -# Output an RFC-822 / RFC-5322 email message using SMTP_* variables +# Output an RFC-822 / RFC-5322 email message using SMTP_* variables. +# (This assumes variables have already been cleaned for use in email headers.) _smtp_raw_message() { echo "From: $SMTP_FROM" echo "To: $SMTP_TO" @@ -259,13 +271,6 @@ _rfc2822_date() { LC_TIME="$_old_lc_time" } -# Simple check for display name in an email address (< > or ") -# email -_email_has_display_name() { - _email="$1" - expr "$_email" : '^.*[<>"]' >/dev/null -} - ## ## Python smtp sending ## From 5a182eddbf4ffafcc1b8a1b3757a49378f46af5f Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 16 Feb 2021 14:41:21 -0800 Subject: [PATCH 278/383] Clarify _readaccountconf_mutable_default --- notify/smtp.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 42c1487c..fabde79b 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -358,7 +358,7 @@ PYTHON # - if MY_CONF is set _empty_, output $default_value # (lets user `export MY_CONF=` to clear previous saved value # and return to default, without user having to know default) -# - otherwise if _readaccountconf_mutable $name is non-empty, return that +# - otherwise if _readaccountconf_mutable MY_CONF is non-empty, return that # (value of SAVED_MY_CONF from account.conf) # - otherwise output $default_value _readaccountconf_mutable_default() { @@ -366,8 +366,9 @@ _readaccountconf_mutable_default() { _default_value="$2" eval "_value=\"\$$_name\"" - eval "_explicit_empty_value=\"\${${_name}+empty}\"" - if [ -z "${_value}" ] && [ "${_explicit_empty_value:-}" != "empty" ]; then + eval "_name_is_set=\"\${${_name}+true}\"" + # ($_name_is_set is "true" if $$_name is set to anything, including empty) + if [ -z "${_value}" ] && [ "${_name_is_set:-}" != "true" ]; then _value="$(_readaccountconf_mutable "$_name")" fi if [ -z "${_value}" ]; then From 8f688e5e13b9cdc77134eb97dcc07435912dc4aa Mon Sep 17 00:00:00 2001 From: medmunds Date: Wed, 17 Feb 2021 09:46:13 -0800 Subject: [PATCH 279/383] Add Date email header in Python implementation --- notify/smtp.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/notify/smtp.sh b/notify/smtp.sh index fabde79b..0c698631 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -287,6 +287,7 @@ try: from email.message import EmailMessage except ImportError: from email.mime.text import MIMEText as EmailMessage # Python 2 + from email.utils import formatdate as rfc2822_date from smtplib import SMTP, SMTP_SSL, SMTPException from socket import error as SocketError except ImportError as err: @@ -318,6 +319,7 @@ except (AttributeError, TypeError): msg["Subject"] = subject msg["From"] = from_email msg["To"] = to_emails +msg["Date"] = rfc2822_date(localtime=True) msg["X-Mailer"] = x_mailer smtp = None From 28d9f00610b11254b43bf38d028524db859e588f Mon Sep 17 00:00:00 2001 From: medmunds Date: Wed, 17 Feb 2021 09:57:44 -0800 Subject: [PATCH 280/383] Use email.policy.default in Python 3 implementation Improves standards compatibility and utf-8 handling in Python 3.3-3.8. (email.policy.default becomes the default in Python 3.9.) --- notify/smtp.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 0c698631..69863206 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -285,8 +285,11 @@ _smtp_send_python() { try: try: from email.message import EmailMessage + from email.policy import default as email_policy_default except ImportError: - from email.mime.text import MIMEText as EmailMessage # Python 2 + # Python 2 (or < 3.3) + from email.mime.text import MIMEText as EmailMessage + email_policy_default = None from email.utils import formatdate as rfc2822_date from smtplib import SMTP, SMTP_SSL, SMTPException from socket import error as SocketError @@ -311,7 +314,7 @@ subject="""$SMTP_SUBJECT""" content="""$SMTP_CONTENT""" try: - msg = EmailMessage() + msg = EmailMessage(policy=email_policy_default) msg.set_content(content) except (AttributeError, TypeError): # Python 2 MIMEText From 6e49c4ffe006c45128c4ad8535e34e39b93901e2 Mon Sep 17 00:00:00 2001 From: medmunds Date: Wed, 17 Feb 2021 10:02:14 -0800 Subject: [PATCH 281/383] Prefer Python to curl when both available --- notify/smtp.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 69863206..71020818 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -15,7 +15,7 @@ # SMTP_USERNAME="" # set if SMTP server requires login # SMTP_PASSWORD="" # set if SMTP server requires login # SMTP_TIMEOUT="30" # seconds for SMTP operations to timeout -# SMTP_BIN="/path/to/curl_or_python" # default finds first of curl, python3, or python on PATH +# SMTP_BIN="/path/to/python_or_curl" # default finds first of python3, python2.7, python, pypy3, pypy, curl on PATH SMTP_SECURE_DEFAULT="none" SMTP_TIMEOUT_DEFAULT="30" @@ -36,7 +36,7 @@ smtp_send() { # Look for a command that can communicate with an SMTP server. # (Please don't add sendmail, ssmtp, mutt, mail, or msmtp here. # Those are already handled by the "mail" notify hook.) - for cmd in curl python3 python2.7 python pypy3 pypy; do + for cmd in python3 python2.7 python pypy3 pypy curl; do if _exists "$cmd"; then SMTP_BIN="$cmd" break From afe6f4030e9f7ec5c03146dd4dfe122d1ab7aab1 Mon Sep 17 00:00:00 2001 From: medmunds Date: Wed, 17 Feb 2021 11:39:16 -0800 Subject: [PATCH 282/383] Change default SMTP_SECURE to "tls" Secure by default. Also try to minimize configuration errors. (Many ESPs/ISPs require STARTTLS, and most support it.) --- notify/smtp.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 71020818..293c665e 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -11,13 +11,13 @@ # SMTP_TO="to@example.com" # required # SMTP_HOST="smtp.example.com" # required # SMTP_PORT="25" # defaults to 25, 465 or 587 depending on SMTP_SECURE -# SMTP_SECURE="none" # one of "none", "ssl" (implicit TLS, TLS Wrapper), "tls" (explicit TLS, STARTTLS) +# SMTP_SECURE="tls" # one of "none", "ssl" (implicit TLS, TLS Wrapper), "tls" (explicit TLS, STARTTLS) # SMTP_USERNAME="" # set if SMTP server requires login # SMTP_PASSWORD="" # set if SMTP server requires login # SMTP_TIMEOUT="30" # seconds for SMTP operations to timeout # SMTP_BIN="/path/to/python_or_curl" # default finds first of python3, python2.7, python, pypy3, pypy, curl on PATH -SMTP_SECURE_DEFAULT="none" +SMTP_SECURE_DEFAULT="tls" SMTP_TIMEOUT_DEFAULT="30" # subject content statuscode From 17f5e557ed07dfcc65d7ea808d2e27fbfc0acf7f Mon Sep 17 00:00:00 2001 From: czeming Date: Sat, 20 Feb 2021 17:16:33 +0800 Subject: [PATCH 283/383] Update dns_dp.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 没有encode中文字符会导致提交失败 --- dnsapi/dns_dp.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_dp.sh b/dnsapi/dns_dp.sh index 033fa5aa..9b8b7a8b 100755 --- a/dnsapi/dns_dp.sh +++ b/dnsapi/dns_dp.sh @@ -89,7 +89,7 @@ add_record() { _info "Adding record" - if ! _rest POST "Record.Create" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=默认"; then + if ! _rest POST "Record.Create" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=%E9%BB%98%E8%AE%A4"; then return 1 fi From a730a08161def8358a68a1662149e670e1af02f3 Mon Sep 17 00:00:00 2001 From: Geert Hendrickx Date: Tue, 23 Feb 2021 10:28:17 +0100 Subject: [PATCH 284/383] No need to include EC parameters explicitly with the private key. (they are embedded) --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 757ed7a5..3c66250e 100755 --- a/acme.sh +++ b/acme.sh @@ -1124,7 +1124,7 @@ _createkey() { if _isEccKey "$length"; then _debug "Using ec name: $eccname" - if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -genkey 2>/dev/null)"; then + if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -noout -genkey 2>/dev/null)"; then echo "$_opkey" >"$f" else _err "error ecc key name: $eccname" From c5100219d15137f65799b1fb315affd1a6831218 Mon Sep 17 00:00:00 2001 From: Kristian Johansson Date: Wed, 24 Feb 2021 08:53:35 +0100 Subject: [PATCH 285/383] Fixes response handling and thereby allow issuing of subdomain certs --- dnsapi/dns_simply.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index d053dcf6..b38d0ed3 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -6,7 +6,7 @@ #SIMPLY_ApiKey="apikey" # #SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]" - +SIMPLY_SUCCESS_CODE='"status": 200' SIMPLY_Api_Default="https://api.simply.com/1" ######## Public functions ##################### @@ -171,7 +171,7 @@ _get_root() { return 1 fi - if _contains "$response" '"code":"NOT_FOUND"'; then + if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then _debug "$h not found" else _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) @@ -196,6 +196,12 @@ _simply_add_record() { return 1 fi + if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then + _err "Call to API not sucessfull, see below message for more details" + _err "$response" + return 1 + fi + return 0 } @@ -211,6 +217,12 @@ _simply_delete_record() { return 1 fi + if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then + _err "Call to API not sucessfull, see below message for more details" + _err "$response" + return 1 + fi + return 0 } From 1917c4b04a17de47d5dc6e08946df6b5bf1b137f Mon Sep 17 00:00:00 2001 From: Kristian Johansson Date: Wed, 24 Feb 2021 17:34:28 +0100 Subject: [PATCH 286/383] Adds comment --- dnsapi/dns_simply.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index b38d0ed3..e0e05017 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -6,9 +6,11 @@ #SIMPLY_ApiKey="apikey" # #SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]" -SIMPLY_SUCCESS_CODE='"status": 200' SIMPLY_Api_Default="https://api.simply.com/1" +#This is used for determining success of REST call +SIMPLY_SUCCESS_CODE='"status": 200' + ######## Public functions ##################### #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_simply_add() { From 9a90fe37944ce23ecee6425a4b11f0594bb2165e Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 25 Feb 2021 07:45:22 +0800 Subject: [PATCH 287/383] fix https://github.com/acmesh-official/acme.sh/issues/3402 --- acme.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 3c66250e..24cda9c4 100755 --- a/acme.sh +++ b/acme.sh @@ -562,8 +562,16 @@ if _exists xargs && [ "$(printf %s '\\x41' | xargs printf)" = 'A' ]; then fi _h2b() { - if _exists xxd && xxd -r -p 2>/dev/null; then - return + if _exists xxd; then + if _contains "$(xxd --help 2>&1)" "assumes -c30"; then + if xxd -r -p -c 9999 2>/dev/null; then + return + fi + else + if xxd -r -p 2>/dev/null; then + return + fi + fi fi hex=$(cat) From 5eb1469dbfe6c9f998817a7947e90bb942d8f87d Mon Sep 17 00:00:00 2001 From: Lukas Brocke Date: Tue, 23 Feb 2021 19:49:58 +0100 Subject: [PATCH 288/383] dnsapi/ionos: Use POST instead of PATCH for adding TXT record The API now supports a POST route for adding records. Therefore checking for already existing records and including them in a PATCH request is no longer necessary. --- dnsapi/dns_ionos.sh | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/dnsapi/dns_ionos.sh b/dnsapi/dns_ionos.sh index e6bd5000..aaf8580f 100755 --- a/dnsapi/dns_ionos.sh +++ b/dnsapi/dns_ionos.sh @@ -24,20 +24,9 @@ dns_ionos_add() { return 1 fi - _new_record="{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}" + _body="[{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}]" - # As no POST route is supported by the API, check for existing records and include them in the PATCH request in order not delete them. - # This is required to support ACME v2 wildcard certificate creation, where two TXT records for the same domain name are created. - - _ionos_get_existing_records "$fulldomain" "$_zone_id" - - if [ "$_existing_records" ]; then - _body="[$_new_record,$_existing_records]" - else - _body="[$_new_record]" - fi - - if _ionos_rest PATCH "$IONOS_ROUTE_ZONES/$_zone_id" "$_body" && [ -z "$response" ]; then + if _ionos_rest POST "$IONOS_ROUTE_ZONES/$_zone_id/records" "$_body" && [ -z "$response" ]; then _info "TXT record has been created successfully." return 0 fi @@ -125,17 +114,6 @@ _get_root() { return 1 } -_ionos_get_existing_records() { - fulldomain=$1 - zone_id=$2 - - if _ionos_rest GET "$IONOS_ROUTE_ZONES/$zone_id?recordName=$fulldomain&recordType=TXT"; then - response="$(echo "$response" | tr -d "\n")" - - _existing_records="$(printf "%s\n" "$response" | _egrep_o "\"records\":\[.*\]" | _head_n 1 | cut -d '[' -f 2 | sed 's/]//')" - fi -} - _ionos_get_record() { fulldomain=$1 zone_id=$2 @@ -168,7 +146,7 @@ _ionos_rest() { export _H2="Accept: application/json" export _H3="Content-Type: application/json" - response="$(_post "$data" "$IONOS_API$route" "" "$method")" + response="$(_post "$data" "$IONOS_API$route" "" "$method" "application/json")" else export _H2="Accept: */*" From 0f494c9dd62fbbd27d03c6e6603cb96023910a01 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 1 Mar 2021 18:13:50 +0800 Subject: [PATCH 289/383] fix https://github.com/acmesh-official/acme.sh/issues/3433 --- acme.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/acme.sh b/acme.sh index 24cda9c4..748363e8 100755 --- a/acme.sh +++ b/acme.sh @@ -2133,6 +2133,12 @@ _send_signed_request() { _sleep $_sleep_retry_sec continue fi + if _contains "$_body" "The Replay Nonce is not recognized"; then + _info "The replay Nonce is not valid, let's get a new one, Sleeping $_sleep_retry_sec seconds." + _CACHED_NONCE="" + _sleep $_sleep_retry_sec + continue + fi fi return 0 done From 3817ddef412d31daf00170c8f3afeadc4aa08e68 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 4 Mar 2021 21:38:51 +0800 Subject: [PATCH 290/383] fix https://github.com/acmesh-official/acme.sh/issues/3019 --- dnsapi/dns_namecheap.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index 7ce39fa9..5e1f4791 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -208,7 +208,7 @@ _namecheap_parse_host() { _hostid=$(echo "$_host" | _egrep_o ' HostId="[^"]*' | cut -d '"' -f 2) _hostname=$(echo "$_host" | _egrep_o ' Name="[^"]*' | cut -d '"' -f 2) _hosttype=$(echo "$_host" | _egrep_o ' Type="[^"]*' | cut -d '"' -f 2) - _hostaddress=$(echo "$_host" | _egrep_o ' Address="[^"]*' | cut -d '"' -f 2) + _hostaddress=$(echo "$_host" | _egrep_o ' Address="[^"]*' | cut -d '"' -f 2 | _xml_decode) _hostmxpref=$(echo "$_host" | _egrep_o ' MXPref="[^"]*' | cut -d '"' -f 2) _hostttl=$(echo "$_host" | _egrep_o ' TTL="[^"]*' | cut -d '"' -f 2) @@ -405,3 +405,11 @@ _namecheap_set_tld_sld() { done } + +_xml_decode() { + sed 's/"/"/g' +} + + + + From 52cfb9a041a4d00f0fe88a34f27e9c2e4b71715e Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 4 Mar 2021 21:50:54 +0800 Subject: [PATCH 291/383] fix format --- dnsapi/dns_namecheap.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index 5e1f4791..e3dc7997 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -410,6 +410,3 @@ _xml_decode() { sed 's/"/"/g' } - - - From 89bb7e6b0ea5796da06ae47cefa847ff23e5523a Mon Sep 17 00:00:00 2001 From: wout Date: Wed, 10 Mar 2021 16:18:07 +0100 Subject: [PATCH 292/383] Add wildcard certificate support for dns_constellix --- dnsapi/dns_constellix.sh | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_constellix.sh b/dnsapi/dns_constellix.sh index 42df710d..d0d3132a 100644 --- a/dnsapi/dns_constellix.sh +++ b/dnsapi/dns_constellix.sh @@ -30,16 +30,38 @@ dns_constellix_add() { return 1 fi - _info "Adding TXT record" - if _constellix_rest POST "domains/${_domain_id}/records" "[{\"type\":\"txt\",\"add\":true,\"set\":{\"name\":\"${_sub_domain}\",\"ttl\":120,\"roundRobin\":[{\"value\":\"${txtvalue}\"}]}}]"; then - if printf -- "%s" "$response" | grep "{\"success\":\"1 record(s) added, 0 record(s) updated, 0 record(s) deleted\"}" >/dev/null; then - _info "Added" - return 0 + # To support wildcard certificates, try to find existig TXT record and update it. + _info "Search existing TXT record" + if _constellix_rest GET "domains/${_domain_id}/records/TXT/search?exact=${_sub_domain}"; then + if printf -- "%s" "$response" | grep "{\"errors\":\[\"Requested record was not found\"\]}" >/dev/null; then + _info "Adding TXT record" + if _constellix_rest POST "domains/${_domain_id}/records" "[{\"type\":\"txt\",\"add\":true,\"set\":{\"name\":\"${_sub_domain}\",\"ttl\":60,\"roundRobin\":[{\"value\":\"${txtvalue}\"}]}}]"; then + if printf -- "%s" "$response" | grep "{\"success\":\"1 record(s) added, 0 record(s) updated, 0 record(s) deleted\"}" >/dev/null; then + _info "Added" + return 0 + else + _err "Error adding TXT record" + fi + fi else - _err "Error adding TXT record" - return 1 + _record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]+" | cut -d ':' -f 2) + if _constellix_rest GET "domains/${_domain_id}/records/TXT/${_record_id}"; then + _new_rr_values=$(printf "%s\n" "$response" | _egrep_o "\"roundRobin\":\[.*?\]" | sed "s/\]$/,{\"value\":\"${txtvalue}\"}]/") + _debug _new_rr_values $_new_rr_values + _info "Updating TXT record" + if _constellix_rest PUT "domains/${_domain_id}/records/TXT/${_record_id}" "{\"name\":\"${_sub_domain}\",\"ttl\":60,${_new_rr_values}}"; then + if printf -- "%s" "$response" | grep "{\"success\":\"Record.*updated successfully\"}" >/dev/null; then + _info "Updated" + return 0 + else + _err "Error updating TXT record" + fi + fi + fi fi fi + + return 1 } # Usage: fulldomain txtvalue @@ -68,9 +90,10 @@ dns_constellix_rm() { return 0 else _err "Error removing TXT record" - return 1 fi fi + + return 1 } #################### Private functions below ################################## From 494a6e6090e4a8b3980f3c92d6d86ce3772e3da2 Mon Sep 17 00:00:00 2001 From: wout Date: Wed, 10 Mar 2021 16:32:09 +0100 Subject: [PATCH 293/383] Fix checks --- dnsapi/dns_constellix.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_constellix.sh b/dnsapi/dns_constellix.sh index d0d3132a..5c20a917 100644 --- a/dnsapi/dns_constellix.sh +++ b/dnsapi/dns_constellix.sh @@ -38,7 +38,7 @@ dns_constellix_add() { if _constellix_rest POST "domains/${_domain_id}/records" "[{\"type\":\"txt\",\"add\":true,\"set\":{\"name\":\"${_sub_domain}\",\"ttl\":60,\"roundRobin\":[{\"value\":\"${txtvalue}\"}]}}]"; then if printf -- "%s" "$response" | grep "{\"success\":\"1 record(s) added, 0 record(s) updated, 0 record(s) deleted\"}" >/dev/null; then _info "Added" - return 0 + return 0 else _err "Error adding TXT record" fi @@ -47,7 +47,7 @@ dns_constellix_add() { _record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]+" | cut -d ':' -f 2) if _constellix_rest GET "domains/${_domain_id}/records/TXT/${_record_id}"; then _new_rr_values=$(printf "%s\n" "$response" | _egrep_o "\"roundRobin\":\[.*?\]" | sed "s/\]$/,{\"value\":\"${txtvalue}\"}]/") - _debug _new_rr_values $_new_rr_values + _debug _new_rr_values "$_new_rr_values" _info "Updating TXT record" if _constellix_rest PUT "domains/${_domain_id}/records/TXT/${_record_id}" "{\"name\":\"${_sub_domain}\",\"ttl\":60,${_new_rr_values}}"; then if printf -- "%s" "$response" | grep "{\"success\":\"Record.*updated successfully\"}" >/dev/null; then From 8fdfe673e8ccd69dfe8cfcd8acff641dd84dae24 Mon Sep 17 00:00:00 2001 From: wout Date: Wed, 10 Mar 2021 23:34:21 +0100 Subject: [PATCH 294/383] Improve the remove handling so it does not print errors --- dnsapi/dns_constellix.sh | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/dnsapi/dns_constellix.sh b/dnsapi/dns_constellix.sh index 5c20a917..fb4e278e 100644 --- a/dnsapi/dns_constellix.sh +++ b/dnsapi/dns_constellix.sh @@ -30,8 +30,8 @@ dns_constellix_add() { return 1 fi - # To support wildcard certificates, try to find existig TXT record and update it. - _info "Search existing TXT record" + # The TXT record might already exist when working with wilcard certificates. In that case, update the record by adding the new value. + _debug "Search TXT record" if _constellix_rest GET "domains/${_domain_id}/records/TXT/search?exact=${_sub_domain}"; then if printf -- "%s" "$response" | grep "{\"errors\":\[\"Requested record was not found\"\]}" >/dev/null; then _info "Adding TXT record" @@ -83,13 +83,22 @@ dns_constellix_rm() { return 1 fi - _info "Removing TXT record" - if _constellix_rest POST "domains/${_domain_id}/records" "[{\"type\":\"txt\",\"delete\":true,\"filter\":{\"field\":\"name\",\"op\":\"eq\",\"value\":\"${_sub_domain}\"}}]"; then - if printf -- "%s" "$response" | grep "{\"success\":\"0 record(s) added, 0 record(s) updated, 1 record(s) deleted\"}" >/dev/null; then + # The TXT record might have been removed already when working with some wildcard certificates. + _debug "Search TXT record" + if _constellix_rest GET "domains/${_domain_id}/records/TXT/search?exact=${_sub_domain}"; then + if printf -- "%s" "$response" | grep "{\"errors\":\[\"Requested record was not found\"\]}" >/dev/null; then _info "Removed" return 0 else - _err "Error removing TXT record" + _info "Removing TXT record" + if _constellix_rest POST "domains/${_domain_id}/records" "[{\"type\":\"txt\",\"delete\":true,\"filter\":{\"field\":\"name\",\"op\":\"eq\",\"value\":\"${_sub_domain}\"}}]"; then + if printf -- "%s" "$response" | grep "{\"success\":\"0 record(s) added, 0 record(s) updated, 1 record(s) deleted\"}" >/dev/null; then + _info "Removed" + return 0 + else + _err "Error removing TXT record" + fi + fi fi fi From 928aa74e89b7aac0f1cddcb3e103a1b151aa34d7 Mon Sep 17 00:00:00 2001 From: wout Date: Wed, 10 Mar 2021 23:36:34 +0100 Subject: [PATCH 295/383] Fix typo --- dnsapi/dns_constellix.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_constellix.sh b/dnsapi/dns_constellix.sh index fb4e278e..75211a6f 100644 --- a/dnsapi/dns_constellix.sh +++ b/dnsapi/dns_constellix.sh @@ -30,7 +30,7 @@ dns_constellix_add() { return 1 fi - # The TXT record might already exist when working with wilcard certificates. In that case, update the record by adding the new value. + # The TXT record might already exist when working with wildcard certificates. In that case, update the record by adding the new value. _debug "Search TXT record" if _constellix_rest GET "domains/${_domain_id}/records/TXT/search?exact=${_sub_domain}"; then if printf -- "%s" "$response" | grep "{\"errors\":\[\"Requested record was not found\"\]}" >/dev/null; then From 8733635638875adfa8b201d4d89990b507ba86e8 Mon Sep 17 00:00:00 2001 From: anom-human <80478363+anom-human@users.noreply.github.com> Date: Thu, 11 Mar 2021 19:11:02 +0100 Subject: [PATCH 296/383] Update dns_servercow.sh to support wildcard certs Updated dns_servercow.sh to support txt records with multiple entries. This supports wildcard certificates that require txt records with the same name and different contents. --- dnsapi/dns_servercow.sh | 42 +++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_servercow.sh b/dnsapi/dns_servercow.sh index e73d85b0..39f16396 100755 --- a/dnsapi/dns_servercow.sh +++ b/dnsapi/dns_servercow.sh @@ -48,18 +48,44 @@ dns_servercow_add() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - - if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then - if printf -- "%s" "$response" | grep "ok" >/dev/null; then - _info "Added, OK" - return 0 + + # check whether a txt record already exists for the subdomain + if printf -- "%s" "$response" | grep "{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\"" >/dev/null; then + _info "A txt record with the same name already exists." + # trim the string on the left + txtvalue_old=${response#*{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\",\"content\":\"} + # trim the string on the right + txtvalue_old=${txtvalue_old%%\"*} + + _debug txtvalue_old "$txtvalue_old" + + _info "Add the new txtvalue to the existing txt record." + if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":[\"$txtvalue\",\"$txtvalue_old\"],\"ttl\":20}"; then + if printf -- "%s" "$response" | grep "ok" >/dev/null; then + _info "Added additional txtvalue, OK" + return 0 + else + _err "add txt record error." + return 1 + fi + fi + _err "add txt record error." + return 1 else + _info "There is no txt record with the name yet." + if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then + if printf -- "%s" "$response" | grep "ok" >/dev/null; then + _info "Added, OK" + return 0 + else + _err "add txt record error." + return 1 + fi + fi _err "add txt record error." return 1 - fi fi - _err "add txt record error." - + return 1 } From 5c4bfbbd950d47d3fe33d4aee75a70499fd117c0 Mon Sep 17 00:00:00 2001 From: anom-human <80478363+anom-human@users.noreply.github.com> Date: Thu, 11 Mar 2021 20:25:49 +0100 Subject: [PATCH 297/383] Update dns_servercow.sh to support wildcard certs Updated dns_servercow.sh to support txt records with multiple entries. This supports wildcard certificates that require txt records with the same name and different contents. --- dnsapi/dns_servercow.sh | 64 ++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/dnsapi/dns_servercow.sh b/dnsapi/dns_servercow.sh index 39f16396..f70a2294 100755 --- a/dnsapi/dns_servercow.sh +++ b/dnsapi/dns_servercow.sh @@ -48,44 +48,44 @@ dns_servercow_add() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - - # check whether a txt record already exists for the subdomain + + # check whether a txt record already exists for the subdomain if printf -- "%s" "$response" | grep "{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\"" >/dev/null; then - _info "A txt record with the same name already exists." - # trim the string on the left - txtvalue_old=${response#*{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\",\"content\":\"} - # trim the string on the right - txtvalue_old=${txtvalue_old%%\"*} - - _debug txtvalue_old "$txtvalue_old" - - _info "Add the new txtvalue to the existing txt record." - if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":[\"$txtvalue\",\"$txtvalue_old\"],\"ttl\":20}"; then - if printf -- "%s" "$response" | grep "ok" >/dev/null; then - _info "Added additional txtvalue, OK" - return 0 - else - _err "add txt record error." + _info "A txt record with the same name already exists." + # trim the string on the left + txtvalue_old=${response#*{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\",\"content\":\"} + # trim the string on the right + txtvalue_old=${txtvalue_old%%\"*} + + _debug txtvalue_old "$txtvalue_old" + + _info "Add the new txtvalue to the existing txt record." + if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":[\"$txtvalue\",\"$txtvalue_old\"],\"ttl\":20}"; then + if printf -- "%s" "$response" | grep "ok" >/dev/null; then + _info "Added additional txtvalue, OK" + return 0 + else + _err "add txt record error." return 1 - fi fi - _err "add txt record error." - return 1 - else - _info "There is no txt record with the name yet." - if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then - if printf -- "%s" "$response" | grep "ok" >/dev/null; then - _info "Added, OK" - return 0 - else - _err "add txt record error." + fi + _err "add txt record error." + return 1 + else + _info "There is no txt record with the name yet." + if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then + if printf -- "%s" "$response" | grep "ok" >/dev/null; then + _info "Added, OK" + return 0 + else + _err "add txt record error." return 1 - fi fi - _err "add txt record error." - return 1 + fi + _err "add txt record error." + return 1 fi - + return 1 } From 96a95ba9fefa05f88e11f500b98e00706d9c7419 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 13 Mar 2021 20:43:25 +0800 Subject: [PATCH 298/383] fix https://github.com/acmesh-official/acme.sh/issues/3312 --- acme.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 748363e8..8d422719 100755 --- a/acme.sh +++ b/acme.sh @@ -5287,6 +5287,7 @@ signcsr() { _renew_hook="${10}" _local_addr="${11}" _challenge_alias="${12}" + _preferred_chain="${13}" _csrsubj=$(_readSubjectFromCSR "$_csrfile") if [ "$?" != "0" ]; then @@ -5333,7 +5334,7 @@ signcsr() { _info "Copy csr to: $CSR_PATH" cp "$_csrfile" "$CSR_PATH" - issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_addr" "$_challenge_alias" + issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_addr" "$_challenge_alias" "$_preferred_chain" } @@ -7430,7 +7431,7 @@ _process() { deploy "$_domain" "$_deploy_hook" "$_ecc" ;; signcsr) - signcsr "$_csr" "$_webroot" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" + signcsr "$_csr" "$_webroot" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" "$_preferred_chain" ;; showcsr) showcsr "$_csr" "$_domain" From 3dbe5d872ba777d6fa5d9eb27d4a6cc7adbb5e0e Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 13 Mar 2021 20:46:12 +0800 Subject: [PATCH 299/383] fix format --- dnsapi/dns_namecheap.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index e3dc7997..d15d6b0e 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -409,4 +409,3 @@ _namecheap_set_tld_sld() { _xml_decode() { sed 's/"/"/g' } - From 8eda5f36fb04df03b74e9c3330cd5e995b0ab840 Mon Sep 17 00:00:00 2001 From: Quentin Dreyer Date: Fri, 12 Mar 2021 12:03:36 +0100 Subject: [PATCH 300/383] feat: add dns_porkbun --- dnsapi/dns_porkbun.sh | 171 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 dnsapi/dns_porkbun.sh diff --git a/dnsapi/dns_porkbun.sh b/dnsapi/dns_porkbun.sh new file mode 100644 index 00000000..05ecb781 --- /dev/null +++ b/dnsapi/dns_porkbun.sh @@ -0,0 +1,171 @@ +#!/usr/bin/env sh + +# +#PORKBUN_API_KEY="pk1_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" +#PORKBUN_SECRET_API_KEY="sk1_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + +PORKBUN_Api="https://porkbun.com/api/json/v3" + +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_porkbun_add() { + fulldomain=$1 + txtvalue=$2 + + PORKBUN_API_KEY="${PORKBUN_API_KEY:-$(_readaccountconf_mutable PORKBUN_API_KEY)}" + PORKBUN_SECRET_API_KEY="${PORKBUN_SECRET_API_KEY:-$(_readaccountconf_mutable PORKBUN_SECRET_API_KEY)}" + + if [ -z "$PORKBUN_API_KEY" ] || [ -z "$PORKBUN_SECRET_API_KEY" ]; then + PORKBUN_API_KEY='' + PORKBUN_SECRET_API_KEY='' + _err "You didn't specify a Porkbun api key and secret api key yet." + _err "You can get yours from here https://porkbun.com/account/api." + return 1 + fi + + #save the credentials to the account conf file. + _saveaccountconf_mutable PORKBUN_API_KEY "$PORKBUN_API_KEY" + _saveaccountconf_mutable PORKBUN_SECRET_API_KEY "$PORKBUN_SECRET_API_KEY" + + _debug 'First detect the root zone' + if ! _get_root "$fulldomain"; then + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting txt records" + _porkbun_rest POST "dns/retrieve/$_domain" + + if ! echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null; then + _err "Error $response" + return 1 + fi + + # For wildcard cert, the main root domain and the wildcard domain have the same txt subdomain name, so + # we can not use updating anymore. + # count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2) + # _debug count "$count" + # if [ "$count" = "0" ]; then + _info "Adding record" + if _porkbun_rest POST "dns/create/$_domain" "{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":120}"; then + if _contains "$response" '\"status\":"SUCCESS"'; then + _info "Added, OK" + return 0 + elif _contains "$response" "The record already exists"; then + _info "Already exists, OK" + return 0 + else + _err "Add txt record error. ($response)" + return 1 + fi + fi + _err "Add txt record error." + return 1 + +} + +#fulldomain txtvalue +dns_porkbun_rm() { + fulldomain=$1 + txtvalue=$2 + + PORKBUN_API_KEY="${PORKBUN_API_KEY:-$(_readaccountconf_mutable PORKBUN_API_KEY)}" + PORKBUN_SECRET_API_KEY="${PORKBUN_SECRET_API_KEY:-$(_readaccountconf_mutable PORKBUN_SECRET_API_KEY)}" + + _debug 'First detect the root zone' + if ! _get_root "$fulldomain"; then + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting txt records" + _porkbun_rest POST "dns/retrieve/$_domain" + + if ! echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null; then + _err "Error: $response" + return 1 + fi + + count=$(echo "$response" | _egrep_o "\"count\": *[^,]*" | cut -d : -f 2 | tr -d " ") + _debug count "$count" + if [ "$count" = "0" ]; then + _info "Don't need to remove." + else + record_id=$(echo "$response" | tr '{' '\n' | grep "$txtvalue" | cut -d, -f1 | cut -d: -f2 | tr -d \") + _debug "record_id" "$record_id" + if [ -z "$record_id" ]; then + _err "Can not get record id to remove." + return 1 + fi + if ! _porkbun_rest POST "dns/delete/$_domain/$record_id"; then + _err "Delete record error." + return 1 + fi + echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null + fi + +} + +#################### Private functions below ################################## +#_acme-challenge.www.domain.com +#returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +_get_root() { + domain=$1 + i=1 + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug h "$h" + if [ -z "$h" ]; then + return 1 + fi + + if _porkbun_rest POST "dns/retrieve/$h"; then + if _contains "$response" "\"status\":\"SUCCESS\""; then + _sub_domain="$(echo "$fulldomain" | sed "s/\\.$_domain\$//")" + _domain=$h + return 0 + else + _debug "Go to next level of $_domain" + fi + else + _debug "Go to next level of $_domain" + fi + i=$(_math "$i" + 1) + done + + return 1 +} + +_porkbun_rest() { + m=$1 + ep="$2" + data="$3" + _debug "$ep" + + api_key_trimmed=$(echo "$PORKBUN_API_KEY" | tr -d '"') + secret_api_key_trimmed=$(echo "$PORKBUN_SECRET_API_KEY" | tr -d '"') + + test -z "$data" && data="{" || data="$(echo $data | cut -d'}' -f1)," + data="$data\"apikey\":\"$api_key_trimmed\",\"secretapikey\":\"$secret_api_key_trimmed\"}" + + export _H1="Content-Type: application/json" + + if [ "$m" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$PORKBUN_Api/$ep" "" "$m")" + else + response="$(_get "$PORKBUN_Api/$ep")" + fi + + if [ "$?" != "0" ]; then + _err "error $ep" + return 1 + fi + _debug2 response "$response" + return 0 +} From 2e34e11b02bba4243fb6e4578c7f3d4ba364cd47 Mon Sep 17 00:00:00 2001 From: qkdreyer Date: Sat, 13 Mar 2021 14:53:43 +0100 Subject: [PATCH 301/383] fix: prevent rate limit --- dnsapi/dns_porkbun.sh | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/dnsapi/dns_porkbun.sh b/dnsapi/dns_porkbun.sh index 05ecb781..18da6b2f 100644 --- a/dnsapi/dns_porkbun.sh +++ b/dnsapi/dns_porkbun.sh @@ -35,14 +35,6 @@ dns_porkbun_add() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - _debug "Getting txt records" - _porkbun_rest POST "dns/retrieve/$_domain" - - if ! echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null; then - _err "Error $response" - return 1 - fi - # For wildcard cert, the main root domain and the wildcard domain have the same txt subdomain name, so # we can not use updating anymore. # count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2) @@ -81,14 +73,6 @@ dns_porkbun_rm() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - _debug "Getting txt records" - _porkbun_rest POST "dns/retrieve/$_domain" - - if ! echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null; then - _err "Error: $response" - return 1 - fi - count=$(echo "$response" | _egrep_o "\"count\": *[^,]*" | cut -d : -f 2 | tr -d " ") _debug count "$count" if [ "$count" = "0" ]; then @@ -162,6 +146,8 @@ _porkbun_rest() { response="$(_get "$PORKBUN_Api/$ep")" fi + _sleep 3 # prevent rate limit + if [ "$?" != "0" ]; then _err "error $ep" return 1 From 2386d2e299561378b11eb6a72dac05e7449e2222 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Sat, 20 Mar 2021 15:26:32 +0100 Subject: [PATCH 304/383] String change --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 922e6819..3b5a8847 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -32,7 +32,7 @@ dns_websupport_add() { WS_ApiKey="" WS_ApiSecret="" _err "You did not specify the API Key and/or API Secret" - _err "You can get the credentials from here https://admin.websupport.sk/en/auth/apiKey" + _err "You can get the API credentials from here https://admin.websupport.sk/en/auth/apiKey" return 1 fi From c384ed960c138f4449e79293644c4d0ec937cef1 Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Sat, 20 Mar 2021 16:01:09 +0100 Subject: [PATCH 305/383] Syncing with the original repo (#2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * change arvan api script * change Author name * change name actor * Updated --preferred-chain to issue ISRG properly To support different openssl crl2pkcs7 help cli format * dnsapi/pdns: also normalize json response in detecting root zone * Chain (#3408) * fix https://github.com/acmesh-official/acme.sh/issues/3384 match the issuer to the root CA cert subject * fix format * fix https://github.com/acmesh-official/acme.sh/issues/3384 * remove the alt files. https://github.com/acmesh-official/acme.sh/issues/3384 * upgrade freebsd and solaris * duckdns - fix "integer expression expected" errors (#3397) * fix "integer expression expected" errors * duckdns fix * Update dns_duckdns.sh * Update dns_duckdns.sh * Implement smtp notify hook Support notifications via direct SMTP server connection. Uses Python (2.7.x or 3.4+) to communicate with SMTP server. * Make shfmt happy (I'm open to better ways of formatting the heredoc that embeds the Python script.) * Only save config if send is successful * Add instructions for reporting bugs * Prep for curl or Python; clean up SMTP_* variable usage * Implement curl version of smtp notify-hook * More than one blank line is an abomination, apparently I will not try to use whitespace to group code visually * Fix: Unifi deploy hook support Unifi Cloud Key (#3327) * fix: unifi deploy hook also update Cloud Key nginx certs When running on a Unifi Cloud Key device, also deploy to /etc/ssl/private/cloudkey.{crt,key} and reload nginx. This makes the new cert available for the Cloud Key management app running via nginx on port 443 (as well as the port 8443 Unifi Controller app the deploy hook already supported). Fixes #3326 * Improve settings documentation comments * Improve Cloud Key pre-flight error messaging * Fix typo * Add support for UnifiOS (Cloud Key Gen2) Since UnifiOS does not use the Java keystore (like a Unifi Controller or Cloud Key Gen1 deploy), this also reworks the settings validation and error messaging somewhat. * PR review fixes * Detect unsupported Cloud Key java keystore location * Don't try to restart inactive services (and remove extra spaces from reload command) * Clean up error messages and internal variables * Change to _getdeployconf/_savedeployconf * Switch from cp to cat to preserve file permissions * feat: add huaweicloud error handling * fix: fix freebsd and solaris * support openssl 3.0 fix https://github.com/acmesh-official/acme.sh/issues/3399 * make the fix for rsa key only * Use PROJECT_NAME and VER for X-Mailer header Also add X-Mailer header to Python version * Add _clearaccountconf_mutable() * Rework read/save config to not save default values Add and use _readaccountconf_mutable_default and _saveaccountconf_mutable_default helpers to capture common default value handling. New approach also eliminates need for separate underscore-prefixed version of each conf var. * Implement _rfc2822_date helper * Clean email headers and warn on unsupported address format Just in case, make sure CR or NL don't end up in an email header. * Clarify _readaccountconf_mutable_default * Add Date email header in Python implementation * Use email.policy.default in Python 3 implementation Improves standards compatibility and utf-8 handling in Python 3.3-3.8. (email.policy.default becomes the default in Python 3.9.) * Prefer Python to curl when both available * Change default SMTP_SECURE to "tls" Secure by default. Also try to minimize configuration errors. (Many ESPs/ISPs require STARTTLS, and most support it.) * Update dns_dp.sh 没有encode中文字符会导致提交失败 * No need to include EC parameters explicitly with the private key. (they are embedded) * Fixes response handling and thereby allow issuing of subdomain certs * Adds comment * fix https://github.com/acmesh-official/acme.sh/issues/3402 * dnsapi/ionos: Use POST instead of PATCH for adding TXT record The API now supports a POST route for adding records. Therefore checking for already existing records and including them in a PATCH request is no longer necessary. * fix https://github.com/acmesh-official/acme.sh/issues/3433 * fix https://github.com/acmesh-official/acme.sh/issues/3019 * fix format * Update dns_servercow.sh to support wildcard certs Updated dns_servercow.sh to support txt records with multiple entries. This supports wildcard certificates that require txt records with the same name and different contents. * Update dns_servercow.sh to support wildcard certs Updated dns_servercow.sh to support txt records with multiple entries. This supports wildcard certificates that require txt records with the same name and different contents. * fix https://github.com/acmesh-official/acme.sh/issues/3312 * fix format * feat: add dns_porkbun * fix: prevent rate limit Co-authored-by: Vahid Fardi Co-authored-by: neil Co-authored-by: Gnought <1684105+gnought@users.noreply.github.com> Co-authored-by: manuel Co-authored-by: jerrm Co-authored-by: medmunds Co-authored-by: Mike Edmunds Co-authored-by: Easton Man Co-authored-by: czeming Co-authored-by: Geert Hendrickx Co-authored-by: Kristian Johansson Co-authored-by: Lukas Brocke Co-authored-by: anom-human <80478363+anom-human@users.noreply.github.com> Co-authored-by: neil Co-authored-by: Quentin Dreyer --- .github/workflows/DNS.yml | 4 +- .github/workflows/LetsEncrypt.yml | 4 +- acme.sh | 98 ++++++-- deploy/unifi.sh | 220 ++++++++++++---- dnsapi/dns_arvan.sh | 47 ++-- dnsapi/dns_dp.sh | 2 +- dnsapi/dns_duckdns.sh | 6 +- dnsapi/dns_huaweicloud.sh | 36 ++- dnsapi/dns_ionos.sh | 28 +-- dnsapi/dns_namecheap.sh | 6 +- dnsapi/dns_pdns.sh | 4 +- dnsapi/dns_porkbun.sh | 157 ++++++++++++ dnsapi/dns_servercow.sh | 42 +++- dnsapi/dns_simply.sh | 18 +- notify/smtp.sh | 402 +++++++++++++++++++++++++++++- 15 files changed, 912 insertions(+), 162 deletions(-) create mode 100644 dnsapi/dns_porkbun.sh diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 5dc2d453..ed0426ad 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -184,7 +184,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.0.7 + - uses: vmactions/freebsd-vm@v0.1.2 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkg install -y socat curl @@ -223,7 +223,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/solaris-vm@v0.0.1 + - uses: vmactions/solaris-vm@v0.0.3 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkgutil -y -i socat curl diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 8d0c4eb0..7c398c09 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -111,7 +111,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.0.7 + - uses: vmactions/freebsd-vm@v0.1.2 with: envs: 'NGROK_TOKEN TEST_LOCAL' prepare: pkg install -y socat curl @@ -136,7 +136,7 @@ jobs: run: echo "TestingDomain=${{steps.ngrok.outputs.server}}" >> $GITHUB_ENV - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/solaris-vm@v0.0.1 + - uses: vmactions/solaris-vm@v0.0.3 with: envs: 'TEST_LOCAL TestingDomain' nat: | diff --git a/acme.sh b/acme.sh index a1ad4195..8d422719 100755 --- a/acme.sh +++ b/acme.sh @@ -562,8 +562,16 @@ if _exists xargs && [ "$(printf %s '\\x41' | xargs printf)" = 'A' ]; then fi _h2b() { - if _exists xxd && xxd -r -p 2>/dev/null; then - return + if _exists xxd; then + if _contains "$(xxd --help 2>&1)" "assumes -c30"; then + if xxd -r -p -c 9999 2>/dev/null; then + return + fi + else + if xxd -r -p 2>/dev/null; then + return + fi + fi fi hex=$(cat) @@ -1124,7 +1132,7 @@ _createkey() { if _isEccKey "$length"; then _debug "Using ec name: $eccname" - if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -genkey 2>/dev/null)"; then + if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -noout -genkey 2>/dev/null)"; then echo "$_opkey" >"$f" else _err "error ecc key name: $eccname" @@ -1132,7 +1140,11 @@ _createkey() { fi else _debug "Using RSA: $length" - if _opkey="$(${ACME_OPENSSL_BIN:-openssl} genrsa "$length" 2>/dev/null)"; then + __traditional="" + if _contains "$(${ACME_OPENSSL_BIN:-openssl} help genrsa 2>&1)" "-traditional"; then + __traditional="-traditional" + fi + if _opkey="$(${ACME_OPENSSL_BIN:-openssl} genrsa $__traditional "$length" 2>/dev/null)"; then echo "$_opkey" >"$f" else _err "error rsa key: $length" @@ -2121,6 +2133,12 @@ _send_signed_request() { _sleep $_sleep_retry_sec continue fi + if _contains "$_body" "The Replay Nonce is not recognized"; then + _info "The replay Nonce is not valid, let's get a new one, Sleeping $_sleep_retry_sec seconds." + _CACHED_NONCE="" + _sleep $_sleep_retry_sec + continue + fi fi return 0 done @@ -2279,6 +2297,13 @@ _clearaccountconf() { _clear_conf "$ACCOUNT_CONF_PATH" "$1" } +#key +_clearaccountconf_mutable() { + _clearaccountconf "SAVED_$1" + #remove later + _clearaccountconf "$1" +} + #_savecaconf key value _savecaconf() { _save_conf "$CA_CONF" "$1" "$2" @@ -4009,12 +4034,42 @@ _check_dns_entries() { } #file -_get_cert_issuers() { +_get_chain_issuers() { _cfile="$1" - if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then - ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 + if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -help 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then + ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep -i 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 else - ${ACME_OPENSSL_BIN:-openssl} x509 -in $_cfile -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 + _cindex=1 + for _startn in $(grep -n -- "$BEGIN_CERT" "$_cfile" | cut -d : -f 1); do + _endn="$(grep -n -- "$END_CERT" "$_cfile" | cut -d : -f 1 | _head_n $_cindex | _tail_n 1)" + _debug2 "_startn" "$_startn" + _debug2 "_endn" "$_endn" + if [ "$DEBUG" ]; then + _debug2 "cert$_cindex" "$(sed -n "$_startn,${_endn}p" "$_cfile")" + fi + sed -n "$_startn,${_endn}p" "$_cfile" | ${ACME_OPENSSL_BIN:-openssl} x509 -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 | sed "s/ *\(.*\)/\1/" + _cindex=$(_math $_cindex + 1) + done + fi +} + +# +_get_chain_subjects() { + _cfile="$1" + if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -help 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then + ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep -i 'Subject:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 + else + _cindex=1 + for _startn in $(grep -n -- "$BEGIN_CERT" "$_cfile" | cut -d : -f 1); do + _endn="$(grep -n -- "$END_CERT" "$_cfile" | cut -d : -f 1 | _head_n $_cindex | _tail_n 1)" + _debug2 "_startn" "$_startn" + _debug2 "_endn" "$_endn" + if [ "$DEBUG" ]; then + _debug2 "cert$_cindex" "$(sed -n "$_startn,${_endn}p" "$_cfile")" + fi + sed -n "$_startn,${_endn}p" "$_cfile" | ${ACME_OPENSSL_BIN:-openssl} x509 -text -noout | grep -i 'Subject:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 | sed "s/ *\(.*\)/\1/" + _cindex=$(_math $_cindex + 1) + done fi } @@ -4022,14 +4077,12 @@ _get_cert_issuers() { _match_issuer() { _cfile="$1" _missuer="$2" - _fissuers="$(_get_cert_issuers $_cfile)" + _fissuers="$(_get_chain_issuers $_cfile)" _debug2 _fissuers "$_fissuers" - if _contains "$_fissuers" "$_missuer"; then - return 0 - fi - _fissuers="$(echo "$_fissuers" | _lower_case)" + _rootissuer="$(echo "$_fissuers" | _lower_case | _tail_n 1)" + _debug2 _rootissuer "$_rootissuer" _missuer="$(echo "$_missuer" | _lower_case)" - _contains "$_fissuers" "$_missuer" + _contains "$_rootissuer" "$_missuer" } #webroot, domain domainlist keylength @@ -4803,6 +4856,9 @@ $_authorizations_map" _split_cert_chain "$CERT_PATH" "$CERT_FULLCHAIN_PATH" "$CA_CERT_PATH" if [ "$_preferred_chain" ] && [ -f "$CERT_FULLCHAIN_PATH" ]; then + if [ "$DEBUG" ]; then + _debug "default chain issuers: " "$(_get_chain_issuers "$CERT_FULLCHAIN_PATH")" + fi if ! _match_issuer "$CERT_FULLCHAIN_PATH" "$_preferred_chain"; then rels="$(echo "$responseHeaders" | tr -d ' <>' | grep -i "^link:" | grep -i 'rel="alternate"' | cut -d : -f 2- | cut -d ';' -f 1)" _debug2 "rels" "$rels" @@ -4818,13 +4874,22 @@ $_authorizations_map" _relca="$CA_CERT_PATH.alt" echo "$response" >"$_relcert" _split_cert_chain "$_relcert" "$_relfullchain" "$_relca" + if [ "$DEBUG" ]; then + _debug "rel chain issuers: " "$(_get_chain_issuers "$_relfullchain")" + fi if _match_issuer "$_relfullchain" "$_preferred_chain"; then _info "Matched issuer in: $rel" cat $_relcert >"$CERT_PATH" cat $_relfullchain >"$CERT_FULLCHAIN_PATH" cat $_relca >"$CA_CERT_PATH" + rm -f "$_relcert" + rm -f "$_relfullchain" + rm -f "$_relca" break fi + rm -f "$_relcert" + rm -f "$_relfullchain" + rm -f "$_relca" done fi fi @@ -5222,6 +5287,7 @@ signcsr() { _renew_hook="${10}" _local_addr="${11}" _challenge_alias="${12}" + _preferred_chain="${13}" _csrsubj=$(_readSubjectFromCSR "$_csrfile") if [ "$?" != "0" ]; then @@ -5268,7 +5334,7 @@ signcsr() { _info "Copy csr to: $CSR_PATH" cp "$_csrfile" "$CSR_PATH" - issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_addr" "$_challenge_alias" + issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_addr" "$_challenge_alias" "$_preferred_chain" } @@ -7365,7 +7431,7 @@ _process() { deploy "$_domain" "$_deploy_hook" "$_ecc" ;; signcsr) - signcsr "$_csr" "$_webroot" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" + signcsr "$_csr" "$_webroot" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" "$_preferred_chain" ;; showcsr) showcsr "$_csr" "$_domain" diff --git a/deploy/unifi.sh b/deploy/unifi.sh index 184aa62e..a864135e 100644 --- a/deploy/unifi.sh +++ b/deploy/unifi.sh @@ -1,12 +1,43 @@ #!/usr/bin/env sh -#Here is a script to deploy cert to unifi server. +# Here is a script to deploy cert on a Unifi Controller or Cloud Key device. +# It supports: +# - self-hosted Unifi Controller +# - Unifi Cloud Key (Gen1/2/2+) +# - Unifi Cloud Key running UnifiOS (v2.0.0+, Gen2/2+ only) +# Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3359 #returns 0 means success, otherwise error. +# The deploy-hook automatically detects standard Unifi installations +# for each of the supported environments. Most users should not need +# to set any of these variables, but if you are running a self-hosted +# Controller with custom locations, set these as necessary before running +# the deploy hook. (Defaults shown below.) +# +# Settings for Unifi Controller: +# Location of Java keystore or unifi.keystore.jks file: #DEPLOY_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore" +# Keystore password (built into Unifi Controller, not a user-set password): #DEPLOY_UNIFI_KEYPASS="aircontrolenterprise" +# Command to restart Unifi Controller: #DEPLOY_UNIFI_RELOAD="service unifi restart" +# +# Settings for Unifi Cloud Key Gen1 (nginx admin pages): +# Directory where cloudkey.crt and cloudkey.key live: +#DEPLOY_UNIFI_CLOUDKEY_CERTDIR="/etc/ssl/private" +# Command to restart maintenance pages and Controller +# (same setting as above, default is updated when running on Cloud Key Gen1): +#DEPLOY_UNIFI_RELOAD="service nginx restart && service unifi restart" +# +# Settings for UnifiOS (Cloud Key Gen2): +# Directory where unifi-core.crt and unifi-core.key live: +#DEPLOY_UNIFI_CORE_CONFIG="/data/unifi-core/config/" +# Command to restart unifi-core: +#DEPLOY_UNIFI_RELOAD="systemctl restart unifi-core" +# +# At least one of DEPLOY_UNIFI_KEYSTORE, DEPLOY_UNIFI_CLOUDKEY_CERTDIR, +# or DEPLOY_UNIFI_CORE_CONFIG must exist to receive the deployed certs. ######## Public functions ##################### @@ -24,77 +55,160 @@ unifi_deploy() { _debug _cca "$_cca" _debug _cfullchain "$_cfullchain" - if ! _exists keytool; then - _err "keytool not found" - return 1 - fi + _getdeployconf DEPLOY_UNIFI_KEYSTORE + _getdeployconf DEPLOY_UNIFI_KEYPASS + _getdeployconf DEPLOY_UNIFI_CLOUDKEY_CERTDIR + _getdeployconf DEPLOY_UNIFI_CORE_CONFIG + _getdeployconf DEPLOY_UNIFI_RELOAD + + _debug2 DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" + _debug2 DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" + _debug2 DEPLOY_UNIFI_CLOUDKEY_CERTDIR "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" + _debug2 DEPLOY_UNIFI_CORE_CONFIG "$DEPLOY_UNIFI_CORE_CONFIG" + _debug2 DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" + + # Space-separated list of environments detected and installed: + _services_updated="" + + # Default reload commands accumulated as we auto-detect environments: + _reload_cmd="" + + # Unifi Controller environment (self hosted or any Cloud Key) -- + # auto-detect by file /usr/lib/unifi/data/keystore: + _unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-/usr/lib/unifi/data/keystore}" + if [ -f "$_unifi_keystore" ]; then + _info "Installing certificate for Unifi Controller (Java keystore)" + _debug _unifi_keystore "$_unifi_keystore" + if ! _exists keytool; then + _err "keytool not found" + return 1 + fi + if [ ! -w "$_unifi_keystore" ]; then + _err "The file $_unifi_keystore is not writable, please change the permission." + return 1 + fi + + _unifi_keypass="${DEPLOY_UNIFI_KEYPASS:-aircontrolenterprise}" - DEFAULT_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore" - _unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-$DEFAULT_UNIFI_KEYSTORE}" - DEFAULT_UNIFI_KEYPASS="aircontrolenterprise" - _unifi_keypass="${DEPLOY_UNIFI_KEYPASS:-$DEFAULT_UNIFI_KEYPASS}" - DEFAULT_UNIFI_RELOAD="service unifi restart" - _reload="${DEPLOY_UNIFI_RELOAD:-$DEFAULT_UNIFI_RELOAD}" - - _debug _unifi_keystore "$_unifi_keystore" - if [ ! -f "$_unifi_keystore" ]; then - if [ -z "$DEPLOY_UNIFI_KEYSTORE" ]; then - _err "unifi keystore is not found, please define DEPLOY_UNIFI_KEYSTORE" + _debug "Generate import pkcs12" + _import_pkcs12="$(_mktemp)" + _toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root + # shellcheck disable=SC2181 + if [ "$?" != "0" ]; then + _err "Error generating pkcs12. Please re-run with --debug and report a bug." return 1 + fi + + _debug "Import into keystore: $_unifi_keystore" + if keytool -importkeystore \ + -deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \ + -srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \ + -alias unifi -noprompt; then + _debug "Import keystore success!" + rm "$_import_pkcs12" else - _err "It seems that the specified unifi keystore is not valid, please check." + _err "Error importing into Unifi Java keystore." + _err "Please re-run with --debug and report a bug." + rm "$_import_pkcs12" return 1 fi + + if systemctl -q is-active unifi; then + _reload_cmd="${_reload_cmd:+$_reload_cmd && }service unifi restart" + fi + _services_updated="${_services_updated} unifi" + _info "Install Unifi Controller certificate success!" + elif [ "$DEPLOY_UNIFI_KEYSTORE" ]; then + _err "The specified DEPLOY_UNIFI_KEYSTORE='$DEPLOY_UNIFI_KEYSTORE' is not valid, please check." + return 1 fi - if [ ! -w "$_unifi_keystore" ]; then - _err "The file $_unifi_keystore is not writable, please change the permission." + + # Cloud Key environment (non-UnifiOS -- nginx serves admin pages) -- + # auto-detect by file /etc/ssl/private/cloudkey.key: + _cloudkey_certdir="${DEPLOY_UNIFI_CLOUDKEY_CERTDIR:-/etc/ssl/private}" + if [ -f "${_cloudkey_certdir}/cloudkey.key" ]; then + _info "Installing certificate for Cloud Key Gen1 (nginx admin pages)" + _debug _cloudkey_certdir "$_cloudkey_certdir" + if [ ! -w "$_cloudkey_certdir" ]; then + _err "The directory $_cloudkey_certdir is not writable; please check permissions." + return 1 + fi + # Cloud Key expects to load the keystore from /etc/ssl/private/unifi.keystore.jks. + # Normally /usr/lib/unifi/data/keystore is a symlink there (so the keystore was + # updated above), but if not, we don't know how to handle this installation: + if ! cmp -s "$_unifi_keystore" "${_cloudkey_certdir}/unifi.keystore.jks"; then + _err "Unsupported Cloud Key configuration: keystore not found at '${_cloudkey_certdir}/unifi.keystore.jks'" + return 1 + fi + + cat "$_cfullchain" >"${_cloudkey_certdir}/cloudkey.crt" + cat "$_ckey" >"${_cloudkey_certdir}/cloudkey.key" + (cd "$_cloudkey_certdir" && tar -cf cert.tar cloudkey.crt cloudkey.key unifi.keystore.jks) + + if systemctl -q is-active nginx; then + _reload_cmd="${_reload_cmd:+$_reload_cmd && }service nginx restart" + fi + _info "Install Cloud Key Gen1 certificate success!" + _services_updated="${_services_updated} nginx" + elif [ "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" ]; then + _err "The specified DEPLOY_UNIFI_CLOUDKEY_CERTDIR='$DEPLOY_UNIFI_CLOUDKEY_CERTDIR' is not valid, please check." return 1 fi - _info "Generate import pkcs12" - _import_pkcs12="$(_mktemp)" - _toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root - if [ "$?" != "0" ]; then - _err "Oops, error creating import pkcs12, please report bug to us." + # UnifiOS environment -- auto-detect by /data/unifi-core/config/unifi-core.key: + _unifi_core_config="${DEPLOY_UNIFI_CORE_CONFIG:-/data/unifi-core/config}" + if [ -f "${_unifi_core_config}/unifi-core.key" ]; then + _info "Installing certificate for UnifiOS" + _debug _unifi_core_config "$_unifi_core_config" + if [ ! -w "$_unifi_core_config" ]; then + _err "The directory $_unifi_core_config is not writable; please check permissions." + return 1 + fi + + cat "$_cfullchain" >"${_unifi_core_config}/unifi-core.crt" + cat "$_ckey" >"${_unifi_core_config}/unifi-core.key" + + if systemctl -q is-active unifi-core; then + _reload_cmd="${_reload_cmd:+$_reload_cmd && }systemctl restart unifi-core" + fi + _info "Install UnifiOS certificate success!" + _services_updated="${_services_updated} unifi-core" + elif [ "$DEPLOY_UNIFI_CORE_CONFIG" ]; then + _err "The specified DEPLOY_UNIFI_CORE_CONFIG='$DEPLOY_UNIFI_CORE_CONFIG' is not valid, please check." return 1 fi - _info "Modify unifi keystore: $_unifi_keystore" - if keytool -importkeystore \ - -deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \ - -srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \ - -alias unifi -noprompt; then - _info "Import keystore success!" - rm "$_import_pkcs12" - else - _err "Import unifi keystore error, please report bug to us." - rm "$_import_pkcs12" + if [ -z "$_services_updated" ]; then + # None of the Unifi environments were auto-detected, so no deployment has occurred + # (and none of DEPLOY_UNIFI_{KEYSTORE,CLOUDKEY_CERTDIR,CORE_CONFIG} were set). + _err "Unable to detect Unifi environment in standard location." + _err "(This deploy hook must be run on the Unifi device, not a remote machine.)" + _err "For non-standard Unifi installations, set DEPLOY_UNIFI_KEYSTORE," + _err "DEPLOY_UNIFI_CLOUDKEY_CERTDIR, and/or DEPLOY_UNIFI_CORE_CONFIG as appropriate." return 1 fi - _info "Run reload: $_reload" - if eval "$_reload"; then + _reload_cmd="${DEPLOY_UNIFI_RELOAD:-$_reload_cmd}" + if [ -z "$_reload_cmd" ]; then + _err "Certificates were installed for services:${_services_updated}," + _err "but none appear to be active. Please set DEPLOY_UNIFI_RELOAD" + _err "to a command that will restart the necessary services." + return 1 + fi + _info "Reload services (this may take some time): $_reload_cmd" + if eval "$_reload_cmd"; then _info "Reload success!" - if [ "$DEPLOY_UNIFI_KEYSTORE" ]; then - _savedomainconf DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" - else - _cleardomainconf DEPLOY_UNIFI_KEYSTORE - fi - if [ "$DEPLOY_UNIFI_KEYPASS" ]; then - _savedomainconf DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" - else - _cleardomainconf DEPLOY_UNIFI_KEYPASS - fi - if [ "$DEPLOY_UNIFI_RELOAD" ]; then - _savedomainconf DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" - else - _cleardomainconf DEPLOY_UNIFI_RELOAD - fi - return 0 else _err "Reload error" return 1 fi - return 0 + # Successful, so save all (non-default) config: + _savedeployconf DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" + _savedeployconf DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" + _savedeployconf DEPLOY_UNIFI_CLOUDKEY_CERTDIR "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" + _savedeployconf DEPLOY_UNIFI_CORE_CONFIG "$DEPLOY_UNIFI_CORE_CONFIG" + _savedeployconf DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" + + return 0 } diff --git a/dnsapi/dns_arvan.sh b/dnsapi/dns_arvan.sh index ca1f56c7..4c9217e5 100644 --- a/dnsapi/dns_arvan.sh +++ b/dnsapi/dns_arvan.sh @@ -1,10 +1,9 @@ #!/usr/bin/env sh -#Arvan_Token="xxxx" +#Arvan_Token="Apikey xxxx" ARVAN_API_URL="https://napi.arvancloud.com/cdn/4.0/domains" - -#Author: Ehsan Aliakbar +#Author: Vahid Fardi #Report Bugs here: https://github.com/Neilpang/acme.sh # ######## Public functions ##################### @@ -38,6 +37,7 @@ dns_arvan_add() { _info "Adding record" if _arvan_rest POST "$_domain/dns-records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":{\"text\":\"$txtvalue\"},\"ttl\":120}"; then if _contains "$response" "$txtvalue"; then + _info "response id is $response" _info "Added, OK" return 0 elif _contains "$response" "Record Data is Duplicated"; then @@ -49,7 +49,7 @@ dns_arvan_add() { fi fi _err "Add txt record error." - return 1 + return 0 } #Usage: fulldomain txtvalue @@ -73,33 +73,21 @@ dns_arvan_rm() { _debug _domain "$_domain" _debug "Getting txt records" - shorted_txtvalue=$(printf "%s" "$txtvalue" | cut -d "-" -d "_" -f1) - _arvan_rest GET "${_domain}/dns-records?search=$shorted_txtvalue" - + _arvan_rest GET "${_domain}/dns-records" if ! printf "%s" "$response" | grep \"current_page\":1 >/dev/null; then _err "Error on Arvan Api" _err "Please create a github issue with debbug log" return 1 fi - count=$(printf "%s\n" "$response" | _egrep_o "\"total\":[^,]*" | cut -d : -f 2) - _debug count "$count" - if [ "$count" = "0" ]; then - _info "Don't need to remove." - else - record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1) - _debug "record_id" "$record_id" - if [ -z "$record_id" ]; then - _err "Can not get record id to remove." - return 1 - fi - if ! _arvan_rest "DELETE" "${_domain}/dns-records/$record_id"; then - _err "Delete record error." - return 1 - fi - _debug "$response" - _contains "$response" 'dns record deleted' + _record_id=$(echo "$response" | _egrep_o ".\"id\":\"[^\"]*\",\"type\":\"txt\",\"name\":\"_acme-challenge\",\"value\":{\"text\":\"$txtvalue\"}" | cut -d : -f 2 | cut -d , -f 1 | tr -d \") + if ! _arvan_rest "DELETE" "${_domain}/dns-records/${_record_id}"; then + _err "Error on Arvan Api" + return 1 fi + _debug "$response" + _contains "$response" 'dns record deleted' + return 0 } #################### Private functions below ################################## @@ -111,7 +99,7 @@ dns_arvan_rm() { # _domain_id=sdjkglgdfewsdfg _get_root() { domain=$1 - i=1 + i=2 p=1 while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) @@ -121,12 +109,11 @@ _get_root() { return 1 fi - if ! _arvan_rest GET "?search=$h"; then + if ! _arvan_rest GET "$h"; then return 1 fi - - if _contains "$response" "\"domain\":\"$h\"" || _contains "$response" '"total":1'; then - _domain_id=$(echo "$response" | _egrep_o "\[.\"id\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \") + if _contains "$response" "\"domain\":\"$h\""; then + _domain_id=$(echo "$response" | cut -d : -f 3 | cut -d , -f 1 | tr -d \") if [ "$_domain_id" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain=$h @@ -146,7 +133,6 @@ _arvan_rest() { data="$3" token_trimmed=$(echo "$Arvan_Token" | tr -d '"') - export _H1="Authorization: $token_trimmed" if [ "$mtd" = "DELETE" ]; then @@ -160,4 +146,5 @@ _arvan_rest() { else response="$(_get "$ARVAN_API_URL/$ep$data")" fi + return 0 } diff --git a/dnsapi/dns_dp.sh b/dnsapi/dns_dp.sh index 033fa5aa..9b8b7a8b 100755 --- a/dnsapi/dns_dp.sh +++ b/dnsapi/dns_dp.sh @@ -89,7 +89,7 @@ add_record() { _info "Adding record" - if ! _rest POST "Record.Create" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=默认"; then + if ! _rest POST "Record.Create" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=%E9%BB%98%E8%AE%A4"; then return 1 fi diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index 618e12c6..d6e1dbdc 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -12,7 +12,7 @@ DuckDNS_API="https://www.duckdns.org/update" -######## Public functions ##################### +######## Public functions ###################### #Usage: dns_duckdns_add _acme-challenge.domain.duckdns.org "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_duckdns_add() { @@ -112,7 +112,7 @@ _duckdns_rest() { param="$2" _debug param "$param" url="$DuckDNS_API?$param" - if [ "$DEBUG" -gt 0 ]; then + if [ -n "$DEBUG" ] && [ "$DEBUG" -gt 0 ]; then url="$url&verbose=true" fi _debug url "$url" @@ -121,7 +121,7 @@ _duckdns_rest() { if [ "$method" = "GET" ]; then response="$(_get "$url")" _debug2 response "$response" - if [ "$DEBUG" -gt 0 ] && _contains "$response" "UPDATED" && _contains "$response" "OK"; then + if [ -n "$DEBUG" ] && [ "$DEBUG" -gt 0 ] && _contains "$response" "UPDATED" && _contains "$response" "OK"; then response="OK" fi else diff --git a/dnsapi/dns_huaweicloud.sh b/dnsapi/dns_huaweicloud.sh index 74fec2a9..f7192725 100644 --- a/dnsapi/dns_huaweicloud.sh +++ b/dnsapi/dns_huaweicloud.sh @@ -5,7 +5,7 @@ # HUAWEICLOUD_ProjectID iam_api="https://iam.myhuaweicloud.com" -dns_api="https://dns.ap-southeast-1.myhuaweicloud.com" +dns_api="https://dns.ap-southeast-1.myhuaweicloud.com" # Should work ######## Public functions ##################### @@ -29,16 +29,27 @@ dns_huaweicloud_add() { return 1 fi + unset token # Clear token token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_ProjectID}")" - _debug2 "${token}" + if [ -z "${token}" ]; then # Check token + _err "dns_api(dns_huaweicloud): Error getting token." + return 1 + fi + _debug "Access token is: ${token}" + + unset zoneid zoneid="$(_get_zoneid "${token}" "${fulldomain}")" - _debug "${zoneid}" + if [ -z "${zoneid}" ]; then + _err "dns_api(dns_huaweicloud): Error getting zone id." + return 1 + fi + _debug "Zone ID is: ${zoneid}" _debug "Adding Record" _add_record "${token}" "${fulldomain}" "${txtvalue}" ret="$?" if [ "${ret}" != "0" ]; then - _err "dns_huaweicloud: Error adding record." + _err "dns_api(dns_huaweicloud): Error adding record." return 1 fi @@ -69,12 +80,21 @@ dns_huaweicloud_rm() { return 1 fi + unset token # Clear token token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_ProjectID}")" - _debug2 "${token}" + if [ -z "${token}" ]; then # Check token + _err "dns_api(dns_huaweicloud): Error getting token." + return 1 + fi + _debug "Access token is: ${token}" + + unset zoneid zoneid="$(_get_zoneid "${token}" "${fulldomain}")" - _debug "${zoneid}" - record_id="$(_get_recordset_id "${token}" "${fulldomain}" "${zoneid}")" - _debug "Record Set ID is: ${record_id}" + if [ -z "${zoneid}" ]; then + _err "dns_api(dns_huaweicloud): Error getting zone id." + return 1 + fi + _debug "Zone ID is: ${zoneid}" # Remove all records # Therotically HuaweiCloud does not allow more than one record set diff --git a/dnsapi/dns_ionos.sh b/dnsapi/dns_ionos.sh index e6bd5000..aaf8580f 100755 --- a/dnsapi/dns_ionos.sh +++ b/dnsapi/dns_ionos.sh @@ -24,20 +24,9 @@ dns_ionos_add() { return 1 fi - _new_record="{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}" + _body="[{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}]" - # As no POST route is supported by the API, check for existing records and include them in the PATCH request in order not delete them. - # This is required to support ACME v2 wildcard certificate creation, where two TXT records for the same domain name are created. - - _ionos_get_existing_records "$fulldomain" "$_zone_id" - - if [ "$_existing_records" ]; then - _body="[$_new_record,$_existing_records]" - else - _body="[$_new_record]" - fi - - if _ionos_rest PATCH "$IONOS_ROUTE_ZONES/$_zone_id" "$_body" && [ -z "$response" ]; then + if _ionos_rest POST "$IONOS_ROUTE_ZONES/$_zone_id/records" "$_body" && [ -z "$response" ]; then _info "TXT record has been created successfully." return 0 fi @@ -125,17 +114,6 @@ _get_root() { return 1 } -_ionos_get_existing_records() { - fulldomain=$1 - zone_id=$2 - - if _ionos_rest GET "$IONOS_ROUTE_ZONES/$zone_id?recordName=$fulldomain&recordType=TXT"; then - response="$(echo "$response" | tr -d "\n")" - - _existing_records="$(printf "%s\n" "$response" | _egrep_o "\"records\":\[.*\]" | _head_n 1 | cut -d '[' -f 2 | sed 's/]//')" - fi -} - _ionos_get_record() { fulldomain=$1 zone_id=$2 @@ -168,7 +146,7 @@ _ionos_rest() { export _H2="Accept: application/json" export _H3="Content-Type: application/json" - response="$(_post "$data" "$IONOS_API$route" "" "$method")" + response="$(_post "$data" "$IONOS_API$route" "" "$method" "application/json")" else export _H2="Accept: */*" diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index 7ce39fa9..d15d6b0e 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -208,7 +208,7 @@ _namecheap_parse_host() { _hostid=$(echo "$_host" | _egrep_o ' HostId="[^"]*' | cut -d '"' -f 2) _hostname=$(echo "$_host" | _egrep_o ' Name="[^"]*' | cut -d '"' -f 2) _hosttype=$(echo "$_host" | _egrep_o ' Type="[^"]*' | cut -d '"' -f 2) - _hostaddress=$(echo "$_host" | _egrep_o ' Address="[^"]*' | cut -d '"' -f 2) + _hostaddress=$(echo "$_host" | _egrep_o ' Address="[^"]*' | cut -d '"' -f 2 | _xml_decode) _hostmxpref=$(echo "$_host" | _egrep_o ' MXPref="[^"]*' | cut -d '"' -f 2) _hostttl=$(echo "$_host" | _egrep_o ' TTL="[^"]*' | cut -d '"' -f 2) @@ -405,3 +405,7 @@ _namecheap_set_tld_sld() { done } + +_xml_decode() { + sed 's/"/"/g' +} diff --git a/dnsapi/dns_pdns.sh b/dnsapi/dns_pdns.sh index 8f07e8c4..28b35492 100755 --- a/dnsapi/dns_pdns.sh +++ b/dnsapi/dns_pdns.sh @@ -175,13 +175,13 @@ _get_root() { i=1 if _pdns_rest "GET" "/api/v1/servers/$PDNS_ServerId/zones"; then - _zones_response="$response" + _zones_response=$(echo "$response" | _normalizeJson) fi while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) - if _contains "$_zones_response" "\"name\": \"$h.\""; then + if _contains "$_zones_response" "\"name\":\"$h.\""; then _domain="$h." if [ -z "$h" ]; then _domain="=2E" diff --git a/dnsapi/dns_porkbun.sh b/dnsapi/dns_porkbun.sh new file mode 100644 index 00000000..18da6b2f --- /dev/null +++ b/dnsapi/dns_porkbun.sh @@ -0,0 +1,157 @@ +#!/usr/bin/env sh + +# +#PORKBUN_API_KEY="pk1_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" +#PORKBUN_SECRET_API_KEY="sk1_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + +PORKBUN_Api="https://porkbun.com/api/json/v3" + +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_porkbun_add() { + fulldomain=$1 + txtvalue=$2 + + PORKBUN_API_KEY="${PORKBUN_API_KEY:-$(_readaccountconf_mutable PORKBUN_API_KEY)}" + PORKBUN_SECRET_API_KEY="${PORKBUN_SECRET_API_KEY:-$(_readaccountconf_mutable PORKBUN_SECRET_API_KEY)}" + + if [ -z "$PORKBUN_API_KEY" ] || [ -z "$PORKBUN_SECRET_API_KEY" ]; then + PORKBUN_API_KEY='' + PORKBUN_SECRET_API_KEY='' + _err "You didn't specify a Porkbun api key and secret api key yet." + _err "You can get yours from here https://porkbun.com/account/api." + return 1 + fi + + #save the credentials to the account conf file. + _saveaccountconf_mutable PORKBUN_API_KEY "$PORKBUN_API_KEY" + _saveaccountconf_mutable PORKBUN_SECRET_API_KEY "$PORKBUN_SECRET_API_KEY" + + _debug 'First detect the root zone' + if ! _get_root "$fulldomain"; then + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + # For wildcard cert, the main root domain and the wildcard domain have the same txt subdomain name, so + # we can not use updating anymore. + # count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2) + # _debug count "$count" + # if [ "$count" = "0" ]; then + _info "Adding record" + if _porkbun_rest POST "dns/create/$_domain" "{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":120}"; then + if _contains "$response" '\"status\":"SUCCESS"'; then + _info "Added, OK" + return 0 + elif _contains "$response" "The record already exists"; then + _info "Already exists, OK" + return 0 + else + _err "Add txt record error. ($response)" + return 1 + fi + fi + _err "Add txt record error." + return 1 + +} + +#fulldomain txtvalue +dns_porkbun_rm() { + fulldomain=$1 + txtvalue=$2 + + PORKBUN_API_KEY="${PORKBUN_API_KEY:-$(_readaccountconf_mutable PORKBUN_API_KEY)}" + PORKBUN_SECRET_API_KEY="${PORKBUN_SECRET_API_KEY:-$(_readaccountconf_mutable PORKBUN_SECRET_API_KEY)}" + + _debug 'First detect the root zone' + if ! _get_root "$fulldomain"; then + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + count=$(echo "$response" | _egrep_o "\"count\": *[^,]*" | cut -d : -f 2 | tr -d " ") + _debug count "$count" + if [ "$count" = "0" ]; then + _info "Don't need to remove." + else + record_id=$(echo "$response" | tr '{' '\n' | grep "$txtvalue" | cut -d, -f1 | cut -d: -f2 | tr -d \") + _debug "record_id" "$record_id" + if [ -z "$record_id" ]; then + _err "Can not get record id to remove." + return 1 + fi + if ! _porkbun_rest POST "dns/delete/$_domain/$record_id"; then + _err "Delete record error." + return 1 + fi + echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null + fi + +} + +#################### Private functions below ################################## +#_acme-challenge.www.domain.com +#returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +_get_root() { + domain=$1 + i=1 + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug h "$h" + if [ -z "$h" ]; then + return 1 + fi + + if _porkbun_rest POST "dns/retrieve/$h"; then + if _contains "$response" "\"status\":\"SUCCESS\""; then + _sub_domain="$(echo "$fulldomain" | sed "s/\\.$_domain\$//")" + _domain=$h + return 0 + else + _debug "Go to next level of $_domain" + fi + else + _debug "Go to next level of $_domain" + fi + i=$(_math "$i" + 1) + done + + return 1 +} + +_porkbun_rest() { + m=$1 + ep="$2" + data="$3" + _debug "$ep" + + api_key_trimmed=$(echo "$PORKBUN_API_KEY" | tr -d '"') + secret_api_key_trimmed=$(echo "$PORKBUN_SECRET_API_KEY" | tr -d '"') + + test -z "$data" && data="{" || data="$(echo $data | cut -d'}' -f1)," + data="$data\"apikey\":\"$api_key_trimmed\",\"secretapikey\":\"$secret_api_key_trimmed\"}" + + export _H1="Content-Type: application/json" + + if [ "$m" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$PORKBUN_Api/$ep" "" "$m")" + else + response="$(_get "$PORKBUN_Api/$ep")" + fi + + _sleep 3 # prevent rate limit + + if [ "$?" != "0" ]; then + _err "error $ep" + return 1 + fi + _debug2 response "$response" + return 0 +} diff --git a/dnsapi/dns_servercow.sh b/dnsapi/dns_servercow.sh index e73d85b0..f70a2294 100755 --- a/dnsapi/dns_servercow.sh +++ b/dnsapi/dns_servercow.sh @@ -49,16 +49,42 @@ dns_servercow_add() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then - if printf -- "%s" "$response" | grep "ok" >/dev/null; then - _info "Added, OK" - return 0 - else - _err "add txt record error." - return 1 + # check whether a txt record already exists for the subdomain + if printf -- "%s" "$response" | grep "{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\"" >/dev/null; then + _info "A txt record with the same name already exists." + # trim the string on the left + txtvalue_old=${response#*{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\",\"content\":\"} + # trim the string on the right + txtvalue_old=${txtvalue_old%%\"*} + + _debug txtvalue_old "$txtvalue_old" + + _info "Add the new txtvalue to the existing txt record." + if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":[\"$txtvalue\",\"$txtvalue_old\"],\"ttl\":20}"; then + if printf -- "%s" "$response" | grep "ok" >/dev/null; then + _info "Added additional txtvalue, OK" + return 0 + else + _err "add txt record error." + return 1 + fi fi + _err "add txt record error." + return 1 + else + _info "There is no txt record with the name yet." + if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then + if printf -- "%s" "$response" | grep "ok" >/dev/null; then + _info "Added, OK" + return 0 + else + _err "add txt record error." + return 1 + fi + fi + _err "add txt record error." + return 1 fi - _err "add txt record error." return 1 } diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index d053dcf6..e0e05017 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -6,9 +6,11 @@ #SIMPLY_ApiKey="apikey" # #SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]" - SIMPLY_Api_Default="https://api.simply.com/1" +#This is used for determining success of REST call +SIMPLY_SUCCESS_CODE='"status": 200' + ######## Public functions ##################### #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_simply_add() { @@ -171,7 +173,7 @@ _get_root() { return 1 fi - if _contains "$response" '"code":"NOT_FOUND"'; then + if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then _debug "$h not found" else _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) @@ -196,6 +198,12 @@ _simply_add_record() { return 1 fi + if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then + _err "Call to API not sucessfull, see below message for more details" + _err "$response" + return 1 + fi + return 0 } @@ -211,6 +219,12 @@ _simply_delete_record() { return 1 fi + if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then + _err "Call to API not sucessfull, see below message for more details" + _err "$response" + return 1 + fi + return 0 } diff --git a/notify/smtp.sh b/notify/smtp.sh index 6aa37ca3..293c665e 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -2,14 +2,398 @@ # support smtp +# Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3358 + +# This implementation uses either curl or Python (3 or 2.7). +# (See also the "mail" notify hook, which supports other ways to send mail.) + +# SMTP_FROM="from@example.com" # required +# SMTP_TO="to@example.com" # required +# SMTP_HOST="smtp.example.com" # required +# SMTP_PORT="25" # defaults to 25, 465 or 587 depending on SMTP_SECURE +# SMTP_SECURE="tls" # one of "none", "ssl" (implicit TLS, TLS Wrapper), "tls" (explicit TLS, STARTTLS) +# SMTP_USERNAME="" # set if SMTP server requires login +# SMTP_PASSWORD="" # set if SMTP server requires login +# SMTP_TIMEOUT="30" # seconds for SMTP operations to timeout +# SMTP_BIN="/path/to/python_or_curl" # default finds first of python3, python2.7, python, pypy3, pypy, curl on PATH + +SMTP_SECURE_DEFAULT="tls" +SMTP_TIMEOUT_DEFAULT="30" + +# subject content statuscode smtp_send() { - _subject="$1" - _content="$2" - _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped - _debug "_subject" "$_subject" - _debug "_content" "$_content" - _debug "_statusCode" "$_statusCode" - - _err "Not implemented yet." - return 1 + SMTP_SUBJECT="$1" + SMTP_CONTENT="$2" + # UNUSED: _statusCode="$3" # 0: success, 1: error 2($RENEW_SKIP): skipped + + # Load and validate config: + SMTP_BIN="$(_readaccountconf_mutable_default SMTP_BIN)" + if [ -n "$SMTP_BIN" ] && ! _exists "$SMTP_BIN"; then + _err "SMTP_BIN '$SMTP_BIN' does not exist." + return 1 + fi + if [ -z "$SMTP_BIN" ]; then + # Look for a command that can communicate with an SMTP server. + # (Please don't add sendmail, ssmtp, mutt, mail, or msmtp here. + # Those are already handled by the "mail" notify hook.) + for cmd in python3 python2.7 python pypy3 pypy curl; do + if _exists "$cmd"; then + SMTP_BIN="$cmd" + break + fi + done + if [ -z "$SMTP_BIN" ]; then + _err "The smtp notify-hook requires curl or Python, but can't find any." + _err 'If you have one of them, define SMTP_BIN="/path/to/curl_or_python".' + _err 'Otherwise, see if you can use the "mail" notify-hook instead.' + return 1 + fi + fi + _debug SMTP_BIN "$SMTP_BIN" + _saveaccountconf_mutable_default SMTP_BIN "$SMTP_BIN" + + SMTP_FROM="$(_readaccountconf_mutable_default SMTP_FROM)" + SMTP_FROM="$(_clean_email_header "$SMTP_FROM")" + if [ -z "$SMTP_FROM" ]; then + _err "You must define SMTP_FROM as the sender email address." + return 1 + fi + if _email_has_display_name "$SMTP_FROM"; then + _err "SMTP_FROM must be only a simple email address (sender@example.com)." + _err "Change your SMTP_FROM='$SMTP_FROM' to remove the display name." + return 1 + fi + _debug SMTP_FROM "$SMTP_FROM" + _saveaccountconf_mutable_default SMTP_FROM "$SMTP_FROM" + + SMTP_TO="$(_readaccountconf_mutable_default SMTP_TO)" + SMTP_TO="$(_clean_email_header "$SMTP_TO")" + if [ -z "$SMTP_TO" ]; then + _err "You must define SMTP_TO as the recipient email address(es)." + return 1 + fi + if _email_has_display_name "$SMTP_TO"; then + _err "SMTP_TO must be only simple email addresses (to@example.com,to2@example.com)." + _err "Change your SMTP_TO='$SMTP_TO' to remove the display name(s)." + return 1 + fi + _debug SMTP_TO "$SMTP_TO" + _saveaccountconf_mutable_default SMTP_TO "$SMTP_TO" + + SMTP_HOST="$(_readaccountconf_mutable_default SMTP_HOST)" + if [ -z "$SMTP_HOST" ]; then + _err "You must define SMTP_HOST as the SMTP server hostname." + return 1 + fi + _debug SMTP_HOST "$SMTP_HOST" + _saveaccountconf_mutable_default SMTP_HOST "$SMTP_HOST" + + SMTP_SECURE="$(_readaccountconf_mutable_default SMTP_SECURE "$SMTP_SECURE_DEFAULT")" + case "$SMTP_SECURE" in + "none") smtp_port_default="25" ;; + "ssl") smtp_port_default="465" ;; + "tls") smtp_port_default="587" ;; + *) + _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." + return 1 + ;; + esac + _debug SMTP_SECURE "$SMTP_SECURE" + _saveaccountconf_mutable_default SMTP_SECURE "$SMTP_SECURE" "$SMTP_SECURE_DEFAULT" + + SMTP_PORT="$(_readaccountconf_mutable_default SMTP_PORT "$smtp_port_default")" + case "$SMTP_PORT" in + *[!0-9]*) + _err "Invalid SMTP_PORT='$SMTP_PORT'. It must be a port number." + return 1 + ;; + esac + _debug SMTP_PORT "$SMTP_PORT" + _saveaccountconf_mutable_default SMTP_PORT "$SMTP_PORT" "$smtp_port_default" + + SMTP_USERNAME="$(_readaccountconf_mutable_default SMTP_USERNAME)" + _debug SMTP_USERNAME "$SMTP_USERNAME" + _saveaccountconf_mutable_default SMTP_USERNAME "$SMTP_USERNAME" + + SMTP_PASSWORD="$(_readaccountconf_mutable_default SMTP_PASSWORD)" + _secure_debug SMTP_PASSWORD "$SMTP_PASSWORD" + _saveaccountconf_mutable_default SMTP_PASSWORD "$SMTP_PASSWORD" + + SMTP_TIMEOUT="$(_readaccountconf_mutable_default SMTP_TIMEOUT "$SMTP_TIMEOUT_DEFAULT")" + _debug SMTP_TIMEOUT "$SMTP_TIMEOUT" + _saveaccountconf_mutable_default SMTP_TIMEOUT "$SMTP_TIMEOUT" "$SMTP_TIMEOUT_DEFAULT" + + SMTP_X_MAILER="$(_clean_email_header "$PROJECT_NAME $VER --notify-hook smtp")" + + # Run with --debug 2 (or above) to echo the transcript of the SMTP session. + # Careful: this may include SMTP_PASSWORD in plaintext! + if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then + SMTP_SHOW_TRANSCRIPT="True" + else + SMTP_SHOW_TRANSCRIPT="" + fi + + SMTP_SUBJECT=$(_clean_email_header "$SMTP_SUBJECT") + _debug SMTP_SUBJECT "$SMTP_SUBJECT" + _debug SMTP_CONTENT "$SMTP_CONTENT" + + # Send the message: + case "$(basename "$SMTP_BIN")" in + curl) _smtp_send=_smtp_send_curl ;; + py*) _smtp_send=_smtp_send_python ;; + *) + _err "Can't figure out how to invoke '$SMTP_BIN'." + _err "Check your SMTP_BIN setting." + return 1 + ;; + esac + + if ! smtp_output="$($_smtp_send)"; then + _err "Error sending message with $SMTP_BIN." + if [ -n "$smtp_output" ]; then + _err "$smtp_output" + fi + return 1 + fi + + return 0 +} + +# Strip CR and NL from text to prevent MIME header injection +# text +_clean_email_header() { + printf "%s" "$(echo "$1" | tr -d "\r\n")" +} + +# Simple check for display name in an email address (< > or ") +# email +_email_has_display_name() { + _email="$1" + expr "$_email" : '^.*[<>"]' >/dev/null +} + +## +## curl smtp sending +## + +# Send the message via curl using SMTP_* variables +_smtp_send_curl() { + # Build curl args in $@ + case "$SMTP_SECURE" in + none) + set -- --url "smtp://${SMTP_HOST}:${SMTP_PORT}" + ;; + ssl) + set -- --url "smtps://${SMTP_HOST}:${SMTP_PORT}" + ;; + tls) + set -- --url "smtp://${SMTP_HOST}:${SMTP_PORT}" --ssl-reqd + ;; + *) + # This will only occur if someone adds a new SMTP_SECURE option above + # without updating this code for it. + _err "Unhandled SMTP_SECURE='$SMTP_SECURE' in _smtp_send_curl" + _err "Please re-run with --debug and report a bug." + return 1 + ;; + esac + + set -- "$@" \ + --upload-file - \ + --mail-from "$SMTP_FROM" \ + --max-time "$SMTP_TIMEOUT" + + # Burst comma-separated $SMTP_TO into individual --mail-rcpt args. + _to="${SMTP_TO}," + while [ -n "$_to" ]; do + _rcpt="${_to%%,*}" + _to="${_to#*,}" + set -- "$@" --mail-rcpt "$_rcpt" + done + + _smtp_login="${SMTP_USERNAME}:${SMTP_PASSWORD}" + if [ "$_smtp_login" != ":" ]; then + set -- "$@" --user "$_smtp_login" + fi + + if [ "$SMTP_SHOW_TRANSCRIPT" = "True" ]; then + set -- "$@" --verbose + else + set -- "$@" --silent --show-error + fi + + raw_message="$(_smtp_raw_message)" + + _debug2 "curl command:" "$SMTP_BIN" "$*" + _debug2 "raw_message:\n$raw_message" + + echo "$raw_message" | "$SMTP_BIN" "$@" +} + +# Output an RFC-822 / RFC-5322 email message using SMTP_* variables. +# (This assumes variables have already been cleaned for use in email headers.) +_smtp_raw_message() { + echo "From: $SMTP_FROM" + echo "To: $SMTP_TO" + echo "Subject: $(_mime_encoded_word "$SMTP_SUBJECT")" + echo "Date: $(_rfc2822_date)" + echo "Content-Type: text/plain; charset=utf-8" + echo "X-Mailer: $SMTP_X_MAILER" + echo + echo "$SMTP_CONTENT" +} + +# Convert text to RFC-2047 MIME "encoded word" format if it contains non-ASCII chars +# text +_mime_encoded_word() { + _text="$1" + # (regex character ranges like [a-z] can be locale-dependent; enumerate ASCII chars to avoid that) + _ascii='] $`"'"[!#%&'()*+,./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ~^_abcdefghijklmnopqrstuvwxyz{|}~-" + if expr "$_text" : "^.*[^$_ascii]" >/dev/null; then + # At least one non-ASCII char; convert entire thing to encoded word + printf "%s" "=?UTF-8?B?$(printf "%s" "$_text" | _base64)?=" + else + # Just printable ASCII, no conversion needed + printf "%s" "$_text" + fi +} + +# Output current date in RFC-2822 Section 3.3 format as required in email headers +# (e.g., "Mon, 15 Feb 2021 14:22:01 -0800") +_rfc2822_date() { + # Notes: + # - this is deliberately not UTC, because it "SHOULD express local time" per spec + # - the spec requires weekday and month in the C locale (English), not localized + # - this date format specifier has been tested on Linux, Mac, Solaris and FreeBSD + _old_lc_time="$LC_TIME" + LC_TIME=C + date +'%a, %-d %b %Y %H:%M:%S %z' + LC_TIME="$_old_lc_time" +} + +## +## Python smtp sending +## + +# Send the message via Python using SMTP_* variables +_smtp_send_python() { + _debug "Python version" "$("$SMTP_BIN" --version 2>&1)" + + # language=Python + "$SMTP_BIN" < Date: Sun, 21 Mar 2021 22:46:35 +0800 Subject: [PATCH 306/383] fix freebsd --- .github/workflows/DNS.yml | 2 +- .github/workflows/LetsEncrypt.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index ed0426ad..5ff1f8ab 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -184,7 +184,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.1.2 + - uses: vmactions/freebsd-vm@v0.1.3 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkg install -y socat curl diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 7c398c09..7193d88d 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -111,7 +111,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.1.2 + - uses: vmactions/freebsd-vm@v0.1.3 with: envs: 'NGROK_TOKEN TEST_LOCAL' prepare: pkg install -y socat curl From 8de3698b230da82f4eac2d5e04a8a754d8d92faa Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Sun, 21 Mar 2021 16:16:38 +0100 Subject: [PATCH 307/383] Revert "Syncing with the original repo (#2)" This reverts commit c384ed960c138f4449e79293644c4d0ec937cef1. --- .github/workflows/DNS.yml | 4 +- .github/workflows/LetsEncrypt.yml | 4 +- acme.sh | 98 ++------ deploy/unifi.sh | 220 ++++------------ dnsapi/dns_arvan.sh | 47 ++-- dnsapi/dns_dp.sh | 2 +- dnsapi/dns_duckdns.sh | 6 +- dnsapi/dns_huaweicloud.sh | 36 +-- dnsapi/dns_ionos.sh | 28 ++- dnsapi/dns_namecheap.sh | 6 +- dnsapi/dns_pdns.sh | 4 +- dnsapi/dns_porkbun.sh | 157 ------------ dnsapi/dns_servercow.sh | 42 +--- dnsapi/dns_simply.sh | 18 +- notify/smtp.sh | 402 +----------------------------- 15 files changed, 162 insertions(+), 912 deletions(-) delete mode 100644 dnsapi/dns_porkbun.sh diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index ed0426ad..5dc2d453 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -184,7 +184,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.1.2 + - uses: vmactions/freebsd-vm@v0.0.7 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkg install -y socat curl @@ -223,7 +223,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/solaris-vm@v0.0.3 + - uses: vmactions/solaris-vm@v0.0.1 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkgutil -y -i socat curl diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 7c398c09..8d0c4eb0 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -111,7 +111,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.1.2 + - uses: vmactions/freebsd-vm@v0.0.7 with: envs: 'NGROK_TOKEN TEST_LOCAL' prepare: pkg install -y socat curl @@ -136,7 +136,7 @@ jobs: run: echo "TestingDomain=${{steps.ngrok.outputs.server}}" >> $GITHUB_ENV - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/solaris-vm@v0.0.3 + - uses: vmactions/solaris-vm@v0.0.1 with: envs: 'TEST_LOCAL TestingDomain' nat: | diff --git a/acme.sh b/acme.sh index 8d422719..a1ad4195 100755 --- a/acme.sh +++ b/acme.sh @@ -562,16 +562,8 @@ if _exists xargs && [ "$(printf %s '\\x41' | xargs printf)" = 'A' ]; then fi _h2b() { - if _exists xxd; then - if _contains "$(xxd --help 2>&1)" "assumes -c30"; then - if xxd -r -p -c 9999 2>/dev/null; then - return - fi - else - if xxd -r -p 2>/dev/null; then - return - fi - fi + if _exists xxd && xxd -r -p 2>/dev/null; then + return fi hex=$(cat) @@ -1132,7 +1124,7 @@ _createkey() { if _isEccKey "$length"; then _debug "Using ec name: $eccname" - if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -noout -genkey 2>/dev/null)"; then + if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -genkey 2>/dev/null)"; then echo "$_opkey" >"$f" else _err "error ecc key name: $eccname" @@ -1140,11 +1132,7 @@ _createkey() { fi else _debug "Using RSA: $length" - __traditional="" - if _contains "$(${ACME_OPENSSL_BIN:-openssl} help genrsa 2>&1)" "-traditional"; then - __traditional="-traditional" - fi - if _opkey="$(${ACME_OPENSSL_BIN:-openssl} genrsa $__traditional "$length" 2>/dev/null)"; then + if _opkey="$(${ACME_OPENSSL_BIN:-openssl} genrsa "$length" 2>/dev/null)"; then echo "$_opkey" >"$f" else _err "error rsa key: $length" @@ -2133,12 +2121,6 @@ _send_signed_request() { _sleep $_sleep_retry_sec continue fi - if _contains "$_body" "The Replay Nonce is not recognized"; then - _info "The replay Nonce is not valid, let's get a new one, Sleeping $_sleep_retry_sec seconds." - _CACHED_NONCE="" - _sleep $_sleep_retry_sec - continue - fi fi return 0 done @@ -2297,13 +2279,6 @@ _clearaccountconf() { _clear_conf "$ACCOUNT_CONF_PATH" "$1" } -#key -_clearaccountconf_mutable() { - _clearaccountconf "SAVED_$1" - #remove later - _clearaccountconf "$1" -} - #_savecaconf key value _savecaconf() { _save_conf "$CA_CONF" "$1" "$2" @@ -4034,42 +4009,12 @@ _check_dns_entries() { } #file -_get_chain_issuers() { +_get_cert_issuers() { _cfile="$1" - if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -help 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then - ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep -i 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 + if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then + ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 else - _cindex=1 - for _startn in $(grep -n -- "$BEGIN_CERT" "$_cfile" | cut -d : -f 1); do - _endn="$(grep -n -- "$END_CERT" "$_cfile" | cut -d : -f 1 | _head_n $_cindex | _tail_n 1)" - _debug2 "_startn" "$_startn" - _debug2 "_endn" "$_endn" - if [ "$DEBUG" ]; then - _debug2 "cert$_cindex" "$(sed -n "$_startn,${_endn}p" "$_cfile")" - fi - sed -n "$_startn,${_endn}p" "$_cfile" | ${ACME_OPENSSL_BIN:-openssl} x509 -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 | sed "s/ *\(.*\)/\1/" - _cindex=$(_math $_cindex + 1) - done - fi -} - -# -_get_chain_subjects() { - _cfile="$1" - if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -help 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then - ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep -i 'Subject:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 - else - _cindex=1 - for _startn in $(grep -n -- "$BEGIN_CERT" "$_cfile" | cut -d : -f 1); do - _endn="$(grep -n -- "$END_CERT" "$_cfile" | cut -d : -f 1 | _head_n $_cindex | _tail_n 1)" - _debug2 "_startn" "$_startn" - _debug2 "_endn" "$_endn" - if [ "$DEBUG" ]; then - _debug2 "cert$_cindex" "$(sed -n "$_startn,${_endn}p" "$_cfile")" - fi - sed -n "$_startn,${_endn}p" "$_cfile" | ${ACME_OPENSSL_BIN:-openssl} x509 -text -noout | grep -i 'Subject:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 | sed "s/ *\(.*\)/\1/" - _cindex=$(_math $_cindex + 1) - done + ${ACME_OPENSSL_BIN:-openssl} x509 -in $_cfile -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 fi } @@ -4077,12 +4022,14 @@ _get_chain_subjects() { _match_issuer() { _cfile="$1" _missuer="$2" - _fissuers="$(_get_chain_issuers $_cfile)" + _fissuers="$(_get_cert_issuers $_cfile)" _debug2 _fissuers "$_fissuers" - _rootissuer="$(echo "$_fissuers" | _lower_case | _tail_n 1)" - _debug2 _rootissuer "$_rootissuer" + if _contains "$_fissuers" "$_missuer"; then + return 0 + fi + _fissuers="$(echo "$_fissuers" | _lower_case)" _missuer="$(echo "$_missuer" | _lower_case)" - _contains "$_rootissuer" "$_missuer" + _contains "$_fissuers" "$_missuer" } #webroot, domain domainlist keylength @@ -4856,9 +4803,6 @@ $_authorizations_map" _split_cert_chain "$CERT_PATH" "$CERT_FULLCHAIN_PATH" "$CA_CERT_PATH" if [ "$_preferred_chain" ] && [ -f "$CERT_FULLCHAIN_PATH" ]; then - if [ "$DEBUG" ]; then - _debug "default chain issuers: " "$(_get_chain_issuers "$CERT_FULLCHAIN_PATH")" - fi if ! _match_issuer "$CERT_FULLCHAIN_PATH" "$_preferred_chain"; then rels="$(echo "$responseHeaders" | tr -d ' <>' | grep -i "^link:" | grep -i 'rel="alternate"' | cut -d : -f 2- | cut -d ';' -f 1)" _debug2 "rels" "$rels" @@ -4874,22 +4818,13 @@ $_authorizations_map" _relca="$CA_CERT_PATH.alt" echo "$response" >"$_relcert" _split_cert_chain "$_relcert" "$_relfullchain" "$_relca" - if [ "$DEBUG" ]; then - _debug "rel chain issuers: " "$(_get_chain_issuers "$_relfullchain")" - fi if _match_issuer "$_relfullchain" "$_preferred_chain"; then _info "Matched issuer in: $rel" cat $_relcert >"$CERT_PATH" cat $_relfullchain >"$CERT_FULLCHAIN_PATH" cat $_relca >"$CA_CERT_PATH" - rm -f "$_relcert" - rm -f "$_relfullchain" - rm -f "$_relca" break fi - rm -f "$_relcert" - rm -f "$_relfullchain" - rm -f "$_relca" done fi fi @@ -5287,7 +5222,6 @@ signcsr() { _renew_hook="${10}" _local_addr="${11}" _challenge_alias="${12}" - _preferred_chain="${13}" _csrsubj=$(_readSubjectFromCSR "$_csrfile") if [ "$?" != "0" ]; then @@ -5334,7 +5268,7 @@ signcsr() { _info "Copy csr to: $CSR_PATH" cp "$_csrfile" "$CSR_PATH" - issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_addr" "$_challenge_alias" "$_preferred_chain" + issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_addr" "$_challenge_alias" } @@ -7431,7 +7365,7 @@ _process() { deploy "$_domain" "$_deploy_hook" "$_ecc" ;; signcsr) - signcsr "$_csr" "$_webroot" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" "$_preferred_chain" + signcsr "$_csr" "$_webroot" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" ;; showcsr) showcsr "$_csr" "$_domain" diff --git a/deploy/unifi.sh b/deploy/unifi.sh index a864135e..184aa62e 100644 --- a/deploy/unifi.sh +++ b/deploy/unifi.sh @@ -1,43 +1,12 @@ #!/usr/bin/env sh -# Here is a script to deploy cert on a Unifi Controller or Cloud Key device. -# It supports: -# - self-hosted Unifi Controller -# - Unifi Cloud Key (Gen1/2/2+) -# - Unifi Cloud Key running UnifiOS (v2.0.0+, Gen2/2+ only) -# Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3359 +#Here is a script to deploy cert to unifi server. #returns 0 means success, otherwise error. -# The deploy-hook automatically detects standard Unifi installations -# for each of the supported environments. Most users should not need -# to set any of these variables, but if you are running a self-hosted -# Controller with custom locations, set these as necessary before running -# the deploy hook. (Defaults shown below.) -# -# Settings for Unifi Controller: -# Location of Java keystore or unifi.keystore.jks file: #DEPLOY_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore" -# Keystore password (built into Unifi Controller, not a user-set password): #DEPLOY_UNIFI_KEYPASS="aircontrolenterprise" -# Command to restart Unifi Controller: #DEPLOY_UNIFI_RELOAD="service unifi restart" -# -# Settings for Unifi Cloud Key Gen1 (nginx admin pages): -# Directory where cloudkey.crt and cloudkey.key live: -#DEPLOY_UNIFI_CLOUDKEY_CERTDIR="/etc/ssl/private" -# Command to restart maintenance pages and Controller -# (same setting as above, default is updated when running on Cloud Key Gen1): -#DEPLOY_UNIFI_RELOAD="service nginx restart && service unifi restart" -# -# Settings for UnifiOS (Cloud Key Gen2): -# Directory where unifi-core.crt and unifi-core.key live: -#DEPLOY_UNIFI_CORE_CONFIG="/data/unifi-core/config/" -# Command to restart unifi-core: -#DEPLOY_UNIFI_RELOAD="systemctl restart unifi-core" -# -# At least one of DEPLOY_UNIFI_KEYSTORE, DEPLOY_UNIFI_CLOUDKEY_CERTDIR, -# or DEPLOY_UNIFI_CORE_CONFIG must exist to receive the deployed certs. ######## Public functions ##################### @@ -55,160 +24,77 @@ unifi_deploy() { _debug _cca "$_cca" _debug _cfullchain "$_cfullchain" - _getdeployconf DEPLOY_UNIFI_KEYSTORE - _getdeployconf DEPLOY_UNIFI_KEYPASS - _getdeployconf DEPLOY_UNIFI_CLOUDKEY_CERTDIR - _getdeployconf DEPLOY_UNIFI_CORE_CONFIG - _getdeployconf DEPLOY_UNIFI_RELOAD - - _debug2 DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" - _debug2 DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" - _debug2 DEPLOY_UNIFI_CLOUDKEY_CERTDIR "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" - _debug2 DEPLOY_UNIFI_CORE_CONFIG "$DEPLOY_UNIFI_CORE_CONFIG" - _debug2 DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" - - # Space-separated list of environments detected and installed: - _services_updated="" - - # Default reload commands accumulated as we auto-detect environments: - _reload_cmd="" - - # Unifi Controller environment (self hosted or any Cloud Key) -- - # auto-detect by file /usr/lib/unifi/data/keystore: - _unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-/usr/lib/unifi/data/keystore}" - if [ -f "$_unifi_keystore" ]; then - _info "Installing certificate for Unifi Controller (Java keystore)" - _debug _unifi_keystore "$_unifi_keystore" - if ! _exists keytool; then - _err "keytool not found" - return 1 - fi - if [ ! -w "$_unifi_keystore" ]; then - _err "The file $_unifi_keystore is not writable, please change the permission." - return 1 - fi - - _unifi_keypass="${DEPLOY_UNIFI_KEYPASS:-aircontrolenterprise}" - - _debug "Generate import pkcs12" - _import_pkcs12="$(_mktemp)" - _toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root - # shellcheck disable=SC2181 - if [ "$?" != "0" ]; then - _err "Error generating pkcs12. Please re-run with --debug and report a bug." - return 1 - fi - - _debug "Import into keystore: $_unifi_keystore" - if keytool -importkeystore \ - -deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \ - -srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \ - -alias unifi -noprompt; then - _debug "Import keystore success!" - rm "$_import_pkcs12" - else - _err "Error importing into Unifi Java keystore." - _err "Please re-run with --debug and report a bug." - rm "$_import_pkcs12" - return 1 - fi - - if systemctl -q is-active unifi; then - _reload_cmd="${_reload_cmd:+$_reload_cmd && }service unifi restart" - fi - _services_updated="${_services_updated} unifi" - _info "Install Unifi Controller certificate success!" - elif [ "$DEPLOY_UNIFI_KEYSTORE" ]; then - _err "The specified DEPLOY_UNIFI_KEYSTORE='$DEPLOY_UNIFI_KEYSTORE' is not valid, please check." + if ! _exists keytool; then + _err "keytool not found" return 1 fi - # Cloud Key environment (non-UnifiOS -- nginx serves admin pages) -- - # auto-detect by file /etc/ssl/private/cloudkey.key: - _cloudkey_certdir="${DEPLOY_UNIFI_CLOUDKEY_CERTDIR:-/etc/ssl/private}" - if [ -f "${_cloudkey_certdir}/cloudkey.key" ]; then - _info "Installing certificate for Cloud Key Gen1 (nginx admin pages)" - _debug _cloudkey_certdir "$_cloudkey_certdir" - if [ ! -w "$_cloudkey_certdir" ]; then - _err "The directory $_cloudkey_certdir is not writable; please check permissions." + DEFAULT_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore" + _unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-$DEFAULT_UNIFI_KEYSTORE}" + DEFAULT_UNIFI_KEYPASS="aircontrolenterprise" + _unifi_keypass="${DEPLOY_UNIFI_KEYPASS:-$DEFAULT_UNIFI_KEYPASS}" + DEFAULT_UNIFI_RELOAD="service unifi restart" + _reload="${DEPLOY_UNIFI_RELOAD:-$DEFAULT_UNIFI_RELOAD}" + + _debug _unifi_keystore "$_unifi_keystore" + if [ ! -f "$_unifi_keystore" ]; then + if [ -z "$DEPLOY_UNIFI_KEYSTORE" ]; then + _err "unifi keystore is not found, please define DEPLOY_UNIFI_KEYSTORE" return 1 - fi - # Cloud Key expects to load the keystore from /etc/ssl/private/unifi.keystore.jks. - # Normally /usr/lib/unifi/data/keystore is a symlink there (so the keystore was - # updated above), but if not, we don't know how to handle this installation: - if ! cmp -s "$_unifi_keystore" "${_cloudkey_certdir}/unifi.keystore.jks"; then - _err "Unsupported Cloud Key configuration: keystore not found at '${_cloudkey_certdir}/unifi.keystore.jks'" + else + _err "It seems that the specified unifi keystore is not valid, please check." return 1 fi - - cat "$_cfullchain" >"${_cloudkey_certdir}/cloudkey.crt" - cat "$_ckey" >"${_cloudkey_certdir}/cloudkey.key" - (cd "$_cloudkey_certdir" && tar -cf cert.tar cloudkey.crt cloudkey.key unifi.keystore.jks) - - if systemctl -q is-active nginx; then - _reload_cmd="${_reload_cmd:+$_reload_cmd && }service nginx restart" - fi - _info "Install Cloud Key Gen1 certificate success!" - _services_updated="${_services_updated} nginx" - elif [ "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" ]; then - _err "The specified DEPLOY_UNIFI_CLOUDKEY_CERTDIR='$DEPLOY_UNIFI_CLOUDKEY_CERTDIR' is not valid, please check." - return 1 fi - - # UnifiOS environment -- auto-detect by /data/unifi-core/config/unifi-core.key: - _unifi_core_config="${DEPLOY_UNIFI_CORE_CONFIG:-/data/unifi-core/config}" - if [ -f "${_unifi_core_config}/unifi-core.key" ]; then - _info "Installing certificate for UnifiOS" - _debug _unifi_core_config "$_unifi_core_config" - if [ ! -w "$_unifi_core_config" ]; then - _err "The directory $_unifi_core_config is not writable; please check permissions." - return 1 - fi - - cat "$_cfullchain" >"${_unifi_core_config}/unifi-core.crt" - cat "$_ckey" >"${_unifi_core_config}/unifi-core.key" - - if systemctl -q is-active unifi-core; then - _reload_cmd="${_reload_cmd:+$_reload_cmd && }systemctl restart unifi-core" - fi - _info "Install UnifiOS certificate success!" - _services_updated="${_services_updated} unifi-core" - elif [ "$DEPLOY_UNIFI_CORE_CONFIG" ]; then - _err "The specified DEPLOY_UNIFI_CORE_CONFIG='$DEPLOY_UNIFI_CORE_CONFIG' is not valid, please check." + if [ ! -w "$_unifi_keystore" ]; then + _err "The file $_unifi_keystore is not writable, please change the permission." return 1 fi - if [ -z "$_services_updated" ]; then - # None of the Unifi environments were auto-detected, so no deployment has occurred - # (and none of DEPLOY_UNIFI_{KEYSTORE,CLOUDKEY_CERTDIR,CORE_CONFIG} were set). - _err "Unable to detect Unifi environment in standard location." - _err "(This deploy hook must be run on the Unifi device, not a remote machine.)" - _err "For non-standard Unifi installations, set DEPLOY_UNIFI_KEYSTORE," - _err "DEPLOY_UNIFI_CLOUDKEY_CERTDIR, and/or DEPLOY_UNIFI_CORE_CONFIG as appropriate." + _info "Generate import pkcs12" + _import_pkcs12="$(_mktemp)" + _toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root + if [ "$?" != "0" ]; then + _err "Oops, error creating import pkcs12, please report bug to us." return 1 fi - _reload_cmd="${DEPLOY_UNIFI_RELOAD:-$_reload_cmd}" - if [ -z "$_reload_cmd" ]; then - _err "Certificates were installed for services:${_services_updated}," - _err "but none appear to be active. Please set DEPLOY_UNIFI_RELOAD" - _err "to a command that will restart the necessary services." + _info "Modify unifi keystore: $_unifi_keystore" + if keytool -importkeystore \ + -deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \ + -srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \ + -alias unifi -noprompt; then + _info "Import keystore success!" + rm "$_import_pkcs12" + else + _err "Import unifi keystore error, please report bug to us." + rm "$_import_pkcs12" return 1 fi - _info "Reload services (this may take some time): $_reload_cmd" - if eval "$_reload_cmd"; then + + _info "Run reload: $_reload" + if eval "$_reload"; then _info "Reload success!" + if [ "$DEPLOY_UNIFI_KEYSTORE" ]; then + _savedomainconf DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" + else + _cleardomainconf DEPLOY_UNIFI_KEYSTORE + fi + if [ "$DEPLOY_UNIFI_KEYPASS" ]; then + _savedomainconf DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" + else + _cleardomainconf DEPLOY_UNIFI_KEYPASS + fi + if [ "$DEPLOY_UNIFI_RELOAD" ]; then + _savedomainconf DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" + else + _cleardomainconf DEPLOY_UNIFI_RELOAD + fi + return 0 else _err "Reload error" return 1 fi - - # Successful, so save all (non-default) config: - _savedeployconf DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" - _savedeployconf DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" - _savedeployconf DEPLOY_UNIFI_CLOUDKEY_CERTDIR "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" - _savedeployconf DEPLOY_UNIFI_CORE_CONFIG "$DEPLOY_UNIFI_CORE_CONFIG" - _savedeployconf DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" - return 0 + } diff --git a/dnsapi/dns_arvan.sh b/dnsapi/dns_arvan.sh index 4c9217e5..ca1f56c7 100644 --- a/dnsapi/dns_arvan.sh +++ b/dnsapi/dns_arvan.sh @@ -1,9 +1,10 @@ #!/usr/bin/env sh -#Arvan_Token="Apikey xxxx" +#Arvan_Token="xxxx" ARVAN_API_URL="https://napi.arvancloud.com/cdn/4.0/domains" -#Author: Vahid Fardi + +#Author: Ehsan Aliakbar #Report Bugs here: https://github.com/Neilpang/acme.sh # ######## Public functions ##################### @@ -37,7 +38,6 @@ dns_arvan_add() { _info "Adding record" if _arvan_rest POST "$_domain/dns-records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":{\"text\":\"$txtvalue\"},\"ttl\":120}"; then if _contains "$response" "$txtvalue"; then - _info "response id is $response" _info "Added, OK" return 0 elif _contains "$response" "Record Data is Duplicated"; then @@ -49,7 +49,7 @@ dns_arvan_add() { fi fi _err "Add txt record error." - return 0 + return 1 } #Usage: fulldomain txtvalue @@ -73,21 +73,33 @@ dns_arvan_rm() { _debug _domain "$_domain" _debug "Getting txt records" - _arvan_rest GET "${_domain}/dns-records" + shorted_txtvalue=$(printf "%s" "$txtvalue" | cut -d "-" -d "_" -f1) + _arvan_rest GET "${_domain}/dns-records?search=$shorted_txtvalue" + if ! printf "%s" "$response" | grep \"current_page\":1 >/dev/null; then _err "Error on Arvan Api" _err "Please create a github issue with debbug log" return 1 fi - _record_id=$(echo "$response" | _egrep_o ".\"id\":\"[^\"]*\",\"type\":\"txt\",\"name\":\"_acme-challenge\",\"value\":{\"text\":\"$txtvalue\"}" | cut -d : -f 2 | cut -d , -f 1 | tr -d \") - if ! _arvan_rest "DELETE" "${_domain}/dns-records/${_record_id}"; then - _err "Error on Arvan Api" - return 1 + count=$(printf "%s\n" "$response" | _egrep_o "\"total\":[^,]*" | cut -d : -f 2) + _debug count "$count" + if [ "$count" = "0" ]; then + _info "Don't need to remove." + else + record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1) + _debug "record_id" "$record_id" + if [ -z "$record_id" ]; then + _err "Can not get record id to remove." + return 1 + fi + if ! _arvan_rest "DELETE" "${_domain}/dns-records/$record_id"; then + _err "Delete record error." + return 1 + fi + _debug "$response" + _contains "$response" 'dns record deleted' fi - _debug "$response" - _contains "$response" 'dns record deleted' - return 0 } #################### Private functions below ################################## @@ -99,7 +111,7 @@ dns_arvan_rm() { # _domain_id=sdjkglgdfewsdfg _get_root() { domain=$1 - i=2 + i=1 p=1 while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) @@ -109,11 +121,12 @@ _get_root() { return 1 fi - if ! _arvan_rest GET "$h"; then + if ! _arvan_rest GET "?search=$h"; then return 1 fi - if _contains "$response" "\"domain\":\"$h\""; then - _domain_id=$(echo "$response" | cut -d : -f 3 | cut -d , -f 1 | tr -d \") + + if _contains "$response" "\"domain\":\"$h\"" || _contains "$response" '"total":1'; then + _domain_id=$(echo "$response" | _egrep_o "\[.\"id\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \") if [ "$_domain_id" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain=$h @@ -133,6 +146,7 @@ _arvan_rest() { data="$3" token_trimmed=$(echo "$Arvan_Token" | tr -d '"') + export _H1="Authorization: $token_trimmed" if [ "$mtd" = "DELETE" ]; then @@ -146,5 +160,4 @@ _arvan_rest() { else response="$(_get "$ARVAN_API_URL/$ep$data")" fi - return 0 } diff --git a/dnsapi/dns_dp.sh b/dnsapi/dns_dp.sh index 9b8b7a8b..033fa5aa 100755 --- a/dnsapi/dns_dp.sh +++ b/dnsapi/dns_dp.sh @@ -89,7 +89,7 @@ add_record() { _info "Adding record" - if ! _rest POST "Record.Create" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=%E9%BB%98%E8%AE%A4"; then + if ! _rest POST "Record.Create" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=默认"; then return 1 fi diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index d6e1dbdc..618e12c6 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -12,7 +12,7 @@ DuckDNS_API="https://www.duckdns.org/update" -######## Public functions ###################### +######## Public functions ##################### #Usage: dns_duckdns_add _acme-challenge.domain.duckdns.org "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_duckdns_add() { @@ -112,7 +112,7 @@ _duckdns_rest() { param="$2" _debug param "$param" url="$DuckDNS_API?$param" - if [ -n "$DEBUG" ] && [ "$DEBUG" -gt 0 ]; then + if [ "$DEBUG" -gt 0 ]; then url="$url&verbose=true" fi _debug url "$url" @@ -121,7 +121,7 @@ _duckdns_rest() { if [ "$method" = "GET" ]; then response="$(_get "$url")" _debug2 response "$response" - if [ -n "$DEBUG" ] && [ "$DEBUG" -gt 0 ] && _contains "$response" "UPDATED" && _contains "$response" "OK"; then + if [ "$DEBUG" -gt 0 ] && _contains "$response" "UPDATED" && _contains "$response" "OK"; then response="OK" fi else diff --git a/dnsapi/dns_huaweicloud.sh b/dnsapi/dns_huaweicloud.sh index f7192725..74fec2a9 100644 --- a/dnsapi/dns_huaweicloud.sh +++ b/dnsapi/dns_huaweicloud.sh @@ -5,7 +5,7 @@ # HUAWEICLOUD_ProjectID iam_api="https://iam.myhuaweicloud.com" -dns_api="https://dns.ap-southeast-1.myhuaweicloud.com" # Should work +dns_api="https://dns.ap-southeast-1.myhuaweicloud.com" ######## Public functions ##################### @@ -29,27 +29,16 @@ dns_huaweicloud_add() { return 1 fi - unset token # Clear token token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_ProjectID}")" - if [ -z "${token}" ]; then # Check token - _err "dns_api(dns_huaweicloud): Error getting token." - return 1 - fi - _debug "Access token is: ${token}" - - unset zoneid + _debug2 "${token}" zoneid="$(_get_zoneid "${token}" "${fulldomain}")" - if [ -z "${zoneid}" ]; then - _err "dns_api(dns_huaweicloud): Error getting zone id." - return 1 - fi - _debug "Zone ID is: ${zoneid}" + _debug "${zoneid}" _debug "Adding Record" _add_record "${token}" "${fulldomain}" "${txtvalue}" ret="$?" if [ "${ret}" != "0" ]; then - _err "dns_api(dns_huaweicloud): Error adding record." + _err "dns_huaweicloud: Error adding record." return 1 fi @@ -80,21 +69,12 @@ dns_huaweicloud_rm() { return 1 fi - unset token # Clear token token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_ProjectID}")" - if [ -z "${token}" ]; then # Check token - _err "dns_api(dns_huaweicloud): Error getting token." - return 1 - fi - _debug "Access token is: ${token}" - - unset zoneid + _debug2 "${token}" zoneid="$(_get_zoneid "${token}" "${fulldomain}")" - if [ -z "${zoneid}" ]; then - _err "dns_api(dns_huaweicloud): Error getting zone id." - return 1 - fi - _debug "Zone ID is: ${zoneid}" + _debug "${zoneid}" + record_id="$(_get_recordset_id "${token}" "${fulldomain}" "${zoneid}")" + _debug "Record Set ID is: ${record_id}" # Remove all records # Therotically HuaweiCloud does not allow more than one record set diff --git a/dnsapi/dns_ionos.sh b/dnsapi/dns_ionos.sh index aaf8580f..e6bd5000 100755 --- a/dnsapi/dns_ionos.sh +++ b/dnsapi/dns_ionos.sh @@ -24,9 +24,20 @@ dns_ionos_add() { return 1 fi - _body="[{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}]" + _new_record="{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}" - if _ionos_rest POST "$IONOS_ROUTE_ZONES/$_zone_id/records" "$_body" && [ -z "$response" ]; then + # As no POST route is supported by the API, check for existing records and include them in the PATCH request in order not delete them. + # This is required to support ACME v2 wildcard certificate creation, where two TXT records for the same domain name are created. + + _ionos_get_existing_records "$fulldomain" "$_zone_id" + + if [ "$_existing_records" ]; then + _body="[$_new_record,$_existing_records]" + else + _body="[$_new_record]" + fi + + if _ionos_rest PATCH "$IONOS_ROUTE_ZONES/$_zone_id" "$_body" && [ -z "$response" ]; then _info "TXT record has been created successfully." return 0 fi @@ -114,6 +125,17 @@ _get_root() { return 1 } +_ionos_get_existing_records() { + fulldomain=$1 + zone_id=$2 + + if _ionos_rest GET "$IONOS_ROUTE_ZONES/$zone_id?recordName=$fulldomain&recordType=TXT"; then + response="$(echo "$response" | tr -d "\n")" + + _existing_records="$(printf "%s\n" "$response" | _egrep_o "\"records\":\[.*\]" | _head_n 1 | cut -d '[' -f 2 | sed 's/]//')" + fi +} + _ionos_get_record() { fulldomain=$1 zone_id=$2 @@ -146,7 +168,7 @@ _ionos_rest() { export _H2="Accept: application/json" export _H3="Content-Type: application/json" - response="$(_post "$data" "$IONOS_API$route" "" "$method" "application/json")" + response="$(_post "$data" "$IONOS_API$route" "" "$method")" else export _H2="Accept: */*" diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index d15d6b0e..7ce39fa9 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -208,7 +208,7 @@ _namecheap_parse_host() { _hostid=$(echo "$_host" | _egrep_o ' HostId="[^"]*' | cut -d '"' -f 2) _hostname=$(echo "$_host" | _egrep_o ' Name="[^"]*' | cut -d '"' -f 2) _hosttype=$(echo "$_host" | _egrep_o ' Type="[^"]*' | cut -d '"' -f 2) - _hostaddress=$(echo "$_host" | _egrep_o ' Address="[^"]*' | cut -d '"' -f 2 | _xml_decode) + _hostaddress=$(echo "$_host" | _egrep_o ' Address="[^"]*' | cut -d '"' -f 2) _hostmxpref=$(echo "$_host" | _egrep_o ' MXPref="[^"]*' | cut -d '"' -f 2) _hostttl=$(echo "$_host" | _egrep_o ' TTL="[^"]*' | cut -d '"' -f 2) @@ -405,7 +405,3 @@ _namecheap_set_tld_sld() { done } - -_xml_decode() { - sed 's/"/"/g' -} diff --git a/dnsapi/dns_pdns.sh b/dnsapi/dns_pdns.sh index 28b35492..8f07e8c4 100755 --- a/dnsapi/dns_pdns.sh +++ b/dnsapi/dns_pdns.sh @@ -175,13 +175,13 @@ _get_root() { i=1 if _pdns_rest "GET" "/api/v1/servers/$PDNS_ServerId/zones"; then - _zones_response=$(echo "$response" | _normalizeJson) + _zones_response="$response" fi while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) - if _contains "$_zones_response" "\"name\":\"$h.\""; then + if _contains "$_zones_response" "\"name\": \"$h.\""; then _domain="$h." if [ -z "$h" ]; then _domain="=2E" diff --git a/dnsapi/dns_porkbun.sh b/dnsapi/dns_porkbun.sh deleted file mode 100644 index 18da6b2f..00000000 --- a/dnsapi/dns_porkbun.sh +++ /dev/null @@ -1,157 +0,0 @@ -#!/usr/bin/env sh - -# -#PORKBUN_API_KEY="pk1_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" -#PORKBUN_SECRET_API_KEY="sk1_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" - -PORKBUN_Api="https://porkbun.com/api/json/v3" - -######## Public functions ##################### - -#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" -dns_porkbun_add() { - fulldomain=$1 - txtvalue=$2 - - PORKBUN_API_KEY="${PORKBUN_API_KEY:-$(_readaccountconf_mutable PORKBUN_API_KEY)}" - PORKBUN_SECRET_API_KEY="${PORKBUN_SECRET_API_KEY:-$(_readaccountconf_mutable PORKBUN_SECRET_API_KEY)}" - - if [ -z "$PORKBUN_API_KEY" ] || [ -z "$PORKBUN_SECRET_API_KEY" ]; then - PORKBUN_API_KEY='' - PORKBUN_SECRET_API_KEY='' - _err "You didn't specify a Porkbun api key and secret api key yet." - _err "You can get yours from here https://porkbun.com/account/api." - return 1 - fi - - #save the credentials to the account conf file. - _saveaccountconf_mutable PORKBUN_API_KEY "$PORKBUN_API_KEY" - _saveaccountconf_mutable PORKBUN_SECRET_API_KEY "$PORKBUN_SECRET_API_KEY" - - _debug 'First detect the root zone' - if ! _get_root "$fulldomain"; then - return 1 - fi - _debug _sub_domain "$_sub_domain" - _debug _domain "$_domain" - - # For wildcard cert, the main root domain and the wildcard domain have the same txt subdomain name, so - # we can not use updating anymore. - # count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2) - # _debug count "$count" - # if [ "$count" = "0" ]; then - _info "Adding record" - if _porkbun_rest POST "dns/create/$_domain" "{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":120}"; then - if _contains "$response" '\"status\":"SUCCESS"'; then - _info "Added, OK" - return 0 - elif _contains "$response" "The record already exists"; then - _info "Already exists, OK" - return 0 - else - _err "Add txt record error. ($response)" - return 1 - fi - fi - _err "Add txt record error." - return 1 - -} - -#fulldomain txtvalue -dns_porkbun_rm() { - fulldomain=$1 - txtvalue=$2 - - PORKBUN_API_KEY="${PORKBUN_API_KEY:-$(_readaccountconf_mutable PORKBUN_API_KEY)}" - PORKBUN_SECRET_API_KEY="${PORKBUN_SECRET_API_KEY:-$(_readaccountconf_mutable PORKBUN_SECRET_API_KEY)}" - - _debug 'First detect the root zone' - if ! _get_root "$fulldomain"; then - return 1 - fi - _debug _sub_domain "$_sub_domain" - _debug _domain "$_domain" - - count=$(echo "$response" | _egrep_o "\"count\": *[^,]*" | cut -d : -f 2 | tr -d " ") - _debug count "$count" - if [ "$count" = "0" ]; then - _info "Don't need to remove." - else - record_id=$(echo "$response" | tr '{' '\n' | grep "$txtvalue" | cut -d, -f1 | cut -d: -f2 | tr -d \") - _debug "record_id" "$record_id" - if [ -z "$record_id" ]; then - _err "Can not get record id to remove." - return 1 - fi - if ! _porkbun_rest POST "dns/delete/$_domain/$record_id"; then - _err "Delete record error." - return 1 - fi - echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null - fi - -} - -#################### Private functions below ################################## -#_acme-challenge.www.domain.com -#returns -# _sub_domain=_acme-challenge.www -# _domain=domain.com -_get_root() { - domain=$1 - i=1 - while true; do - h=$(printf "%s" "$domain" | cut -d . -f $i-100) - _debug h "$h" - if [ -z "$h" ]; then - return 1 - fi - - if _porkbun_rest POST "dns/retrieve/$h"; then - if _contains "$response" "\"status\":\"SUCCESS\""; then - _sub_domain="$(echo "$fulldomain" | sed "s/\\.$_domain\$//")" - _domain=$h - return 0 - else - _debug "Go to next level of $_domain" - fi - else - _debug "Go to next level of $_domain" - fi - i=$(_math "$i" + 1) - done - - return 1 -} - -_porkbun_rest() { - m=$1 - ep="$2" - data="$3" - _debug "$ep" - - api_key_trimmed=$(echo "$PORKBUN_API_KEY" | tr -d '"') - secret_api_key_trimmed=$(echo "$PORKBUN_SECRET_API_KEY" | tr -d '"') - - test -z "$data" && data="{" || data="$(echo $data | cut -d'}' -f1)," - data="$data\"apikey\":\"$api_key_trimmed\",\"secretapikey\":\"$secret_api_key_trimmed\"}" - - export _H1="Content-Type: application/json" - - if [ "$m" != "GET" ]; then - _debug data "$data" - response="$(_post "$data" "$PORKBUN_Api/$ep" "" "$m")" - else - response="$(_get "$PORKBUN_Api/$ep")" - fi - - _sleep 3 # prevent rate limit - - if [ "$?" != "0" ]; then - _err "error $ep" - return 1 - fi - _debug2 response "$response" - return 0 -} diff --git a/dnsapi/dns_servercow.sh b/dnsapi/dns_servercow.sh index f70a2294..e73d85b0 100755 --- a/dnsapi/dns_servercow.sh +++ b/dnsapi/dns_servercow.sh @@ -49,42 +49,16 @@ dns_servercow_add() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - # check whether a txt record already exists for the subdomain - if printf -- "%s" "$response" | grep "{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\"" >/dev/null; then - _info "A txt record with the same name already exists." - # trim the string on the left - txtvalue_old=${response#*{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\",\"content\":\"} - # trim the string on the right - txtvalue_old=${txtvalue_old%%\"*} - - _debug txtvalue_old "$txtvalue_old" - - _info "Add the new txtvalue to the existing txt record." - if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":[\"$txtvalue\",\"$txtvalue_old\"],\"ttl\":20}"; then - if printf -- "%s" "$response" | grep "ok" >/dev/null; then - _info "Added additional txtvalue, OK" - return 0 - else - _err "add txt record error." - return 1 - fi - fi - _err "add txt record error." - return 1 - else - _info "There is no txt record with the name yet." - if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then - if printf -- "%s" "$response" | grep "ok" >/dev/null; then - _info "Added, OK" - return 0 - else - _err "add txt record error." - return 1 - fi + if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then + if printf -- "%s" "$response" | grep "ok" >/dev/null; then + _info "Added, OK" + return 0 + else + _err "add txt record error." + return 1 fi - _err "add txt record error." - return 1 fi + _err "add txt record error." return 1 } diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index e0e05017..d053dcf6 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -6,10 +6,8 @@ #SIMPLY_ApiKey="apikey" # #SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]" -SIMPLY_Api_Default="https://api.simply.com/1" -#This is used for determining success of REST call -SIMPLY_SUCCESS_CODE='"status": 200' +SIMPLY_Api_Default="https://api.simply.com/1" ######## Public functions ##################### #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" @@ -173,7 +171,7 @@ _get_root() { return 1 fi - if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then + if _contains "$response" '"code":"NOT_FOUND"'; then _debug "$h not found" else _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) @@ -198,12 +196,6 @@ _simply_add_record() { return 1 fi - if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then - _err "Call to API not sucessfull, see below message for more details" - _err "$response" - return 1 - fi - return 0 } @@ -219,12 +211,6 @@ _simply_delete_record() { return 1 fi - if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then - _err "Call to API not sucessfull, see below message for more details" - _err "$response" - return 1 - fi - return 0 } diff --git a/notify/smtp.sh b/notify/smtp.sh index 293c665e..6aa37ca3 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -2,398 +2,14 @@ # support smtp -# Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3358 - -# This implementation uses either curl or Python (3 or 2.7). -# (See also the "mail" notify hook, which supports other ways to send mail.) - -# SMTP_FROM="from@example.com" # required -# SMTP_TO="to@example.com" # required -# SMTP_HOST="smtp.example.com" # required -# SMTP_PORT="25" # defaults to 25, 465 or 587 depending on SMTP_SECURE -# SMTP_SECURE="tls" # one of "none", "ssl" (implicit TLS, TLS Wrapper), "tls" (explicit TLS, STARTTLS) -# SMTP_USERNAME="" # set if SMTP server requires login -# SMTP_PASSWORD="" # set if SMTP server requires login -# SMTP_TIMEOUT="30" # seconds for SMTP operations to timeout -# SMTP_BIN="/path/to/python_or_curl" # default finds first of python3, python2.7, python, pypy3, pypy, curl on PATH - -SMTP_SECURE_DEFAULT="tls" -SMTP_TIMEOUT_DEFAULT="30" - -# subject content statuscode smtp_send() { - SMTP_SUBJECT="$1" - SMTP_CONTENT="$2" - # UNUSED: _statusCode="$3" # 0: success, 1: error 2($RENEW_SKIP): skipped - - # Load and validate config: - SMTP_BIN="$(_readaccountconf_mutable_default SMTP_BIN)" - if [ -n "$SMTP_BIN" ] && ! _exists "$SMTP_BIN"; then - _err "SMTP_BIN '$SMTP_BIN' does not exist." - return 1 - fi - if [ -z "$SMTP_BIN" ]; then - # Look for a command that can communicate with an SMTP server. - # (Please don't add sendmail, ssmtp, mutt, mail, or msmtp here. - # Those are already handled by the "mail" notify hook.) - for cmd in python3 python2.7 python pypy3 pypy curl; do - if _exists "$cmd"; then - SMTP_BIN="$cmd" - break - fi - done - if [ -z "$SMTP_BIN" ]; then - _err "The smtp notify-hook requires curl or Python, but can't find any." - _err 'If you have one of them, define SMTP_BIN="/path/to/curl_or_python".' - _err 'Otherwise, see if you can use the "mail" notify-hook instead.' - return 1 - fi - fi - _debug SMTP_BIN "$SMTP_BIN" - _saveaccountconf_mutable_default SMTP_BIN "$SMTP_BIN" - - SMTP_FROM="$(_readaccountconf_mutable_default SMTP_FROM)" - SMTP_FROM="$(_clean_email_header "$SMTP_FROM")" - if [ -z "$SMTP_FROM" ]; then - _err "You must define SMTP_FROM as the sender email address." - return 1 - fi - if _email_has_display_name "$SMTP_FROM"; then - _err "SMTP_FROM must be only a simple email address (sender@example.com)." - _err "Change your SMTP_FROM='$SMTP_FROM' to remove the display name." - return 1 - fi - _debug SMTP_FROM "$SMTP_FROM" - _saveaccountconf_mutable_default SMTP_FROM "$SMTP_FROM" - - SMTP_TO="$(_readaccountconf_mutable_default SMTP_TO)" - SMTP_TO="$(_clean_email_header "$SMTP_TO")" - if [ -z "$SMTP_TO" ]; then - _err "You must define SMTP_TO as the recipient email address(es)." - return 1 - fi - if _email_has_display_name "$SMTP_TO"; then - _err "SMTP_TO must be only simple email addresses (to@example.com,to2@example.com)." - _err "Change your SMTP_TO='$SMTP_TO' to remove the display name(s)." - return 1 - fi - _debug SMTP_TO "$SMTP_TO" - _saveaccountconf_mutable_default SMTP_TO "$SMTP_TO" - - SMTP_HOST="$(_readaccountconf_mutable_default SMTP_HOST)" - if [ -z "$SMTP_HOST" ]; then - _err "You must define SMTP_HOST as the SMTP server hostname." - return 1 - fi - _debug SMTP_HOST "$SMTP_HOST" - _saveaccountconf_mutable_default SMTP_HOST "$SMTP_HOST" - - SMTP_SECURE="$(_readaccountconf_mutable_default SMTP_SECURE "$SMTP_SECURE_DEFAULT")" - case "$SMTP_SECURE" in - "none") smtp_port_default="25" ;; - "ssl") smtp_port_default="465" ;; - "tls") smtp_port_default="587" ;; - *) - _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." - return 1 - ;; - esac - _debug SMTP_SECURE "$SMTP_SECURE" - _saveaccountconf_mutable_default SMTP_SECURE "$SMTP_SECURE" "$SMTP_SECURE_DEFAULT" - - SMTP_PORT="$(_readaccountconf_mutable_default SMTP_PORT "$smtp_port_default")" - case "$SMTP_PORT" in - *[!0-9]*) - _err "Invalid SMTP_PORT='$SMTP_PORT'. It must be a port number." - return 1 - ;; - esac - _debug SMTP_PORT "$SMTP_PORT" - _saveaccountconf_mutable_default SMTP_PORT "$SMTP_PORT" "$smtp_port_default" - - SMTP_USERNAME="$(_readaccountconf_mutable_default SMTP_USERNAME)" - _debug SMTP_USERNAME "$SMTP_USERNAME" - _saveaccountconf_mutable_default SMTP_USERNAME "$SMTP_USERNAME" - - SMTP_PASSWORD="$(_readaccountconf_mutable_default SMTP_PASSWORD)" - _secure_debug SMTP_PASSWORD "$SMTP_PASSWORD" - _saveaccountconf_mutable_default SMTP_PASSWORD "$SMTP_PASSWORD" - - SMTP_TIMEOUT="$(_readaccountconf_mutable_default SMTP_TIMEOUT "$SMTP_TIMEOUT_DEFAULT")" - _debug SMTP_TIMEOUT "$SMTP_TIMEOUT" - _saveaccountconf_mutable_default SMTP_TIMEOUT "$SMTP_TIMEOUT" "$SMTP_TIMEOUT_DEFAULT" - - SMTP_X_MAILER="$(_clean_email_header "$PROJECT_NAME $VER --notify-hook smtp")" - - # Run with --debug 2 (or above) to echo the transcript of the SMTP session. - # Careful: this may include SMTP_PASSWORD in plaintext! - if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then - SMTP_SHOW_TRANSCRIPT="True" - else - SMTP_SHOW_TRANSCRIPT="" - fi - - SMTP_SUBJECT=$(_clean_email_header "$SMTP_SUBJECT") - _debug SMTP_SUBJECT "$SMTP_SUBJECT" - _debug SMTP_CONTENT "$SMTP_CONTENT" - - # Send the message: - case "$(basename "$SMTP_BIN")" in - curl) _smtp_send=_smtp_send_curl ;; - py*) _smtp_send=_smtp_send_python ;; - *) - _err "Can't figure out how to invoke '$SMTP_BIN'." - _err "Check your SMTP_BIN setting." - return 1 - ;; - esac - - if ! smtp_output="$($_smtp_send)"; then - _err "Error sending message with $SMTP_BIN." - if [ -n "$smtp_output" ]; then - _err "$smtp_output" - fi - return 1 - fi - - return 0 -} - -# Strip CR and NL from text to prevent MIME header injection -# text -_clean_email_header() { - printf "%s" "$(echo "$1" | tr -d "\r\n")" -} - -# Simple check for display name in an email address (< > or ") -# email -_email_has_display_name() { - _email="$1" - expr "$_email" : '^.*[<>"]' >/dev/null -} - -## -## curl smtp sending -## - -# Send the message via curl using SMTP_* variables -_smtp_send_curl() { - # Build curl args in $@ - case "$SMTP_SECURE" in - none) - set -- --url "smtp://${SMTP_HOST}:${SMTP_PORT}" - ;; - ssl) - set -- --url "smtps://${SMTP_HOST}:${SMTP_PORT}" - ;; - tls) - set -- --url "smtp://${SMTP_HOST}:${SMTP_PORT}" --ssl-reqd - ;; - *) - # This will only occur if someone adds a new SMTP_SECURE option above - # without updating this code for it. - _err "Unhandled SMTP_SECURE='$SMTP_SECURE' in _smtp_send_curl" - _err "Please re-run with --debug and report a bug." - return 1 - ;; - esac - - set -- "$@" \ - --upload-file - \ - --mail-from "$SMTP_FROM" \ - --max-time "$SMTP_TIMEOUT" - - # Burst comma-separated $SMTP_TO into individual --mail-rcpt args. - _to="${SMTP_TO}," - while [ -n "$_to" ]; do - _rcpt="${_to%%,*}" - _to="${_to#*,}" - set -- "$@" --mail-rcpt "$_rcpt" - done - - _smtp_login="${SMTP_USERNAME}:${SMTP_PASSWORD}" - if [ "$_smtp_login" != ":" ]; then - set -- "$@" --user "$_smtp_login" - fi - - if [ "$SMTP_SHOW_TRANSCRIPT" = "True" ]; then - set -- "$@" --verbose - else - set -- "$@" --silent --show-error - fi - - raw_message="$(_smtp_raw_message)" - - _debug2 "curl command:" "$SMTP_BIN" "$*" - _debug2 "raw_message:\n$raw_message" - - echo "$raw_message" | "$SMTP_BIN" "$@" -} - -# Output an RFC-822 / RFC-5322 email message using SMTP_* variables. -# (This assumes variables have already been cleaned for use in email headers.) -_smtp_raw_message() { - echo "From: $SMTP_FROM" - echo "To: $SMTP_TO" - echo "Subject: $(_mime_encoded_word "$SMTP_SUBJECT")" - echo "Date: $(_rfc2822_date)" - echo "Content-Type: text/plain; charset=utf-8" - echo "X-Mailer: $SMTP_X_MAILER" - echo - echo "$SMTP_CONTENT" -} - -# Convert text to RFC-2047 MIME "encoded word" format if it contains non-ASCII chars -# text -_mime_encoded_word() { - _text="$1" - # (regex character ranges like [a-z] can be locale-dependent; enumerate ASCII chars to avoid that) - _ascii='] $`"'"[!#%&'()*+,./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ~^_abcdefghijklmnopqrstuvwxyz{|}~-" - if expr "$_text" : "^.*[^$_ascii]" >/dev/null; then - # At least one non-ASCII char; convert entire thing to encoded word - printf "%s" "=?UTF-8?B?$(printf "%s" "$_text" | _base64)?=" - else - # Just printable ASCII, no conversion needed - printf "%s" "$_text" - fi -} - -# Output current date in RFC-2822 Section 3.3 format as required in email headers -# (e.g., "Mon, 15 Feb 2021 14:22:01 -0800") -_rfc2822_date() { - # Notes: - # - this is deliberately not UTC, because it "SHOULD express local time" per spec - # - the spec requires weekday and month in the C locale (English), not localized - # - this date format specifier has been tested on Linux, Mac, Solaris and FreeBSD - _old_lc_time="$LC_TIME" - LC_TIME=C - date +'%a, %-d %b %Y %H:%M:%S %z' - LC_TIME="$_old_lc_time" -} - -## -## Python smtp sending -## - -# Send the message via Python using SMTP_* variables -_smtp_send_python() { - _debug "Python version" "$("$SMTP_BIN" --version 2>&1)" - - # language=Python - "$SMTP_BIN" < Date: Tue, 5 Jan 2021 15:29:08 +0330 Subject: [PATCH 308/383] change arvan api script --- dnsapi/dns_arvan.sh | 43 +++++++++++++++---------------------------- 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/dnsapi/dns_arvan.sh b/dnsapi/dns_arvan.sh index ca1f56c7..3c4ced15 100644 --- a/dnsapi/dns_arvan.sh +++ b/dnsapi/dns_arvan.sh @@ -3,7 +3,6 @@ #Arvan_Token="xxxx" ARVAN_API_URL="https://napi.arvancloud.com/cdn/4.0/domains" - #Author: Ehsan Aliakbar #Report Bugs here: https://github.com/Neilpang/acme.sh # @@ -38,6 +37,7 @@ dns_arvan_add() { _info "Adding record" if _arvan_rest POST "$_domain/dns-records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":{\"text\":\"$txtvalue\"},\"ttl\":120}"; then if _contains "$response" "$txtvalue"; then + _info "response id is $response" _info "Added, OK" return 0 elif _contains "$response" "Record Data is Duplicated"; then @@ -49,7 +49,7 @@ dns_arvan_add() { fi fi _err "Add txt record error." - return 1 + return 0 } #Usage: fulldomain txtvalue @@ -73,33 +73,21 @@ dns_arvan_rm() { _debug _domain "$_domain" _debug "Getting txt records" - shorted_txtvalue=$(printf "%s" "$txtvalue" | cut -d "-" -d "_" -f1) - _arvan_rest GET "${_domain}/dns-records?search=$shorted_txtvalue" - + _arvan_rest GET "${_domain}/dns-records" if ! printf "%s" "$response" | grep \"current_page\":1 >/dev/null; then _err "Error on Arvan Api" _err "Please create a github issue with debbug log" return 1 fi - count=$(printf "%s\n" "$response" | _egrep_o "\"total\":[^,]*" | cut -d : -f 2) - _debug count "$count" - if [ "$count" = "0" ]; then - _info "Don't need to remove." - else - record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1) - _debug "record_id" "$record_id" - if [ -z "$record_id" ]; then - _err "Can not get record id to remove." - return 1 - fi - if ! _arvan_rest "DELETE" "${_domain}/dns-records/$record_id"; then - _err "Delete record error." - return 1 - fi - _debug "$response" - _contains "$response" 'dns record deleted' + _record_id=$(echo "$response" | _egrep_o ".\"id\":\"[^\"]*\",\"type\":\"txt\",\"name\":\"_acme-challenge\",\"value\":{\"text\":\"$txtvalue\"}" | cut -d : -f 2 | cut -d , -f 1 | tr -d \") + if ! _arvan_rest "DELETE" "${_domain}/dns-records/${_record_id}"; then + _err "Error on Arvan Api" + return 1 fi + _debug "$response" + _contains "$response" 'dns record deleted' + return 0 } #################### Private functions below ################################## @@ -111,7 +99,7 @@ dns_arvan_rm() { # _domain_id=sdjkglgdfewsdfg _get_root() { domain=$1 - i=1 + i=2 p=1 while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) @@ -121,12 +109,11 @@ _get_root() { return 1 fi - if ! _arvan_rest GET "?search=$h"; then + if ! _arvan_rest GET "$h"; then return 1 fi - - if _contains "$response" "\"domain\":\"$h\"" || _contains "$response" '"total":1'; then - _domain_id=$(echo "$response" | _egrep_o "\[.\"id\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \") + if _contains "$response" "\"domain\":\"$h\""; then + _domain_id=$(echo "$response" | cut -d : -f 3 | cut -d , -f 1 | tr -d \") if [ "$_domain_id" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain=$h @@ -146,7 +133,6 @@ _arvan_rest() { data="$3" token_trimmed=$(echo "$Arvan_Token" | tr -d '"') - export _H1="Authorization: $token_trimmed" if [ "$mtd" = "DELETE" ]; then @@ -160,4 +146,5 @@ _arvan_rest() { else response="$(_get "$ARVAN_API_URL/$ep$data")" fi + return 0 } From e232565971b6090b6a23e47ce530d730bb1c22ef Mon Sep 17 00:00:00 2001 From: Vahid Fardi Date: Tue, 5 Jan 2021 17:10:41 +0330 Subject: [PATCH 309/383] change Author name --- dnsapi/dns_arvan.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_arvan.sh b/dnsapi/dns_arvan.sh index 3c4ced15..a33504d0 100644 --- a/dnsapi/dns_arvan.sh +++ b/dnsapi/dns_arvan.sh @@ -1,10 +1,10 @@ #!/usr/bin/env sh -#Arvan_Token="xxxx" +#Arvan_Token="Apikey xxxx" ARVAN_API_URL="https://napi.arvancloud.com/cdn/4.0/domains" -#Author: Ehsan Aliakbar -#Report Bugs here: https://github.com/Neilpang/acme.sh +#Author: Vahid Fardi +#Report Bugs here: https://github.com/fvahid/acme.sh # ######## Public functions ##################### From 91a739af6e3d7d0aa4624343d83c53d4faea03a6 Mon Sep 17 00:00:00 2001 From: Vahid Fardi Date: Tue, 5 Jan 2021 21:31:31 +0330 Subject: [PATCH 310/383] change name actor --- dnsapi/dns_arvan.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_arvan.sh b/dnsapi/dns_arvan.sh index a33504d0..4c9217e5 100644 --- a/dnsapi/dns_arvan.sh +++ b/dnsapi/dns_arvan.sh @@ -4,7 +4,7 @@ ARVAN_API_URL="https://napi.arvancloud.com/cdn/4.0/domains" #Author: Vahid Fardi -#Report Bugs here: https://github.com/fvahid/acme.sh +#Report Bugs here: https://github.com/Neilpang/acme.sh # ######## Public functions ##################### From 6502bdecbe0e556eda5d7a41dd7d4d7e677c885c Mon Sep 17 00:00:00 2001 From: Gnought <1684105+gnought@users.noreply.github.com> Date: Thu, 11 Feb 2021 01:08:08 +0800 Subject: [PATCH 311/383] Updated --preferred-chain to issue ISRG properly To support different openssl crl2pkcs7 help cli format --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index a1ad4195..749400e2 100755 --- a/acme.sh +++ b/acme.sh @@ -4011,7 +4011,7 @@ _check_dns_entries() { #file _get_cert_issuers() { _cfile="$1" - if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then + if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -help 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 else ${ACME_OPENSSL_BIN:-openssl} x509 -in $_cfile -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 From 016dca654e959656242b392fcc3e26263e5f8241 Mon Sep 17 00:00:00 2001 From: manuel Date: Thu, 11 Feb 2021 11:20:18 +0100 Subject: [PATCH 312/383] dnsapi/pdns: also normalize json response in detecting root zone --- dnsapi/dns_pdns.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_pdns.sh b/dnsapi/dns_pdns.sh index 8f07e8c4..28b35492 100755 --- a/dnsapi/dns_pdns.sh +++ b/dnsapi/dns_pdns.sh @@ -175,13 +175,13 @@ _get_root() { i=1 if _pdns_rest "GET" "/api/v1/servers/$PDNS_ServerId/zones"; then - _zones_response="$response" + _zones_response=$(echo "$response" | _normalizeJson) fi while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) - if _contains "$_zones_response" "\"name\": \"$h.\""; then + if _contains "$_zones_response" "\"name\":\"$h.\""; then _domain="$h." if [ -z "$h" ]; then _domain="=2E" From ac148ce0e979aa7c7eb3ade1add0cd69e9981dd0 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 13 Feb 2021 16:22:31 +0800 Subject: [PATCH 313/383] Chain (#3408) * fix https://github.com/acmesh-official/acme.sh/issues/3384 match the issuer to the root CA cert subject * fix format * fix https://github.com/acmesh-official/acme.sh/issues/3384 * remove the alt files. https://github.com/acmesh-official/acme.sh/issues/3384 --- acme.sh | 58 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/acme.sh b/acme.sh index 749400e2..a9301e10 100755 --- a/acme.sh +++ b/acme.sh @@ -4009,12 +4009,42 @@ _check_dns_entries() { } #file -_get_cert_issuers() { +_get_chain_issuers() { _cfile="$1" if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -help 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then - ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 + ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep -i 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 else - ${ACME_OPENSSL_BIN:-openssl} x509 -in $_cfile -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 + _cindex=1 + for _startn in $(grep -n -- "$BEGIN_CERT" "$_cfile" | cut -d : -f 1); do + _endn="$(grep -n -- "$END_CERT" "$_cfile" | cut -d : -f 1 | _head_n $_cindex | _tail_n 1)" + _debug2 "_startn" "$_startn" + _debug2 "_endn" "$_endn" + if [ "$DEBUG" ]; then + _debug2 "cert$_cindex" "$(sed -n "$_startn,${_endn}p" "$_cfile")" + fi + sed -n "$_startn,${_endn}p" "$_cfile" | ${ACME_OPENSSL_BIN:-openssl} x509 -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 | sed "s/ *\(.*\)/\1/" + _cindex=$(_math $_cindex + 1) + done + fi +} + +# +_get_chain_subjects() { + _cfile="$1" + if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -help 2>&1)" "Usage: crl2pkcs7" || _contains "$(${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 help 2>&1)" "unknown option help"; then + ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep -i 'Subject:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 + else + _cindex=1 + for _startn in $(grep -n -- "$BEGIN_CERT" "$_cfile" | cut -d : -f 1); do + _endn="$(grep -n -- "$END_CERT" "$_cfile" | cut -d : -f 1 | _head_n $_cindex | _tail_n 1)" + _debug2 "_startn" "$_startn" + _debug2 "_endn" "$_endn" + if [ "$DEBUG" ]; then + _debug2 "cert$_cindex" "$(sed -n "$_startn,${_endn}p" "$_cfile")" + fi + sed -n "$_startn,${_endn}p" "$_cfile" | ${ACME_OPENSSL_BIN:-openssl} x509 -text -noout | grep -i 'Subject:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2 | sed "s/ *\(.*\)/\1/" + _cindex=$(_math $_cindex + 1) + done fi } @@ -4022,14 +4052,12 @@ _get_cert_issuers() { _match_issuer() { _cfile="$1" _missuer="$2" - _fissuers="$(_get_cert_issuers $_cfile)" + _fissuers="$(_get_chain_issuers $_cfile)" _debug2 _fissuers "$_fissuers" - if _contains "$_fissuers" "$_missuer"; then - return 0 - fi - _fissuers="$(echo "$_fissuers" | _lower_case)" + _rootissuer="$(echo "$_fissuers" | _lower_case | _tail_n 1)" + _debug2 _rootissuer "$_rootissuer" _missuer="$(echo "$_missuer" | _lower_case)" - _contains "$_fissuers" "$_missuer" + _contains "$_rootissuer" "$_missuer" } #webroot, domain domainlist keylength @@ -4803,6 +4831,9 @@ $_authorizations_map" _split_cert_chain "$CERT_PATH" "$CERT_FULLCHAIN_PATH" "$CA_CERT_PATH" if [ "$_preferred_chain" ] && [ -f "$CERT_FULLCHAIN_PATH" ]; then + if [ "$DEBUG" ]; then + _debug "default chain issuers: " "$(_get_chain_issuers "$CERT_FULLCHAIN_PATH")" + fi if ! _match_issuer "$CERT_FULLCHAIN_PATH" "$_preferred_chain"; then rels="$(echo "$responseHeaders" | tr -d ' <>' | grep -i "^link:" | grep -i 'rel="alternate"' | cut -d : -f 2- | cut -d ';' -f 1)" _debug2 "rels" "$rels" @@ -4818,13 +4849,22 @@ $_authorizations_map" _relca="$CA_CERT_PATH.alt" echo "$response" >"$_relcert" _split_cert_chain "$_relcert" "$_relfullchain" "$_relca" + if [ "$DEBUG" ]; then + _debug "rel chain issuers: " "$(_get_chain_issuers "$_relfullchain")" + fi if _match_issuer "$_relfullchain" "$_preferred_chain"; then _info "Matched issuer in: $rel" cat $_relcert >"$CERT_PATH" cat $_relfullchain >"$CERT_FULLCHAIN_PATH" cat $_relca >"$CA_CERT_PATH" + rm -f "$_relcert" + rm -f "$_relfullchain" + rm -f "$_relca" break fi + rm -f "$_relcert" + rm -f "$_relfullchain" + rm -f "$_relca" done fi fi From fb5d72c29be41398d38c2f43032d3c13ac8d458a Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 13 Feb 2021 17:27:22 +0800 Subject: [PATCH 314/383] upgrade freebsd and solaris --- .github/workflows/LetsEncrypt.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 8d0c4eb0..7c398c09 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -111,7 +111,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.0.7 + - uses: vmactions/freebsd-vm@v0.1.2 with: envs: 'NGROK_TOKEN TEST_LOCAL' prepare: pkg install -y socat curl @@ -136,7 +136,7 @@ jobs: run: echo "TestingDomain=${{steps.ngrok.outputs.server}}" >> $GITHUB_ENV - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/solaris-vm@v0.0.1 + - uses: vmactions/solaris-vm@v0.0.3 with: envs: 'TEST_LOCAL TestingDomain' nat: | From b1988c7b67b7e077a68555594d174c4856b9c1f1 Mon Sep 17 00:00:00 2001 From: jerrm Date: Sat, 13 Feb 2021 05:58:44 -0500 Subject: [PATCH 315/383] duckdns - fix "integer expression expected" errors (#3397) * fix "integer expression expected" errors * duckdns fix * Update dns_duckdns.sh * Update dns_duckdns.sh --- dnsapi/dns_duckdns.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index 618e12c6..d6e1dbdc 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -12,7 +12,7 @@ DuckDNS_API="https://www.duckdns.org/update" -######## Public functions ##################### +######## Public functions ###################### #Usage: dns_duckdns_add _acme-challenge.domain.duckdns.org "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_duckdns_add() { @@ -112,7 +112,7 @@ _duckdns_rest() { param="$2" _debug param "$param" url="$DuckDNS_API?$param" - if [ "$DEBUG" -gt 0 ]; then + if [ -n "$DEBUG" ] && [ "$DEBUG" -gt 0 ]; then url="$url&verbose=true" fi _debug url "$url" @@ -121,7 +121,7 @@ _duckdns_rest() { if [ "$method" = "GET" ]; then response="$(_get "$url")" _debug2 response "$response" - if [ "$DEBUG" -gt 0 ] && _contains "$response" "UPDATED" && _contains "$response" "OK"; then + if [ -n "$DEBUG" ] && [ "$DEBUG" -gt 0 ] && _contains "$response" "UPDATED" && _contains "$response" "OK"; then response="OK" fi else From 2d9506eb546f66947bf7e86d6bc6ccd9f5ddb621 Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 29 Dec 2020 16:28:38 -0800 Subject: [PATCH 316/383] Implement smtp notify hook Support notifications via direct SMTP server connection. Uses Python (2.7.x or 3.4+) to communicate with SMTP server. --- notify/smtp.sh | 185 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 183 insertions(+), 2 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 6aa37ca3..367021c8 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -2,7 +2,103 @@ # support smtp +# This implementation uses Python (2 or 3), which is available in many environments. +# If you don't have Python, try "mail" notification instead of "smtp". + +# SMTP_FROM="from@example.com" # required +# SMTP_TO="to@example.com" # required +# SMTP_HOST="smtp.example.com" # required +# SMTP_PORT="25" # defaults to 25, 465 or 587 depending on SMTP_SECURE +# SMTP_SECURE="none" # one of "none", "ssl" (implicit TLS, TLS Wrapper), "tls" (explicit TLS, STARTTLS) +# SMTP_USERNAME="" # set if SMTP server requires login +# SMTP_PASSWORD="" # set if SMTP server requires login +# SMTP_TIMEOUT="15" # seconds for SMTP operations to timeout +# SMTP_PYTHON="/path/to/python" # defaults to system python3 or python + smtp_send() { + # Find a Python interpreter: + SMTP_PYTHON="${SMTP_PYTHON:-$(_readaccountconf_mutable SMTP_PYTHON)}" + if [ "$SMTP_PYTHON" ]; then + if _exists "$SMTP_PYTHON"; then + _saveaccountconf_mutable SMTP_PYTHON "$SMTP_PYTHON" + else + _err "SMTP_PYTHON '$SMTP_PYTHON' does not exist." + return 1 + fi + else + # No SMTP_PYTHON setting; try to run default Python. + # (This is not saved with the conf.) + if _exists python3; then + SMTP_PYTHON="python3" + elif _exists python; then + SMTP_PYTHON="python" + else + _err "Can't locate Python interpreter; please define SMTP_PYTHON." + return 1 + fi + fi + _debug "SMTP_PYTHON" "$SMTP_PYTHON" + _debug "Python version" "$($SMTP_PYTHON --version 2>&1)" + + # Validate other settings: + SMTP_FROM="${SMTP_FROM:-$(_readaccountconf_mutable SMTP_FROM)}" + if [ -z "$SMTP_FROM" ]; then + _err "You must define SMTP_FROM as the sender email address." + return 1 + fi + + SMTP_TO="${SMTP_TO:-$(_readaccountconf_mutable SMTP_TO)}" + if [ -z "$SMTP_TO" ]; then + _err "You must define SMTP_TO as the recipient email address." + return 1 + fi + + SMTP_HOST="${SMTP_HOST:-$(_readaccountconf_mutable SMTP_HOST)}" + if [ -z "$SMTP_HOST" ]; then + _err "You must define SMTP_HOST as the SMTP server hostname." + return 1 + fi + SMTP_PORT="${SMTP_PORT:-$(_readaccountconf_mutable SMTP_PORT)}" + + SMTP_SECURE="${SMTP_SECURE:-$(_readaccountconf_mutable SMTP_SECURE)}" + SMTP_SECURE="${SMTP_SECURE:-none}" + case "$SMTP_SECURE" in + "none") SMTP_DEFAULT_PORT="25";; + "ssl") SMTP_DEFAULT_PORT="465";; + "tls") SMTP_DEFAULT_PORT="587";; + *) + _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." + return 1 + ;; + esac + + SMTP_USERNAME="${SMTP_USERNAME:-$(_readaccountconf_mutable SMTP_USERNAME)}" + SMTP_PASSWORD="${SMTP_PASSWORD:-$(_readaccountconf_mutable SMTP_PASSWORD)}" + + SMTP_TIMEOUT="${SMTP_TIMEOUT:-$(_readaccountconf_mutable SMTP_TIMEOUT)}" + SMTP_DEFAULT_TIMEOUT="15" + + _saveaccountconf_mutable SMTP_FROM "$SMTP_FROM" + _saveaccountconf_mutable SMTP_TO "$SMTP_TO" + _saveaccountconf_mutable SMTP_HOST "$SMTP_HOST" + _saveaccountconf_mutable SMTP_PORT "$SMTP_PORT" + _saveaccountconf_mutable SMTP_SECURE "$SMTP_SECURE" + _saveaccountconf_mutable SMTP_USERNAME "$SMTP_USERNAME" + _saveaccountconf_mutable SMTP_PASSWORD "$SMTP_PASSWORD" + _saveaccountconf_mutable SMTP_TIMEOUT "$SMTP_TIMEOUT" + + # Send the message: + if ! _smtp_send "$@"; then + _err "$smtp_send_output" + return 1 + fi + + return 0 +} + +# _send subject content statuscode +# Send the message via Python using SMTP_* settings +_smtp_send() { _subject="$1" _content="$2" _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped @@ -10,6 +106,91 @@ smtp_send() { _debug "_content" "$_content" _debug "_statusCode" "$_statusCode" - _err "Not implemented yet." - return 1 + _debug "SMTP_FROM" "$SMTP_FROM" + _debug "SMTP_TO" "$SMTP_TO" + _debug "SMTP_HOST" "$SMTP_HOST" + _debug "SMTP_PORT" "$SMTP_PORT" + _debug "SMTP_DEFAULT_PORT" "$SMTP_DEFAULT_PORT" + _debug "SMTP_SECURE" "$SMTP_SECURE" + _debug "SMTP_USERNAME" "$SMTP_USERNAME" + _secure_debug "SMTP_PASSWORD" "$SMTP_PASSWORD" + _debug "SMTP_TIMEOUT" "$SMTP_TIMEOUT" + _debug "SMTP_DEFAULT_TIMEOUT" "$SMTP_DEFAULT_TIMEOUT" + + if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then + # Output the SMTP server dialogue. (Note this will include SMTP_PASSWORD!) + smtp_debug="True" + else + smtp_debug="" + fi + + # language=Python + smtp_send_output="$($SMTP_PYTHON < Date: Tue, 29 Dec 2020 17:10:36 -0800 Subject: [PATCH 317/383] Make shfmt happy (I'm open to better ways of formatting the heredoc that embeds the Python script.) --- notify/smtp.sh | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 367021c8..6171cb9b 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -63,13 +63,13 @@ smtp_send() { SMTP_SECURE="${SMTP_SECURE:-$(_readaccountconf_mutable SMTP_SECURE)}" SMTP_SECURE="${SMTP_SECURE:-none}" case "$SMTP_SECURE" in - "none") SMTP_DEFAULT_PORT="25";; - "ssl") SMTP_DEFAULT_PORT="465";; - "tls") SMTP_DEFAULT_PORT="587";; - *) - _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." - return 1 - ;; + "none") SMTP_DEFAULT_PORT="25" ;; + "ssl") SMTP_DEFAULT_PORT="465" ;; + "tls") SMTP_DEFAULT_PORT="587" ;; + *) + _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." + return 1 + ;; esac SMTP_USERNAME="${SMTP_USERNAME:-$(_readaccountconf_mutable SMTP_USERNAME)}" @@ -125,7 +125,8 @@ _smtp_send() { fi # language=Python - smtp_send_output="$($SMTP_PYTHON < Date: Mon, 11 Jan 2021 11:46:26 -0800 Subject: [PATCH 318/383] Only save config if send is successful --- notify/smtp.sh | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 6171cb9b..092bb2b9 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -78,6 +78,13 @@ smtp_send() { SMTP_TIMEOUT="${SMTP_TIMEOUT:-$(_readaccountconf_mutable SMTP_TIMEOUT)}" SMTP_DEFAULT_TIMEOUT="15" + # Send the message: + if ! _smtp_send "$@"; then + _err "$smtp_send_output" + return 1 + fi + + # Save remaining config if successful. (SMTP_PYTHON is saved earlier.) _saveaccountconf_mutable SMTP_FROM "$SMTP_FROM" _saveaccountconf_mutable SMTP_TO "$SMTP_TO" _saveaccountconf_mutable SMTP_HOST "$SMTP_HOST" @@ -87,12 +94,6 @@ smtp_send() { _saveaccountconf_mutable SMTP_PASSWORD "$SMTP_PASSWORD" _saveaccountconf_mutable SMTP_TIMEOUT "$SMTP_TIMEOUT" - # Send the message: - if ! _smtp_send "$@"; then - _err "$smtp_send_output" - return 1 - fi - return 0 } From e272fde95e260727de8ceaea05c2767a3eb6114f Mon Sep 17 00:00:00 2001 From: medmunds Date: Mon, 11 Jan 2021 12:59:51 -0800 Subject: [PATCH 319/383] Add instructions for reporting bugs --- notify/smtp.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/notify/smtp.sh b/notify/smtp.sh index 092bb2b9..a74ce092 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -2,6 +2,8 @@ # support smtp +# Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3358 + # This implementation uses Python (2 or 3), which is available in many environments. # If you don't have Python, try "mail" notification instead of "smtp". From 65a1b892e31ae3b5c2600965615d124c47b47955 Mon Sep 17 00:00:00 2001 From: medmunds Date: Sun, 14 Feb 2021 15:47:51 -0800 Subject: [PATCH 320/383] Prep for curl or Python; clean up SMTP_* variable usage --- notify/smtp.sh | 203 ++++++++++++++++++++++++++++--------------------- 1 file changed, 118 insertions(+), 85 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index a74ce092..cb29d0f7 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -4,8 +4,8 @@ # Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3358 -# This implementation uses Python (2 or 3), which is available in many environments. -# If you don't have Python, try "mail" notification instead of "smtp". +# This implementation uses either curl or Python (3 or 2.7). +# (See also the "mail" notify hook, which supports other ways to send mail.) # SMTP_FROM="from@example.com" # required # SMTP_TO="to@example.com" # required @@ -14,79 +14,132 @@ # SMTP_SECURE="none" # one of "none", "ssl" (implicit TLS, TLS Wrapper), "tls" (explicit TLS, STARTTLS) # SMTP_USERNAME="" # set if SMTP server requires login # SMTP_PASSWORD="" # set if SMTP server requires login -# SMTP_TIMEOUT="15" # seconds for SMTP operations to timeout -# SMTP_PYTHON="/path/to/python" # defaults to system python3 or python +# SMTP_TIMEOUT="30" # seconds for SMTP operations to timeout +# SMTP_BIN="/path/to/curl_or_python" # default finds first of curl, python3, or python on PATH +# subject content statuscode smtp_send() { - # Find a Python interpreter: - SMTP_PYTHON="${SMTP_PYTHON:-$(_readaccountconf_mutable SMTP_PYTHON)}" - if [ "$SMTP_PYTHON" ]; then - if _exists "$SMTP_PYTHON"; then - _saveaccountconf_mutable SMTP_PYTHON "$SMTP_PYTHON" - else - _err "SMTP_PYTHON '$SMTP_PYTHON' does not exist." - return 1 - fi - else - # No SMTP_PYTHON setting; try to run default Python. - # (This is not saved with the conf.) - if _exists python3; then - SMTP_PYTHON="python3" - elif _exists python; then - SMTP_PYTHON="python" - else - _err "Can't locate Python interpreter; please define SMTP_PYTHON." + _SMTP_SUBJECT="$1" + _SMTP_CONTENT="$2" + # UNUSED: _statusCode="$3" # 0: success, 1: error 2($RENEW_SKIP): skipped + + # Load config: + SMTP_FROM="${SMTP_FROM:-$(_readaccountconf_mutable SMTP_FROM)}" + SMTP_TO="${SMTP_TO:-$(_readaccountconf_mutable SMTP_TO)}" + SMTP_HOST="${SMTP_HOST:-$(_readaccountconf_mutable SMTP_HOST)}" + SMTP_PORT="${SMTP_PORT:-$(_readaccountconf_mutable SMTP_PORT)}" + SMTP_SECURE="${SMTP_SECURE:-$(_readaccountconf_mutable SMTP_SECURE)}" + SMTP_USERNAME="${SMTP_USERNAME:-$(_readaccountconf_mutable SMTP_USERNAME)}" + SMTP_PASSWORD="${SMTP_PASSWORD:-$(_readaccountconf_mutable SMTP_PASSWORD)}" + SMTP_TIMEOUT="${SMTP_TIMEOUT:-$(_readaccountconf_mutable SMTP_TIMEOUT)}" + SMTP_BIN="${SMTP_BIN:-$(_readaccountconf_mutable SMTP_BIN)}" + + _debug "SMTP_FROM" "$SMTP_FROM" + _debug "SMTP_TO" "$SMTP_TO" + _debug "SMTP_HOST" "$SMTP_HOST" + _debug "SMTP_PORT" "$SMTP_PORT" + _debug "SMTP_SECURE" "$SMTP_SECURE" + _debug "SMTP_USERNAME" "$SMTP_USERNAME" + _secure_debug "SMTP_PASSWORD" "$SMTP_PASSWORD" + _debug "SMTP_TIMEOUT" "$SMTP_TIMEOUT" + _debug "SMTP_BIN" "$SMTP_BIN" + + _debug "_SMTP_SUBJECT" "$_SMTP_SUBJECT" + _debug "_SMTP_CONTENT" "$_SMTP_CONTENT" + + # Validate config and apply defaults: + # _SMTP_* variables are the resolved (with defaults) versions of SMTP_*. + # (The _SMTP_* versions will not be stored in account conf.) + + if [ -n "$SMTP_BIN" ] && ! _exists "$SMTP_BIN"; then + _err "SMTP_BIN '$SMTP_BIN' does not exist." + return 1 + fi + _SMTP_BIN="$SMTP_BIN" + if [ -z "$_SMTP_BIN" ]; then + # Look for a command that can communicate with an SMTP server. + # (Please don't add sendmail, ssmtp, mutt, mail, or msmtp here. + # Those are already handled by the "mail" notify hook.) + for cmd in curl python3 python2.7 python pypy3 pypy; do + if _exists "$cmd"; then + _SMTP_BIN="$cmd" + break + fi + done + if [ -z "$_SMTP_BIN" ]; then + _err "The smtp notify-hook requires curl or Python, but can't find any." + _err 'If you have one of them, define SMTP_BIN="/path/to/curl_or_python".' + _err 'Otherwise, see if you can use the "mail" notify-hook instead.' return 1 fi + _debug "_SMTP_BIN" "$_SMTP_BIN" fi - _debug "SMTP_PYTHON" "$SMTP_PYTHON" - _debug "Python version" "$($SMTP_PYTHON --version 2>&1)" - # Validate other settings: - SMTP_FROM="${SMTP_FROM:-$(_readaccountconf_mutable SMTP_FROM)}" if [ -z "$SMTP_FROM" ]; then _err "You must define SMTP_FROM as the sender email address." return 1 fi + _SMTP_FROM="$SMTP_FROM" - SMTP_TO="${SMTP_TO:-$(_readaccountconf_mutable SMTP_TO)}" if [ -z "$SMTP_TO" ]; then _err "You must define SMTP_TO as the recipient email address." return 1 fi + _SMTP_TO="$SMTP_TO" - SMTP_HOST="${SMTP_HOST:-$(_readaccountconf_mutable SMTP_HOST)}" if [ -z "$SMTP_HOST" ]; then _err "You must define SMTP_HOST as the SMTP server hostname." return 1 fi - SMTP_PORT="${SMTP_PORT:-$(_readaccountconf_mutable SMTP_PORT)}" + _SMTP_HOST="$SMTP_HOST" - SMTP_SECURE="${SMTP_SECURE:-$(_readaccountconf_mutable SMTP_SECURE)}" - SMTP_SECURE="${SMTP_SECURE:-none}" - case "$SMTP_SECURE" in - "none") SMTP_DEFAULT_PORT="25" ;; - "ssl") SMTP_DEFAULT_PORT="465" ;; - "tls") SMTP_DEFAULT_PORT="587" ;; + _SMTP_SECURE="${SMTP_SECURE:-none}" + case "$_SMTP_SECURE" in + "none") smtp_default_port="25" ;; + "ssl") smtp_default_port="465" ;; + "tls") smtp_default_port="587" ;; *) _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." return 1 ;; esac - SMTP_USERNAME="${SMTP_USERNAME:-$(_readaccountconf_mutable SMTP_USERNAME)}" - SMTP_PASSWORD="${SMTP_PASSWORD:-$(_readaccountconf_mutable SMTP_PASSWORD)}" + _SMTP_PORT="${SMTP_PORT:-$smtp_default_port}" + if [ -z "$SMTP_PORT" ]; then + _debug "_SMTP_PORT" "$_SMTP_PORT" + fi - SMTP_TIMEOUT="${SMTP_TIMEOUT:-$(_readaccountconf_mutable SMTP_TIMEOUT)}" - SMTP_DEFAULT_TIMEOUT="15" + _SMTP_USERNAME="$SMTP_USERNAME" + _SMTP_PASSWORD="$SMTP_PASSWORD" + _SMTP_TIMEOUT="${SMTP_TIMEOUT:-30}" + + # Run with --debug 2 (or above) to echo the transcript of the SMTP session. + # Careful: this may include SMTP_PASSWORD in plaintext! + if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then + _SMTP_SHOW_TRANSCRIPT="True" + else + _SMTP_SHOW_TRANSCRIPT="" + fi # Send the message: - if ! _smtp_send "$@"; then - _err "$smtp_send_output" + case "$(basename "$_SMTP_BIN")" in + curl) _smtp_send=_smtp_send_curl ;; + py*) _smtp_send=_smtp_send_python ;; + *) + _err "Can't figure out how to invoke $_SMTP_BIN." + _err "Please re-run with --debug and report a bug." + return 1 + ;; + esac + + if ! smtp_output="$($_smtp_send)"; then + _err "Error sending message with $_SMTP_BIN." + _err "${smtp_output:-(No additional details; try --debug or --debug 2)}" return 1 fi - # Save remaining config if successful. (SMTP_PYTHON is saved earlier.) + # Save config only if send was successful: + _saveaccountconf_mutable SMTP_BIN "$SMTP_BIN" _saveaccountconf_mutable SMTP_FROM "$SMTP_FROM" _saveaccountconf_mutable SMTP_TO "$SMTP_TO" _saveaccountconf_mutable SMTP_HOST "$SMTP_HOST" @@ -99,37 +152,21 @@ smtp_send() { return 0 } -# _send subject content statuscode -# Send the message via Python using SMTP_* settings -_smtp_send() { - _subject="$1" - _content="$2" - _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped - _debug "_subject" "$_subject" - _debug "_content" "$_content" - _debug "_statusCode" "$_statusCode" - _debug "SMTP_FROM" "$SMTP_FROM" - _debug "SMTP_TO" "$SMTP_TO" - _debug "SMTP_HOST" "$SMTP_HOST" - _debug "SMTP_PORT" "$SMTP_PORT" - _debug "SMTP_DEFAULT_PORT" "$SMTP_DEFAULT_PORT" - _debug "SMTP_SECURE" "$SMTP_SECURE" - _debug "SMTP_USERNAME" "$SMTP_USERNAME" - _secure_debug "SMTP_PASSWORD" "$SMTP_PASSWORD" - _debug "SMTP_TIMEOUT" "$SMTP_TIMEOUT" - _debug "SMTP_DEFAULT_TIMEOUT" "$SMTP_DEFAULT_TIMEOUT" +# Send the message via curl using _SMTP_* variables +_smtp_send_curl() { + # TODO: implement + echo "_smtp_send_curl not implemented" + return 1 +} - if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then - # Output the SMTP server dialogue. (Note this will include SMTP_PASSWORD!) - smtp_debug="True" - else - smtp_debug="" - fi + +# Send the message via Python using _SMTP_* variables +_smtp_send_python() { + _debug "Python version" "$("$_SMTP_BIN" --version 2>&1)" # language=Python - smtp_send_output="$( - $SMTP_PYTHON < Date: Sun, 14 Feb 2021 19:56:23 -0800 Subject: [PATCH 321/383] Implement curl version of smtp notify-hook --- notify/smtp.sh | 111 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 105 insertions(+), 6 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index cb29d0f7..44a5821f 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -127,14 +127,16 @@ smtp_send() { py*) _smtp_send=_smtp_send_python ;; *) _err "Can't figure out how to invoke $_SMTP_BIN." - _err "Please re-run with --debug and report a bug." + _err "Check your SMTP_BIN setting." return 1 ;; esac if ! smtp_output="$($_smtp_send)"; then _err "Error sending message with $_SMTP_BIN." - _err "${smtp_output:-(No additional details; try --debug or --debug 2)}" + if [ -n "$smtp_output" ]; then + _err "$smtp_output" + fi return 1 fi @@ -152,12 +154,109 @@ smtp_send() { return 0 } - # Send the message via curl using _SMTP_* variables _smtp_send_curl() { - # TODO: implement - echo "_smtp_send_curl not implemented" - return 1 + # curl passes --mail-from and --mail-rcpt directly to the SMTP protocol without + # additional parsing, and SMTP requires addr-spec only (no display names). + # In the future, maybe try to parse the addr-spec out for curl args (non-trivial). + if _email_has_display_name "$_SMTP_FROM"; then + _err "curl smtp only allows a simple email address in SMTP_FROM." + _err "Change your SMTP_FROM='$SMTP_FROM' to remove the display name." + return 1 + fi + if _email_has_display_name "$_SMTP_TO"; then + _err "curl smtp only allows simple email addresses in SMTP_TO." + _err "Change your SMTP_TO='$SMTP_TO' to remove the display name(s)." + return 1 + fi + + # Build curl args in $@ + + case "$_SMTP_SECURE" in + none) + set -- --url "smtp://${_SMTP_HOST}:${_SMTP_PORT}" + ;; + ssl) + set -- --url "smtps://${_SMTP_HOST}:${_SMTP_PORT}" + ;; + tls) + set -- --url "smtp://${_SMTP_HOST}:${_SMTP_PORT}" --ssl-reqd + ;; + *) + # This will only occur if someone adds a new SMTP_SECURE option above + # without updating this code for it. + _err "Unhandled _SMTP_SECURE='$_SMTP_SECURE' in _smtp_send_curl" + _err "Please re-run with --debug and report a bug." + return 1 + ;; + esac + + set -- "$@" \ + --upload-file - \ + --mail-from "$_SMTP_FROM" \ + --max-time "$_SMTP_TIMEOUT" + + # Burst comma-separated $_SMTP_TO into individual --mail-rcpt args. + _to="${_SMTP_TO}," + while [ -n "$_to" ]; do + _rcpt="${_to%%,*}" + _to="${_to#*,}" + set -- "$@" --mail-rcpt "$_rcpt" + done + + _smtp_login="${_SMTP_USERNAME}:${_SMTP_PASSWORD}" + if [ "$_smtp_login" != ":" ]; then + set -- "$@" --user "$_smtp_login" + fi + + if [ "$_SMTP_SHOW_TRANSCRIPT" = "True" ]; then + set -- "$@" --verbose + else + set -- "$@" --silent --show-error + fi + + raw_message="$(_smtp_raw_message)" + + _debug2 "curl command:" "$_SMTP_BIN" "$*" + _debug2 "raw_message:\n$raw_message" + + echo "$raw_message" | "$_SMTP_BIN" "$@" +} + +# Output an RFC-822 / RFC-5322 email message using _SMTP_* variables +_smtp_raw_message() { + echo "From: $_SMTP_FROM" + echo "To: $_SMTP_TO" + echo "Subject: $(_mime_encoded_word "$_SMTP_SUBJECT")" + if _exists date; then + echo "Date: $(date +'%a, %-d %b %Y %H:%M:%S %z')" + fi + echo "Content-Type: text/plain; charset=utf-8" + echo "X-Mailer: acme.sh --notify-hook smtp" + echo + echo "$_SMTP_CONTENT" +} + +# Convert text to RFC-2047 MIME "encoded word" format if it contains non-ASCII chars +# text +_mime_encoded_word() { + _text="$1" + # (regex character ranges like [a-z] can be locale-dependent; enumerate ASCII chars to avoid that) + _ascii='] $`"'"[!#%&'()*+,./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ~^_abcdefghijklmnopqrstuvwxyz{|}~-" + if expr "$_text" : "^.*[^$_ascii]" >/dev/null; then + # At least one non-ASCII char; convert entire thing to encoded word + printf "%s" "=?UTF-8?B?$(printf "%s" "$_text" | _base64)?=" + else + # Just printable ASCII, no conversion needed + printf "%s" "$_text" + fi +} + +# Simple check for display name in an email address (< > or ") +# email +_email_has_display_name() { + _email="$1" + expr "$_email" : '^.*[<>"]' > /dev/null } From fe3e8a7bb6fc93daf938f965fbf0b260803c7b19 Mon Sep 17 00:00:00 2001 From: medmunds Date: Sun, 14 Feb 2021 20:06:07 -0800 Subject: [PATCH 322/383] More than one blank line is an abomination, apparently I will not try to use whitespace to group code visually --- notify/smtp.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 44a5821f..c9927e3e 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -256,10 +256,9 @@ _mime_encoded_word() { # email _email_has_display_name() { _email="$1" - expr "$_email" : '^.*[<>"]' > /dev/null + expr "$_email" : '^.*[<>"]' >/dev/null } - # Send the message via Python using _SMTP_* variables _smtp_send_python() { _debug "Python version" "$("$_SMTP_BIN" --version 2>&1)" From 06fb3d94767e475df2c4c0bcb418994f6554674e Mon Sep 17 00:00:00 2001 From: Mike Edmunds Date: Sun, 14 Feb 2021 23:01:21 -0800 Subject: [PATCH 323/383] Fix: Unifi deploy hook support Unifi Cloud Key (#3327) * fix: unifi deploy hook also update Cloud Key nginx certs When running on a Unifi Cloud Key device, also deploy to /etc/ssl/private/cloudkey.{crt,key} and reload nginx. This makes the new cert available for the Cloud Key management app running via nginx on port 443 (as well as the port 8443 Unifi Controller app the deploy hook already supported). Fixes #3326 * Improve settings documentation comments * Improve Cloud Key pre-flight error messaging * Fix typo * Add support for UnifiOS (Cloud Key Gen2) Since UnifiOS does not use the Java keystore (like a Unifi Controller or Cloud Key Gen1 deploy), this also reworks the settings validation and error messaging somewhat. * PR review fixes * Detect unsupported Cloud Key java keystore location * Don't try to restart inactive services (and remove extra spaces from reload command) * Clean up error messages and internal variables * Change to _getdeployconf/_savedeployconf * Switch from cp to cat to preserve file permissions --- deploy/unifi.sh | 220 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 167 insertions(+), 53 deletions(-) diff --git a/deploy/unifi.sh b/deploy/unifi.sh index 184aa62e..a864135e 100644 --- a/deploy/unifi.sh +++ b/deploy/unifi.sh @@ -1,12 +1,43 @@ #!/usr/bin/env sh -#Here is a script to deploy cert to unifi server. +# Here is a script to deploy cert on a Unifi Controller or Cloud Key device. +# It supports: +# - self-hosted Unifi Controller +# - Unifi Cloud Key (Gen1/2/2+) +# - Unifi Cloud Key running UnifiOS (v2.0.0+, Gen2/2+ only) +# Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3359 #returns 0 means success, otherwise error. +# The deploy-hook automatically detects standard Unifi installations +# for each of the supported environments. Most users should not need +# to set any of these variables, but if you are running a self-hosted +# Controller with custom locations, set these as necessary before running +# the deploy hook. (Defaults shown below.) +# +# Settings for Unifi Controller: +# Location of Java keystore or unifi.keystore.jks file: #DEPLOY_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore" +# Keystore password (built into Unifi Controller, not a user-set password): #DEPLOY_UNIFI_KEYPASS="aircontrolenterprise" +# Command to restart Unifi Controller: #DEPLOY_UNIFI_RELOAD="service unifi restart" +# +# Settings for Unifi Cloud Key Gen1 (nginx admin pages): +# Directory where cloudkey.crt and cloudkey.key live: +#DEPLOY_UNIFI_CLOUDKEY_CERTDIR="/etc/ssl/private" +# Command to restart maintenance pages and Controller +# (same setting as above, default is updated when running on Cloud Key Gen1): +#DEPLOY_UNIFI_RELOAD="service nginx restart && service unifi restart" +# +# Settings for UnifiOS (Cloud Key Gen2): +# Directory where unifi-core.crt and unifi-core.key live: +#DEPLOY_UNIFI_CORE_CONFIG="/data/unifi-core/config/" +# Command to restart unifi-core: +#DEPLOY_UNIFI_RELOAD="systemctl restart unifi-core" +# +# At least one of DEPLOY_UNIFI_KEYSTORE, DEPLOY_UNIFI_CLOUDKEY_CERTDIR, +# or DEPLOY_UNIFI_CORE_CONFIG must exist to receive the deployed certs. ######## Public functions ##################### @@ -24,77 +55,160 @@ unifi_deploy() { _debug _cca "$_cca" _debug _cfullchain "$_cfullchain" - if ! _exists keytool; then - _err "keytool not found" - return 1 - fi + _getdeployconf DEPLOY_UNIFI_KEYSTORE + _getdeployconf DEPLOY_UNIFI_KEYPASS + _getdeployconf DEPLOY_UNIFI_CLOUDKEY_CERTDIR + _getdeployconf DEPLOY_UNIFI_CORE_CONFIG + _getdeployconf DEPLOY_UNIFI_RELOAD + + _debug2 DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" + _debug2 DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" + _debug2 DEPLOY_UNIFI_CLOUDKEY_CERTDIR "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" + _debug2 DEPLOY_UNIFI_CORE_CONFIG "$DEPLOY_UNIFI_CORE_CONFIG" + _debug2 DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" + + # Space-separated list of environments detected and installed: + _services_updated="" + + # Default reload commands accumulated as we auto-detect environments: + _reload_cmd="" + + # Unifi Controller environment (self hosted or any Cloud Key) -- + # auto-detect by file /usr/lib/unifi/data/keystore: + _unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-/usr/lib/unifi/data/keystore}" + if [ -f "$_unifi_keystore" ]; then + _info "Installing certificate for Unifi Controller (Java keystore)" + _debug _unifi_keystore "$_unifi_keystore" + if ! _exists keytool; then + _err "keytool not found" + return 1 + fi + if [ ! -w "$_unifi_keystore" ]; then + _err "The file $_unifi_keystore is not writable, please change the permission." + return 1 + fi + + _unifi_keypass="${DEPLOY_UNIFI_KEYPASS:-aircontrolenterprise}" - DEFAULT_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore" - _unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-$DEFAULT_UNIFI_KEYSTORE}" - DEFAULT_UNIFI_KEYPASS="aircontrolenterprise" - _unifi_keypass="${DEPLOY_UNIFI_KEYPASS:-$DEFAULT_UNIFI_KEYPASS}" - DEFAULT_UNIFI_RELOAD="service unifi restart" - _reload="${DEPLOY_UNIFI_RELOAD:-$DEFAULT_UNIFI_RELOAD}" - - _debug _unifi_keystore "$_unifi_keystore" - if [ ! -f "$_unifi_keystore" ]; then - if [ -z "$DEPLOY_UNIFI_KEYSTORE" ]; then - _err "unifi keystore is not found, please define DEPLOY_UNIFI_KEYSTORE" + _debug "Generate import pkcs12" + _import_pkcs12="$(_mktemp)" + _toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root + # shellcheck disable=SC2181 + if [ "$?" != "0" ]; then + _err "Error generating pkcs12. Please re-run with --debug and report a bug." return 1 + fi + + _debug "Import into keystore: $_unifi_keystore" + if keytool -importkeystore \ + -deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \ + -srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \ + -alias unifi -noprompt; then + _debug "Import keystore success!" + rm "$_import_pkcs12" else - _err "It seems that the specified unifi keystore is not valid, please check." + _err "Error importing into Unifi Java keystore." + _err "Please re-run with --debug and report a bug." + rm "$_import_pkcs12" return 1 fi + + if systemctl -q is-active unifi; then + _reload_cmd="${_reload_cmd:+$_reload_cmd && }service unifi restart" + fi + _services_updated="${_services_updated} unifi" + _info "Install Unifi Controller certificate success!" + elif [ "$DEPLOY_UNIFI_KEYSTORE" ]; then + _err "The specified DEPLOY_UNIFI_KEYSTORE='$DEPLOY_UNIFI_KEYSTORE' is not valid, please check." + return 1 fi - if [ ! -w "$_unifi_keystore" ]; then - _err "The file $_unifi_keystore is not writable, please change the permission." + + # Cloud Key environment (non-UnifiOS -- nginx serves admin pages) -- + # auto-detect by file /etc/ssl/private/cloudkey.key: + _cloudkey_certdir="${DEPLOY_UNIFI_CLOUDKEY_CERTDIR:-/etc/ssl/private}" + if [ -f "${_cloudkey_certdir}/cloudkey.key" ]; then + _info "Installing certificate for Cloud Key Gen1 (nginx admin pages)" + _debug _cloudkey_certdir "$_cloudkey_certdir" + if [ ! -w "$_cloudkey_certdir" ]; then + _err "The directory $_cloudkey_certdir is not writable; please check permissions." + return 1 + fi + # Cloud Key expects to load the keystore from /etc/ssl/private/unifi.keystore.jks. + # Normally /usr/lib/unifi/data/keystore is a symlink there (so the keystore was + # updated above), but if not, we don't know how to handle this installation: + if ! cmp -s "$_unifi_keystore" "${_cloudkey_certdir}/unifi.keystore.jks"; then + _err "Unsupported Cloud Key configuration: keystore not found at '${_cloudkey_certdir}/unifi.keystore.jks'" + return 1 + fi + + cat "$_cfullchain" >"${_cloudkey_certdir}/cloudkey.crt" + cat "$_ckey" >"${_cloudkey_certdir}/cloudkey.key" + (cd "$_cloudkey_certdir" && tar -cf cert.tar cloudkey.crt cloudkey.key unifi.keystore.jks) + + if systemctl -q is-active nginx; then + _reload_cmd="${_reload_cmd:+$_reload_cmd && }service nginx restart" + fi + _info "Install Cloud Key Gen1 certificate success!" + _services_updated="${_services_updated} nginx" + elif [ "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" ]; then + _err "The specified DEPLOY_UNIFI_CLOUDKEY_CERTDIR='$DEPLOY_UNIFI_CLOUDKEY_CERTDIR' is not valid, please check." return 1 fi - _info "Generate import pkcs12" - _import_pkcs12="$(_mktemp)" - _toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root - if [ "$?" != "0" ]; then - _err "Oops, error creating import pkcs12, please report bug to us." + # UnifiOS environment -- auto-detect by /data/unifi-core/config/unifi-core.key: + _unifi_core_config="${DEPLOY_UNIFI_CORE_CONFIG:-/data/unifi-core/config}" + if [ -f "${_unifi_core_config}/unifi-core.key" ]; then + _info "Installing certificate for UnifiOS" + _debug _unifi_core_config "$_unifi_core_config" + if [ ! -w "$_unifi_core_config" ]; then + _err "The directory $_unifi_core_config is not writable; please check permissions." + return 1 + fi + + cat "$_cfullchain" >"${_unifi_core_config}/unifi-core.crt" + cat "$_ckey" >"${_unifi_core_config}/unifi-core.key" + + if systemctl -q is-active unifi-core; then + _reload_cmd="${_reload_cmd:+$_reload_cmd && }systemctl restart unifi-core" + fi + _info "Install UnifiOS certificate success!" + _services_updated="${_services_updated} unifi-core" + elif [ "$DEPLOY_UNIFI_CORE_CONFIG" ]; then + _err "The specified DEPLOY_UNIFI_CORE_CONFIG='$DEPLOY_UNIFI_CORE_CONFIG' is not valid, please check." return 1 fi - _info "Modify unifi keystore: $_unifi_keystore" - if keytool -importkeystore \ - -deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \ - -srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \ - -alias unifi -noprompt; then - _info "Import keystore success!" - rm "$_import_pkcs12" - else - _err "Import unifi keystore error, please report bug to us." - rm "$_import_pkcs12" + if [ -z "$_services_updated" ]; then + # None of the Unifi environments were auto-detected, so no deployment has occurred + # (and none of DEPLOY_UNIFI_{KEYSTORE,CLOUDKEY_CERTDIR,CORE_CONFIG} were set). + _err "Unable to detect Unifi environment in standard location." + _err "(This deploy hook must be run on the Unifi device, not a remote machine.)" + _err "For non-standard Unifi installations, set DEPLOY_UNIFI_KEYSTORE," + _err "DEPLOY_UNIFI_CLOUDKEY_CERTDIR, and/or DEPLOY_UNIFI_CORE_CONFIG as appropriate." return 1 fi - _info "Run reload: $_reload" - if eval "$_reload"; then + _reload_cmd="${DEPLOY_UNIFI_RELOAD:-$_reload_cmd}" + if [ -z "$_reload_cmd" ]; then + _err "Certificates were installed for services:${_services_updated}," + _err "but none appear to be active. Please set DEPLOY_UNIFI_RELOAD" + _err "to a command that will restart the necessary services." + return 1 + fi + _info "Reload services (this may take some time): $_reload_cmd" + if eval "$_reload_cmd"; then _info "Reload success!" - if [ "$DEPLOY_UNIFI_KEYSTORE" ]; then - _savedomainconf DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" - else - _cleardomainconf DEPLOY_UNIFI_KEYSTORE - fi - if [ "$DEPLOY_UNIFI_KEYPASS" ]; then - _savedomainconf DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" - else - _cleardomainconf DEPLOY_UNIFI_KEYPASS - fi - if [ "$DEPLOY_UNIFI_RELOAD" ]; then - _savedomainconf DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" - else - _cleardomainconf DEPLOY_UNIFI_RELOAD - fi - return 0 else _err "Reload error" return 1 fi - return 0 + # Successful, so save all (non-default) config: + _savedeployconf DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" + _savedeployconf DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" + _savedeployconf DEPLOY_UNIFI_CLOUDKEY_CERTDIR "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR" + _savedeployconf DEPLOY_UNIFI_CORE_CONFIG "$DEPLOY_UNIFI_CORE_CONFIG" + _savedeployconf DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" + + return 0 } From 8fbec785e826370974a3ccf68a9136fb617dcd7f Mon Sep 17 00:00:00 2001 From: Easton Man Date: Mon, 15 Feb 2021 15:18:49 +0800 Subject: [PATCH 324/383] feat: add huaweicloud error handling --- dnsapi/dns_huaweicloud.sh | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_huaweicloud.sh b/dnsapi/dns_huaweicloud.sh index 74fec2a9..f7192725 100644 --- a/dnsapi/dns_huaweicloud.sh +++ b/dnsapi/dns_huaweicloud.sh @@ -5,7 +5,7 @@ # HUAWEICLOUD_ProjectID iam_api="https://iam.myhuaweicloud.com" -dns_api="https://dns.ap-southeast-1.myhuaweicloud.com" +dns_api="https://dns.ap-southeast-1.myhuaweicloud.com" # Should work ######## Public functions ##################### @@ -29,16 +29,27 @@ dns_huaweicloud_add() { return 1 fi + unset token # Clear token token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_ProjectID}")" - _debug2 "${token}" + if [ -z "${token}" ]; then # Check token + _err "dns_api(dns_huaweicloud): Error getting token." + return 1 + fi + _debug "Access token is: ${token}" + + unset zoneid zoneid="$(_get_zoneid "${token}" "${fulldomain}")" - _debug "${zoneid}" + if [ -z "${zoneid}" ]; then + _err "dns_api(dns_huaweicloud): Error getting zone id." + return 1 + fi + _debug "Zone ID is: ${zoneid}" _debug "Adding Record" _add_record "${token}" "${fulldomain}" "${txtvalue}" ret="$?" if [ "${ret}" != "0" ]; then - _err "dns_huaweicloud: Error adding record." + _err "dns_api(dns_huaweicloud): Error adding record." return 1 fi @@ -69,12 +80,21 @@ dns_huaweicloud_rm() { return 1 fi + unset token # Clear token token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_ProjectID}")" - _debug2 "${token}" + if [ -z "${token}" ]; then # Check token + _err "dns_api(dns_huaweicloud): Error getting token." + return 1 + fi + _debug "Access token is: ${token}" + + unset zoneid zoneid="$(_get_zoneid "${token}" "${fulldomain}")" - _debug "${zoneid}" - record_id="$(_get_recordset_id "${token}" "${fulldomain}" "${zoneid}")" - _debug "Record Set ID is: ${record_id}" + if [ -z "${zoneid}" ]; then + _err "dns_api(dns_huaweicloud): Error getting zone id." + return 1 + fi + _debug "Zone ID is: ${zoneid}" # Remove all records # Therotically HuaweiCloud does not allow more than one record set From c090c19bfee692b69a31984c5eb40d367f38592d Mon Sep 17 00:00:00 2001 From: Easton Man Date: Mon, 15 Feb 2021 15:19:18 +0800 Subject: [PATCH 325/383] fix: fix freebsd and solaris --- .github/workflows/DNS.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 5dc2d453..ed0426ad 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -184,7 +184,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.0.7 + - uses: vmactions/freebsd-vm@v0.1.2 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkg install -y socat curl @@ -223,7 +223,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/solaris-vm@v0.0.1 + - uses: vmactions/solaris-vm@v0.0.3 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkgutil -y -i socat curl From fe0bee21b0a1a545e939357438f9c46d0cc13a7e Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 15 Feb 2021 21:25:27 +0800 Subject: [PATCH 326/383] support openssl 3.0 fix https://github.com/acmesh-official/acme.sh/issues/3399 --- acme.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index a9301e10..2cb9dd00 100755 --- a/acme.sh +++ b/acme.sh @@ -1122,9 +1122,14 @@ _createkey() { fi fi + __traditional="" + if _contains "$(${ACME_OPENSSL_BIN:-openssl} help genrsa 2>&1)" "-traditional"; then + __traditional="-traditional" + fi + if _isEccKey "$length"; then _debug "Using ec name: $eccname" - if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -genkey 2>/dev/null)"; then + if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam $__traditional -name "$eccname" -genkey 2>/dev/null)"; then echo "$_opkey" >"$f" else _err "error ecc key name: $eccname" @@ -1132,7 +1137,7 @@ _createkey() { fi else _debug "Using RSA: $length" - if _opkey="$(${ACME_OPENSSL_BIN:-openssl} genrsa "$length" 2>/dev/null)"; then + if _opkey="$(${ACME_OPENSSL_BIN:-openssl} genrsa $__traditional "$length" 2>/dev/null)"; then echo "$_opkey" >"$f" else _err "error rsa key: $length" From ae5a6d330d139c150b6011664a9e55d7d5e899ed Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 15 Feb 2021 21:35:59 +0800 Subject: [PATCH 327/383] make the fix for rsa key only --- acme.sh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/acme.sh b/acme.sh index 2cb9dd00..5e9829a4 100755 --- a/acme.sh +++ b/acme.sh @@ -1122,14 +1122,9 @@ _createkey() { fi fi - __traditional="" - if _contains "$(${ACME_OPENSSL_BIN:-openssl} help genrsa 2>&1)" "-traditional"; then - __traditional="-traditional" - fi - if _isEccKey "$length"; then _debug "Using ec name: $eccname" - if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam $__traditional -name "$eccname" -genkey 2>/dev/null)"; then + if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -genkey 2>/dev/null)"; then echo "$_opkey" >"$f" else _err "error ecc key name: $eccname" @@ -1137,6 +1132,10 @@ _createkey() { fi else _debug "Using RSA: $length" + __traditional="" + if _contains "$(${ACME_OPENSSL_BIN:-openssl} help genrsa 2>&1)" "-traditional"; then + __traditional="-traditional" + fi if _opkey="$(${ACME_OPENSSL_BIN:-openssl} genrsa $__traditional "$length" 2>/dev/null)"; then echo "$_opkey" >"$f" else From dc8d91ea39e897679cf02ecb416758afa8df2ba3 Mon Sep 17 00:00:00 2001 From: medmunds Date: Mon, 15 Feb 2021 12:23:48 -0800 Subject: [PATCH 328/383] Use PROJECT_NAME and VER for X-Mailer header Also add X-Mailer header to Python version --- notify/smtp.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index c9927e3e..bb71a563 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -112,6 +112,7 @@ smtp_send() { _SMTP_USERNAME="$SMTP_USERNAME" _SMTP_PASSWORD="$SMTP_PASSWORD" _SMTP_TIMEOUT="${SMTP_TIMEOUT:-30}" + _SMTP_X_MAILER="${PROJECT_NAME} ${VER} --notify-hook smtp" # Run with --debug 2 (or above) to echo the transcript of the SMTP session. # Careful: this may include SMTP_PASSWORD in plaintext! @@ -232,7 +233,7 @@ _smtp_raw_message() { echo "Date: $(date +'%a, %-d %b %Y %H:%M:%S %z')" fi echo "Content-Type: text/plain; charset=utf-8" - echo "X-Mailer: acme.sh --notify-hook smtp" + echo "X-Mailer: $_SMTP_X_MAILER" echo echo "$_SMTP_CONTENT" } @@ -286,6 +287,7 @@ smtp_secure = """$_SMTP_SECURE""" username = """$_SMTP_USERNAME""" password = """$_SMTP_PASSWORD""" timeout=int("""$_SMTP_TIMEOUT""") # seconds +x_mailer="""$_SMTP_X_MAILER""" from_email="""$_SMTP_FROM""" to_emails="""$_SMTP_TO""" # can be comma-separated @@ -301,6 +303,7 @@ except (AttributeError, TypeError): msg["Subject"] = subject msg["From"] = from_email msg["To"] = to_emails +msg["X-Mailer"] = x_mailer smtp = None try: From d1cdc1c6a0e81fc1201b38869d52e67d192e94a2 Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 16 Feb 2021 09:33:39 -0800 Subject: [PATCH 329/383] Add _clearaccountconf_mutable() --- acme.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/acme.sh b/acme.sh index 5e9829a4..757ed7a5 100755 --- a/acme.sh +++ b/acme.sh @@ -2283,6 +2283,13 @@ _clearaccountconf() { _clear_conf "$ACCOUNT_CONF_PATH" "$1" } +#key +_clearaccountconf_mutable() { + _clearaccountconf "SAVED_$1" + #remove later + _clearaccountconf "$1" +} + #_savecaconf key value _savecaconf() { _save_conf "$CA_CONF" "$1" "$2" From d0445455200076f2470752fad648c61c2c48780c Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 16 Feb 2021 12:49:27 -0800 Subject: [PATCH 330/383] Rework read/save config to not save default values Add and use _readaccountconf_mutable_default and _saveaccountconf_mutable_default helpers to capture common default value handling. New approach also eliminates need for separate underscore-prefixed version of each conf var. --- notify/smtp.sh | 255 +++++++++++++++++++++++++++++-------------------- 1 file changed, 149 insertions(+), 106 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index bb71a563..85801604 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -17,155 +17,150 @@ # SMTP_TIMEOUT="30" # seconds for SMTP operations to timeout # SMTP_BIN="/path/to/curl_or_python" # default finds first of curl, python3, or python on PATH +SMTP_SECURE_DEFAULT="none" +SMTP_TIMEOUT_DEFAULT="30" + # subject content statuscode smtp_send() { - _SMTP_SUBJECT="$1" - _SMTP_CONTENT="$2" + SMTP_SUBJECT="$1" + SMTP_CONTENT="$2" # UNUSED: _statusCode="$3" # 0: success, 1: error 2($RENEW_SKIP): skipped - # Load config: - SMTP_FROM="${SMTP_FROM:-$(_readaccountconf_mutable SMTP_FROM)}" - SMTP_TO="${SMTP_TO:-$(_readaccountconf_mutable SMTP_TO)}" - SMTP_HOST="${SMTP_HOST:-$(_readaccountconf_mutable SMTP_HOST)}" - SMTP_PORT="${SMTP_PORT:-$(_readaccountconf_mutable SMTP_PORT)}" - SMTP_SECURE="${SMTP_SECURE:-$(_readaccountconf_mutable SMTP_SECURE)}" - SMTP_USERNAME="${SMTP_USERNAME:-$(_readaccountconf_mutable SMTP_USERNAME)}" - SMTP_PASSWORD="${SMTP_PASSWORD:-$(_readaccountconf_mutable SMTP_PASSWORD)}" - SMTP_TIMEOUT="${SMTP_TIMEOUT:-$(_readaccountconf_mutable SMTP_TIMEOUT)}" - SMTP_BIN="${SMTP_BIN:-$(_readaccountconf_mutable SMTP_BIN)}" - - _debug "SMTP_FROM" "$SMTP_FROM" - _debug "SMTP_TO" "$SMTP_TO" - _debug "SMTP_HOST" "$SMTP_HOST" - _debug "SMTP_PORT" "$SMTP_PORT" - _debug "SMTP_SECURE" "$SMTP_SECURE" - _debug "SMTP_USERNAME" "$SMTP_USERNAME" - _secure_debug "SMTP_PASSWORD" "$SMTP_PASSWORD" - _debug "SMTP_TIMEOUT" "$SMTP_TIMEOUT" - _debug "SMTP_BIN" "$SMTP_BIN" - - _debug "_SMTP_SUBJECT" "$_SMTP_SUBJECT" - _debug "_SMTP_CONTENT" "$_SMTP_CONTENT" - - # Validate config and apply defaults: - # _SMTP_* variables are the resolved (with defaults) versions of SMTP_*. - # (The _SMTP_* versions will not be stored in account conf.) - + # Load and validate config: + SMTP_BIN="$(_readaccountconf_mutable_default SMTP_BIN)" if [ -n "$SMTP_BIN" ] && ! _exists "$SMTP_BIN"; then _err "SMTP_BIN '$SMTP_BIN' does not exist." return 1 fi - _SMTP_BIN="$SMTP_BIN" - if [ -z "$_SMTP_BIN" ]; then + if [ -z "$SMTP_BIN" ]; then # Look for a command that can communicate with an SMTP server. # (Please don't add sendmail, ssmtp, mutt, mail, or msmtp here. # Those are already handled by the "mail" notify hook.) for cmd in curl python3 python2.7 python pypy3 pypy; do if _exists "$cmd"; then - _SMTP_BIN="$cmd" + SMTP_BIN="$cmd" break fi done - if [ -z "$_SMTP_BIN" ]; then + if [ -z "$SMTP_BIN" ]; then _err "The smtp notify-hook requires curl or Python, but can't find any." _err 'If you have one of them, define SMTP_BIN="/path/to/curl_or_python".' _err 'Otherwise, see if you can use the "mail" notify-hook instead.' return 1 fi - _debug "_SMTP_BIN" "$_SMTP_BIN" fi + _debug SMTP_BIN "$SMTP_BIN" + _saveaccountconf_mutable_default SMTP_BIN "$SMTP_BIN" + SMTP_FROM="$(_readaccountconf_mutable_default SMTP_FROM)" if [ -z "$SMTP_FROM" ]; then _err "You must define SMTP_FROM as the sender email address." return 1 fi - _SMTP_FROM="$SMTP_FROM" + _debug SMTP_FROM "$SMTP_FROM" + _saveaccountconf_mutable_default SMTP_FROM "$SMTP_FROM" + SMTP_TO="$(_readaccountconf_mutable_default SMTP_TO)" if [ -z "$SMTP_TO" ]; then _err "You must define SMTP_TO as the recipient email address." return 1 fi - _SMTP_TO="$SMTP_TO" + _debug SMTP_TO "$SMTP_TO" + _saveaccountconf_mutable_default SMTP_TO "$SMTP_TO" + SMTP_HOST="$(_readaccountconf_mutable_default SMTP_HOST)" if [ -z "$SMTP_HOST" ]; then _err "You must define SMTP_HOST as the SMTP server hostname." return 1 fi - _SMTP_HOST="$SMTP_HOST" - - _SMTP_SECURE="${SMTP_SECURE:-none}" - case "$_SMTP_SECURE" in - "none") smtp_default_port="25" ;; - "ssl") smtp_default_port="465" ;; - "tls") smtp_default_port="587" ;; + _debug SMTP_HOST "$SMTP_HOST" + _saveaccountconf_mutable_default SMTP_HOST "$SMTP_HOST" + + SMTP_SECURE="$(_readaccountconf_mutable_default SMTP_SECURE "$SMTP_SECURE_DEFAULT")" + case "$SMTP_SECURE" in + "none") smtp_port_default="25" ;; + "ssl") smtp_port_default="465" ;; + "tls") smtp_port_default="587" ;; *) _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'." return 1 ;; esac + _debug SMTP_SECURE "$SMTP_SECURE" + _saveaccountconf_mutable_default SMTP_SECURE "$SMTP_SECURE" "$SMTP_SECURE_DEFAULT" - _SMTP_PORT="${SMTP_PORT:-$smtp_default_port}" - if [ -z "$SMTP_PORT" ]; then - _debug "_SMTP_PORT" "$_SMTP_PORT" - fi + SMTP_PORT="$(_readaccountconf_mutable_default SMTP_PORT "$smtp_port_default")" + case "$SMTP_PORT" in + *[!0-9]*) + _err "Invalid SMTP_PORT='$SMTP_PORT'. It must be a port number." + return 1 + ;; + esac + _debug SMTP_PORT "$SMTP_PORT" + _saveaccountconf_mutable_default SMTP_PORT "$SMTP_PORT" "$smtp_port_default" + + SMTP_USERNAME="$(_readaccountconf_mutable_default SMTP_USERNAME)" + _debug SMTP_USERNAME "$SMTP_USERNAME" + _saveaccountconf_mutable_default SMTP_USERNAME "$SMTP_USERNAME" + + SMTP_PASSWORD="$(_readaccountconf_mutable_default SMTP_PASSWORD)" + _secure_debug SMTP_PASSWORD "$SMTP_PASSWORD" + _saveaccountconf_mutable_default SMTP_PASSWORD "$SMTP_PASSWORD" - _SMTP_USERNAME="$SMTP_USERNAME" - _SMTP_PASSWORD="$SMTP_PASSWORD" - _SMTP_TIMEOUT="${SMTP_TIMEOUT:-30}" - _SMTP_X_MAILER="${PROJECT_NAME} ${VER} --notify-hook smtp" + SMTP_TIMEOUT="$(_readaccountconf_mutable_default SMTP_TIMEOUT "$SMTP_TIMEOUT_DEFAULT")" + _debug SMTP_TIMEOUT "$SMTP_TIMEOUT" + _saveaccountconf_mutable_default SMTP_TIMEOUT "$SMTP_TIMEOUT" "$SMTP_TIMEOUT_DEFAULT" + + SMTP_X_MAILER="${PROJECT_NAME} ${VER} --notify-hook smtp" # Run with --debug 2 (or above) to echo the transcript of the SMTP session. # Careful: this may include SMTP_PASSWORD in plaintext! if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then - _SMTP_SHOW_TRANSCRIPT="True" + SMTP_SHOW_TRANSCRIPT="True" else - _SMTP_SHOW_TRANSCRIPT="" + SMTP_SHOW_TRANSCRIPT="" fi + _debug SMTP_SUBJECT "$SMTP_SUBJECT" + _debug SMTP_CONTENT "$SMTP_CONTENT" + # Send the message: - case "$(basename "$_SMTP_BIN")" in + case "$(basename "$SMTP_BIN")" in curl) _smtp_send=_smtp_send_curl ;; py*) _smtp_send=_smtp_send_python ;; *) - _err "Can't figure out how to invoke $_SMTP_BIN." + _err "Can't figure out how to invoke '$SMTP_BIN'." _err "Check your SMTP_BIN setting." return 1 ;; esac if ! smtp_output="$($_smtp_send)"; then - _err "Error sending message with $_SMTP_BIN." + _err "Error sending message with $SMTP_BIN." if [ -n "$smtp_output" ]; then _err "$smtp_output" fi return 1 fi - # Save config only if send was successful: - _saveaccountconf_mutable SMTP_BIN "$SMTP_BIN" - _saveaccountconf_mutable SMTP_FROM "$SMTP_FROM" - _saveaccountconf_mutable SMTP_TO "$SMTP_TO" - _saveaccountconf_mutable SMTP_HOST "$SMTP_HOST" - _saveaccountconf_mutable SMTP_PORT "$SMTP_PORT" - _saveaccountconf_mutable SMTP_SECURE "$SMTP_SECURE" - _saveaccountconf_mutable SMTP_USERNAME "$SMTP_USERNAME" - _saveaccountconf_mutable SMTP_PASSWORD "$SMTP_PASSWORD" - _saveaccountconf_mutable SMTP_TIMEOUT "$SMTP_TIMEOUT" - return 0 } -# Send the message via curl using _SMTP_* variables +## +## curl smtp sending +## + +# Send the message via curl using SMTP_* variables _smtp_send_curl() { # curl passes --mail-from and --mail-rcpt directly to the SMTP protocol without # additional parsing, and SMTP requires addr-spec only (no display names). # In the future, maybe try to parse the addr-spec out for curl args (non-trivial). - if _email_has_display_name "$_SMTP_FROM"; then + if _email_has_display_name "$SMTP_FROM"; then _err "curl smtp only allows a simple email address in SMTP_FROM." _err "Change your SMTP_FROM='$SMTP_FROM' to remove the display name." return 1 fi - if _email_has_display_name "$_SMTP_TO"; then + if _email_has_display_name "$SMTP_TO"; then _err "curl smtp only allows simple email addresses in SMTP_TO." _err "Change your SMTP_TO='$SMTP_TO' to remove the display name(s)." return 1 @@ -173,20 +168,20 @@ _smtp_send_curl() { # Build curl args in $@ - case "$_SMTP_SECURE" in + case "$SMTP_SECURE" in none) - set -- --url "smtp://${_SMTP_HOST}:${_SMTP_PORT}" + set -- --url "smtp://${SMTP_HOST}:${SMTP_PORT}" ;; ssl) - set -- --url "smtps://${_SMTP_HOST}:${_SMTP_PORT}" + set -- --url "smtps://${SMTP_HOST}:${SMTP_PORT}" ;; tls) - set -- --url "smtp://${_SMTP_HOST}:${_SMTP_PORT}" --ssl-reqd + set -- --url "smtp://${SMTP_HOST}:${SMTP_PORT}" --ssl-reqd ;; *) # This will only occur if someone adds a new SMTP_SECURE option above # without updating this code for it. - _err "Unhandled _SMTP_SECURE='$_SMTP_SECURE' in _smtp_send_curl" + _err "Unhandled SMTP_SECURE='$SMTP_SECURE' in _smtp_send_curl" _err "Please re-run with --debug and report a bug." return 1 ;; @@ -194,23 +189,23 @@ _smtp_send_curl() { set -- "$@" \ --upload-file - \ - --mail-from "$_SMTP_FROM" \ - --max-time "$_SMTP_TIMEOUT" + --mail-from "$SMTP_FROM" \ + --max-time "$SMTP_TIMEOUT" - # Burst comma-separated $_SMTP_TO into individual --mail-rcpt args. - _to="${_SMTP_TO}," + # Burst comma-separated $SMTP_TO into individual --mail-rcpt args. + _to="${SMTP_TO}," while [ -n "$_to" ]; do _rcpt="${_to%%,*}" _to="${_to#*,}" set -- "$@" --mail-rcpt "$_rcpt" done - _smtp_login="${_SMTP_USERNAME}:${_SMTP_PASSWORD}" + _smtp_login="${SMTP_USERNAME}:${SMTP_PASSWORD}" if [ "$_smtp_login" != ":" ]; then set -- "$@" --user "$_smtp_login" fi - if [ "$_SMTP_SHOW_TRANSCRIPT" = "True" ]; then + if [ "$SMTP_SHOW_TRANSCRIPT" = "True" ]; then set -- "$@" --verbose else set -- "$@" --silent --show-error @@ -218,24 +213,24 @@ _smtp_send_curl() { raw_message="$(_smtp_raw_message)" - _debug2 "curl command:" "$_SMTP_BIN" "$*" + _debug2 "curl command:" "$SMTP_BIN" "$*" _debug2 "raw_message:\n$raw_message" - echo "$raw_message" | "$_SMTP_BIN" "$@" + echo "$raw_message" | "$SMTP_BIN" "$@" } -# Output an RFC-822 / RFC-5322 email message using _SMTP_* variables +# Output an RFC-822 / RFC-5322 email message using SMTP_* variables _smtp_raw_message() { - echo "From: $_SMTP_FROM" - echo "To: $_SMTP_TO" - echo "Subject: $(_mime_encoded_word "$_SMTP_SUBJECT")" + echo "From: $SMTP_FROM" + echo "To: $SMTP_TO" + echo "Subject: $(_mime_encoded_word "$SMTP_SUBJECT")" if _exists date; then echo "Date: $(date +'%a, %-d %b %Y %H:%M:%S %z')" fi echo "Content-Type: text/plain; charset=utf-8" - echo "X-Mailer: $_SMTP_X_MAILER" + echo "X-Mailer: $SMTP_X_MAILER" echo - echo "$_SMTP_CONTENT" + echo "$SMTP_CONTENT" } # Convert text to RFC-2047 MIME "encoded word" format if it contains non-ASCII chars @@ -260,12 +255,16 @@ _email_has_display_name() { expr "$_email" : '^.*[<>"]' >/dev/null } -# Send the message via Python using _SMTP_* variables +## +## Python smtp sending +## + +# Send the message via Python using SMTP_* variables _smtp_send_python() { - _debug "Python version" "$("$_SMTP_BIN" --version 2>&1)" + _debug "Python version" "$("$SMTP_BIN" --version 2>&1)" # language=Python - "$_SMTP_BIN" < Date: Tue, 16 Feb 2021 13:13:26 -0800 Subject: [PATCH 331/383] Implement _rfc2822_date helper --- notify/smtp.sh | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 85801604..43536cd2 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -224,9 +224,7 @@ _smtp_raw_message() { echo "From: $SMTP_FROM" echo "To: $SMTP_TO" echo "Subject: $(_mime_encoded_word "$SMTP_SUBJECT")" - if _exists date; then - echo "Date: $(date +'%a, %-d %b %Y %H:%M:%S %z')" - fi + echo "Date: $(_rfc2822_date)" echo "Content-Type: text/plain; charset=utf-8" echo "X-Mailer: $SMTP_X_MAILER" echo @@ -248,6 +246,19 @@ _mime_encoded_word() { fi } +# Output current date in RFC-2822 Section 3.3 format as required in email headers +# (e.g., "Mon, 15 Feb 2021 14:22:01 -0800") +_rfc2822_date() { + # Notes: + # - this is deliberately not UTC, because it "SHOULD express local time" per spec + # - the spec requires weekday and month in the C locale (English), not localized + # - this date format specifier has been tested on Linux, Mac, Solaris and FreeBSD + _old_lc_time="$LC_TIME" + LC_TIME=C + date +'%a, %-d %b %Y %H:%M:%S %z' + LC_TIME="$_old_lc_time" +} + # Simple check for display name in an email address (< > or ") # email _email_has_display_name() { From 1330a092fae83fbd831fb51f648209d1ed3b7bff Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 16 Feb 2021 14:02:09 -0800 Subject: [PATCH 332/383] Clean email headers and warn on unsupported address format Just in case, make sure CR or NL don't end up in an email header. --- notify/smtp.sh | 55 +++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 43536cd2..42c1487c 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -53,16 +53,28 @@ smtp_send() { _saveaccountconf_mutable_default SMTP_BIN "$SMTP_BIN" SMTP_FROM="$(_readaccountconf_mutable_default SMTP_FROM)" + SMTP_FROM="$(_clean_email_header "$SMTP_FROM")" if [ -z "$SMTP_FROM" ]; then _err "You must define SMTP_FROM as the sender email address." return 1 fi + if _email_has_display_name "$SMTP_FROM"; then + _err "SMTP_FROM must be only a simple email address (sender@example.com)." + _err "Change your SMTP_FROM='$SMTP_FROM' to remove the display name." + return 1 + fi _debug SMTP_FROM "$SMTP_FROM" _saveaccountconf_mutable_default SMTP_FROM "$SMTP_FROM" SMTP_TO="$(_readaccountconf_mutable_default SMTP_TO)" + SMTP_TO="$(_clean_email_header "$SMTP_TO")" if [ -z "$SMTP_TO" ]; then - _err "You must define SMTP_TO as the recipient email address." + _err "You must define SMTP_TO as the recipient email address(es)." + return 1 + fi + if _email_has_display_name "$SMTP_TO"; then + _err "SMTP_TO must be only simple email addresses (to@example.com,to2@example.com)." + _err "Change your SMTP_TO='$SMTP_TO' to remove the display name(s)." return 1 fi _debug SMTP_TO "$SMTP_TO" @@ -111,7 +123,7 @@ smtp_send() { _debug SMTP_TIMEOUT "$SMTP_TIMEOUT" _saveaccountconf_mutable_default SMTP_TIMEOUT "$SMTP_TIMEOUT" "$SMTP_TIMEOUT_DEFAULT" - SMTP_X_MAILER="${PROJECT_NAME} ${VER} --notify-hook smtp" + SMTP_X_MAILER="$(_clean_email_header "$PROJECT_NAME $VER --notify-hook smtp")" # Run with --debug 2 (or above) to echo the transcript of the SMTP session. # Careful: this may include SMTP_PASSWORD in plaintext! @@ -121,6 +133,7 @@ smtp_send() { SMTP_SHOW_TRANSCRIPT="" fi + SMTP_SUBJECT=$(_clean_email_header "$SMTP_SUBJECT") _debug SMTP_SUBJECT "$SMTP_SUBJECT" _debug SMTP_CONTENT "$SMTP_CONTENT" @@ -146,28 +159,26 @@ smtp_send() { return 0 } +# Strip CR and NL from text to prevent MIME header injection +# text +_clean_email_header() { + printf "%s" "$(echo "$1" | tr -d "\r\n")" +} + +# Simple check for display name in an email address (< > or ") +# email +_email_has_display_name() { + _email="$1" + expr "$_email" : '^.*[<>"]' >/dev/null +} + ## ## curl smtp sending ## # Send the message via curl using SMTP_* variables _smtp_send_curl() { - # curl passes --mail-from and --mail-rcpt directly to the SMTP protocol without - # additional parsing, and SMTP requires addr-spec only (no display names). - # In the future, maybe try to parse the addr-spec out for curl args (non-trivial). - if _email_has_display_name "$SMTP_FROM"; then - _err "curl smtp only allows a simple email address in SMTP_FROM." - _err "Change your SMTP_FROM='$SMTP_FROM' to remove the display name." - return 1 - fi - if _email_has_display_name "$SMTP_TO"; then - _err "curl smtp only allows simple email addresses in SMTP_TO." - _err "Change your SMTP_TO='$SMTP_TO' to remove the display name(s)." - return 1 - fi - # Build curl args in $@ - case "$SMTP_SECURE" in none) set -- --url "smtp://${SMTP_HOST}:${SMTP_PORT}" @@ -219,7 +230,8 @@ _smtp_send_curl() { echo "$raw_message" | "$SMTP_BIN" "$@" } -# Output an RFC-822 / RFC-5322 email message using SMTP_* variables +# Output an RFC-822 / RFC-5322 email message using SMTP_* variables. +# (This assumes variables have already been cleaned for use in email headers.) _smtp_raw_message() { echo "From: $SMTP_FROM" echo "To: $SMTP_TO" @@ -259,13 +271,6 @@ _rfc2822_date() { LC_TIME="$_old_lc_time" } -# Simple check for display name in an email address (< > or ") -# email -_email_has_display_name() { - _email="$1" - expr "$_email" : '^.*[<>"]' >/dev/null -} - ## ## Python smtp sending ## From eb1606b086959eae973365fea6ba0fcad380f908 Mon Sep 17 00:00:00 2001 From: medmunds Date: Tue, 16 Feb 2021 14:41:21 -0800 Subject: [PATCH 333/383] Clarify _readaccountconf_mutable_default --- notify/smtp.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 42c1487c..fabde79b 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -358,7 +358,7 @@ PYTHON # - if MY_CONF is set _empty_, output $default_value # (lets user `export MY_CONF=` to clear previous saved value # and return to default, without user having to know default) -# - otherwise if _readaccountconf_mutable $name is non-empty, return that +# - otherwise if _readaccountconf_mutable MY_CONF is non-empty, return that # (value of SAVED_MY_CONF from account.conf) # - otherwise output $default_value _readaccountconf_mutable_default() { @@ -366,8 +366,9 @@ _readaccountconf_mutable_default() { _default_value="$2" eval "_value=\"\$$_name\"" - eval "_explicit_empty_value=\"\${${_name}+empty}\"" - if [ -z "${_value}" ] && [ "${_explicit_empty_value:-}" != "empty" ]; then + eval "_name_is_set=\"\${${_name}+true}\"" + # ($_name_is_set is "true" if $$_name is set to anything, including empty) + if [ -z "${_value}" ] && [ "${_name_is_set:-}" != "true" ]; then _value="$(_readaccountconf_mutable "$_name")" fi if [ -z "${_value}" ]; then From 3503474bb8e7d5647d20ceda988b398cab21cbca Mon Sep 17 00:00:00 2001 From: medmunds Date: Wed, 17 Feb 2021 09:46:13 -0800 Subject: [PATCH 334/383] Add Date email header in Python implementation --- notify/smtp.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/notify/smtp.sh b/notify/smtp.sh index fabde79b..0c698631 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -287,6 +287,7 @@ try: from email.message import EmailMessage except ImportError: from email.mime.text import MIMEText as EmailMessage # Python 2 + from email.utils import formatdate as rfc2822_date from smtplib import SMTP, SMTP_SSL, SMTPException from socket import error as SocketError except ImportError as err: @@ -318,6 +319,7 @@ except (AttributeError, TypeError): msg["Subject"] = subject msg["From"] = from_email msg["To"] = to_emails +msg["Date"] = rfc2822_date(localtime=True) msg["X-Mailer"] = x_mailer smtp = None From d8918ea1565b9ae6a575b78f0e6c14092710e8f2 Mon Sep 17 00:00:00 2001 From: medmunds Date: Wed, 17 Feb 2021 09:57:44 -0800 Subject: [PATCH 335/383] Use email.policy.default in Python 3 implementation Improves standards compatibility and utf-8 handling in Python 3.3-3.8. (email.policy.default becomes the default in Python 3.9.) --- notify/smtp.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 0c698631..69863206 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -285,8 +285,11 @@ _smtp_send_python() { try: try: from email.message import EmailMessage + from email.policy import default as email_policy_default except ImportError: - from email.mime.text import MIMEText as EmailMessage # Python 2 + # Python 2 (or < 3.3) + from email.mime.text import MIMEText as EmailMessage + email_policy_default = None from email.utils import formatdate as rfc2822_date from smtplib import SMTP, SMTP_SSL, SMTPException from socket import error as SocketError @@ -311,7 +314,7 @@ subject="""$SMTP_SUBJECT""" content="""$SMTP_CONTENT""" try: - msg = EmailMessage() + msg = EmailMessage(policy=email_policy_default) msg.set_content(content) except (AttributeError, TypeError): # Python 2 MIMEText From db967780641780ddaf35e01b0aaee50ffd160a50 Mon Sep 17 00:00:00 2001 From: medmunds Date: Wed, 17 Feb 2021 10:02:14 -0800 Subject: [PATCH 336/383] Prefer Python to curl when both available --- notify/smtp.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 69863206..71020818 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -15,7 +15,7 @@ # SMTP_USERNAME="" # set if SMTP server requires login # SMTP_PASSWORD="" # set if SMTP server requires login # SMTP_TIMEOUT="30" # seconds for SMTP operations to timeout -# SMTP_BIN="/path/to/curl_or_python" # default finds first of curl, python3, or python on PATH +# SMTP_BIN="/path/to/python_or_curl" # default finds first of python3, python2.7, python, pypy3, pypy, curl on PATH SMTP_SECURE_DEFAULT="none" SMTP_TIMEOUT_DEFAULT="30" @@ -36,7 +36,7 @@ smtp_send() { # Look for a command that can communicate with an SMTP server. # (Please don't add sendmail, ssmtp, mutt, mail, or msmtp here. # Those are already handled by the "mail" notify hook.) - for cmd in curl python3 python2.7 python pypy3 pypy; do + for cmd in python3 python2.7 python pypy3 pypy curl; do if _exists "$cmd"; then SMTP_BIN="$cmd" break From 06f51a5c34b418d991a672c8bbcd56b76f7b86ec Mon Sep 17 00:00:00 2001 From: medmunds Date: Wed, 17 Feb 2021 11:39:16 -0800 Subject: [PATCH 337/383] Change default SMTP_SECURE to "tls" Secure by default. Also try to minimize configuration errors. (Many ESPs/ISPs require STARTTLS, and most support it.) --- notify/smtp.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notify/smtp.sh b/notify/smtp.sh index 71020818..293c665e 100644 --- a/notify/smtp.sh +++ b/notify/smtp.sh @@ -11,13 +11,13 @@ # SMTP_TO="to@example.com" # required # SMTP_HOST="smtp.example.com" # required # SMTP_PORT="25" # defaults to 25, 465 or 587 depending on SMTP_SECURE -# SMTP_SECURE="none" # one of "none", "ssl" (implicit TLS, TLS Wrapper), "tls" (explicit TLS, STARTTLS) +# SMTP_SECURE="tls" # one of "none", "ssl" (implicit TLS, TLS Wrapper), "tls" (explicit TLS, STARTTLS) # SMTP_USERNAME="" # set if SMTP server requires login # SMTP_PASSWORD="" # set if SMTP server requires login # SMTP_TIMEOUT="30" # seconds for SMTP operations to timeout # SMTP_BIN="/path/to/python_or_curl" # default finds first of python3, python2.7, python, pypy3, pypy, curl on PATH -SMTP_SECURE_DEFAULT="none" +SMTP_SECURE_DEFAULT="tls" SMTP_TIMEOUT_DEFAULT="30" # subject content statuscode From d078ce794ee73b4c98d9d520e339c48de6bb7f30 Mon Sep 17 00:00:00 2001 From: czeming Date: Sat, 20 Feb 2021 17:16:33 +0800 Subject: [PATCH 338/383] Update dns_dp.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 没有encode中文字符会导致提交失败 --- dnsapi/dns_dp.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_dp.sh b/dnsapi/dns_dp.sh index 033fa5aa..9b8b7a8b 100755 --- a/dnsapi/dns_dp.sh +++ b/dnsapi/dns_dp.sh @@ -89,7 +89,7 @@ add_record() { _info "Adding record" - if ! _rest POST "Record.Create" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=默认"; then + if ! _rest POST "Record.Create" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=%E9%BB%98%E8%AE%A4"; then return 1 fi From a290f63a15d9e8f8784e735da17c617476e89c51 Mon Sep 17 00:00:00 2001 From: Geert Hendrickx Date: Tue, 23 Feb 2021 10:28:17 +0100 Subject: [PATCH 339/383] No need to include EC parameters explicitly with the private key. (they are embedded) --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 757ed7a5..3c66250e 100755 --- a/acme.sh +++ b/acme.sh @@ -1124,7 +1124,7 @@ _createkey() { if _isEccKey "$length"; then _debug "Using ec name: $eccname" - if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -genkey 2>/dev/null)"; then + if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -noout -genkey 2>/dev/null)"; then echo "$_opkey" >"$f" else _err "error ecc key name: $eccname" From b0f5ad75aee5fa70f7f4a83e9eb1a9ed6c025c77 Mon Sep 17 00:00:00 2001 From: Kristian Johansson Date: Wed, 24 Feb 2021 08:53:35 +0100 Subject: [PATCH 340/383] Fixes response handling and thereby allow issuing of subdomain certs --- dnsapi/dns_simply.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index d053dcf6..b38d0ed3 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -6,7 +6,7 @@ #SIMPLY_ApiKey="apikey" # #SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]" - +SIMPLY_SUCCESS_CODE='"status": 200' SIMPLY_Api_Default="https://api.simply.com/1" ######## Public functions ##################### @@ -171,7 +171,7 @@ _get_root() { return 1 fi - if _contains "$response" '"code":"NOT_FOUND"'; then + if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then _debug "$h not found" else _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) @@ -196,6 +196,12 @@ _simply_add_record() { return 1 fi + if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then + _err "Call to API not sucessfull, see below message for more details" + _err "$response" + return 1 + fi + return 0 } @@ -211,6 +217,12 @@ _simply_delete_record() { return 1 fi + if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then + _err "Call to API not sucessfull, see below message for more details" + _err "$response" + return 1 + fi + return 0 } From 0fe3538331e8380cbab6d9707144a88ada534456 Mon Sep 17 00:00:00 2001 From: Kristian Johansson Date: Wed, 24 Feb 2021 17:34:28 +0100 Subject: [PATCH 341/383] Adds comment --- dnsapi/dns_simply.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index b38d0ed3..e0e05017 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -6,9 +6,11 @@ #SIMPLY_ApiKey="apikey" # #SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]" -SIMPLY_SUCCESS_CODE='"status": 200' SIMPLY_Api_Default="https://api.simply.com/1" +#This is used for determining success of REST call +SIMPLY_SUCCESS_CODE='"status": 200' + ######## Public functions ##################### #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_simply_add() { From 9e5ae30372a273fc5a3e279e370c637609c39a99 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 25 Feb 2021 07:45:22 +0800 Subject: [PATCH 342/383] fix https://github.com/acmesh-official/acme.sh/issues/3402 --- acme.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 3c66250e..24cda9c4 100755 --- a/acme.sh +++ b/acme.sh @@ -562,8 +562,16 @@ if _exists xargs && [ "$(printf %s '\\x41' | xargs printf)" = 'A' ]; then fi _h2b() { - if _exists xxd && xxd -r -p 2>/dev/null; then - return + if _exists xxd; then + if _contains "$(xxd --help 2>&1)" "assumes -c30"; then + if xxd -r -p -c 9999 2>/dev/null; then + return + fi + else + if xxd -r -p 2>/dev/null; then + return + fi + fi fi hex=$(cat) From fd406af9623e8e67b710d8b0787b25850225ac3b Mon Sep 17 00:00:00 2001 From: Lukas Brocke Date: Tue, 23 Feb 2021 19:49:58 +0100 Subject: [PATCH 343/383] dnsapi/ionos: Use POST instead of PATCH for adding TXT record The API now supports a POST route for adding records. Therefore checking for already existing records and including them in a PATCH request is no longer necessary. --- dnsapi/dns_ionos.sh | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/dnsapi/dns_ionos.sh b/dnsapi/dns_ionos.sh index e6bd5000..aaf8580f 100755 --- a/dnsapi/dns_ionos.sh +++ b/dnsapi/dns_ionos.sh @@ -24,20 +24,9 @@ dns_ionos_add() { return 1 fi - _new_record="{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}" + _body="[{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}]" - # As no POST route is supported by the API, check for existing records and include them in the PATCH request in order not delete them. - # This is required to support ACME v2 wildcard certificate creation, where two TXT records for the same domain name are created. - - _ionos_get_existing_records "$fulldomain" "$_zone_id" - - if [ "$_existing_records" ]; then - _body="[$_new_record,$_existing_records]" - else - _body="[$_new_record]" - fi - - if _ionos_rest PATCH "$IONOS_ROUTE_ZONES/$_zone_id" "$_body" && [ -z "$response" ]; then + if _ionos_rest POST "$IONOS_ROUTE_ZONES/$_zone_id/records" "$_body" && [ -z "$response" ]; then _info "TXT record has been created successfully." return 0 fi @@ -125,17 +114,6 @@ _get_root() { return 1 } -_ionos_get_existing_records() { - fulldomain=$1 - zone_id=$2 - - if _ionos_rest GET "$IONOS_ROUTE_ZONES/$zone_id?recordName=$fulldomain&recordType=TXT"; then - response="$(echo "$response" | tr -d "\n")" - - _existing_records="$(printf "%s\n" "$response" | _egrep_o "\"records\":\[.*\]" | _head_n 1 | cut -d '[' -f 2 | sed 's/]//')" - fi -} - _ionos_get_record() { fulldomain=$1 zone_id=$2 @@ -168,7 +146,7 @@ _ionos_rest() { export _H2="Accept: application/json" export _H3="Content-Type: application/json" - response="$(_post "$data" "$IONOS_API$route" "" "$method")" + response="$(_post "$data" "$IONOS_API$route" "" "$method" "application/json")" else export _H2="Accept: */*" From 5a30f5c00ef3e1a5a1d5c6284056abfcafe420f3 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 1 Mar 2021 18:13:50 +0800 Subject: [PATCH 344/383] fix https://github.com/acmesh-official/acme.sh/issues/3433 --- acme.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/acme.sh b/acme.sh index 24cda9c4..748363e8 100755 --- a/acme.sh +++ b/acme.sh @@ -2133,6 +2133,12 @@ _send_signed_request() { _sleep $_sleep_retry_sec continue fi + if _contains "$_body" "The Replay Nonce is not recognized"; then + _info "The replay Nonce is not valid, let's get a new one, Sleeping $_sleep_retry_sec seconds." + _CACHED_NONCE="" + _sleep $_sleep_retry_sec + continue + fi fi return 0 done From 7dce465c0662db6f5b55e5bbc8441e1f4ef13a84 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 4 Mar 2021 21:38:51 +0800 Subject: [PATCH 345/383] fix https://github.com/acmesh-official/acme.sh/issues/3019 --- dnsapi/dns_namecheap.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index 7ce39fa9..5e1f4791 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -208,7 +208,7 @@ _namecheap_parse_host() { _hostid=$(echo "$_host" | _egrep_o ' HostId="[^"]*' | cut -d '"' -f 2) _hostname=$(echo "$_host" | _egrep_o ' Name="[^"]*' | cut -d '"' -f 2) _hosttype=$(echo "$_host" | _egrep_o ' Type="[^"]*' | cut -d '"' -f 2) - _hostaddress=$(echo "$_host" | _egrep_o ' Address="[^"]*' | cut -d '"' -f 2) + _hostaddress=$(echo "$_host" | _egrep_o ' Address="[^"]*' | cut -d '"' -f 2 | _xml_decode) _hostmxpref=$(echo "$_host" | _egrep_o ' MXPref="[^"]*' | cut -d '"' -f 2) _hostttl=$(echo "$_host" | _egrep_o ' TTL="[^"]*' | cut -d '"' -f 2) @@ -405,3 +405,11 @@ _namecheap_set_tld_sld() { done } + +_xml_decode() { + sed 's/"/"/g' +} + + + + From d4fb313ff0363fd31f308a301ea7fbfccdb79f84 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 4 Mar 2021 21:50:54 +0800 Subject: [PATCH 346/383] fix format --- dnsapi/dns_namecheap.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index 5e1f4791..e3dc7997 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -410,6 +410,3 @@ _xml_decode() { sed 's/"/"/g' } - - - From 923eece3f50f455c076da8e101a1c15ba3031653 Mon Sep 17 00:00:00 2001 From: anom-human <80478363+anom-human@users.noreply.github.com> Date: Thu, 11 Mar 2021 19:11:02 +0100 Subject: [PATCH 347/383] Update dns_servercow.sh to support wildcard certs Updated dns_servercow.sh to support txt records with multiple entries. This supports wildcard certificates that require txt records with the same name and different contents. --- dnsapi/dns_servercow.sh | 42 +++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_servercow.sh b/dnsapi/dns_servercow.sh index e73d85b0..39f16396 100755 --- a/dnsapi/dns_servercow.sh +++ b/dnsapi/dns_servercow.sh @@ -48,18 +48,44 @@ dns_servercow_add() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - - if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then - if printf -- "%s" "$response" | grep "ok" >/dev/null; then - _info "Added, OK" - return 0 + + # check whether a txt record already exists for the subdomain + if printf -- "%s" "$response" | grep "{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\"" >/dev/null; then + _info "A txt record with the same name already exists." + # trim the string on the left + txtvalue_old=${response#*{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\",\"content\":\"} + # trim the string on the right + txtvalue_old=${txtvalue_old%%\"*} + + _debug txtvalue_old "$txtvalue_old" + + _info "Add the new txtvalue to the existing txt record." + if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":[\"$txtvalue\",\"$txtvalue_old\"],\"ttl\":20}"; then + if printf -- "%s" "$response" | grep "ok" >/dev/null; then + _info "Added additional txtvalue, OK" + return 0 + else + _err "add txt record error." + return 1 + fi + fi + _err "add txt record error." + return 1 else + _info "There is no txt record with the name yet." + if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then + if printf -- "%s" "$response" | grep "ok" >/dev/null; then + _info "Added, OK" + return 0 + else + _err "add txt record error." + return 1 + fi + fi _err "add txt record error." return 1 - fi fi - _err "add txt record error." - + return 1 } From 2cbf3f7e158567848e8451ff80754c32f3841b9c Mon Sep 17 00:00:00 2001 From: anom-human <80478363+anom-human@users.noreply.github.com> Date: Thu, 11 Mar 2021 20:25:49 +0100 Subject: [PATCH 348/383] Update dns_servercow.sh to support wildcard certs Updated dns_servercow.sh to support txt records with multiple entries. This supports wildcard certificates that require txt records with the same name and different contents. --- dnsapi/dns_servercow.sh | 64 ++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/dnsapi/dns_servercow.sh b/dnsapi/dns_servercow.sh index 39f16396..f70a2294 100755 --- a/dnsapi/dns_servercow.sh +++ b/dnsapi/dns_servercow.sh @@ -48,44 +48,44 @@ dns_servercow_add() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - - # check whether a txt record already exists for the subdomain + + # check whether a txt record already exists for the subdomain if printf -- "%s" "$response" | grep "{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\"" >/dev/null; then - _info "A txt record with the same name already exists." - # trim the string on the left - txtvalue_old=${response#*{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\",\"content\":\"} - # trim the string on the right - txtvalue_old=${txtvalue_old%%\"*} - - _debug txtvalue_old "$txtvalue_old" - - _info "Add the new txtvalue to the existing txt record." - if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":[\"$txtvalue\",\"$txtvalue_old\"],\"ttl\":20}"; then - if printf -- "%s" "$response" | grep "ok" >/dev/null; then - _info "Added additional txtvalue, OK" - return 0 - else - _err "add txt record error." + _info "A txt record with the same name already exists." + # trim the string on the left + txtvalue_old=${response#*{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\",\"content\":\"} + # trim the string on the right + txtvalue_old=${txtvalue_old%%\"*} + + _debug txtvalue_old "$txtvalue_old" + + _info "Add the new txtvalue to the existing txt record." + if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":[\"$txtvalue\",\"$txtvalue_old\"],\"ttl\":20}"; then + if printf -- "%s" "$response" | grep "ok" >/dev/null; then + _info "Added additional txtvalue, OK" + return 0 + else + _err "add txt record error." return 1 - fi fi - _err "add txt record error." - return 1 - else - _info "There is no txt record with the name yet." - if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then - if printf -- "%s" "$response" | grep "ok" >/dev/null; then - _info "Added, OK" - return 0 - else - _err "add txt record error." + fi + _err "add txt record error." + return 1 + else + _info "There is no txt record with the name yet." + if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then + if printf -- "%s" "$response" | grep "ok" >/dev/null; then + _info "Added, OK" + return 0 + else + _err "add txt record error." return 1 - fi fi - _err "add txt record error." - return 1 + fi + _err "add txt record error." + return 1 fi - + return 1 } From 69ee81654149962691513c3586254ce8bea4d890 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 13 Mar 2021 20:43:25 +0800 Subject: [PATCH 349/383] fix https://github.com/acmesh-official/acme.sh/issues/3312 --- acme.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 748363e8..8d422719 100755 --- a/acme.sh +++ b/acme.sh @@ -5287,6 +5287,7 @@ signcsr() { _renew_hook="${10}" _local_addr="${11}" _challenge_alias="${12}" + _preferred_chain="${13}" _csrsubj=$(_readSubjectFromCSR "$_csrfile") if [ "$?" != "0" ]; then @@ -5333,7 +5334,7 @@ signcsr() { _info "Copy csr to: $CSR_PATH" cp "$_csrfile" "$CSR_PATH" - issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_addr" "$_challenge_alias" + issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_addr" "$_challenge_alias" "$_preferred_chain" } @@ -7430,7 +7431,7 @@ _process() { deploy "$_domain" "$_deploy_hook" "$_ecc" ;; signcsr) - signcsr "$_csr" "$_webroot" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" + signcsr "$_csr" "$_webroot" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" "$_preferred_chain" ;; showcsr) showcsr "$_csr" "$_domain" From 2b2bce64579908642c340e9bebdbc526a03347ea Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 13 Mar 2021 20:46:12 +0800 Subject: [PATCH 350/383] fix format --- dnsapi/dns_namecheap.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index e3dc7997..d15d6b0e 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -409,4 +409,3 @@ _namecheap_set_tld_sld() { _xml_decode() { sed 's/"/"/g' } - From 42ab98b83087cdf459520c895d567a7c81a17203 Mon Sep 17 00:00:00 2001 From: Quentin Dreyer Date: Fri, 12 Mar 2021 12:03:36 +0100 Subject: [PATCH 351/383] feat: add dns_porkbun --- dnsapi/dns_porkbun.sh | 171 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 dnsapi/dns_porkbun.sh diff --git a/dnsapi/dns_porkbun.sh b/dnsapi/dns_porkbun.sh new file mode 100644 index 00000000..05ecb781 --- /dev/null +++ b/dnsapi/dns_porkbun.sh @@ -0,0 +1,171 @@ +#!/usr/bin/env sh + +# +#PORKBUN_API_KEY="pk1_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" +#PORKBUN_SECRET_API_KEY="sk1_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + +PORKBUN_Api="https://porkbun.com/api/json/v3" + +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_porkbun_add() { + fulldomain=$1 + txtvalue=$2 + + PORKBUN_API_KEY="${PORKBUN_API_KEY:-$(_readaccountconf_mutable PORKBUN_API_KEY)}" + PORKBUN_SECRET_API_KEY="${PORKBUN_SECRET_API_KEY:-$(_readaccountconf_mutable PORKBUN_SECRET_API_KEY)}" + + if [ -z "$PORKBUN_API_KEY" ] || [ -z "$PORKBUN_SECRET_API_KEY" ]; then + PORKBUN_API_KEY='' + PORKBUN_SECRET_API_KEY='' + _err "You didn't specify a Porkbun api key and secret api key yet." + _err "You can get yours from here https://porkbun.com/account/api." + return 1 + fi + + #save the credentials to the account conf file. + _saveaccountconf_mutable PORKBUN_API_KEY "$PORKBUN_API_KEY" + _saveaccountconf_mutable PORKBUN_SECRET_API_KEY "$PORKBUN_SECRET_API_KEY" + + _debug 'First detect the root zone' + if ! _get_root "$fulldomain"; then + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting txt records" + _porkbun_rest POST "dns/retrieve/$_domain" + + if ! echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null; then + _err "Error $response" + return 1 + fi + + # For wildcard cert, the main root domain and the wildcard domain have the same txt subdomain name, so + # we can not use updating anymore. + # count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2) + # _debug count "$count" + # if [ "$count" = "0" ]; then + _info "Adding record" + if _porkbun_rest POST "dns/create/$_domain" "{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":120}"; then + if _contains "$response" '\"status\":"SUCCESS"'; then + _info "Added, OK" + return 0 + elif _contains "$response" "The record already exists"; then + _info "Already exists, OK" + return 0 + else + _err "Add txt record error. ($response)" + return 1 + fi + fi + _err "Add txt record error." + return 1 + +} + +#fulldomain txtvalue +dns_porkbun_rm() { + fulldomain=$1 + txtvalue=$2 + + PORKBUN_API_KEY="${PORKBUN_API_KEY:-$(_readaccountconf_mutable PORKBUN_API_KEY)}" + PORKBUN_SECRET_API_KEY="${PORKBUN_SECRET_API_KEY:-$(_readaccountconf_mutable PORKBUN_SECRET_API_KEY)}" + + _debug 'First detect the root zone' + if ! _get_root "$fulldomain"; then + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting txt records" + _porkbun_rest POST "dns/retrieve/$_domain" + + if ! echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null; then + _err "Error: $response" + return 1 + fi + + count=$(echo "$response" | _egrep_o "\"count\": *[^,]*" | cut -d : -f 2 | tr -d " ") + _debug count "$count" + if [ "$count" = "0" ]; then + _info "Don't need to remove." + else + record_id=$(echo "$response" | tr '{' '\n' | grep "$txtvalue" | cut -d, -f1 | cut -d: -f2 | tr -d \") + _debug "record_id" "$record_id" + if [ -z "$record_id" ]; then + _err "Can not get record id to remove." + return 1 + fi + if ! _porkbun_rest POST "dns/delete/$_domain/$record_id"; then + _err "Delete record error." + return 1 + fi + echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null + fi + +} + +#################### Private functions below ################################## +#_acme-challenge.www.domain.com +#returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +_get_root() { + domain=$1 + i=1 + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug h "$h" + if [ -z "$h" ]; then + return 1 + fi + + if _porkbun_rest POST "dns/retrieve/$h"; then + if _contains "$response" "\"status\":\"SUCCESS\""; then + _sub_domain="$(echo "$fulldomain" | sed "s/\\.$_domain\$//")" + _domain=$h + return 0 + else + _debug "Go to next level of $_domain" + fi + else + _debug "Go to next level of $_domain" + fi + i=$(_math "$i" + 1) + done + + return 1 +} + +_porkbun_rest() { + m=$1 + ep="$2" + data="$3" + _debug "$ep" + + api_key_trimmed=$(echo "$PORKBUN_API_KEY" | tr -d '"') + secret_api_key_trimmed=$(echo "$PORKBUN_SECRET_API_KEY" | tr -d '"') + + test -z "$data" && data="{" || data="$(echo $data | cut -d'}' -f1)," + data="$data\"apikey\":\"$api_key_trimmed\",\"secretapikey\":\"$secret_api_key_trimmed\"}" + + export _H1="Content-Type: application/json" + + if [ "$m" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$PORKBUN_Api/$ep" "" "$m")" + else + response="$(_get "$PORKBUN_Api/$ep")" + fi + + if [ "$?" != "0" ]; then + _err "error $ep" + return 1 + fi + _debug2 response "$response" + return 0 +} From 4dd202742869c6cb840d7d76fa9ae03530b8fe1a Mon Sep 17 00:00:00 2001 From: qkdreyer Date: Sat, 13 Mar 2021 14:53:43 +0100 Subject: [PATCH 352/383] fix: prevent rate limit --- dnsapi/dns_porkbun.sh | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/dnsapi/dns_porkbun.sh b/dnsapi/dns_porkbun.sh index 05ecb781..18da6b2f 100644 --- a/dnsapi/dns_porkbun.sh +++ b/dnsapi/dns_porkbun.sh @@ -35,14 +35,6 @@ dns_porkbun_add() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - _debug "Getting txt records" - _porkbun_rest POST "dns/retrieve/$_domain" - - if ! echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null; then - _err "Error $response" - return 1 - fi - # For wildcard cert, the main root domain and the wildcard domain have the same txt subdomain name, so # we can not use updating anymore. # count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2) @@ -81,14 +73,6 @@ dns_porkbun_rm() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - _debug "Getting txt records" - _porkbun_rest POST "dns/retrieve/$_domain" - - if ! echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null; then - _err "Error: $response" - return 1 - fi - count=$(echo "$response" | _egrep_o "\"count\": *[^,]*" | cut -d : -f 2 | tr -d " ") _debug count "$count" if [ "$count" = "0" ]; then @@ -162,6 +146,8 @@ _porkbun_rest() { response="$(_get "$PORKBUN_Api/$ep")" fi + _sleep 3 # prevent rate limit + if [ "$?" != "0" ]; then _err "error $ep" return 1 From e0d5b91388ad5b83d59454aa8db2bc50d3e2b301 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 21 Mar 2021 22:46:35 +0800 Subject: [PATCH 353/383] fix freebsd --- .github/workflows/DNS.yml | 2 +- .github/workflows/LetsEncrypt.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index ed0426ad..5ff1f8ab 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -184,7 +184,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.1.2 + - uses: vmactions/freebsd-vm@v0.1.3 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkg install -y socat curl diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 7c398c09..7193d88d 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -111,7 +111,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.1.2 + - uses: vmactions/freebsd-vm@v0.1.3 with: envs: 'NGROK_TOKEN TEST_LOCAL' prepare: pkg install -y socat curl From 051775b9b453b491418f8b23703bf0bc541f076e Mon Sep 17 00:00:00 2001 From: Alexander Kulumbeg Date: Sun, 21 Mar 2021 16:25:04 +0100 Subject: [PATCH 354/383] String update Hopefully the last one --- dnsapi/dns_websupport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_websupport.sh b/dnsapi/dns_websupport.sh index 3b5a8847..e824c9c0 100644 --- a/dnsapi/dns_websupport.sh +++ b/dnsapi/dns_websupport.sh @@ -32,7 +32,7 @@ dns_websupport_add() { WS_ApiKey="" WS_ApiSecret="" _err "You did not specify the API Key and/or API Secret" - _err "You can get the API credentials from here https://admin.websupport.sk/en/auth/apiKey" + _err "You can get the API login credentials from https://admin.websupport.sk/en/auth/apiKey" return 1 fi From 3c7be32ef50f6df4ced3a75f92305ba9555b7da9 Mon Sep 17 00:00:00 2001 From: emueller Date: Mon, 22 Mar 2021 15:12:27 +0100 Subject: [PATCH 355/383] fix _exists error message when MAIL_BIN env variable is not set --- notify/mail.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/notify/mail.sh b/notify/mail.sh index d33fd0d2..10e93f9a 100644 --- a/notify/mail.sh +++ b/notify/mail.sh @@ -78,8 +78,13 @@ mail_send() { _mail_bin() { _MAIL_BIN="" + _MAIL_BINS="sendmail ssmtp mutt mail msmtp" - for b in "$MAIL_BIN" sendmail ssmtp mutt mail msmtp; do + if [ -n "$MAIL_BIN" ]; then + _MAIL_BINS="$MAIL_BIN $_MAIL_BINS" + fi + + for b in $_MAIL_BINS; do if _exists "$b"; then _MAIL_BIN="$b" break From 37e3e2f9c2b829d0691e9d958d764bfc4eb7d03e Mon Sep 17 00:00:00 2001 From: emueller Date: Mon, 22 Mar 2021 15:32:02 +0100 Subject: [PATCH 356/383] fixed formating --- notify/mail.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notify/mail.sh b/notify/mail.sh index 10e93f9a..2be93cd8 100644 --- a/notify/mail.sh +++ b/notify/mail.sh @@ -78,7 +78,7 @@ mail_send() { _mail_bin() { _MAIL_BIN="" - _MAIL_BINS="sendmail ssmtp mutt mail msmtp" + _MAIL_BINS="sendmail ssmtp mutt mail msmtp" if [ -n "$MAIL_BIN" ]; then _MAIL_BINS="$MAIL_BIN $_MAIL_BINS" From 8adb8a69866a5a540ce3ee470872188e7c7c58dd Mon Sep 17 00:00:00 2001 From: wout Date: Tue, 23 Mar 2021 21:20:27 +0100 Subject: [PATCH 357/383] While [0-9]+ is a bit more correct than [0-9]*, the former does not seem to work on Solaris. --- dnsapi/dns_constellix.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_constellix.sh b/dnsapi/dns_constellix.sh index 75211a6f..2c3b3265 100644 --- a/dnsapi/dns_constellix.sh +++ b/dnsapi/dns_constellix.sh @@ -44,7 +44,7 @@ dns_constellix_add() { fi fi else - _record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]+" | cut -d ':' -f 2) + _record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]*" | cut -d ':' -f 2) if _constellix_rest GET "domains/${_domain_id}/records/TXT/${_record_id}"; then _new_rr_values=$(printf "%s\n" "$response" | _egrep_o "\"roundRobin\":\[.*?\]" | sed "s/\]$/,{\"value\":\"${txtvalue}\"}]/") _debug _new_rr_values "$_new_rr_values" @@ -123,7 +123,7 @@ _get_root() { fi if _contains "$response" "\"name\":\"$h\""; then - _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]+" | cut -d ':' -f 2) + _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]*" | cut -d ':' -f 2) if [ "$_domain_id" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d '.' -f 1-$p) _domain="$h" From 6b7db22981085eb2e0b4473f72261f1a575f6899 Mon Sep 17 00:00:00 2001 From: wout Date: Wed, 24 Mar 2021 09:01:54 +0100 Subject: [PATCH 358/383] Catch the situation when the TXT record is updated with the same value --- dnsapi/dns_constellix.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dnsapi/dns_constellix.sh b/dnsapi/dns_constellix.sh index 2c3b3265..914f79df 100644 --- a/dnsapi/dns_constellix.sh +++ b/dnsapi/dns_constellix.sh @@ -53,6 +53,9 @@ dns_constellix_add() { if printf -- "%s" "$response" | grep "{\"success\":\"Record.*updated successfully\"}" >/dev/null; then _info "Updated" return 0 + elif printf -- "%s" "$response" | grep "{\"errors\":\[\"Contents are identical\"\]}" >/dev/null; then + _info "Already exists, no need to update" + return 0 else _err "Error updating TXT record" fi From 3bfcd18a03e532d150b0076643d457aa7d244368 Mon Sep 17 00:00:00 2001 From: wout Date: Wed, 24 Mar 2021 13:56:14 +0100 Subject: [PATCH 359/383] Workaround for Solaris, as it does not support non-greedy regex --- dnsapi/dns_constellix.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_constellix.sh b/dnsapi/dns_constellix.sh index 914f79df..69d216f0 100644 --- a/dnsapi/dns_constellix.sh +++ b/dnsapi/dns_constellix.sh @@ -46,7 +46,7 @@ dns_constellix_add() { else _record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]*" | cut -d ':' -f 2) if _constellix_rest GET "domains/${_domain_id}/records/TXT/${_record_id}"; then - _new_rr_values=$(printf "%s\n" "$response" | _egrep_o "\"roundRobin\":\[.*?\]" | sed "s/\]$/,{\"value\":\"${txtvalue}\"}]/") + _new_rr_values=$(printf "%s\n" "$response" | _egrep_o '"roundRobin":\[[^]]*\]' | sed "s/\]$/,{\"value\":\"${txtvalue}\"}]/") _debug _new_rr_values "$_new_rr_values" _info "Updating TXT record" if _constellix_rest PUT "domains/${_domain_id}/records/TXT/${_record_id}" "{\"name\":\"${_sub_domain}\",\"ttl\":60,${_new_rr_values}}"; then From 1530abbd1aacf5877a7317f24f60d8fab96d9735 Mon Sep 17 00:00:00 2001 From: Jan-Philipp Benecke Date: Fri, 26 Mar 2021 15:37:12 +0100 Subject: [PATCH 360/383] Make uploading cert to subaccount possible --- deploy/cleverreach.sh | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/deploy/cleverreach.sh b/deploy/cleverreach.sh index 552d8149..10670f34 100644 --- a/deploy/cleverreach.sh +++ b/deploy/cleverreach.sh @@ -25,6 +25,7 @@ cleverreach_deploy() { _getdeployconf DEPLOY_CLEVERREACH_CLIENT_ID _getdeployconf DEPLOY_CLEVERREACH_CLIENT_SECRET + _getdeployconf DEPLOY_CLEVERREACH_SUBCLIENT_ID if [ -z "${DEPLOY_CLEVERREACH_CLIENT_ID}" ]; then _err "CleverReach Client ID is not found, please define DEPLOY_CLEVERREACH_CLIENT_ID." @@ -37,6 +38,7 @@ cleverreach_deploy() { _savedeployconf DEPLOY_CLEVERREACH_CLIENT_ID "${DEPLOY_CLEVERREACH_CLIENT_ID}" _savedeployconf DEPLOY_CLEVERREACH_CLIENT_SECRET "${DEPLOY_CLEVERREACH_CLIENT_SECRET}" + _savedeployconf DEPLOY_CLEVERREACH_SUBCLIENT_ID "${DEPLOY_CLEVERREACH_SUBCLIENT_ID}" _info "Obtaining a CleverReach access token" @@ -50,14 +52,26 @@ cleverreach_deploy() { _debug _regex "$_regex" _access_token=$(echo "$_auth_result" | _json_decode | sed -n "s/$_regex/\1/p") + if ${DEPLOY_CLEVERREACH_SUBCLIENT_ID}; then + _info "Obtaining token for sub-client" + export _H1="Authorization: Bearer ${_access_token}" + _subclient_token_result="$(_get "https://rest.cleverreach.com/v3/clients/$DEPLOY_CLEVERREACH_SUBCLIENT_ID}/token")" + _access_token=$(echo "$_subclient_token_result" | _json_decode | sed -n "s/$_regex/\1/p") + + _debug "Destroying parent token at CleverReach" + _post "" "https://rest.cleverreach.com/v3/oauth/token.json" "" "DELETE" "application/json" + fi + _info "Uploading certificate and key to CleverReach" _certData="{\"cert\":\"$(_json_encode <"$_cfullchain")\", \"key\":\"$(_json_encode <"$_ckey")\"}" export _H1="Authorization: Bearer ${_access_token}" _add_cert_result="$(_post "$_certData" "https://rest.cleverreach.com/v3/ssl" "" "POST" "application/json")" - _debug "Destroying token at CleverReach" - _post "" "https://rest.cleverreach.com/v3/oauth/token.json" "" "DELETE" "application/json" + if ! ${DEPLOY_CLEVERREACH_SUBCLIENT_ID}; then + _debug "Destroying token at CleverReach" + _post "" "https://rest.cleverreach.com/v3/oauth/token.json" "" "DELETE" "application/json" + fi if ! echo "$_add_cert_result" | grep '"error":' >/dev/null; then _info "Uploaded certificate successfully" From cc90f8346351f3d38617e4186e8edf9b9f17a490 Mon Sep 17 00:00:00 2001 From: Christophe Le Guern Date: Mon, 29 Mar 2021 15:10:14 +0200 Subject: [PATCH 361/383] Use 'vault kv put' instead of 'vault write' When using vault_cli with a kv2 path, it isn't working. I have the following error: ``` WARNING! The following warnings were returned from Vault: * Invalid path for a versioned K/V secrets engine. See the API docs for the appropriate API endpoints to use. If using the Vault CLI, use 'vault kv put' for this operation. ``` The new way to write data is to use `vault kv put`, it is compatible with kv1 and kv2. Ref: https://www.vaultproject.io/docs/commands#reading-and-writing-data ``` The original version of K/V used the common read and write operations. A more advanced K/V Version 2 engine was released in Vault 0.10 and introduced the kv get and kv put commands. ``` --- deploy/vault_cli.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/deploy/vault_cli.sh b/deploy/vault_cli.sh index 8b854137..cbb8cc59 100644 --- a/deploy/vault_cli.sh +++ b/deploy/vault_cli.sh @@ -50,12 +50,12 @@ vault_cli_deploy() { fi if [ -n "$FABIO" ]; then - $VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}" cert=@"$_cfullchain" key=@"$_ckey" || return 1 + $VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}" cert=@"$_cfullchain" key=@"$_ckey" || return 1 else - $VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/cert.pem" value=@"$_ccert" || return 1 - $VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/cert.key" value=@"$_ckey" || return 1 - $VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/chain.pem" value=@"$_cca" || return 1 - $VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/fullchain.pem" value=@"$_cfullchain" || return 1 + $VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/cert.pem" value=@"$_ccert" || return 1 + $VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/cert.key" value=@"$_ckey" || return 1 + $VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/chain.pem" value=@"$_cca" || return 1 + $VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/fullchain.pem" value=@"$_cfullchain" || return 1 fi } From d853a9ebbed913d752faceb86be29edaf82806a0 Mon Sep 17 00:00:00 2001 From: Jan-Philipp Benecke Date: Tue, 30 Mar 2021 09:13:32 +0200 Subject: [PATCH 362/383] Make uploading cert to subaccount possible --- deploy/cleverreach.sh | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/deploy/cleverreach.sh b/deploy/cleverreach.sh index 10670f34..03fccc74 100644 --- a/deploy/cleverreach.sh +++ b/deploy/cleverreach.sh @@ -17,6 +17,8 @@ cleverreach_deploy() { _cca="$4" _cfullchain="$5" + _rest_endpoint="https://rest.cleverreach.com" + _debug _cdomain "$_cdomain" _debug _ckey "$_ckey" _debug _ccert "$_ccert" @@ -43,7 +45,7 @@ cleverreach_deploy() { _info "Obtaining a CleverReach access token" _data="{\"grant_type\": \"client_credentials\", \"client_id\": \"${DEPLOY_CLEVERREACH_CLIENT_ID}\", \"client_secret\": \"${DEPLOY_CLEVERREACH_CLIENT_SECRET}\"}" - _auth_result="$(_post "$_data" "https://rest.cleverreach.com/oauth/token.php" "" "POST" "application/json")" + _auth_result="$(_post "$_data" "$_rest_endpoint/oauth/token.php" "" "POST" "application/json")" _debug _data "$_data" _debug _auth_result "$_auth_result" @@ -52,25 +54,31 @@ cleverreach_deploy() { _debug _regex "$_regex" _access_token=$(echo "$_auth_result" | _json_decode | sed -n "s/$_regex/\1/p") - if ${DEPLOY_CLEVERREACH_SUBCLIENT_ID}; then - _info "Obtaining token for sub-client" + _debug _subclient "${DEPLOY_CLEVERREACH_SUBCLIENT_ID}" + + if ! [ -z "${DEPLOY_CLEVERREACH_SUBCLIENT_ID}" ]; then + _info "Obtaining token for sub-client ${DEPLOY_CLEVERREACH_SUBCLIENT_ID}" export _H1="Authorization: Bearer ${_access_token}" - _subclient_token_result="$(_get "https://rest.cleverreach.com/v3/clients/$DEPLOY_CLEVERREACH_SUBCLIENT_ID}/token")" - _access_token=$(echo "$_subclient_token_result" | _json_decode | sed -n "s/$_regex/\1/p") + _subclient_token_result="$(_get "$_rest_endpoint/v3/clients/$DEPLOY_CLEVERREACH_SUBCLIENT_ID/token")" + _access_token=$(echo "$_subclient_token_result" | sed -n "s/\"//p") + + _debug _subclient_token_result "$_access_token" - _debug "Destroying parent token at CleverReach" - _post "" "https://rest.cleverreach.com/v3/oauth/token.json" "" "DELETE" "application/json" + _info "Destroying parent token at CleverReach, as it not needed anymore" + _destroy_result="$(_post "" "$_rest_endpoint/v3/oauth/token.json" "" "DELETE" "application/json")" + _debug _destroy_result "$_destroy_result" fi _info "Uploading certificate and key to CleverReach" _certData="{\"cert\":\"$(_json_encode <"$_cfullchain")\", \"key\":\"$(_json_encode <"$_ckey")\"}" export _H1="Authorization: Bearer ${_access_token}" - _add_cert_result="$(_post "$_certData" "https://rest.cleverreach.com/v3/ssl" "" "POST" "application/json")" + _add_cert_result="$(_post "$_certData" "$_rest_endpoint/v3/ssl" "" "POST" "application/json")" - if ! ${DEPLOY_CLEVERREACH_SUBCLIENT_ID}; then - _debug "Destroying token at CleverReach" - _post "" "https://rest.cleverreach.com/v3/oauth/token.json" "" "DELETE" "application/json" + if [ -z "${DEPLOY_CLEVERREACH_SUBCLIENT_ID}" ]; then + _info "Destroying token at CleverReach, as it not needed anymore" + _destroy_result="$(_post "" "$_rest_endpoint/v3/oauth/token.json" "" "DELETE" "application/json")" + _debug _destroy_result "$_destroy_result" fi if ! echo "$_add_cert_result" | grep '"error":' >/dev/null; then From 2867ec509efae5136bf9cb4572bfd46eb7eba7fa Mon Sep 17 00:00:00 2001 From: Jan-Philipp Benecke Date: Tue, 30 Mar 2021 09:18:33 +0200 Subject: [PATCH 363/383] Make CI happy --- deploy/cleverreach.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/cleverreach.sh b/deploy/cleverreach.sh index 03fccc74..a460a139 100644 --- a/deploy/cleverreach.sh +++ b/deploy/cleverreach.sh @@ -56,7 +56,7 @@ cleverreach_deploy() { _debug _subclient "${DEPLOY_CLEVERREACH_SUBCLIENT_ID}" - if ! [ -z "${DEPLOY_CLEVERREACH_SUBCLIENT_ID}" ]; then + if [ -n "${DEPLOY_CLEVERREACH_SUBCLIENT_ID}" ]; then _info "Obtaining token for sub-client ${DEPLOY_CLEVERREACH_SUBCLIENT_ID}" export _H1="Authorization: Bearer ${_access_token}" _subclient_token_result="$(_get "$_rest_endpoint/v3/clients/$DEPLOY_CLEVERREACH_SUBCLIENT_ID/token")" From e21f3e6c73253c5f8ddc57f640d055237c550552 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Thu, 8 Apr 2021 16:36:42 +1200 Subject: [PATCH 364/383] Escape asterisks in notification content This messes with markdown parsing Signed-off-by: Mike Beattie --- notify/telegram.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/notify/telegram.sh b/notify/telegram.sh index b1306ee1..d9b375d0 100644 --- a/notify/telegram.sh +++ b/notify/telegram.sh @@ -27,6 +27,7 @@ telegram_send() { fi _saveaccountconf_mutable TELEGRAM_BOT_CHATID "$TELEGRAM_BOT_CHATID" + _content="$(printf "%s" "$_content" | sed -e 's/*/\\\\*/')" _content="$(printf "*%s*\n%s" "$_subject" "$_content" | _json_encode)" _data="{\"text\": \"$_content\", " _data="$_data\"chat_id\": \"$TELEGRAM_BOT_CHATID\", " From 53d26e5c5c5a5ca5f650784dfe22be49d65b06cd Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Thu, 8 Apr 2021 16:37:27 +1200 Subject: [PATCH 365/383] Add debug output of $_data variable to aid diagnosis Signed-off-by: Mike Beattie --- notify/telegram.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/notify/telegram.sh b/notify/telegram.sh index d9b375d0..3e266040 100644 --- a/notify/telegram.sh +++ b/notify/telegram.sh @@ -34,6 +34,8 @@ telegram_send() { _data="$_data\"parse_mode\": \"markdown\", " _data="$_data\"disable_web_page_preview\": \"1\"}" + _debug "$_data" + export _H1="Content-Type: application/json" _telegram_bot_url="https://api.telegram.org/bot${TELEGRAM_BOT_APITOKEN}/sendMessage" if _post "$_data" "$_telegram_bot_url"; then From 39b09f8f87a45656b98d1e8e704783bff2d666ca Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Thu, 8 Apr 2021 16:38:00 +1200 Subject: [PATCH 366/383] Dump _post() call output to /dev/null Signed-off-by: Mike Beattie --- notify/telegram.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notify/telegram.sh b/notify/telegram.sh index 3e266040..c46bc1e2 100644 --- a/notify/telegram.sh +++ b/notify/telegram.sh @@ -38,7 +38,7 @@ telegram_send() { export _H1="Content-Type: application/json" _telegram_bot_url="https://api.telegram.org/bot${TELEGRAM_BOT_APITOKEN}/sendMessage" - if _post "$_data" "$_telegram_bot_url"; then + if _post "$_data" "$_telegram_bot_url" > /dev/null; then # shellcheck disable=SC2154 _message=$(printf "%s\n" "$response" | sed -n 's/.*"ok":\([^,]*\).*/\1/p') if [ "$_message" = "true" ]; then From fb079f9e50f4de51f44773ac1e24ea3ba81a8a50 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Thu, 8 Apr 2021 16:44:22 +1200 Subject: [PATCH 367/383] Update telegram.sh (fix shellcheck failure) --- notify/telegram.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notify/telegram.sh b/notify/telegram.sh index c46bc1e2..d16f3a98 100644 --- a/notify/telegram.sh +++ b/notify/telegram.sh @@ -38,7 +38,7 @@ telegram_send() { export _H1="Content-Type: application/json" _telegram_bot_url="https://api.telegram.org/bot${TELEGRAM_BOT_APITOKEN}/sendMessage" - if _post "$_data" "$_telegram_bot_url" > /dev/null; then + if _post "$_data" "$_telegram_bot_url" >/dev/null; then # shellcheck disable=SC2154 _message=$(printf "%s\n" "$response" | sed -n 's/.*"ok":\([^,]*\).*/\1/p') if [ "$_message" = "true" ]; then From cfbc294832508d9ed18ef17f8517cc337141431d Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 14 Apr 2021 22:18:01 +0800 Subject: [PATCH 368/383] fix onecom api --- dnsapi/dns_one.sh | 55 +++-------------------------------------------- 1 file changed, 3 insertions(+), 52 deletions(-) diff --git a/dnsapi/dns_one.sh b/dnsapi/dns_one.sh index 890cc804..0a4b2a14 100644 --- a/dnsapi/dns_one.sh +++ b/dnsapi/dns_one.sh @@ -1,22 +1,10 @@ #!/usr/bin/env sh -# -*- mode: sh; tab-width: 2; indent-tabs-mode: s; coding: utf-8 -*- - # one.com ui wrapper for acme.sh -# Author: github: @diseq -# Created: 2019-02-17 -# Fixed by: @der-berni -# Modified: 2020-04-07 -# -# Use ONECOM_KeepCnameProxy to keep the CNAME DNS record -# export ONECOM_KeepCnameProxy="1" + # # export ONECOM_User="username" # export ONECOM_Password="password" -# -# Usage: -# acme.sh --issue --dns dns_one -d example.com -# -# only single domain supported atm + dns_one_add() { fulldomain=$1 @@ -36,26 +24,10 @@ dns_one_add() { subdomain="${_sub_domain}" maindomain=${_domain} - useProxy=0 - if [ "${_sub_domain}" = "_acme-challenge" ]; then - subdomain="proxy${_sub_domain}" - useProxy=1 - fi _debug subdomain "$subdomain" _debug maindomain "$maindomain" - if [ $useProxy -eq 1 ]; then - #Check if the CNAME exists - _dns_one_getrecord "CNAME" "$_sub_domain" "$subdomain.$maindomain" - if [ -z "$id" ]; then - _info "$(__red "Add CNAME Proxy record: '$(__green "\"$_sub_domain\" => \"$subdomain.$maindomain\"")'")" - _dns_one_addrecord "CNAME" "$_sub_domain" "$subdomain.$maindomain" - - _info "Not valid yet, let's wait 1 hour to take effect." - _sleep 3600 - fi - fi #Check if the TXT exists _dns_one_getrecord "TXT" "$subdomain" "$txtvalue" @@ -92,26 +64,8 @@ dns_one_rm() { subdomain="${_sub_domain}" maindomain=${_domain} - useProxy=0 - if [ "${_sub_domain}" = "_acme-challenge" ]; then - subdomain="proxy${_sub_domain}" - useProxy=1 - fi - _debug subdomain "$subdomain" _debug maindomain "$maindomain" - if [ $useProxy -eq 1 ]; then - if [ "$ONECOM_KeepCnameProxy" = "1" ]; then - _info "$(__red "Keeping CNAME Proxy record: '$(__green "\"$_sub_domain\" => \"$subdomain.$maindomain\"")'")" - else - #Check if the CNAME exists - _dns_one_getrecord "CNAME" "$_sub_domain" "$subdomain.$maindomain" - if [ -n "$id" ]; then - _info "$(__red "Removing CNAME Proxy record: '$(__green "\"$_sub_domain\" => \"$subdomain.$maindomain\"")'")" - _dns_one_delrecord "$id" - fi - fi - fi #Check if the TXT exists _dns_one_getrecord "TXT" "$subdomain" "$txtvalue" @@ -136,7 +90,7 @@ dns_one_rm() { # _domain=domain.com _get_root() { domain="$1" - i=2 + i=1 p=1 while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) @@ -163,8 +117,6 @@ _get_root() { _dns_one_login() { # get credentials - ONECOM_KeepCnameProxy="${ONECOM_KeepCnameProxy:-$(_readaccountconf_mutable ONECOM_KeepCnameProxy)}" - ONECOM_KeepCnameProxy="${ONECOM_KeepCnameProxy:-0}" ONECOM_User="${ONECOM_User:-$(_readaccountconf_mutable ONECOM_User)}" ONECOM_Password="${ONECOM_Password:-$(_readaccountconf_mutable ONECOM_Password)}" if [ -z "$ONECOM_User" ] || [ -z "$ONECOM_Password" ]; then @@ -176,7 +128,6 @@ _dns_one_login() { fi #save the api key and email to the account conf file. - _saveaccountconf_mutable ONECOM_KeepCnameProxy "$ONECOM_KeepCnameProxy" _saveaccountconf_mutable ONECOM_User "$ONECOM_User" _saveaccountconf_mutable ONECOM_Password "$ONECOM_Password" From 1c58913eeb54911457f289c32ed52f52e2b82f53 Mon Sep 17 00:00:00 2001 From: Jasper Zonneveld Date: Fri, 26 Mar 2021 14:59:13 +0100 Subject: [PATCH 369/383] Add Aurora DNS API --- dnsapi/dns_aurora.sh | 171 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 dnsapi/dns_aurora.sh diff --git a/dnsapi/dns_aurora.sh b/dnsapi/dns_aurora.sh new file mode 100644 index 00000000..00f44739 --- /dev/null +++ b/dnsapi/dns_aurora.sh @@ -0,0 +1,171 @@ +#!/usr/bin/env sh + +# +#AURORA_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" +# +#AURORA_Secret="sdfsdfsdfljlbjkljlkjsdfoiwje" + +AURORA_Api="https://api.auroradns.eu" + +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_aurora_add() { + fulldomain=$1 + txtvalue=$2 + + AURORA_Key="${AURORA_Key:-$(_readaccountconf_mutable AURORA_Key)}" + AURORA_Secret="${AURORA_Secret:-$(_readaccountconf_mutable AURORA_Secret)}" + + if [ -z "$AURORA_Key" ] || [ -z "$AURORA_Secret" ]; then + AURORA_Key="" + AURORA_Secret="" + _err "You didn't specify an Aurora api key and secret yet." + _err "You can get yours from here https://cp.pcextreme.nl/auroradns/users." + return 1 + fi + + #save the api key and secret to the account conf file. + _saveaccountconf_mutable AURORA_Key "$AURORA_Key" + _saveaccountconf_mutable AURORA_Secret "$AURORA_Secret" + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _domain_id "$_domain_id" + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _info "Adding record" + if _aurora_rest POST "zones/$_domain_id/records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":300}"; then + if _contains "$response" "$txtvalue"; then + _info "Added, OK" + return 0 + elif _contains "$response" "RecordExistsError"; then + _info "Already exists, OK" + return 0 + else + _err "Add txt record error." + return 1 + fi + fi + _err "Add txt record error." + return 1 + +} + +#fulldomain txtvalue +dns_aurora_rm() { + fulldomain=$1 + txtvalue=$2 + + AURORA_Key="${AURORA_Key:-$(_readaccountconf_mutable AURORA_Key)}" + AURORA_Secret="${AURORA_Secret:-$(_readaccountconf_mutable AURORA_Secret)}" + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _domain_id "$_domain_id" + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting records" + _aurora_rest GET "zones/${_domain_id}/records" + + if ! _contains "$response" "$txtvalue"; then + _info "Don't need to remove." + else + records=$(echo "$response" | _normalizeJson | tr -d "[]" | sed "s/},{/}|{/g" | tr "|" "\n") + if [ "$(echo "$records" | wc -l)" -le 2 ]; then + _err "Can not parse records." + return 1 + fi + record_id=$(echo "$records" | grep "\"type\": *\"TXT\"" | grep "\"name\": *\"$_sub_domain\"" | grep "\"content\": *\"$txtvalue\"" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | _head_n 1 | tr -d " ") + _debug "record_id" "$record_id" + if [ -z "$record_id" ]; then + _err "Can not get record id to remove." + return 1 + fi + if ! _aurora_rest DELETE "zones/$_domain_id/records/$record_id"; then + _err "Delete record error." + return 1 + fi + fi + return 0 + +} + +#################### Private functions below ################################## +#_acme-challenge.www.domain.com +#returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +# _domain_id=sdjkglgdfewsdfg +_get_root() { + domain=$1 + i=1 + p=1 + + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug h "$h" + if [ -z "$h" ]; then + #not valid + return 1 + fi + + if ! _aurora_rest GET "zones/$h"; then + return 1 + fi + + if _contains "$response" "\"name\": \"$h\""; then + _domain_id=$(echo "$response" | _normalizeJson | tr -d "{}" | tr "," "\n" | grep "\"id\": *\"" | cut -d : -f 2 | tr -d \" | _head_n 1 | tr -d " ") + _debug _domain_id "$_domain_id" + if [ "$_domain_id" ]; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain=$h + return 0 + fi + return 1 + fi + p=$i + i=$(_math "$i" + 1) + done + return 1 +} + +_aurora_rest() { + m=$1 + ep="$2" + data="$3" + _debug "$ep" + + key_trimmed=$(echo "$AURORA_Key" | tr -d '"') + secret_trimmed=$(echo "$AURORA_Secret" | tr -d '"') + + timestamp=$(date -u +"%Y%m%dT%H%M%SZ") + signature=$(printf "%s/%s%s" "$m" "$ep" "$timestamp" | _hmac sha256 "$(printf "%s" "$secret_trimmed" | _hex_dump | tr -d " ")" | _base64) + authorization=$(printf "AuroraDNSv1 %s" "$(printf "%s:%s" "$key_trimmed" "$signature" | _base64)") + + export _H1="Content-Type: application/json; charset=UTF-8" + export _H2="X-AuroraDNS-Date: $timestamp" + export _H3="Authorization: $authorization" + + if [ "$m" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$AURORA_Api/$ep" "" "$m")" + else + response="$(_get "$AURORA_Api/$ep")" + fi + + if [ "$?" != "0" ]; then + _err "error $ep" + return 1 + fi + _debug2 response "$response" + return 0 +} From f3682f0e8e30899dab1fb3fbbf6b477f4a798c0d Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 17 Apr 2021 22:09:59 +0800 Subject: [PATCH 370/383] fix format --- dnsapi/dns_one.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/dnsapi/dns_one.sh b/dnsapi/dns_one.sh index 0a4b2a14..1565b767 100644 --- a/dnsapi/dns_one.sh +++ b/dnsapi/dns_one.sh @@ -5,7 +5,6 @@ # export ONECOM_User="username" # export ONECOM_Password="password" - dns_one_add() { fulldomain=$1 txtvalue=$2 @@ -24,11 +23,9 @@ dns_one_add() { subdomain="${_sub_domain}" maindomain=${_domain} - _debug subdomain "$subdomain" _debug maindomain "$maindomain" - #Check if the TXT exists _dns_one_getrecord "TXT" "$subdomain" "$txtvalue" if [ -n "$id" ]; then From eb0c629fad119604d0944719ca2bfc5e70dbc97e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eike-Christian=20M=C3=BCller?= Date: Thu, 29 Apr 2021 12:53:13 +0200 Subject: [PATCH 371/383] more simple mail.sh fix Reverted the original patch and changed it to the obvious simple solution provided by @Neilpang. --- notify/mail.sh | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/notify/mail.sh b/notify/mail.sh index 2be93cd8..2cbddb63 100644 --- a/notify/mail.sh +++ b/notify/mail.sh @@ -78,13 +78,8 @@ mail_send() { _mail_bin() { _MAIL_BIN="" - _MAIL_BINS="sendmail ssmtp mutt mail msmtp" - if [ -n "$MAIL_BIN" ]; then - _MAIL_BINS="$MAIL_BIN $_MAIL_BINS" - fi - - for b in $_MAIL_BINS; do + for b in $MAIL_BIN sendmail ssmtp mutt mail msmtp; do if _exists "$b"; then _MAIL_BIN="$b" break From 81b2d0732f6a8db79f7059c5fb0dccdf02783387 Mon Sep 17 00:00:00 2001 From: Jeff Goeke-Smith Date: Thu, 29 Apr 2021 16:46:32 -0400 Subject: [PATCH 372/383] arguments passed to printf are more generic On systems that /bin/sh is served by shells other than bash, or shells that don't implement the same syntax as the bash printf builtin, printf -- fails to produce the output necessary for standalone operation. The test case for this was SmartOS, which uses ksh93 as its /bin/sh. This change uses the more generic method of passing a format parameter of a single string, and then the argument to replace it with. --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 8d422719..b408ed30 100755 --- a/acme.sh +++ b/acme.sh @@ -2357,7 +2357,7 @@ _startserver() { echo 'HTTP/1.0 200 OK'; \ echo 'Content-Length\: $_content_len'; \ echo ''; \ -printf -- '$content';" & +printf '%s' '$content';" & serverproc="$!" } From 91d37c78750d382d0edfec6f36e6c49bb834159c Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 1 May 2021 22:32:44 +0800 Subject: [PATCH 373/383] fix compatibility issue --- acme.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index b408ed30..2ec8ba57 100755 --- a/acme.sh +++ b/acme.sh @@ -2038,7 +2038,7 @@ _send_signed_request() { if _post "" "$nonceurl" "" "HEAD" "$__request_conent_type" >/dev/null; then _headers="$(cat "$HTTP_HEADER")" _debug2 _headers "$_headers" - _CACHED_NONCE="$(echo "$_headers" | grep -i "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)" + _CACHED_NONCE="$(echo "$_headers" | grep -i "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2 | cut -d , -f 1)" fi fi if [ -z "$_CACHED_NONCE" ]; then @@ -2118,7 +2118,7 @@ _send_signed_request() { fi _debug2 response "$response" - _CACHED_NONCE="$(echo "$responseHeaders" | grep -i "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)" + _CACHED_NONCE="$(echo "$responseHeaders" | grep -i "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2 | cut -d , -f 1)" if ! _startswith "$code" "2"; then _body="$response" @@ -4720,7 +4720,7 @@ $_authorizations_map" _debug2 response "$response" status=$(echo "$response" | _egrep_o '"status":"[^"]*' | cut -d : -f 2 | tr -d '"') - if [ "$status" = "valid" ]; then + if _contains "$status" "valid"; then _info "$(__green Success)" _stopserver "$serverproc" serverproc="" From f855862ade83a0fc61f409c21397202f7f781c63 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 2 May 2021 22:20:04 +0800 Subject: [PATCH 374/383] upgrade freebsd --- .github/workflows/DNS.yml | 2 +- .github/workflows/LetsEncrypt.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 5ff1f8ab..f8e501ed 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -184,7 +184,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.1.3 + - uses: vmactions/freebsd-vm@v0.1.4 with: envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' prepare: pkg install -y socat curl diff --git a/.github/workflows/LetsEncrypt.yml b/.github/workflows/LetsEncrypt.yml index 7193d88d..ba9a5317 100644 --- a/.github/workflows/LetsEncrypt.yml +++ b/.github/workflows/LetsEncrypt.yml @@ -111,7 +111,7 @@ jobs: - uses: actions/checkout@v2 - name: Clone acmetest run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - - uses: vmactions/freebsd-vm@v0.1.3 + - uses: vmactions/freebsd-vm@v0.1.4 with: envs: 'NGROK_TOKEN TEST_LOCAL' prepare: pkg install -y socat curl From 1a4a180e8cf0825a34a4df4810b43cc5990e47a3 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sun, 2 May 2021 13:37:59 -0600 Subject: [PATCH 375/383] FIX: Synology sets "default" on wrong certificate For some DSM installs, it appears that setting the "default" flag to the string "false" actually sets it to true. This causes Synology to set the last updated certificate to be the default certificate. Using an empty string appears to still be accepted as a false-y value for DSMs where this isn't happening and corrects the behavior in the cases that it was. Credit to @Run-King for identifying the fix and @buxm for reporting. --- deploy/synology_dsm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 35d33209..25d43efb 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -121,7 +121,7 @@ synology_dsm_deploy() { # we've verified this certificate description is a thing, so save it _savedeployconf SYNO_Certificate "$SYNO_Certificate" - default=false + default="" if echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\([^{]*\).*/\1/p" | grep -- 'is_default":true' >/dev/null; then default=true fi From 25a8240d12eb8884076242fb8adc4aa7f7bbaa84 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 3 May 2021 15:52:56 +0800 Subject: [PATCH 376/383] fix https://github.com/acmesh-official/acme.sh/issues/3421 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 2ec8ba57..4955a5d4 100755 --- a/acme.sh +++ b/acme.sh @@ -2266,7 +2266,7 @@ _getdeployconf() { return 0 # do nothing fi _saved=$(_readdomainconf "SAVED_$_rac_key") - eval "export $_rac_key=\"$_saved\"" + eval "export $_rac_key=\"\$_saved\"" } #_saveaccountconf key value base64encode From e65144a1053fa4a6a21d3a61f8be37202211d061 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 3 May 2021 16:35:42 +0800 Subject: [PATCH 377/383] fix https://github.com/acmesh-official/acme.sh/issues/3487 suppor Ali doh and dnspod doh. --- acme.sh | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/acme.sh b/acme.sh index 4955a5d4..efed674b 100755 --- a/acme.sh +++ b/acme.sh @@ -102,6 +102,8 @@ DEBUG_LEVEL_NONE=0 DOH_CLOUDFLARE=1 DOH_GOOGLE=2 +DOH_ALI=3 +DOH_DP=4 HIDDEN_VALUE="[hidden](please add '--output-insecure' to see this value)" @@ -3916,7 +3918,15 @@ _ns_purge_cf() { #checks if cf server is available _ns_is_available_cf() { - if _get "https://cloudflare-dns.com" >/dev/null 2>&1; then + if _get "https://cloudflare-dns.com" "" 1 >/dev/null 2>&1; then + return 0 + else + return 1 + fi +} + +_ns_is_available_google() { + if _get "https://dns.google" "" 1 >/dev/null 2>&1; then return 0 else return 1 @@ -3931,6 +3941,38 @@ _ns_lookup_google() { _ns_lookup_impl "$_cf_ep" "$_cf_ld" "$_cf_ld_type" } +_ns_is_available_ali() { + if _get "https://dns.alidns.com" "" 1 >/dev/null 2>&1; then + return 0 + else + return 1 + fi +} + +#domain, type +_ns_lookup_ali() { + _cf_ld="$1" + _cf_ld_type="$2" + _cf_ep="https://dns.alidns.com/resolve" + _ns_lookup_impl "$_cf_ep" "$_cf_ld" "$_cf_ld_type" +} + +_ns_is_available_dp() { + if _get "https://dns.alidns.com" "" 1 >/dev/null 2>&1; then + return 0 + else + return 1 + fi +} + +#dnspod +_ns_lookup_dp() { + _cf_ld="$1" + _cf_ld_type="$2" + _cf_ep="https://doh.pub/dns-query" + _ns_lookup_impl "$_cf_ep" "$_cf_ld" "$_cf_ld_type" +} + #domain, type _ns_lookup() { if [ -z "$DOH_USE" ]; then @@ -3938,16 +3980,28 @@ _ns_lookup() { if _ns_is_available_cf; then _debug "Use cloudflare doh server" export DOH_USE=$DOH_CLOUDFLARE - else + elif _ns_is_available_google; then _debug "Use google doh server" export DOH_USE=$DOH_GOOGLE + elif _ns_is_available_ali; then + _debug "Use aliyun doh server" + export DOH_USE=$DOH_ALI + else _ns_is_available_dp; + _debug "Use dns pod doh server" + export DOH_USE=$DOH_DP fi fi if [ "$DOH_USE" = "$DOH_CLOUDFLARE" ] || [ -z "$DOH_USE" ]; then _ns_lookup_cf "$@" - else + elif [ "$DOH_USE" = "$DOH_GOOGLE" ]; then _ns_lookup_google "$@" + elif [ "$DOH_USE" = "$DOH_ALI" ]; then + _ns_lookup_ali "$@" + elif [ "$DOH_USE" = "$DOH_DP" ]; then + _ns_lookup_dp "$@" + else + _err "Unknown doh provider: DOH_USE=$DOH_USE" fi } @@ -3972,7 +4026,7 @@ __purge_txt() { if [ "$DOH_USE" = "$DOH_CLOUDFLARE" ] || [ -z "$DOH_USE" ]; then _ns_purge_cf "$_p_txtdomain" "TXT" else - _debug "no purge api for google dns api, just sleep 5 secs" + _debug "no purge api for this doh api, just sleep 5 secs" _sleep 5 fi From e0c32ce7004cfe842bda3bf631cbcf92f37651b0 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 3 May 2021 16:42:09 +0800 Subject: [PATCH 378/383] minor --- acme.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index efed674b..d7ec50b4 100755 --- a/acme.sh +++ b/acme.sh @@ -3986,9 +3986,11 @@ _ns_lookup() { elif _ns_is_available_ali; then _debug "Use aliyun doh server" export DOH_USE=$DOH_ALI - else _ns_is_available_dp; + elif _ns_is_available_dp; _debug "Use dns pod doh server" export DOH_USE=$DOH_DP + else + _err "No doh" fi fi From 0a4ef171351db5eb7f02341e231801e80026d33e Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 3 May 2021 17:11:02 +0800 Subject: [PATCH 379/383] fix nginx relative path issue: https://github.com/acmesh-official/acme.sh/issues/1743 https://github.com/acmesh-official/acme.sh/issues/1914 --- acme.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/acme.sh b/acme.sh index d7ec50b4..36e33c7b 100755 --- a/acme.sh +++ b/acme.sh @@ -3098,6 +3098,11 @@ _checkConf() { _debug "Try include files" for included in $(cat "$2" | tr "\t" " " | grep "^ *include *.*;" | sed "s/include //" | tr -d " ;"); do _debug "check included $included" + if !_startswith "$included" "/" && _exists dirname; then + _relpath="$(dirname "$_c_file")" + _debug "_relpath" "$_relpath" + included="$_relpath/included" + fi if _checkConf "$1" "$included"; then return 0 fi From 290beb90a74ff617d9fdf006beb287fb9450d6e5 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 3 May 2021 17:14:54 +0800 Subject: [PATCH 380/383] minor --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 36e33c7b..0ea93cf7 100755 --- a/acme.sh +++ b/acme.sh @@ -3991,7 +3991,7 @@ _ns_lookup() { elif _ns_is_available_ali; then _debug "Use aliyun doh server" export DOH_USE=$DOH_ALI - elif _ns_is_available_dp; + elif _ns_is_available_dp; then _debug "Use dns pod doh server" export DOH_USE=$DOH_DP else From 0881cf13799e6d2ee8b1d8a969feac8d634e2c85 Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 4 May 2021 13:32:59 +0800 Subject: [PATCH 381/383] start 2.9.0 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 0ea93cf7..9967e541 100755 --- a/acme.sh +++ b/acme.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -VER=2.8.9 +VER=2.9.0 PROJECT_NAME="acme.sh" From aa59c46c4cffb89717388824e766e3c6cc1990a9 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 7 May 2021 21:49:47 +0800 Subject: [PATCH 382/383] fix https://github.com/acmesh-official/acme.sh/issues/3504 --- acme.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 9967e541..1f7bbda7 100755 --- a/acme.sh +++ b/acme.sh @@ -3578,6 +3578,7 @@ _regAccount() { _err "Can not get EAB credentials from ZeroSSL." return 1 fi + _debug2 "$_eabresp" _eab_id="$(echo "$_eabresp" | tr ',}' '\n' | grep '"eab_kid"' | cut -d : -f 2 | tr -d '"')" if [ -z "$_eab_id" ]; then _err "Can not resolve _eab_id" @@ -4781,7 +4782,7 @@ $_authorizations_map" _debug2 response "$response" status=$(echo "$response" | _egrep_o '"status":"[^"]*' | cut -d : -f 2 | tr -d '"') - if _contains "$status" "valid"; then + if _contains "$status" '"valid"'; then _info "$(__green Success)" _stopserver "$serverproc" serverproc="" From aede5c486be6e5f55882dcdbdecb7512200ee5be Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 7 May 2021 22:02:40 +0800 Subject: [PATCH 383/383] fix https://github.com/acmesh-official/acme.sh/issues/3504 check invalid status first. --- acme.sh | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/acme.sh b/acme.sh index 1f7bbda7..4fa83744 100755 --- a/acme.sh +++ b/acme.sh @@ -4782,15 +4782,8 @@ $_authorizations_map" _debug2 response "$response" status=$(echo "$response" | _egrep_o '"status":"[^"]*' | cut -d : -f 2 | tr -d '"') - if _contains "$status" '"valid"'; then - _info "$(__green Success)" - _stopserver "$serverproc" - serverproc="" - _clearupwebbroot "$_currentRoot" "$removelevel" "$token" - break - fi - if [ "$status" = "invalid" ]; then + if _contains "$status" "invalid"; then error="$(echo "$response" | _egrep_o '"error":\{[^\}]*')" _debug2 error "$error" errordetail="$(echo "$error" | _egrep_o '"detail": *"[^"]*' | cut -d '"' -f 4)" @@ -4812,6 +4805,14 @@ $_authorizations_map" return 1 fi + if _contains "$status" "valid"; then + _info "$(__green Success)" + _stopserver "$serverproc" + serverproc="" + _clearupwebbroot "$_currentRoot" "$removelevel" "$token" + break + fi + if [ "$status" = "pending" ]; then _info "Pending" elif [ "$status" = "processing" ]; then