From 0ec9b9823f3ff32108bab78f5e2b5f1c0750adf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20L=C3=BCscher?= Date: Tue, 22 Nov 2016 00:24:26 +0100 Subject: [PATCH 01/29] Add DNS API for cyon.ch --- dnsapi/dns_cyon.sh | 355 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 355 insertions(+) create mode 100644 dnsapi/dns_cyon.sh diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh new file mode 100644 index 00000000..95e690bb --- /dev/null +++ b/dnsapi/dns_cyon.sh @@ -0,0 +1,355 @@ +#!/usr/bin/env sh + +######## +# Custom cyon.ch DNS API for use with [acme.sh](https://github.com/Neilpang/acme.sh) +# +# Usage: acme.sh --issue --dns dns_cyon -d www.domain.com +# +# Dependencies: +# ------------- +# - jq (get it here: https://stedolan.github.io/jq/download) +# - oathtool (When using 2 Factor Authentication) +# +# Author: Armando Lüscher +######## + +######## +# Define cyon.ch login credentials: +# +# Either set them here: (uncomment these lines) +# +# cyon_username='your_cyon_username' +# cyon_password='your_cyon_password' +# cyon_otp_secret='your_otp_secret' # Only required if using 2FA +# +# ...or export them as environment variables in your shell: +# +# $ export cyon_username='your_cyon_username' +# $ export cyon_password='your_cyon_password' +# $ export cyon_otp_secret='your_otp_secret' # Only required if using 2FA +# +# *Note:* +# After the first run, the credentials are saved in the "account.conf" +# file, so any hard-coded or environment variables can then be removed. +######## + +dns_cyon_add() { + if ! _exists jq; then + _fail "Please install jq to use cyon.ch DNS API." + fi + + _load_credentials + _load_parameters "$@" + + _info_header "add" + _login + _domain_env + _add_txt + _cleanup + + return 0 +} + +dns_cyon_rm() { + _load_credentials + _load_parameters "$@" + + _info_header "delete" + _login + _domain_env + _delete_txt + _cleanup + + return 0 +} + +######################### +### PRIVATE FUNCTIONS ### +######################### + +_load_credentials() { + # Convert loaded password to/from base64 as needed. + if [ "${cyon_password_b64}" ] ; then + cyon_password="$(echo "${cyon_password_b64}" | _dbase64)" + elif [ "${cyon_password}" ] ; then + cyon_password_b64="$(echo "${cyon_password}" | _base64)" + fi + + if [ -z "${cyon_username}" ] || [ -z "${cyon_password}" ] ; then + _err "" + _err "You haven't set your cyon.ch login credentials yet." + _err "Please set the required cyon environment variables." + _err "" + exit 1 + fi + + # Save the login credentials to the account.conf file. + _debug "Save credentials to account.conf" + _saveaccountconf cyon_username "${cyon_username}" + _saveaccountconf cyon_password_b64 "$cyon_password_b64" + if [ ! -z "${cyon_otp_secret}" ] ; then + _saveaccountconf cyon_otp_secret "$cyon_otp_secret" + fi +} + +_is_idn() { + _idn_temp=$(printf "%s" "$1" | tr -d "[0-9a-zA-Z.,-]") + _idn_temp2="$(printf "%s" "$1" | grep -o "xn--")" + [ "$_idn_temp" ] || [ "$_idn_temp2" ] +} + +_load_parameters() { + # Read the required parameters to add the TXT entry. + fulldomain="$(echo "$1" | tr '[:upper:]' '[:lower:]')" + fulldomain_idn="${fulldomain}" + + # Special case for IDNs, as cyon needs a domain environment change, + # which uses the "pretty" instead of the punycode version. + if _is_idn "$1" ; then + if ! _exists idn; then + _fail "Please install idn to process IDN names." + fi + + fulldomain="$(idn -u "${fulldomain}")" + fulldomain_idn="$(idn -a "${fulldomain}")" + fi + + _debug fulldomain "$fulldomain" + _debug fulldomain_idn "$fulldomain_idn" + + txtvalue="$2" + _debug txtvalue "$txtvalue" + + # Cookiejar required for login session, as cyon.ch has no official API (yet). + cookiejar=$(tempfile) + _debug cookiejar "$cookiejar" +} + +_info_header() { + if [ "$1" = "add" ]; then + _info "" + _info "+---------------------------------------------+" + _info "| Adding DNS TXT entry to your cyon.ch domain |" + _info "+---------------------------------------------+" + _info "" + _info " * Full Domain: ${fulldomain}" + _info " * TXT Value: ${txtvalue}" + _info " * Cookie Jar: ${cookiejar}" + _info "" + elif [ "$1" = "delete" ]; then + _info "" + _info "+-------------------------------------------------+" + _info "| Deleting DNS TXT entry from your cyon.ch domain |" + _info "+-------------------------------------------------+" + _info "" + _info " * Full Domain: ${fulldomain}" + _info " * Cookie Jar: ${cookiejar}" + _info "" + fi +} + +_login() { + _info " - Logging in..." + login_response=$(curl \ + "https://my.cyon.ch/auth/index/dologin-async" \ + -s \ + -c "${cookiejar}" \ + -H "X-Requested-With: XMLHttpRequest" \ + --data-urlencode "username=${cyon_username}" \ + --data-urlencode "password=${cyon_password}" \ + --data-urlencode "pathname=/") + + _debug login_response "${login_response}" + + # Bail if login fails. + if [ "$(echo "${login_response}" | jq -r '.onSuccess')" != "success" ]; then + _fail " $(echo "${login_response}" | jq -r '.message')" + fi + + _info " success" + + + # NECESSARY!! Load the main page after login, before the OTP check. + curl "https://my.cyon.ch/" -s --compressed -b "${cookiejar}" >/dev/null + + + # todo: instead of just checking if the env variable is defined, check if we actually need to do a 2FA auth request. + + + # 2FA authentication with OTP? + if [ ! -z "${cyon_otp_secret}" ] ; then + _info " - Authorising with OTP code..." + + if ! _exists oathtool; then + _fail "Please install oathtool to use 2 Factor Authentication." + fi + + # Get OTP code with the defined secret. + otp_code=$(oathtool --base32 --totp "${cyon_otp_secret}" 2>/dev/null) + + otp_response=$(curl \ + "https://my.cyon.ch/auth/multi-factor/domultifactorauth-async" \ + -s \ + --compressed \ + -b "${cookiejar}" \ + -c "${cookiejar}" \ + -H "X-Requested-With: XMLHttpRequest" \ + -d "totpcode=${otp_code}&pathname=%2F&rememberme=0") + + _debug otp_response "${otp_response}" + + # Bail if OTP authentication fails. + if [ "$(echo "${otp_response}" | jq -r '.onSuccess')" != "success" ]; then + _fail " $(echo "${otp_response}" | jq -r '.message')" + fi + + _info " success" + fi + + _info "" +} + +_domain_env() { + _info " - Changing domain environment..." + + # Get the "example.com" part of the full domain name. + domain_env=$(echo "${fulldomain}" | sed -E -e 's/.*\.(.*\..*)$/\1/') + _debug "Changing domain environment to ${domain_env}" + + domain_env_response=$(curl \ + "https://my.cyon.ch/user/environment/setdomain/d/${domain_env}/gik/domain%3A${domain_env}" \ + -s \ + --compressed \ + -b "${cookiejar}" \ + -H "X-Requested-With: XMLHttpRequest") + + _debug domain_env_response "${domain_env_response}" + + _check_2fa_miss "${domain_env_response}" + + domain_env_success=$(echo "${domain_env_response}" | jq -r '.authenticated') + + # Bail if domain environment change fails. + if [ "${domain_env_success}" != "true" ]; then + _fail " $(echo "${domain_env_response}" | jq -r '.message')" + fi + + _info " success" + _info "" +} + +_add_txt() { + _info " - Adding DNS TXT entry..." + addtxt_response=$(curl \ + "https://my.cyon.ch/domain/dnseditor/add-record-async" \ + -s \ + --compressed \ + -b "${cookiejar}" \ + -H "X-Requested-With: XMLHttpRequest" \ + -d "zone=${fulldomain_idn}.&ttl=900&type=TXT&value=${txtvalue}") + + _debug addtxt_response "${addtxt_response}" + + _check_2fa_miss "${addtxt_response}" + + addtxt_message=$(echo "${addtxt_response}" | jq -r '.message') + addtxt_status=$(echo "${addtxt_response}" | jq -r '.status') + + # Bail if adding TXT entry fails. + if [ "${addtxt_status}" != "true" ]; then + if [ "${addtxt_status}" = "null" ]; then + addtxt_message=$(echo "${addtxt_response}" | jq -r '.error.message') + fi + _fail " ${addtxt_message}" + fi + + _info " success" + _info "" +} + +_delete_txt() { + _info " - Deleting DNS TXT entry..." + + list_txt_response=$(curl \ + "https://my.cyon.ch/domain/dnseditor/list-async" \ + -s \ + -b "${cookiejar}" \ + --compressed \ + -H "X-Requested-With: XMLHttpRequest") + + _debug list_txt_response "${list_txt_response}" + + _check_2fa_miss "${list_txt_response}" + + # Find and delete all acme challenge entries for the $fulldomain. + _dns_entries=$(echo "$list_txt_response" | jq -r --arg fulldomain_idn "${fulldomain_idn}." ' + .rows[] | + label $out| + if .[0] != $fulldomain_idn then + break $out + else + .[4]| + capture("data-hash=\"(?[^\"]*)\" data-identifier=\"(?[^\"]*)\"";"g")| + .hash + " " + .identifier + end') + _dns_entries_cnt=$(echo "${_dns_entries}" | wc -l | grep -o '\d') + + _info " (entries found: ${_dns_entries_cnt})" + + _dns_entry_num=0 + + echo "${_dns_entries}" | while read -r _hash _identifier + do + ((_dns_entry_num++)) + + delete_txt_response=$(curl \ + "https://my.cyon.ch/domain/dnseditor/delete-record-async" \ + -s \ + --compressed \ + -b "${cookiejar}" \ + -H "X-Requested-With: XMLHttpRequest" \ + --data-urlencode "hash=${_hash}" \ + --data-urlencode "identifier=${_identifier}") + + _debug delete_txt_response "${delete_txt_response}" + + _check_2fa_miss "${delete_txt_response}" + + delete_txt_message=$(echo "${delete_txt_response}" | jq -r '.message') + delete_txt_status=$(echo "${delete_txt_response}" | jq -r '.status') + + # Skip if deleting TXT entry fails. + if [ "${delete_txt_status}" != "true" ]; then + if [ "${delete_txt_status}" = "null" ]; then + delete_txt_message=$(echo "${delete_txt_response}" | jq -r '.error.message') + fi + _err " [${_dns_entry_num}/${_dns_entries_cnt}] ${delete_txt_message} (${_identifier})" + else + _info " [${_dns_entry_num}/${_dns_entries_cnt}] success (${_identifier})" + fi + done + + _info " done" + _info "" +} + +_check_2fa_miss() { + # Did we miss the 2FA? + if [[ "$1" =~ "multi_factor_form" ]] ; then + _fail " Missed OTP authentication!" + fi +} + +_fail() { + _err "$1" + _err "" + _cleanup + exit 1 +} + +_cleanup() { + _info " - Cleanup." + _debug "Remove cookie jar: ${cookiejar}" + rm "${cookiejar}" 2>/dev/null + _info "" +} From c90fa3bcfc71f298cdbb1f2207df981ffc126c79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20L=C3=BCscher?= Date: Tue, 22 Nov 2016 00:45:56 +0100 Subject: [PATCH 02/29] Fix problems found by travis. --- dnsapi/dns_cyon.sh | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index 95e690bb..3ebd3099 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -69,13 +69,16 @@ dns_cyon_rm() { _load_credentials() { # Convert loaded password to/from base64 as needed. - if [ "${cyon_password_b64}" ] ; then + if [ "${cyon_password_b64}" ]; then cyon_password="$(echo "${cyon_password_b64}" | _dbase64)" - elif [ "${cyon_password}" ] ; then + elif [ "${cyon_password}" ]; then cyon_password_b64="$(echo "${cyon_password}" | _base64)" fi - if [ -z "${cyon_username}" ] || [ -z "${cyon_password}" ] ; then + if [ -z "${cyon_username}" ] || [ -z "${cyon_password}" ]; then + cyon_username="" + cyon_password="" + cyon_otp_secret="" _err "" _err "You haven't set your cyon.ch login credentials yet." _err "Please set the required cyon environment variables." @@ -87,7 +90,7 @@ _load_credentials() { _debug "Save credentials to account.conf" _saveaccountconf cyon_username "${cyon_username}" _saveaccountconf cyon_password_b64 "$cyon_password_b64" - if [ ! -z "${cyon_otp_secret}" ] ; then + if [ ! -z "${cyon_otp_secret}" ]; then _saveaccountconf cyon_otp_secret "$cyon_otp_secret" fi } @@ -105,7 +108,7 @@ _load_parameters() { # Special case for IDNs, as cyon needs a domain environment change, # which uses the "pretty" instead of the punycode version. - if _is_idn "$1" ; then + if _is_idn "$1"; then if ! _exists idn; then _fail "Please install idn to process IDN names." fi @@ -168,16 +171,13 @@ _login() { _info " success" - # NECESSARY!! Load the main page after login, before the OTP check. curl "https://my.cyon.ch/" -s --compressed -b "${cookiejar}" >/dev/null - # todo: instead of just checking if the env variable is defined, check if we actually need to do a 2FA auth request. - # 2FA authentication with OTP? - if [ ! -z "${cyon_otp_secret}" ] ; then + if [ ! -z "${cyon_otp_secret}" ]; then _info " - Authorising with OTP code..." if ! _exists oathtool; then @@ -298,9 +298,8 @@ _delete_txt() { _dns_entry_num=0 - echo "${_dns_entries}" | while read -r _hash _identifier - do - ((_dns_entry_num++)) + echo "${_dns_entries}" | while read -r _hash _identifier; do + _dns_entry_num=$((_dns_entry_num + 1)) delete_txt_response=$(curl \ "https://my.cyon.ch/domain/dnseditor/delete-record-async" \ @@ -335,7 +334,7 @@ _delete_txt() { _check_2fa_miss() { # Did we miss the 2FA? - if [[ "$1" =~ "multi_factor_form" ]] ; then + if test "${1#*multi_factor_form}" != "$1"; then _fail " Missed OTP authentication!" fi } From 0085e6f83bbf78bffd8f34681be6e6d6865a19a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20L=C3=BCscher?= Date: Tue, 22 Nov 2016 15:21:04 +0100 Subject: [PATCH 03/29] Don't use jq to fetch list of DNS entries to be deleted. --- dnsapi/dns_cyon.sh | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index 3ebd3099..605585e6 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -275,31 +275,23 @@ _delete_txt() { -s \ -b "${cookiejar}" \ --compressed \ - -H "X-Requested-With: XMLHttpRequest") + -H "X-Requested-With: XMLHttpRequest" | \ + sed -e 's/data-hash/\\ndata-hash/g') _debug list_txt_response "${list_txt_response}" _check_2fa_miss "${list_txt_response}" # Find and delete all acme challenge entries for the $fulldomain. - _dns_entries=$(echo "$list_txt_response" | jq -r --arg fulldomain_idn "${fulldomain_idn}." ' - .rows[] | - label $out| - if .[0] != $fulldomain_idn then - break $out - else - .[4]| - capture("data-hash=\"(?[^\"]*)\" data-identifier=\"(?[^\"]*)\"";"g")| - .hash + " " + .identifier - end') - _dns_entries_cnt=$(echo "${_dns_entries}" | wc -l | grep -o '\d') - - _info " (entries found: ${_dns_entries_cnt})" - - _dns_entry_num=0 + _dns_entries=$(echo -e "$list_txt_response" | sed -n 's/data-hash=\\"\([^"]*\)\\" data-identifier=\\"\([^"]*\)\\".*/\1 \2/p') echo "${_dns_entries}" | while read -r _hash _identifier; do - _dns_entry_num=$((_dns_entry_num + 1)) + dns_type="$(echo "$_identifier" | cut -d'|' -f1)" + dns_domain="$(echo "$_identifier" | cut -d'|' -f2)" + + if [ "${dns_type}" != "TXT" ] || [ "${dns_domain}" != "${fulldomain_idn}." ]; then + continue + fi delete_txt_response=$(curl \ "https://my.cyon.ch/domain/dnseditor/delete-record-async" \ @@ -322,9 +314,9 @@ _delete_txt() { if [ "${delete_txt_status}" = "null" ]; then delete_txt_message=$(echo "${delete_txt_response}" | jq -r '.error.message') fi - _err " [${_dns_entry_num}/${_dns_entries_cnt}] ${delete_txt_message} (${_identifier})" + _err " ${delete_txt_message} (${_identifier})" else - _info " [${_dns_entry_num}/${_dns_entries_cnt}] success (${_identifier})" + _info " success (${_identifier})" fi done From e7ee3a7dd55dc505b0cfb959b15161fb35704272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20L=C3=BCscher?= Date: Tue, 22 Nov 2016 18:06:16 +0100 Subject: [PATCH 04/29] Remove jq completely to not require it as a dependency. --- dnsapi/dns_cyon.sh | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index 605585e6..af5a225b 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -7,7 +7,6 @@ # # Dependencies: # ------------- -# - jq (get it here: https://stedolan.github.io/jq/download) # - oathtool (When using 2 Factor Authentication) # # Author: Armando Lüscher @@ -34,10 +33,6 @@ ######## dns_cyon_add() { - if ! _exists jq; then - _fail "Please install jq to use cyon.ch DNS API." - fi - _load_credentials _load_parameters "$@" @@ -165,8 +160,8 @@ _login() { _debug login_response "${login_response}" # Bail if login fails. - if [ "$(echo "${login_response}" | jq -r '.onSuccess')" != "success" ]; then - _fail " $(echo "${login_response}" | jq -r '.message')" + if [ "$(echo "${login_response}" | _get_response_success)" != "success" ]; then + _fail " $(echo "${login_response}" | _get_response_message)" fi _info " success" @@ -199,8 +194,8 @@ _login() { _debug otp_response "${otp_response}" # Bail if OTP authentication fails. - if [ "$(echo "${otp_response}" | jq -r '.onSuccess')" != "success" ]; then - _fail " $(echo "${otp_response}" | jq -r '.message')" + if [ "$(echo "${otp_response}" | _get_response_success)" != "success" ]; then + _fail " $(echo "${otp_response}" | _get_response_message)" fi _info " success" @@ -227,11 +222,11 @@ _domain_env() { _check_2fa_miss "${domain_env_response}" - domain_env_success=$(echo "${domain_env_response}" | jq -r '.authenticated') + domain_env_success=$(echo "${domain_env_response}" | _egrep_o '"authenticated":\w*' | cut -d : -f 2) # Bail if domain environment change fails. if [ "${domain_env_success}" != "true" ]; then - _fail " $(echo "${domain_env_response}" | jq -r '.message')" + _fail " $(echo "${domain_env_response}" | _get_response_message)" fi _info " success" @@ -252,14 +247,11 @@ _add_txt() { _check_2fa_miss "${addtxt_response}" - addtxt_message=$(echo "${addtxt_response}" | jq -r '.message') - addtxt_status=$(echo "${addtxt_response}" | jq -r '.status') + addtxt_message=$(echo "${addtxt_response}" | _get_response_message) + addtxt_status=$(echo "${addtxt_response}" | _get_response_status) # Bail if adding TXT entry fails. if [ "${addtxt_status}" != "true" ]; then - if [ "${addtxt_status}" = "null" ]; then - addtxt_message=$(echo "${addtxt_response}" | jq -r '.error.message') - fi _fail " ${addtxt_message}" fi @@ -306,14 +298,11 @@ _delete_txt() { _check_2fa_miss "${delete_txt_response}" - delete_txt_message=$(echo "${delete_txt_response}" | jq -r '.message') - delete_txt_status=$(echo "${delete_txt_response}" | jq -r '.status') + delete_txt_message=$(echo "${delete_txt_response}" | _get_response_message) + delete_txt_status=$(echo "${delete_txt_response}" | _get_response_status) # Skip if deleting TXT entry fails. if [ "${delete_txt_status}" != "true" ]; then - if [ "${delete_txt_status}" = "null" ]; then - delete_txt_message=$(echo "${delete_txt_response}" | jq -r '.error.message') - fi _err " ${delete_txt_message} (${_identifier})" else _info " success (${_identifier})" @@ -324,6 +313,18 @@ _delete_txt() { _info "" } +_get_response_message() { + _egrep_o '"message":"[^"]*"' | cut -d : -f 2 | tr -d '"' +} + +_get_response_status() { + _egrep_o '"status":\w*' | cut -d : -f 2 +} + +_get_response_success() { + _egrep_o '"onSuccess":"[^"]*"' | cut -d : -f 2 | tr -d '"' +} + _check_2fa_miss() { # Did we miss the 2FA? if test "${1#*multi_factor_form}" != "$1"; then From 46b2ee3bae604619e3d191085581846853e25ad4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20L=C3=BCscher?= Date: Tue, 22 Nov 2016 18:31:38 +0100 Subject: [PATCH 05/29] Replace all echos with printf. --- dnsapi/dns_cyon.sh | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index af5a225b..28cb9e6e 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -65,9 +65,9 @@ dns_cyon_rm() { _load_credentials() { # Convert loaded password to/from base64 as needed. if [ "${cyon_password_b64}" ]; then - cyon_password="$(echo "${cyon_password_b64}" | _dbase64)" + cyon_password="$(printf "%s" "${cyon_password_b64}" | _dbase64)" elif [ "${cyon_password}" ]; then - cyon_password_b64="$(echo "${cyon_password}" | _base64)" + cyon_password_b64="$(printf "%s" "${cyon_password}" | _base64)" fi if [ -z "${cyon_username}" ] || [ -z "${cyon_password}" ]; then @@ -98,7 +98,7 @@ _is_idn() { _load_parameters() { # Read the required parameters to add the TXT entry. - fulldomain="$(echo "$1" | tr '[:upper:]' '[:lower:]')" + fulldomain="$(printf "%s" "$1" | tr '[:upper:]' '[:lower:]')" fulldomain_idn="${fulldomain}" # Special case for IDNs, as cyon needs a domain environment change, @@ -160,8 +160,8 @@ _login() { _debug login_response "${login_response}" # Bail if login fails. - if [ "$(echo "${login_response}" | _get_response_success)" != "success" ]; then - _fail " $(echo "${login_response}" | _get_response_message)" + if [ "$(printf "%s" "${login_response}" | _get_response_success)" != "success" ]; then + _fail " $(printf "%s" "${login_response}" | _get_response_message)" fi _info " success" @@ -194,8 +194,8 @@ _login() { _debug otp_response "${otp_response}" # Bail if OTP authentication fails. - if [ "$(echo "${otp_response}" | _get_response_success)" != "success" ]; then - _fail " $(echo "${otp_response}" | _get_response_message)" + if [ "$(printf "%s" "${otp_response}" | _get_response_success)" != "success" ]; then + _fail " $(printf "%s" "${otp_response}" | _get_response_message)" fi _info " success" @@ -208,7 +208,7 @@ _domain_env() { _info " - Changing domain environment..." # Get the "example.com" part of the full domain name. - domain_env=$(echo "${fulldomain}" | sed -E -e 's/.*\.(.*\..*)$/\1/') + domain_env=$(printf "%s" "${fulldomain}" | sed -E -e 's/.*\.(.*\..*)$/\1/') _debug "Changing domain environment to ${domain_env}" domain_env_response=$(curl \ @@ -222,11 +222,11 @@ _domain_env() { _check_2fa_miss "${domain_env_response}" - domain_env_success=$(echo "${domain_env_response}" | _egrep_o '"authenticated":\w*' | cut -d : -f 2) + domain_env_success=$(printf "%s" "${domain_env_response}" | _egrep_o '"authenticated":\w*' | cut -d : -f 2) # Bail if domain environment change fails. if [ "${domain_env_success}" != "true" ]; then - _fail " $(echo "${domain_env_response}" | _get_response_message)" + _fail " $(printf "%s" "${domain_env_response}" | _get_response_message)" fi _info " success" @@ -247,8 +247,8 @@ _add_txt() { _check_2fa_miss "${addtxt_response}" - addtxt_message=$(echo "${addtxt_response}" | _get_response_message) - addtxt_status=$(echo "${addtxt_response}" | _get_response_status) + addtxt_message=$(printf "%s" "${addtxt_response}" | _get_response_message) + addtxt_status=$(printf "%s" "${addtxt_response}" | _get_response_status) # Bail if adding TXT entry fails. if [ "${addtxt_status}" != "true" ]; then @@ -267,19 +267,19 @@ _delete_txt() { -s \ -b "${cookiejar}" \ --compressed \ - -H "X-Requested-With: XMLHttpRequest" | \ - sed -e 's/data-hash/\\ndata-hash/g') + -H "X-Requested-With: XMLHttpRequest" \ + | sed -e 's/data-hash/\\ndata-hash/g') _debug list_txt_response "${list_txt_response}" _check_2fa_miss "${list_txt_response}" # Find and delete all acme challenge entries for the $fulldomain. - _dns_entries=$(echo -e "$list_txt_response" | sed -n 's/data-hash=\\"\([^"]*\)\\" data-identifier=\\"\([^"]*\)\\".*/\1 \2/p') + _dns_entries=$(printf "%s" "$list_txt_response" | sed -n 's/data-hash=\\"\([^"]*\)\\" data-identifier=\\"\([^"]*\)\\".*/\1 \2/p') - echo "${_dns_entries}" | while read -r _hash _identifier; do - dns_type="$(echo "$_identifier" | cut -d'|' -f1)" - dns_domain="$(echo "$_identifier" | cut -d'|' -f2)" + printf "%s" "${_dns_entries}" | while read -r _hash _identifier; do + dns_type="$(printf "%s" "$_identifier" | cut -d'|' -f1)" + dns_domain="$(printf "%s" "$_identifier" | cut -d'|' -f2)" if [ "${dns_type}" != "TXT" ] || [ "${dns_domain}" != "${fulldomain_idn}." ]; then continue @@ -298,8 +298,8 @@ _delete_txt() { _check_2fa_miss "${delete_txt_response}" - delete_txt_message=$(echo "${delete_txt_response}" | _get_response_message) - delete_txt_status=$(echo "${delete_txt_response}" | _get_response_status) + delete_txt_message=$(printf "%s" "${delete_txt_response}" | _get_response_message) + delete_txt_status=$(printf "%s" "${delete_txt_response}" | _get_response_status) # Skip if deleting TXT entry fails. if [ "${delete_txt_status}" != "true" ]; then From 2698ef6c5f7795703c49c49e8225d6e99e94dc6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20L=C3=BCscher?= Date: Wed, 23 Nov 2016 11:16:51 +0100 Subject: [PATCH 06/29] Return instead of exit. Clear OTP secret if environment variable is set to empty. This is for when the 2FA is disabled. Rename `_is_idn` function to `_is_idn_cyon`. Remove usage of curl (except for URL encoding of data). Instead of cleaning up the cookie jar, get rid of it completely and logout of cyon instead. --- dnsapi/dns_cyon.sh | 242 ++++++++++++++++++++++----------------------- 1 file changed, 118 insertions(+), 124 deletions(-) diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index 28cb9e6e..05079351 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -33,29 +33,23 @@ ######## dns_cyon_add() { - _load_credentials - _load_parameters "$@" - - _info_header "add" - _login - _domain_env - _add_txt - _cleanup - - return 0 + _load_credentials \ + && _load_parameters "$@" \ + && _info_header "add" \ + && _login \ + && _domain_env \ + && _add_txt \ + && _logout } dns_cyon_rm() { - _load_credentials - _load_parameters "$@" - - _info_header "delete" - _login - _domain_env - _delete_txt - _cleanup - - return 0 + _load_credentials \ + && _load_parameters "$@" \ + && _info_header "delete" \ + && _login \ + && _domain_env \ + && _delete_txt \ + && _logout } ######################### @@ -65,20 +59,22 @@ dns_cyon_rm() { _load_credentials() { # Convert loaded password to/from base64 as needed. if [ "${cyon_password_b64}" ]; then - cyon_password="$(printf "%s" "${cyon_password_b64}" | _dbase64)" + cyon_password="$(printf "%s" "${cyon_password_b64}" | _dbase64 "multiline")" elif [ "${cyon_password}" ]; then cyon_password_b64="$(printf "%s" "${cyon_password}" | _base64)" fi if [ -z "${cyon_username}" ] || [ -z "${cyon_password}" ]; then + # Dummy entries to satify script checker. cyon_username="" cyon_password="" cyon_otp_secret="" + _err "" _err "You haven't set your cyon.ch login credentials yet." _err "Please set the required cyon environment variables." _err "" - exit 1 + return 1 fi # Save the login credentials to the account.conf file. @@ -87,44 +83,52 @@ _load_credentials() { _saveaccountconf cyon_password_b64 "$cyon_password_b64" if [ ! -z "${cyon_otp_secret}" ]; then _saveaccountconf cyon_otp_secret "$cyon_otp_secret" + else + _clearaccountconf cyon_otp_secret fi } -_is_idn() { - _idn_temp=$(printf "%s" "$1" | tr -d "[0-9a-zA-Z.,-]") - _idn_temp2="$(printf "%s" "$1" | grep -o "xn--")" +_is_idn_cyon() { + _idn_temp="$(printf "%s" "${1}" | tr -d "[0-9a-zA-Z.,-_]")" + _idn_temp2="$(printf "%s" "${1}" | grep -o "xn--")" [ "$_idn_temp" ] || [ "$_idn_temp2" ] } +# comment on https://stackoverflow.com/a/10797966 +_urlencode_cyon() { + curl -Gso /dev/null -w %{url_effective} --data-urlencode @- "" | cut -c 3- +} + _load_parameters() { # Read the required parameters to add the TXT entry. - fulldomain="$(printf "%s" "$1" | tr '[:upper:]' '[:lower:]')" + fulldomain="$(printf "%s" "${1}" | tr '[:upper:]' '[:lower:]')" fulldomain_idn="${fulldomain}" # Special case for IDNs, as cyon needs a domain environment change, # which uses the "pretty" instead of the punycode version. - if _is_idn "$1"; then + if _is_idn_cyon "${fulldomain}"; then if ! _exists idn; then - _fail "Please install idn to process IDN names." + _err "Please install idn to process IDN names." + _err "" + return 1 fi fulldomain="$(idn -u "${fulldomain}")" fulldomain_idn="$(idn -a "${fulldomain}")" fi - _debug fulldomain "$fulldomain" - _debug fulldomain_idn "$fulldomain_idn" + _debug fulldomain "${fulldomain}" + _debug fulldomain_idn "${fulldomain_idn}" - txtvalue="$2" - _debug txtvalue "$txtvalue" + txtvalue="${2}" + _debug txtvalue "${txtvalue}" - # Cookiejar required for login session, as cyon.ch has no official API (yet). - cookiejar=$(tempfile) - _debug cookiejar "$cookiejar" + # This header is required for curl calls. + _H1="X-Requested-With: XMLHttpRequest" } _info_header() { - if [ "$1" = "add" ]; then + if [ "${1}" = "add" ]; then _info "" _info "+---------------------------------------------+" _info "| Adding DNS TXT entry to your cyon.ch domain |" @@ -132,42 +136,46 @@ _info_header() { _info "" _info " * Full Domain: ${fulldomain}" _info " * TXT Value: ${txtvalue}" - _info " * Cookie Jar: ${cookiejar}" _info "" - elif [ "$1" = "delete" ]; then + elif [ "${1}" = "delete" ]; then _info "" _info "+-------------------------------------------------+" _info "| Deleting DNS TXT entry from your cyon.ch domain |" _info "+-------------------------------------------------+" _info "" _info " * Full Domain: ${fulldomain}" - _info " * Cookie Jar: ${cookiejar}" _info "" fi } +_get_cookie_header() { + printf "%s" "$(sed -n 's/Set-\(Cookie:.*cyon=[^;]*\).*/\1/p' "$HTTP_HEADER" | _tail_n 1)" +} + _login() { _info " - Logging in..." - login_response=$(curl \ - "https://my.cyon.ch/auth/index/dologin-async" \ - -s \ - -c "${cookiejar}" \ - -H "X-Requested-With: XMLHttpRequest" \ - --data-urlencode "username=${cyon_username}" \ - --data-urlencode "password=${cyon_password}" \ - --data-urlencode "pathname=/") + username_encoded="$(printf "%s" "${cyon_username}" | _urlencode_cyon)" + password_encoded="$(printf "%s" "${cyon_password}" | _urlencode_cyon)" + + login_url="https://my.cyon.ch/auth/index/dologin-async" + login_data="$(printf "%s" "username=${username_encoded}&password=${password_encoded}&pathname=%2F")" + + login_response="$(_post "$login_data" "$login_url")" _debug login_response "${login_response}" # Bail if login fails. if [ "$(printf "%s" "${login_response}" | _get_response_success)" != "success" ]; then - _fail " $(printf "%s" "${login_response}" | _get_response_message)" + _err " $(printf "%s" "${login_response}" | _get_response_message)" + _err "" + return 1 fi _info " success" - # NECESSARY!! Load the main page after login, before the OTP check. - curl "https://my.cyon.ch/" -s --compressed -b "${cookiejar}" >/dev/null + # NECESSARY!! Load the main page after login, to get the new cookie. + _H2="$(_get_cookie_header)" + _get "https://my.cyon.ch/" > /dev/null # todo: instead of just checking if the env variable is defined, check if we actually need to do a 2FA auth request. @@ -176,26 +184,25 @@ _login() { _info " - Authorising with OTP code..." if ! _exists oathtool; then - _fail "Please install oathtool to use 2 Factor Authentication." + _err "Please install oathtool to use 2 Factor Authentication." + _err "" + return 1 fi # Get OTP code with the defined secret. - otp_code=$(oathtool --base32 --totp "${cyon_otp_secret}" 2>/dev/null) + otp_code="$(oathtool --base32 --totp "${cyon_otp_secret}" 2>/dev/null)" - otp_response=$(curl \ - "https://my.cyon.ch/auth/multi-factor/domultifactorauth-async" \ - -s \ - --compressed \ - -b "${cookiejar}" \ - -c "${cookiejar}" \ - -H "X-Requested-With: XMLHttpRequest" \ - -d "totpcode=${otp_code}&pathname=%2F&rememberme=0") + login_otp_url="https://my.cyon.ch/auth/multi-factor/domultifactorauth-async" + login_otp_data="totpcode=${otp_code}&pathname=%2F&rememberme=0" - _debug otp_response "${otp_response}" + login_otp_response="$(_post "$login_otp_data" "$login_otp_url")" + _debug login_otp_response "${login_otp_response}" # Bail if OTP authentication fails. - if [ "$(printf "%s" "${otp_response}" | _get_response_success)" != "success" ]; then - _fail " $(printf "%s" "${otp_response}" | _get_response_message)" + if [ "$(printf "%s" "${login_otp_response}" | _get_response_success)" != "success" ]; then + _err " $(printf "%s" "${login_otp_response}" | _get_response_message)" + _err "" + return 1 fi _info " success" @@ -204,29 +211,36 @@ _login() { _info "" } +_logout() { + _info " - Logging out..." + + _get "https://my.cyon.ch/auth/index/dologout" > /dev/null + + _info " success" + _info "" +} + _domain_env() { _info " - Changing domain environment..." # Get the "example.com" part of the full domain name. - domain_env=$(printf "%s" "${fulldomain}" | sed -E -e 's/.*\.(.*\..*)$/\1/') + domain_env="$(printf "%s" "${fulldomain}" | sed -E -e 's/.*\.(.*\..*)$/\1/')" _debug "Changing domain environment to ${domain_env}" - domain_env_response=$(curl \ - "https://my.cyon.ch/user/environment/setdomain/d/${domain_env}/gik/domain%3A${domain_env}" \ - -s \ - --compressed \ - -b "${cookiejar}" \ - -H "X-Requested-With: XMLHttpRequest") + domain_env_url="https://my.cyon.ch/user/environment/setdomain/d/${domain_env}/gik/domain%3A${domain_env}" + domain_env_response="$(_get "${domain_env_url}")" _debug domain_env_response "${domain_env_response}" - _check_2fa_miss "${domain_env_response}" + if ! _check_if_2fa_missed "${domain_env_response}"; then return 1; fi - domain_env_success=$(printf "%s" "${domain_env_response}" | _egrep_o '"authenticated":\w*' | cut -d : -f 2) + domain_env_success="$(printf "%s" "${domain_env_response}" | _egrep_o '"authenticated":\w*' | cut -d : -f 2)" # Bail if domain environment change fails. if [ "${domain_env_success}" != "true" ]; then - _fail " $(printf "%s" "${domain_env_response}" | _get_response_message)" + _err " $(printf "%s" "${domain_env_response}" | _get_response_message)" + _err "" + return 1 fi _info " success" @@ -235,47 +249,41 @@ _domain_env() { _add_txt() { _info " - Adding DNS TXT entry..." - addtxt_response=$(curl \ - "https://my.cyon.ch/domain/dnseditor/add-record-async" \ - -s \ - --compressed \ - -b "${cookiejar}" \ - -H "X-Requested-With: XMLHttpRequest" \ - -d "zone=${fulldomain_idn}.&ttl=900&type=TXT&value=${txtvalue}") - _debug addtxt_response "${addtxt_response}" + add_txt_url="https://my.cyon.ch/domain/dnseditor/add-record-async" + add_txt_data="zone=${fulldomain_idn}.&ttl=900&type=TXT&value=${txtvalue}" - _check_2fa_miss "${addtxt_response}" + add_txt_response="$(_post "$add_txt_data" "$add_txt_url")" + _debug add_txt_response "${add_txt_response}" - addtxt_message=$(printf "%s" "${addtxt_response}" | _get_response_message) - addtxt_status=$(printf "%s" "${addtxt_response}" | _get_response_status) + if ! _check_if_2fa_missed "${add_txt_response}"; then return 1; fi + + add_txt_message="$(printf "%s" "${add_txt_response}" | _get_response_message)" + add_txt_status="$(printf "%s" "${add_txt_response}" | _get_response_status)" # Bail if adding TXT entry fails. - if [ "${addtxt_status}" != "true" ]; then - _fail " ${addtxt_message}" + if [ "${add_txt_status}" != "true" ]; then + _err " ${add_txt_message}" + _err "" + return 1 fi - _info " success" + _info " success (TXT|${fulldomain_idn}.|${txtvalue})" _info "" } _delete_txt() { _info " - Deleting DNS TXT entry..." - list_txt_response=$(curl \ - "https://my.cyon.ch/domain/dnseditor/list-async" \ - -s \ - -b "${cookiejar}" \ - --compressed \ - -H "X-Requested-With: XMLHttpRequest" \ - | sed -e 's/data-hash/\\ndata-hash/g') + list_txt_url="https://my.cyon.ch/domain/dnseditor/list-async" + list_txt_response="$(_get "${list_txt_url}" | sed -e 's/data-hash/\\ndata-hash/g')" _debug list_txt_response "${list_txt_response}" - _check_2fa_miss "${list_txt_response}" + if ! _check_if_2fa_missed "${list_txt_response}"; then return 1; fi # Find and delete all acme challenge entries for the $fulldomain. - _dns_entries=$(printf "%s" "$list_txt_response" | sed -n 's/data-hash=\\"\([^"]*\)\\" data-identifier=\\"\([^"]*\)\\".*/\1 \2/p') + _dns_entries="$(printf "%b\n" "${list_txt_response}" | sed -n 's/data-hash=\\"\([^"]*\)\\" data-identifier=\\"\([^"]*\)\\".*/\1 \2/p')" printf "%s" "${_dns_entries}" | while read -r _hash _identifier; do dns_type="$(printf "%s" "$_identifier" | cut -d'|' -f1)" @@ -285,21 +293,19 @@ _delete_txt() { continue fi - delete_txt_response=$(curl \ - "https://my.cyon.ch/domain/dnseditor/delete-record-async" \ - -s \ - --compressed \ - -b "${cookiejar}" \ - -H "X-Requested-With: XMLHttpRequest" \ - --data-urlencode "hash=${_hash}" \ - --data-urlencode "identifier=${_identifier}") + hash_encoded="$(printf "%s" "${_hash}" | _urlencode_cyon)" + identifier_encoded="$(printf "%s" "${_identifier}" | _urlencode_cyon)" + delete_txt_url="https://my.cyon.ch/domain/dnseditor/delete-record-async" + delete_txt_data="$(printf "%s" "hash=${hash_encoded}&identifier=${identifier_encoded}")" + + delete_txt_response="$(_post "$delete_txt_data" "$delete_txt_url")" _debug delete_txt_response "${delete_txt_response}" - _check_2fa_miss "${delete_txt_response}" + if ! _check_if_2fa_missed "${delete_txt_response}"; then return 1; fi - delete_txt_message=$(printf "%s" "${delete_txt_response}" | _get_response_message) - delete_txt_status=$(printf "%s" "${delete_txt_response}" | _get_response_status) + delete_txt_message="$(printf "%s" "${delete_txt_response}" | _get_response_message)" + delete_txt_status="$(printf "%s" "${delete_txt_response}" | _get_response_status)" # Skip if deleting TXT entry fails. if [ "${delete_txt_status}" != "true" ]; then @@ -325,23 +331,11 @@ _get_response_success() { _egrep_o '"onSuccess":"[^"]*"' | cut -d : -f 2 | tr -d '"' } -_check_2fa_miss() { +_check_if_2fa_missed() { # Did we miss the 2FA? - if test "${1#*multi_factor_form}" != "$1"; then - _fail " Missed OTP authentication!" + if test "${1#*multi_factor_form}" != "${1}"; then + _err " Missed OTP authentication!" + _err "" + return 1 fi } - -_fail() { - _err "$1" - _err "" - _cleanup - exit 1 -} - -_cleanup() { - _info " - Cleanup." - _debug "Remove cookie jar: ${cookiejar}" - rm "${cookiejar}" 2>/dev/null - _info "" -} From 98b3dcbf37fd462609b92e72080542e4b01b48c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20L=C3=BCscher?= Date: Fri, 16 Dec 2016 03:44:48 +0100 Subject: [PATCH 07/29] Prefix all private functions with `_cyon`. Satisfy shellcheck. --- dnsapi/dns_cyon.sh | 106 ++++++++++++++++++++++----------------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index 05079351..3a441aaf 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -33,30 +33,30 @@ ######## dns_cyon_add() { - _load_credentials \ - && _load_parameters "$@" \ - && _info_header "add" \ - && _login \ - && _domain_env \ - && _add_txt \ - && _logout + _cyon_load_credentials \ + && _cyon_load_parameters "$@" \ + && _cyon_print_header "add" \ + && _cyon_login \ + && _cyon_change_domain_env \ + && _cyon_add_txt \ + && _cyon_logout } dns_cyon_rm() { - _load_credentials \ - && _load_parameters "$@" \ - && _info_header "delete" \ - && _login \ - && _domain_env \ - && _delete_txt \ - && _logout + _cyon_load_credentials \ + && _cyon_load_parameters "$@" \ + && _cyon_print_header "delete" \ + && _cyon_login \ + && _cyon_change_domain_env \ + && _cyon_delete_txt \ + && _cyon_logout } ######################### ### PRIVATE FUNCTIONS ### ######################### -_load_credentials() { +_cyon_load_credentials() { # Convert loaded password to/from base64 as needed. if [ "${cyon_password_b64}" ]; then cyon_password="$(printf "%s" "${cyon_password_b64}" | _dbase64 "multiline")" @@ -88,25 +88,25 @@ _load_credentials() { fi } -_is_idn_cyon() { +_cyon_is_idn() { _idn_temp="$(printf "%s" "${1}" | tr -d "[0-9a-zA-Z.,-_]")" _idn_temp2="$(printf "%s" "${1}" | grep -o "xn--")" [ "$_idn_temp" ] || [ "$_idn_temp2" ] } # comment on https://stackoverflow.com/a/10797966 -_urlencode_cyon() { - curl -Gso /dev/null -w %{url_effective} --data-urlencode @- "" | cut -c 3- +_cyon_urlencode() { + curl -Gso /dev/null -w "%{url_effective}" --data-urlencode @- "" | cut -c 3- } -_load_parameters() { +_cyon_load_parameters() { # Read the required parameters to add the TXT entry. fulldomain="$(printf "%s" "${1}" | tr '[:upper:]' '[:lower:]')" fulldomain_idn="${fulldomain}" # Special case for IDNs, as cyon needs a domain environment change, # which uses the "pretty" instead of the punycode version. - if _is_idn_cyon "${fulldomain}"; then + if _cyon_is_idn "${fulldomain}"; then if ! _exists idn; then _err "Please install idn to process IDN names." _err "" @@ -127,7 +127,7 @@ _load_parameters() { _H1="X-Requested-With: XMLHttpRequest" } -_info_header() { +_cyon_print_header() { if [ "${1}" = "add" ]; then _info "" _info "+---------------------------------------------+" @@ -148,15 +148,15 @@ _info_header() { fi } -_get_cookie_header() { +_cyon_get_cookie_header() { printf "%s" "$(sed -n 's/Set-\(Cookie:.*cyon=[^;]*\).*/\1/p' "$HTTP_HEADER" | _tail_n 1)" } -_login() { +_cyon_login() { _info " - Logging in..." - username_encoded="$(printf "%s" "${cyon_username}" | _urlencode_cyon)" - password_encoded="$(printf "%s" "${cyon_password}" | _urlencode_cyon)" + username_encoded="$(printf "%s" "${cyon_username}" | _cyon_urlencode)" + password_encoded="$(printf "%s" "${cyon_password}" | _cyon_urlencode)" login_url="https://my.cyon.ch/auth/index/dologin-async" login_data="$(printf "%s" "username=${username_encoded}&password=${password_encoded}&pathname=%2F")" @@ -165,8 +165,8 @@ _login() { _debug login_response "${login_response}" # Bail if login fails. - if [ "$(printf "%s" "${login_response}" | _get_response_success)" != "success" ]; then - _err " $(printf "%s" "${login_response}" | _get_response_message)" + if [ "$(printf "%s" "${login_response}" | _cyon_get_response_success)" != "success" ]; then + _err " $(printf "%s" "${login_response}" | _cyon_get_response_message)" _err "" return 1 fi @@ -174,8 +174,8 @@ _login() { _info " success" # NECESSARY!! Load the main page after login, to get the new cookie. - _H2="$(_get_cookie_header)" - _get "https://my.cyon.ch/" > /dev/null + _H2="$(_cyon_get_cookie_header)" + _get "https://my.cyon.ch/" >/dev/null # todo: instead of just checking if the env variable is defined, check if we actually need to do a 2FA auth request. @@ -199,8 +199,8 @@ _login() { _debug login_otp_response "${login_otp_response}" # Bail if OTP authentication fails. - if [ "$(printf "%s" "${login_otp_response}" | _get_response_success)" != "success" ]; then - _err " $(printf "%s" "${login_otp_response}" | _get_response_message)" + if [ "$(printf "%s" "${login_otp_response}" | _cyon_get_response_success)" != "success" ]; then + _err " $(printf "%s" "${login_otp_response}" | _cyon_get_response_message)" _err "" return 1 fi @@ -211,16 +211,16 @@ _login() { _info "" } -_logout() { +_cyon_logout() { _info " - Logging out..." - _get "https://my.cyon.ch/auth/index/dologout" > /dev/null + _get "https://my.cyon.ch/auth/index/dologout" >/dev/null _info " success" _info "" } -_domain_env() { +_cyon_change_domain_env() { _info " - Changing domain environment..." # Get the "example.com" part of the full domain name. @@ -232,13 +232,13 @@ _domain_env() { domain_env_response="$(_get "${domain_env_url}")" _debug domain_env_response "${domain_env_response}" - if ! _check_if_2fa_missed "${domain_env_response}"; then return 1; fi + if ! _cyon_check_if_2fa_missed "${domain_env_response}"; then return 1; fi domain_env_success="$(printf "%s" "${domain_env_response}" | _egrep_o '"authenticated":\w*' | cut -d : -f 2)" # Bail if domain environment change fails. if [ "${domain_env_success}" != "true" ]; then - _err " $(printf "%s" "${domain_env_response}" | _get_response_message)" + _err " $(printf "%s" "${domain_env_response}" | _cyon_get_response_message)" _err "" return 1 fi @@ -247,7 +247,7 @@ _domain_env() { _info "" } -_add_txt() { +_cyon_add_txt() { _info " - Adding DNS TXT entry..." add_txt_url="https://my.cyon.ch/domain/dnseditor/add-record-async" @@ -256,10 +256,10 @@ _add_txt() { add_txt_response="$(_post "$add_txt_data" "$add_txt_url")" _debug add_txt_response "${add_txt_response}" - if ! _check_if_2fa_missed "${add_txt_response}"; then return 1; fi + if ! _cyon_check_if_2fa_missed "${add_txt_response}"; then return 1; fi - add_txt_message="$(printf "%s" "${add_txt_response}" | _get_response_message)" - add_txt_status="$(printf "%s" "${add_txt_response}" | _get_response_status)" + add_txt_message="$(printf "%s" "${add_txt_response}" | _cyon_get_response_message)" + add_txt_status="$(printf "%s" "${add_txt_response}" | _cyon_get_response_status)" # Bail if adding TXT entry fails. if [ "${add_txt_status}" != "true" ]; then @@ -272,7 +272,7 @@ _add_txt() { _info "" } -_delete_txt() { +_cyon_delete_txt() { _info " - Deleting DNS TXT entry..." list_txt_url="https://my.cyon.ch/domain/dnseditor/list-async" @@ -280,7 +280,7 @@ _delete_txt() { list_txt_response="$(_get "${list_txt_url}" | sed -e 's/data-hash/\\ndata-hash/g')" _debug list_txt_response "${list_txt_response}" - if ! _check_if_2fa_missed "${list_txt_response}"; then return 1; fi + if ! _cyon_check_if_2fa_missed "${list_txt_response}"; then return 1; fi # Find and delete all acme challenge entries for the $fulldomain. _dns_entries="$(printf "%b\n" "${list_txt_response}" | sed -n 's/data-hash=\\"\([^"]*\)\\" data-identifier=\\"\([^"]*\)\\".*/\1 \2/p')" @@ -293,8 +293,8 @@ _delete_txt() { continue fi - hash_encoded="$(printf "%s" "${_hash}" | _urlencode_cyon)" - identifier_encoded="$(printf "%s" "${_identifier}" | _urlencode_cyon)" + hash_encoded="$(printf "%s" "${_hash}" | _cyon_urlencode)" + identifier_encoded="$(printf "%s" "${_identifier}" | _cyon_urlencode)" delete_txt_url="https://my.cyon.ch/domain/dnseditor/delete-record-async" delete_txt_data="$(printf "%s" "hash=${hash_encoded}&identifier=${identifier_encoded}")" @@ -302,10 +302,10 @@ _delete_txt() { delete_txt_response="$(_post "$delete_txt_data" "$delete_txt_url")" _debug delete_txt_response "${delete_txt_response}" - if ! _check_if_2fa_missed "${delete_txt_response}"; then return 1; fi + if ! _cyon_check_if_2fa_missed "${delete_txt_response}"; then return 1; fi - delete_txt_message="$(printf "%s" "${delete_txt_response}" | _get_response_message)" - delete_txt_status="$(printf "%s" "${delete_txt_response}" | _get_response_status)" + delete_txt_message="$(printf "%s" "${delete_txt_response}" | _cyon_get_response_message)" + delete_txt_status="$(printf "%s" "${delete_txt_response}" | _cyon_get_response_status)" # Skip if deleting TXT entry fails. if [ "${delete_txt_status}" != "true" ]; then @@ -319,23 +319,23 @@ _delete_txt() { _info "" } -_get_response_message() { +_cyon_get_response_message() { _egrep_o '"message":"[^"]*"' | cut -d : -f 2 | tr -d '"' } -_get_response_status() { +_cyon_get_response_status() { _egrep_o '"status":\w*' | cut -d : -f 2 } -_get_response_success() { +_cyon_get_response_success() { _egrep_o '"onSuccess":"[^"]*"' | cut -d : -f 2 | tr -d '"' } -_check_if_2fa_missed() { +_cyon_check_if_2fa_missed() { # Did we miss the 2FA? if test "${1#*multi_factor_form}" != "${1}"; then _err " Missed OTP authentication!" - _err "" - return 1 + _err "" + return 1 fi } From edfefb6763e6e2ecc523aac762e4db4d247bf72f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20L=C3=BCscher?= Date: Tue, 27 Dec 2016 00:56:05 +0100 Subject: [PATCH 08/29] Add usage instructions and repo link to post issues. --- README.md | 1 + dnsapi/README.md | 18 ++++++++++++++++++ dnsapi/dns_cyon.sh | 25 +++++-------------------- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index f1c74806..5f82effb 100644 --- a/README.md +++ b/README.md @@ -272,6 +272,7 @@ You don't have to do anything manually! 1. Alwaysdata.com API 1. Linode.com API 1. FreeDNS (https://freedns.afraid.org/) +1. cyon.ch **More APIs coming soon...** diff --git a/dnsapi/README.md b/dnsapi/README.md index 6a86bf4c..70af17e7 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -305,6 +305,24 @@ Note that you cannot use acme.sh automatic DNS validation for FreeDNS public dom you create under a FreeDNS public domain. You must own the top level domain in order to automaitcally validate with acme.sh at FreeDNS. +## 16. Use cyon.ch + +You only need to set your cyon.ch login credentials. +If you also have 2 Factor Authentication (OTP) enabled, you need to set your secret token too and have `oathtool` installed. + +``` +export cyon_username="your_cyon_username" +export cyon_password="your_cyon_password" +export cyon_otp_secret="your_otp_secret" # Only required if using 2FA +``` + +To issue a cert: +``` +acme.sh --issue --dns dns_cyon -d example.com -d www.example.com +``` + +The `cyon_username`, `cyon_password` and `cyon_otp_secret` 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_cyon.sh b/dnsapi/dns_cyon.sh index 3a441aaf..6c9c5c5d 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -9,29 +9,14 @@ # ------------- # - oathtool (When using 2 Factor Authentication) # +# Issues: +# ------- +# Any issues / questions / suggestions can be posted here: +# https://github.com/noplanman/cyon-api/issues +# # Author: Armando Lüscher ######## -######## -# Define cyon.ch login credentials: -# -# Either set them here: (uncomment these lines) -# -# cyon_username='your_cyon_username' -# cyon_password='your_cyon_password' -# cyon_otp_secret='your_otp_secret' # Only required if using 2FA -# -# ...or export them as environment variables in your shell: -# -# $ export cyon_username='your_cyon_username' -# $ export cyon_password='your_cyon_password' -# $ export cyon_otp_secret='your_otp_secret' # Only required if using 2FA -# -# *Note:* -# After the first run, the credentials are saved in the "account.conf" -# file, so any hard-coded or environment variables can then be removed. -######## - dns_cyon_add() { _cyon_load_credentials \ && _cyon_load_parameters "$@" \ From 09eccf6fc075c8f39ff0ec9ee1d7d20aa9826b0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20L=C3=BCscher?= Date: Wed, 28 Dec 2016 13:37:24 +0100 Subject: [PATCH 09/29] Use more flexible version of uppercase to lowercase conversion. --- dnsapi/dns_cyon.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index 6c9c5c5d..ab8a38e5 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -86,7 +86,7 @@ _cyon_urlencode() { _cyon_load_parameters() { # Read the required parameters to add the TXT entry. - fulldomain="$(printf "%s" "${1}" | tr '[:upper:]' '[:lower:]')" + fulldomain="$(printf "%s" "${1}" | tr '[A-Z]' '[a-z]')" fulldomain_idn="${fulldomain}" # Special case for IDNs, as cyon needs a domain environment change, From afa3fc8bf921209476329cf9ebc6f58415dc0907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20L=C3=BCscher?= Date: Wed, 28 Dec 2016 14:51:39 +0100 Subject: [PATCH 10/29] Adapt to use general naming rule for account variables. --- dnsapi/README.md | 8 ++++---- dnsapi/dns_cyon.sh | 34 +++++++++++++++++----------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/dnsapi/README.md b/dnsapi/README.md index 70af17e7..fd88d579 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -311,9 +311,9 @@ You only need to set your cyon.ch login credentials. If you also have 2 Factor Authentication (OTP) enabled, you need to set your secret token too and have `oathtool` installed. ``` -export cyon_username="your_cyon_username" -export cyon_password="your_cyon_password" -export cyon_otp_secret="your_otp_secret" # Only required if using 2FA +export CY_Username="your_cyon_username" +export CY_Password="your_cyon_password" +export CY_OTP_Secret="your_otp_secret" # Only required if using 2FA ``` To issue a cert: @@ -321,7 +321,7 @@ To issue a cert: acme.sh --issue --dns dns_cyon -d example.com -d www.example.com ``` -The `cyon_username`, `cyon_password` and `cyon_otp_secret` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. +The `CY_Username`, `CY_Password` and `CY_OTP_Secret` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. # Use custom API diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index ab8a38e5..ca952db4 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -43,17 +43,17 @@ dns_cyon_rm() { _cyon_load_credentials() { # Convert loaded password to/from base64 as needed. - if [ "${cyon_password_b64}" ]; then - cyon_password="$(printf "%s" "${cyon_password_b64}" | _dbase64 "multiline")" - elif [ "${cyon_password}" ]; then - cyon_password_b64="$(printf "%s" "${cyon_password}" | _base64)" + if [ "${CY_Password_B64}" ]; then + CY_Password="$(printf "%s" "${CY_Password_B64}" | _dbase64 "multiline")" + elif [ "${CY_Password}" ]; then + CY_Password_B64="$(printf "%s" "${CY_Password}" | _base64)" fi - if [ -z "${cyon_username}" ] || [ -z "${cyon_password}" ]; then + if [ -z "${CY_Username}" ] || [ -z "${CY_Password}" ]; then # Dummy entries to satify script checker. - cyon_username="" - cyon_password="" - cyon_otp_secret="" + CY_Username="" + CY_Password="" + CY_OTP_Secret="" _err "" _err "You haven't set your cyon.ch login credentials yet." @@ -64,12 +64,12 @@ _cyon_load_credentials() { # Save the login credentials to the account.conf file. _debug "Save credentials to account.conf" - _saveaccountconf cyon_username "${cyon_username}" - _saveaccountconf cyon_password_b64 "$cyon_password_b64" - if [ ! -z "${cyon_otp_secret}" ]; then - _saveaccountconf cyon_otp_secret "$cyon_otp_secret" + _saveaccountconf CY_Username "${CY_Username}" + _saveaccountconf CY_Password_B64 "$CY_Password_B64" + if [ ! -z "${CY_OTP_Secret}" ]; then + _saveaccountconf CY_OTP_Secret "$CY_OTP_Secret" else - _clearaccountconf cyon_otp_secret + _clearaccountconf CY_OTP_Secret fi } @@ -140,8 +140,8 @@ _cyon_get_cookie_header() { _cyon_login() { _info " - Logging in..." - username_encoded="$(printf "%s" "${cyon_username}" | _cyon_urlencode)" - password_encoded="$(printf "%s" "${cyon_password}" | _cyon_urlencode)" + username_encoded="$(printf "%s" "${CY_Username}" | _cyon_urlencode)" + password_encoded="$(printf "%s" "${CY_Password}" | _cyon_urlencode)" login_url="https://my.cyon.ch/auth/index/dologin-async" login_data="$(printf "%s" "username=${username_encoded}&password=${password_encoded}&pathname=%2F")" @@ -165,7 +165,7 @@ _cyon_login() { # todo: instead of just checking if the env variable is defined, check if we actually need to do a 2FA auth request. # 2FA authentication with OTP? - if [ ! -z "${cyon_otp_secret}" ]; then + if [ ! -z "${CY_OTP_Secret}" ]; then _info " - Authorising with OTP code..." if ! _exists oathtool; then @@ -175,7 +175,7 @@ _cyon_login() { fi # Get OTP code with the defined secret. - otp_code="$(oathtool --base32 --totp "${cyon_otp_secret}" 2>/dev/null)" + otp_code="$(oathtool --base32 --totp "${CY_OTP_Secret}" 2>/dev/null)" login_otp_url="https://my.cyon.ch/auth/multi-factor/domultifactorauth-async" login_otp_data="totpcode=${otp_code}&pathname=%2F&rememberme=0" From ce9fae82bd7a31c52514e5f0f7d6f6a0f5854117 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20L=C3=BCscher?= Date: Thu, 29 Dec 2016 16:12:42 +0100 Subject: [PATCH 11/29] Update cookie retrieval using _egrep_o (thanks @Neilpang) --- dnsapi/dns_cyon.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index ca952db4..0390592a 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -134,7 +134,7 @@ _cyon_print_header() { } _cyon_get_cookie_header() { - printf "%s" "$(sed -n 's/Set-\(Cookie:.*cyon=[^;]*\).*/\1/p' "$HTTP_HEADER" | _tail_n 1)" + printf "Cookie: %s" "$(cat "$HTTP_HEADER" | grep "cyon=" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'cyon=[^;]*;' | tr -d ';')" } _cyon_login() { From 6e8dcdce7834938db893f85955aef27e1d71ca9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20L=C3=BCscher?= Date: Wed, 4 Jan 2017 03:19:58 +0100 Subject: [PATCH 12/29] Satisfy shellcheck. --- dnsapi/dns_cyon.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index 0390592a..54162198 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -134,7 +134,7 @@ _cyon_print_header() { } _cyon_get_cookie_header() { - printf "Cookie: %s" "$(cat "$HTTP_HEADER" | grep "cyon=" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'cyon=[^;]*;' | tr -d ';')" + printf "Cookie: %s" "$(grep "cyon=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'cyon=[^;]*;' | tr -d ';')" } _cyon_login() { From 9499a1142bfdaf0c3fb9f729421fd8ae853705ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20L=C3=BCscher?= Date: Mon, 30 Jan 2017 16:36:49 +0100 Subject: [PATCH 13/29] Remove custom URL encoding and use library's implementation. --- dnsapi/dns_cyon.sh | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index 54162198..d225138b 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -79,11 +79,6 @@ _cyon_is_idn() { [ "$_idn_temp" ] || [ "$_idn_temp2" ] } -# comment on https://stackoverflow.com/a/10797966 -_cyon_urlencode() { - curl -Gso /dev/null -w "%{url_effective}" --data-urlencode @- "" | cut -c 3- -} - _cyon_load_parameters() { # Read the required parameters to add the TXT entry. fulldomain="$(printf "%s" "${1}" | tr '[A-Z]' '[a-z]')" @@ -140,8 +135,8 @@ _cyon_get_cookie_header() { _cyon_login() { _info " - Logging in..." - username_encoded="$(printf "%s" "${CY_Username}" | _cyon_urlencode)" - password_encoded="$(printf "%s" "${CY_Password}" | _cyon_urlencode)" + username_encoded="$(printf "%s" "${CY_Username}" | _url_encode)" + password_encoded="$(printf "%s" "${CY_Password}" | _url_encode)" login_url="https://my.cyon.ch/auth/index/dologin-async" login_data="$(printf "%s" "username=${username_encoded}&password=${password_encoded}&pathname=%2F")" @@ -278,8 +273,8 @@ _cyon_delete_txt() { continue fi - hash_encoded="$(printf "%s" "${_hash}" | _cyon_urlencode)" - identifier_encoded="$(printf "%s" "${_identifier}" | _cyon_urlencode)" + hash_encoded="$(printf "%s" "${_hash}" | _url_encode)" + identifier_encoded="$(printf "%s" "${_identifier}" | _url_encode)" delete_txt_url="https://my.cyon.ch/domain/dnseditor/delete-record-async" delete_txt_data="$(printf "%s" "hash=${hash_encoded}&identifier=${identifier_encoded}")" From 884f70fb399cd73c1004c9eb5c11a582e9e35c70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20L=C3=BCscher?= Date: Tue, 31 Jan 2017 15:23:40 +0100 Subject: [PATCH 14/29] Remove square brackets from ranges. Export curl header variables. --- dnsapi/dns_cyon.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index d225138b..85ff028c 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -74,14 +74,14 @@ _cyon_load_credentials() { } _cyon_is_idn() { - _idn_temp="$(printf "%s" "${1}" | tr -d "[0-9a-zA-Z.,-_]")" + _idn_temp="$(printf "%s" "${1}" | tr -d "0-9a-zA-Z.,-_")" _idn_temp2="$(printf "%s" "${1}" | grep -o "xn--")" [ "$_idn_temp" ] || [ "$_idn_temp2" ] } _cyon_load_parameters() { # Read the required parameters to add the TXT entry. - fulldomain="$(printf "%s" "${1}" | tr '[A-Z]' '[a-z]')" + fulldomain="$(printf "%s" "${1}" | tr "A-Z" "a-z")" fulldomain_idn="${fulldomain}" # Special case for IDNs, as cyon needs a domain environment change, @@ -105,6 +105,7 @@ _cyon_load_parameters() { # This header is required for curl calls. _H1="X-Requested-With: XMLHttpRequest" + export _H1 } _cyon_print_header() { @@ -155,6 +156,8 @@ _cyon_login() { # NECESSARY!! Load the main page after login, to get the new cookie. _H2="$(_cyon_get_cookie_header)" + export _H2 + _get "https://my.cyon.ch/" >/dev/null # todo: instead of just checking if the env variable is defined, check if we actually need to do a 2FA auth request. From 3e1418d662a3dc15a8359c2441397d63688d596e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20L=C3=BCscher?= Date: Sun, 12 Feb 2017 12:30:06 +0100 Subject: [PATCH 15/29] Use gloo item key for environment change, to support different account types. (this isn't working 100% yet, still looking for a solution) --- dnsapi/dns_cyon.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index 85ff028c..0ced4217 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -210,7 +210,10 @@ _cyon_change_domain_env() { domain_env="$(printf "%s" "${fulldomain}" | sed -E -e 's/.*\.(.*\..*)$/\1/')" _debug "Changing domain environment to ${domain_env}" - domain_env_url="https://my.cyon.ch/user/environment/setdomain/d/${domain_env}/gik/domain%3A${domain_env}" + gloo_item_key="$(_get "https://my.cyon.ch/domain/" | tr '\n' ' ' | sed -E -e "s/.*data-domain=\"${domain_env}\"[^<]*data-itemkey=\"([^\"]*).*/\1/")" + _debug gloo_item_key "${gloo_item_key}" + + domain_env_url="https://my.cyon.ch/user/environment/setdomain/d/${domain_env}/gik/${gloo_item_key}" domain_env_response="$(_get "${domain_env_url}")" _debug domain_env_response "${domain_env_response}" From 52765466c12aaeaff6d7c9c9eab1e18f8cb84042 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 19 Feb 2017 12:55:05 +0800 Subject: [PATCH 16/29] fix syslog doc --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index f4ee89c9..aa9d24b0 100755 --- a/acme.sh +++ b/acme.sh @@ -4596,7 +4596,7 @@ Parameters: --accountkeylength, -ak [2048] Specifies the account key length. --log [/path/to/logfile] Specifies the log file. The default is: \"$DEFAULT_LOG_FILE\" if you don't give a file path here. --log-level 1|2 Specifies the log level, default is 1. - --syslog [1|0] Enable/Disable syslog. + --syslog [0|3|6|7] Syslog level, 0: disable syslog, 3: error, 6: info, 7: debug. These parameters are to install the cert to nginx/apache or anyother server after issue/renew a cert: From e6e85b0c556a5458177fd2a4d31cf3d019d6f727 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 19 Feb 2017 13:24:00 +0800 Subject: [PATCH 17/29] secure debug message --- acme.sh | 68 ++++++++++++++++++++++++++++++++++++++++++- dnsapi/dns_aws.sh | 4 +-- dnsapi/dns_lexicon.sh | 8 ++--- dnsapi/dns_ovh.sh | 4 +-- 4 files changed, 75 insertions(+), 9 deletions(-) diff --git a/acme.sh b/acme.sh index aa9d24b0..a8b0790b 100755 --- a/acme.sh +++ b/acme.sh @@ -71,6 +71,8 @@ DEBUG_LEVEL_3=3 DEBUG_LEVEL_DEFAULT=$DEBUG_LEVEL_1 DEBUG_LEVEL_NONE=0 +HIDDEN_VALUE="[hidden](please add '--output-insecure' to see this value)" + SYSLOG_ERROR="user.error" SYSLOG_INFO="user.info" SYSLOG_DEBUG="user.debug" @@ -212,6 +214,27 @@ _debug() { fi } +#output the sensitive messages +_secure_debug() { + if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_1" ]; then + if [ "$OUTPUT_INSECURE" = "1" ]; then + _log "$@" + else + _log "$1" "$HIDDEN_VALUE" + fi + fi + if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG" ]; then + _syslog "$SYSLOG_DEBUG" "$1" "$HIDDEN_VALUE" + fi + if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_1" ]; then + if [ "$OUTPUT_INSECURE" = "1" ]; then + _printargs "$@" >&2 + else + _printargs "$1" "$HIDDEN_VALUE" >&2 + fi + fi +} + _debug2() { if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_2" ]; then _log "$@" @@ -224,6 +247,26 @@ _debug2() { fi } +_secure_debug2() { + if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_2" ]; then + if [ "$OUTPUT_INSECURE" = "1" ]; then + _log "$@" + else + _log "$1" "$HIDDEN_VALUE" + fi + fi + if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG_2" ]; then + _syslog "$SYSLOG_DEBUG" "$1" "$HIDDEN_VALUE" + fi + if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then + if [ "$OUTPUT_INSECURE" = "1" ]; then + _printargs "$@" >&2 + else + _printargs "$1" "$HIDDEN_VALUE" >&2 + fi + fi +} + _debug3() { if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_3" ]; then _log "$@" @@ -236,6 +279,26 @@ _debug3() { fi } +_secure_debug3() { + if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_3" ]; then + if [ "$OUTPUT_INSECURE" = "1" ]; then + _log "$@" + else + _log "$1" "$HIDDEN_VALUE" + fi + fi + if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG_3" ]; then + _syslog "$SYSLOG_DEBUG" "$1" "$HIDDEN_VALUE" + fi + if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_3" ]; then + if [ "$OUTPUT_INSECURE" = "1" ]; then + _printargs "$@" >&2 + else + _printargs "$1" "$HIDDEN_VALUE" >&2 + fi + fi +} + _startswith() { _str="$1" _sub="$2" @@ -4583,7 +4646,7 @@ Parameters: --force, -f Used to force to install or force to renew a cert immediately. --staging, --test Use staging server, just for test. --debug Output debug info. - + --output-insecure Output all the sensitive messages. By default all the credentials/sensitive messages are hidden from the output/debug/log for secure. --webroot, -w /path/to/webroot Specifies the web root folder for web root mode. --standalone Use standalone mode. --stateless Use stateless mode, see: $_STATELESS_WIKI @@ -4877,6 +4940,9 @@ _process() { shift fi ;; + --output-insecure) + export OUTPUT_INSECURE=1 + ;; --webroot | -w) wvalue="$2" if [ -z "$_webroot" ]; then diff --git a/dnsapi/dns_aws.sh b/dnsapi/dns_aws.sh index 29d7a2cd..84aa28d3 100755 --- a/dnsapi/dns_aws.sh +++ b/dnsapi/dns_aws.sh @@ -181,10 +181,10 @@ aws_rest() { #kSecret="wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY" ############################ - _debug2 kSecret "$kSecret" + _secure_debug2 kSecret "$kSecret" kSecretH="$(printf "%s" "$kSecret" | _hex_dump | tr -d " ")" - _debug2 kSecretH "$kSecretH" + _secure_debug2 kSecretH "$kSecretH" kDateH="$(printf "$RequestDateOnly%s" | _hmac "$Hash" "$kSecretH" hex)" _debug2 kDateH "$kDateH" diff --git a/dnsapi/dns_lexicon.sh b/dnsapi/dns_lexicon.sh index c38ff3e3..c09f16fd 100755 --- a/dnsapi/dns_lexicon.sh +++ b/dnsapi/dns_lexicon.sh @@ -34,7 +34,7 @@ dns_lexicon_add() { # shellcheck disable=SC2018,SC2019 Lx_name=$(echo LEXICON_"${PROVIDER}"_USERNAME | tr 'a-z' 'A-Z') Lx_name_v=$(eval echo \$"$Lx_name") - _debug "$Lx_name" "$Lx_name_v" + _secure_debug "$Lx_name" "$Lx_name_v" if [ "$Lx_name_v" ]; then _saveaccountconf "$Lx_name" "$Lx_name_v" eval export "$Lx_name" @@ -43,7 +43,7 @@ dns_lexicon_add() { # shellcheck disable=SC2018,SC2019 Lx_token=$(echo LEXICON_"${PROVIDER}"_TOKEN | tr 'a-z' 'A-Z') Lx_token_v=$(eval echo \$"$Lx_token") - _debug "$Lx_token" "$Lx_token_v" + _secure_debug "$Lx_token" "$Lx_token_v" if [ "$Lx_token_v" ]; then _saveaccountconf "$Lx_token" "$Lx_token_v" eval export "$Lx_token" @@ -52,7 +52,7 @@ dns_lexicon_add() { # shellcheck disable=SC2018,SC2019 Lx_password=$(echo LEXICON_"${PROVIDER}"_PASSWORD | tr 'a-z' 'A-Z') Lx_password_v=$(eval echo \$"$Lx_password") - _debug "$Lx_password" "$Lx_password_v" + _secure_debug "$Lx_password" "$Lx_password_v" if [ "$Lx_password_v" ]; then _saveaccountconf "$Lx_password" "$Lx_password_v" eval export "$Lx_password" @@ -61,7 +61,7 @@ dns_lexicon_add() { # shellcheck disable=SC2018,SC2019 Lx_domaintoken=$(echo LEXICON_"${PROVIDER}"_DOMAINTOKEN | tr 'a-z' 'A-Z') Lx_domaintoken_v=$(eval echo \$"$Lx_domaintoken") - _debug "$Lx_domaintoken" "$Lx_domaintoken_v" + _secure_debug "$Lx_domaintoken" "$Lx_domaintoken_v" if [ "$Lx_domaintoken_v" ]; then eval export "$Lx_domaintoken" _saveaccountconf "$Lx_domaintoken" "$Lx_domaintoken_v" diff --git a/dnsapi/dns_ovh.sh b/dnsapi/dns_ovh.sh index 8833c0a1..faf5b42b 100755 --- a/dnsapi/dns_ovh.sh +++ b/dnsapi/dns_ovh.sh @@ -207,7 +207,7 @@ _ovh_authentication() { _err "Unable to get consumerKey" return 1 fi - _debug consumerKey "$consumerKey" + _secure_debug consumerKey "$consumerKey" OVH_CK="$consumerKey" _saveaccountconf OVH_CK "$OVH_CK" @@ -269,7 +269,7 @@ _ovh_rest() { _ovh_t="$(_ovh_timestamp)" _debug2 _ovh_t "$_ovh_t" _ovh_p="$OVH_AS+$OVH_CK+$m+$_ovh_url+$data+$_ovh_t" - _debug _ovh_p "$_ovh_p" + _secure_debug _ovh_p "$_ovh_p" _ovh_hex="$(printf "%s" "$_ovh_p" | _digest sha1 hex)" _debug2 _ovh_hex "$_ovh_hex" From 43d3b51bdee418732e54d0779da491e9369b836f Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 19 Feb 2017 18:16:12 +0800 Subject: [PATCH 18/29] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2624690a..716abe20 100644 --- a/README.md +++ b/README.md @@ -403,6 +403,6 @@ Please Star and Fork me. # Donate -1. PayPal: donate@acme.sh - +1. PayPal/Alipay(支付宝)/Wechat(微信): [https://donate.acme.sh/](https://donate.acme.sh/) + [Donate List](https://github.com/Neilpang/acme.sh/wiki/Donate-list) From cb6f62295748a415c55316cb90865a2f3a9bc9e9 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 19 Feb 2017 18:19:24 +0800 Subject: [PATCH 19/29] Update README.md --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 716abe20..a297b998 100644 --- a/README.md +++ b/README.md @@ -378,21 +378,21 @@ acme.sh --upgrade --auto-upgrade 0 https://github.com/Neilpang/acme.sh/wiki/Issue-a-cert-from-existing-CSR -# Under the Hood +# 14. Under the Hood Speak ACME language using shell, directly to "Let's Encrypt". TODO: -# Acknowledgments +# 15. Acknowledgments 1. Acme-tiny: https://github.com/diafygi/acme-tiny 2. ACME protocol: https://github.com/ietf-wg-acme/acme 3. Certbot: https://github.com/certbot/certbot -# License & Others +# 16. License & Others License is GPLv3 @@ -401,7 +401,8 @@ Please Star and Fork me. [Issues](https://github.com/Neilpang/acme.sh/issues) and [pull requests](https://github.com/Neilpang/acme.sh/pulls) are welcome. -# Donate +# 17. Donate +Your donation makes **acme.sh** better: 1. PayPal/Alipay(支付宝)/Wechat(微信): [https://donate.acme.sh/](https://donate.acme.sh/) From 93bce1b24cd1f3af6740ed6a8070a2cd176f8201 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 19 Feb 2017 20:15:00 +0800 Subject: [PATCH 20/29] support multiple deploy hook fix https://github.com/Neilpang/acme.sh/issues/508 --- acme.sh | 90 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 52 insertions(+), 38 deletions(-) diff --git a/acme.sh b/acme.sh index a8b0790b..2086ccc2 100755 --- a/acme.sh +++ b/acme.sh @@ -3693,7 +3693,7 @@ renew() { fi if [ "$Le_DeployHook" ]; then - deploy "$Le_Domain" "$Le_DeployHook" "$Le_Keylength" + _deploy "$Le_Domain" "$Le_DeployHook" res="$?" fi @@ -3865,54 +3865,64 @@ list() { } +_deploy() { + _d="$1" + _hooks="$2" + + for _d_api in $(echo "$_hooks" | tr ',' " "); do + _deployApi="$(_findHook "$_d" deploy "$_d_api")" + if [ -z "$_deployApi" ]; then + _err "The deploy hook $_d_api is not found." + return 1 + fi + _debug _deployApi "$_deployApi" + + if ! ( + if ! . "$_deployApi"; then + _err "Load file $_deployApi error. Please check your api file and try again." + return 1 + fi + + d_command="${_d_api}_deploy" + if ! _exists "$d_command"; then + _err "It seems that your api file is not correct, it must have a function named: $d_command" + return 1 + fi + + if ! $d_command "$_d" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$CERT_FULLCHAIN_PATH"; then + _err "Error deploy for domain:$_d" + return 1 + fi + ); then + _err "Deploy error." + return 1 + else + _info "$(__green Success)" + fi + done +} + +#domain hooks deploy() { - Le_Domain="$1" - Le_DeployHook="$2" + _d="$1" + _hooks="$2" _isEcc="$3" - if [ -z "$Le_DeployHook" ]; then + if [ -z "$_hooks" ]; then _usage "Usage: $PROJECT_ENTRY --deploy -d domain.com --deploy-hook cpanel [--ecc] " return 1 fi - _initpath "$Le_Domain" "$_isEcc" + _initpath "$_d" "$_isEcc" if [ ! -d "$DOMAIN_PATH" ]; then - _err "Domain is not valid:'$Le_Domain'" + _err "Domain is not valid:'$_d'" return 1 fi - _deployApi="$(_findHook "$Le_Domain" deploy "$Le_DeployHook")" - if [ -z "$_deployApi" ]; then - _err "The deploy hook $Le_DeployHook is not found." - return 1 - fi - _debug _deployApi "$_deployApi" + . "$DOMAIN_CONF" - _savedomainconf Le_DeployHook "$Le_DeployHook" - - if ! ( - if ! . "$_deployApi"; then - _err "Load file $_deployApi error. Please check your api file and try again." - return 1 - fi - - d_command="${Le_DeployHook}_deploy" - if ! _exists "$d_command"; then - _err "It seems that your api file is not correct, it must have a function named: $d_command" - return 1 - fi - - if ! $d_command "$Le_Domain" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$CERT_FULLCHAIN_PATH"; then - _err "Error deploy for domain:$Le_Domain" - _on_issue_err - return 1 - fi - ); then - _err "Deploy error." - return 1 - else - _info "$(__green Success)" - fi + _savedomainconf Le_DeployHook "$_hooks" + _deploy "$_d" "$_hooks" } installcert() { @@ -5136,7 +5146,11 @@ _process() { shift ;; --deploy-hook) - _deploy_hook="$2" + if [ -z "$2" ] || _startswith "$2" "-"; then + _usage "Please specify a value for '--deploy-hook'" + return 1 + fi + _deploy_hook="$_deploy_hook$2," shift ;; --ocsp-must-staple | --ocsp) From a6d2e3a1e6b34c1fbf0675401672b76e8925809b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20L=C3=BCscher?= Date: Sun, 19 Feb 2017 13:26:32 +0100 Subject: [PATCH 21/29] Suppress shellcheck warnings. --- dnsapi/dns_cyon.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index 0ced4217..c096d8b0 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -81,6 +81,7 @@ _cyon_is_idn() { _cyon_load_parameters() { # Read the required parameters to add the TXT entry. + # shellcheck disable=SC2018,SC2019 fulldomain="$(printf "%s" "${1}" | tr "A-Z" "a-z")" fulldomain_idn="${fulldomain}" From 3a1bd3114b3c965d9718ee5bb039ced856136a65 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 19 Feb 2017 20:35:32 +0800 Subject: [PATCH 22/29] add hooks, not implemented yet. --- deploy/apache.sh | 26 ++++++++++++++++++++++++++ deploy/dovecot.sh | 26 ++++++++++++++++++++++++++ deploy/exim4.sh | 26 ++++++++++++++++++++++++++ deploy/haproxy.sh | 26 ++++++++++++++++++++++++++ deploy/mysqld.sh | 26 ++++++++++++++++++++++++++ deploy/nginx.sh | 26 ++++++++++++++++++++++++++ deploy/opensshd.sh | 26 ++++++++++++++++++++++++++ deploy/pureftpd.sh | 26 ++++++++++++++++++++++++++ deploy/vsftpd.sh | 26 ++++++++++++++++++++++++++ 9 files changed, 234 insertions(+) create mode 100644 deploy/apache.sh create mode 100644 deploy/dovecot.sh create mode 100644 deploy/exim4.sh create mode 100644 deploy/haproxy.sh create mode 100644 deploy/mysqld.sh create mode 100644 deploy/nginx.sh create mode 100644 deploy/opensshd.sh create mode 100644 deploy/pureftpd.sh create mode 100644 deploy/vsftpd.sh diff --git a/deploy/apache.sh b/deploy/apache.sh new file mode 100644 index 00000000..42de93f4 --- /dev/null +++ b/deploy/apache.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env sh + +#Here is a script to deploy cert to dovecot server. + +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +apache_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" + + _err "Deploy cert to apache server, Not implemented yet" + return 1 + +} diff --git a/deploy/dovecot.sh b/deploy/dovecot.sh new file mode 100644 index 00000000..99a17d51 --- /dev/null +++ b/deploy/dovecot.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env sh + +#Here is a script to deploy cert to dovecot server. + +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +dovecot_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" + + _err "Not implemented yet" + return 1 + +} diff --git a/deploy/exim4.sh b/deploy/exim4.sh new file mode 100644 index 00000000..cc53e344 --- /dev/null +++ b/deploy/exim4.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env sh + +#Here is a script to deploy cert to exim4 server. + +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +exim4_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" + + _err "deploy cert to exim4 server, Not implemented yet" + return 1 + +} diff --git a/deploy/haproxy.sh b/deploy/haproxy.sh new file mode 100644 index 00000000..e7fa5b09 --- /dev/null +++ b/deploy/haproxy.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env sh + +#Here is a script to deploy cert to haproxy server. + +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +haproxy_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" + + _err "deploy cert to haproxy server, Not implemented yet" + return 1 + +} diff --git a/deploy/mysqld.sh b/deploy/mysqld.sh new file mode 100644 index 00000000..6fb178d7 --- /dev/null +++ b/deploy/mysqld.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env sh + +#Here is a script to deploy cert to mysqld server. + +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +mysqld_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" + + _err "deploy cert to mysqld server, Not implemented yet" + return 1 + +} diff --git a/deploy/nginx.sh b/deploy/nginx.sh new file mode 100644 index 00000000..2fb127fd --- /dev/null +++ b/deploy/nginx.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env sh + +#Here is a script to deploy cert to nginx server. + +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +nginx_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" + + _err "deploy cert to nginx server, Not implemented yet" + return 1 + +} diff --git a/deploy/opensshd.sh b/deploy/opensshd.sh new file mode 100644 index 00000000..01fbc3f1 --- /dev/null +++ b/deploy/opensshd.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env sh + +#Here is a script to deploy cert to opensshd server. + +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +opensshd_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" + + _err "deploy cert to opensshd server, Not implemented yet" + return 1 + +} diff --git a/deploy/pureftpd.sh b/deploy/pureftpd.sh new file mode 100644 index 00000000..28643204 --- /dev/null +++ b/deploy/pureftpd.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env sh + +#Here is a script to deploy cert to pureftpd server. + +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +pureftpd_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" + + _err "deploy cert to pureftpd server, Not implemented yet" + return 1 + +} diff --git a/deploy/vsftpd.sh b/deploy/vsftpd.sh new file mode 100644 index 00000000..7ff1a58a --- /dev/null +++ b/deploy/vsftpd.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env sh + +#Here is a script to deploy cert to vsftpd server. + +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +vsftpd_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" + + _err "deploy cert to vsftpd server, Not implemented yet" + return 1 + +} From f845b371ceb95c4712405704928d90813d67c591 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 19 Feb 2017 20:40:53 +0800 Subject: [PATCH 23/29] fix format --- deploy/apache.sh | 52 +++++++++++++++++++++++----------------------- deploy/dovecot.sh | 52 +++++++++++++++++++++++----------------------- deploy/exim4.sh | 52 +++++++++++++++++++++++----------------------- deploy/haproxy.sh | 52 +++++++++++++++++++++++----------------------- deploy/mysqld.sh | 52 +++++++++++++++++++++++----------------------- deploy/nginx.sh | 52 +++++++++++++++++++++++----------------------- deploy/opensshd.sh | 52 +++++++++++++++++++++++----------------------- deploy/pureftpd.sh | 52 +++++++++++++++++++++++----------------------- deploy/vsftpd.sh | 52 +++++++++++++++++++++++----------------------- 9 files changed, 234 insertions(+), 234 deletions(-) diff --git a/deploy/apache.sh b/deploy/apache.sh index 42de93f4..b6c1fbc2 100644 --- a/deploy/apache.sh +++ b/deploy/apache.sh @@ -1,26 +1,26 @@ -#!/usr/bin/env sh - -#Here is a script to deploy cert to dovecot server. - -#returns 0 means success, otherwise error. - -######## Public functions ##################### - -#domain keyfile certfile cafile fullchain -apache_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" - - _err "Deploy cert to apache server, Not implemented yet" - return 1 - -} +#!/usr/bin/env sh + +#Here is a script to deploy cert to dovecot server. + +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +apache_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" + + _err "Deploy cert to apache server, Not implemented yet" + return 1 + +} diff --git a/deploy/dovecot.sh b/deploy/dovecot.sh index 99a17d51..3baf23d9 100644 --- a/deploy/dovecot.sh +++ b/deploy/dovecot.sh @@ -1,26 +1,26 @@ -#!/usr/bin/env sh - -#Here is a script to deploy cert to dovecot server. - -#returns 0 means success, otherwise error. - -######## Public functions ##################### - -#domain keyfile certfile cafile fullchain -dovecot_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" - - _err "Not implemented yet" - return 1 - -} +#!/usr/bin/env sh + +#Here is a script to deploy cert to dovecot server. + +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +dovecot_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" + + _err "Not implemented yet" + return 1 + +} diff --git a/deploy/exim4.sh b/deploy/exim4.sh index cc53e344..b53f58ec 100644 --- a/deploy/exim4.sh +++ b/deploy/exim4.sh @@ -1,26 +1,26 @@ -#!/usr/bin/env sh - -#Here is a script to deploy cert to exim4 server. - -#returns 0 means success, otherwise error. - -######## Public functions ##################### - -#domain keyfile certfile cafile fullchain -exim4_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" - - _err "deploy cert to exim4 server, Not implemented yet" - return 1 - -} +#!/usr/bin/env sh + +#Here is a script to deploy cert to exim4 server. + +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +exim4_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" + + _err "deploy cert to exim4 server, Not implemented yet" + return 1 + +} diff --git a/deploy/haproxy.sh b/deploy/haproxy.sh index e7fa5b09..34efbb1f 100644 --- a/deploy/haproxy.sh +++ b/deploy/haproxy.sh @@ -1,26 +1,26 @@ -#!/usr/bin/env sh - -#Here is a script to deploy cert to haproxy server. - -#returns 0 means success, otherwise error. - -######## Public functions ##################### - -#domain keyfile certfile cafile fullchain -haproxy_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" - - _err "deploy cert to haproxy server, Not implemented yet" - return 1 - -} +#!/usr/bin/env sh + +#Here is a script to deploy cert to haproxy server. + +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +haproxy_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" + + _err "deploy cert to haproxy server, Not implemented yet" + return 1 + +} diff --git a/deploy/mysqld.sh b/deploy/mysqld.sh index 6fb178d7..8778843e 100644 --- a/deploy/mysqld.sh +++ b/deploy/mysqld.sh @@ -1,26 +1,26 @@ -#!/usr/bin/env sh - -#Here is a script to deploy cert to mysqld server. - -#returns 0 means success, otherwise error. - -######## Public functions ##################### - -#domain keyfile certfile cafile fullchain -mysqld_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" - - _err "deploy cert to mysqld server, Not implemented yet" - return 1 - -} +#!/usr/bin/env sh + +#Here is a script to deploy cert to mysqld server. + +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +mysqld_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" + + _err "deploy cert to mysqld server, Not implemented yet" + return 1 + +} diff --git a/deploy/nginx.sh b/deploy/nginx.sh index 2fb127fd..952b27f3 100644 --- a/deploy/nginx.sh +++ b/deploy/nginx.sh @@ -1,26 +1,26 @@ -#!/usr/bin/env sh - -#Here is a script to deploy cert to nginx server. - -#returns 0 means success, otherwise error. - -######## Public functions ##################### - -#domain keyfile certfile cafile fullchain -nginx_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" - - _err "deploy cert to nginx server, Not implemented yet" - return 1 - -} +#!/usr/bin/env sh + +#Here is a script to deploy cert to nginx server. + +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +nginx_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" + + _err "deploy cert to nginx server, Not implemented yet" + return 1 + +} diff --git a/deploy/opensshd.sh b/deploy/opensshd.sh index 01fbc3f1..9001b97c 100644 --- a/deploy/opensshd.sh +++ b/deploy/opensshd.sh @@ -1,26 +1,26 @@ -#!/usr/bin/env sh - -#Here is a script to deploy cert to opensshd server. - -#returns 0 means success, otherwise error. - -######## Public functions ##################### - -#domain keyfile certfile cafile fullchain -opensshd_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" - - _err "deploy cert to opensshd server, Not implemented yet" - return 1 - -} +#!/usr/bin/env sh + +#Here is a script to deploy cert to opensshd server. + +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +opensshd_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" + + _err "deploy cert to opensshd server, Not implemented yet" + return 1 + +} diff --git a/deploy/pureftpd.sh b/deploy/pureftpd.sh index 28643204..3d803601 100644 --- a/deploy/pureftpd.sh +++ b/deploy/pureftpd.sh @@ -1,26 +1,26 @@ -#!/usr/bin/env sh - -#Here is a script to deploy cert to pureftpd server. - -#returns 0 means success, otherwise error. - -######## Public functions ##################### - -#domain keyfile certfile cafile fullchain -pureftpd_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" - - _err "deploy cert to pureftpd server, Not implemented yet" - return 1 - -} +#!/usr/bin/env sh + +#Here is a script to deploy cert to pureftpd server. + +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +pureftpd_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" + + _err "deploy cert to pureftpd server, Not implemented yet" + return 1 + +} diff --git a/deploy/vsftpd.sh b/deploy/vsftpd.sh index 7ff1a58a..5e89ea95 100644 --- a/deploy/vsftpd.sh +++ b/deploy/vsftpd.sh @@ -1,26 +1,26 @@ -#!/usr/bin/env sh - -#Here is a script to deploy cert to vsftpd server. - -#returns 0 means success, otherwise error. - -######## Public functions ##################### - -#domain keyfile certfile cafile fullchain -vsftpd_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" - - _err "deploy cert to vsftpd server, Not implemented yet" - return 1 - -} +#!/usr/bin/env sh + +#Here is a script to deploy cert to vsftpd server. + +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +vsftpd_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" + + _err "deploy cert to vsftpd server, Not implemented yet" + return 1 + +} From af1cc3b3317d7a8ed2f4c65d8b57cb2cf7e75602 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 19 Feb 2017 21:13:00 +0800 Subject: [PATCH 24/29] refactor params --- acme.sh | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/acme.sh b/acme.sh index 2086ccc2..d2910ab3 100755 --- a/acme.sh +++ b/acme.sh @@ -2707,6 +2707,7 @@ _clearupwebbroot() { } _on_before_issue() { + _chk_web_roots="$1" _debug _on_before_issue #run pre hook if [ "$Le_PreHook" ]; then @@ -2719,7 +2720,7 @@ _on_before_issue() { fi fi - if _hasfield "$Le_Webroot" "$NO_VALUE"; then + if _hasfield "$_chk_web_roots" "$NO_VALUE"; then if ! _exists "nc"; then _err "Please install netcat(nc) tools first." return 1 @@ -2734,7 +2735,7 @@ _on_before_issue() { _addrIndex=1 for d in $alldomains; do _debug "Check for domain" "$d" - _currentRoot="$(_getfield "$Le_Webroot" $_index)" + _currentRoot="$(_getfield "$_chk_web_roots" $_index)" _debug "_currentRoot" "$_currentRoot" _index=$(_math $_index + 1) _checkport="" @@ -2777,7 +2778,7 @@ _on_before_issue() { fi done - if _hasfield "$Le_Webroot" "apache"; then + if _hasfield "$_chk_web_roots" "apache"; then if ! _setApache; then _err "set up apache error. Report error to me." return 1 @@ -3027,11 +3028,11 @@ issue() { _usage "Usage: $PROJECT_ENTRY --issue -d a.com -w /path/to/webroot/a.com/ " return 1 fi - Le_Webroot="$1" - Le_Domain="$2" + _web_roots="$1" + _main_domain="$2" Le_Alt="$3" - if _contains "$Le_Domain" ","; then - Le_Domain=$(echo "$2,$3" | cut -d , -f 1) + if _contains "$_main_domain" ","; then + _main_domain=$(echo "$2,$3" | cut -d , -f 1) Le_Alt=$(echo "$2,$3" | cut -d , -f 2- | sed "s/,${NO_VALUE}$//") fi Le_Keylength="$4" @@ -3046,19 +3047,19 @@ issue() { Le_LocalAddress="${13}" #remove these later. - if [ "$Le_Webroot" = "dns-cf" ]; then - Le_Webroot="dns_cf" + if [ "$_web_roots" = "dns-cf" ]; then + _web_roots="dns_cf" fi - if [ "$Le_Webroot" = "dns-dp" ]; then - Le_Webroot="dns_dp" + if [ "$_web_roots" = "dns-dp" ]; then + _web_roots="dns_dp" fi - if [ "$Le_Webroot" = "dns-cx" ]; then - Le_Webroot="dns_cx" + if [ "$_web_roots" = "dns-cx" ]; then + _web_roots="dns_cx" fi _debug "Using api: $API" if [ ! "$IS_RENEW" ]; then - _initpath "$Le_Domain" "$Le_Keylength" + _initpath "$_main_domain" "$Le_Keylength" mkdir -p "$DOMAIN_PATH" fi @@ -3070,7 +3071,7 @@ issue() { _debug _saved_domain "$_saved_domain" _saved_alt=$(_readdomainconf Le_Alt) _debug _saved_alt "$_saved_alt" - if [ "$_saved_domain,$_saved_alt" = "$Le_Domain,$Le_Alt" ]; then + if [ "$_saved_domain,$_saved_alt" = "$_main_domain,$Le_Alt" ]; then _info "Domains not changed." _info "Skip, Next renewal time is: $(__green "$(_readdomainconf Le_NextRenewTimeStr)")" _info "Add '$(__red '--force')' to force to renew." @@ -3081,9 +3082,9 @@ issue() { fi fi - _savedomainconf "Le_Domain" "$Le_Domain" + _savedomainconf "Le_Domain" "$_main_domain" _savedomainconf "Le_Alt" "$Le_Alt" - _savedomainconf "Le_Webroot" "$Le_Webroot" + _savedomainconf "Le_Webroot" "$_web_roots" _savedomainconf "Le_PreHook" "$Le_PreHook" _savedomainconf "Le_PostHook" "$Le_PostHook" @@ -3106,7 +3107,7 @@ issue() { Le_Keylength="" fi - if ! _on_before_issue; then + if ! _on_before_issue "$_web_roots"; then _err "_on_before_issue." return 1 fi @@ -3129,7 +3130,7 @@ issue() { _key=$(_readdomainconf Le_Keylength) _debug "Read key length:$_key" if [ ! -f "$CERT_KEY_PATH" ] || [ "$Le_Keylength" != "$_key" ]; then - if ! createDomainKey "$Le_Domain" "$Le_Keylength"; then + if ! createDomainKey "$_main_domain" "$Le_Keylength"; then _err "Create domain key error." _clearup _on_issue_err @@ -3137,7 +3138,7 @@ issue() { fi fi - if ! _createcsr "$Le_Domain" "$Le_Alt" "$CERT_KEY_PATH" "$CSR_PATH" "$DOMAIN_SSL_CONF"; then + if ! _createcsr "$_main_domain" "$Le_Alt" "$CERT_KEY_PATH" "$CSR_PATH" "$DOMAIN_SSL_CONF"; then _err "Create CSR error." _clearup _on_issue_err @@ -3153,12 +3154,12 @@ issue() { sep='#' dvsep=',' if [ -z "$vlist" ]; then - alldomains=$(echo "$Le_Domain,$Le_Alt" | tr ',' ' ') + alldomains=$(echo "$_main_domain,$Le_Alt" | tr ',' ' ') _index=1 _currentRoot="" for d in $alldomains; do _info "Getting webroot for domain" "$d" - _w="$(echo $Le_Webroot | cut -d , -f $_index)" + _w="$(echo $_web_roots | cut -d , -f $_index)" _debug _w "$_w" if [ "$_w" ]; then _currentRoot="$_w" From 02140ce763c2f254674def89ee63ab9b5bbc4feb Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 19 Feb 2017 21:18:00 +0800 Subject: [PATCH 25/29] refactor alt domains --- acme.sh | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/acme.sh b/acme.sh index d2910ab3..30bb0585 100755 --- a/acme.sh +++ b/acme.sh @@ -2708,6 +2708,8 @@ _clearupwebbroot() { _on_before_issue() { _chk_web_roots="$1" + _chk_main_domain="$2" + _chk_alt_domains="$3" _debug _on_before_issue #run pre hook if [ "$Le_PreHook" ]; then @@ -2729,7 +2731,7 @@ _on_before_issue() { _debug Le_LocalAddress "$Le_LocalAddress" - alldomains=$(echo "$Le_Domain,$Le_Alt" | tr ',' ' ') + alldomains=$(echo "$_chk_main_domain,$_chk_alt_domains" | tr ',' ' ') _index=1 _currentRoot="" _addrIndex=1 @@ -3030,10 +3032,10 @@ issue() { fi _web_roots="$1" _main_domain="$2" - Le_Alt="$3" + _alt_domains="$3" if _contains "$_main_domain" ","; then _main_domain=$(echo "$2,$3" | cut -d , -f 1) - Le_Alt=$(echo "$2,$3" | cut -d , -f 2- | sed "s/,${NO_VALUE}$//") + _alt_domains=$(echo "$2,$3" | cut -d , -f 2- | sed "s/,${NO_VALUE}$//") fi Le_Keylength="$4" Le_RealCertPath="$5" @@ -3071,7 +3073,7 @@ issue() { _debug _saved_domain "$_saved_domain" _saved_alt=$(_readdomainconf Le_Alt) _debug _saved_alt "$_saved_alt" - if [ "$_saved_domain,$_saved_alt" = "$_main_domain,$Le_Alt" ]; then + if [ "$_saved_domain,$_saved_alt" = "$_main_domain,$_alt_domains" ]; then _info "Domains not changed." _info "Skip, Next renewal time is: $(__green "$(_readdomainconf Le_NextRenewTimeStr)")" _info "Add '$(__red '--force')' to force to renew." @@ -3083,7 +3085,7 @@ issue() { fi _savedomainconf "Le_Domain" "$_main_domain" - _savedomainconf "Le_Alt" "$Le_Alt" + _savedomainconf "Le_Alt" "$_alt_domains" _savedomainconf "Le_Webroot" "$_web_roots" _savedomainconf "Le_PreHook" "$Le_PreHook" @@ -3099,15 +3101,15 @@ issue() { Le_API="$API" _savedomainconf "Le_API" "$Le_API" - if [ "$Le_Alt" = "$NO_VALUE" ]; then - Le_Alt="" + if [ "$_alt_domains" = "$NO_VALUE" ]; then + _alt_domains="" fi if [ "$Le_Keylength" = "$NO_VALUE" ]; then Le_Keylength="" fi - if ! _on_before_issue "$_web_roots"; then + if ! _on_before_issue "$_web_roots" "$_main_domain" "$_alt_domains"; then _err "_on_before_issue." return 1 fi @@ -3138,7 +3140,7 @@ issue() { fi fi - if ! _createcsr "$_main_domain" "$Le_Alt" "$CERT_KEY_PATH" "$CSR_PATH" "$DOMAIN_SSL_CONF"; then + if ! _createcsr "$_main_domain" "$_alt_domains" "$CERT_KEY_PATH" "$CSR_PATH" "$DOMAIN_SSL_CONF"; then _err "Create CSR error." _clearup _on_issue_err @@ -3154,7 +3156,7 @@ issue() { sep='#' dvsep=',' if [ -z "$vlist" ]; then - alldomains=$(echo "$_main_domain,$Le_Alt" | tr ',' ' ') + alldomains=$(echo "$_main_domain,$_alt_domains" | tr ',' ' ') _index=1 _currentRoot="" for d in $alldomains; do From d9c9114b3b897dcedd4c6a77f5dd03a346caec06 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 19 Feb 2017 21:21:11 +0800 Subject: [PATCH 26/29] refactor key length --- acme.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/acme.sh b/acme.sh index 30bb0585..a9f9e72c 100755 --- a/acme.sh +++ b/acme.sh @@ -3037,7 +3037,7 @@ issue() { _main_domain=$(echo "$2,$3" | cut -d , -f 1) _alt_domains=$(echo "$2,$3" | cut -d , -f 2- | sed "s/,${NO_VALUE}$//") fi - Le_Keylength="$4" + _key_length="$4" Le_RealCertPath="$5" Le_RealKeyPath="$6" Le_RealCACertPath="$7" @@ -3061,7 +3061,7 @@ issue() { _debug "Using api: $API" if [ ! "$IS_RENEW" ]; then - _initpath "$_main_domain" "$Le_Keylength" + _initpath "$_main_domain" "$_key_length" mkdir -p "$DOMAIN_PATH" fi @@ -3105,8 +3105,8 @@ issue() { _alt_domains="" fi - if [ "$Le_Keylength" = "$NO_VALUE" ]; then - Le_Keylength="" + if [ "$_key_length" = "$NO_VALUE" ]; then + _key_length="" fi if ! _on_before_issue "$_web_roots" "$_main_domain" "$_alt_domains"; then @@ -3131,8 +3131,8 @@ issue() { else _key=$(_readdomainconf Le_Keylength) _debug "Read key length:$_key" - if [ ! -f "$CERT_KEY_PATH" ] || [ "$Le_Keylength" != "$_key" ]; then - if ! createDomainKey "$_main_domain" "$Le_Keylength"; then + if [ ! -f "$CERT_KEY_PATH" ] || [ "$_key_length" != "$_key" ]; then + if ! createDomainKey "$_main_domain" "$_key_length"; then _err "Create domain key error." _clearup _on_issue_err @@ -3148,7 +3148,7 @@ issue() { fi fi - _savedomainconf "Le_Keylength" "$Le_Keylength" + _savedomainconf "Le_Keylength" "$_key_length" vlist="$Le_Vlist" From 85e1f4ea13f2fa5a754bf6c65795c03da84f2584 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 19 Feb 2017 22:09:22 +0800 Subject: [PATCH 27/29] refactor parameters --- acme.sh | 227 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 120 insertions(+), 107 deletions(-) diff --git a/acme.sh b/acme.sh index a9f9e72c..db77c226 100755 --- a/acme.sh +++ b/acme.sh @@ -2710,12 +2710,14 @@ _on_before_issue() { _chk_web_roots="$1" _chk_main_domain="$2" _chk_alt_domains="$3" + _chk_pre_hook="$4" + _chk_local_addr="$5" _debug _on_before_issue #run pre hook - if [ "$Le_PreHook" ]; then - _info "Run pre hook:'$Le_PreHook'" + if [ "$_chk_pre_hook" ]; then + _info "Run pre hook:'$_chk_pre_hook'" if ! ( - cd "$DOMAIN_PATH" && eval "$Le_PreHook" + cd "$DOMAIN_PATH" && eval "$_chk_pre_hook" ); then _err "Error when run pre hook." return 1 @@ -2729,7 +2731,7 @@ _on_before_issue() { fi fi - _debug Le_LocalAddress "$Le_LocalAddress" + _debug Le_LocalAddress "$_chk_local_addr" alldomains=$(echo "$_chk_main_domain,$_chk_alt_domains" | tr ',' ' ') _index=1 @@ -2761,7 +2763,7 @@ _on_before_issue() { if [ "$_checkport" ]; then _debug _checkport "$_checkport" - _checkaddr="$(_getfield "$Le_LocalAddress" $_addrIndex)" + _checkaddr="$(_getfield "$_chk_local_addr" $_addrIndex)" _debug _checkaddr "$_checkaddr" _addrIndex="$(_math $_addrIndex + 1)" @@ -2792,6 +2794,7 @@ _on_before_issue() { } _on_issue_err() { + _chk_post_hook="$1" _debug _on_issue_err if [ "$LOG_FILE" ]; then _err "Please check log file for more details: $LOG_FILE" @@ -2805,10 +2808,10 @@ _on_issue_err() { fi #run the post hook - if [ "$Le_PostHook" ]; then - _info "Run post hook:'$Le_PostHook'" + if [ "$_chk_post_hook" ]; then + _info "Run post hook:'$_chk_post_hook'" if ! ( - cd "$DOMAIN_PATH" && eval "$Le_PostHook" + cd "$DOMAIN_PATH" && eval "$_chk_post_hook" ); then _err "Error when run post hook." return 1 @@ -2817,12 +2820,14 @@ _on_issue_err() { } _on_issue_success() { + _chk_post_hook="$1" + _chk_renew_hook="$2" _debug _on_issue_success #run the post hook - if [ "$Le_PostHook" ]; then - _info "Run post hook:'$Le_PostHook'" + if [ "$_chk_post_hook" ]; then + _info "Run post hook:'$_chk_post_hook'" if ! ( - cd "$DOMAIN_PATH" && eval "$Le_PostHook" + cd "$DOMAIN_PATH" && eval "$_chk_post_hook" ); then _err "Error when run post hook." return 1 @@ -2830,10 +2835,10 @@ _on_issue_success() { fi #run renew hook - if [ "$IS_RENEW" ] && [ "$Le_RenewHook" ]; then - _info "Run renew hook:'$Le_RenewHook'" + if [ "$IS_RENEW" ] && [ "$_chk_renew_hook" ]; then + _info "Run renew hook:'$_chk_renew_hook'" if ! ( - cd "$DOMAIN_PATH" && eval "$Le_RenewHook" + cd "$DOMAIN_PATH" && eval "$_chk_renew_hook" ); then _err "Error when run renew hook." return 1 @@ -3038,15 +3043,15 @@ issue() { _alt_domains=$(echo "$2,$3" | cut -d , -f 2- | sed "s/,${NO_VALUE}$//") fi _key_length="$4" - Le_RealCertPath="$5" - Le_RealKeyPath="$6" - Le_RealCACertPath="$7" - Le_ReloadCmd="$8" - Le_RealFullChainPath="$9" - Le_PreHook="${10}" - Le_PostHook="${11}" - Le_RenewHook="${12}" - Le_LocalAddress="${13}" + _real_cert="$5" + _real_key="$6" + _real_ca="$7" + _reload_cmd="$8" + _real_fullchain="$9" + _pre_hook="${10}" + _post_hook="${11}" + _renew_hook="${12}" + _local_addr="${13}" #remove these later. if [ "$_web_roots" = "dns-cf" ]; then @@ -3088,12 +3093,12 @@ issue() { _savedomainconf "Le_Alt" "$_alt_domains" _savedomainconf "Le_Webroot" "$_web_roots" - _savedomainconf "Le_PreHook" "$Le_PreHook" - _savedomainconf "Le_PostHook" "$Le_PostHook" - _savedomainconf "Le_RenewHook" "$Le_RenewHook" + _savedomainconf "Le_PreHook" "$_pre_hook" + _savedomainconf "Le_PostHook" "$_post_hook" + _savedomainconf "Le_RenewHook" "$_renew_hook" - if [ "$Le_LocalAddress" ]; then - _savedomainconf "Le_LocalAddress" "$Le_LocalAddress" + if [ "$_local_addr" ]; then + _savedomainconf "Le_LocalAddress" "$_local_addr" else _cleardomainconf "Le_LocalAddress" fi @@ -3109,7 +3114,7 @@ issue() { _key_length="" fi - if ! _on_before_issue "$_web_roots" "$_main_domain" "$_alt_domains"; then + if ! _on_before_issue "$_web_roots" "$_main_domain" "$_alt_domains" "$_pre_hook" "$_local_addr"; then _err "_on_before_issue." return 1 fi @@ -3119,7 +3124,7 @@ issue() { if [ -z "$_saved_account_key_hash" ] || [ "$_saved_account_key_hash" != "$(__calcAccountKeyHash)" ]; then if ! _regAccount "$_accountkeylength"; then - _on_issue_err + _on_issue_err "$_post_hook" return 1 fi else @@ -3135,7 +3140,7 @@ issue() { if ! createDomainKey "$_main_domain" "$_key_length"; then _err "Create domain key error." _clearup - _on_issue_err + _on_issue_err "$_post_hook" return 1 fi fi @@ -3143,7 +3148,7 @@ issue() { if ! _createcsr "$_main_domain" "$_alt_domains" "$CERT_KEY_PATH" "$CSR_PATH" "$DOMAIN_SSL_CONF"; then _err "Create CSR error." _clearup - _on_issue_err + _on_issue_err "$_post_hook" return 1 fi fi @@ -3180,7 +3185,7 @@ issue() { if ! __get_domain_new_authz "$d"; then _clearup - _on_issue_err + _on_issue_err "$_post_hook" return 1 fi @@ -3193,7 +3198,7 @@ issue() { if [ -z "$entry" ]; then _err "Error, can not get domain token $d" _clearup - _on_issue_err + _on_issue_err "$_post_hook" return 1 fi token="$(printf "%s\n" "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')" @@ -3274,7 +3279,7 @@ issue() { if [ "$?" != "0" ]; then _clearup - _on_issue_err + _on_issue_err "$_post_hook" return 1 fi dnsadded='1' @@ -3286,7 +3291,7 @@ issue() { _debug "Dns record not added yet, so, save to $DOMAIN_CONF and exit." _err "Please add the TXT records to the domains, and retry again." _clearup - _on_issue_err + _on_issue_err "$_post_hook" return 1 fi @@ -3332,12 +3337,12 @@ issue() { if [ "$vtype" = "$VTYPE_HTTP" ]; then if [ "$_currentRoot" = "$NO_VALUE" ]; then _info "Standalone mode server" - _ncaddr="$(_getfield "$Le_LocalAddress" "$_ncIndex")" + _ncaddr="$(_getfield "$_local_addr" "$_ncIndex")" _ncIndex="$(_math $_ncIndex + 1)" _startserver "$keyauthorization" "$_ncaddr" & if [ "$?" != "0" ]; then _clearup - _on_issue_err + _on_issue_err "$_post_hook" return 1 fi serverproc="$!" @@ -3353,7 +3358,7 @@ issue() { BACKUP_NGINX_CONF="" if ! _setNginx "$d" "$_currentRoot" "$thumbprint"; then _clearup - _on_issue_err + _on_issue_err "$_post_hook" return 1 fi @@ -3388,7 +3393,7 @@ issue() { _err "$d:Can not write token to file : $wellknown_path/$token" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup - _on_issue_err + _on_issue_err "$_post_hook" return 1 fi @@ -3427,13 +3432,13 @@ issue() { _SAN_B="$_x.$_y.acme.invalid" _debug2 _SAN_B "$_SAN_B" - _ncaddr="$(_getfield "$Le_LocalAddress" "$_ncIndex")" + _ncaddr="$(_getfield "$_local_addr" "$_ncIndex")" _ncIndex="$(_math "$_ncIndex" + 1)" if ! _starttlsserver "$_SAN_B" "$_SAN_A" "$Le_TLSPort" "$keyauthorization" "$_ncaddr"; then _err "Start tls server error." _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup - _on_issue_err + _on_issue_err "$_post_hook" return 1 fi fi @@ -3442,7 +3447,7 @@ issue() { _err "$d:Can not get challenge: $response" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup - _on_issue_err + _on_issue_err "$_post_hook" return 1 fi @@ -3450,7 +3455,7 @@ issue() { _err "$d:Challenge error: $response" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup - _on_issue_err + _on_issue_err "$_post_hook" return 1 fi @@ -3477,7 +3482,7 @@ issue() { _err "$d:Verify error:$response" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup - _on_issue_err + _on_issue_err "$_post_hook" return 1 fi _debug2 original "$response" @@ -3512,7 +3517,7 @@ issue() { fi _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup - _on_issue_err + _on_issue_err "$_post_hook" return 1 fi @@ -3522,7 +3527,7 @@ issue() { _err "$d:Verify error:$response" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup - _on_issue_err + _on_issue_err "$_post_hook" return 1 fi @@ -3536,7 +3541,7 @@ issue() { if ! _send_signed_request "$API/acme/new-cert" "{\"resource\": \"new-cert\", \"csr\": \"$der\"}" "needbase64"; then _err "Sign failed." - _on_issue_err + _on_issue_err "$_post_hook" return 1 fi @@ -3578,7 +3583,7 @@ issue() { if [ -z "$Le_LinkCert" ]; then response="$(echo "$response" | _dbase64 "multiline" | _normalizeJson)" _err "Sign failed: $(echo "$response" | _egrep_o '"detail":"[^"]*"')" - _on_issue_err + _on_issue_err "$_post_hook" return 1 fi @@ -3640,10 +3645,15 @@ issue() { Le_NextRenewTime=$(_math "$Le_NextRenewTime" - 86400) _savedomainconf "Le_NextRenewTime" "$Le_NextRenewTime" - _on_issue_success + _on_issue_success "$_post_hook" "$_renew_hook" - if [ "$Le_RealCertPath$Le_RealKeyPath$Le_RealCACertPath$Le_ReloadCmd$Le_RealFullChainPath" ]; then - _installcert + if [ "$_real_cert$_real_key$_real_ca$_reload_cmd$_real_fullchain" ]; then + _savedomainconf "Le_RealCertPath" "$_real_cert" + _savedomainconf "Le_RealCACertPath" "$_real_ca" + _savedomainconf "Le_RealKeyPath" "$_real_key" + _savedomainconf "Le_ReloadCmd" "$_reload_cmd" + _savedomainconf "Le_RealFullChainPath" "$_real_fullchain" + _installcert "$_main_domain" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" fi } @@ -3929,104 +3939,107 @@ deploy() { } installcert() { - Le_Domain="$1" - if [ -z "$Le_Domain" ]; then + _main_domain="$1" + if [ -z "$_main_domain" ]; then _usage "Usage: $PROJECT_ENTRY --installcert -d domain.com [--ecc] [--certpath cert-file-path] [--keypath key-file-path] [--capath ca-cert-file-path] [ --reloadCmd reloadCmd] [--fullchainpath fullchain-path]" return 1 fi - Le_RealCertPath="$2" - Le_RealKeyPath="$3" - Le_RealCACertPath="$4" - Le_ReloadCmd="$5" - Le_RealFullChainPath="$6" + _real_cert="$2" + _real_key="$3" + _real_ca="$4" + _reload_cmd="$5" + _real_fullchain="$6" _isEcc="$7" - _initpath "$Le_Domain" "$_isEcc" + _initpath "$_main_domain" "$_isEcc" if [ ! -d "$DOMAIN_PATH" ]; then - _err "Domain is not valid:'$Le_Domain'" + _err "Domain is not valid:'$_main_domain'" return 1 fi - _installcert + _savedomainconf "Le_RealCertPath" "$_real_cert" + _savedomainconf "Le_RealCACertPath" "$_real_ca" + _savedomainconf "Le_RealKeyPath" "$_real_key" + _savedomainconf "Le_ReloadCmd" "$_reload_cmd" + _savedomainconf "Le_RealFullChainPath" "$_real_fullchain" + + _installcert "$_main_domain" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" } _installcert() { - _savedomainconf "Le_RealCertPath" "$Le_RealCertPath" - _savedomainconf "Le_RealCACertPath" "$Le_RealCACertPath" - _savedomainconf "Le_RealKeyPath" "$Le_RealKeyPath" - _savedomainconf "Le_ReloadCmd" "$Le_ReloadCmd" - _savedomainconf "Le_RealFullChainPath" "$Le_RealFullChainPath" + _main_domain="$1" + _real_cert="$2" + _real_key="$3" + _real_ca="$4" + _reload_cmd="$5" + _real_fullchain="$6" - if [ "$Le_RealCertPath" = "$NO_VALUE" ]; then - Le_RealCertPath="" + if [ "$_real_cert" = "$NO_VALUE" ]; then + _real_cert="" fi - if [ "$Le_RealKeyPath" = "$NO_VALUE" ]; then - Le_RealKeyPath="" + if [ "$_real_key" = "$NO_VALUE" ]; then + _real_key="" fi - if [ "$Le_RealCACertPath" = "$NO_VALUE" ]; then - Le_RealCACertPath="" + if [ "$_real_ca" = "$NO_VALUE" ]; then + _real_ca="" fi - if [ "$Le_ReloadCmd" = "$NO_VALUE" ]; then - Le_ReloadCmd="" + if [ "$_reload_cmd" = "$NO_VALUE" ]; then + _reload_cmd="" fi - if [ "$Le_RealFullChainPath" = "$NO_VALUE" ]; then - Le_RealFullChainPath="" + if [ "$_real_fullchain" = "$NO_VALUE" ]; then + _real_fullchain="" fi - if [ "$Le_RealCertPath" ]; then - - _info "Installing cert to:$Le_RealCertPath" - if [ -f "$Le_RealCertPath" ] && [ ! "$IS_RENEW" ]; then + if [ "$_real_cert" ]; then + _info "Installing cert to:$_real_cert" + if [ -f "$_real_cert" ] && [ ! "$IS_RENEW" ]; then mkdir -p "$DOMAIN_BACKUP_PATH" - cp "$Le_RealCertPath" "$DOMAIN_BACKUP_PATH/cert.bak" + cp "$_real_cert" "$DOMAIN_BACKUP_PATH/cert.bak" fi - cat "$CERT_PATH" >"$Le_RealCertPath" + cat "$CERT_PATH" >"$_real_cert" fi - if [ "$Le_RealCACertPath" ]; then - - _info "Installing CA to:$Le_RealCACertPath" - if [ "$Le_RealCACertPath" = "$Le_RealCertPath" ]; then - echo "" >>"$Le_RealCACertPath" - cat "$CA_CERT_PATH" >>"$Le_RealCACertPath" + if [ "$_real_ca" ]; then + _info "Installing CA to:$_real_ca" + if [ "$_real_ca" = "$_real_cert" ]; then + echo "" >>"$_real_ca" + cat "$CA_CERT_PATH" >>"$_real_ca" else - if [ -f "$Le_RealCACertPath" ] && [ ! "$IS_RENEW" ]; then + if [ -f "$_real_ca" ] && [ ! "$IS_RENEW" ]; then mkdir -p "$DOMAIN_BACKUP_PATH" - cp "$Le_RealCACertPath" "$DOMAIN_BACKUP_PATH/ca.bak" + cp "$_real_ca" "$DOMAIN_BACKUP_PATH/ca.bak" fi - cat "$CA_CERT_PATH" >"$Le_RealCACertPath" + cat "$CA_CERT_PATH" >"$_real_ca" fi fi - if [ "$Le_RealKeyPath" ]; then - - _info "Installing key to:$Le_RealKeyPath" - if [ -f "$Le_RealKeyPath" ] && [ ! "$IS_RENEW" ]; then + if [ "$_real_key" ]; then + _info "Installing key to:$_real_key" + if [ -f "$_real_key" ] && [ ! "$IS_RENEW" ]; then mkdir -p "$DOMAIN_BACKUP_PATH" - cp "$Le_RealKeyPath" "$DOMAIN_BACKUP_PATH/key.bak" + cp "$_real_key" "$DOMAIN_BACKUP_PATH/key.bak" fi - cat "$CERT_KEY_PATH" >"$Le_RealKeyPath" + cat "$CERT_KEY_PATH" >"$_real_key" fi - if [ "$Le_RealFullChainPath" ]; then - - _info "Installing full chain to:$Le_RealFullChainPath" - if [ -f "$Le_RealFullChainPath" ] && [ ! "$IS_RENEW" ]; then + if [ "$_real_fullchain" ]; then + _info "Installing full chain to:$_real_fullchain" + if [ -f "$_real_fullchain" ] && [ ! "$IS_RENEW" ]; then mkdir -p "$DOMAIN_BACKUP_PATH" - cp "$Le_RealFullChainPath" "$DOMAIN_BACKUP_PATH/fullchain.bak" + cp "$_real_fullchain" "$DOMAIN_BACKUP_PATH/fullchain.bak" fi - cat "$CERT_FULLCHAIN_PATH" >"$Le_RealFullChainPath" + cat "$CERT_FULLCHAIN_PATH" >"$_real_fullchain" fi - if [ "$Le_ReloadCmd" ]; then - _info "Run Le_ReloadCmd: $Le_ReloadCmd" + if [ "$_reload_cmd" ]; then + _info "Run reload cmd: $_reload_cmd" if ( export CERT_PATH export CERT_KEY_PATH export CA_CERT_PATH export CERT_FULLCHAIN_PATH - cd "$DOMAIN_PATH" && eval "$Le_ReloadCmd" + cd "$DOMAIN_PATH" && eval "$_reload_cmd" ); then _info "$(__green "Reload success")" else From 8796adfd6393257177f96e2b5ab8bf0dfd0d2a47 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 20 Feb 2017 18:03:16 +0800 Subject: [PATCH 28/29] fix https://github.com/Neilpang/acme.sh/issues/614 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index db77c226..1bd955bc 100755 --- a/acme.sh +++ b/acme.sh @@ -1088,7 +1088,7 @@ _readKeyLengthFromCSR() { echo "$_outcsr" | _egrep_o "^ *ASN1 OID:.*" | cut -d ':' -f 2 | tr -d ' ' else _debug "RSA CSR" - echo "$_outcsr" | _egrep_o "^ *Public.Key:.*" | cut -d '(' -f 2 | cut -d ' ' -f 1 + echo "$_outcsr" | _egrep_o "(^ *|^RSA )Public.Key:.*" | cut -d '(' -f 2 | cut -d ' ' -f 1 fi } From 1efb2085e98859261f9b697b1358a4478d5bb5cf Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 20 Feb 2017 20:18:58 +0800 Subject: [PATCH 29/29] fix debug info --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 1bd955bc..43f87e98 100755 --- a/acme.sh +++ b/acme.sh @@ -1730,7 +1730,7 @@ _setopt() { _debug3 APP echo "$__opt$__sep$__val$__end" >>"$__conf" fi - _debug2 "$(grep -n "^$__opt$__sep" "$__conf")" + _debug3 "$(grep -n "^$__opt$__sep" "$__conf")" } #_save_conf file key value