-#!/usr/bin/env sh
+#!/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"
-# copied from acme.sh
-# Usage: multiline
_base64() {
- [ "" ] #urgly
- if [ "$1" ]; then
- _debug3 "base64 multiline:'$1'"
- ${ACME_OPENSSL_BIN:-openssl} base64 -e
- else
- _debug3 "base64 single line."
- ${ACME_OPENSSL_BIN:-openssl} base64 -e | tr -d '\r\n'
- fi
+ openssl base64 -e | tr -d '\r\n'
}
-# Usage: multiline
_dbase64() {
- if [ "$1" ]; then
- ${ACME_OPENSSL_BIN:-openssl} base64 -d -A
- else
- ${ACME_OPENSSL_BIN:-openssl} base64 -d
- fi
+ openssl base64 -d
}
# Usage: hashalg [outputhex]
# Output Base64-encoded digest
_digest() {
alg="$1"
- if [ -z "$alg" ]; then
- _usage "Usage: _digest hashalg"
- return 1
- fi
-
- outputhex="$2"
if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ] || [ "$alg" = "md5" ]; then
- if [ "$outputhex" ]; then
- ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -hex | cut -d = -f 2 | tr -d ' '
+ if [ "$2" ]; then
+ openssl dgst -"$alg" -hex | cut -d = -f 2 | tr -d ' '
else
- ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -binary | _base64
+ openssl dgst -"$alg" -binary | _base64
fi
- else
- _err "$alg is not supported yet"
- return 1
fi
+}
+_usage() {
+ __red "$@" >&2
+ printf "\n" >&2
}
_upper_case() {
_findex="$2"
_sep="$3"
- if [ -z "$_findex" ]; then
- _usage "Usage: str field [sep]"
- return 1
- fi
-
if [ -z "$_sep" ]; then
_sep=","
fi
_exists() {
cmd="$1"
- if [ -z "$cmd" ]; then
- _usage "Usage: _exists cmd"
- return 1
- fi
-
if eval type type >/dev/null 2>&1; then
- eval type "$cmd" >/dev/null 2>&1
- elif command >/dev/null 2>&1; then
+ type "$cmd" >/dev/null 2>&1
+ else command
command -v "$cmd" >/dev/null 2>&1
- else
- which "$cmd" >/dev/null 2>&1
fi
ret="$?"
- _debug3 "$cmd exists=$ret"
return $ret
}
fi
}
-_inithttp() {
-
- if [ -z "$HTTP_HEADER" ] || ! touch "$HTTP_HEADER"; then
- HTTP_HEADER="$(_mktemp)"
- _debug2 HTTP_HEADER "$HTTP_HEADER"
- fi
-
- if [ "$__HTTP_INITIALIZED" ]; then
- if [ "$_ACME_CURL$_ACME_WGET" ]; then
- _debug2 "Http already initialized."
- return 0
+_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
- if [ -z "$_ACME_CURL" ] && _exists "curl"; then
- _ACME_CURL="curl -L --silent --dump-header $HTTP_HEADER "
- if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
- _CURL_DUMP="$(_mktemp)"
- _ACME_CURL="$_ACME_CURL --trace-ascii $_CURL_DUMP "
+ 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
- if [ "$CA_PATH" ]; then
- _ACME_CURL="$_ACME_CURL --capath $CA_PATH "
- elif [ "$CA_BUNDLE" ]; then
- _ACME_CURL="$_ACME_CURL --cacert $CA_BUNDLE "
- fi
+}
- if _contains "$(curl --help 2>&1)" "--globoff"; then
- _ACME_CURL="$_ACME_CURL -g "
- 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
- if [ -z "$_ACME_WGET" ] && _exists "wget"; then
- _ACME_WGET="wget -q"
- if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
- _ACME_WGET="$_ACME_WGET -d "
+ _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
- if [ "$CA_PATH" ]; then
- _ACME_WGET="$_ACME_WGET --ca-directory=$CA_PATH "
- elif [ "$CA_BUNDLE" ]; then
- _ACME_WGET="$_ACME_WGET --ca-certificate=$CA_BUNDLE "
+ _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
- #from wget 1.14: do not skip body on 404 error
- if [ "$_ACME_WGET" ] && _contains "$($_ACME_WGET --help 2>&1)" "--content-on-error"; then
- _ACME_WGET="$_ACME_WGET --content-on-error "
- fi
-
- __HTTP_INITIALIZED=1
+}
+#dummy function because proxmox-acme does not call inithttp
+_resethttp() {
+ :
}
+_HTTP_MAX_RETRY=8
+
# body url [needbase64] [POST|PUT|DELETE] [ContentType]
_post() {
body="$1"
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
- _debug $httpmethod
- _debug "_post_url" "$_post_url"
- _debug2 "body" "$body"
- _debug2 "_postContentType" "$_postContentType"
-
- _inithttp
- if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then
- _CURL="$_ACME_CURL"
- if [ "$HTTPS_INSECURE" ]; then
- _CURL="$_CURL --insecure "
- fi
- if [ "$httpmethod" = "HEAD" ]; then
- _CURL="$_CURL -I "
- fi
- _debug "_CURL" "$_CURL"
- 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
+ _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
- 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
+ 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 [ "$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
+ 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
- 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
- _err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $_ret"
- if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
- _err "Here is the curl dump log:"
- _err "$(cat "$_CURL_DUMP")"
+ response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$_post_url" | _base64)"
fi
fi
- elif [ "$_ACME_WGET" ]; then
- _WGET="$_ACME_WGET"
- if [ "$HTTPS_INSECURE" ]; then
- _WGET="$_WGET --no-check-certificate "
- fi
- if [ "$httpmethod" = "HEAD" ]; then
- _WGET="$_WGET --read-timeout=3.0 --tries=2 "
- fi
- _debug "_WGET" "$_WGET"
- if [ "$needbase64" ]; then
- if [ "$httpmethod" = "POST" ]; then
- if [ "$_postContentType" ]; then
- response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)"
- else
- response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)"
- fi
+ else
+ if [ "$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
- if [ "$_postContentType" ]; then
- response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)"
- else
- response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)"
- fi
+ 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 [ "$httpmethod" = "POST" ]; then
- if [ "$_postContentType" ]; then
- response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER")"
- else
- response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER")"
- fi
- elif [ "$httpmethod" = "HEAD" ]; then
- if [ "$_postContentType" ]; then
- response="$($_WGET --spider -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER")"
- else
- response="$($_WGET --spider -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER")"
- fi
+ 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
- if [ "$_postContentType" ]; then
- response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER")"
- else
- response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER")"
- fi
+ response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$_post_url")"
fi
fi
- _ret="$?"
- if [ "$_ret" = "8" ]; then
- _ret=0
- _debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later."
- fi
- if [ "$_ret" != "0" ]; then
- _err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $_ret"
+ fi
+ _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
- _sed_i "s/^ *//g" "$HTTP_HEADER"
- else
- _ret="$?"
- _err "Neither curl nor wget is found, can not do $httpmethod."
fi
- _debug "_ret" "$_ret"
printf "%s" "$response"
return $_ret
}
# url getheader timeout
_get() {
- _debug GET
url="$1"
onlyheader="$2"
t="$3"
- _debug url "$url"
- _debug "timeout=$t"
+ _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
+}
- _inithttp
+# url getheader timeout displayError
+_get_impl() {
+ url="$1"
+ onlyheader="$2"
+ t="$3"
+ displayError="$4"
- if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then
- _CURL="$_ACME_CURL"
- if [ "$HTTPS_INSECURE" ]; then
- _CURL="$_CURL --insecure "
- fi
- if [ "$t" ]; then
- _CURL="$_CURL --connect-timeout $t"
- fi
- _debug "_CURL" "$_CURL"
- 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
+ _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"
- if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
- _err "Here is the curl dump log:"
- _err "$(cat "$_CURL_DUMP")"
- fi
- fi
- elif [ "$_ACME_WGET" ]; then
- _WGET="$_ACME_WGET"
- if [ "$HTTPS_INSECURE" ]; then
- _WGET="$_WGET --no-check-certificate "
- fi
- if [ "$t" ]; then
- _WGET="$_WGET --timeout=$t"
- fi
- _debug "_WGET" "$_WGET"
- if [ "$onlyheader" ]; then
- $_WGET --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" -S -O /dev/null "$url" 2>&1 | sed 's/^[ ]*//g'
- else
- $_WGET --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" -O - "$url"
fi
- ret=$?
- if [ "$ret" = "8" ]; then
- ret=0
- _debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later."
- fi
- if [ "$ret" != "0" ]; then
- _err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $ret"
- fi
- else
- ret=$?
- _err "Neither curl nor wget is found, can not do GET."
fi
- _debug "ret" "$ret"
return $ret
}
}
_tail_n() {
- if ! tail -n "$1" 2>/dev/null; then
- #fix for solaris
- tail -"$1"
- fi
+ tail -n "$1"
}
# stdin output hexstr splited by one space
# input:"abc"
# output: " 61 62 63"
_hex_dump() {
- if _exists od; then
- od -A n -v -t x1 | tr -s " " | sed 's/ $//' | tr -d "\r\t\n"
- elif _exists hexdump; then
- _debug3 "using hexdump"
- hexdump -v -e '/1 ""' -e '/1 " %02x" ""'
- elif _exists xxd; then
- _debug3 "using xxd"
- xxd -ps -c 20 -i | sed "s/ 0x/ /g" | tr -d ",\n" | tr -s " "
- else
- _debug3 "using _ascii_hex"
- str=$(cat)
- _ascii_hex "$str"
- fi
+ od -A n -v -t x1 | tr -s " " | sed 's/ $//' | tr -d "\r\t\n"
}
# stdin stdout
_url_encode() {
_hex_str=$(_hex_dump)
- _debug3 "_url_encode"
- _debug3 "_hex_str" "$_hex_str"
for _hex_code in $_hex_str; do
#upper case
case "${_hex_code}" in
"7a")
printf "%s" "z"
;;
+
#numbers
"30")
printf "%s" "0"
"7e")
printf "%s" "~"
;;
+
#other hex
*)
printf '%%%s' "$_hex_code"
secret_hex="$2"
outputhex="$3"
- if [ -z "$secret_hex" ]; then
- _usage "Usage: _hmac hashalg secret [outputhex]"
- return 1
- fi
-
if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ]; then
if [ "$outputhex" ]; then
- (${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" 2>/dev/null || ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)") | cut -d = -f 2 | tr -d ' '
+ (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
- ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" -binary 2>/dev/null || ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)" -binary
+ openssl dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" -binary 2>/dev/null || openssl dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)" -binary
fi
- else
- _err "$alg is not supported yet"
- return 1
fi
-
}
# domain
_is_idn() {
_is_idn_d="$1"
- _debug2 _is_idn_d "$_is_idn_d"
_idn_temp=$(printf "%s" "$_is_idn_d" | tr -d '0-9' | tr -d 'a-z' | tr -d 'A-Z' | tr -d '*.,-_')
- _debug2 _idn_temp "$_idn_temp"
[ "$_idn_temp" ]
}
# aa.com
-# aa.com,bb.com,cc.com
_idn() {
__idn_d="$1"
if ! _is_idn "$__idn_d"; then
fi
if _exists idn; then
- if _contains "$__idn_d" ','; then
- _i_first="1"
- for f in $(echo "$__idn_d" | tr ',' ' '); do
- [ -z "$f" ] && continue
- if [ -z "$_i_first" ]; then
- printf "%s" ","
- else
- _i_first=""
- fi
- idn --quiet "$f" | tr -d "\r\n"
- done
- else
- idn "$__idn_d" | tr -d "\r\n"
- fi
+ idn "$__idn_d" | tr -d "\r\n"
else
_err "Please install idn to process IDN names."
fi
# options file
_sed_i() {
- options="$1"
- filename="$2"
- if [ -z "$filename" ]; then
- _usage "Usage:_sed_i options filename"
- return 1
- fi
- _debug2 options "$options"
- if sed -h 2>&1 | grep "\-i\[SUFFIX]" >/dev/null 2>&1; then
- _debug "Using sed -i"
- sed -i "$options" "$filename"
- else
- _debug "No -i support in sed"
- text="$(cat "$filename")"
- echo "$text" | sed "$options" >"$filename"
- fi
+ sed -i "$1" "$2"
}
# sleep sec
_sleep() {
- _sleep_sec="$1"
- if [ "$__INTERACTIVE" ]; then
- _sleep_c="$_sleep_sec"
- while [ "$_sleep_c" -ge "0" ]; do
- printf "\r \r"
- __green "$_sleep_c"
- _sleep_c="$(_math "$_sleep_c" - 1)"
- sleep 1
- done
- printf "\r"
- else
- sleep "$_sleep_sec"
- fi
+ sleep "$1"
}
_stat() {
- #Linux
- if stat -c '%U:%G' "$1" 2>/dev/null; then
- return
- fi
-
- #BSD
- if stat -f '%Su:%Sg' "$1" 2>/dev/null; then
- return
- fi
-
- return 1 #error, 'stat' not found
+ stat -c '%U:%G' "$1" 2>/dev/null
}
-
_time() {
date -u "+%s"
}
# stubbed/aliased:
__green() {
- if [ "${__INTERACTIVE}${ACME_NO_COLOR:-0}" = "10" -o "${ACME_FORCE_COLOR}" = "1" ]; then
- printf '\033[1;31;32m%b\033[0m' "$1"
- return
- fi
printf -- "%b" "$1"
}
__red() {
- if [ "${__INTERACTIVE}${ACME_NO_COLOR:-0}" = "10" -o "${ACME_FORCE_COLOR}" = "1" ]; then
- printf '\033[1;31;40m%b\033[0m' "$1"
- return
- fi
printf -- "%b" "$1"
}
_log() {
- [ -z "$LOG_FILE" ] && return
- _printargs "$@" >>"$LOG_FILE"
+ return 0
}
_info() {
- _log "$@"
- if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_INFO" ]; then
- _syslog "$SYSLOG_INFO" "$@"
- fi
- _printargs "$@"
+ printf -- "%s" "[$(date)] " >&1
+ echo "$1"
}
_err() {
- _syslog "$SYSLOG_ERROR" "$@"
- _log "$@"
- if [ -z "$NO_TIMESTAMP" ] || [ "$NO_TIMESTAMP" = "0" ]; then
- printf -- "%s" "[$(date)] " >&2
- fi
+ printf -- "%s" "[$(date)] " >&2
if [ -z "$2" ]; then
__red "$1" >&2
else
# key
_readaccountconf() {
- _read_conf "$ACCOUNT_CONF_PATH" "$1"
+ echo "${!1}"
}
# key
_readaccountconf_mutable() {
- _rac_key="$1"
- _readaccountconf "SAVED_$_rac_key"
+ _readaccountconf "$1"
+}
+
+# no-ops:
+_clearaccountconf() {
+ 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
+}
+
+# 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
+}
+
+"$@"