From f6da19ba835e52fba79caec2544aa89af0116c62 Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Tue, 29 Aug 2017 23:13:29 +0200 Subject: [PATCH 01/65] add deploy script for the AVM FRITZ!Box --- deploy/fritzbox.sh | 85 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 deploy/fritzbox.sh diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh new file mode 100644 index 0000000..1290dc7 --- /dev/null +++ b/deploy/fritzbox.sh @@ -0,0 +1,85 @@ +#!/usr/bin/env sh + +#Here is a script to deploy cert to an AVM FRITZ!Box router. + +#returns 0 means success, otherwise error. + +#DEPLOY_FRITZBOX_USERNAME="username" +#DEPLOY_FRITZBOX_PASSWORD="password" +#DEPLOY_FRITZBOX_URL="https://fritz.box" + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +fritzbox_deploy() { + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + + if ! _exists wget; then + _err "wget not found" + return 1 + fi + if ! exists iconv; then + _err "iconv not found" + return 1 + fi + + _fritzbox_username="${DEPLOY_FRITZBOX_USERNAME}" + _fritzbox_password="${DEPLOY_FRITZBOX_PASSWORD}" + _fritzbox_url="${DEPLOY_FRITZBOX_URL}" + + _debug _fritzbox_url "$_fritzbox_url" + _debug _fritzbox_usename "$_fritzbox_username" + _secure_debug _fritzbox_password "$_fritzbox_password" + if [ ! -z "$_fritzbox_username" ]; then + _err "FRITZ!Box username is not found, please define DEPLOY_FRITZBOX_USERNAME." + return 1 + fi + if [ ! -z "$_fritzbox_password" ]; then + _err "FRITZ!Box password is not found, please define DEPLOY_FRITZBOX_PASSWORD." + return 1 + fi + if [ ! -z "$_fritzbox_url" ]; then + _err "FRITZ!Box url is not found, please define DEPLOY_FRITZBOX_URL." + return 1 + fi + + _info "Log in in to the FRITZ!Box" + _fritzbox_challenge="$(wget -q -O - ${_fritzbox_url}/login_sid.lua | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" + _fritzbox_hash="$(echo -n ${_fritzbox_challenge}-${_fritzbox_password} | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" + _fritzbox_sid="$(wget -q -O - ${_fritzbox_url}/login_sid.lua?sid=0000000000000000\&username=${_frithbox_username}\&response=${_fritzbox_challenge}-${_fritzbox_hash} | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" + + _info "Generate form POST request" + _post_request="$(_mktemp)" + _post_boundary="---------------------------$(date +%Y%m%d%H%M%S)" + printf -- "--${_post_boundary}\r\n" >> "${_post_request}" + printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n${_fritzbox_sid}\r\n" >> "${_post_request}" + printf -- "--${_post_boundary}\r\n" >> "${_post_request}" + # _CERTPASSWORD_ is unset because Let's Encrypt certificates don't have a passwort. But if they ever do, here's the place to use it! + printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n${_CERTPASSWORD_}\r\n" >> "${_post_request}" + printf -- "--${_post_boundary}\r\n" >> "${_post_request}" + printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n" >> "${_post_request}" + printf "Content-Type: application/octet-stream\r\n\r\n" >> "${_post_request}" + cat "${_ckey}" >> "${_post_request}" + cat "${_cfullchain}" >> "${_post_request}" + printf "\r\n" >> "${_post_request}" + printf -- "--${_post_boundary}--" >> "${_post_request}" + + _info "Upload certificate to the FRITZ!Box" + wget -q -O - "${_fritzbox_url}/cgi-bin/firmwarecfg" --header="Content-type: multipart/form-data boundary=${_post_boundary}" --post-file "${_post_request}" + + _info "Upload successful" + rm "${_post_request}" + + return 0 +} + From 4bb488258d24159284fc55b5b81d7a146880f0fc Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Tue, 29 Aug 2017 23:53:41 +0200 Subject: [PATCH 02/65] - Bugfixes - Make sure the login actually worked - Less output --- deploy/fritzbox.sh | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index 1290dc7..c6a730c 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -28,7 +28,7 @@ fritzbox_deploy() { _err "wget not found" return 1 fi - if ! exists iconv; then + if ! _exists iconv; then _err "iconv not found" return 1 fi @@ -40,23 +40,32 @@ fritzbox_deploy() { _debug _fritzbox_url "$_fritzbox_url" _debug _fritzbox_usename "$_fritzbox_username" _secure_debug _fritzbox_password "$_fritzbox_password" - if [ ! -z "$_fritzbox_username" ]; then + if [ -z "$_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 "$_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 "$_fritzbox_url" ]; then _err "FRITZ!Box url is not found, please define DEPLOY_FRITZBOX_URL." return 1 fi - _info "Log in in to the FRITZ!Box" + _saveaccountconf DEPLOY_FRITZBOX_USERNAME "${_fritzbox_username}" + _saveaccountconf DEPLOY_FRITZBOX_PASSWORD "${_fritzbox_password}" + _saveaccountconf DEPLOY_FRITZBOX_URL "${_fritzbox_url}" + + _info "Log in to the FRITZ!Box" _fritzbox_challenge="$(wget -q -O - ${_fritzbox_url}/login_sid.lua | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" _fritzbox_hash="$(echo -n ${_fritzbox_challenge}-${_fritzbox_password} | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" - _fritzbox_sid="$(wget -q -O - ${_fritzbox_url}/login_sid.lua?sid=0000000000000000\&username=${_frithbox_username}\&response=${_fritzbox_challenge}-${_fritzbox_hash} | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" + _fritzbox_sid="$(wget -q -O - ${_fritzbox_url}/login_sid.lua?sid=0000000000000000\&username=${_fritzbox_username}\&response=${_fritzbox_challenge}-${_fritzbox_hash} | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" + + if [ -z "${_fritzbox_sid}" -o "${_fritzbox_sid}" = "0000000000000000" ] ; then + _err "Logging in to the FRITZ!Box failed. Please check username, password and URL." + return 1 + fi _info "Generate form POST request" _post_request="$(_mktemp)" @@ -65,6 +74,7 @@ fritzbox_deploy() { printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n${_fritzbox_sid}\r\n" >> "${_post_request}" printf -- "--${_post_boundary}\r\n" >> "${_post_request}" # _CERTPASSWORD_ is unset because Let's Encrypt certificates don't have a passwort. But if they ever do, here's the place to use it! + _CERTPASSWORD_= printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n${_CERTPASSWORD_}\r\n" >> "${_post_request}" printf -- "--${_post_boundary}\r\n" >> "${_post_request}" printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n" >> "${_post_request}" @@ -75,11 +85,10 @@ fritzbox_deploy() { printf -- "--${_post_boundary}--" >> "${_post_request}" _info "Upload certificate to the FRITZ!Box" - wget -q -O - "${_fritzbox_url}/cgi-bin/firmwarecfg" --header="Content-type: multipart/form-data boundary=${_post_boundary}" --post-file "${_post_request}" + wget -q -O - "${_fritzbox_url}/cgi-bin/firmwarecfg" --header="Content-type: multipart/form-data boundary=${_post_boundary}" --post-file "${_post_request}" | grep SSL _info "Upload successful" rm "${_post_request}" return 0 } - From d50281453d6bc704c0a647b523073f06b002ca34 Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Tue, 29 Aug 2017 23:57:24 +0200 Subject: [PATCH 03/65] Add --no-check-certificate option to wget, or else the initial deployment won't work because there isn't a valid certificate installed on the router yet. --- deploy/fritzbox.sh | 6 +-- deploy/fritzbox.sh~ | 94 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 deploy/fritzbox.sh~ diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index c6a730c..16c310b 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -58,9 +58,9 @@ fritzbox_deploy() { _saveaccountconf DEPLOY_FRITZBOX_URL "${_fritzbox_url}" _info "Log in to the FRITZ!Box" - _fritzbox_challenge="$(wget -q -O - ${_fritzbox_url}/login_sid.lua | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" + _fritzbox_challenge="$(wget --no-check-certificate -q -O - ${_fritzbox_url}/login_sid.lua | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" _fritzbox_hash="$(echo -n ${_fritzbox_challenge}-${_fritzbox_password} | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" - _fritzbox_sid="$(wget -q -O - ${_fritzbox_url}/login_sid.lua?sid=0000000000000000\&username=${_fritzbox_username}\&response=${_fritzbox_challenge}-${_fritzbox_hash} | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" + _fritzbox_sid="$(wget --no-check-certificate -q -O - ${_fritzbox_url}/login_sid.lua?sid=0000000000000000\&username=${_fritzbox_username}\&response=${_fritzbox_challenge}-${_fritzbox_hash} | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" if [ -z "${_fritzbox_sid}" -o "${_fritzbox_sid}" = "0000000000000000" ] ; then _err "Logging in to the FRITZ!Box failed. Please check username, password and URL." @@ -85,7 +85,7 @@ fritzbox_deploy() { printf -- "--${_post_boundary}--" >> "${_post_request}" _info "Upload certificate to the FRITZ!Box" - wget -q -O - "${_fritzbox_url}/cgi-bin/firmwarecfg" --header="Content-type: multipart/form-data boundary=${_post_boundary}" --post-file "${_post_request}" | grep SSL + wget --no-check-certificate -q -O - "${_fritzbox_url}/cgi-bin/firmwarecfg" --header="Content-type: multipart/form-data boundary=${_post_boundary}" --post-file "${_post_request}" | grep SSL _info "Upload successful" rm "${_post_request}" diff --git a/deploy/fritzbox.sh~ b/deploy/fritzbox.sh~ new file mode 100644 index 0000000..c6a730c --- /dev/null +++ b/deploy/fritzbox.sh~ @@ -0,0 +1,94 @@ +#!/usr/bin/env sh + +#Here is a script to deploy cert to an AVM FRITZ!Box router. + +#returns 0 means success, otherwise error. + +#DEPLOY_FRITZBOX_USERNAME="username" +#DEPLOY_FRITZBOX_PASSWORD="password" +#DEPLOY_FRITZBOX_URL="https://fritz.box" + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +fritzbox_deploy() { + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + + if ! _exists wget; then + _err "wget not found" + return 1 + fi + if ! _exists iconv; then + _err "iconv not found" + return 1 + fi + + _fritzbox_username="${DEPLOY_FRITZBOX_USERNAME}" + _fritzbox_password="${DEPLOY_FRITZBOX_PASSWORD}" + _fritzbox_url="${DEPLOY_FRITZBOX_URL}" + + _debug _fritzbox_url "$_fritzbox_url" + _debug _fritzbox_usename "$_fritzbox_username" + _secure_debug _fritzbox_password "$_fritzbox_password" + if [ -z "$_fritzbox_username" ]; then + _err "FRITZ!Box username is not found, please define DEPLOY_FRITZBOX_USERNAME." + return 1 + fi + if [ -z "$_fritzbox_password" ]; then + _err "FRITZ!Box password is not found, please define DEPLOY_FRITZBOX_PASSWORD." + return 1 + fi + if [ -z "$_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}" + + _info "Log in to the FRITZ!Box" + _fritzbox_challenge="$(wget -q -O - ${_fritzbox_url}/login_sid.lua | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" + _fritzbox_hash="$(echo -n ${_fritzbox_challenge}-${_fritzbox_password} | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" + _fritzbox_sid="$(wget -q -O - ${_fritzbox_url}/login_sid.lua?sid=0000000000000000\&username=${_fritzbox_username}\&response=${_fritzbox_challenge}-${_fritzbox_hash} | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" + + if [ -z "${_fritzbox_sid}" -o "${_fritzbox_sid}" = "0000000000000000" ] ; then + _err "Logging in to the FRITZ!Box failed. Please check username, password and URL." + return 1 + fi + + _info "Generate form POST request" + _post_request="$(_mktemp)" + _post_boundary="---------------------------$(date +%Y%m%d%H%M%S)" + printf -- "--${_post_boundary}\r\n" >> "${_post_request}" + printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n${_fritzbox_sid}\r\n" >> "${_post_request}" + printf -- "--${_post_boundary}\r\n" >> "${_post_request}" + # _CERTPASSWORD_ is unset because Let's Encrypt certificates don't have a passwort. But if they ever do, here's the place to use it! + _CERTPASSWORD_= + printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n${_CERTPASSWORD_}\r\n" >> "${_post_request}" + printf -- "--${_post_boundary}\r\n" >> "${_post_request}" + printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n" >> "${_post_request}" + printf "Content-Type: application/octet-stream\r\n\r\n" >> "${_post_request}" + cat "${_ckey}" >> "${_post_request}" + cat "${_cfullchain}" >> "${_post_request}" + printf "\r\n" >> "${_post_request}" + printf -- "--${_post_boundary}--" >> "${_post_request}" + + _info "Upload certificate to the FRITZ!Box" + wget -q -O - "${_fritzbox_url}/cgi-bin/firmwarecfg" --header="Content-type: multipart/form-data boundary=${_post_boundary}" --post-file "${_post_request}" | grep SSL + + _info "Upload successful" + rm "${_post_request}" + + return 0 +} From e6f81173a38c5768aae800acf058a2aea07f092e Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Tue, 29 Aug 2017 23:58:20 +0200 Subject: [PATCH 04/65] Delete auto-backup file --- deploy/fritzbox.sh~ | 94 --------------------------------------------- 1 file changed, 94 deletions(-) delete mode 100644 deploy/fritzbox.sh~ diff --git a/deploy/fritzbox.sh~ b/deploy/fritzbox.sh~ deleted file mode 100644 index c6a730c..0000000 --- a/deploy/fritzbox.sh~ +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env sh - -#Here is a script to deploy cert to an AVM FRITZ!Box router. - -#returns 0 means success, otherwise error. - -#DEPLOY_FRITZBOX_USERNAME="username" -#DEPLOY_FRITZBOX_PASSWORD="password" -#DEPLOY_FRITZBOX_URL="https://fritz.box" - -######## Public functions ##################### - -#domain keyfile certfile cafile fullchain -fritzbox_deploy() { - _cdomain="$1" - _ckey="$2" - _ccert="$3" - _cca="$4" - _cfullchain="$5" - - _debug _cdomain "$_cdomain" - _debug _ckey "$_ckey" - _debug _ccert "$_ccert" - _debug _cca "$_cca" - _debug _cfullchain "$_cfullchain" - - if ! _exists wget; then - _err "wget not found" - return 1 - fi - if ! _exists iconv; then - _err "iconv not found" - return 1 - fi - - _fritzbox_username="${DEPLOY_FRITZBOX_USERNAME}" - _fritzbox_password="${DEPLOY_FRITZBOX_PASSWORD}" - _fritzbox_url="${DEPLOY_FRITZBOX_URL}" - - _debug _fritzbox_url "$_fritzbox_url" - _debug _fritzbox_usename "$_fritzbox_username" - _secure_debug _fritzbox_password "$_fritzbox_password" - if [ -z "$_fritzbox_username" ]; then - _err "FRITZ!Box username is not found, please define DEPLOY_FRITZBOX_USERNAME." - return 1 - fi - if [ -z "$_fritzbox_password" ]; then - _err "FRITZ!Box password is not found, please define DEPLOY_FRITZBOX_PASSWORD." - return 1 - fi - if [ -z "$_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}" - - _info "Log in to the FRITZ!Box" - _fritzbox_challenge="$(wget -q -O - ${_fritzbox_url}/login_sid.lua | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" - _fritzbox_hash="$(echo -n ${_fritzbox_challenge}-${_fritzbox_password} | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" - _fritzbox_sid="$(wget -q -O - ${_fritzbox_url}/login_sid.lua?sid=0000000000000000\&username=${_fritzbox_username}\&response=${_fritzbox_challenge}-${_fritzbox_hash} | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" - - if [ -z "${_fritzbox_sid}" -o "${_fritzbox_sid}" = "0000000000000000" ] ; then - _err "Logging in to the FRITZ!Box failed. Please check username, password and URL." - return 1 - fi - - _info "Generate form POST request" - _post_request="$(_mktemp)" - _post_boundary="---------------------------$(date +%Y%m%d%H%M%S)" - printf -- "--${_post_boundary}\r\n" >> "${_post_request}" - printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n${_fritzbox_sid}\r\n" >> "${_post_request}" - printf -- "--${_post_boundary}\r\n" >> "${_post_request}" - # _CERTPASSWORD_ is unset because Let's Encrypt certificates don't have a passwort. But if they ever do, here's the place to use it! - _CERTPASSWORD_= - printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n${_CERTPASSWORD_}\r\n" >> "${_post_request}" - printf -- "--${_post_boundary}\r\n" >> "${_post_request}" - printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n" >> "${_post_request}" - printf "Content-Type: application/octet-stream\r\n\r\n" >> "${_post_request}" - cat "${_ckey}" >> "${_post_request}" - cat "${_cfullchain}" >> "${_post_request}" - printf "\r\n" >> "${_post_request}" - printf -- "--${_post_boundary}--" >> "${_post_request}" - - _info "Upload certificate to the FRITZ!Box" - wget -q -O - "${_fritzbox_url}/cgi-bin/firmwarecfg" --header="Content-type: multipart/form-data boundary=${_post_boundary}" --post-file "${_post_request}" | grep SSL - - _info "Upload successful" - rm "${_post_request}" - - return 0 -} From 412e4e6cf9ecbf26c4d9b9330c3dfef1ddc92e42 Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Wed, 30 Aug 2017 00:24:31 +0200 Subject: [PATCH 05/65] Add acknowledgement note --- deploy/fritzbox.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index 16c310b..804548c 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -8,6 +8,9 @@ #DEPLOY_FRITZBOX_PASSWORD="password" #DEPLOY_FRITZBOX_URL="https://fritz.box" +# Kudos to wikrie at Github for his FRITZ!Box update script: +# https://gist.github.com/wikrie/f1d5747a714e0a34d0582981f7cb4cfb + ######## Public functions ##################### #domain keyfile certfile cafile fullchain From b6d48b7a144cefeebd3db92f8a3cabcad05139c6 Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Wed, 30 Aug 2017 00:45:03 +0200 Subject: [PATCH 06/65] Update README.md for the deploy hooks. --- deploy/README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/deploy/README.md b/deploy/README.md index e026cad..d0f3d7f 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -93,8 +93,18 @@ If you are login as root, please specify the username to deploy cert to: export DEPLOY_CPANEL_USER=username acme.sh --deploy -d example.com --deploy-hook cpanel_uapi ``` +## 8. Deploy the cert to your FRITZ!Box router +You must specify the credentials that have administrative privileges on the FRITZ!Box in order to deploy the certificate, plus the URL of your FRITZ!Box, through the following environment variables: +```sh +$ export DEPLOY_FRITZBOX_USERNAME=my_username +$ export DEPLOY_FRITZBOX_PASSWORD=the_password +$ export DEPLOY_FRITZBOX_URL=https://fritzbox.example.com +``` +After the first deployment, these values will be stored in your $HOME/.acme.sh/account.conf. You may now deploy the certificate like this: - +```sh +acme.sh --deploy -d fritz.box --deploy-hook fritzbox +``` From 103fa959cb7346d6bbade60d4009df84f1726a21 Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Wed, 30 Aug 2017 00:47:31 +0200 Subject: [PATCH 07/65] Typo --- deploy/fritzbox.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index 804548c..cea84f5 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -41,7 +41,7 @@ fritzbox_deploy() { _fritzbox_url="${DEPLOY_FRITZBOX_URL}" _debug _fritzbox_url "$_fritzbox_url" - _debug _fritzbox_usename "$_fritzbox_username" + _debug _fritzbox_username "$_fritzbox_username" _secure_debug _fritzbox_password "$_fritzbox_password" if [ -z "$_fritzbox_username" ]; then _err "FRITZ!Box username is not found, please define DEPLOY_FRITZBOX_USERNAME." From a3a92ff1dfc283ffc80bfd2a3cb9527295a832e7 Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Thu, 31 Aug 2017 17:12:11 +0200 Subject: [PATCH 08/65] Fix formatting errors. --- deploy/fritzbox.sh | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index cea84f5..e2102ed 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -61,11 +61,11 @@ fritzbox_deploy() { _saveaccountconf DEPLOY_FRITZBOX_URL "${_fritzbox_url}" _info "Log in to the FRITZ!Box" - _fritzbox_challenge="$(wget --no-check-certificate -q -O - ${_fritzbox_url}/login_sid.lua | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" - _fritzbox_hash="$(echo -n ${_fritzbox_challenge}-${_fritzbox_password} | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" - _fritzbox_sid="$(wget --no-check-certificate -q -O - ${_fritzbox_url}/login_sid.lua?sid=0000000000000000\&username=${_fritzbox_username}\&response=${_fritzbox_challenge}-${_fritzbox_hash} | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" + _fritzbox_challenge="$(wget --no-check-certificate -q -O - "${_fritzbox_url}/login_sid.lua" | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" + _fritzbox_hash="$(echo -n "${_fritzbox_challenge}-${_fritzbox_password}" | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" + _fritzbox_sid="$(wget --no-check-certificate -q -O - "${_fritzbox_url}/login_sid.lua?sid=0000000000000000\&username=${_fritzbox_username}\&response=${_fritzbox_challenge}-${_fritzbox_hash}" | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" - if [ -z "${_fritzbox_sid}" -o "${_fritzbox_sid}" = "0000000000000000" ] ; then + if [ -z "${_fritzbox_sid}" ] || [ "${_fritzbox_sid}" = "0000000000000000" ]; then _err "Logging in to the FRITZ!Box failed. Please check username, password and URL." return 1 fi @@ -73,19 +73,24 @@ fritzbox_deploy() { _info "Generate form POST request" _post_request="$(_mktemp)" _post_boundary="---------------------------$(date +%Y%m%d%H%M%S)" - printf -- "--${_post_boundary}\r\n" >> "${_post_request}" - printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n${_fritzbox_sid}\r\n" >> "${_post_request}" - printf -- "--${_post_boundary}\r\n" >> "${_post_request}" + { + printf -- "--%s\r\n" "${_post_boundary}"; + printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n%s\r\n" "${_fritzbox_sid}"; + printf -- "--%s\r\n""${_post_boundary}"; + } >>"${_post_request}" # _CERTPASSWORD_ is unset because Let's Encrypt certificates don't have a passwort. But if they ever do, here's the place to use it! _CERTPASSWORD_= - printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n${_CERTPASSWORD_}\r\n" >> "${_post_request}" - printf -- "--${_post_boundary}\r\n" >> "${_post_request}" - printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n" >> "${_post_request}" - printf "Content-Type: application/octet-stream\r\n\r\n" >> "${_post_request}" - cat "${_ckey}" >> "${_post_request}" - cat "${_cfullchain}" >> "${_post_request}" - printf "\r\n" >> "${_post_request}" - printf -- "--${_post_boundary}--" >> "${_post_request}" + { + printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n%s\r\n" "${_CERTPASSWORD_}"; + printf -- "--%s\r\n" "${_post_boundary}"; + printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n"; + printf "Content-Type: application/octet-stream\r\n\r\n"; + } >>"${_post_request}" + cat "${_ckey}${_cfullchain}" >>"${_post_request}" + { + printf "\r\n"; + printf -- "--%s--" "${_post_boundary}"; + } >>"${_post_request}" _info "Upload certificate to the FRITZ!Box" wget --no-check-certificate -q -O - "${_fritzbox_url}/cgi-bin/firmwarecfg" --header="Content-type: multipart/form-data boundary=${_post_boundary}" --post-file "${_post_request}" | grep SSL From 6cb5377d73c2ad6a4c9e7adfc727b191f127910b Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Thu, 31 Aug 2017 17:25:08 +0200 Subject: [PATCH 09/65] Fix bugs and more/new formatting errors. --- deploy/fritzbox.sh | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index e2102ed..1fe28e8 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -63,7 +63,7 @@ fritzbox_deploy() { _info "Log in to the FRITZ!Box" _fritzbox_challenge="$(wget --no-check-certificate -q -O - "${_fritzbox_url}/login_sid.lua" | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" _fritzbox_hash="$(echo -n "${_fritzbox_challenge}-${_fritzbox_password}" | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" - _fritzbox_sid="$(wget --no-check-certificate -q -O - "${_fritzbox_url}/login_sid.lua?sid=0000000000000000\&username=${_fritzbox_username}\&response=${_fritzbox_challenge}-${_fritzbox_hash}" | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" + _fritzbox_sid="$(wget --no-check-certificate -q -O - "${_fritzbox_url}/login_sid.lua?sid=0000000000000000&username=${_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." @@ -74,22 +74,22 @@ fritzbox_deploy() { _post_request="$(_mktemp)" _post_boundary="---------------------------$(date +%Y%m%d%H%M%S)" { - printf -- "--%s\r\n" "${_post_boundary}"; - printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n%s\r\n" "${_fritzbox_sid}"; - printf -- "--%s\r\n""${_post_boundary}"; + printf -- "--%s\r\n" "${_post_boundary}" + printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n%s\r\n" "${_fritzbox_sid}" + printf -- "--%s\r\n" "${_post_boundary}" } >>"${_post_request}" # _CERTPASSWORD_ is unset because Let's Encrypt certificates don't have a passwort. But if they ever do, here's the place to use it! _CERTPASSWORD_= { - printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n%s\r\n" "${_CERTPASSWORD_}"; - printf -- "--%s\r\n" "${_post_boundary}"; - printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n"; - printf "Content-Type: application/octet-stream\r\n\r\n"; + printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n%s\r\n" "${_CERTPASSWORD_}" + printf -- "--%s\r\n" "${_post_boundary}" + printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n" + printf "Content-Type: application/octet-stream\r\n\r\n" } >>"${_post_request}" - cat "${_ckey}${_cfullchain}" >>"${_post_request}" + cat "${_ckey}" "${_cfullchain}" >>"${_post_request}" { - printf "\r\n"; - printf -- "--%s--" "${_post_boundary}"; + printf "\r\n" + printf -- "--%s--" "${_post_boundary}" } >>"${_post_request}" _info "Upload certificate to the FRITZ!Box" From a098167bdbd145ff3d522b33c4d18f99e8ff09ec Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Mon, 4 Sep 2017 14:07:10 +0200 Subject: [PATCH 10/65] Fix more formatting errors --- deploy/fritzbox.sh | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index 1fe28e8..c86b44a 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -62,7 +62,7 @@ fritzbox_deploy() { _info "Log in to the FRITZ!Box" _fritzbox_challenge="$(wget --no-check-certificate -q -O - "${_fritzbox_url}/login_sid.lua" | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" - _fritzbox_hash="$(echo -n "${_fritzbox_challenge}-${_fritzbox_password}" | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" + _fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" _fritzbox_sid="$(wget --no-check-certificate -q -O - "${_fritzbox_url}/login_sid.lua?sid=0000000000000000&username=${_fritzbox_username}&response=${_fritzbox_challenge}-${_fritzbox_hash}" | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" if [ -z "${_fritzbox_sid}" ] || [ "${_fritzbox_sid}" = "0000000000000000" ]; then @@ -73,14 +73,12 @@ fritzbox_deploy() { _info "Generate form POST request" _post_request="$(_mktemp)" _post_boundary="---------------------------$(date +%Y%m%d%H%M%S)" + # _CERTPASSWORD_ is unset because Let's Encrypt certificates don't have a password. But if they ever do, here's the place to use it! + _CERTPASSWORD_= { printf -- "--%s\r\n" "${_post_boundary}" printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n%s\r\n" "${_fritzbox_sid}" printf -- "--%s\r\n" "${_post_boundary}" - } >>"${_post_request}" - # _CERTPASSWORD_ is unset because Let's Encrypt certificates don't have a passwort. But if they ever do, here's the place to use it! - _CERTPASSWORD_= - { printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n%s\r\n" "${_CERTPASSWORD_}" printf -- "--%s\r\n" "${_post_boundary}" printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n" From bd8b1a2501a867a373772398b3687ac47341f0f5 Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Mon, 4 Sep 2017 14:27:22 +0200 Subject: [PATCH 11/65] Don't use wget directly, but instead use _get and _post. --- deploy/fritzbox.sh | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index c86b44a..e7d01a8 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -27,10 +27,6 @@ fritzbox_deploy() { _debug _cca "$_cca" _debug _cfullchain "$_cfullchain" - if ! _exists wget; then - _err "wget not found" - return 1 - fi if ! _exists iconv; then _err "iconv not found" return 1 @@ -60,10 +56,13 @@ fritzbox_deploy() { _saveaccountconf DEPLOY_FRITZBOX_PASSWORD "${_fritzbox_password}" _saveaccountconf DEPLOY_FRITZBOX_URL "${_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="$(wget --no-check-certificate -q -O - "${_fritzbox_url}/login_sid.lua" | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" + _fritzbox_challenge="$(_get "${_fritzbox_url}/login_sid.lua" | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" _fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" - _fritzbox_sid="$(wget --no-check-certificate -q -O - "${_fritzbox_url}/login_sid.lua?sid=0000000000000000&username=${_fritzbox_username}&response=${_fritzbox_challenge}-${_fritzbox_hash}" | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" + _fritzbox_sid="$(_get "${_fritzbox_url}/login_sid.lua?sid=0000000000000000&username=${_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." @@ -91,10 +90,17 @@ fritzbox_deploy() { } >>"${_post_request}" _info "Upload certificate to the FRITZ!Box" - wget --no-check-certificate -q -O - "${_fritzbox_url}/cgi-bin/firmwarecfg" --header="Content-type: multipart/form-data boundary=${_post_boundary}" --post-file "${_post_request}" | grep SSL - _info "Upload successful" + export _H1="Content-type: multipart/form-data boundary=${_post_boundary}" + _post "$(cat ${_post_request})" "${_fritzbox_url}/cgi-bin/firmwarecfg" | grep SSL + + retval=$? + if [ $retval = 0 ] ; then + _info "Upload successful" + else + _err "Upload failed" + fi rm "${_post_request}" - return 0 + return $retval } From 8ee5ede834f2493b9d0e3af9a251ccfbaf4156ec Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Mon, 4 Sep 2017 14:30:40 +0200 Subject: [PATCH 12/65] Fix more formatting errors --- deploy/fritzbox.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index e7d01a8..a6f6684 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -92,10 +92,10 @@ 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}")" "${_fritzbox_url}/cgi-bin/firmwarecfg" | grep SSL retval=$? - if [ $retval = 0 ] ; then + if [ $retval = 0 ]; then _info "Upload successful" else _err "Upload failed" From 72e1eb88d969dfb26935b1c8070db7685105d6b1 Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Mon, 4 Sep 2017 14:40:28 +0200 Subject: [PATCH 13/65] Don't use individual redirects, but do it all in one block. --- deploy/fritzbox.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index a6f6684..dbff368 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -82,9 +82,7 @@ fritzbox_deploy() { printf -- "--%s\r\n" "${_post_boundary}" printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n" printf "Content-Type: application/octet-stream\r\n\r\n" - } >>"${_post_request}" - cat "${_ckey}" "${_cfullchain}" >>"${_post_request}" - { + cat "${_ckey}" "${_cfullchain}" printf "\r\n" printf -- "--%s--" "${_post_boundary}" } >>"${_post_request}" From 1e30718df63555700444226ef056f132f8620a1c Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Mon, 4 Sep 2017 14:48:27 +0200 Subject: [PATCH 14/65] Try and work around shellcheck error SC2039: In POSIX sh, printf -%s-- is undefined. --- deploy/fritzbox.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index dbff368..943b198 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -75,16 +75,20 @@ fritzbox_deploy() { # _CERTPASSWORD_ is unset because Let's Encrypt certificates don't have a password. But if they ever do, here's the place to use it! _CERTPASSWORD_= { - printf -- "--%s\r\n" "${_post_boundary}" + printf -- "--" + printf -- "%s\r\n" "${_post_boundary}" printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n%s\r\n" "${_fritzbox_sid}" - printf -- "--%s\r\n" "${_post_boundary}" + printf -- "--" + printf -- "%s\r\n" "${_post_boundary}" printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n%s\r\n" "${_CERTPASSWORD_}" - printf -- "--%s\r\n" "${_post_boundary}" + printf -- "--" + printf -- "%s\r\n" "${_post_boundary}" printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n" printf "Content-Type: application/octet-stream\r\n\r\n" cat "${_ckey}" "${_cfullchain}" printf "\r\n" - printf -- "--%s--" "${_post_boundary}" + printf -- "--" + printf -- "%s--" "${_post_boundary}" } >>"${_post_request}" _info "Upload certificate to the FRITZ!Box" From 2fc0225bc98da5e0a7221c12ea13b20c9cf26ec2 Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Tue, 12 Sep 2017 11:35:21 +0200 Subject: [PATCH 15/65] Make command line example consistent with env variable example. --- deploy/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/README.md b/deploy/README.md index f76c667..af6fc5f 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -108,6 +108,6 @@ $ export DEPLOY_FRITZBOX_URL=https://fritzbox.example.com After the first deployment, these values will be stored in your $HOME/.acme.sh/account.conf. You may now deploy the certificate like this: ```sh -acme.sh --deploy -d fritz.box --deploy-hook fritzbox +acme.sh --deploy -d fritzbox.example.com --deploy-hook fritzbox ``` From 754a4a7c8bef3fcaa384be159e1744cdae0399bc Mon Sep 17 00:00:00 2001 From: sahsanu Date: Sat, 30 Sep 2017 20:12:53 +0200 Subject: [PATCH 16/65] Update dns_cloudns.sh Added code to save CLOUDNS_AUTH_ID and CLOUDNS_AUTH_PASSWORD on account.conf file so the id and password for cloudns can be reused. --- dnsapi/dns_cloudns.sh | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_cloudns.sh b/dnsapi/dns_cloudns.sh index f48a805..14403a7 100755 --- a/dnsapi/dns_cloudns.sh +++ b/dnsapi/dns_cloudns.sh @@ -96,6 +96,16 @@ _dns_cloudns_init_check() { return 0 fi + CLOUDNS_AUTH_ID="${CLOUDNS_AUTH_ID:-$(_readaccountconf_mutable CLOUDNS_AUTH_ID)}" + CLOUDNS_AUTH_PASSWORD="${CLOUDNS_AUTH_PASSWORD:-$(_readaccountconf_mutable CLOUDNS_AUTH_PASSWORD)}" + if [ -z "$CLOUDNS_AUTH_ID" ] || [ -z "$CLOUDNS_AUTH_PASSWORD" ]; then + CLOUDNS_AUTH_ID="" + CLOUDNS_AUTH_PASSWORD="" + _err "You don't specify cloudns api id and password yet." + _err "Please create you id and password and try again." + return 1 + fi + if [ -z "$CLOUDNS_AUTH_ID" ]; then _err "CLOUDNS_AUTH_ID is not configured" return 1 @@ -113,8 +123,12 @@ _dns_cloudns_init_check() { return 1 fi + #save the api id and password to the account conf file. + _saveaccountconf_mutable CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID" + _saveaccountconf_mutable CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD" + CLOUDNS_INIT_CHECK_COMPLETED=1 - + return 0 } From 6c7da215e7d364fb9d9af3274397c947269b966e Mon Sep 17 00:00:00 2001 From: sahsanu Date: Sun, 1 Oct 2017 10:06:38 +0200 Subject: [PATCH 17/65] Update dns_cloudns.sh --- dnsapi/dns_cloudns.sh | 238 ++++++++++++++++++++---------------------- 1 file changed, 112 insertions(+), 126 deletions(-) diff --git a/dnsapi/dns_cloudns.sh b/dnsapi/dns_cloudns.sh index 14403a7..2ad77ca 100755 --- a/dnsapi/dns_cloudns.sh +++ b/dnsapi/dns_cloudns.sh @@ -11,174 +11,160 @@ CLOUDNS_API="https://api.cloudns.net" #Usage: dns_cloudns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_cloudns_add() { - _info "Using cloudns" + _info "Using cloudns" - if ! _dns_cloudns_init_check; then - return 1 - fi + if ! _dns_cloudns_init_check; then + return 1 + fi - zone="$(_dns_cloudns_get_zone_name "$1")" - if [ -z "$zone" ]; then - _err "Missing DNS zone at ClouDNS. Please log into your control panel and create the required DNS zone for the initial setup." - return 1 - fi + zone="$(_dns_cloudns_get_zone_name "$1")" + if [ -z "$zone" ]; then + _err "Missing DNS zone at ClouDNS. Please log into your control panel and create the required DNS zone for the initial setup." + return 1 + fi - host="$(echo "$1" | sed "s/\.$zone\$//")" - record=$2 - record_id=$(_dns_cloudns_get_record_id "$zone" "$host") + host="$(echo "$1" | sed "s/\.$zone\$//")" + record=$2 + record_id=$(_dns_cloudns_get_record_id "$zone" "$host") - _debug zone "$zone" - _debug host "$host" - _debug record "$record" - _debug record_id "$record_id" + _debug zone "$zone" + _debug host "$host" + _debug record "$record" + _debug record_id "$record_id" - if [ -z "$record_id" ]; then - _info "Adding the TXT record for $1" - _dns_cloudns_http_api_call "dns/add-record.json" "domain-name=$zone&record-type=TXT&host=$host&record=$record&ttl=60" - if ! _contains "$response" "\"status\":\"Success\""; then - _err "Record cannot be added." - return 1 - fi - _info "Added." - else - _info "Updating the TXT record for $1" - _dns_cloudns_http_api_call "dns/mod-record.json" "domain-name=$zone&record-id=$record_id&record-type=TXT&host=$host&record=$record&ttl=60" - if ! _contains "$response" "\"status\":\"Success\""; then - _err "The TXT record for $1 cannot be updated." - return 1 - fi - _info "Updated." - fi + if [ -z "$record_id" ]; then + _info "Adding the TXT record for $1" + _dns_cloudns_http_api_call "dns/add-record.json" "domain-name=$zone&record-type=TXT&host=$host&record=$record&ttl=60" + if ! _contains "$response" "\"status\":\"Success\""; then + _err "Record cannot be added." + return 1 + fi + _info "Added." + else + _info "Updating the TXT record for $1" + _dns_cloudns_http_api_call "dns/mod-record.json" "domain-name=$zone&record-id=$record_id&record-type=TXT&host=$host&record=$record&ttl=60" + if ! _contains "$response" "\"status\":\"Success\""; then + _err "The TXT record for $1 cannot be updated." + return 1 + fi + _info "Updated." + fi - return 0 + return 0 } #Usage: dns_cloudns_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_cloudns_rm() { - _info "Using cloudns" + _info "Using cloudns" - if ! _dns_cloudns_init_check; then - return 1 - fi + if ! _dns_cloudns_init_check; then + return 1 + fi - if [ -z "$zone" ]; then - zone="$(_dns_cloudns_get_zone_name "$1")" - if [ -z "$zone" ]; then - _err "Missing DNS zone at ClouDNS. Please log into your control panel and create the required DNS zone for the initial setup." - return 1 - fi - fi + if [ -z "$zone" ]; then + zone="$(_dns_cloudns_get_zone_name "$1")" + if [ -z "$zone" ]; then + _err "Missing DNS zone at ClouDNS. Please log into your control panel and create the required DNS zone for the initial setup." + return 1 + fi + fi - host="$(echo "$1" | sed "s/\.$zone\$//")" - record=$2 - record_id=$(_dns_cloudns_get_record_id "$zone" "$host") + host="$(echo "$1" | sed "s/\.$zone\$//")" + record=$2 + record_id=$(_dns_cloudns_get_record_id "$zone" "$host") - _debug zone "$zone" - _debug host "$host" - _debug record "$record" - _debug record_id "$record_id" + _debug zone "$zone" + _debug host "$host" + _debug record "$record" + _debug record_id "$record_id" - if [ ! -z "$record_id" ]; then - _info "Deleting the TXT record for $1" - _dns_cloudns_http_api_call "dns/delete-record.json" "domain-name=$zone&record-id=$record_id" - if ! _contains "$response" "\"status\":\"Success\""; then - _err "The TXT record for $1 cannot be deleted." - return 1 - fi - _info "Deleted." - fi - return 0 + if [ ! -z "$record_id" ]; then + _info "Deleting the TXT record for $1" + _dns_cloudns_http_api_call "dns/delete-record.json" "domain-name=$zone&record-id=$record_id" + if ! _contains "$response" "\"status\":\"Success\""; then + _err "The TXT record for $1 cannot be deleted." + return 1 + fi + _info "Deleted." + fi + return 0 } #################### Private functions below ################################## _dns_cloudns_init_check() { - if [ ! -z "$CLOUDNS_INIT_CHECK_COMPLETED" ]; then - return 0 - fi + if [ ! -z "$CLOUDNS_INIT_CHECK_COMPLETED" ]; then + return 0 + fi - CLOUDNS_AUTH_ID="${CLOUDNS_AUTH_ID:-$(_readaccountconf_mutable CLOUDNS_AUTH_ID)}" - CLOUDNS_AUTH_PASSWORD="${CLOUDNS_AUTH_PASSWORD:-$(_readaccountconf_mutable CLOUDNS_AUTH_PASSWORD)}" - if [ -z "$CLOUDNS_AUTH_ID" ] || [ -z "$CLOUDNS_AUTH_PASSWORD" ]; then - CLOUDNS_AUTH_ID="" - CLOUDNS_AUTH_PASSWORD="" - _err "You don't specify cloudns api id and password yet." - _err "Please create you id and password and try again." - return 1 - fi + if [ -z "$CLOUDNS_AUTH_ID" ]; then + _err "CLOUDNS_AUTH_ID is not configured" + return 1 + fi - if [ -z "$CLOUDNS_AUTH_ID" ]; then - _err "CLOUDNS_AUTH_ID is not configured" - return 1 - fi + if [ -z "$CLOUDNS_AUTH_PASSWORD" ]; then + _err "CLOUDNS_AUTH_PASSWORD is not configured" + return 1 + fi - if [ -z "$CLOUDNS_AUTH_PASSWORD" ]; then - _err "CLOUDNS_AUTH_PASSWORD is not configured" - return 1 - fi + _dns_cloudns_http_api_call "dns/login.json" "" - _dns_cloudns_http_api_call "dns/login.json" "" + if ! _contains "$response" "\"status\":\"Success\""; then + _err "Invalid CLOUDNS_AUTH_ID or CLOUDNS_AUTH_PASSWORD. Please check your login credentials." + return 1 + fi - if ! _contains "$response" "\"status\":\"Success\""; then - _err "Invalid CLOUDNS_AUTH_ID or CLOUDNS_AUTH_PASSWORD. Please check your login credentials." - return 1 - fi + CLOUDNS_INIT_CHECK_COMPLETED=1 - #save the api id and password to the account conf file. - _saveaccountconf_mutable CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID" - _saveaccountconf_mutable CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD" - - CLOUDNS_INIT_CHECK_COMPLETED=1 - - return 0 + return 0 } _dns_cloudns_get_zone_name() { - i=2 - while true; do - zoneForCheck=$(printf "%s" "$1" | cut -d . -f $i-100) + i=2 + while true; do + zoneForCheck=$(printf "%s" "$1" | cut -d . -f $i-100) - if [ -z "$zoneForCheck" ]; then - return 1 - fi + if [ -z "$zoneForCheck" ]; then + return 1 + fi - _debug zoneForCheck "$zoneForCheck" + _debug zoneForCheck "$zoneForCheck" - _dns_cloudns_http_api_call "dns/get-zone-info.json" "domain-name=$zoneForCheck" + _dns_cloudns_http_api_call "dns/get-zone-info.json" "domain-name=$zoneForCheck" - if ! _contains "$response" "\"status\":\"Failed\""; then - echo "$zoneForCheck" - return 0 - fi + if ! _contains "$response" "\"status\":\"Failed\""; then + echo "$zoneForCheck" + return 0 + fi - i=$(_math "$i" + 1) - done - return 1 + i=$(_math "$i" + 1) + done + return 1 } _dns_cloudns_get_record_id() { - _dns_cloudns_http_api_call "dns/records.json" "domain-name=$1&host=$2&type=TXT" - if _contains "$response" "\"id\":"; then - echo "$response" | cut -d '"' -f 2 - return 0 - fi - return 1 + _dns_cloudns_http_api_call "dns/records.json" "domain-name=$1&host=$2&type=TXT" + if _contains "$response" "\"id\":"; then + echo "$response" | cut -d '"' -f 2 + return 0 + fi + return 1 } _dns_cloudns_http_api_call() { - method=$1 + method=$1 - _debug CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID" - _debug CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD" + _debug CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID" + _debug CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD" - if [ -z "$2" ]; then - data="auth-id=$CLOUDNS_AUTH_ID&auth-password=$CLOUDNS_AUTH_PASSWORD" - else - data="auth-id=$CLOUDNS_AUTH_ID&auth-password=$CLOUDNS_AUTH_PASSWORD&$2" - fi + if [ -z "$2" ]; then + data="auth-id=$CLOUDNS_AUTH_ID&auth-password=$CLOUDNS_AUTH_PASSWORD" + else + data="auth-id=$CLOUDNS_AUTH_ID&auth-password=$CLOUDNS_AUTH_PASSWORD&$2" + fi - response="$(_get "$CLOUDNS_API/$method?$data")" + response="$(_get "$CLOUDNS_API/$method?$data")" - _debug2 response "$response" + _debug2 response "$response" - return 0 + return 0 } From c73c33f94c4d5731ef1d9bee92a33ab71dea1f92 Mon Sep 17 00:00:00 2001 From: sahsanu Date: Sun, 1 Oct 2017 10:31:38 +0200 Subject: [PATCH 18/65] Update dns_cloudns.sh --- dnsapi/dns_cloudns.sh | 238 ++++++++++++++++++++++-------------------- 1 file changed, 126 insertions(+), 112 deletions(-) diff --git a/dnsapi/dns_cloudns.sh b/dnsapi/dns_cloudns.sh index 2ad77ca..b1861b2 100755 --- a/dnsapi/dns_cloudns.sh +++ b/dnsapi/dns_cloudns.sh @@ -11,160 +11,174 @@ CLOUDNS_API="https://api.cloudns.net" #Usage: dns_cloudns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_cloudns_add() { - _info "Using cloudns" + _info "Using cloudns" - if ! _dns_cloudns_init_check; then - return 1 - fi + if ! _dns_cloudns_init_check; then + return 1 + fi - zone="$(_dns_cloudns_get_zone_name "$1")" - if [ -z "$zone" ]; then - _err "Missing DNS zone at ClouDNS. Please log into your control panel and create the required DNS zone for the initial setup." - return 1 - fi + zone="$(_dns_cloudns_get_zone_name "$1")" + if [ -z "$zone" ]; then + _err "Missing DNS zone at ClouDNS. Please log into your control panel and create the required DNS zone for the initial setup." + return 1 + fi - host="$(echo "$1" | sed "s/\.$zone\$//")" - record=$2 - record_id=$(_dns_cloudns_get_record_id "$zone" "$host") + host="$(echo "$1" | sed "s/\.$zone\$//")" + record=$2 + record_id=$(_dns_cloudns_get_record_id "$zone" "$host") - _debug zone "$zone" - _debug host "$host" - _debug record "$record" - _debug record_id "$record_id" + _debug zone "$zone" + _debug host "$host" + _debug record "$record" + _debug record_id "$record_id" - if [ -z "$record_id" ]; then - _info "Adding the TXT record for $1" - _dns_cloudns_http_api_call "dns/add-record.json" "domain-name=$zone&record-type=TXT&host=$host&record=$record&ttl=60" - if ! _contains "$response" "\"status\":\"Success\""; then - _err "Record cannot be added." - return 1 - fi - _info "Added." - else - _info "Updating the TXT record for $1" - _dns_cloudns_http_api_call "dns/mod-record.json" "domain-name=$zone&record-id=$record_id&record-type=TXT&host=$host&record=$record&ttl=60" - if ! _contains "$response" "\"status\":\"Success\""; then - _err "The TXT record for $1 cannot be updated." - return 1 - fi - _info "Updated." - fi + if [ -z "$record_id" ]; then + _info "Adding the TXT record for $1" + _dns_cloudns_http_api_call "dns/add-record.json" "domain-name=$zone&record-type=TXT&host=$host&record=$record&ttl=60" + if ! _contains "$response" "\"status\":\"Success\""; then + _err "Record cannot be added." + return 1 + fi + _info "Added." + else + _info "Updating the TXT record for $1" + _dns_cloudns_http_api_call "dns/mod-record.json" "domain-name=$zone&record-id=$record_id&record-type=TXT&host=$host&record=$record&ttl=60" + if ! _contains "$response" "\"status\":\"Success\""; then + _err "The TXT record for $1 cannot be updated." + return 1 + fi + _info "Updated." + fi - return 0 + return 0 } #Usage: dns_cloudns_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_cloudns_rm() { - _info "Using cloudns" + _info "Using cloudns" - if ! _dns_cloudns_init_check; then - return 1 - fi + if ! _dns_cloudns_init_check; then + return 1 + fi - if [ -z "$zone" ]; then - zone="$(_dns_cloudns_get_zone_name "$1")" - if [ -z "$zone" ]; then - _err "Missing DNS zone at ClouDNS. Please log into your control panel and create the required DNS zone for the initial setup." - return 1 - fi - fi + if [ -z "$zone" ]; then + zone="$(_dns_cloudns_get_zone_name "$1")" + if [ -z "$zone" ]; then + _err "Missing DNS zone at ClouDNS. Please log into your control panel and create the required DNS zone for the initial setup." + return 1 + fi + fi - host="$(echo "$1" | sed "s/\.$zone\$//")" - record=$2 - record_id=$(_dns_cloudns_get_record_id "$zone" "$host") + host="$(echo "$1" | sed "s/\.$zone\$//")" + record=$2 + record_id=$(_dns_cloudns_get_record_id "$zone" "$host") - _debug zone "$zone" - _debug host "$host" - _debug record "$record" - _debug record_id "$record_id" + _debug zone "$zone" + _debug host "$host" + _debug record "$record" + _debug record_id "$record_id" - if [ ! -z "$record_id" ]; then - _info "Deleting the TXT record for $1" - _dns_cloudns_http_api_call "dns/delete-record.json" "domain-name=$zone&record-id=$record_id" - if ! _contains "$response" "\"status\":\"Success\""; then - _err "The TXT record for $1 cannot be deleted." - return 1 - fi - _info "Deleted." - fi - return 0 + if [ ! -z "$record_id" ]; then + _info "Deleting the TXT record for $1" + _dns_cloudns_http_api_call "dns/delete-record.json" "domain-name=$zone&record-id=$record_id" + if ! _contains "$response" "\"status\":\"Success\""; then + _err "The TXT record for $1 cannot be deleted." + return 1 + fi + _info "Deleted." + fi + return 0 } #################### Private functions below ################################## _dns_cloudns_init_check() { - if [ ! -z "$CLOUDNS_INIT_CHECK_COMPLETED" ]; then - return 0 - fi + if [ ! -z "$CLOUDNS_INIT_CHECK_COMPLETED" ]; then + return 0 + fi - if [ -z "$CLOUDNS_AUTH_ID" ]; then - _err "CLOUDNS_AUTH_ID is not configured" - return 1 - fi + CLOUDNS_AUTH_ID="${CLOUDNS_AUTH_ID:-$(_readaccountconf_mutable CLOUDNS_AUTH_ID)}" + CLOUDNS_AUTH_PASSWORD="${CLOUDNS_AUTH_PASSWORD:-$(_readaccountconf_mutable CLOUDNS_AUTH_PASSWORD)}" + if [ -z "$CLOUDNS_AUTH_ID" ] || [ -z "$CLOUDNS_AUTH_PASSWORD" ]; then + CLOUDNS_AUTH_ID="" + CLOUDNS_AUTH_PASSWORD="" + _err "You don't specify cloudns api id and password yet." + _err "Please create you id and password and try again." + return 1 + fi - if [ -z "$CLOUDNS_AUTH_PASSWORD" ]; then - _err "CLOUDNS_AUTH_PASSWORD is not configured" - return 1 - fi + if [ -z "$CLOUDNS_AUTH_ID" ]; then + _err "CLOUDNS_AUTH_ID is not configured" + return 1 + fi - _dns_cloudns_http_api_call "dns/login.json" "" + if [ -z "$CLOUDNS_AUTH_PASSWORD" ]; then + _err "CLOUDNS_AUTH_PASSWORD is not configured" + return 1 + fi - if ! _contains "$response" "\"status\":\"Success\""; then - _err "Invalid CLOUDNS_AUTH_ID or CLOUDNS_AUTH_PASSWORD. Please check your login credentials." - return 1 - fi + _dns_cloudns_http_api_call "dns/login.json" "" - CLOUDNS_INIT_CHECK_COMPLETED=1 + if ! _contains "$response" "\"status\":\"Success\""; then + _err "Invalid CLOUDNS_AUTH_ID or CLOUDNS_AUTH_PASSWORD. Please check your login credentials." + return 1 + fi - return 0 + #save the api id and password to the account conf file. + _saveaccountconf_mutable CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID" + _saveaccountconf_mutable CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD" + + CLOUDNS_INIT_CHECK_COMPLETED=1 + + return 0 } _dns_cloudns_get_zone_name() { - i=2 - while true; do - zoneForCheck=$(printf "%s" "$1" | cut -d . -f $i-100) + i=2 + while true; do + zoneForCheck=$(printf "%s" "$1" | cut -d . -f $i-100) - if [ -z "$zoneForCheck" ]; then - return 1 - fi + if [ -z "$zoneForCheck" ]; then + return 1 + fi - _debug zoneForCheck "$zoneForCheck" + _debug zoneForCheck "$zoneForCheck" - _dns_cloudns_http_api_call "dns/get-zone-info.json" "domain-name=$zoneForCheck" + _dns_cloudns_http_api_call "dns/get-zone-info.json" "domain-name=$zoneForCheck" - if ! _contains "$response" "\"status\":\"Failed\""; then - echo "$zoneForCheck" - return 0 - fi + if ! _contains "$response" "\"status\":\"Failed\""; then + echo "$zoneForCheck" + return 0 + fi - i=$(_math "$i" + 1) - done - return 1 + i=$(_math "$i" + 1) + done + return 1 } _dns_cloudns_get_record_id() { - _dns_cloudns_http_api_call "dns/records.json" "domain-name=$1&host=$2&type=TXT" - if _contains "$response" "\"id\":"; then - echo "$response" | cut -d '"' -f 2 - return 0 - fi - return 1 + _dns_cloudns_http_api_call "dns/records.json" "domain-name=$1&host=$2&type=TXT" + if _contains "$response" "\"id\":"; then + echo "$response" | cut -d '"' -f 2 + return 0 + fi + return 1 } _dns_cloudns_http_api_call() { - method=$1 + method=$1 - _debug CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID" - _debug CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD" + _debug CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID" + _debug CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD" - if [ -z "$2" ]; then - data="auth-id=$CLOUDNS_AUTH_ID&auth-password=$CLOUDNS_AUTH_PASSWORD" - else - data="auth-id=$CLOUDNS_AUTH_ID&auth-password=$CLOUDNS_AUTH_PASSWORD&$2" - fi + if [ -z "$2" ]; then + data="auth-id=$CLOUDNS_AUTH_ID&auth-password=$CLOUDNS_AUTH_PASSWORD" + else + data="auth-id=$CLOUDNS_AUTH_ID&auth-password=$CLOUDNS_AUTH_PASSWORD&$2" + fi - response="$(_get "$CLOUDNS_API/$method?$data")" + response="$(_get "$CLOUDNS_API/$method?$data")" - _debug2 response "$response" + _debug2 response "$response" - return 0 + return 0 } From 641a2895a6282472fe3c8d52e5289165bf8a3d7d Mon Sep 17 00:00:00 2001 From: hiska Date: Mon, 2 Oct 2017 08:32:36 +0900 Subject: [PATCH 19/65] Create strongswan.sh --- deploy/strongswan.sh | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 deploy/strongswan.sh diff --git a/deploy/strongswan.sh b/deploy/strongswan.sh new file mode 100644 index 0000000..7323278 --- /dev/null +++ b/deploy/strongswan.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env sh + +#Here is a sample custom api script. +#This file name is "myapi.sh" +#So, here must be a method myapi_deploy() +#Which will be called by acme.sh to deploy the cert +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +strongswan_deploy() { + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + + cat "$_ckey" >"/etc/ipsec.d/private/$(basename "$_ckey")" + cat "$_ccert" >"/etc/ipsec.d/certs/$(basename "$_ccert")" + cat "$_cca" >"/etc/ipsec.d/cacerts/$(basename "$_cca")" + cat "$_cfullchain" >"/etc/ipsec.d/cacerts/$(basename "$_cfullchain")" + + ipsec reload + + return 0 + +} From afe3283c53930c66017aadbb8e35d5f01b3c714e Mon Sep 17 00:00:00 2001 From: hiska Date: Mon, 2 Oct 2017 08:34:32 +0900 Subject: [PATCH 20/65] Update README.md --- deploy/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/deploy/README.md b/deploy/README.md index c80a567..3105357 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -97,6 +97,10 @@ acme.sh --deploy -d example.com --deploy-hook cpanel_uapi Please note, that the cpanel_uapi hook will deploy only the first domain when your certificate will automatically renew. Therefore you should issue a separete certificate for each domain. - +## 8. Deploy the cert to strongswan + +```sh +acme.sh --deploy -d ftp.example.com --deploy-hook strongswan +``` From 372f691fd69a191cb2d718ace2d6f6a16568514e Mon Sep 17 00:00:00 2001 From: hebbet Date: Mon, 2 Oct 2017 15:04:02 +0200 Subject: [PATCH 21/65] unify headlines unify headlines in deploy readme --- deploy/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/deploy/README.md b/deploy/README.md index af6fc5f..4e4a726 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -4,7 +4,7 @@ Before you can deploy your cert, you must [issue the cert first](https://github. Here are the scripts to deploy the certs/key to the server/services. -## 1. Deploy the certs to your cpanel host. +## 1. Deploy the certs to your cpanel host If you want to deploy using cpanel UAPI see 7. @@ -20,7 +20,7 @@ export DEPLOY_CPANEL_PASSWORD=PASSWORD acme.sh --deploy -d example.com --deploy-hook cpanel ``` -## 2. Deploy ssl cert on kong proxy engine based on api. +## 2. Deploy ssl cert on kong proxy engine based on api Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert). Currently supports Kong-v0.10.x. @@ -29,11 +29,11 @@ Currently supports Kong-v0.10.x. acme.sh --deploy -d ftp.example.com --deploy-hook kong ``` -## 3. Deploy the cert to remote server through SSH access. +## 3. Deploy the cert to remote server through SSH access (TODO) -## 4. Deploy the cert to local vsftpd server. +## 4. Deploy the cert to local vsftpd server ```sh acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd @@ -55,7 +55,7 @@ export DEPLOY_VSFTPD_RELOAD="/etc/init.d/vsftpd restart" acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd ``` -## 5. Deploy the cert to local exim4 server. +## 5. Deploy the cert to local exim4 server ```sh acme.sh --deploy -d ftp.example.com --deploy-hook exim4 From c924e7c537249a33713e8dc6691ae3311e0b7a23 Mon Sep 17 00:00:00 2001 From: hiska Date: Wed, 4 Oct 2017 06:44:02 +0900 Subject: [PATCH 22/65] remove "return 0" --- deploy/strongswan.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/deploy/strongswan.sh b/deploy/strongswan.sh index 7323278..2de18f8 100644 --- a/deploy/strongswan.sh +++ b/deploy/strongswan.sh @@ -29,6 +29,4 @@ strongswan_deploy() { ipsec reload - return 0 - } From ee56b9cd4e50da0ff36af392676074d3914f12d7 Mon Sep 17 00:00:00 2001 From: sahsanu Date: Sat, 7 Oct 2017 21:31:24 +0200 Subject: [PATCH 23/65] Update ClouDNS.net API doc Update ClouDNS.net API doc to show that CLOUDNS_AUTH_ID and CLOUDNS_AUTH_PASSWORD will be saved in ~/.acme.sh/account.conf --- dnsapi/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/dnsapi/README.md b/dnsapi/README.md index 34b3867..ce8bbfb 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -420,6 +420,7 @@ Ok, let's issue a cert now: ``` acme.sh --issue --dns dns_cloudns -d example.com -d www.example.com ``` +The `CLOUDNS_AUTH_ID` and `CLOUDNS_AUTH_PASSWORD` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. ## 22. Use Infoblox API From 5f6e3da766ef6ffcefca8d5ced3df4b2fcdd7a62 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 8 Oct 2017 19:45:50 +0800 Subject: [PATCH 24/65] fix https://github.com/Neilpang/acme.sh/issues/1062 change back to use openssl for tls mode. --- acme.sh | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index 3e63282..9b917f7 100755 --- a/acme.sh +++ b/acme.sh @@ -2054,7 +2054,12 @@ _starttlsserver() { return 1 fi - __S_OPENSSL="socat" + __S_OPENSSL="${ACME_OPENSSL_BIN:-openssl} s_server -www -cert $TLS_CERT -key $TLS_KEY " + if [ "$opaddr" ]; then + __S_OPENSSL="$__S_OPENSSL -accept $opaddr:$port" + else + __S_OPENSSL="$__S_OPENSSL -accept $port" + fi _debug Le_Listen_V4 "$Le_Listen_V4" _debug Le_Listen_V6 "$Le_Listen_V6" @@ -2065,9 +2070,12 @@ _starttlsserver() { fi _debug "$__S_OPENSSL" + if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then + $__S_OPENSSL -tlsextdebug & + else + $__S_OPENSSL >/dev/null 2>&1 & + fi - #todo listen address - $__S_OPENSSL openssl-listen:$port,cert=$TLS_CERT,key=$TLS_KEY,verify=0,reuseaddr,fork SYSTEM:"sleep 0.5; echo HTTP/1.1 200 OK'; echo ; echo $content; echo;" & serverproc="$!" sleep 1 _debug serverproc "$serverproc" From 872bfe4757a9593e1a3a6f8e9969ad465ef66beb Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 11 Oct 2017 20:34:56 +0800 Subject: [PATCH 25/65] fix for PR https://github.com/Neilpang/acme.sh/pull/1069 --- dnsapi/dns_aws.sh | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/dnsapi/dns_aws.sh b/dnsapi/dns_aws.sh index 4078257..5a71651 100755 --- a/dnsapi/dns_aws.sh +++ b/dnsapi/dns_aws.sh @@ -87,6 +87,7 @@ _get_root() { _debug "response" "$response" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug2 "Checking domain: $h" if [ -z "$h" ]; then if _contains "$response" "true" && _contains "$response" ""; then _debug "IsTruncated" @@ -102,23 +103,23 @@ _get_root() { fi fi #not valid + _err "Invalid domain" return 1 fi if _contains "$response" "$h."; then hostedzone="$(echo "$response" | sed 's//#&/g' | tr '#' '\n' | _egrep_o "[^<]*<.Id>$h.<.Name>.*false<.PrivateZone>.*<.HostedZone>")" _debug hostedzone "$hostedzone" - if [ -z "$hostedzone" ]; then - _err "Error, can not get hostedzone." + if [ "$hostedzone" ]; then + _domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o ".*<.Id>" | head -n 1 | _egrep_o ">.*<" | tr -d "<>") + if [ "$_domain_id" ]; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain=$h + return 0 + fi + _err "Can not find domain id: $h" return 1 fi - _domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o ".*<.Id>" | head -n 1 | _egrep_o ">.*<" | 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) From 352dd907ac0d90ed5cecf4a9553a59d25ca4ac3d Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 18 Oct 2017 20:27:09 +0800 Subject: [PATCH 26/65] fix https://github.com/Neilpang/acme.sh/issues/1074 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 9b917f7..d988eb0 100755 --- a/acme.sh +++ b/acme.sh @@ -3135,7 +3135,7 @@ _regAccount() { fi if [ "$code" = '202' ]; then _info "Update account tos info success." - + echo "$response" >"$ACCOUNT_JSON_PATH" CA_KEY_HASH="$(__calcAccountKeyHash)" _debug "Calc CA_KEY_HASH" "$CA_KEY_HASH" _savecaconf CA_KEY_HASH "$CA_KEY_HASH" From 7902d10a3aaeff25bd2225e5c2ffd1af1f8e834b Mon Sep 17 00:00:00 2001 From: max2711 <32955673+max2711@users.noreply.github.com> Date: Fri, 20 Oct 2017 14:22:20 +0200 Subject: [PATCH 27/65] remove unused crontab jobs --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index e85098e..97626ba 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ ADD ./ /install_acme.sh/ RUN cd /install_acme.sh && ([ -f /install_acme.sh/acme.sh ] && /install_acme.sh/acme.sh --install || curl https://get.acme.sh | sh) && rm -rf /install_acme.sh/ -RUN ln -s /root/.acme.sh/acme.sh /usr/local/bin/acme.sh && crontab -l | sed 's#> /dev/null##' | crontab - +RUN ln -s /root/.acme.sh/acme.sh /usr/local/bin/acme.sh && crontab -l | grep acme.sh | sed 's#> /dev/null##' | crontab - RUN for verb in help \ version \ From 4c99c0127b849a8db29151a10b78acb66f78ebdd Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 1 Nov 2017 10:14:44 +0800 Subject: [PATCH 28/65] add dev guide --- dnsapi/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/dnsapi/README.md b/dnsapi/README.md index ce8bbfb..cff59c7 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -618,6 +618,7 @@ acme.sh --issue --dns dns_myapi -d example.com -d www.example.com For more details, please check our sample script: [dns_myapi.sh](dns_myapi.sh) +See: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide # Use lexicon DNS API From 6e93ff8bcac9744ff451181b6feeb7269d2ce1a8 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 10 Nov 2017 23:01:29 +0800 Subject: [PATCH 29/65] fix https://github.com/Neilpang/acme.sh/issues/1106 --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index d988eb0..9c8d6d4 100755 --- a/acme.sh +++ b/acme.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -VER=2.7.4 +VER=2.7.5 PROJECT_NAME="acme.sh" @@ -3474,7 +3474,7 @@ issue() { token="$(printf "%s\n" "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')" _debug token "$token" - uri="$(printf "%s\n" "$entry" | _egrep_o '"uri":"[^"]*' | cut -d : -f 2,3 | tr -d '"')" + uri="$(printf "%s\n" "$entry" | _egrep_o '"uri":"[^"]*' | cut -d '"' -f 4)" _debug uri "$uri" keyauthorization="$token.$thumbprint" From f62457a24e2f286f309c245b09bd52631f8e00f9 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 13 Nov 2017 20:54:29 +0800 Subject: [PATCH 30/65] fix --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b45cc46..dda8eb1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ install: openssl version 2>&1 || true; $ACME_OPENSSL_BIN version 2>&1 || true; export PATH="$_old_path"; - else sudo apt-get install socat; + else sudo apt-get -y update && sudo apt-get install -y socat; fi script: From ceafe389afb406b92f77392fd7fe2005cb6b750f Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 26 Nov 2017 20:57:02 +0800 Subject: [PATCH 31/65] fix https://github.com/Neilpang/acme.sh/issues/1109 --- dnsapi/dns_freedns.sh | 77 ++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 45 deletions(-) diff --git a/dnsapi/dns_freedns.sh b/dnsapi/dns_freedns.sh index 53da411..ae77d06 100755 --- a/dnsapi/dns_freedns.sh +++ b/dnsapi/dns_freedns.sh @@ -53,6 +53,8 @@ dns_freedns_add() { i="$(_math "$i" - 1)" sub_domain="$(echo "$fulldomain" | cut -d. -f -"$i")" + _debug top_domain "$top_domain" + _debug sub_domain "$sub_domain" # Sometimes FreeDNS does not return the subdomain page but rather # returns a page regarding becoming a premium member. This usually # happens after a period of inactivity. Immediately trying again @@ -61,7 +63,6 @@ dns_freedns_add() { attempts=2 while [ "$attempts" -gt "0" ]; do attempts="$(_math "$attempts" - 1)" - htmlpage="$(_freedns_retrieve_subdomain_page "$FREEDNS_COOKIE")" if [ "$?" != "0" ]; then if [ "$using_cached_cookies" = "true" ]; then @@ -70,19 +71,11 @@ dns_freedns_add() { fi return 1 fi + _debug2 htmlpage "$htmlpage" + + subdomain_csv="$(echo "$htmlpage" | tr -d "\n\r" | _egrep_o '
' | sed 's//@/g' | tr '@' '\n' | grep edit.php | grep $top_domain)" + _debug2 subdomain_csv "$subdomain_csv" - # Now convert the tables in the HTML to CSV. This litte gem from - # http://stackoverflow.com/questions/1403087/how-can-i-convert-an-html-table-to-csv - subdomain_csv="$(echo "$htmlpage" \ - | grep -i -e ']*>/\n/Ig' \ - | sed 's/<\/\?\(TABLE\|TR\)[^>]*>//Ig' \ - | sed 's/^]*>\|<\/\?T[DH][^>]*>$//Ig' \ - | sed 's/<\/T[DH][^>]*>]*>/,/Ig' \ - | grep 'edit.php?' \ - | grep "$top_domain")" # The above beauty ends with striping out rows that do not have an # href to edit.php and do not have the top domain we are looking for. # So all we should be left with is CSV of table of subdomains we are @@ -90,30 +83,32 @@ dns_freedns_add() { # Now we have to read through this table and extract the data we need lines="$(echo "$subdomain_csv" | wc -l)" - nl=' -' i=0 found=0 while [ "$i" -lt "$lines" ]; do i="$(_math "$i" + 1)" - line="$(echo "$subdomain_csv" | cut -d "$nl" -f "$i")" - tmp="$(echo "$line" | cut -d ',' -f 1)" - if [ $found = 0 ] && _startswith "$tmp" "$top_domain"; then + line="$(echo "$subdomain_csv" | sed -n ${i}p)" + _debug2 line "$line" + if [ $found = 0 ] && _contains "$line" "$top_domain"; then # this line will contain DNSdomainid for the top_domain - DNSdomainid="$(echo "$line" | cut -d ',' -f 2 | sed 's/^.*domain_id=//;s/>.*//')" + DNSdomainid="$(echo "$line" | _egrep_o "edit_domain_id *= *.*>" | cut -d = -f 2 | cut -d '>' -f 1)" + _debug2 DNSdomainid "$DNSdomainid" found=1 else # lines contain DNS records for all subdomains - DNSname="$(echo "$line" | cut -d ',' -f 2 | sed 's/^[^>]*>//;s/<\/a>.*//')" - DNStype="$(echo "$line" | cut -d ',' -f 3)" + DNSname="$(echo "$line" | _egrep_o 'edit.php.*' | cut -d '>' -f 2 | cut -d '<' -f 1)" + _debug2 DNSname "$DNSname" + DNStype="$(echo "$line" | sed 's/' -f 2 | cut -d '<' -f 1)" + _debug2 DNStype "$DNStype" if [ "$DNSname" = "$fulldomain" ] && [ "$DNStype" = "TXT" ]; then - DNSdataid="$(echo "$line" | cut -d ',' -f 2 | sed 's/^.*data_id=//;s/>.*//')" + DNSdataid="$(echo "$line" | _egrep_o 'data_id=.*' | cut -d = -f 2 | cut -d '>' -f 1)" # Now get current value for the TXT record. This method may # not produce accurate results as the value field is truncated # on this webpage. To get full value we would need to load # another page. However we don't really need this so long as # there is only one TXT record for the acme challenge subdomain. - DNSvalue="$(echo "$line" | cut -d ',' -f 4 | sed 's/^[^"]*"//;s/".*//;s/<\/td>.*//')" + DNSvalue="$(echo "$line" | sed 's/' -f 2 | cut -d '<' -f 1)" + _debug2 DNSvalue "$DNSvalue" if [ $found != 0 ]; then break # we are breaking out of the loop at the first match of DNS name @@ -169,8 +164,7 @@ dns_freedns_add() { return 0 else # Delete the old TXT record (with the wrong value) - _freedns_delete_txt_record "$FREEDNS_COOKIE" "$DNSdataid" - if [ "$?" = "0" ]; then + if _freedns_delete_txt_record "$FREEDNS_COOKIE" "$DNSdataid"; then # And add in new TXT record with the value provided _freedns_add_txt_record "$FREEDNS_COOKIE" "$DNSdomainid" "$sub_domain" "$txtvalue" fi @@ -210,18 +204,9 @@ dns_freedns_rm() { return 1 fi - # Now convert the tables in the HTML to CSV. This litte gem from - # http://stackoverflow.com/questions/1403087/how-can-i-convert-an-html-table-to-csv - subdomain_csv="$(echo "$htmlpage" \ - | grep -i -e ']*>/\n/Ig' \ - | sed 's/<\/\?\(TABLE\|TR\)[^>]*>//Ig' \ - | sed 's/^]*>\|<\/\?T[DH][^>]*>$//Ig' \ - | sed 's/<\/T[DH][^>]*>]*>/,/Ig' \ - | grep 'edit.php?' \ - | grep "$fulldomain")" + subdomain_csv="$(echo "$htmlpage" | tr -d "\n\r" | _egrep_o '' | sed 's//@/g' | tr '@' '\n' | grep edit.php | grep $fulldomain)" + _debug2 subdomain_csv "$subdomain_csv" + # The above beauty ends with striping out rows that do not have an # href to edit.php and do not have the domain name we are looking for. # So all we should be left with is CSV of table of subdomains we are @@ -229,19 +214,21 @@ dns_freedns_rm() { # Now we have to read through this table and extract the data we need lines="$(echo "$subdomain_csv" | wc -l)" - nl=' -' i=0 found=0 while [ "$i" -lt "$lines" ]; do i="$(_math "$i" + 1)" - line="$(echo "$subdomain_csv" | cut -d "$nl" -f "$i")" - DNSname="$(echo "$line" | cut -d ',' -f 2 | sed 's/^[^>]*>//;s/<\/a>.*//')" - DNStype="$(echo "$line" | cut -d ',' -f 3)" + line="$(echo "$subdomain_csv" | sed -n ${i}p)" + _debug2 line "$line" + DNSname="$(echo "$line" | _egrep_o 'edit.php.*' | cut -d '>' -f 2 | cut -d '<' -f 1)" + _debug2 DNSname "$DNSname" + DNStype="$(echo "$line" | sed 's/' -f 2 | cut -d '<' -f 1)" + _debug2 DNStype "$DNStype" if [ "$DNSname" = "$fulldomain" ] && [ "$DNStype" = "TXT" ]; then - DNSdataid="$(echo "$line" | cut -d ',' -f 2 | sed 's/^.*data_id=//;s/>.*//')" - DNSvalue="$(echo "$line" | cut -d ',' -f 4 | sed 's/^[^"]*"//;s/".*//;s/<\/td>.*//')" - _debug "DNSvalue: $DNSvalue" + DNSdataid="$(echo "$line" | _egrep_o 'data_id=.*' | cut -d = -f 2 | cut -d '>' -f 1)" + _debug2 DNSdataid "$DNSdataid" + DNSvalue="$(echo "$line" | sed 's/' -f 2 | cut -d '<' -f 1)" + _debug2 DNSvalue "$DNSvalue" # if [ "$DNSvalue" = "$txtvalue" ]; then # Testing value match fails. Website is truncating the value # field. So for now we will assume that there is only one TXT From b615cce92d69c0de937a15538ef764a21fda33b5 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 2 Dec 2017 19:54:33 +0800 Subject: [PATCH 32/65] fix https://github.com/Neilpang/acme.sh/issues/1127 --- Dockerfile | 2 +- acme.sh | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 97626ba..b286673 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine +FROM alpine:3.6 RUN apk update -f \ && apk --no-cache add -f \ diff --git a/acme.sh b/acme.sh index 9c8d6d4..98f4067 100755 --- a/acme.sh +++ b/acme.sh @@ -463,8 +463,7 @@ if _exists xargs && [ "$(printf %s '\\x41' | xargs printf)" = 'A' ]; then fi _h2b() { - if _exists xxd; then - xxd -r -p + if _exists xxd && xxd -r -p 2>/dev/null; then return fi From 529cbc037900506969e996e98903d7e60b211751 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 3 Dec 2017 12:51:51 +0800 Subject: [PATCH 33/65] run ci in docker --- .travis.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index dda8eb1..ab5632d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,14 @@ language: shell sudo: required +dist: trusty os: - linux - osx +services: + - docker + env: global: - SHFMT_URL=https://github.com/mvdan/sh/releases/download/v0.4.0/shfmt_v0.4.0_linux_amd64 @@ -30,7 +34,6 @@ install: openssl version 2>&1 || true; $ACME_OPENSSL_BIN version 2>&1 || true; export PATH="$_old_path"; - else sudo apt-get -y update && sudo apt-get install -y socat; fi script: @@ -44,7 +47,7 @@ script: - if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck -e SC2181 **/*.sh && echo "shellcheck OK" ; fi - cd .. - git clone https://github.com/Neilpang/acmetest.git && cp -r acme.sh acmetest/ && cd acmetest - - if [ "$TRAVIS_OS_NAME" = "linux" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ./letest.sh ; fi + - if [ "$TRAVIS_OS_NAME" = "linux" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ./rundocker.sh testplat ubuntu:latest ; fi - if [ "$TRAVIS_OS_NAME" = "osx" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ACME_OPENSSL_BIN="$ACME_OPENSSL_BIN" ./letest.sh ; fi From dcf8457f4d4b6d80236557fbc77ecd7060f56ec0 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 3 Dec 2017 13:16:37 +0800 Subject: [PATCH 34/65] fix format --- dnsapi/dns_freedns.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_freedns.sh b/dnsapi/dns_freedns.sh index ae77d06..afd8b79 100755 --- a/dnsapi/dns_freedns.sh +++ b/dnsapi/dns_freedns.sh @@ -73,7 +73,7 @@ dns_freedns_add() { fi _debug2 htmlpage "$htmlpage" - subdomain_csv="$(echo "$htmlpage" | tr -d "\n\r" | _egrep_o '' | sed 's//@/g' | tr '@' '\n' | grep edit.php | grep $top_domain)" + subdomain_csv="$(echo "$htmlpage" | tr -d "\n\r" | _egrep_o '' | sed 's//@/g' | tr '@' '\n' | grep edit.php | grep "$top_domain")" _debug2 subdomain_csv "$subdomain_csv" # The above beauty ends with striping out rows that do not have an @@ -87,7 +87,7 @@ dns_freedns_add() { found=0 while [ "$i" -lt "$lines" ]; do i="$(_math "$i" + 1)" - line="$(echo "$subdomain_csv" | sed -n ${i}p)" + line="$(echo "$subdomain_csv" | sed -n "${i}p")" _debug2 line "$line" if [ $found = 0 ] && _contains "$line" "$top_domain"; then # this line will contain DNSdomainid for the top_domain @@ -204,7 +204,7 @@ dns_freedns_rm() { return 1 fi - subdomain_csv="$(echo "$htmlpage" | tr -d "\n\r" | _egrep_o '' | sed 's//@/g' | tr '@' '\n' | grep edit.php | grep $fulldomain)" + subdomain_csv="$(echo "$htmlpage" | tr -d "\n\r" | _egrep_o '' | sed 's//@/g' | tr '@' '\n' | grep edit.php | grep "$fulldomain")" _debug2 subdomain_csv "$subdomain_csv" # The above beauty ends with striping out rows that do not have an @@ -218,7 +218,7 @@ dns_freedns_rm() { found=0 while [ "$i" -lt "$lines" ]; do i="$(_math "$i" + 1)" - line="$(echo "$subdomain_csv" | sed -n ${i}p)" + line="$(echo "$subdomain_csv" | sed -n "${i}p")" _debug2 line "$line" DNSname="$(echo "$line" | _egrep_o 'edit.php.*' | cut -d '>' -f 2 | cut -d '<' -f 1)" _debug2 DNSname "$DNSname" From 9eeebb147f9747a68e567ac40e202c51dc7aa4a3 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 3 Dec 2017 20:57:25 +0800 Subject: [PATCH 35/65] fix osx build --- .travis.yml | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index ab5632d..b6b5742 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,20 +22,10 @@ addons: install: - if [ "$TRAVIS_OS_NAME" = 'osx' ]; then - brew update && brew install openssl socat; - brew info openssl; - ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; - ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; - ln -s /usr/local/Cellar/openssl/1.0.2j/bin/openssl /usr/local/openssl; - _old_path="$PATH"; - echo "PATH=$PATH"; - export PATH=""; - export ACME_OPENSSL_BIN="/usr/local/openssl"; - openssl version 2>&1 || true; - $ACME_OPENSSL_BIN version 2>&1 || true; - export PATH="$_old_path"; + brew update && brew install socat; + export PATH="/usr/local/opt/openssl@1.1/bin:$PATH" ; fi - + script: - echo "NGROK_TOKEN=$(echo "$NGROK_TOKEN" | wc -c)" - command -V openssl && openssl version From 0ca3141088ead8a638c5067519e6c97216f699cf Mon Sep 17 00:00:00 2001 From: Aarup Date: Wed, 6 Dec 2017 11:50:54 +0100 Subject: [PATCH 36/65] Added support for UnoEuro api --- dnsapi/dns_unoeuro.sh | 194 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 dnsapi/dns_unoeuro.sh diff --git a/dnsapi/dns_unoeuro.sh b/dnsapi/dns_unoeuro.sh new file mode 100644 index 0000000..985b441 --- /dev/null +++ b/dnsapi/dns_unoeuro.sh @@ -0,0 +1,194 @@ +#!/usr/bin/env sh + +# +#Uno_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" +# +#Uno_User="UExxxxxx" + +Uno_Api="https://api.unoeuro.com/1/$Uno_User/$Uno_Key" + +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_unoeuro_add() { + fulldomain=$1 + txtvalue=$2 + + Uno_Key="${Uno_Key:-$(_readaccountconf_mutable Uno_Key)}" + Uno_User="${Uno_User:-$(_readaccountconf_mutable Uno_User)}" + if [ -z "$Uno_Key" ] || [ -z "$Uno_User" ]; then + Uno_Key="" + Uno_User="" + _err "You haven't specified a UnoEuro api key and account yet." + _err "Please create your key and try again." + return 1 + fi + + if ! _contains "$Uno_User" "UE"; then + _err "It seems that the Uno_User=$Uno_User is not a valid email address." + _err "Please check and retry." + return 1 + fi + + #save the api key and email to the account conf file. + _saveaccountconf_mutable Uno_Key "$Uno_Key" + _saveaccountconf_mutable Uno_User "$Uno_User" + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _domain_id "$_domain_id" + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting txt records" + _uno_rest GET "my/products/$h/dns/records" + + if ! _contains "$response" "\"status\": 200" >/dev/null; then + _err "Error" + return 1 + fi + + if ! _contains "$response" "$_sub_domain" >/dev/null; then + _info "Adding record" + if _uno_rest POST "my/products/$h/dns/records" "{\"name\":\"$fulldomain\",\"type\":\"TXT\",\"data\":\"$txtvalue\",\"ttl\":120}"; then + if _contains "$response" "\"status\": 200" >/dev/null; then + _info "Added, OK" + return 0 + else + _err "Add txt record error." + return 1 + fi + fi + _err "Add txt record error." + else + _info "Updating record" + record_id=$(echo "$response" | grep -B 1 "$_sub_domain" | head -1 | _egrep_o "[0-9]{1,}") + _debug "record_id" "$record_id" + + _uno_rest PUT "my/products/$h/dns/records/$record_id" "{\"name\":\"$fulldomain\",\"type\":\"TXT\",\"data\":\"$txtvalue\",\"ttl\":120}" + if _contains "$response" "\"status\": 200" >/dev/null; then + _info "Updated, OK" + return 0 + fi + _err "Update error" + return 1 + fi + +} + +#fulldomain txtvalue +dns_unoeuro_rm() { + fulldomain=$1 + txtvalue=$2 + + Uno_Key="${Uno_Key:-$(_readaccountconf_mutable Uno_Key)}" + Uno_User="${Uno_User:-$(_readaccountconf_mutable Uno_User)}" + if [ -z "$Uno_Key" ] || [ -z "$Uno_User" ]; then + Uno_Key="" + Uno_User="" + _err "You haven't specified a UnoEuro api key and account yet." + _err "Please create your key and try again." + return 1 + fi + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _domain_id "$_domain_id" + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting txt records" + _uno_rest GET "my/products/$h/dns/records" + + if ! _contains "$response" "\"status\": 200" >/dev/null; then + _err "Error" + return 1 + fi + + if ! _contains "$response" "$_sub_domain" >/dev/null; then + _info "Don't need to remove." + else + record_id=$(echo "$response" | grep -B 1 "$_sub_domain" | head -1 | _egrep_o "[0-9]{1,}") + _debug "record_id" "$record_id" + + if [ -z "$record_id" ]; then + _err "Can not get record id to remove." + return 1 + fi + + if ! _uno_rest DELETE "my/products/$h/dns/records/$record_id"; then + _err "Delete record error." + return 1 + fi + _contains "$response" "\"status\": 200" + 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 ! _uno_rest GET "my/products/$h/dns/records"; then + return 1 + fi + + if _contains "$response" "\"status\": 200" >/dev/null; then + _domain_id=$h + 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 +} + +_uno_rest() { + m=$1 + ep="$2" + data="$3" + _debug "$ep" + + #export _H1="X-Auth-Email: $Uno_User" + #export _H2="X-Auth-Key: $Uno_Key" + export _H1="Content-Type: application/json" + + if [ "$m" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$Uno_Api/$ep" "" "$m")" + else + response="$(_get "$Uno_Api/$ep")" + fi + + if [ "$?" != "0" ]; then + _err "error $ep" + return 1 + fi + _debug2 response "$response" + return 0 +} From 70702e41e994ce98dac23b06bf59e2bbcdf4f560 Mon Sep 17 00:00:00 2001 From: Aarup Date: Wed, 6 Dec 2017 11:55:29 +0100 Subject: [PATCH 37/65] Use _head_n --- dnsapi/dns_unoeuro.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_unoeuro.sh b/dnsapi/dns_unoeuro.sh index 985b441..4774187 100644 --- a/dnsapi/dns_unoeuro.sh +++ b/dnsapi/dns_unoeuro.sh @@ -65,7 +65,7 @@ dns_unoeuro_add() { _err "Add txt record error." else _info "Updating record" - record_id=$(echo "$response" | grep -B 1 "$_sub_domain" | head -1 | _egrep_o "[0-9]{1,}") + record_id=$(echo "$response" | grep -B 1 "$_sub_domain" | _head_n -1 | _egrep_o "[0-9]{1,}") _debug "record_id" "$record_id" _uno_rest PUT "my/products/$h/dns/records/$record_id" "{\"name\":\"$fulldomain\",\"type\":\"TXT\",\"data\":\"$txtvalue\",\"ttl\":120}" @@ -114,7 +114,7 @@ dns_unoeuro_rm() { if ! _contains "$response" "$_sub_domain" >/dev/null; then _info "Don't need to remove." else - record_id=$(echo "$response" | grep -B 1 "$_sub_domain" | head -1 | _egrep_o "[0-9]{1,}") + record_id=$(echo "$response" | grep -B 1 "$_sub_domain" | _head_n -1 | _egrep_o "[0-9]{1,}") _debug "record_id" "$record_id" if [ -z "$record_id" ]; then From 78712245f70800f4bd4875732271b9e96af1c4f9 Mon Sep 17 00:00:00 2001 From: Aarup Date: Wed, 6 Dec 2017 12:13:40 +0100 Subject: [PATCH 38/65] Add UnoEuro to README --- README.md | 1 + dnsapi/README.md | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/README.md b/README.md index 7d4353c..9e64e61 100644 --- a/README.md +++ b/README.md @@ -339,6 +339,7 @@ You don't have to do anything manually! 1. Dyn Managed DNS API 1. Yandex PDD API (https://pdd.yandex.ru) 1. Hurricane Electric DNS service (https://dns.he.net) +1. UnoEuro API (https://www.unoeuro.com/) And: diff --git a/dnsapi/README.md b/dnsapi/README.md index cff59c7..5fdcd84 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -602,6 +602,22 @@ The `HE_Username` and `HE_Password` settings will be saved in `~/.acme.sh/accoun Please report any issues to https://github.com/angel333/acme.sh or to . +## 32. Use UnoEuro API to automatically issue cert + +First you need to login to your UnoEuro account to get your API key. + +``` +export Uno_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" +export Uno_User="UExxxxxx" +``` + +Ok, let's issue a cert now: +``` +acme.sh --issue --dns dns_unoeuro -d example.com -d www.example.com +``` + +The `Uno_Key` and `Uno_User` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. + # Use custom API If your API is not supported yet, you can write your own DNS API. From 657334fb67e25b5503d02fc9abba2f5a2dbca410 Mon Sep 17 00:00:00 2001 From: speedmann Date: Thu, 7 Dec 2017 11:47:01 +0100 Subject: [PATCH 39/65] Add support for inwx.de API --- README.md | 1 + dnsapi/README.md | 17 +++ dnsapi/dns_inwx.sh | 365 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 383 insertions(+) create mode 100755 dnsapi/dns_inwx.sh diff --git a/README.md b/README.md index 7d4353c..e8f9464 100644 --- a/README.md +++ b/README.md @@ -339,6 +339,7 @@ You don't have to do anything manually! 1. Dyn Managed DNS API 1. Yandex PDD API (https://pdd.yandex.ru) 1. Hurricane Electric DNS service (https://dns.he.net) +1. INWX (https://www.inwx.de/) And: diff --git a/dnsapi/README.md b/dnsapi/README.md index cff59c7..768f69a 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -602,6 +602,23 @@ The `HE_Username` and `HE_Password` settings will be saved in `~/.acme.sh/accoun Please report any issues to https://github.com/angel333/acme.sh or to . +## 31. Use INWX + +INWX offers an xmlrpc api with your standard login credentials, set them like so: + +``` +export INWX_User="yourusername" +export INWX_Password="password" +``` + +Then you can issue your certificates with: + +``` +acme.sh --issue --dns dns_inwx -d example.com -d www.example.com +``` + +The `INWX_User` and `INWX_Password` settings will be saved in `~/.acme.sh/account.conf` and will be reused when needed. + # Use custom API If your API is not supported yet, you can write your own DNS API. diff --git a/dnsapi/dns_inwx.sh b/dnsapi/dns_inwx.sh new file mode 100755 index 0000000..db5b18c --- /dev/null +++ b/dnsapi/dns_inwx.sh @@ -0,0 +1,365 @@ +#!/usr/local/bin/bash + +# +#INWX_User="username" +# +#INWX_Password="password" + +INWX_Api="https://api.domrobot.com/xmlrpc/" + +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_inwx_add() { + fulldomain=$1 + txtvalue=$2 + + INWX_User="${INWX_User:-$(_readaccountconf_mutable INWX_User)}" + INWX_Password="${INWX_Password:-$(_readaccountconf_mutable INWX_Password)}" + if [ -z "$INWX_User" ] || [ -z "$INWX_Password" ]; then + INWX_User="" + INWX_Password="" + _err "You don't specify inwx user and password yet." + _err "Please create you key and try again." + return 1 + fi + + #save the api key and email to the account conf file. + _saveaccountconf_mutable INWX_User "$INWX_User" + _saveaccountconf_mutable INWX_Password "$INWX_Password" + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting txt records" + + + printf -v xml_content ' + + nameserver.info + + + + + + domain + + %s + + + + type + + TXT + + + + name + + %s + + + + + + + ' $_domain $_sub_domain + response="$(_post "$xml_content" "$INWX_Api" "" "POST")" + + if ! printf "%s" "$response" | grep "Command completed successfully" > /dev/null; then + _err "Error could net get txt records" + return 1 + fi + + if ! printf "%s" "$response" | grep "count" -q; then + _info "Adding record" + _inwx_add_record $_domain $_sub_domain $txtvalue + else + _record_id=$(printf '%s' $response | sed -nE 's/.*(record){1}(.*)(id<\/name>)([0-9]+){1}.*/\4/p') + _info "Updating record" + _inwx_update_record $_record_id $txtvalue + fi + +} + +#fulldomain txtvalue +dns_inwx_rm() { + + fulldomain=$1 + txtvalue=$2 + + INWX_User="${INWX_User:-$(_readaccountconf_mutable INWX_User)}" + INWX_Password="${INWX_Password:-$(_readaccountconf_mutable INWX_Password)}" + if [ -z "$INWX_User" ] || [ -z "$INWX_Password" ]; then + INWX_User="" + INWX_Password="" + _err "You don't specify inwx user and password yet." + _err "Please create you key and try again." + return 1 + fi + + #save the api key and email to the account conf file. + _saveaccountconf_mutable INWX_User "$INWX_User" + _saveaccountconf_mutable INWX_Password "$INWX_Password" + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting txt records" + + + printf -v xml_content ' + + nameserver.info + + + + + + domain + + %s + + + + type + + TXT + + + + name + + %s + + + + + + + ' $_domain $_sub_domain + response="$(_post "$xml_content" "$INWX_Api" "" "POST")" + + if ! printf "%s" "$response" | grep "Command completed successfully" > /dev/null; then + _err "Error could not get txt records" + return 1 + fi + + if ! printf "%s" "$response" | grep "count" -q; then + _info "Do not need to delete record" + else + _record_id=$(printf '%s' $response | sed -nE 's/.*(record){1}(.*)(id<\/name>)([0-9]+){1}.*/\4/p') + _info "Deleting record" + _inwx_delete_record $_record_id + fi + + +} + +#################### Private functions below ################################## + +_inwx_login() { + + printf -v xml_content ' + + account.login + + + + + + user + + %s + + + + pass + + %s + + + + + + + ' $INWX_User $INWX_Password + + response="$(_post "$xml_content" "$INWX_Api" "" "POST")" + + printf "Cookie: %s" "$(grep "domrobot=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'domrobot=[^;]*;' | tr -d ';')" + +} + +_get_root() { + domain=$1 + _debug "get root" + + domain=$1 + i=2 + p=1 + + + export _H1=$(_inwx_login) + printf -v xml_content ' + + nameserver.list + ' + + response="$(_post "$xml_content" "$INWX_Api" "" "POST")" + 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" "$h"; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain="$h" + return 0 + fi + p=$i + i=$(_math "$i" + 1) + done + return 1 + +} + +_inwx_delete_record() { + record_id=$1 + printf -v xml_content ' + + nameserver.deleteRecord + + + + + + id + + %s + + + + + + + ' $record_id + + response="$(_post "$xml_content" "$INWX_Api" "" "POST")" + + if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then + _err "Error" + return 1 + fi + return 0 + + +} + +_inwx_update_record() { + record_id=$1 + txtval=$2 + printf -v xml_content ' + + nameserver.updateRecord + + + + + + content + + %s + + + + id + + %s + + + + + + + ' $txtval $record_id + + + response="$(_post "$xml_content" "$INWX_Api" "" "POST")" + + if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then + _err "Error" + return 1 + fi + return 0 + +} + +_inwx_add_record() { + + domain=$1 + sub_domain=$2 + txtval=$3 + + _debug domain: $domain + _debug value: $txtval + _debug subd: $sub_domain + + printf -v xml_content ' + + nameserver.createRecord + + + + + + domain + + %s + + + + type + + TXT + + + + content + + %s + + + + name + + %s + + + + + + + ' $domain $txtval $sub_domain + + response="$(_post "$xml_content" "$INWX_Api" "" "POST")" + + if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then + _err "Error" + return 1 + fi + return 0 +} From a8202d4b3780e04b3b68cc7196ee47871e63ee3d Mon Sep 17 00:00:00 2001 From: speedmann Date: Thu, 7 Dec 2017 12:05:03 +0100 Subject: [PATCH 40/65] Fix CI issues --- dnsapi/dns_inwx.sh | 64 +++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 37 deletions(-) diff --git a/dnsapi/dns_inwx.sh b/dnsapi/dns_inwx.sh index db5b18c..9e2302b 100755 --- a/dnsapi/dns_inwx.sh +++ b/dnsapi/dns_inwx.sh @@ -35,11 +35,9 @@ dns_inwx_add() { fi _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - _debug "Getting txt records" - - printf -v xml_content ' + printf -v xml_content ' nameserver.info @@ -68,21 +66,21 @@ dns_inwx_add() { - ' $_domain $_sub_domain + ' "$_domain" "$_sub_domain" response="$(_post "$xml_content" "$INWX_Api" "" "POST")" - if ! printf "%s" "$response" | grep "Command completed successfully" > /dev/null; then + if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then _err "Error could net get txt records" return 1 fi if ! printf "%s" "$response" | grep "count" -q; then _info "Adding record" - _inwx_add_record $_domain $_sub_domain $txtvalue + _inwx_add_record "$_domain" "$_sub_domain" "$txtvalue" else - _record_id=$(printf '%s' $response | sed -nE 's/.*(record){1}(.*)(id<\/name>)([0-9]+){1}.*/\4/p') + _record_id=$(printf '%s' "$response" | sed -nE 's/.*(record){1}(.*)(id<\/name>)([0-9]+){1}.*/\4/p') _info "Updating record" - _inwx_update_record $_record_id $txtvalue + _inwx_update_record "$_record_id" "$txtvalue" fi } @@ -117,8 +115,7 @@ dns_inwx_rm() { _debug "Getting txt records" - - printf -v xml_content ' + printf -v xml_content ' nameserver.info @@ -147,10 +144,10 @@ dns_inwx_rm() { - ' $_domain $_sub_domain + ' "$_domain" "$_sub_domain" response="$(_post "$xml_content" "$INWX_Api" "" "POST")" - if ! printf "%s" "$response" | grep "Command completed successfully" > /dev/null; then + if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then _err "Error could not get txt records" return 1 fi @@ -158,12 +155,11 @@ dns_inwx_rm() { if ! printf "%s" "$response" | grep "count" -q; then _info "Do not need to delete record" else - _record_id=$(printf '%s' $response | sed -nE 's/.*(record){1}(.*)(id<\/name>)([0-9]+){1}.*/\4/p') + _record_id=$(printf '%s' "$response" | sed -nE 's/.*(record){1}(.*)(id<\/name>)([0-9]+){1}.*/\4/p') _info "Deleting record" - _inwx_delete_record $_record_id + _inwx_delete_record "$_record_id" fi - } #################### Private functions below ################################## @@ -196,26 +192,26 @@ _inwx_login() { ' $INWX_User $INWX_Password response="$(_post "$xml_content" "$INWX_Api" "" "POST")" - + printf "Cookie: %s" "$(grep "domrobot=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'domrobot=[^;]*;' | tr -d ';')" } _get_root() { - domain=$1 + domain=$1 _debug "get root" domain=$1 i=2 p=1 - - export _H1=$(_inwx_login) + _H1=$(_inwx_login) + export _H1 printf -v xml_content ' nameserver.list ' - + response="$(_post "$xml_content" "$INWX_Api" "" "POST")" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) @@ -256,17 +252,16 @@ _inwx_delete_record() { - ' $record_id - + ' "$record_id" + response="$(_post "$xml_content" "$INWX_Api" "" "POST")" - + if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then _err "Error" return 1 fi return 0 - - + } _inwx_update_record() { @@ -295,17 +290,16 @@ _inwx_update_record() { - ' $txtval $record_id - - + ' "$txtval" "$record_id" + response="$(_post "$xml_content" "$INWX_Api" "" "POST")" - + if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then _err "Error" return 1 fi return 0 - + } _inwx_add_record() { @@ -314,10 +308,6 @@ _inwx_add_record() { sub_domain=$2 txtval=$3 - _debug domain: $domain - _debug value: $txtval - _debug subd: $sub_domain - printf -v xml_content ' nameserver.createRecord @@ -353,10 +343,10 @@ _inwx_add_record() { - ' $domain $txtval $sub_domain - + ' "$domain" "$txtval" "$sub_domain" + response="$(_post "$xml_content" "$INWX_Api" "" "POST")" - + if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then _err "Error" return 1 From ecba959dd99cda64d72c88c1d9c7d77894f72f80 Mon Sep 17 00:00:00 2001 From: speedmann Date: Thu, 7 Dec 2017 13:07:05 +0100 Subject: [PATCH 41/65] Fix missed whitespaces --- dnsapi/dns_inwx.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dnsapi/dns_inwx.sh b/dnsapi/dns_inwx.sh index 9e2302b..b02d1fb 100755 --- a/dnsapi/dns_inwx.sh +++ b/dnsapi/dns_inwx.sh @@ -155,7 +155,7 @@ dns_inwx_rm() { if ! printf "%s" "$response" | grep "count" -q; then _info "Do not need to delete record" else - _record_id=$(printf '%s' "$response" | sed -nE 's/.*(record){1}(.*)(id<\/name>)([0-9]+){1}.*/\4/p') + _record_id=$(printf '%s' "$response" | sed -nE 's/.*(record){1}(.*)(id<\/name>)([0-9]+){1}.*/\4/p') _info "Deleting record" _inwx_delete_record "$_record_id" fi @@ -253,7 +253,7 @@ _inwx_delete_record() { ' "$record_id" - + response="$(_post "$xml_content" "$INWX_Api" "" "POST")" if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then @@ -261,7 +261,7 @@ _inwx_delete_record() { return 1 fi return 0 - + } _inwx_update_record() { @@ -293,13 +293,13 @@ _inwx_update_record() { ' "$txtval" "$record_id" response="$(_post "$xml_content" "$INWX_Api" "" "POST")" - + if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then _err "Error" return 1 fi return 0 - + } _inwx_add_record() { From a00169451fc21653763efefd0dc7938362a0e5fa Mon Sep 17 00:00:00 2001 From: speedmann Date: Thu, 7 Dec 2017 13:10:59 +0100 Subject: [PATCH 42/65] Change bash to sh to fit project requirements --- dnsapi/dns_inwx.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_inwx.sh b/dnsapi/dns_inwx.sh index b02d1fb..78e101e 100755 --- a/dnsapi/dns_inwx.sh +++ b/dnsapi/dns_inwx.sh @@ -1,4 +1,4 @@ -#!/usr/local/bin/bash +#!/usr/local/bin/sh # #INWX_User="username" From 4a9f607d318a6a5e451f6962e44697c857580eea Mon Sep 17 00:00:00 2001 From: JAA Date: Thu, 7 Dec 2017 13:53:27 +0100 Subject: [PATCH 43/65] Cleanup --- dnsapi/dns_unoeuro.sh | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/dnsapi/dns_unoeuro.sh b/dnsapi/dns_unoeuro.sh index 4774187..f48b8b9 100644 --- a/dnsapi/dns_unoeuro.sh +++ b/dnsapi/dns_unoeuro.sh @@ -5,7 +5,7 @@ # #Uno_User="UExxxxxx" -Uno_Api="https://api.unoeuro.com/1/$Uno_User/$Uno_Key" +Uno_Api="https://api.unoeuro.com/1" ######## Public functions ##################### @@ -25,7 +25,7 @@ dns_unoeuro_add() { fi if ! _contains "$Uno_User" "UE"; then - _err "It seems that the Uno_User=$Uno_User is not a valid email address." + _err "It seems that the Uno_User=$Uno_User is not a valid username." _err "Please check and retry." return 1 fi @@ -94,6 +94,12 @@ dns_unoeuro_rm() { return 1 fi + if ! _contains "$Uno_User" "UE"; then + _err "It seems that the Uno_User=$Uno_User is not a valid username." + _err "Please check and retry." + return 1 + fi + _debug "First detect the root zone" if ! _get_root "$fulldomain"; then _err "invalid domain" @@ -174,15 +180,13 @@ _uno_rest() { data="$3" _debug "$ep" - #export _H1="X-Auth-Email: $Uno_User" - #export _H2="X-Auth-Key: $Uno_Key" export _H1="Content-Type: application/json" if [ "$m" != "GET" ]; then _debug data "$data" - response="$(_post "$data" "$Uno_Api/$ep" "" "$m")" + response="$(_post "$data" "$Uno_Api/$Uno_User/$Uno_Key/$ep" "" "$m")" else - response="$(_get "$Uno_Api/$ep")" + response="$(_get "$Uno_Api/$Uno_User/$Uno_Key/$ep")" fi if [ "$?" != "0" ]; then From b91c0a0616f11f3475d21269883cf3107201581f Mon Sep 17 00:00:00 2001 From: JAA Date: Thu, 7 Dec 2017 13:53:40 +0100 Subject: [PATCH 44/65] Don't use grep -B --- dnsapi/dns_unoeuro.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_unoeuro.sh b/dnsapi/dns_unoeuro.sh index f48b8b9..d19e9eb 100644 --- a/dnsapi/dns_unoeuro.sh +++ b/dnsapi/dns_unoeuro.sh @@ -65,7 +65,7 @@ dns_unoeuro_add() { _err "Add txt record error." else _info "Updating record" - record_id=$(echo "$response" | grep -B 1 "$_sub_domain" | _head_n -1 | _egrep_o "[0-9]{1,}") + record_id=$(echo "$response" | sed -n -e "/$_sub_domain/{x;p;d;}" -e x | _head_n -1 | _egrep_o "[0-9]{1,}") _debug "record_id" "$record_id" _uno_rest PUT "my/products/$h/dns/records/$record_id" "{\"name\":\"$fulldomain\",\"type\":\"TXT\",\"data\":\"$txtvalue\",\"ttl\":120}" @@ -120,7 +120,7 @@ dns_unoeuro_rm() { if ! _contains "$response" "$_sub_domain" >/dev/null; then _info "Don't need to remove." else - record_id=$(echo "$response" | grep -B 1 "$_sub_domain" | _head_n -1 | _egrep_o "[0-9]{1,}") + record_id=$(echo "$response" | sed -n -e "/$_sub_domain/{x;p;d;}" -e x | _head_n -1 | _egrep_o "[0-9]{1,}") _debug "record_id" "$record_id" if [ -z "$record_id" ]; then From 9a1f769828c426b26589110b70f324bde4e6c7e2 Mon Sep 17 00:00:00 2001 From: speedmann Date: Thu, 7 Dec 2017 14:18:54 +0100 Subject: [PATCH 45/65] Avoid usage of `sed -E` `grep -q` and `printf -v` --- dnsapi/dns_inwx.sh | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/dnsapi/dns_inwx.sh b/dnsapi/dns_inwx.sh index 78e101e..2a2895f 100755 --- a/dnsapi/dns_inwx.sh +++ b/dnsapi/dns_inwx.sh @@ -37,7 +37,7 @@ dns_inwx_add() { _debug _domain "$_domain" _debug "Getting txt records" - printf -v xml_content ' + xml_content=$(printf ' nameserver.info @@ -66,7 +66,7 @@ dns_inwx_add() { - ' "$_domain" "$_sub_domain" + ' "$_domain" "$_sub_domain") response="$(_post "$xml_content" "$INWX_Api" "" "POST")" if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then @@ -74,11 +74,11 @@ dns_inwx_add() { return 1 fi - if ! printf "%s" "$response" | grep "count" -q; then + if ! printf "%s" "$response" | grep "count" >/dev/null; then _info "Adding record" _inwx_add_record "$_domain" "$_sub_domain" "$txtvalue" else - _record_id=$(printf '%s' "$response" | sed -nE 's/.*(record){1}(.*)(id<\/name>)([0-9]+){1}.*/\4/p') + _record_id=$(printf '%s' "$response" | _egrep_o '.*(record){1}(.*)([0-9]+){1}' | _egrep_o 'id<\/name>[0-9]+' | egrep -o '[0-9]+') _info "Updating record" _inwx_update_record "$_record_id" "$txtvalue" fi @@ -115,7 +115,7 @@ dns_inwx_rm() { _debug "Getting txt records" - printf -v xml_content ' + xml_content=$(printf ' nameserver.info @@ -144,7 +144,7 @@ dns_inwx_rm() { - ' "$_domain" "$_sub_domain" + ' "$_domain" "$_sub_domain") response="$(_post "$xml_content" "$INWX_Api" "" "POST")" if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then @@ -152,10 +152,10 @@ dns_inwx_rm() { return 1 fi - if ! printf "%s" "$response" | grep "count" -q; then + if ! printf "%s" "$response" | grep "count" >/dev/null; then _info "Do not need to delete record" else - _record_id=$(printf '%s' "$response" | sed -nE 's/.*(record){1}(.*)(id<\/name>)([0-9]+){1}.*/\4/p') + _record_id=$(printf '%s' "$response" | _egrep_o '.*(record){1}(.*)([0-9]+){1}' | _egrep_o 'id<\/name>[0-9]+' | egrep -o '[0-9]+') _info "Deleting record" _inwx_delete_record "$_record_id" fi @@ -166,7 +166,7 @@ dns_inwx_rm() { _inwx_login() { - printf -v xml_content ' + xml_content=$(printf ' account.login @@ -189,7 +189,7 @@ _inwx_login() { - ' $INWX_User $INWX_Password + ' $INWX_User $INWX_Password) response="$(_post "$xml_content" "$INWX_Api" "" "POST")" @@ -207,7 +207,7 @@ _get_root() { _H1=$(_inwx_login) export _H1 - printf -v xml_content ' + xml_content=' nameserver.list ' @@ -235,7 +235,7 @@ _get_root() { _inwx_delete_record() { record_id=$1 - printf -v xml_content ' + xml_content=$(printf ' nameserver.deleteRecord @@ -252,7 +252,7 @@ _inwx_delete_record() { - ' "$record_id" + ' "$record_id") response="$(_post "$xml_content" "$INWX_Api" "" "POST")" @@ -267,7 +267,7 @@ _inwx_delete_record() { _inwx_update_record() { record_id=$1 txtval=$2 - printf -v xml_content ' + xml_content=$(printf ' nameserver.updateRecord @@ -290,7 +290,7 @@ _inwx_update_record() { - ' "$txtval" "$record_id" + ' "$txtval" "$record_id") response="$(_post "$xml_content" "$INWX_Api" "" "POST")" @@ -308,7 +308,7 @@ _inwx_add_record() { sub_domain=$2 txtval=$3 - printf -v xml_content ' + xml_content=$(printf ' nameserver.createRecord @@ -343,7 +343,7 @@ _inwx_add_record() { - ' "$domain" "$txtval" "$sub_domain" + ' "$domain" "$txtval" "$sub_domain") response="$(_post "$xml_content" "$INWX_Api" "" "POST")" From 5911594906f07aa2db4b7d3256388e7514f28b92 Mon Sep 17 00:00:00 2001 From: speedmann Date: Thu, 7 Dec 2017 14:21:37 +0100 Subject: [PATCH 46/65] Fix egrep invocation --- dnsapi/dns_inwx.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_inwx.sh b/dnsapi/dns_inwx.sh index 2a2895f..ae20074 100755 --- a/dnsapi/dns_inwx.sh +++ b/dnsapi/dns_inwx.sh @@ -78,7 +78,7 @@ dns_inwx_add() { _info "Adding record" _inwx_add_record "$_domain" "$_sub_domain" "$txtvalue" else - _record_id=$(printf '%s' "$response" | _egrep_o '.*(record){1}(.*)([0-9]+){1}' | _egrep_o 'id<\/name>[0-9]+' | egrep -o '[0-9]+') + _record_id=$(printf '%s' "$response" | _egrep_o '.*(record){1}(.*)([0-9]+){1}' | _egrep_o 'id<\/name>[0-9]+' | _egrep_o '[0-9]+') _info "Updating record" _inwx_update_record "$_record_id" "$txtvalue" fi @@ -155,7 +155,7 @@ dns_inwx_rm() { if ! printf "%s" "$response" | grep "count" >/dev/null; then _info "Do not need to delete record" else - _record_id=$(printf '%s' "$response" | _egrep_o '.*(record){1}(.*)([0-9]+){1}' | _egrep_o 'id<\/name>[0-9]+' | egrep -o '[0-9]+') + _record_id=$(printf '%s' "$response" | _egrep_o '.*(record){1}(.*)([0-9]+){1}' | _egrep_o 'id<\/name>[0-9]+' | _egrep_o '[0-9]+') _info "Deleting record" _inwx_delete_record "$_record_id" fi From f87890cb4b534feecd23dd2e7042e8601f15a3c3 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 7 Dec 2017 21:32:17 +0800 Subject: [PATCH 47/65] v2.7.6 fix ECC 384 signature https://github.com/Neilpang/acme.sh/issues/1130 https://github.com/Neilpang/acme.sh/issues/990 --- acme.sh | 149 ++++++++++++++++++++++---------------------------------- 1 file changed, 57 insertions(+), 92 deletions(-) diff --git a/acme.sh b/acme.sh index 98f4067..0755f78 100755 --- a/acme.sh +++ b/acme.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -VER=2.7.5 +VER=2.7.6 PROJECT_NAME="acme.sh" @@ -15,7 +15,7 @@ _SUB_FOLDERS="dnsapi deploy" _OLD_CA_HOST="https://acme-v01.api.letsencrypt.org" DEFAULT_CA="https://acme-v01.api.letsencrypt.org/directory" -DEFAULT_AGREEMENT="https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf" + DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)" DEFAULT_ACCOUNT_EMAIL="" @@ -900,17 +900,11 @@ _sign() { fi _sign_openssl="${ACME_OPENSSL_BIN:-openssl} dgst -sign $keyfile " - if [ "$alg" = "sha256" ]; then - _sign_openssl="$_sign_openssl -$alg" - else - _err "$alg is not supported yet" - return 1 - fi if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then - $_sign_openssl | _base64 + $_sign_openssl -$alg | _base64 elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then - if ! _signedECText="$($_sign_openssl | ${ACME_OPENSSL_BIN:-openssl} asn1parse -inform DER)"; 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" @@ -1433,7 +1427,11 @@ _calcjwk() { _debug "EC key" crv="$(${ACME_OPENSSL_BIN:-openssl} ec -in "$keyfile" -noout -text 2>/dev/null | grep "^NIST CURVE:" | cut -d ":" -f 2 | tr -d " \r\n")" _debug3 crv "$crv" - + __ECC_KEY_LEN=$(echo "$crv" | cut -d "-" -f 2) + if [ "$__ECC_KEY_LEN" = "521" ]; then + __ECC_KEY_LEN=512 + fi + _debug3 __ECC_KEY_LEN "$__ECC_KEY_LEN" if [ -z "$crv" ]; then _debug "Let's try ASN1 OID" crv_oid="$(${ACME_OPENSSL_BIN:-openssl} ec -in "$keyfile" -noout -text 2>/dev/null | grep "^ASN1 OID:" | cut -d ":" -f 2 | tr -d " \r\n")" @@ -1441,12 +1439,15 @@ _calcjwk() { case "${crv_oid}" in "prime256v1") crv="P-256" + __ECC_KEY_LEN=256 ;; "secp384r1") crv="P-384" + __ECC_KEY_LEN=384 ;; "secp521r1") crv="P-521" + __ECC_KEY_LEN=512 ;; *) _err "ECC oid : $crv_oid" @@ -1488,9 +1489,9 @@ _calcjwk() { jwk='{"crv": "'$crv'", "kty": "EC", "x": "'$x64'", "y": "'$y64'"}' _debug3 jwk "$jwk" - JWK_HEADER='{"alg": "ES256", "jwk": '$jwk'}' + JWK_HEADER='{"alg": "ES'$__ECC_KEY_LEN'", "jwk": '$jwk'}' JWK_HEADERPLACE_PART1='{"nonce": "' - JWK_HEADERPLACE_PART2='", "alg": "ES256", "jwk": '$jwk'}' + JWK_HEADERPLACE_PART2='", "alg": "ES'$__ECC_KEY_LEN'", "jwk": '$jwk'}' else _err "Only RSA or EC key is supported." return 1 @@ -2160,17 +2161,6 @@ _initAPI() { _api_server="${1:-$ACME_DIRECTORY}" _debug "_init api for server: $_api_server" - if [ "$_api_server" = "$DEFAULT_CA" ]; then - #just for performance, hardcode the default entry points - export ACME_KEY_CHANGE="https://acme-v01.api.letsencrypt.org/acme/key-change" - export ACME_NEW_AUTHZ="https://acme-v01.api.letsencrypt.org/acme/new-authz" - export ACME_NEW_ORDER="https://acme-v01.api.letsencrypt.org/acme/new-cert" - export ACME_NEW_ORDER_RES="new-cert" - export ACME_NEW_ACCOUNT="https://acme-v01.api.letsencrypt.org/acme/new-reg" - export ACME_NEW_ACCOUNT_RES="new-reg" - export ACME_REVOKE_CERT="https://acme-v01.api.letsencrypt.org/acme/revoke-cert" - fi - if [ -z "$ACME_NEW_ACCOUNT" ]; then response=$(_get "$_api_server") if [ "$?" != "0" ]; then @@ -2209,14 +2199,18 @@ _initAPI() { ACME_NEW_NONCE=$(echo "$response" | _egrep_o 'new-nonce" *: *"[^"]*"' | cut -d '"' -f 3) export ACME_NEW_NONCE + + ACME_AGREEMENT=$(echo "$response" | _egrep_o 'terms-of-service" *: *"[^"]*"' | cut -d '"' -f 3) + export ACME_AGREEMENT + + _debug "ACME_KEY_CHANGE" "$ACME_KEY_CHANGE" + _debug "ACME_NEW_AUTHZ" "$ACME_NEW_AUTHZ" + _debug "ACME_NEW_ORDER" "$ACME_NEW_ORDER" + _debug "ACME_NEW_ACCOUNT" "$ACME_NEW_ACCOUNT" + _debug "ACME_REVOKE_CERT" "$ACME_REVOKE_CERT" + _debug "ACME_AGREEMENT" "$ACME_AGREEMENT" fi - - _debug "ACME_KEY_CHANGE" "$ACME_KEY_CHANGE" - _debug "ACME_NEW_AUTHZ" "$ACME_NEW_AUTHZ" - _debug "ACME_NEW_ORDER" "$ACME_NEW_ORDER" - _debug "ACME_NEW_ACCOUNT" "$ACME_NEW_ACCOUNT" - _debug "ACME_REVOKE_CERT" "$ACME_REVOKE_CERT" } #[domain] [keylength or isEcc flag] @@ -3058,7 +3052,7 @@ __calc_account_thumbprint() { _regAccount() { _initpath _reg_length="$1" - + _debug3 _regAccount "$_regAccount" mkdir -p "$CA_DIR" if [ ! -f "$ACCOUNT_KEY_PATH" ] && [ -f "$_OLD_ACCOUNT_KEY" ]; then _info "mv $_OLD_ACCOUNT_KEY to $ACCOUNT_KEY_PATH" @@ -3081,75 +3075,46 @@ _regAccount() { return 1 fi _initAPI - _updateTos="" _reg_res="$ACME_NEW_ACCOUNT_RES" - while true; do - _debug AGREEMENT "$AGREEMENT" + regjson='{"resource": "'$_reg_res'", "terms-of-service-agreed": true, "agreement": "'$ACME_AGREEMENT'"}' + if [ "$ACCOUNT_EMAIL" ]; then + regjson='{"resource": "'$_reg_res'", "contact": ["mailto: '$ACCOUNT_EMAIL'"], "terms-of-service-agreed": true, "agreement": "'$ACME_AGREEMENT'"}' + fi - regjson='{"resource": "'$_reg_res'", "agreement": "'$AGREEMENT'"}' + if [ -z "$_updateTos" ]; then + _info "Registering account" - if [ "$ACCOUNT_EMAIL" ]; then - regjson='{"resource": "'$_reg_res'", "contact": ["mailto: '$ACCOUNT_EMAIL'"], "agreement": "'$AGREEMENT'"}' - fi + if ! _send_signed_request "${ACME_NEW_ACCOUNT}" "$regjson"; then + _err "Register account Error: $response" + return 1 + fi - if [ -z "$_updateTos" ]; then - _info "Registering account" + if [ "$code" = "" ] || [ "$code" = '201' ]; then + echo "$response" >"$ACCOUNT_JSON_PATH" + _info "Registered" + elif [ "$code" = '409' ]; then + _info "Already registered" + else + _err "Register account Error: $response" + return 1 + fi - if ! _send_signed_request "${ACME_NEW_ACCOUNT}" "$regjson"; then - _err "Register account Error: $response" - return 1 - fi + _accUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ' ' -f 2 | tr -d "\r\n")" + _debug "_accUri" "$_accUri" + _savecaconf "ACCOUNT_URL" "$_accUri" - if [ "$code" = "" ] || [ "$code" = '201' ]; then - echo "$response" >"$ACCOUNT_JSON_PATH" - _info "Registered" - elif [ "$code" = '409' ]; then - _info "Already registered" - else - _err "Register account Error: $response" - return 1 - fi + echo "$response" >"$ACCOUNT_JSON_PATH" + CA_KEY_HASH="$(__calcAccountKeyHash)" + _debug "Calc CA_KEY_HASH" "$CA_KEY_HASH" + _savecaconf CA_KEY_HASH "$CA_KEY_HASH" - _accUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ' ' -f 2 | tr -d "\r\n")" - _debug "_accUri" "$_accUri" - _savecaconf "ACCOUNT_URL" "$_accUri" - _tos="$(echo "$responseHeaders" | grep "^Link:.*rel=\"terms-of-service\"" | _head_n 1 | _egrep_o "<.*>" | tr -d '<>')" - _debug "_tos" "$_tos" - if [ -z "$_tos" ]; then - _debug "Use default tos: $DEFAULT_AGREEMENT" - _tos="$DEFAULT_AGREEMENT" - fi - if [ "$_tos" != "$AGREEMENT" ]; then - _updateTos=1 - AGREEMENT="$_tos" - _reg_res="reg" - continue - fi + if [ "$code" = '403' ]; then + _err "It seems that the account key is already deactivated, please use a new account key." + return 1 + fi - else - _debug "Update tos: $_tos" - if ! _send_signed_request "$_accUri" "$regjson"; then - _err "Update tos error." - return 1 - fi - if [ "$code" = '202' ]; then - _info "Update account tos info success." - echo "$response" >"$ACCOUNT_JSON_PATH" - CA_KEY_HASH="$(__calcAccountKeyHash)" - _debug "Calc CA_KEY_HASH" "$CA_KEY_HASH" - _savecaconf CA_KEY_HASH "$CA_KEY_HASH" - elif [ "$code" = '403' ]; then - _err "It seems that the account key is already deactivated, please use a new account key." - return 1 - else - _err "Update account error." - return 1 - fi - fi - ACCOUNT_THUMBPRINT="$(__calc_account_thumbprint)" - _info "ACCOUNT_THUMBPRINT" "$ACCOUNT_THUMBPRINT" - return 0 - done + ACCOUNT_THUMBPRINT="$(__calc_account_thumbprint)" + _info "ACCOUNT_THUMBPRINT" "$ACCOUNT_THUMBPRINT" } From db3043553cbfb9ca05f5a6807590603ee381a80a Mon Sep 17 00:00:00 2001 From: JAA Date: Thu, 7 Dec 2017 14:52:09 +0100 Subject: [PATCH 48/65] Also don't use sed --- dnsapi/dns_unoeuro.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_unoeuro.sh b/dnsapi/dns_unoeuro.sh index d19e9eb..6b582dd 100644 --- a/dnsapi/dns_unoeuro.sh +++ b/dnsapi/dns_unoeuro.sh @@ -53,6 +53,7 @@ dns_unoeuro_add() { if ! _contains "$response" "$_sub_domain" >/dev/null; then _info "Adding record" + if _uno_rest POST "my/products/$h/dns/records" "{\"name\":\"$fulldomain\",\"type\":\"TXT\",\"data\":\"$txtvalue\",\"ttl\":120}"; then if _contains "$response" "\"status\": 200" >/dev/null; then _info "Added, OK" @@ -65,7 +66,9 @@ dns_unoeuro_add() { _err "Add txt record error." else _info "Updating record" - record_id=$(echo "$response" | sed -n -e "/$_sub_domain/{x;p;d;}" -e x | _head_n -1 | _egrep_o "[0-9]{1,}") + record_line_number=$(echo "$response" | grep -n "$_sub_domain" | cut -d : -f 1) + record_line_number=$(($record_line_number-1)) + record_id=$(echo "$response" | _head_n "$record_line_number" | _tail_n 1 1 | _egrep_o "[0-9]{1,}") _debug "record_id" "$record_id" _uno_rest PUT "my/products/$h/dns/records/$record_id" "{\"name\":\"$fulldomain\",\"type\":\"TXT\",\"data\":\"$txtvalue\",\"ttl\":120}" @@ -76,7 +79,6 @@ dns_unoeuro_add() { _err "Update error" return 1 fi - } #fulldomain txtvalue @@ -120,7 +122,9 @@ dns_unoeuro_rm() { if ! _contains "$response" "$_sub_domain" >/dev/null; then _info "Don't need to remove." else - record_id=$(echo "$response" | sed -n -e "/$_sub_domain/{x;p;d;}" -e x | _head_n -1 | _egrep_o "[0-9]{1,}") + record_line_number=$(echo "$response" | grep -n "$_sub_domain" | cut -d : -f 1) + record_line_number=$(($record_line_number-1)) + record_id=$(echo "$response" | _head_n "$record_line_number" | _tail_n 1 1 | _egrep_o "[0-9]{1,}") _debug "record_id" "$record_id" if [ -z "$record_id" ]; then From 1f635b90e76a5fb61a92f038a20a78b5381b1ea2 Mon Sep 17 00:00:00 2001 From: Aarup Date: Fri, 8 Dec 2017 08:26:52 +0100 Subject: [PATCH 49/65] Try to fix build --- dnsapi/dns_unoeuro.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_unoeuro.sh b/dnsapi/dns_unoeuro.sh index 6b582dd..8a1928d 100644 --- a/dnsapi/dns_unoeuro.sh +++ b/dnsapi/dns_unoeuro.sh @@ -67,7 +67,7 @@ dns_unoeuro_add() { else _info "Updating record" record_line_number=$(echo "$response" | grep -n "$_sub_domain" | cut -d : -f 1) - record_line_number=$(($record_line_number-1)) + record_line_number=$(($record_line_number - 1)) record_id=$(echo "$response" | _head_n "$record_line_number" | _tail_n 1 1 | _egrep_o "[0-9]{1,}") _debug "record_id" "$record_id" @@ -123,7 +123,7 @@ dns_unoeuro_rm() { _info "Don't need to remove." else record_line_number=$(echo "$response" | grep -n "$_sub_domain" | cut -d : -f 1) - record_line_number=$(($record_line_number-1)) + record_line_number=$(($record_line_number - 1)) record_id=$(echo "$response" | _head_n "$record_line_number" | _tail_n 1 1 | _egrep_o "[0-9]{1,}") _debug "record_id" "$record_id" From 3f1e6c128ff0d1af3fc1fc896f115821b55af885 Mon Sep 17 00:00:00 2001 From: Aarup Date: Fri, 8 Dec 2017 08:31:24 +0100 Subject: [PATCH 50/65] Try again --- dnsapi/dns_unoeuro.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_unoeuro.sh b/dnsapi/dns_unoeuro.sh index 8a1928d..be0fadb 100644 --- a/dnsapi/dns_unoeuro.sh +++ b/dnsapi/dns_unoeuro.sh @@ -67,7 +67,7 @@ dns_unoeuro_add() { else _info "Updating record" record_line_number=$(echo "$response" | grep -n "$_sub_domain" | cut -d : -f 1) - record_line_number=$(($record_line_number - 1)) + record_line_number=$((record_line_number - 1)) record_id=$(echo "$response" | _head_n "$record_line_number" | _tail_n 1 1 | _egrep_o "[0-9]{1,}") _debug "record_id" "$record_id" @@ -123,7 +123,7 @@ dns_unoeuro_rm() { _info "Don't need to remove." else record_line_number=$(echo "$response" | grep -n "$_sub_domain" | cut -d : -f 1) - record_line_number=$(($record_line_number - 1)) + record_line_number=$((record_line_number - 1)) record_id=$(echo "$response" | _head_n "$record_line_number" | _tail_n 1 1 | _egrep_o "[0-9]{1,}") _debug "record_id" "$record_id" From ca7ebd933324db4c9ea4a383321413c6deb399f3 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 8 Dec 2017 19:49:18 +0800 Subject: [PATCH 51/65] fix typo --- acme.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 0755f78..2affeb9 100755 --- a/acme.sh +++ b/acme.sh @@ -3081,8 +3081,7 @@ _regAccount() { regjson='{"resource": "'$_reg_res'", "contact": ["mailto: '$ACCOUNT_EMAIL'"], "terms-of-service-agreed": true, "agreement": "'$ACME_AGREEMENT'"}' fi - if [ -z "$_updateTos" ]; then - _info "Registering account" + _info "Registering account" if ! _send_signed_request "${ACME_NEW_ACCOUNT}" "$regjson"; then _err "Register account Error: $response" From 4249e13eb4089deb518d0e54e10b8bd24d2f5640 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 8 Dec 2017 19:54:25 +0800 Subject: [PATCH 52/65] fix format --- acme.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 2affeb9..88273cf 100755 --- a/acme.sh +++ b/acme.sh @@ -16,7 +16,6 @@ _SUB_FOLDERS="dnsapi deploy" _OLD_CA_HOST="https://acme-v01.api.letsencrypt.org" DEFAULT_CA="https://acme-v01.api.letsencrypt.org/directory" - DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)" DEFAULT_ACCOUNT_EMAIL="" @@ -2199,7 +2198,7 @@ _initAPI() { ACME_NEW_NONCE=$(echo "$response" | _egrep_o 'new-nonce" *: *"[^"]*"' | cut -d '"' -f 3) export ACME_NEW_NONCE - + ACME_AGREEMENT=$(echo "$response" | _egrep_o 'terms-of-service" *: *"[^"]*"' | cut -d '"' -f 3) export ACME_AGREEMENT From dbc3ad130461a4c9dde8b2ce778ae1881960508f Mon Sep 17 00:00:00 2001 From: Aarup Date: Fri, 8 Dec 2017 12:59:02 +0100 Subject: [PATCH 53/65] use _math --- dnsapi/dns_unoeuro.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_unoeuro.sh b/dnsapi/dns_unoeuro.sh index be0fadb..1479d54 100644 --- a/dnsapi/dns_unoeuro.sh +++ b/dnsapi/dns_unoeuro.sh @@ -67,7 +67,7 @@ dns_unoeuro_add() { else _info "Updating record" record_line_number=$(echo "$response" | grep -n "$_sub_domain" | cut -d : -f 1) - record_line_number=$((record_line_number - 1)) + record_line_number=$(_math "$record_line_number" - 1) record_id=$(echo "$response" | _head_n "$record_line_number" | _tail_n 1 1 | _egrep_o "[0-9]{1,}") _debug "record_id" "$record_id" @@ -123,7 +123,7 @@ dns_unoeuro_rm() { _info "Don't need to remove." else record_line_number=$(echo "$response" | grep -n "$_sub_domain" | cut -d : -f 1) - record_line_number=$((record_line_number - 1)) + record_line_number=$(_math "$record_line_number" - 1) record_id=$(echo "$response" | _head_n "$record_line_number" | _tail_n 1 1 | _egrep_o "[0-9]{1,}") _debug "record_id" "$record_id" From f763e1edd7c677e9d313288b8426223f86ca9e49 Mon Sep 17 00:00:00 2001 From: Aarup Date: Fri, 8 Dec 2017 13:20:25 +0100 Subject: [PATCH 54/65] fix contains usage --- dnsapi/dns_unoeuro.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_unoeuro.sh b/dnsapi/dns_unoeuro.sh index 1479d54..f75de39 100644 --- a/dnsapi/dns_unoeuro.sh +++ b/dnsapi/dns_unoeuro.sh @@ -114,12 +114,12 @@ dns_unoeuro_rm() { _debug "Getting txt records" _uno_rest GET "my/products/$h/dns/records" - if ! _contains "$response" "\"status\": 200" >/dev/null; then + if ! _contains "$response" "\"status\": 200"; then _err "Error" return 1 fi - if ! _contains "$response" "$_sub_domain" >/dev/null; then + if ! _contains "$response" "$_sub_domain"; then _info "Don't need to remove." else record_line_number=$(echo "$response" | grep -n "$_sub_domain" | cut -d : -f 1) @@ -163,7 +163,7 @@ _get_root() { return 1 fi - if _contains "$response" "\"status\": 200" >/dev/null; then + if _contains "$response" "\"status\": 200"; then _domain_id=$h if [ "$_domain_id" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) From f9b8d7a9d8316ad0e6b663572f552bb32a6236a4 Mon Sep 17 00:00:00 2001 From: Aarup Date: Fri, 8 Dec 2017 13:22:17 +0100 Subject: [PATCH 55/65] renamed uno_user and uno_key --- dnsapi/dns_unoeuro.sh | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/dnsapi/dns_unoeuro.sh b/dnsapi/dns_unoeuro.sh index f75de39..a3803a2 100644 --- a/dnsapi/dns_unoeuro.sh +++ b/dnsapi/dns_unoeuro.sh @@ -1,9 +1,9 @@ #!/usr/bin/env sh # -#Uno_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" +#UNO_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" # -#Uno_User="UExxxxxx" +#UNO_User="UExxxxxx" Uno_Api="https://api.unoeuro.com/1" @@ -14,25 +14,25 @@ dns_unoeuro_add() { fulldomain=$1 txtvalue=$2 - Uno_Key="${Uno_Key:-$(_readaccountconf_mutable Uno_Key)}" - Uno_User="${Uno_User:-$(_readaccountconf_mutable Uno_User)}" - if [ -z "$Uno_Key" ] || [ -z "$Uno_User" ]; then - Uno_Key="" - Uno_User="" + UNO_Key="${UNO_Key:-$(_readaccountconf_mutable UNO_Key)}" + UNO_User="${UNO_User:-$(_readaccountconf_mutable UNO_User)}" + if [ -z "$UNO_Key" ] || [ -z "$UNO_User" ]; then + UNO_Key="" + UNO_User="" _err "You haven't specified a UnoEuro api key and account yet." _err "Please create your key and try again." return 1 fi - if ! _contains "$Uno_User" "UE"; then - _err "It seems that the Uno_User=$Uno_User is not a valid username." + if ! _contains "$UNO_User" "UE"; then + _err "It seems that the UNO_User=$UNO_User is not a valid username." _err "Please check and retry." return 1 fi #save the api key and email to the account conf file. - _saveaccountconf_mutable Uno_Key "$Uno_Key" - _saveaccountconf_mutable Uno_User "$Uno_User" + _saveaccountconf_mutable UNO_Key "$UNO_Key" + _saveaccountconf_mutable UNO_User "$UNO_User" _debug "First detect the root zone" if ! _get_root "$fulldomain"; then @@ -86,18 +86,18 @@ dns_unoeuro_rm() { fulldomain=$1 txtvalue=$2 - Uno_Key="${Uno_Key:-$(_readaccountconf_mutable Uno_Key)}" - Uno_User="${Uno_User:-$(_readaccountconf_mutable Uno_User)}" - if [ -z "$Uno_Key" ] || [ -z "$Uno_User" ]; then - Uno_Key="" - Uno_User="" + UNO_Key="${UNO_Key:-$(_readaccountconf_mutable UNO_Key)}" + UNO_User="${UNO_User:-$(_readaccountconf_mutable UNO_User)}" + if [ -z "$UNO_Key" ] || [ -z "$UNO_User" ]; then + UNO_Key="" + UNO_User="" _err "You haven't specified a UnoEuro api key and account yet." _err "Please create your key and try again." return 1 fi - if ! _contains "$Uno_User" "UE"; then - _err "It seems that the Uno_User=$Uno_User is not a valid username." + if ! _contains "$UNO_User" "UE"; then + _err "It seems that the UNO_User=$UNO_User is not a valid username." _err "Please check and retry." return 1 fi @@ -188,9 +188,9 @@ _uno_rest() { if [ "$m" != "GET" ]; then _debug data "$data" - response="$(_post "$data" "$Uno_Api/$Uno_User/$Uno_Key/$ep" "" "$m")" + response="$(_post "$data" "$Uno_Api/$UNO_User/$UNO_Key/$ep" "" "$m")" else - response="$(_get "$Uno_Api/$Uno_User/$Uno_Key/$ep")" + response="$(_get "$Uno_Api/$UNO_User/$UNO_Key/$ep")" fi if [ "$?" != "0" ]; then From fb6e0658cf23a79cf4c16a3898fd57d281be0a32 Mon Sep 17 00:00:00 2001 From: Aarup Date: Fri, 8 Dec 2017 14:09:04 +0100 Subject: [PATCH 56/65] update README --- dnsapi/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/README.md b/dnsapi/README.md index 5fdcd84..8a486ae 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -607,8 +607,8 @@ Please report any issues to https://github.com/angel333/acme.sh or to Date: Sat, 9 Dec 2017 14:13:05 +0100 Subject: [PATCH 57/65] Fix shebang --- dnsapi/dns_inwx.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_inwx.sh b/dnsapi/dns_inwx.sh index ae20074..74440bd 100755 --- a/dnsapi/dns_inwx.sh +++ b/dnsapi/dns_inwx.sh @@ -1,4 +1,4 @@ -#!/usr/local/bin/sh +#!/usr/bin/env sh # #INWX_User="username" From f7c346de0928fcc57eb0c8f7561fada69118022d Mon Sep 17 00:00:00 2001 From: speedmann Date: Sat, 9 Dec 2017 14:20:36 +0100 Subject: [PATCH 58/65] Fix order in README and add link to inwx.de and apidocs --- README.md | 2 +- dnsapi/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8420c02..eb12291 100644 --- a/README.md +++ b/README.md @@ -339,8 +339,8 @@ You don't have to do anything manually! 1. Dyn Managed DNS API 1. Yandex PDD API (https://pdd.yandex.ru) 1. Hurricane Electric DNS service (https://dns.he.net) -1. INWX (https://www.inwx.de/) 1. UnoEuro API (https://www.unoeuro.com/) +1. INWX (https://www.inwx.de/) And: diff --git a/dnsapi/README.md b/dnsapi/README.md index 11b6b3a..c16e759 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -620,7 +620,7 @@ The `UNO_Key` and `UNO_User` will be saved in `~/.acme.sh/account.conf` and will ## 33. Use INWX -INWX offers an xmlrpc api with your standard login credentials, set them like so: +[INWX](https://www.inwx.de/) offers an [xmlrpc api](https://www.inwx.de/de/help/apidoc) with your standard login credentials, set them like so: ``` export INWX_User="yourusername" From 8201458332ea5898177118097621dbac842ad64f Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 9 Dec 2017 21:50:45 +0800 Subject: [PATCH 59/65] fix https://github.com/Neilpang/acme.sh/issues/1123 --- acme.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 88273cf..472975a 100755 --- a/acme.sh +++ b/acme.sh @@ -4308,7 +4308,12 @@ _installcert() { if [ -f "$_real_key" ] && [ ! "$IS_RENEW" ]; then cp "$_real_key" "$_backup_path/key.bak" fi - cat "$CERT_KEY_PATH" >"$_real_key" + if [ -f "$_real_key" ]; then + cat "$CERT_KEY_PATH" >"$_real_key" + else + cat "$CERT_KEY_PATH" >"$_real_key" + chmod 700 "$_real_key" + fi fi if [ "$_real_fullchain" ]; then From ae29929714b8cb8e4b7c612a354b56433f8ac47c Mon Sep 17 00:00:00 2001 From: Jens Hartlep Date: Sat, 9 Dec 2017 19:32:53 +0100 Subject: [PATCH 60/65] added dns api for servercow --- dnsapi/README.md | 16 ++++ dnsapi/dns_servercow.sh | 170 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 186 insertions(+) create mode 100755 dnsapi/dns_servercow.sh diff --git a/dnsapi/README.md b/dnsapi/README.md index c16e759..d357c05 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -635,6 +635,22 @@ acme.sh --issue --dns dns_inwx -d example.com -d www.example.com The `INWX_User` and `INWX_Password` settings will be saved in `~/.acme.sh/account.conf` and will be reused when needed. +## 34. User Servercow API v1 + +Create a new user from the servercow control center. Don't forget to activate **DNS API** for this user. + +``` +export SERVERCOW_API_Username=username +export SERVERCOW_API_Password=password +``` + +Now you cann issue a cert: + +``` +acme.sh --issue --dns dns_servercow -d example.com -d www.example.com +``` +Both, `SERVERCOW_API_Username` and `SERVERCOW_API_Password` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. + # Use custom API If your API is not supported yet, you can write your own DNS API. diff --git a/dnsapi/dns_servercow.sh b/dnsapi/dns_servercow.sh new file mode 100755 index 0000000..e704959 --- /dev/null +++ b/dnsapi/dns_servercow.sh @@ -0,0 +1,170 @@ +#!/usr/bin/env sh + +########## +# Custom servercow.de DNS API v1 for use with [acme.sh](https://github.com/Neilpang/acme.sh) +# +# Usage: +# export SERVERCOW_API_Username=username +# export SERVERCOW_API_Password=password +# acme.sh --issue -d example.com --dns dns_servercow +# +# Issues: +# Any issues / questions / suggestions can be posted here: +# https://github.com/jhartlep/servercow-dns-api/issues +# +# Author: Jens Hartlep +########## + +SERVERCOW_API="https://api.servercow.de/dns/v1/domains" + +# Usage dns_servercow_add _acme-challenge.www.domain.com "abcdefghijklmnopqrstuvwxyz" +dns_servercow_add() { + fulldomain=$1 + txtvalue=$2 + + _info "Using servercow" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + SERVERCOW_API_Username="${SERVERCOW_API_Username:-$(_readaccountconf_mutable SERVERCOW_API_Username)}" + SERVERCOW_API_Password="${SERVERCOW_API_Password:-$(_readaccountconf_mutable SERVERCOW_API_Password)}" + if [ -z "$SERVERCOW_API_Username" ] || [ -z "$SERVERCOW_API_Password" ]; then + SERVERCOW_API_Username="" + SERVERCOW_API_Password="" + _err "You don't specify servercow api username and password yet." + _err "Please create your username and password and try again." + return 1 + fi + + # save the credentials to the account conf file + _saveaccountconf_mutable SERVERCOW_API_Username "$SERVERCOW_API_Username" + _saveaccountconf_mutable SERVERCOW_API_Password "$SERVERCOW_API_Password" + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then + if printf -- "%s" "$response" | grep "ok" > /dev/null; then + _info "Added, OK" + return 0 + else + _err "add txt record error." + return 1 + fi + fi + _err "add txt record error." + + return 1 +} + +# Usage fulldomain txtvalue +# Remove the txt record after validation +dns_servercow_rm() { + fulldomain=$1 + txtvalue=$2 + + _info "Using servercow" + _debug fulldomain "$fulldomain" + _debug txtvalue "$fulldomain" + + SERVERCOW_API_Username="${SERVERCOW_API_Username:-$(_readaccountconf_mutable SERVERCOW_API_Username)}" + SERVERCOW_API_Password="${SERVERCOW_API_Password:-$(_readaccountconf_mutable SERVERCOW_API_Password)}" + if [ -z "$SERVERCOW_API_Username" ] || [ -z "$SERVERCOW_API_Password" ]; then + SERVERCOW_API_Username="" + SERVERCOW_API_Password="" + _err "You don't specify servercow api username and password yet." + _err "Please create your username and password and try again." + return 1 + fi + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + if _servercow_api DELETE "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\"}"; then + if printf -- "%s" "$response" | grep "ok" > /dev/null; then + _info "Deleted, OK" + _contains "$response" '"message":"ok"' + else + _err "delete txt record error." + return 1 + fi + fi + +} + +#################### Private functions below ################################## + +# _acme-challenge.www.domain.com +# returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +_get_root() { + fulldomain=$1 + i=2 + p=1 + + while true; do + _domain=$(printf "%s" "$fulldomain" | cut -d . -f $i-100) + + _debug _domain "$_domain" + if [ -z "$_domain" ]; then + # not valid + return 1 + fi + + if ! _servercow_api GET "$_domain"; then + return 1 + fi + + if ! _contains "$response" '"error":"no such domain in user context"' > /dev/null; then + _sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-$p) + if [ -z "$_sub_domain" ]; then + # not valid + return 1 + fi + + return 0 + fi + + p=$i + i=$(_math "$i" + 1) + done; + + return 1 +} + +_servercow_api() { + method=$1 + domain=$2 + data="$3" + + export _H1="Content-Type: application/json" + export _H2="X-Auth-Username: $SERVERCOW_API_Username" + export _H3="X-Auth-Password: $SERVERCOW_API_Password" + + if [ "$method" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$SERVERCOW_API/$domain" "" "$method")" + else + response="$(_get "$SERVERCOW_API/$domain")" + fi + + if [ "$?" != "0" ]; then + _err "error $domain" + return 1 + fi + _debug2 response "$response" + return 0 +} From b140e2553bdfce40b99fb3ecd246ef3e64d33d42 Mon Sep 17 00:00:00 2001 From: Jens Hartlep Date: Sat, 9 Dec 2017 19:33:48 +0100 Subject: [PATCH 61/65] added Servercow to supported list --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index eb12291..5574b67 100644 --- a/README.md +++ b/README.md @@ -341,7 +341,7 @@ You don't have to do anything manually! 1. Hurricane Electric DNS service (https://dns.he.net) 1. UnoEuro API (https://www.unoeuro.com/) 1. INWX (https://www.inwx.de/) - +1. Servercow (https://servercow.de) And: From 488745f3783e767adf5421b20ff96fc82aae9a37 Mon Sep 17 00:00:00 2001 From: Jens Date: Sat, 9 Dec 2017 20:05:05 +0100 Subject: [PATCH 62/65] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5574b67..0d94275 100644 --- a/README.md +++ b/README.md @@ -343,6 +343,7 @@ You don't have to do anything manually! 1. INWX (https://www.inwx.de/) 1. Servercow (https://servercow.de) + And: 1. lexicon DNS API: https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api From 1c9b19833cf0ebd0087f171f9f3f5cf24fc96ecc Mon Sep 17 00:00:00 2001 From: Jens Date: Sat, 9 Dec 2017 20:14:46 +0100 Subject: [PATCH 63/65] Update dns_servercow.sh replaced tab with space --- dnsapi/dns_servercow.sh | 216 ++++++++++++++++++++-------------------- 1 file changed, 108 insertions(+), 108 deletions(-) diff --git a/dnsapi/dns_servercow.sh b/dnsapi/dns_servercow.sh index e704959..3ffc393 100755 --- a/dnsapi/dns_servercow.sh +++ b/dnsapi/dns_servercow.sh @@ -19,88 +19,88 @@ SERVERCOW_API="https://api.servercow.de/dns/v1/domains" # Usage dns_servercow_add _acme-challenge.www.domain.com "abcdefghijklmnopqrstuvwxyz" dns_servercow_add() { - fulldomain=$1 - txtvalue=$2 + fulldomain=$1 + txtvalue=$2 - _info "Using servercow" - _debug fulldomain "$fulldomain" - _debug txtvalue "$txtvalue" + _info "Using servercow" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" - SERVERCOW_API_Username="${SERVERCOW_API_Username:-$(_readaccountconf_mutable SERVERCOW_API_Username)}" - SERVERCOW_API_Password="${SERVERCOW_API_Password:-$(_readaccountconf_mutable SERVERCOW_API_Password)}" - if [ -z "$SERVERCOW_API_Username" ] || [ -z "$SERVERCOW_API_Password" ]; then - SERVERCOW_API_Username="" - SERVERCOW_API_Password="" - _err "You don't specify servercow api username and password yet." - _err "Please create your username and password and try again." - return 1 - fi + SERVERCOW_API_Username="${SERVERCOW_API_Username:-$(_readaccountconf_mutable SERVERCOW_API_Username)}" + SERVERCOW_API_Password="${SERVERCOW_API_Password:-$(_readaccountconf_mutable SERVERCOW_API_Password)}" + if [ -z "$SERVERCOW_API_Username" ] || [ -z "$SERVERCOW_API_Password" ]; then + SERVERCOW_API_Username="" + SERVERCOW_API_Password="" + _err "You don't specify servercow api username and password yet." + _err "Please create your username and password and try again." + return 1 + fi - # save the credentials to the account conf file - _saveaccountconf_mutable SERVERCOW_API_Username "$SERVERCOW_API_Username" - _saveaccountconf_mutable SERVERCOW_API_Password "$SERVERCOW_API_Password" + # save the credentials to the account conf file + _saveaccountconf_mutable SERVERCOW_API_Username "$SERVERCOW_API_Username" + _saveaccountconf_mutable SERVERCOW_API_Password "$SERVERCOW_API_Password" - _debug "First detect the root zone" - if ! _get_root "$fulldomain"; then - _err "invalid domain" - return 1 - fi + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi - _debug _sub_domain "$_sub_domain" - _debug _domain "$_domain" + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" - if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then - if printf -- "%s" "$response" | grep "ok" > /dev/null; then - _info "Added, OK" - return 0 - else - _err "add txt record error." - return 1 - fi - fi - _err "add txt record error." + if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then + if printf -- "%s" "$response" | grep "ok" > /dev/null; then + _info "Added, OK" + return 0 + else + _err "add txt record error." + return 1 + fi + fi + _err "add txt record error." - return 1 + return 1 } # Usage fulldomain txtvalue # Remove the txt record after validation dns_servercow_rm() { - fulldomain=$1 - txtvalue=$2 + fulldomain=$1 + txtvalue=$2 - _info "Using servercow" - _debug fulldomain "$fulldomain" - _debug txtvalue "$fulldomain" + _info "Using servercow" + _debug fulldomain "$fulldomain" + _debug txtvalue "$fulldomain" - SERVERCOW_API_Username="${SERVERCOW_API_Username:-$(_readaccountconf_mutable SERVERCOW_API_Username)}" - SERVERCOW_API_Password="${SERVERCOW_API_Password:-$(_readaccountconf_mutable SERVERCOW_API_Password)}" - if [ -z "$SERVERCOW_API_Username" ] || [ -z "$SERVERCOW_API_Password" ]; then - SERVERCOW_API_Username="" - SERVERCOW_API_Password="" - _err "You don't specify servercow api username and password yet." - _err "Please create your username and password and try again." - return 1 - fi + SERVERCOW_API_Username="${SERVERCOW_API_Username:-$(_readaccountconf_mutable SERVERCOW_API_Username)}" + SERVERCOW_API_Password="${SERVERCOW_API_Password:-$(_readaccountconf_mutable SERVERCOW_API_Password)}" + if [ -z "$SERVERCOW_API_Username" ] || [ -z "$SERVERCOW_API_Password" ]; then + SERVERCOW_API_Username="" + SERVERCOW_API_Password="" + _err "You don't specify servercow api username and password yet." + _err "Please create your username and password and try again." + return 1 + fi - _debug "First detect the root zone" - if ! _get_root "$fulldomain"; then - _err "invalid domain" - return 1 - fi + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi - _debug _sub_domain "$_sub_domain" - _debug _domain "$_domain" + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" - if _servercow_api DELETE "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\"}"; then - if printf -- "%s" "$response" | grep "ok" > /dev/null; then - _info "Deleted, OK" - _contains "$response" '"message":"ok"' - else - _err "delete txt record error." - return 1 - fi - fi + if _servercow_api DELETE "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\"}"; then + if printf -- "%s" "$response" | grep "ok" > /dev/null; then + _info "Deleted, OK" + _contains "$response" '"message":"ok"' + else + _err "delete txt record error." + return 1 + fi + fi } @@ -111,60 +111,60 @@ dns_servercow_rm() { # _sub_domain=_acme-challenge.www # _domain=domain.com _get_root() { - fulldomain=$1 - i=2 - p=1 + fulldomain=$1 + i=2 + p=1 - while true; do - _domain=$(printf "%s" "$fulldomain" | cut -d . -f $i-100) + while true; do + _domain=$(printf "%s" "$fulldomain" | cut -d . -f $i-100) - _debug _domain "$_domain" - if [ -z "$_domain" ]; then - # not valid - return 1 - fi + _debug _domain "$_domain" + if [ -z "$_domain" ]; then + # not valid + return 1 + fi - if ! _servercow_api GET "$_domain"; then - return 1 - fi + if ! _servercow_api GET "$_domain"; then + return 1 + fi - if ! _contains "$response" '"error":"no such domain in user context"' > /dev/null; then - _sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-$p) - if [ -z "$_sub_domain" ]; then - # not valid - return 1 - fi + if ! _contains "$response" '"error":"no such domain in user context"' > /dev/null; then + _sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-$p) + if [ -z "$_sub_domain" ]; then + # not valid + return 1 + fi - return 0 - fi + return 0 + fi - p=$i - i=$(_math "$i" + 1) - done; + p=$i + i=$(_math "$i" + 1) + done; - return 1 + return 1 } _servercow_api() { - method=$1 - domain=$2 - data="$3" + method=$1 + domain=$2 + data="$3" - export _H1="Content-Type: application/json" - export _H2="X-Auth-Username: $SERVERCOW_API_Username" - export _H3="X-Auth-Password: $SERVERCOW_API_Password" + export _H1="Content-Type: application/json" + export _H2="X-Auth-Username: $SERVERCOW_API_Username" + export _H3="X-Auth-Password: $SERVERCOW_API_Password" - if [ "$method" != "GET" ]; then - _debug data "$data" - response="$(_post "$data" "$SERVERCOW_API/$domain" "" "$method")" - else - response="$(_get "$SERVERCOW_API/$domain")" - fi + if [ "$method" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$SERVERCOW_API/$domain" "" "$method")" + else + response="$(_get "$SERVERCOW_API/$domain")" + fi - if [ "$?" != "0" ]; then - _err "error $domain" - return 1 - fi - _debug2 response "$response" - return 0 + if [ "$?" != "0" ]; then + _err "error $domain" + return 1 + fi + _debug2 response "$response" + return 0 } From 8101aceab5dad0ac83c8446380d814d77f44fecf Mon Sep 17 00:00:00 2001 From: Jens Date: Sat, 9 Dec 2017 20:18:05 +0100 Subject: [PATCH 64/65] Update dns_servercow.sh fixed remaining issues from shellcheck --- dnsapi/dns_servercow.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_servercow.sh b/dnsapi/dns_servercow.sh index 3ffc393..872ae58 100755 --- a/dnsapi/dns_servercow.sh +++ b/dnsapi/dns_servercow.sh @@ -50,7 +50,7 @@ dns_servercow_add() { _debug _domain "$_domain" if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then - if printf -- "%s" "$response" | grep "ok" > /dev/null; then + if printf -- "%s" "$response" | grep "ok" >/dev/null; then _info "Added, OK" return 0 else @@ -92,8 +92,8 @@ dns_servercow_rm() { _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - if _servercow_api DELETE "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\"}"; then - if printf -- "%s" "$response" | grep "ok" > /dev/null; then + if _servercow_api DELETE "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\"}"; then + if printf -- "%s" "$response" | grep "ok" >/dev/null; then _info "Deleted, OK" _contains "$response" '"message":"ok"' else @@ -140,7 +140,7 @@ _get_root() { p=$i i=$(_math "$i" + 1) - done; + done return 1 } From a95ccc7e4cecd7fa92144dc8af7bca5ffccb107a Mon Sep 17 00:00:00 2001 From: Jens Date: Sat, 9 Dec 2017 20:22:09 +0100 Subject: [PATCH 65/65] Update dns_servercow.sh ... didn't see this line in spellcheck ... :S --- dnsapi/dns_servercow.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_servercow.sh b/dnsapi/dns_servercow.sh index 872ae58..be4e59d 100755 --- a/dnsapi/dns_servercow.sh +++ b/dnsapi/dns_servercow.sh @@ -128,7 +128,7 @@ _get_root() { return 1 fi - if ! _contains "$response" '"error":"no such domain in user context"' > /dev/null; then + if ! _contains "$response" '"error":"no such domain in user context"' >/dev/null; then _sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-$p) if [ -z "$_sub_domain" ]; then # not valid