-#!/usr/bin/env sh
+#!/bin/bash
-VER=0.9
+VER=1.0
PROJECT_NAME="ProxmoxACME"
fi
}
+_usage() {
+ __red "$@" >&2
+ printf "\n" >&2
+}
+
_upper_case() {
# shellcheck disable=SC2018,SC2019
tr 'a-z' 'A-Z'
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"
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
_ret="$?"
if [ "$_ret" != "0" ]; then
- _err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $_ret"
+ 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="$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
fi
ret=$?
if [ "$ret" != "0" ]; then
- _err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $ret"
+ 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
}
}
_log() {
- return
+ return 0
}
_info() {
# key
_readaccountconf() {
- echo "$1"
+ echo "${!1}"
}
# key
# no-ops:
_clearaccountconf() {
- return
+ return 0
}
_cleardomainconf() {
- return
+ return 0
}
_debug() {
}
_saveaccountconf() {
- return
+ return 0
}
_saveaccountconf_mutable() {
- return
+ return 0
}
_save_conf() {
- return
+ return 0
}
_savedomainconf() {
- return
+ return 0
}
_source_plugin_config() {
- return
+ return 0
}
# Proxmox implementation to inject the DNSAPI variables