From f500c7abcba29d19b2d49d8e3b25d9c6d5e2f726 Mon Sep 17 00:00:00 2001 From: Bill Gertz Date: Tue, 8 Oct 2019 15:47:39 +0200 Subject: [PATCH 01/11] dnsapi/dns_miab.sh MIAB DNS-01 Validation Know I'm new to contorting to this project. I i've broke conventions please let me know what I've screwed up and I'll set it right as quickly as possible. Propose this as a new DNS-01 validation script to dynamically add challenge DNS records to MailinaBox (MIAB) DNS. MIAB uses a custom DNS API to manage external DNS records. The script was originally written by Darven Dissek and can be found in his repository: https://framagit.org/DarvenDissek/acme.sh-MIAB-DNS-API/). This has been forked and some slight cleanup applied and change shebang to UNIx shell. The forked repository can be found here: https://github.com/billgertz/MIAB_dns_api. Wrote to Darven but received no reply. Support for this script has been submitted to the OPNsense project via this pull request: https://github.com/opnsense/plugins/pull/1531 --- dnsapi/dns_miab.sh | 273 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 dnsapi/dns_miab.sh diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh new file mode 100644 index 00000000..b0a52d7e --- /dev/null +++ b/dnsapi/dns_miab.sh @@ -0,0 +1,273 @@ +#!/usr/bin/env sh + +#Name: dns_miab.sh +# +#Authors: +# Darven Dissek 2018 +# William Gertz 2019 +# +# Thanks to Neil Pang for the code reused from acme.sh from HTTP-01 validation +# used to communicate with the MailintheBox Custom DNS API +#Report Bugs here: +# https://github.com/billgertz/MIAB_dns_api (for dns_miab.sh) +# https://github.com/Neilpang/acme.sh (for acme.sh) +# +######## Public functions ##################### + +#Usage: dns_miab_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_miab_add() { + fulldomain=$1 + txtvalue=$2 + _info "Using miab" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + MIAB_Username="${MIAB_Username:-$(_readaccountconf_mutable MIAB_Username)}" + MIAB_Password="${MIAB_Password:-$(_readaccountconf_mutable MIAB_Password)}" + MIAB_Server="${MIAB_Server:-$(_readaccountconf_mutable MIAB_Server)}" + + #debug log the environmental variables + _debug MIAB_Username "$MIAB_Username" + _debug MIAB_Password "$MIAB_Password" + _debug MIAB_Server "$MIAB_Server" + + if [ -z "$MIAB_Username" ] || [ -z "$MIAB_Password" ] || [ -z "$MIAB_Server" ]; then + MIAB_Username="" + MIAB_Password="" + MIAB_Server="" + _err "You didn't specify MIAB_Username or MIAB_Password or MIAB_Server." + _err "Please try again." + return 1 + fi + + #save the credentials to the account conf file. + _saveaccountconf_mutable MIAB_Username "$MIAB_Username" + _saveaccountconf_mutable MIAB_Password "$MIAB_Password" + _saveaccountconf_mutable MIAB_Server "$MIAB_Server" + + baseurl="https://$MIAB_Server/admin/dns/custom/$fulldomain/txt" + + #Add the challenge record + result="$(_miab_post "$txtvalue" "$baseurl" "" "POST" "" "$MIAB_Username" "$MIAB_Password")" + + _debug result "$result" + + #check if result was good + if _contains "$result" "updated DNS"; then + _info "Successfully created the txt record" + return 0 + else + _err "Error encountered during record addition" + _err "$result" + return 1 + fi + +} + +#Usage: fulldomain txtvalue +#Remove the txt record after validation. +dns_miab_rm() { + fulldomain=$1 + txtvalue=$2 + _info "Using miab" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + MIAB_Username="${MIAB_Username:-$(_readaccountconf_mutable MIAB_Username)}" + MIAB_Password="${MIAB_Password:-$(_readaccountconf_mutable MIAB_Password)}" + MIAB_Server="${MIAB_Server:-$(_readaccountconf_mutable MIAB_Server)}" + + #debug log the environmental variables + _debug MIAB_Username "$MIAB_Username" + _debug MIAB_Password "$MIAB_Password" + _debug MIAB_Server "$MIAB_Server" + + if [ -z "$MIAB_Username" ] || [ -z "$MIAB_Password" ] || [ -z "$MIAB_Server" ]; then + MIAB_Username="" + MIAB_Password="" + MIAB_Server="" + _err "You didn't specify MIAB_Username or MIAB_Password or MIAB_Server." + _err "Please try again." + return 1 + fi + + #save the credentials to the account conf file. + _saveaccountconf_mutable MIAB_Username "$MIAB_Username" + _saveaccountconf_mutable MIAB_Password "$MIAB_Password" + _saveaccountconf_mutable MIAB_Server "$MIAB_Server" + + baseurl="https://$MIAB_Server/admin/dns/custom/$fulldomain/txt" + + #Remove the challenge record + result="$(_miab_post "$txtvalue" "$baseurl" "" "DELETE" "" "$MIAB_Username" "$MIAB_Password")" + + _debug result $result + + #check if result was good + if _contains "$result" "updated DNS"; then + _info "Successfully created the txt record" + return 0 + else + _err "Error encountered during record addition" + _err "$result" + return 1 + fi +} + +#################### 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=2 + 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 _contains "$response" "\"name\":\"$h\"" >/dev/null; then + _domain_id=$(printf "%s\n" "$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 + return 0 + fi + + return 1 + fi + + p=$i + i=$(_math "$i" + 1) + done + + return 1 +} + +# post changes to MIAB dns (taken from acme.sh) +_miab_post() { + body="$1" + _post_url="$2" + needbase64="$3" + httpmethod="$4" + _postContentType="$5" + username="$6" + password="$7" + + 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 + + _debug "_CURL" "$_CURL" + + if [ "$needbase64" ]; then + if [ "$_postContentType" ]; then + response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod --user "$username:$password" -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 --user "$username:$password" -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 --user "$username:$password" -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 --user "$username:$password" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")" + 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")" + fi + fi + + elif [ "$_ACME_WGET" ]; then + _WGET="$_ACME_WGET" + + if [ "$HTTPS_INSECURE" ]; then + _WGET="$_WGET --no-check-certificate " + 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 [ "$_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 + 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 + 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 + 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 + + _sed_i "s/^ *//g" "$HTTP_HEADER" + + else + _ret="$?" + _err "Neither curl nor wget was found, cannot do $httpmethod." + fi + + _debug "_ret" "$_ret" + printf "%s" "$response" + return $_ret +} From 47c33d0344208d0bb47f173d64672e69fc18ac37 Mon Sep 17 00:00:00 2001 From: Bill Gertz Date: Tue, 8 Oct 2019 16:29:23 +0200 Subject: [PATCH 02/11] Cleanup/ removed private function _get_root Function _get_root() copied from acme.sh and is not needed here. Other cleanup as recommended by acme.sh test bot. --- dnsapi/dns_miab.sh | 71 +++++++++++----------------------------------- 1 file changed, 17 insertions(+), 54 deletions(-) diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh index b0a52d7e..b68f6705 100644 --- a/dnsapi/dns_miab.sh +++ b/dnsapi/dns_miab.sh @@ -1,16 +1,16 @@ #!/usr/bin/env sh -#Name: dns_miab.sh +# Name: dns_miab.sh # -#Authors: -# Darven Dissek 2018 -# William Gertz 2019 +# Authors: +# Darven Dissek 2018 +# William Gertz 2019 # -# Thanks to Neil Pang for the code reused from acme.sh from HTTP-01 validation -# used to communicate with the MailintheBox Custom DNS API -#Report Bugs here: -# https://github.com/billgertz/MIAB_dns_api (for dns_miab.sh) -# https://github.com/Neilpang/acme.sh (for acme.sh) +# Thanks to Neil Pang for the code reused from acme.sh from HTTP-01 validation +# used to communicate with the MailintheBox Custom DNS API +# Report Bugs here: +# https://github.com/billgertz/MIAB_dns_api (for dns_miab.sh) +# https://github.com/Neilpang/acme.sh (for acme.sh) # ######## Public functions ##################### @@ -41,9 +41,9 @@ dns_miab_add() { fi #save the credentials to the account conf file. - _saveaccountconf_mutable MIAB_Username "$MIAB_Username" - _saveaccountconf_mutable MIAB_Password "$MIAB_Password" - _saveaccountconf_mutable MIAB_Server "$MIAB_Server" + _saveaccountconf_mutable MIAB_Username "$MIAB_Username" + _saveaccountconf_mutable MIAB_Password "$MIAB_Password" + _saveaccountconf_mutable MIAB_Server "$MIAB_Server" baseurl="https://$MIAB_Server/admin/dns/custom/$fulldomain/txt" @@ -61,7 +61,6 @@ dns_miab_add() { _err "$result" return 1 fi - } #Usage: fulldomain txtvalue @@ -92,16 +91,16 @@ dns_miab_rm() { fi #save the credentials to the account conf file. - _saveaccountconf_mutable MIAB_Username "$MIAB_Username" - _saveaccountconf_mutable MIAB_Password "$MIAB_Password" - _saveaccountconf_mutable MIAB_Server "$MIAB_Server" + _saveaccountconf_mutable MIAB_Username "$MIAB_Username" + _saveaccountconf_mutable MIAB_Password "$MIAB_Password" + _saveaccountconf_mutable MIAB_Server "$MIAB_Server" baseurl="https://$MIAB_Server/admin/dns/custom/$fulldomain/txt" #Remove the challenge record result="$(_miab_post "$txtvalue" "$baseurl" "" "DELETE" "" "$MIAB_Username" "$MIAB_Password")" - _debug result $result + _debug result "$result" #check if result was good if _contains "$result" "updated DNS"; then @@ -115,43 +114,7 @@ dns_miab_rm() { } #################### 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=2 - 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 _contains "$response" "\"name\":\"$h\"" >/dev/null; then - _domain_id=$(printf "%s\n" "$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 - return 0 - fi - - return 1 - fi - - p=$i - i=$(_math "$i" + 1) - done - - return 1 -} - +# # post changes to MIAB dns (taken from acme.sh) _miab_post() { body="$1" From a4ec9f8b44a0ae2a22c4af44d423b58e73fa6fdf Mon Sep 17 00:00:00 2001 From: Bill Gertz Date: Tue, 8 Oct 2019 16:34:56 +0200 Subject: [PATCH 03/11] Fixed weird spacing on line 180 Um, fixed. --- dnsapi/dns_miab.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh index b68f6705..c91bf3c8 100644 --- a/dnsapi/dns_miab.sh +++ b/dnsapi/dns_miab.sh @@ -180,7 +180,7 @@ _miab_post() { if [ "$needbase64" ]; then - if [ "$httpmethod" = "POST" ]; 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 From 835f9aad91e9995e688b1be8e827f0a6443af746 Mon Sep 17 00:00:00 2001 From: Bill Gertz Date: Tue, 8 Oct 2019 16:47:32 +0200 Subject: [PATCH 04/11] Um that's a wee bit of nit pick. 'Errant' space removed on blank line on line 147. --- dnsapi/dns_miab.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh index c91bf3c8..8786634d 100644 --- a/dnsapi/dns_miab.sh +++ b/dnsapi/dns_miab.sh @@ -144,7 +144,7 @@ _miab_post() { fi _debug "_CURL" "$_CURL" - + if [ "$needbase64" ]; then if [ "$_postContentType" ]; then response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod --user "$username:$password" -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)" From c06ec7c6bae0cc40daede2121d006b764e73cb47 Mon Sep 17 00:00:00 2001 From: Bill Gertz Date: Tue, 8 Oct 2019 18:15:16 +0200 Subject: [PATCH 05/11] Removed parameters and unused code for _miab_post Ok, should have noticed earlier that the calls to the private function _miab_post() never used the _needbase64_ or the __postContentType parameters. Parameters and code to handle them has been factored out. --- dnsapi/dns_miab.sh | 70 +++++++++------------------------------------- 1 file changed, 13 insertions(+), 57 deletions(-) diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh index 8786634d..df2ca6e2 100644 --- a/dnsapi/dns_miab.sh +++ b/dnsapi/dns_miab.sh @@ -48,7 +48,7 @@ dns_miab_add() { baseurl="https://$MIAB_Server/admin/dns/custom/$fulldomain/txt" #Add the challenge record - result="$(_miab_post "$txtvalue" "$baseurl" "" "POST" "" "$MIAB_Username" "$MIAB_Password")" + result="$(_miab_post "$txtvalue" "$baseurl" "POST" "$MIAB_Username" "$MIAB_Password")" _debug result "$result" @@ -91,14 +91,14 @@ dns_miab_rm() { fi #save the credentials to the account conf file. - _saveaccountconf_mutable MIAB_Username "$MIAB_Username" - _saveaccountconf_mutable MIAB_Password "$MIAB_Password" - _saveaccountconf_mutable MIAB_Server "$MIAB_Server" + _saveaccountconf_mutable MIAB_Username "$MIAB_Username" + _saveaccountconf_mutable MIAB_Password "$MIAB_Password" + _saveaccountconf_mutable MIAB_Server "$MIAB_Server" baseurl="https://$MIAB_Server/admin/dns/custom/$fulldomain/txt" #Remove the challenge record - result="$(_miab_post "$txtvalue" "$baseurl" "" "DELETE" "" "$MIAB_Username" "$MIAB_Password")" + result="$(_miab_post "$txtvalue" "$baseurl" "DELETE" "$MIAB_Username" "$MIAB_Password")" _debug result "$result" @@ -119,11 +119,9 @@ dns_miab_rm() { _miab_post() { body="$1" _post_url="$2" - needbase64="$3" - httpmethod="$4" - _postContentType="$5" - username="$6" - password="$7" + httpmethod="$3" + username="$4" + password="$5" if [ -z "$httpmethod" ]; then httpmethod="POST" @@ -144,21 +142,7 @@ _miab_post() { fi _debug "_CURL" "$_CURL" - - if [ "$needbase64" ]; then - if [ "$_postContentType" ]; then - response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod --user "$username:$password" -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 --user "$username:$password" -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 --user "$username:$password" -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 --user "$username:$password" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")" - fi - fi - + response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod --user "$username:$password" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")" _ret="$?" if [ "$_ret" != "0" ]; then @@ -178,40 +162,12 @@ _miab_post() { _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 [ "$_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 - fi - + if [ "$httpmethod" = "POST" ]; then + 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")" 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 - 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 - fi - + 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 - + _ret="$?" if [ "$_ret" = "8" ]; then From f323ced4ca0d46c4119a8c4ac3ce67125edce149 Mon Sep 17 00:00:00 2001 From: Bill Gertz Date: Tue, 8 Oct 2019 18:24:14 +0200 Subject: [PATCH 06/11] Style issues and orphan _postContentType debug fix Fixed spacing and removed unneeded debug for _postContenetType --- dnsapi/dns_miab.sh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh index df2ca6e2..e2f4d593 100644 --- a/dnsapi/dns_miab.sh +++ b/dnsapi/dns_miab.sh @@ -91,9 +91,9 @@ dns_miab_rm() { fi #save the credentials to the account conf file. - _saveaccountconf_mutable MIAB_Username "$MIAB_Username" - _saveaccountconf_mutable MIAB_Password "$MIAB_Password" - _saveaccountconf_mutable MIAB_Server "$MIAB_Server" + _saveaccountconf_mutable MIAB_Username "$MIAB_Username" + _saveaccountconf_mutable MIAB_Password "$MIAB_Password" + _saveaccountconf_mutable MIAB_Server "$MIAB_Server" baseurl="https://$MIAB_Server/admin/dns/custom/$fulldomain/txt" @@ -130,8 +130,7 @@ _miab_post() { _debug $httpmethod _debug "_post_url" "$_post_url" _debug2 "body" "$body" - _debug2 "_postContentType" "$_postContentType" - + _inithttp if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then @@ -167,7 +166,7 @@ _miab_post() { 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 - + _ret="$?" if [ "$_ret" = "8" ]; then From f64b061a28bf06f7f1586048615cef090b9c09e9 Mon Sep 17 00:00:00 2001 From: Bill Gertz Date: Tue, 8 Oct 2019 18:46:35 +0200 Subject: [PATCH 07/11] Style issue Spaces on blank line on line 133. --- dnsapi/dns_miab.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh index e2f4d593..d17a1f75 100644 --- a/dnsapi/dns_miab.sh +++ b/dnsapi/dns_miab.sh @@ -130,7 +130,7 @@ _miab_post() { _debug $httpmethod _debug "_post_url" "$_post_url" _debug2 "body" "$body" - + _inithttp if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then From aa6112482d90e17b19127b71d5f12d097e13c485 Mon Sep 17 00:00:00 2001 From: Bill Gertz Date: Sun, 13 Oct 2019 19:56:04 +0200 Subject: [PATCH 08/11] Rewrite to conform to Dev guide Created _get_root() that tests the requested host is a subdomain to the domains hosted on MailinaBox (MIAB) DNS Server. Created common _miab_rest() used with dns_miab_add(), dns_miab_rm() and _get_root(). Also created barbaric _is_json() to test the response given by the MIAB Custom DNS API at least looks like a JSON file. We should add a hint to use _normalizeJson with JSON responses so _startswith, _endswith won't perplexingly fail. --- dnsapi/dns_miab.sh | 273 ++++++++++++++++++++++++--------------------- 1 file changed, 147 insertions(+), 126 deletions(-) diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh index d17a1f75..313e4eb8 100644 --- a/dnsapi/dns_miab.sh +++ b/dnsapi/dns_miab.sh @@ -6,186 +6,207 @@ # Darven Dissek 2018 # William Gertz 2019 # -# Thanks to Neil Pang for the code reused from acme.sh from HTTP-01 validation -# used to communicate with the MailintheBox Custom DNS API +# Thanks to Neil Pang and other developers here for code reused from acme.sh from DNS-01 +# used to communicate with the MailinaBox Custom DNS API # Report Bugs here: # https://github.com/billgertz/MIAB_dns_api (for dns_miab.sh) # https://github.com/Neilpang/acme.sh (for acme.sh) # ######## Public functions ##################### -#Usage: dns_miab_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +#Usage: dns_miab_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_miab_add() { fulldomain=$1 txtvalue=$2 - _info "Using miab" + _info "Using miab challange add" _debug fulldomain "$fulldomain" _debug txtvalue "$txtvalue" - MIAB_Username="${MIAB_Username:-$(_readaccountconf_mutable MIAB_Username)}" - MIAB_Password="${MIAB_Password:-$(_readaccountconf_mutable MIAB_Password)}" - MIAB_Server="${MIAB_Server:-$(_readaccountconf_mutable MIAB_Server)}" - - #debug log the environmental variables - _debug MIAB_Username "$MIAB_Username" - _debug MIAB_Password "$MIAB_Password" - _debug MIAB_Server "$MIAB_Server" - - if [ -z "$MIAB_Username" ] || [ -z "$MIAB_Password" ] || [ -z "$MIAB_Server" ]; then - MIAB_Username="" - MIAB_Password="" - MIAB_Server="" - _err "You didn't specify MIAB_Username or MIAB_Password or MIAB_Server." - _err "Please try again." + #retrieve MIAB environemt vars + if ! _retrieve_miab_env; then + return 1 + fi + + #check domain and seperate into doamin and host + if ! _get_root "$fulldomain"; then + _err "Cannot find any part of ${fulldomain} is hosted on ${MIAB_Server}" return 1 fi - #save the credentials to the account conf file. - _saveaccountconf_mutable MIAB_Username "$MIAB_Username" - _saveaccountconf_mutable MIAB_Password "$MIAB_Password" - _saveaccountconf_mutable MIAB_Server "$MIAB_Server" + _debug2 _sub_domain "$_sub_domain" + _debug2 _domain "$_domain" - baseurl="https://$MIAB_Server/admin/dns/custom/$fulldomain/txt" - - #Add the challenge record - result="$(_miab_post "$txtvalue" "$baseurl" "POST" "$MIAB_Username" "$MIAB_Password")" - - _debug result "$result" + #add the challenge record + _api_path="custom/${fulldomain}/txt" + _miab_rest "$txtvalue" "$_api_path" "POST" #check if result was good - if _contains "$result" "updated DNS"; then + if _contains "$response" "updated DNS"; then _info "Successfully created the txt record" return 0 else - _err "Error encountered during record addition" - _err "$result" + _err "Error encountered during record add" + _err "$response" return 1 fi } -#Usage: fulldomain txtvalue -#Remove the txt record after validation. +#Usage: dns_miab_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_miab_rm() { fulldomain=$1 txtvalue=$2 - _info "Using miab" + + _info "Using miab challage delete" _debug fulldomain "$fulldomain" _debug txtvalue "$txtvalue" - MIAB_Username="${MIAB_Username:-$(_readaccountconf_mutable MIAB_Username)}" - MIAB_Password="${MIAB_Password:-$(_readaccountconf_mutable MIAB_Password)}" - MIAB_Server="${MIAB_Server:-$(_readaccountconf_mutable MIAB_Server)}" + #retrieve MIAB environemt vars + if ! _retrieve_miab_env; then + return 1 + fi - #debug log the environmental variables - _debug MIAB_Username "$MIAB_Username" - _debug MIAB_Password "$MIAB_Password" - _debug MIAB_Server "$MIAB_Server" - - if [ -z "$MIAB_Username" ] || [ -z "$MIAB_Password" ] || [ -z "$MIAB_Server" ]; then - MIAB_Username="" - MIAB_Password="" - MIAB_Server="" - _err "You didn't specify MIAB_Username or MIAB_Password or MIAB_Server." - _err "Please try again." + #check domain and seperate into doamin and host + if ! _get_root "$fulldomain"; then + _err "Cannot find any part of ${fulldomain} is hosted on ${MIAB_Server}" return 1 fi - #save the credentials to the account conf file. - _saveaccountconf_mutable MIAB_Username "$MIAB_Username" - _saveaccountconf_mutable MIAB_Password "$MIAB_Password" - _saveaccountconf_mutable MIAB_Server "$MIAB_Server" - - baseurl="https://$MIAB_Server/admin/dns/custom/$fulldomain/txt" + _debug2 _sub_domain "$_sub_domain" + _debug2 _domain "$_domain" #Remove the challenge record - result="$(_miab_post "$txtvalue" "$baseurl" "DELETE" "$MIAB_Username" "$MIAB_Password")" - - _debug result "$result" + _api_path="custom/${fulldomain}/txt" + _miab_rest "$txtvalue" "$_api_path" "DELETE" #check if result was good - if _contains "$result" "updated DNS"; then - _info "Successfully created the txt record" + if _contains "$response" "updated DNS"; then + _info "Successfully removed the txt record" return 0 else - _err "Error encountered during record addition" - _err "$result" + _err "Error encountered during record remove" + _err "$response" return 1 fi } #################### Private functions below ################################## # -# post changes to MIAB dns (taken from acme.sh) -_miab_post() { - body="$1" - _post_url="$2" - httpmethod="$3" - username="$4" - password="$5" +#Usage: _get_root _acme-challenge.www.domain.com +#Returns: +# _sub_domain=_acme-challenge.www +# _domain=domain.com +_get_root() { + _passed_domain=$1 + _debug _passed_domain "$_passed_domain" + _i=2 + _p=1 - if [ -z "$httpmethod" ]; then - httpmethod="POST" + #get the zones hosed on MIAB server, must be a json stream + _miab_rest "" "zones" "GET" + + _info "_startswith test:$(_startswith "test" "t")" + _info "_endstest test:$(_endswith "test" "t")" + + if ! _is_json "$response"; then + _err "ERROR fetching domain list" + _err "$response" + return 1 fi - _debug $httpmethod - _debug "_post_url" "$_post_url" - _debug2 "body" "$body" + #cycle through the passed domain seperating out a test domain discarding + # the subdomain by marching thorugh the dots + while true; do + _test_domain=$(printf "%s" "$_passed_domain" | cut -d . -f ${_i}-100) + _debug _test_domain "$_test_domain" - _inithttp - - if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then - _CURL="$_ACME_CURL" - - if [ "$HTTPS_INSECURE" ]; then - _CURL="$_CURL --insecure " + if [ -z "$_test_domain" ]; then + return 1 fi - _debug "_CURL" "$_CURL" - response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod --user "$username:$password" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")" - _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")" - fi + #report found if the test domain is in the json response and + # report the subdomain + if _contains "$response" "\"$_test_domain\""; then + _sub_domain=$(printf "%s" "$_passed_domain" | cut -d . -f 1-${_p}) + _domain=${_test_domain} + return 0 fi - elif [ "$_ACME_WGET" ]; then - _WGET="$_ACME_WGET" + #cycle to the next dot in the passed domain + _p=${_i} + _i=$(_math "$_i" + 1) + done - if [ "$HTTPS_INSECURE" ]; then - _WGET="$_WGET --no-check-certificate " - fi - - _debug "_WGET" "$_WGET" - - if [ "$httpmethod" = "POST" ]; then - 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")" - 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 - - _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 - - _sed_i "s/^ *//g" "$HTTP_HEADER" - - else - _ret="$?" - _err "Neither curl nor wget was found, cannot do $httpmethod." - fi - - _debug "_ret" "$_ret" - printf "%s" "$response" - return $_ret + return 1 +} + +#Usage: _retrieve_miab_env +#Returns (from store or environment variables): +# MIAB_Username +# MIAB_Password +# MIAB_Server +#retrieve MIAB environment variables, report errors and quit if problems +_retrieve_miab_env() { + MIAB_Username="${MIAB_Username:-$(_readaccountconf_mutable MIAB_Username)}" + MIAB_Password="${MIAB_Password:-$(_readaccountconf_mutable MIAB_Password)}" + MIAB_Server="${MIAB_Server:-$(_readaccountconf_mutable MIAB_Server)}" + + #debug log the environmental variables + _debug MIAB_Username "$MIAB_Username" + _debug MIAB_Password "$MIAB_Password" + _debug MIAB_Server "$MIAB_Server" + + #check if MIAB environemt vars set and quit if not + if [ -z "$MIAB_Username" ] || [ -z "$MIAB_Password" ] || [ -z "$MIAB_Server" ]; then + _err "You didn't specify one or more of MIAB_Username, MIAB_Password or MIAB_Server." + _err "Please check these environment variables and try again." + return 1 + fi + + #save the credentials to the account conf file. + _saveaccountconf_mutable MIAB_Username "$MIAB_Username" + _saveaccountconf_mutable MIAB_Password "$MIAB_Password" + _saveaccountconf_mutable MIAB_Server "$MIAB_Server" +} + +#Useage: _miab_rest "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" "custom/_acme-challenge.www.domain.com/txt "POST" +#Returns: "updated DNS: domain.com" +#rest interface MIAB dns +_miab_rest() { + _data="$1" + _api_path="$2" + _httpmethod="$3" + + #encode username and password for url + _username="$(printf "%s" "$MIAB_Username" | _url_encode)" + _password="$(printf "%s" "$MIAB_Password" | _url_encode)" + _url="https://${_username}:${_password}@${MIAB_Server}/admin/dns/${_api_path}" + + _debug2 _data "$_data" + _debug _api_path "$_api_path" + _debug2 _url "$_url" + _debug _httpmethod "$_httpmethod" + + if [ "$_httpmethod" = "GET" ]; then + response="$(_get "$_url")" + else + response="$(_post "$_data" "$_url" "" "$_httpmethod")" + fi + + _retcode="$?" + + if [ "$_retcode" != "0" ]; then + _err "MAAB REST authentication failed on $_httpmethod" + return 1 + fi + + _debug response "$response" + return 0 +} + +#Usage: _is_json "\[\n "mydomain.com"\n]" +#Reurns "\[\n "mydomain.com"\n]" +#returns the string if it begins and ends with square braces +_is_json() { + _str="$(echo "$1" | _normalizeJson)" + echo "$_str" | grep '^\[.*\]$' >/dev/null 2>&1 } From 7ec52145e807fc15dfb6c1e501183f14b58f3d80 Mon Sep 17 00:00:00 2001 From: Bill Gertz Date: Sun, 13 Oct 2019 20:02:03 +0200 Subject: [PATCH 09/11] Space style changes. Local copy of shellcheck somehow missed these, odd. --- dnsapi/dns_miab.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh index 313e4eb8..7630a744 100644 --- a/dnsapi/dns_miab.sh +++ b/dnsapi/dns_miab.sh @@ -23,10 +23,10 @@ dns_miab_add() { _debug txtvalue "$txtvalue" #retrieve MIAB environemt vars - if ! _retrieve_miab_env; then - return 1 - fi - + if ! _retrieve_miab_env; then + return 1 + fi + #check domain and seperate into doamin and host if ! _get_root "$fulldomain"; then _err "Cannot find any part of ${fulldomain} is hosted on ${MIAB_Server}" @@ -61,9 +61,9 @@ dns_miab_rm() { _debug txtvalue "$txtvalue" #retrieve MIAB environemt vars - if ! _retrieve_miab_env; then - return 1 - fi + if ! _retrieve_miab_env; then + return 1 + fi #check domain and seperate into doamin and host if ! _get_root "$fulldomain"; then @@ -76,7 +76,7 @@ dns_miab_rm() { #Remove the challenge record _api_path="custom/${fulldomain}/txt" - _miab_rest "$txtvalue" "$_api_path" "DELETE" + _miab_rest "$txtvalue" "$_api_path" "DELETE" #check if result was good if _contains "$response" "updated DNS"; then From 9af85f5a7eedb7d3fd36a01834492e50e8c65138 Mon Sep 17 00:00:00 2001 From: Bill Gertz Date: Mon, 14 Oct 2019 00:01:25 +0200 Subject: [PATCH 10/11] Updated to use _H1 Authorization: Basic Updated to use suggested export _H1 env var to supply Authorization Basic credentials. This undocumented support for Basic Authorization, ContentType, etc. needs to be documented in DNSAPI Dev Guide. Removed two stray debugging lines. --- dnsapi/dns_miab.sh | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh index 7630a744..25a8ffc7 100644 --- a/dnsapi/dns_miab.sh +++ b/dnsapi/dns_miab.sh @@ -26,7 +26,7 @@ dns_miab_add() { if ! _retrieve_miab_env; then return 1 fi - + #check domain and seperate into doamin and host if ! _get_root "$fulldomain"; then _err "Cannot find any part of ${fulldomain} is hosted on ${MIAB_Server}" @@ -104,9 +104,6 @@ _get_root() { #get the zones hosed on MIAB server, must be a json stream _miab_rest "" "zones" "GET" - _info "_startswith test:$(_startswith "test" "t")" - _info "_endstest test:$(_endswith "test" "t")" - if ! _is_json "$response"; then _err "ERROR fetching domain list" _err "$response" @@ -176,14 +173,15 @@ _miab_rest() { _api_path="$2" _httpmethod="$3" - #encode username and password for url - _username="$(printf "%s" "$MIAB_Username" | _url_encode)" - _password="$(printf "%s" "$MIAB_Password" | _url_encode)" - _url="https://${_username}:${_password}@${MIAB_Server}/admin/dns/${_api_path}" + #encode username and password for basic authentication + _credentials="$(printf "%s" "$MIAB_Username:$MIAB_Password" | _base64)" + export _H1="Authorization: Basic $_credentials" + _url="https://${MIAB_Server}/admin/dns/${_api_path}" _debug2 _data "$_data" _debug _api_path "$_api_path" _debug2 _url "$_url" + _debug2 _credentails "$_credentials" _debug _httpmethod "$_httpmethod" if [ "$_httpmethod" = "GET" ]; then @@ -195,7 +193,7 @@ _miab_rest() { _retcode="$?" if [ "$_retcode" != "0" ]; then - _err "MAAB REST authentication failed on $_httpmethod" + _err "MIAB REST authentication failed on $_httpmethod" return 1 fi From 933d49b0b09cc886402c59e08de1651e8121d822 Mon Sep 17 00:00:00 2001 From: Bill Gertz Date: Mon, 14 Oct 2019 00:06:08 +0200 Subject: [PATCH 11/11] Style space change Extra space on empty line 27. --- dnsapi/dns_miab.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_miab.sh b/dnsapi/dns_miab.sh index 25a8ffc7..23ff6cee 100644 --- a/dnsapi/dns_miab.sh +++ b/dnsapi/dns_miab.sh @@ -26,7 +26,7 @@ dns_miab_add() { if ! _retrieve_miab_env; then return 1 fi - + #check domain and seperate into doamin and host if ! _get_root "$fulldomain"; then _err "Cannot find any part of ${fulldomain} is hosted on ${MIAB_Server}"