diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 32d97614..46fd8283 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -37,7 +37,7 @@ jobs: - name: "Read this: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test" run: | echo "Read this: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test" - if [ "${{github.actor}}" != "Neilpang" ]; then + if [ "${{github.repository_owner}}" != "acmesh-official" ]; then false fi diff --git a/acme.sh b/acme.sh index b536d742..b25619bf 100755 --- a/acme.sh +++ b/acme.sh @@ -1252,7 +1252,7 @@ _createcsr() { else domainlist="$(_idn "$domainlist")" _debug2 domainlist "$domainlist" - alt="$(_getIdType "$domain" | _upper_case):$domain" + alt="$(_getIdType "$domain" | _upper_case):$(_idn "$domain")" for dl in $(echo "$domainlist" | tr "," ' '); do alt="$alt,$(_getIdType "$dl" | _upper_case):$dl" done @@ -1831,8 +1831,6 @@ _inithttp() { } -_HTTP_MAX_RETRY=8 - # body url [needbase64] [POST|PUT|DELETE] [ContentType] _post() { body="$1" @@ -1840,33 +1838,6 @@ _post() { 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" @@ -1918,9 +1889,7 @@ _post_impl() { 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 + _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")" @@ -1976,9 +1945,7 @@ _post_impl() { _debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later." fi if [ "$_ret" != "0" ]; then - if [ -z "$displayError" ] || [ "$displayError" = "0" ]; then - _err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $_ret" - fi + _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 @@ -1992,38 +1959,13 @@ _post_impl() { # 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() { _debug GET url="$1" onlyheader="$2" t="$3" - displayError="$4" _debug url "$url" _debug "timeout=$t" - _debug "displayError" "$displayError" + _inithttp if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then @@ -2042,9 +1984,7 @@ _get_impl() { 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 + _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")" @@ -2070,9 +2010,7 @@ _get_impl() { _debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later." fi if [ "$ret" != "0" ]; then - if [ -z "$displayError" ] || [ "$displayError" = "0" ]; then - _err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $ret" - fi + _err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $ret" fi else ret=$? diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index 2ca7ab7d..416a4121 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -36,43 +36,51 @@ fritzbox_deploy() { fi fi - _fritzbox_username="${DEPLOY_FRITZBOX_USERNAME}" - _fritzbox_password="${DEPLOY_FRITZBOX_PASSWORD}" - _fritzbox_url="${DEPLOY_FRITZBOX_URL}" - - _debug _fritzbox_url "$_fritzbox_url" - _debug _fritzbox_username "$_fritzbox_username" - _secure_debug _fritzbox_password "$_fritzbox_password" - if [ -z "$_fritzbox_username" ]; then + # Clear traces of incorrectly stored values + _clearaccountconf DEPLOY_FRITZBOX_USERNAME + _clearaccountconf DEPLOY_FRITZBOX_PASSWORD + _clearaccountconf DEPLOY_FRITZBOX_URL + + # Read config from saved values or env + _getdeployconf DEPLOY_FRITZBOX_USERNAME + _getdeployconf DEPLOY_FRITZBOX_PASSWORD + _getdeployconf DEPLOY_FRITZBOX_URL + + _debug DEPLOY_FRITZBOX_URL "$DEPLOY_FRITZBOX_URL" + _debug DEPLOY_FRITZBOX_USERNAME "$DEPLOY_FRITZBOX_USERNAME" + _secure_debug DEPLOY_FRITZBOX_PASSWORD "$DEPLOY_FRITZBOX_PASSWORD" + + if [ -z "$DEPLOY_FRITZBOX_USERNAME" ]; then _err "FRITZ!Box username is not found, please define DEPLOY_FRITZBOX_USERNAME." return 1 fi - if [ -z "$_fritzbox_password" ]; then + if [ -z "$DEPLOY_FRITZBOX_PASSWORD" ]; then _err "FRITZ!Box password is not found, please define DEPLOY_FRITZBOX_PASSWORD." return 1 fi - if [ -z "$_fritzbox_url" ]; then + if [ -z "$DEPLOY_FRITZBOX_URL" ]; then _err "FRITZ!Box url is not found, please define DEPLOY_FRITZBOX_URL." return 1 fi - _saveaccountconf DEPLOY_FRITZBOX_USERNAME "${_fritzbox_username}" - _saveaccountconf DEPLOY_FRITZBOX_PASSWORD "${_fritzbox_password}" - _saveaccountconf DEPLOY_FRITZBOX_URL "${_fritzbox_url}" + # Save current values + _savedeployconf DEPLOY_FRITZBOX_USERNAME "$DEPLOY_FRITZBOX_USERNAME" + _savedeployconf DEPLOY_FRITZBOX_PASSWORD "$DEPLOY_FRITZBOX_PASSWORD" + _savedeployconf DEPLOY_FRITZBOX_URL "$DEPLOY_FRITZBOX_URL" # Do not check for a valid SSL certificate, because initially the cert is not valid, so it could not install the LE generated certificate export HTTPS_INSECURE=1 _info "Log in to the FRITZ!Box" - _fritzbox_challenge="$(_get "${_fritzbox_url}/login_sid.lua" | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" + _fritzbox_challenge="$(_get "${DEPLOY_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)" + _fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${DEPLOY_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)" + _fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${DEPLOY_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)" + _fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${DEPLOY_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>.*$//')" + _fritzbox_sid="$(_get "${DEPLOY_FRITZBOX_URL}/login_sid.lua?sid=0000000000000000&username=${DEPLOY_FRITZBOX_USERNAME}&response=${_fritzbox_challenge}-${_fritzbox_hash}" | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" if [ -z "${_fritzbox_sid}" ] || [ "${_fritzbox_sid}" = "0000000000000000" ]; then _err "Logging in to the FRITZ!Box failed. Please check username, password and URL." @@ -104,7 +112,7 @@ fritzbox_deploy() { _info "Upload certificate to the FRITZ!Box" export _H1="Content-type: multipart/form-data boundary=${_post_boundary}" - _post "$(cat "${_post_request}")" "${_fritzbox_url}/cgi-bin/firmwarecfg" | grep SSL + _post "$(cat "${_post_request}")" "${DEPLOY_FRITZBOX_URL}/cgi-bin/firmwarecfg" | grep SSL retval=$? if [ $retval = 0 ]; then diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 177b3fbe..66e28f93 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -2,8 +2,7 @@ # Here is a script to deploy cert to Synology DSM # -# it requires the jq and curl are in the $PATH and the following -# environment variables must be set: +# It requires following environment variables: # # SYNO_Username - Synology Username to login (must be an administrator) # SYNO_Password - Synology Password to login @@ -16,6 +15,12 @@ # SYNO_Hostname - defaults to localhost # SYNO_Port - defaults to 5000 # SYNO_DID - device ID to skip OTP - defaults to empty +# SYNO_TOTP_SECRET - TOTP secret to generate OTP - defaults to empty +# +# Dependencies: +# ------------- +# - jq and curl +# - oathtool (When using 2 Factor Authentication and SYNO_TOTP_SECRET is set) # #returns 0 means success, otherwise error. @@ -36,6 +41,7 @@ synology_dsm_deploy() { _getdeployconf SYNO_Password _getdeployconf SYNO_Create _getdeployconf SYNO_DID + _getdeployconf SYNO_TOTP_SECRET if [ -z "${SYNO_Username:-}" ] || [ -z "${SYNO_Password:-}" ]; then _err "SYNO_Username & SYNO_Password must be set" return 1 @@ -86,13 +92,18 @@ synology_dsm_deploy() { encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)" encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)" + otp_code="" + if [ -n "$SYNO_TOTP_SECRET" ]; then + otp_code="$(oathtool --base32 --totp "${SYNO_TOTP_SECRET}" 2>/dev/null)" + fi + if [ -n "$SYNO_DID" ]; then _H1="Cookie: did=$SYNO_DID" export _H1 _debug3 H1 "${_H1}" fi - 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") + response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&api=SYNO.API.Auth&version=$api_version&enable_syno_token=yes&otp_code=$otp_code" "$_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" @@ -100,7 +111,7 @@ synology_dsm_deploy() { if [ -z "$token" ]; then _err "Unable to authenticate to $SYNO_Hostname:$SYNO_Port using $SYNO_Scheme." _err "Check your username and password." - _err "If two-factor authentication is enabled for the user, you have to choose another user." + _err "If two-factor authentication is enabled for the user, set SYNO_TOTP_SECRET." return 1 fi sid=$(echo "$response" | grep "sid" | sed -n 's/.*"sid" *: *"\([^"]*\).*/\1/p') @@ -113,6 +124,7 @@ synology_dsm_deploy() { _savedeployconf SYNO_Username "$SYNO_Username" _savedeployconf SYNO_Password "$SYNO_Password" _savedeployconf SYNO_DID "$SYNO_DID" + _savedeployconf SYNO_TOTP_SECRET "$SYNO_TOTP_SECRET" _info "Getting certificates in Synology DSM" response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1&_sid=$sid" "$_base_url/webapi/entry.cgi") diff --git a/dnsapi/dns_simply.sh b/dnsapi/dns_simply.sh index e0e05017..437e5e5c 100644 --- a/dnsapi/dns_simply.sh +++ b/dnsapi/dns_simply.sh @@ -1,15 +1,15 @@ #!/usr/bin/env sh -# +# API-integration for Simply.com (https://www.simply.com) + #SIMPLY_AccountName="accountname" -# #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_SUCCESS_CODE='"status":200' ######## Public functions ##################### #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" @@ -51,7 +51,7 @@ dns_simply_rm() { _simply_save_config - _debug "First detect the root zone" + _debug "Find the DNS zone" if ! _get_root "$fulldomain"; then _err "invalid domain" @@ -77,8 +77,8 @@ 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) + record_data=$(echo "$record" | sed -n "s/.*\"data\":\"\([^\"]*\)\".*/\1/p") + record_type=$(echo "$record" | sed -n "s/.*\"type\":\"\([^\"]*\)\".*/\1/p") _debug2 record_data "$record_data" _debug2 record_type "$record_type" @@ -151,7 +151,7 @@ _simply_save_config() { _simply_get_all_records() { domain=$1 - if ! _simply_rest GET "my/products/$domain/dns/records"; then + if ! _simply_rest GET "my/products/$domain/dns/records/"; then return 1 fi @@ -169,7 +169,7 @@ _get_root() { return 1 fi - if ! _simply_rest GET "my/products/$h/dns"; then + if ! _simply_rest GET "my/products/$h/dns/"; then return 1 fi @@ -193,7 +193,7 @@ _simply_add_record() { data="{\"name\": \"$sub_domain\", \"type\":\"TXT\", \"data\": \"$txtval\", \"priority\":0, \"ttl\": 3600}" - if ! _simply_rest POST "my/products/$domain/dns/records" "$data"; then + if ! _simply_rest POST "my/products/$domain/dns/records/" "$data"; then _err "Adding record not successfull!" return 1 fi @@ -214,7 +214,7 @@ _simply_delete_record() { _debug record_id "Delete record with id $record_id" - if ! _simply_rest DELETE "my/products/$domain/dns/records/$record_id"; then + if ! _simply_rest DELETE "my/products/$domain/dns/records/$record_id/"; then _err "Deleting record not successfull!" return 1 fi @@ -250,6 +250,8 @@ _simply_rest() { return 1 fi + response="$(echo "$response" | _normalizeJson)" + _debug2 response "$response" if _contains "$response" "Invalid account authorization"; then