Files
proxmox-git-proxmox-acme/src/proxmox-acme
T
dualfroz f696e885c0 fix #7155: proxmox-acme: support upper-hex mode of _url_encode
The _url_encode function of acme.sh takes an optional 'upper-hex'
argument, which makes it output the percent-encoded characters with
upper-case hex digits. Our copy of the function in proxmox-acme lacks
it and always outputs lower-case hex.

The Aliyun DNS plugin of the bundled acme.sh version uses this argument
for the signature of its API requests, as the Aliyun API requires
upper-case hex there. So the signature never matched, and adding the
TXT record always failed with "SignatureDoesNotMatch".

Add the argument the same way acme.sh implements it, as suggested in
the bug. Upstream changed the Aliyun plugin in the meantime to not rely
on the argument anymore, because of bundled copies like ours, but newer
plugins, like dns_baidu.sh and dns_hw.sh, use it too.

Signed-off-by: Michal Fox <me@dualfroz.com>
2026-10-02 16:57:43 +02:00

1005 lines
20 KiB
Bash

#!/bin/bash
VER=1.0
PROJECT_NAME="ProxmoxACME"
USER_AGENT="$PROJECT_NAME/$VER"
DNS_PLUGIN_PATH="/usr/share/proxmox-acme/dnsapi"
HTTP_HEADER="$(mktemp)"
DEBUG="0"
_base64() {
openssl base64 -e | tr -d '\r\n'
}
_dbase64() {
openssl base64 -d
}
# Usage: hashalg [outputhex]
# Output Base64-encoded digest
_digest() {
alg="$1"
if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ] || [ "$alg" = "md5" ]; then
if [ "$2" ]; then
openssl dgst -"$alg" -hex | cut -d = -f 2 | tr -d ' '
else
openssl dgst -"$alg" -binary | _base64
fi
fi
}
_usage() {
__red "$@" >&2
printf "\n" >&2
}
_upper_case() {
# shellcheck disable=SC2018,SC2019
tr 'a-z' 'A-Z'
}
_lower_case() {
# shellcheck disable=SC2018,SC2019
tr 'A-Z' 'a-z'
}
_startswith() {
_str="$1"
_sub="$2"
echo "$_str" | grep "^$_sub" >/dev/null 2>&1
}
_endswith() {
_str="$1"
_sub="$2"
echo "$_str" | grep -- "$_sub\$" >/dev/null 2>&1
}
_contains() {
_str="$1"
_sub="$2"
echo "$_str" | grep -- "$_sub" >/dev/null 2>&1
}
# str index [sep]
_getfield() {
_str="$1"
_findex="$2"
_sep="$3"
if [ -z "$_sep" ]; then
_sep=","
fi
_ffi="$_findex"
while [ "$_ffi" -gt "0" ]; do
_fv="$(echo "$_str" | cut -d "$_sep" -f "$_ffi")"
if [ "$_fv" ]; then
printf -- "%s" "$_fv"
return 0
fi
_ffi="$(_math "$_ffi" - 1)"
done
printf -- "%s" "$_str"
}
_exists() {
cmd="$1"
if eval type type >/dev/null 2>&1; then
type "$cmd" >/dev/null 2>&1
else command
command -v "$cmd" >/dev/null 2>&1
fi
ret="$?"
return $ret
}
# a + b
_math() {
_m_opts="$@"
printf "%s" "$(($_m_opts))"
}
_egrep_o() {
if ! egrep -o "$1" 2>/dev/null; then
sed -n 's/.*\('"$1"'\).*/\1/p'
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
fi
hex=$(cat)
ic=""
jc=""
_debug2 _URGLY_PRINTF "$_URGLY_PRINTF"
if [ -z "$_URGLY_PRINTF" ]; then
if [ "$_ESCAPE_XARGS" ] && _exists xargs; then
_debug2 "xargs"
echo "$hex" | _upper_case | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/g' | xargs printf
else
for h in $(echo "$hex" | _upper_case | sed 's/\([0-9A-F]\{2\}\)/ \1/g'); do
if [ -z "$h" ]; then
break
fi
printf "\x$h%s"
done
fi
else
for c in $(echo "$hex" | _upper_case | sed 's/\([0-9A-F]\)/ \1/g'); do
if [ -z "$ic" ]; then
ic=$c
continue
fi
jc=$c
ic="$(_h_char_2_dec "$ic")"
jc="$(_h_char_2_dec "$jc")"
printf '\'"$(printf "%o" "$(_math "$ic" \* 16 + $jc)")""%s"
ic=""
jc=""
done
fi
}
#Usage: keyfile hashalg
#Output: Base64-encoded signature value
_sign() {
keyfile="$1"
alg="$2"
if [ -z "$alg" ]; then
_usage "Usage: _sign keyfile hashalg"
return 1
fi
_sign_openssl="${ACME_OPENSSL_BIN:-openssl} dgst -sign $keyfile "
if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1 || grep "BEGIN PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
$_sign_openssl -$alg | _base64
elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
if ! _signedECText="$($_sign_openssl -sha$__ECC_KEY_LEN | ${ACME_OPENSSL_BIN:-openssl} asn1parse -inform DER)"; then
_err "Sign failed: $_sign_openssl"
_err "Key file: $keyfile"
_err "Key content:$(wc -l <"$keyfile") lines"
return 1
fi
_debug3 "_signedECText" "$_signedECText"
_ec_r="$(echo "$_signedECText" | _head_n 2 | _tail_n 1 | cut -d : -f 4 | tr -d "\r\n")"
_ec_s="$(echo "$_signedECText" | _head_n 3 | _tail_n 1 | cut -d : -f 4 | tr -d "\r\n")"
if [ "$__ECC_KEY_LEN" -eq "256" ]; then
while [ "${#_ec_r}" -lt "64" ]; do
_ec_r="0${_ec_r}"
done
while [ "${#_ec_s}" -lt "64" ]; do
_ec_s="0${_ec_s}"
done
fi
if [ "$__ECC_KEY_LEN" -eq "384" ]; then
while [ "${#_ec_r}" -lt "96" ]; do
_ec_r="0${_ec_r}"
done
while [ "${#_ec_s}" -lt "96" ]; do
_ec_s="0${_ec_s}"
done
fi
if [ "$__ECC_KEY_LEN" -eq "512" ]; then
while [ "${#_ec_r}" -lt "132" ]; do
_ec_r="0${_ec_r}"
done
while [ "${#_ec_s}" -lt "132" ]; do
_ec_s="0${_ec_s}"
done
fi
_debug3 "_ec_r" "$_ec_r"
_debug3 "_ec_s" "$_ec_s"
printf "%s" "$_ec_r$_ec_s" | _h2b | _base64
else
_err "Unknown key file format."
return 1
fi
}
#dummy function because proxmox-acme does not call inithttp
_resethttp() {
:
}
_HTTP_MAX_RETRY=8
# body url [needbase64] [POST|PUT|DELETE] [ContentType]
_post() {
body="$1"
_post_url="$2"
needbase64="$3"
httpmethod="$4"
_postContentType="$5"
_sleep_retry_sec=1
_http_retry_times=0
_hcode=0
while [ "${_http_retry_times}" -le "$_HTTP_MAX_RETRY" ]; do
[ "$_http_retry_times" = "$_HTTP_MAX_RETRY" ]
_lastHCode="$?"
_debug "Retrying post"
_post_impl "$body" "$_post_url" "$needbase64" "$httpmethod" "$_postContentType" "$_lastHCode"
_hcode="$?"
_debug _hcode "$_hcode"
if [ "$_hcode" = "0" ]; then
break
fi
_http_retry_times=$(_math $_http_retry_times + 1)
_sleep $_sleep_retry_sec
done
return $_hcode
}
# body url [needbase64] [POST|PUT|DELETE] [ContentType] [displayError]
_post_impl() {
body="$1"
_post_url="$2"
needbase64="$3"
httpmethod="$4"
_postContentType="$5"
displayError="$6"
if [ -z "$httpmethod" ]; then
httpmethod="POST"
fi
_CURL="curl -L --silent --dump-header $HTTP_HEADER -g "
if [ "$HTTPS_INSECURE" ]; then
_CURL="$_CURL --insecure "
fi
if [ "$httpmethod" = "HEAD" ]; then
_CURL="$_CURL -I "
fi
if [ "$needbase64" ]; then
if [ "$body" ]; then
if [ "$_postContentType" ]; then
response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)"
else
response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)"
fi
else
if [ "$_postContentType" ]; then
response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$_post_url" | _base64)"
else
response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$_post_url" | _base64)"
fi
fi
else
if [ "$body" ]; then
if [ "$_postContentType" ]; then
response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")"
else
response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")"
fi
else
if [ "$_postContentType" ]; then
response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$_post_url")"
else
response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$_post_url")"
fi
fi
fi
_ret="$?"
if [ "$_ret" != "0" ]; then
if [ -z "$displayError" ] || [ "$displayError" = "0" ]; then
_err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $_ret"
fi
fi
printf "%s" "$response"
return $_ret
}
# url getheader timeout
_get() {
url="$1"
onlyheader="$2"
t="$3"
_sleep_retry_sec=1
_http_retry_times=0
_hcode=0
while [ "${_http_retry_times}" -le "$_HTTP_MAX_RETRY" ]; do
[ "$_http_retry_times" = "$_HTTP_MAX_RETRY" ]
_lastHCode="$?"
_debug "Retrying GET"
_get_impl "$url" "$onlyheader" "$t" "$_lastHCode"
_hcode="$?"
_debug _hcode "$_hcode"
if [ "$_hcode" = "0" ]; then
break
fi
_http_retry_times=$(_math $_http_retry_times + 1)
_sleep $_sleep_retry_sec
done
return $_hcode
}
# url getheader timeout displayError
_get_impl() {
url="$1"
onlyheader="$2"
t="$3"
displayError="$4"
_CURL="curl -L --silent --dump-header $HTTP_HEADER -g "
if [ "$HTTPS_INSECURE" ]; then
_CURL="$_CURL --insecure "
fi
if [ "$t" ]; then
_CURL="$_CURL --connect-timeout $t"
fi
if [ "$onlyheader" ]; then
$_CURL -I --user-agent "USER_AGENT" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$url"
else
$_CURL --user-agent "USER_AGENT" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$url"
fi
ret=$?
if [ "$ret" != "0" ]; then
if [ -z "$displayError" ] || [ "$displayError" = "0" ]; then
_err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $ret"
fi
fi
return $ret
}
#endpoint domain type
_ns_lookup_impl() {
_ns_ep="$1"
_ns_domain="$2"
_ns_type="$3"
_debug2 "_ns_ep" "$_ns_ep"
_debug2 "_ns_domain" "$_ns_domain"
_debug2 "_ns_type" "$_ns_type"
response="$(_H1="accept: application/dns-json" _get "$_ns_ep?name=$_ns_domain&type=$_ns_type")"
_ret=$?
_debug2 "response" "$response"
if [ "$_ret" != "0" ]; then
return $_ret
fi
_answers="$(echo "$response" | tr '{}' '<>' | _egrep_o '"Answer":\[[^]]*]' | tr '<>' '\n\n')"
_debug2 "_answers" "$_answers"
echo "$_answers"
}
#domain, type
_ns_lookup_cf() {
_cf_ld="$1"
_cf_ld_type="$2"
_cf_ep="https://cloudflare-dns.com/dns-query"
_ns_lookup_impl "$_cf_ep" "$_cf_ld" "$_cf_ld_type"
}
#domain, type
_ns_purge_cf() {
_cf_d="$1"
_cf_d_type="$2"
_debug "Purging Cloudflare $_cf_d_type record for domain $_cf_d"
_cf_purl="https://cloudflare-dns.com/api/v1/purge?domain=$_cf_d&type=$_cf_d_type"
response="$(_post "" "$_cf_purl")"
_debug2 response "$response"
}
#checks if cf server is available
_ns_is_available_cf() {
if _get "https://cloudflare-dns.com" "" 10 >/dev/null; then
return 0
else
return 1
fi
}
_ns_is_available_google() {
if _get "https://dns.google" "" 10 >/dev/null; then
return 0
else
return 1
fi
}
#domain, type
_ns_lookup_google() {
_cf_ld="$1"
_cf_ld_type="$2"
_cf_ep="https://dns.google/resolve"
_ns_lookup_impl "$_cf_ep" "$_cf_ld" "$_cf_ld_type"
}
_ns_is_available_ali() {
if _get "https://dns.alidns.com" "" 10 >/dev/null; 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://doh.pub" "" 10 >/dev/null; 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"
}
_ns_select_doh() {
if [ -z "$DOH_USE" ]; then
_debug "Detecting DNS server first."
if _ns_is_available_cf; then
_debug "Using Cloudflare doh server"
export DOH_USE=$DOH_CLOUDFLARE
elif _ns_is_available_google; then
_debug "Using Google DOH server"
export DOH_USE=$DOH_GOOGLE
elif _ns_is_available_ali; then
_debug "Using Aliyun DOH server"
export DOH_USE=$DOH_ALI
elif _ns_is_available_dp; then
_debug "Using DNS POD DOH server"
export DOH_USE=$DOH_DP
else
_err "No DOH"
fi
fi
}
#domain, type
_ns_lookup() {
_ns_select_doh
if [ "$DOH_USE" = "$DOH_CLOUDFLARE" ] || [ -z "$DOH_USE" ]; then
_ns_lookup_cf "$@"
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
}
_head_n() {
head -n "$1"
}
_tail_n() {
tail -n "$1"
}
# stdin output hexstr splited by one space
# input:"abc"
# output: " 61 62 63"
_hex_dump() {
od -A n -v -t x1 | tr -s " " | sed 's/ $//' | tr -d "\r\t\n"
}
# stdin stdout
#_url_encode [upper-hex] the encoded hex will be upper-case if the argument upper-hex is followed
_url_encode() {
_upper_hex=$1
_hex_str=$(_hex_dump)
for _hex_code in $_hex_str; do
#upper case
case "${_hex_code}" in
"41")
printf "%s" "A"
;;
"42")
printf "%s" "B"
;;
"43")
printf "%s" "C"
;;
"44")
printf "%s" "D"
;;
"45")
printf "%s" "E"
;;
"46")
printf "%s" "F"
;;
"47")
printf "%s" "G"
;;
"48")
printf "%s" "H"
;;
"49")
printf "%s" "I"
;;
"4a")
printf "%s" "J"
;;
"4b")
printf "%s" "K"
;;
"4c")
printf "%s" "L"
;;
"4d")
printf "%s" "M"
;;
"4e")
printf "%s" "N"
;;
"4f")
printf "%s" "O"
;;
"50")
printf "%s" "P"
;;
"51")
printf "%s" "Q"
;;
"52")
printf "%s" "R"
;;
"53")
printf "%s" "S"
;;
"54")
printf "%s" "T"
;;
"55")
printf "%s" "U"
;;
"56")
printf "%s" "V"
;;
"57")
printf "%s" "W"
;;
"58")
printf "%s" "X"
;;
"59")
printf "%s" "Y"
;;
"5a")
printf "%s" "Z"
;;
#lower case
"61")
printf "%s" "a"
;;
"62")
printf "%s" "b"
;;
"63")
printf "%s" "c"
;;
"64")
printf "%s" "d"
;;
"65")
printf "%s" "e"
;;
"66")
printf "%s" "f"
;;
"67")
printf "%s" "g"
;;
"68")
printf "%s" "h"
;;
"69")
printf "%s" "i"
;;
"6a")
printf "%s" "j"
;;
"6b")
printf "%s" "k"
;;
"6c")
printf "%s" "l"
;;
"6d")
printf "%s" "m"
;;
"6e")
printf "%s" "n"
;;
"6f")
printf "%s" "o"
;;
"70")
printf "%s" "p"
;;
"71")
printf "%s" "q"
;;
"72")
printf "%s" "r"
;;
"73")
printf "%s" "s"
;;
"74")
printf "%s" "t"
;;
"75")
printf "%s" "u"
;;
"76")
printf "%s" "v"
;;
"77")
printf "%s" "w"
;;
"78")
printf "%s" "x"
;;
"79")
printf "%s" "y"
;;
"7a")
printf "%s" "z"
;;
#numbers
"30")
printf "%s" "0"
;;
"31")
printf "%s" "1"
;;
"32")
printf "%s" "2"
;;
"33")
printf "%s" "3"
;;
"34")
printf "%s" "4"
;;
"35")
printf "%s" "5"
;;
"36")
printf "%s" "6"
;;
"37")
printf "%s" "7"
;;
"38")
printf "%s" "8"
;;
"39")
printf "%s" "9"
;;
"2d")
printf "%s" "-"
;;
"5f")
printf "%s" "_"
;;
"2e")
printf "%s" "."
;;
"7e")
printf "%s" "~"
;;
#other hex
*)
if [ "$_upper_hex" = "upper-hex" ]; then
_hex_code=$(printf "%s" "$_hex_code" | _upper_case)
fi
printf '%%%s' "$_hex_code"
;;
esac
done
}
# Usage: hashalg secret_hex [outputhex]
# Output binary hmac
_hmac() {
alg="$1"
secret_hex="$2"
outputhex="$3"
if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ]; then
if [ "$outputhex" ]; then
(openssl dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" 2>/dev/null || openssl dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)") | cut -d = -f 2 | tr -d ' '
else
openssl dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" -binary 2>/dev/null || openssl dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)" -binary
fi
fi
}
# domain
_is_idn() {
_is_idn_d="$1"
_idn_temp=$(printf "%s" "$_is_idn_d" | tr -d '0-9' | tr -d 'a-z' | tr -d 'A-Z' | tr -d '*.,-_')
[ "$_idn_temp" ]
}
# aa.com
_idn() {
__idn_d="$1"
if ! _is_idn "$__idn_d"; then
printf "%s" "$__idn_d"
return 0
fi
if _exists idn; then
idn "$__idn_d" | tr -d "\r\n"
else
_err "Please install idn to process IDN names."
fi
}
_normalizeJson() {
sed "s/\" *: *\([\"{\[]\)/\":\1/g" | sed "s/^ *\([^ ]\)/\1/" | tr -d "\r\n"
}
# options file
_sed_i() {
sed -i "$1" "$2"
}
# sleep sec
_sleep() {
sleep "$1"
}
_stat() {
stat -c '%U:%G' "$1" 2>/dev/null
}
#keyfile
_isRSA() {
keyfile=$1
if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1 || ${ACME_OPENSSL_BIN:-openssl} rsa -in "$keyfile" -noout -text | grep "^publicExponent:" >/dev/null 2>&1; then
return 0
fi
return 1
}
#keyfile
_isEcc() {
keyfile=$1
if grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1 || ${ACME_OPENSSL_BIN:-openssl} ec -in "$keyfile" -noout -text 2>/dev/null | grep "^NIST CURVE:" >/dev/null 2>&1; then
return 0
fi
return 1
}
_time() {
date -u "+%s"
}
_utc_date() {
date -u "+%Y-%m-%d %H:%M:%S"
}
# stubbed/aliased:
__green() {
printf -- "%b" "$1"
}
__red() {
printf -- "%b" "$1"
}
_log() {
return 0
}
_info() {
printf -- "%s" "[$(date)] " >&1
echo "$1"
}
_err() {
printf -- "%s" "[$(date)] " >&2
if [ -z "$2" ]; then
__red "$1" >&2
else
__red "$1='$2'" >&2
fi
printf "\n" >&2
return 1
}
# key
_readaccountconf() {
echo "${!1}"
}
# key
_readaccountconf_mutable() {
_readaccountconf "$1"
}
# key
_readdomainconf() {
echo "${!1}"
}
# no-ops:
_clearaccountconf() {
return 0
}
_clearaccountconf_mutable() {
return 0
}
_cleardomainconf() {
return 0
}
_debug() {
if [[ $DEBUG -eq 0 ]]; then
return
fi
printf -- "%s" "[$(date)] " >&1
echo "$1 $2"
}
_debug2() {
_debug $1 $2
}
_debug3() {
_debug $1 $2
}
_secure_debug() {
_debug $1 $2
}
_secure_debug2() {
_debug $1 $2
}
_secure_debug3() {
_debug $1 $2
}
_saveaccountconf() {
return 0
}
_saveaccountconf_mutable() {
return 0
}
_save_conf() {
return 0
}
_savedomainconf() {
return 0
}
_source_plugin_config() {
return 0
}
# this is for de-escaping a JSON-encoded *string*, e.g. from: http:\/\/ to http://
_json_decode() {
_j_str="$(sed 's#\\/#/#g')"
_debug3 "_json_decode"
_debug3 "_j_str" "$_j_str"
echo "$_j_str"
}
# Proxmox implementation to inject the DNSAPI variables
_load_plugin_config() {
while IFS= read -r line; do
ADDR=(${line/=/ })
key="${ADDR[0]}"
value="${ADDR[1]}"
# acme.sh uses eval insted of export
if [ -n "$key" ]; then
export "$key"="$value"
fi
done
}
# call setup and teardown direct
# the parameter must be set in the correct order
# $1 <String> DNS Plugin name
# $2 <String> Fully Qualified Domain Name
# $3 <String> value for TXT record
# $4 <String> DNS plugin auth and config parameter separated by ","
# $5 <Integer> 0 is off, and the default all others are on.
setup() {
dns_plugin="dns_$1"
dns_plugin_path="${DNS_PLUGIN_PATH}/${dns_plugin}.sh"
fqdn="_acme-challenge.$2"
DEBUG=$3
IFS= read -r txtvalue
plugin_conf_string=$4
_load_plugin_config
if ! . "$dns_plugin_path"; then
_err "Load file $dns_plugin error."
return 1
fi
addcommand="${dns_plugin}_add"
if ! _exists "$addcommand"; then
_err "It seems that your api file is not correct, it must have a function named: $addcommand"
return 1
fi
if ! $addcommand "$fqdn" "$txtvalue"; then
_err "Error add txt for domain:$fulldomain"
return 1
fi
}
teardown() {
dns_plugin="dns_$1"
dns_plugin_path="${DNS_PLUGIN_PATH}/${dns_plugin}.sh"
fqdn="_acme-challenge.$2"
DEBUG=$3
IFS= read -r txtvalue
_load_plugin_config
if ! . "$dns_plugin_path"; then
_err "Load file $dns_plugin error."
return 1
fi
rmcommand="${dns_plugin}_rm"
if ! _exists "$rmcommand"; then
_err "It seems that your api file is not correct, it must have a function named: $rmcommand"
return 1
fi
if ! $rmcommand "$fqdn" "$txtvalue"; then
_err "Error add txt for domain:$fulldomain"
return 1
fi
}
"$@"