From b22b085b508c745030b9ecd4ce931fca19f43455 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 5 Feb 2017 22:08:52 +0800 Subject: [PATCH 001/113] fix https://github.com/Neilpang/acme.sh/issues/578 support openssl 1.1.0 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index df4a0b4a..ec41b60f 100755 --- a/acme.sh +++ b/acme.sh @@ -914,7 +914,7 @@ _readSubjectFromCSR() { _usage "_readSubjectFromCSR mycsr.csr" return 1 fi - $OPENSSL_BIN req -noout -in "$_csrfile" -subject | _egrep_o "CN=.*" | cut -d = -f 2 | cut -d / -f 1 | tr -d '\n' + $OPENSSL_BIN req -noout -in "$_csrfile" -subject | _egrep_o "CN *=.*" | cut -d = -f 2 | cut -d / -f 1 | tr -d '\n' } #_csrfile From 562a4c056ea208e85e6f0551a188d55cee8050d5 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 5 Feb 2017 23:06:06 +0800 Subject: [PATCH 002/113] add note info if netcat-openbsd is required. --- acme.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/acme.sh b/acme.sh index ec41b60f..b22b2e69 100755 --- a/acme.sh +++ b/acme.sh @@ -61,6 +61,8 @@ DEFAULT_LOG_LEVEL="$LOG_LEVEL_1" _DEBUG_WIKI="https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh" +_PREPARE_LINK="https://github.com/Neilpang/acme.sh/wiki/Install-preparations" + __INTERACTIVE="" if [ -t 1 ]; then __INTERACTIVE="1" @@ -1684,6 +1686,14 @@ _startserver() { _NC="$_NC -6" fi + if [ "$Le_Listen_V4$Le_Listen_V6$ncaddr" ]; then + if ! _contains "$nchelp" "OpenBSD"; then + _err "The nc doesn't support '-4', '-6' or local-address, please install 'netcat-openbsd' and try again." + _err "See $(__green $_PREPARE_LINK)" + return 1 + fi + fi + if echo "$nchelp" | grep "\-q[ ,]" >/dev/null; then _NC="$_NC -q 1 -l $ncaddr" else From b4325026b17374efdbcc7726369085e4373f23ef Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 5 Feb 2017 23:14:25 +0800 Subject: [PATCH 003/113] exe --- deploy/kong.sh | 0 deploy/myapi.sh | 0 dnsapi/dns_ad.sh | 0 dnsapi/dns_ali.sh | 0 dnsapi/dns_aws.sh | 0 5 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 deploy/kong.sh mode change 100644 => 100755 deploy/myapi.sh mode change 100644 => 100755 dnsapi/dns_ad.sh mode change 100644 => 100755 dnsapi/dns_ali.sh mode change 100644 => 100755 dnsapi/dns_aws.sh diff --git a/deploy/kong.sh b/deploy/kong.sh old mode 100644 new mode 100755 diff --git a/deploy/myapi.sh b/deploy/myapi.sh old mode 100644 new mode 100755 diff --git a/dnsapi/dns_ad.sh b/dnsapi/dns_ad.sh old mode 100644 new mode 100755 diff --git a/dnsapi/dns_ali.sh b/dnsapi/dns_ali.sh old mode 100644 new mode 100755 diff --git a/dnsapi/dns_aws.sh b/dnsapi/dns_aws.sh old mode 100644 new mode 100755 From 0ca5b7996cddab0e471efcb25313c3d6301cdfb1 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 6 Feb 2017 09:28:30 +0800 Subject: [PATCH 004/113] minor clear account conf --- acme.sh | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/acme.sh b/acme.sh index b22b2e69..08e06fbd 100755 --- a/acme.sh +++ b/acme.sh @@ -3906,12 +3906,7 @@ _detect_profile() { _initconf() { _initpath if [ ! -f "$ACCOUNT_CONF_PATH" ]; then - echo "#ACCOUNT_CONF_PATH=xxxx - -#ACCOUNT_EMAIL=aaa@example.com # the account email used to register account. -#ACCOUNT_KEY_PATH=\"/path/to/account.key\" -#CERT_HOME=\"/path/to/cert/home\" - + echo " #LOG_FILE=\"$DEFAULT_LOG_FILE\" #LOG_LEVEL=1 @@ -3919,12 +3914,6 @@ _initconf() { #AUTO_UPGRADE=\"1\" #NO_TIMESTAMP=1 -#OPENSSL_BIN=openssl - -#USER_AGENT=\"$USER_AGENT\" - -#USER_PATH= - " >"$ACCOUNT_CONF_PATH" fi From dba26c3240efaa6cdd9c6f163f8294242c2bdbfd Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 6 Feb 2017 13:27:58 +0800 Subject: [PATCH 005/113] fix check for Mac nc command, it doesn't contain "openbsd", but it works. --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 08e06fbd..d3d46b59 100755 --- a/acme.sh +++ b/acme.sh @@ -1687,7 +1687,7 @@ _startserver() { fi if [ "$Le_Listen_V4$Le_Listen_V6$ncaddr" ]; then - if ! _contains "$nchelp" "OpenBSD"; then + if ! _contains "$nchelp" "-4"; then _err "The nc doesn't support '-4', '-6' or local-address, please install 'netcat-openbsd' and try again." _err "See $(__green $_PREPARE_LINK)" return 1 From d6edff3182e3e3fe672652aa02324590e7f2057d Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 6 Feb 2017 14:20:37 +0800 Subject: [PATCH 006/113] fix ci --- .travis.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8d6d30ad..1d54faed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,7 +33,6 @@ install: fi script: - - echo "TEST_LOCAL=$TEST_LOCAL" - echo "NGROK_TOKEN=$(echo "$NGROK_TOKEN" | wc -c)" - command -V openssl && openssl version - if [ "$TRAVIS_OS_NAME" = "linux" ]; then curl -sSL $SHFMT_URL -o ~/shfmt ; fi @@ -44,8 +43,8 @@ script: - if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck **/*.sh && echo "shellcheck OK" ; fi - cd .. - git clone https://github.com/Neilpang/acmetest.git && cp -r acme.sh acmetest/ && cd acmetest - - if [ "$TRAVIS_OS_NAME" = "linux" -a "$NGROK_TOKEN" ]; then sudo NGROK_TOKEN="$NGROK_TOKEN" ./letest.sh ; fi - - if [ "$TRAVIS_OS_NAME" = "osx" -a "$NGROK_TOKEN" ]; then sudo NGROK_TOKEN="$NGROK_TOKEN" OPENSSL_BIN="$OPENSSL_BIN" ./letest.sh ; fi + - if [ "$TRAVIS_OS_NAME" = "linux" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ./letest.sh ; fi + - if [ "$TRAVIS_OS_NAME" = "osx" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" OPENSSL_BIN="$OPENSSL_BIN" ./letest.sh ; fi matrix: From 5d2c5b01a80c2cdc555673926e7b865e33297ddd Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 6 Feb 2017 19:30:53 +0800 Subject: [PATCH 007/113] add _utc_date function --- acme.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/acme.sh b/acme.sh index d3d46b59..0b234953 100755 --- a/acme.sh +++ b/acme.sh @@ -1265,6 +1265,10 @@ _time() { date -u "+%s" } +_utc_date() { + date -u "+%Y-%m-%d %H:%M:%S" +} + _mktemp() { if _exists mktemp; then if mktemp 2>/dev/null; then From 339a8ad61041591d6cc2bb3af77ed855e13e735d Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 6 Feb 2017 19:53:12 +0800 Subject: [PATCH 008/113] minor, output thumbprint --- acme.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 0b234953..7ad5897d 100755 --- a/acme.sh +++ b/acme.sh @@ -2489,6 +2489,10 @@ __calcAccountKeyHash() { [ -f "$ACCOUNT_KEY_PATH" ] && _digest sha256 <"$ACCOUNT_KEY_PATH" } +__calc_account_thumbprint() { + printf "%s" "$jwk" | tr -d ' ' | _digest "sha256" | _url_replace +} + #keylength _regAccount() { _initpath @@ -2579,6 +2583,8 @@ _regAccount() { return 1 fi fi + ACCOUNT_THUMBPRINT="$(__calc_account_thumbprint)" + _info "ACCOUNT_THUMBPRINT" "$ACCOUNT_THUMBPRINT" return 0 done @@ -2810,8 +2816,7 @@ issue() { fi if [ -z "$thumbprint" ]; then - accountkey_json=$(printf "%s" "$jwk" | tr -d ' ') - thumbprint=$(printf "%s" "$accountkey_json" | _digest "sha256" | _url_replace) + thumbprint="$(__calc_account_thumbprint)" fi entry="$(printf "%s\n" "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')" From 0e44f587a5052ece05ad09674c0384809c95dd7e Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 6 Feb 2017 20:42:54 +0800 Subject: [PATCH 009/113] add stateless mode --- acme.sh | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 7ad5897d..cb99b5ab 100755 --- a/acme.sh +++ b/acme.sh @@ -41,6 +41,8 @@ NO_VALUE="no" W_TLS="tls" +MODE_STATELESS="stateless" + STATE_VERIFIED="verified_ok" BEGIN_CSR="-----BEGIN CERTIFICATE REQUEST-----" @@ -63,6 +65,8 @@ _DEBUG_WIKI="https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh" _PREPARE_LINK="https://github.com/Neilpang/acme.sh/wiki/Install-preparations" +_STATELESS_WIKI="https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode" + __INTERACTIVE="" if [ -t 1 ]; then __INTERACTIVE="1" @@ -2973,7 +2977,9 @@ issue() { serverproc="$!" sleep 1 _debug serverproc "$serverproc" - + elif [ "$_currentRoot" = "$MODE_STATELESS" ]; then + _info "Stateless mode for domain:$d" + _sleep 1 else if [ "$_currentRoot" = "apache" ]; then wellknown_path="$ACME_DIR" @@ -4258,6 +4264,7 @@ Parameters: --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 --tls Use standalone tls mode. --apache Use apache mode. --dns [dns_cf|dns_dp|dns_cx|/path/to/api/file] Use dns mode or dns api. @@ -4563,6 +4570,14 @@ _process() { _webroot="$_webroot,$wvalue" fi ;; + --stateless) + wvalue="$MODE_STATELESS" + if [ -z "$_webroot" ]; then + _webroot="$wvalue" + else + _webroot="$_webroot,$wvalue" + fi + ;; --local-address) lvalue="$2" _local_address="$_local_address$lvalue," From 7c488b5913f47aecfcc61d8e6d329a4b374387c3 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 6 Feb 2017 21:37:21 +0800 Subject: [PATCH 010/113] doc for stateless mode --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c6362ed7..2dd178d8 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ https://github.com/Neilpang/acmetest - Standalone mode - Apache mode - DNS mode +- [Stateless mode](https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode) # 1. How to install From c9d7daab70476e7c5f60a4e0aea06c671d91cb3d Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 10 Feb 2017 13:34:34 +0800 Subject: [PATCH 011/113] fix https://github.com/Neilpang/acme.sh/issues/593 --- dnsapi/dns_aws.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_aws.sh b/dnsapi/dns_aws.sh index 555bd70b..29d7a2cd 100755 --- a/dnsapi/dns_aws.sh +++ b/dnsapi/dns_aws.sh @@ -93,7 +93,7 @@ _get_root() { fi if _contains "$response" "$h."; then - hostedzone="$(echo "$response" | _egrep_o "[^<]*<.Id>$h.<.Name>.*<.HostedZone>")" + hostedzone="$(echo "$response" | sed 's//#&/g' | tr '#' '\n' | _egrep_o "[^<]*<.Id>$h.<.Name>.*<.HostedZone>")" _debug hostedzone "$hostedzone" if [ -z "$hostedzone" ]; then _err "Error, can not get hostedzone." From 34f25fa590ba9917ecfd8f70887635ed5d2c467d Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 10 Feb 2017 18:20:15 +0800 Subject: [PATCH 012/113] support mingw/git-bash --- acme.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index cb99b5ab..4279ddfc 100755 --- a/acme.sh +++ b/acme.sh @@ -896,7 +896,11 @@ _createcsr() { _csr_cn="$(_idn "$domain")" _debug2 _csr_cn "$_csr_cn" - $OPENSSL_BIN req -new -sha256 -key "$csrkey" -subj "/CN=$_csr_cn" -config "$csrconf" -out "$csr" + if _contains "$(uname -a)" "MINGW"; then + $OPENSSL_BIN req -new -sha256 -key "$csrkey" -subj "//CN=$_csr_cn" -config "$csrconf" -out "$csr" + else + $OPENSSL_BIN req -new -sha256 -key "$csrkey" -subj "/CN=$_csr_cn" -config "$csrconf" -out "$csr" + fi } #_signcsr key csr conf cert From d8beaf727f84ac8149e290b5695dc35634e195e2 Mon Sep 17 00:00:00 2001 From: hebbet Date: Fri, 10 Feb 2017 13:26:17 +0100 Subject: [PATCH 013/113] remove extra space remove extra space from help --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 4279ddfc..8eb52d3e 100755 --- a/acme.sh +++ b/acme.sh @@ -4238,7 +4238,7 @@ Commands: --version, -v Show version info. --install Install $PROJECT_NAME to your system. --uninstall Uninstall $PROJECT_NAME, and uninstall the cron job. - --upgrade Upgrade $PROJECT_NAME to the latest code from $PROJECT . + --upgrade Upgrade $PROJECT_NAME to the latest code from $PROJECT. --issue Issue a cert. --signcsr Issue a cert from an existing csr. --deploy Deploy the cert to your server. From 4e4a6d83973fa0580ef8b2f1d7d0312fdd671543 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 10 Feb 2017 20:55:25 +0800 Subject: [PATCH 014/113] better hexdump fix https://github.com/Neilpang/acme.sh/issues/595 --- acme.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 4279ddfc..b544f531 100755 --- a/acme.sh +++ b/acme.sh @@ -364,8 +364,16 @@ _ascii_hex() { #input:"abc" #output: " 61 62 63" _hex_dump() { - #in wired some system, the od command is missing. - if ! od -A n -v -t x1 | tr -d "\r\t" | tr -s " " | sed "s/ $//" | tr -d "\n" 2>/dev/null; then + if _exists od; then + od -A n -v -t x1 | tr -s " " | sed 's/ $//' | tr -d "\r\t\n" + elif _exists hexdump; then + _debug3 "using hexdump" + hexdump -v -e '/1 ""' -e '/1 " %02x" ""' + elif _exists xxd; then + _debug3 "using xxd" + xxd -ps -c 20 -i | sed "s/ 0x/ /g" | tr -d ",\n" | tr -s " " + else + _debug3 "using _ascii_hex" str=$(cat) _ascii_hex "$str" fi From 04e0f87c0387e81b100f94de9a511e47f0b49f75 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 11 Feb 2017 13:24:00 +0800 Subject: [PATCH 015/113] add doc --- deploy/README.md | 31 ++++++++++++++++++++++++++++++- deploy/cpanel.sh | 29 +++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 deploy/cpanel.sh diff --git a/deploy/README.md b/deploy/README.md index 580eaac8..fcdf8019 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -1 +1,30 @@ -#Using deploy api +# Using deploy api + +Here are the scripts to deploy the certs/key to the server/services. + +## 1. Deploy the certs to your cpanel host. + +(cpanel deploy hook is not finished yet, this is just an example.) + +Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert). + +Then you can deploy now: + +```sh +export DEPLOY_CPANEL_USER=myusername +export DEPLOY_CPANEL_PASSWORD=PASSWORD +acme.sh --deploy -d example.com --deploy --deploy-hook cpanel +``` + +## 2. Deploy ssl cert on kong proxy engine based on api. + +Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert). + +(TODO) + +## 3. Deploy the cert to remote server through SSH access. + +(TODO) + + + diff --git a/deploy/cpanel.sh b/deploy/cpanel.sh new file mode 100644 index 00000000..bf1332ff --- /dev/null +++ b/deploy/cpanel.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env sh + +#Here is the script to deploy the cert to your cpanel account by the cpanel APIs. + +#returns 0 means success, otherwise error. + +#export DEPLOY_CPANEL_USER=myusername +#export DEPLOY_CPANEL_PASSWORD=PASSWORD + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +cpanel_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 + +} From 0984585d58cc87a8b49ee93ad8d5c6924c88a79d Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 11 Feb 2017 13:36:52 +0800 Subject: [PATCH 016/113] minor, rename command --- acme.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/acme.sh b/acme.sh index 04bf55ad..67c72068 100755 --- a/acme.sh +++ b/acme.sh @@ -4263,8 +4263,8 @@ Commands: --toPkcs Export the certificate and key to a pfx file. --update-account Update account info. --register-account Register account key. - --createAccountKey, -cak Create an account private key, professional use. - --createDomainKey, -cdk Create an domain private key, professional use. + --create-account-key Create an account private key, professional use. + --create-domain-key Create an domain private key, professional use. --createCSR, -ccsr Create CSR , professional use. --deactivate Deactivate the domain authz, professional use. @@ -4506,10 +4506,10 @@ _process() { --toPkcs) _CMD="toPkcs" ;; - --createAccountKey | --createaccountkey | -cak) + --createAccountKey | --createaccountkey | -cak | --create-account-key) _CMD="createAccountKey" ;; - --createDomainKey | --createdomainkey | -cdk) + --createDomainKey | --createdomainkey | -cdk | --create-domain-key) _CMD="createDomainKey" ;; --createCSR | --createcsr | -ccr) From d47c5eaf604743867ae0ca2fdeda0d2108747c4e Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 11 Feb 2017 20:13:21 +0800 Subject: [PATCH 017/113] update issue template --- .github/ISSUE_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 4abbb7ab..f7d4d1d7 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,4 +1,6 @@ Steps to reproduce ------------------ - Debug log ----------------- From e2edf2083384f6ceae71d89e569052b1ba3b827d Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 11 Feb 2017 21:15:36 +0800 Subject: [PATCH 018/113] support syslog --- acme.sh | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 7 deletions(-) diff --git a/acme.sh b/acme.sh index 67c72068..9929dfad 100755 --- a/acme.sh +++ b/acme.sh @@ -61,6 +61,10 @@ LOG_LEVEL_2=2 LOG_LEVEL_3=3 DEFAULT_LOG_LEVEL="$LOG_LEVEL_1" +SYSLOG_INFO="user.info" +SYSLOG_ERROR="user.error" +SYSLOG_DEBUG="user.debug" + _DEBUG_WIKI="https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh" _PREPARE_LINK="https://github.com/Neilpang/acme.sh/wiki/Install-preparations" @@ -128,18 +132,30 @@ _dlg_versions() { fi } +#class +_syslog() { + if [ -z "$SYS_LOG" ] || [ "$SYS_LOG" = "0" ]; then + return + fi + _logclass="$1" + shift + logger -i -t "$PROJECT_NAME" -p "$_logclass" "$(_printargs "$@")" >/dev/null 2>&1 +} + _log() { + _syslog "$@" [ -z "$LOG_FILE" ] && return + shift _printargs "$@" >>"$LOG_FILE" } _info() { - _log "$@" + _log "$SYSLOG_INFO" "$@" _printargs "$@" } _err() { - _log "$@" + _log "$SYSLOG_ERROR" "$@" if [ -z "$NO_TIMESTAMP" ] || [ "$NO_TIMESTAMP" = "0" ]; then printf -- "%s" "[$(date)] " >&2 fi @@ -159,7 +175,7 @@ _usage() { _debug() { if [ -z "$LOG_LEVEL" ] || [ "$LOG_LEVEL" -ge "$LOG_LEVEL_1" ]; then - _log "$@" + _log "$SYSLOG_DEBUG" "$@" fi if [ -z "$DEBUG" ]; then return @@ -169,19 +185,19 @@ _debug() { _debug2() { if [ "$LOG_LEVEL" ] && [ "$LOG_LEVEL" -ge "$LOG_LEVEL_2" ]; then - _log "$@" + _log "$SYSLOG_DEBUG" "$@" fi if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then - _debug "$@" + _printargs "$@" >&2 fi } _debug3() { if [ "$LOG_LEVEL" ] && [ "$LOG_LEVEL" -ge "$LOG_LEVEL_3" ]; then - _log "$@" + _log "$SYSLOG_DEBUG" "$@" fi if [ "$DEBUG" ] && [ "$DEBUG" -ge "3" ]; then - _debug "$@" + _printargs "$@" >&2 fi } @@ -4286,6 +4302,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. These parameters are to install the cert to nginx/apache or anyother server after issue/renew a cert: @@ -4444,6 +4461,7 @@ _process() { _listen_v4="" _listen_v6="" _openssl_bin="" + _syslog="" while [ ${#} -gt 0 ]; do case "${1}" in @@ -4774,6 +4792,15 @@ _process() { LOG_LEVEL="$_log_level" shift ;; + --syslog) + if ! _startswith "$2" '-'; then + _syslog="$2" + shift + fi + if [ -z "$_syslog" ]; then + _syslog="1" + fi + ;; --auto-upgrade) _auto_upgrade="$2" if [ -z "$_auto_upgrade" ] || _startswith "$_auto_upgrade" '-'; then @@ -4821,6 +4848,21 @@ _process() { LOG_LEVEL="$_log_level" fi + if [ "$_syslog" ]; then + if _exists logger; then + if [ "$_syslog" = "0" ]; then + _clearaccountconf "SYS_LOG" + else + _saveaccountconf "SYS_LOG" "$_syslog" + fi + SYS_LOG="$_syslog" + else + _err "The 'logger' command is not found, can not enable syslog." + _clearaccountconf "SYS_LOG" + SYS_LOG="" + fi + fi + _processAccountConf fi @@ -4913,6 +4955,21 @@ _process() { if [ "$_log_level" ]; then _saveaccountconf "LOG_LEVEL" "$_log_level" fi + + if [ "$_syslog" ]; then + if _exists logger; then + if [ "$_syslog" = "0" ]; then + _clearaccountconf "SYS_LOG" + else + _saveaccountconf "SYS_LOG" "$_syslog" + fi + else + _err "The 'logger' command is not found, can not enable syslog." + _clearaccountconf "SYS_LOG" + SYS_LOG="" + fi + fi + _processAccountConf fi From cd9c3a79e556c6221d3fe15aaa4dc3f50689bc98 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 11 Feb 2017 21:29:36 +0800 Subject: [PATCH 019/113] update doc --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2dd178d8..f1c74806 100644 --- a/README.md +++ b/README.md @@ -147,7 +147,7 @@ You **MUST** use this command to copy the certs to the target files, **DO NOT** **Apache** example: ```bash -acme.sh --installcert -d example.com \ +acme.sh --install-cert -d example.com \ --certpath /path/to/certfile/in/apache/cert.pem \ --keypath /path/to/keyfile/in/apache/key.pem \ --fullchainpath /path/to/fullchain/certfile/apache/fullchain.pem \ @@ -156,7 +156,7 @@ acme.sh --installcert -d example.com \ **Nginx** example: ```bash -acme.sh --installcert -d example.com \ +acme.sh --install-cert -d example.com \ --keypath /path/to/keyfile/in/nginx/key.pem \ --fullchainpath /path/to/fullchain/nginx/cert.pem \ --reloadcmd "service nginx force-reload" From fd72cced13e37c3a5f877e14825bac2d6c455a2a Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 12 Feb 2017 10:10:53 +0800 Subject: [PATCH 020/113] move the backup file to acme home fix https://github.com/Neilpang/acme.sh/issues/488 --- acme.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/acme.sh b/acme.sh index 9929dfad..5ce5b803 100755 --- a/acme.sh +++ b/acme.sh @@ -2059,6 +2059,10 @@ _initpath() { _debug DOMAIN_PATH "$DOMAIN_PATH" fi + if [ -z "$DOMAIN_BACKUP_PATH" ]; then + DOMAIN_BACKUP_PATH="$DOMAIN_PATH" + fi + if [ -z "$DOMAIN_CONF" ]; then DOMAIN_CONF="$DOMAIN_PATH/$domain.conf" fi @@ -3612,7 +3616,7 @@ _installcert() { _info "Installing cert to:$Le_RealCertPath" if [ -f "$Le_RealCertPath" ] && [ ! "$IS_RENEW" ]; then - cp "$Le_RealCertPath" "$Le_RealCertPath".bak + cp "$Le_RealCertPath" "$DOMAIN_BACKUP_PATH/cert.bak" fi cat "$CERT_PATH" >"$Le_RealCertPath" fi @@ -3625,7 +3629,7 @@ _installcert() { cat "$CA_CERT_PATH" >>"$Le_RealCACertPath" else if [ -f "$Le_RealCACertPath" ] && [ ! "$IS_RENEW" ]; then - cp "$Le_RealCACertPath" "$Le_RealCACertPath".bak + cp "$Le_RealCACertPath" "$DOMAIN_BACKUP_PATH/ca.bak" fi cat "$CA_CERT_PATH" >"$Le_RealCACertPath" fi @@ -3635,7 +3639,7 @@ _installcert() { _info "Installing key to:$Le_RealKeyPath" if [ -f "$Le_RealKeyPath" ] && [ ! "$IS_RENEW" ]; then - cp "$Le_RealKeyPath" "$Le_RealKeyPath".bak + cp "$Le_RealKeyPath" "$DOMAIN_BACKUP_PATH/key.bak" fi cat "$CERT_KEY_PATH" >"$Le_RealKeyPath" fi @@ -3644,7 +3648,7 @@ _installcert() { _info "Installing full chain to:$Le_RealFullChainPath" if [ -f "$Le_RealFullChainPath" ] && [ ! "$IS_RENEW" ]; then - cp "$Le_RealFullChainPath" "$Le_RealFullChainPath".bak + cp "$Le_RealFullChainPath" "$DOMAIN_BACKUP_PATH/fullchain.bak" fi cat "$CERT_FULLCHAIN_PATH" >"$Le_RealFullChainPath" fi From d88f8e862bc33d4d989be7acb1e1f05049e0163f Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 12 Feb 2017 10:20:50 +0800 Subject: [PATCH 021/113] move backup to sub folder. --- acme.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 5ce5b803..f03501b4 100755 --- a/acme.sh +++ b/acme.sh @@ -2060,7 +2060,7 @@ _initpath() { fi if [ -z "$DOMAIN_BACKUP_PATH" ]; then - DOMAIN_BACKUP_PATH="$DOMAIN_PATH" + DOMAIN_BACKUP_PATH="$DOMAIN_PATH/backup" fi if [ -z "$DOMAIN_CONF" ]; then @@ -3616,6 +3616,7 @@ _installcert() { _info "Installing cert to:$Le_RealCertPath" if [ -f "$Le_RealCertPath" ] && [ ! "$IS_RENEW" ]; then + mkdir -p "$DOMAIN_BACKUP_PATH" cp "$Le_RealCertPath" "$DOMAIN_BACKUP_PATH/cert.bak" fi cat "$CERT_PATH" >"$Le_RealCertPath" @@ -3629,6 +3630,7 @@ _installcert() { cat "$CA_CERT_PATH" >>"$Le_RealCACertPath" else if [ -f "$Le_RealCACertPath" ] && [ ! "$IS_RENEW" ]; then + mkdir -p "$DOMAIN_BACKUP_PATH" cp "$Le_RealCACertPath" "$DOMAIN_BACKUP_PATH/ca.bak" fi cat "$CA_CERT_PATH" >"$Le_RealCACertPath" @@ -3639,6 +3641,7 @@ _installcert() { _info "Installing key to:$Le_RealKeyPath" if [ -f "$Le_RealKeyPath" ] && [ ! "$IS_RENEW" ]; then + mkdir -p "$DOMAIN_BACKUP_PATH" cp "$Le_RealKeyPath" "$DOMAIN_BACKUP_PATH/key.bak" fi cat "$CERT_KEY_PATH" >"$Le_RealKeyPath" @@ -3648,6 +3651,7 @@ _installcert() { _info "Installing full chain to:$Le_RealFullChainPath" if [ -f "$Le_RealFullChainPath" ] && [ ! "$IS_RENEW" ]; then + mkdir -p "$DOMAIN_BACKUP_PATH" cp "$Le_RealFullChainPath" "$DOMAIN_BACKUP_PATH/fullchain.bak" fi cat "$CERT_FULLCHAIN_PATH" >"$Le_RealFullChainPath" 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 022/113] 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 023/113] 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 024/113] 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 025/113] 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 026/113] 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 027/113] 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 028/113] 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 029/113] 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 030/113] 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 031/113] 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 032/113] 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 033/113] 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 034/113] 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 035/113] 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 036/113] 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 9d725af60221519a8ac4cc976a0af49ff0be2e26 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 13 Feb 2017 23:29:37 +0800 Subject: [PATCH 037/113] support nginx mode --- README.md | 32 ++++++-- acme.sh | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 235 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index f1c74806..edc4555c 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,7 @@ https://github.com/Neilpang/acmetest - Webroot mode - Standalone mode - Apache mode +- Nginx mode - DNS mode - [Stateless mode](https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode) @@ -215,8 +216,27 @@ acme.sh --issue --apache -d example.com -d www.example.com -d cp.example.com More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert +# 7. Use Nginx mode -# 7. Use DNS mode: +**(requires you to be root/sudoer, since it is required to interact with Nginx server)** + +If you are running a web server, Apache or Nginx, it is recommended to use the `Webroot mode`. + +Particularly, if you are running an nginx server, you can use nginx mode instead. This mode doesn't write any files to your web root folder. + +Just set string "nginx" as the second argument. + +It will configure nginx server automatically to verify the domain and then restore the nginx config to the original version. + +So, the config is not changed. + +``` +acme.sh --issue --nginx -d example.com -d www.example.com -d cp.example.com +``` + +More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert + +# 8. Use DNS mode: Support the `dns-01` challenge. @@ -247,7 +267,7 @@ acme.sh --renew -d example.com Ok, it's finished. -# 8. Automatic DNS API integration +# 9. Automatic DNS API integration If your DNS provider supports API access, we can use that API to automatically issue the certs. @@ -280,7 +300,7 @@ If your DNS provider is not on the supported list above, you can write your own For more details: [How to use DNS API](dnsapi) -# 9. Issue ECC certificates +# 10. Issue ECC certificates `Let's Encrypt` can now issue **ECDSA** certificates. @@ -311,7 +331,7 @@ Valid values are: 3. **ec-521 (secp521r1, "ECDSA P-521", which is not supported by Let's Encrypt yet.)** -# 10. How to renew the issued certs +# 11. How to renew the issued certs No, you don't need to renew the certs manually. All the certs will be renewed automatically every **60** days. @@ -328,7 +348,7 @@ acme.sh --renew -d example.com --force --ecc ``` -# 11. How to upgrade `acme.sh` +# 12. How to upgrade `acme.sh` acme.sh is in constant development, so it's strongly recommended to use the latest code. @@ -353,7 +373,7 @@ acme.sh --upgrade --auto-upgrade 0 ``` -# 12. Issue a cert from an existing CSR +# 13. Issue a cert from an existing CSR https://github.com/Neilpang/acme.sh/wiki/Issue-a-cert-from-existing-CSR diff --git a/acme.sh b/acme.sh index f03501b4..612c2094 100755 --- a/acme.sh +++ b/acme.sh @@ -45,6 +45,8 @@ MODE_STATELESS="stateless" STATE_VERIFIED="verified_ok" +NGINX="nginx:" + BEGIN_CSR="-----BEGIN CERTIFICATE REQUEST-----" END_CSR="-----END CERTIFICATE REQUEST-----" @@ -2277,10 +2279,186 @@ Allow from all return 0 } +#find the real nginx conf file +#backup +#set the nginx conf +#returns the real nginx conf file +_setNginx() { + _d="$1" + _croot="$2" + _thumbpt="$3" + if ! _exists "nginx"; then + _err "nginx command is not found." + return 1 + fi + FOUND_REAL_NGINX_CONF="" + BACKUP_NGINX_CONF="" + _debug _croot "$_croot" + _start_f="$(echo "$_croot" | cut -d : -f 2)" + _debug _start_f "$_start_f" + if [ -z "$_start_f" ]; then + _debug "find start conf from nginx command" + if [ -z "$NGINX_CONF" ]; then + NGINX_CONF="$(nginx -V 2>&1 | _egrep_o "--conf-path=[^ ]* " | tr -d " ")" + _debug NGINX_CONF "$NGINX_CONF" + NGINX_CONF="$(echo "$NGINX_CONF" | cut -d = -f 2)" + _debug NGINX_CONF "$NGINX_CONF" + if [ ! -f "$NGINX_CONF" ]; then + _err "'$NGINX_CONF' doesn't exist." + NGINX_CONF="" + return 1 + fi + _debug "Found nginx conf file:$NGINX_CONF" + fi + _start_f="$NGINX_CONF" + fi + _info "Start detect nginx conf for $_d from:$_start_f" + if ! _checkConf "$_d" "$_start_f"; then + "Can not find conf file for domain $d" + return 1 + fi + _info "Found conf file: $FOUND_REAL_NGINX_CONF" + + mkdir -p "$DOMAIN_BACKUP_PATH" + _backup_conf="$DOMAIN_BACKUP_PATH/$_d.nginx.conf" + _debug _backup_conf "$_backup_conf" + BACKUP_NGINX_CONF="$_backup_conf" + _info "Backup $FOUND_REAL_NGINX_CONF to $_backup_conf" + if ! cp "$FOUND_REAL_NGINX_CONF" "$_backup_conf"; then + _err "backup error." + FOUND_REAL_NGINX_CONF="" + return 1 + fi + + _info "Check the nginx conf before setting up." + if ! _exec "nginx -t" >/dev/null; then + _exec_err + return 1 + fi + + _info "OK, Set up nginx config file" + _ln=$(grep -n "^ *server_name.* $_d" "$_backup_conf" | cut -d : -f 1 | tr -d "\n") + _debug "_ln" "$_ln" + + if ! sed -n "1,${_ln}p" "$_backup_conf" > "$FOUND_REAL_NGINX_CONF"; then + cat "$_backup_conf" > "$FOUND_REAL_NGINX_CONF" + _err "write nginx conf error, but don't worry, the file is restored to the original version." + return 1 + fi + + echo " +location ~ \"^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)\$\" { + default_type text/plain; + return 200 \"\$1.$_thumbpt\"; +} +" >> "$FOUND_REAL_NGINX_CONF" + + _ln=$(_math $_ln + 1) + if ! sed -n "${_ln},99999p" "$_backup_conf" >> "$FOUND_REAL_NGINX_CONF"; then + cat "$_backup_conf" > "$FOUND_REAL_NGINX_CONF" + _err "write nginx conf error, but don't worry, the file is restored." + return 1 + fi + + _info "nginx conf is done, let's check it again." + if ! _exec "nginx -t" >/dev/null; then + _exec_err + _err "It seems that nginx conf was broken, let's restore." + cat "$_backup_conf" > "$FOUND_REAL_NGINX_CONF" + return 1 + fi + + _info "Reload nginx" + if ! _exec "nginx -s reload" >/dev/null; then + _exec_err + _err "It seems that nginx reload error, let's restore." + cat "$_backup_conf" > "$FOUND_REAL_NGINX_CONF" + return 1 + fi + + return 0 +} + +#d , conf +_checkConf() { + _d="$1" + _c_file="$2" + _debug "Start _checkConf from:$_c_file" + if [ ! -f "$2" ] && ! echo "$2" | grep '*$' >/dev/null && echo "$2" | grep '*' >/dev/null; then + _debug "wildcard" + for _w_f in $2; do + if _checkConf "$1" "$_w_f"; then + return 0 + fi + done + #not found + return 1 + elif [ -f "$2" ]; then + _debug "single" + if _isRealNginxConf "$1" "$2"; then + _debug "$2 is found." + FOUND_REAL_NGINX_CONF="$2" + return 0 + fi + if grep "^ *include *.*;" "$2" >/dev/null; then + _debug "Try include files" + for included in $(grep "^ *include *.*;" "$2"| sed "s/include //" | tr -d " ;" ); do + _debug "check included $included" + if _checkConf "$1" "$included"; then + return 0 + fi + done + fi + return 1 + else + _debug "$2 not found." + return 1 + fi + return 1 +} + +#d , conf +_isRealNginxConf() { + _debug "_isRealNginxConf $1 $2" + if [ -f "$2" ] && grep "^ *server_name " "$2" | grep " $1" >/dev/null; then + return 0 + else + return 1 + fi +} + +#restore all the nginx conf +_restoreNginx() { + if [ -z "$NGINX_VLIST" ]; then + _debug "No need to restore nginx, skip." + return + fi + _debug "_restoreNginx" + _debug "NGINX_VLIST" "$NGINX_VLIST" + + for ng_entry in $(echo "$NGINX_VLIST" | tr "$dvsep" ' '); do + _debug "ng_entry" "$ng_entry" + _nd=$(echo "$ng_entry" | cut -d "$sep" -f 1) + _ngconf=$(echo "$ng_entry" | cut -d "$sep" -f 2) + _ngbackupconf=$(echo "$ng_entry" | cut -d "$sep" -f 3) + _info "Restoring from $_ngbackupconf to $_ngconf" + cat "$_ngbackupconf" > "$_ngconf" + done + + _info "Reload nginx" + if ! _exec "nginx -s reload" >/dev/null; then + _exec_err + _err "It seems that nginx reload error, please report bug." + return 1 + fi + return 0 +} + _clearup() { _stopserver "$serverproc" serverproc="" _restoreApache + _restoreNginx _clearupdns if [ -z "$DEBUG" ]; then rm -f "$TLS_CONF" @@ -2822,6 +3000,7 @@ issue() { _info "Getting domain auth token for each domain" sep='#' + dvsep=',' if [ -z "$vlist" ]; then alldomains=$(echo "$Le_Domain,$Le_Alt" | tr ',' ' ') _index=1 @@ -2829,7 +3008,7 @@ issue() { for d in $alldomains; do _info "Getting webroot for domain" "$d" _w="$(echo $Le_Webroot | cut -d , -f $_index)" - _info _w "$_w" + _debug _w "$_w" if [ "$_w" ]; then _currentRoot="$_w" fi @@ -2881,13 +3060,13 @@ issue() { dvlist="$d$sep$keyauthorization$sep$uri$sep$vtype$sep$_currentRoot" _debug dvlist "$dvlist" - vlist="$vlist$dvlist," + vlist="$vlist$dvlist$dvsep" done - + _debug vlist "$vlist" #add entry dnsadded="" - ventries=$(echo "$vlist" | tr ',' ' ') + ventries=$(echo "$vlist" | tr "$dvsep" ' ') for ventry in $ventries; do d=$(echo "$ventry" | cut -d "$sep" -f 1) keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2) @@ -2970,10 +3149,11 @@ issue() { _sleep "$Le_DNSSleep" fi + NGINX_VLIST="" _debug "ok, let's start to verify" _ncIndex=1 - ventries=$(echo "$vlist" | tr ',' ' ') + ventries=$(echo "$vlist" | tr "$dvsep" ' ') for ventry in $ventries; do d=$(echo "$ventry" | cut -d "$sep" -f 1) keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2) @@ -3012,6 +3192,22 @@ issue() { elif [ "$_currentRoot" = "$MODE_STATELESS" ]; then _info "Stateless mode for domain:$d" _sleep 1 + elif _startswith "$_currentRoot" "$NGINX"; then + _info "Nginx mode for domain:$d" + #set up nginx server + FOUND_REAL_NGINX_CONF="" + BACKUP_NGINX_CONF="" + if ! _setNginx "$d" "$_currentRoot" "$thumbprint"; then + _clearup + _on_issue_err + return 1 + else + _realConf="$FOUND_REAL_NGINX_CONF" + _backup="$BACKUP_NGINX_CONF" + _debug _realConf "$_realConf" + NGINX_VLIST="$NGINX_VLIST$d$sep$_realConf$sep$_backup$dvsep" + fi + _sleep 1 else if [ "$_currentRoot" = "apache" ]; then wellknown_path="$ACME_DIR" @@ -4629,6 +4825,14 @@ _process() { _webroot="$_webroot,$wvalue" fi ;; + --nginx) + wvalue="$NGINX" + if [ -z "$_webroot" ]; then + _webroot="$wvalue" + else + _webroot="$_webroot,$wvalue" + fi + ;; --tls) wvalue="$W_TLS" if [ -z "$_webroot" ]; then From 03f8d6e946d642c529927668c078df2025f7aa22 Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 14 Feb 2017 22:03:48 +0800 Subject: [PATCH 038/113] fix https://github.com/Neilpang/acme.sh/issues/615 --- acme.sh | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/acme.sh b/acme.sh index 612c2094..349e1b39 100755 --- a/acme.sh +++ b/acme.sh @@ -46,6 +46,8 @@ MODE_STATELESS="stateless" STATE_VERIFIED="verified_ok" NGINX="nginx:" +NGINX_START="#ACME_NGINX_START" +NGINX_END="#ACME_NGINX_END" BEGIN_CSR="-----BEGIN CERTIFICATE REQUEST-----" END_CSR="-----END CERTIFICATE REQUEST-----" @@ -2312,13 +2314,26 @@ _setNginx() { fi _start_f="$NGINX_CONF" fi - _info "Start detect nginx conf for $_d from:$_start_f" + _debug "Start detect nginx conf for $_d from:$_start_f" if ! _checkConf "$_d" "$_start_f"; then "Can not find conf file for domain $d" return 1 fi _info "Found conf file: $FOUND_REAL_NGINX_CONF" + _ln=$(grep -n "^ *server_name.* $_d" "$FOUND_REAL_NGINX_CONF" | cut -d : -f 1 | tr -d "\n") + _debug "_ln" "$_ln" + + _lnn=$(_math $_ln + 1) + _debug _lnn "$_lnn" + _start_tag="$(sed -n "$_lnn,${_lnn}p" "$FOUND_REAL_NGINX_CONF")" + _debug "_start_tag" "$_start_tag" + if [ "$_start_tag" = "$NGINX_START" ]; then + _info "The domain $_d is already configured, skip" + FOUND_REAL_NGINX_CONF="" + return 0 + fi + mkdir -p "$DOMAIN_BACKUP_PATH" _backup_conf="$DOMAIN_BACKUP_PATH/$_d.nginx.conf" _debug _backup_conf "$_backup_conf" @@ -2337,25 +2352,23 @@ _setNginx() { fi _info "OK, Set up nginx config file" - _ln=$(grep -n "^ *server_name.* $_d" "$_backup_conf" | cut -d : -f 1 | tr -d "\n") - _debug "_ln" "$_ln" if ! sed -n "1,${_ln}p" "$_backup_conf" > "$FOUND_REAL_NGINX_CONF"; then - cat "$_backup_conf" > "$FOUND_REAL_NGINX_CONF" + cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF" _err "write nginx conf error, but don't worry, the file is restored to the original version." return 1 fi - echo " + echo "$NGINX_START location ~ \"^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)\$\" { default_type text/plain; return 200 \"\$1.$_thumbpt\"; } -" >> "$FOUND_REAL_NGINX_CONF" +#NGINX_START +" >>"$FOUND_REAL_NGINX_CONF" - _ln=$(_math $_ln + 1) - if ! sed -n "${_ln},99999p" "$_backup_conf" >> "$FOUND_REAL_NGINX_CONF"; then - cat "$_backup_conf" > "$FOUND_REAL_NGINX_CONF" + if ! sed -n "${_lnn},99999p" "$_backup_conf" >>"$FOUND_REAL_NGINX_CONF"; then + cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF" _err "write nginx conf error, but don't worry, the file is restored." return 1 fi @@ -2364,7 +2377,7 @@ location ~ \"^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)\$\" { if ! _exec "nginx -t" >/dev/null; then _exec_err _err "It seems that nginx conf was broken, let's restore." - cat "$_backup_conf" > "$FOUND_REAL_NGINX_CONF" + cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF" return 1 fi @@ -2372,7 +2385,7 @@ location ~ \"^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)\$\" { if ! _exec "nginx -s reload" >/dev/null; then _exec_err _err "It seems that nginx reload error, let's restore." - cat "$_backup_conf" > "$FOUND_REAL_NGINX_CONF" + cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF" return 1 fi @@ -3201,7 +3214,9 @@ issue() { _clearup _on_issue_err return 1 - else + fi + + if [ "$FOUND_REAL_NGINX_CONF" ]; then _realConf="$FOUND_REAL_NGINX_CONF" _backup="$BACKUP_NGINX_CONF" _debug _realConf "$_realConf" From 5d943a35f8341660c0429e11ea5299bfb008689d Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 14 Feb 2017 22:12:58 +0800 Subject: [PATCH 039/113] fix https://github.com/Neilpang/acme.sh/issues/616 --- acme.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/acme.sh b/acme.sh index 349e1b39..6234500e 100755 --- a/acme.sh +++ b/acme.sh @@ -2442,14 +2442,14 @@ _isRealNginxConf() { #restore all the nginx conf _restoreNginx() { - if [ -z "$NGINX_VLIST" ]; then + if [ -z "$NGINX_RESTORE_VLIST" ]; then _debug "No need to restore nginx, skip." return fi _debug "_restoreNginx" - _debug "NGINX_VLIST" "$NGINX_VLIST" + _debug "NGINX_RESTORE_VLIST" "$NGINX_RESTORE_VLIST" - for ng_entry in $(echo "$NGINX_VLIST" | tr "$dvsep" ' '); do + for ng_entry in $(echo "$NGINX_RESTORE_VLIST" | tr "$dvsep" ' '); do _debug "ng_entry" "$ng_entry" _nd=$(echo "$ng_entry" | cut -d "$sep" -f 1) _ngconf=$(echo "$ng_entry" | cut -d "$sep" -f 2) @@ -3162,7 +3162,7 @@ issue() { _sleep "$Le_DNSSleep" fi - NGINX_VLIST="" + NGINX_RESTORE_VLIST="" _debug "ok, let's start to verify" _ncIndex=1 @@ -3220,7 +3220,7 @@ issue() { _realConf="$FOUND_REAL_NGINX_CONF" _backup="$BACKUP_NGINX_CONF" _debug _realConf "$_realConf" - NGINX_VLIST="$NGINX_VLIST$d$sep$_realConf$sep$_backup$dvsep" + NGINX_RESTORE_VLIST="$d$sep$_realConf$sep$_backup$dvsep$NGINX_RESTORE_VLIST" fi _sleep 1 else From 302c41edc9c8696f8f266352449eb7e8e2c79533 Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 14 Feb 2017 22:41:34 +0800 Subject: [PATCH 040/113] fix format --- acme.sh | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/acme.sh b/acme.sh index 6234500e..6121224f 100755 --- a/acme.sh +++ b/acme.sh @@ -2353,7 +2353,7 @@ _setNginx() { _info "OK, Set up nginx config file" - if ! sed -n "1,${_ln}p" "$_backup_conf" > "$FOUND_REAL_NGINX_CONF"; then + if ! sed -n "1,${_ln}p" "$_backup_conf" >"$FOUND_REAL_NGINX_CONF"; then cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF" _err "write nginx conf error, but don't worry, the file is restored to the original version." return 1 @@ -2377,7 +2377,7 @@ location ~ \"^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)\$\" { if ! _exec "nginx -t" >/dev/null; then _exec_err _err "It seems that nginx conf was broken, let's restore." - cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF" + cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF" return 1 fi @@ -2385,7 +2385,7 @@ location ~ \"^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)\$\" { if ! _exec "nginx -s reload" >/dev/null; then _exec_err _err "It seems that nginx reload error, let's restore." - cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF" + cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF" return 1 fi @@ -2415,7 +2415,7 @@ _checkConf() { fi if grep "^ *include *.*;" "$2" >/dev/null; then _debug "Try include files" - for included in $(grep "^ *include *.*;" "$2"| sed "s/include //" | tr -d " ;" ); do + for included in $(grep "^ *include *.*;" "$2" | sed "s/include //" | tr -d " ;"); do _debug "check included $included" if _checkConf "$1" "$included"; then return 0 @@ -2433,11 +2433,17 @@ _checkConf() { #d , conf _isRealNginxConf() { _debug "_isRealNginxConf $1 $2" - if [ -f "$2" ] && grep "^ *server_name " "$2" | grep " $1" >/dev/null; then + if [ -f "$2" ]; then + for _fln in $(grep -n "^ *server_name.* $1" "$2" | cut -d : -f 1); do + _debug _fln "$_fln" + if [ "$_fln" ]; then + _listen=$(cat "$2" | _head_n "$_fln" | grep "^ *listen .*" | _tail_n 1) + fi + done return 0 - else - return 1 fi + + return 1 } #restore all the nginx conf @@ -2455,7 +2461,7 @@ _restoreNginx() { _ngconf=$(echo "$ng_entry" | cut -d "$sep" -f 2) _ngbackupconf=$(echo "$ng_entry" | cut -d "$sep" -f 3) _info "Restoring from $_ngbackupconf to $_ngconf" - cat "$_ngbackupconf" > "$_ngconf" + cat "$_ngbackupconf" >"$_ngconf" done _info "Reload nginx" @@ -3215,7 +3221,7 @@ issue() { _on_issue_err return 1 fi - + if [ "$FOUND_REAL_NGINX_CONF" ]; then _realConf="$FOUND_REAL_NGINX_CONF" _backup="$BACKUP_NGINX_CONF" From 9f90618a707750475604f5ad8bf726f62f281c67 Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 14 Feb 2017 23:57:00 +0800 Subject: [PATCH 041/113] fix https://github.com/Neilpang/acme.sh/issues/617 --- acme.sh | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/acme.sh b/acme.sh index 6121224f..a846b97a 100755 --- a/acme.sh +++ b/acme.sh @@ -2294,6 +2294,7 @@ _setNginx() { return 1 fi FOUND_REAL_NGINX_CONF="" + FOUND_REAL_NGINX_CONF_LN="" BACKUP_NGINX_CONF="" _debug _croot "$_croot" _start_f="$(echo "$_croot" | cut -d : -f 2)" @@ -2321,7 +2322,7 @@ _setNginx() { fi _info "Found conf file: $FOUND_REAL_NGINX_CONF" - _ln=$(grep -n "^ *server_name.* $_d" "$FOUND_REAL_NGINX_CONF" | cut -d : -f 1 | tr -d "\n") + _ln=$FOUND_REAL_NGINX_CONF_LN _debug "_ln" "$_ln" _lnn=$(_math $_ln + 1) @@ -2437,12 +2438,36 @@ _isRealNginxConf() { for _fln in $(grep -n "^ *server_name.* $1" "$2" | cut -d : -f 1); do _debug _fln "$_fln" if [ "$_fln" ]; then - _listen=$(cat "$2" | _head_n "$_fln" | grep "^ *listen .*" | _tail_n 1) + _start=$(cat "$2" | _head_n "$_fln" | grep -n "^ *server *{" | _tail_n 1) + _debug "_start" "$_start" + _start_n=$(echo "$_start" | cut -d : -f 1) + _start_nn=$(_math $_start_n + 1) + _debug "_start_n" "$_start_n" + _debug "_start_nn" "$_start_nn" + + _left="$(sed -n "${_start_nn},99999p" "$2")" + _debug2 _left "$_left" + if echo "$_left" | grep -n "^ *server *{" >/dev/null; then + _end=$(echo "$_left" | grep -n "^ *server *{" | _head_n 1) + _debug "_end" "$_end" + _end_n=$(echo "$_end" | cut -d : -f 1) + _debug "_end_n" "$_end_n" + _seg_n=$(echo "$_left" | sed -n "1,${_end_n}p") + else + _seg_n="$_left" + fi + + _debug "_seg_n" "$_seg_n" + + if [ "$(echo "$_seg_n" | _egrep_o "^ *ssl *on *;")" ]; then + _debug "ssl on, skip" + return 1 + fi + FOUND_REAL_NGINX_CONF_LN=$_fln + return 0 fi done - return 0 fi - return 1 } From 6921211461a1c4d7d24c21643ead5d56d15ea532 Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 15 Feb 2017 20:24:24 +0800 Subject: [PATCH 042/113] fix debug message --- acme.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index a846b97a..5e84eeaa 100755 --- a/acme.sh +++ b/acme.sh @@ -2528,7 +2528,7 @@ _clearupdns() { txt="$(printf "%s" "$keyauthorization" | _digest "sha256" | _url_replace)" _debug txt "$txt" if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then - _info "$d is already verified, skip $vtype." + _debug "$d is already verified, skip $vtype." continue fi @@ -3096,7 +3096,7 @@ issue() { _debug keyauthorization "$keyauthorization" if printf "%s" "$response" | grep '"status":"valid"' >/dev/null 2>&1; then - _info "$d is already verified, skip." + _debug "$d is already verified, skip." keyauthorization="$STATE_VERIFIED" _debug keyauthorization "$keyauthorization" fi @@ -3118,7 +3118,7 @@ issue() { _currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5) if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then - _info "$d is already verified, skip $vtype." + _debug "$d is already verified, skip $vtype." continue fi From 7db28745c89b168d55b26ab68d696b069d091c23 Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 15 Feb 2017 20:28:50 +0800 Subject: [PATCH 043/113] start v2.6.7 --- README.md | 2 +- acme.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index edc4555c..2624690a 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ https://github.com/Neilpang/acmetest - Webroot mode - Standalone mode - Apache mode -- Nginx mode +- Nginx mode ( Beta ) - DNS mode - [Stateless mode](https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode) diff --git a/acme.sh b/acme.sh index 5e84eeaa..7a229eb6 100755 --- a/acme.sh +++ b/acme.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -VER=2.6.6 +VER=2.6.7 PROJECT_NAME="acme.sh" From 72af092cc1ac37908954366edf3abf05d7fae4be Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 15 Feb 2017 21:09:01 +0800 Subject: [PATCH 044/113] 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 7a229eb6..36443e39 100755 --- a/acme.sh +++ b/acme.sh @@ -994,7 +994,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 "^ *Public.Key:.*" | cut -d '(' -f 2 | cut -d ' ' -f 1 fi } From ad153ae041f40c4c4d730f35d9e58700ccd25906 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 16 Feb 2017 22:29:08 +0800 Subject: [PATCH 045/113] fix https://github.com/Neilpang/acme.sh/issues/622 --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 36443e39..cf9d8501 100755 --- a/acme.sh +++ b/acme.sh @@ -1610,14 +1610,14 @@ _setopt() { __val="$(echo "$__val" | sed 's/&/\\&/g')" fi text="$(cat "$__conf")" - echo "$text" | sed "s|^$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf" + printf -- "%s" "$text" | sed "s|^$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf" elif grep -n "^#$__opt$__sep" "$__conf" >/dev/null; then if _contains "$__val" "&"; then __val="$(echo "$__val" | sed 's/&/\\&/g')" fi text="$(cat "$__conf")" - echo "$text" | sed "s|^#$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf" + printf -- "%s" "$text" | sed "s|^#$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf" else _debug3 APP From 52f8b787c981ffc761694ad979d58b86390ca9f5 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 16 Feb 2017 22:37:32 +0800 Subject: [PATCH 046/113] fix https://github.com/Neilpang/acme.sh/issues/622 --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index cf9d8501..a590d10e 100755 --- a/acme.sh +++ b/acme.sh @@ -1610,14 +1610,14 @@ _setopt() { __val="$(echo "$__val" | sed 's/&/\\&/g')" fi text="$(cat "$__conf")" - printf -- "%s" "$text" | sed "s|^$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf" + printf -- "%s\n" "$text" | sed "s|^$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf" elif grep -n "^#$__opt$__sep" "$__conf" >/dev/null; then if _contains "$__val" "&"; then __val="$(echo "$__val" | sed 's/&/\\&/g')" fi text="$(cat "$__conf")" - printf -- "%s" "$text" | sed "s|^#$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf" + printf -- "%s\n" "$text" | sed "s|^#$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf" else _debug3 APP From 0bc745f68fa9ca0dbb5350bf51ea65f3865824a9 Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 17 Feb 2017 13:51:17 +0800 Subject: [PATCH 047/113] retry if nonce is invalid fix https://github.com/Neilpang/acme.sh/issues/627 --- acme.sh | 103 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 58 insertions(+), 45 deletions(-) diff --git a/acme.sh b/acme.sh index a590d10e..d3d3d507 100755 --- a/acme.sh +++ b/acme.sh @@ -1530,62 +1530,75 @@ _send_signed_request() { payload64=$(printf "%s" "$payload" | _base64 | _url_replace) _debug3 payload64 "$payload64" - if [ -z "$_CACHED_NONCE" ]; then - _debug2 "Get nonce." - nonceurl="$API/directory" - _headers="$(_get "$nonceurl" "onlyheader")" + MAX_REQUEST_RETRY_TIMES=5 + _request_retry_times=0 + while [ "${_request_retry_times}" -lt "$MAX_REQUEST_RETRY_TIMES" ]; do + _debug3 _request_retry_times "$_request_retry_times" + if [ -z "$_CACHED_NONCE" ]; then + _debug2 "Get nonce." + nonceurl="$API/directory" + _headers="$(_get "$nonceurl" "onlyheader")" - if [ "$?" != "0" ]; then - _err "Can not connect to $nonceurl to get nonce." + if [ "$?" != "0" ]; then + _err "Can not connect to $nonceurl to get nonce." + return 1 + fi + + _debug2 _headers "$_headers" + + _CACHED_NONCE="$(echo "$_headers" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)" + _debug2 _CACHED_NONCE "$_CACHED_NONCE" + else + _debug2 "Use _CACHED_NONCE" "$_CACHED_NONCE" + fi + nonce="$_CACHED_NONCE" + _debug2 nonce "$nonce" + + protected="$JWK_HEADERPLACE_PART1$nonce$JWK_HEADERPLACE_PART2" + _debug3 protected "$protected" + + protected64="$(printf "%s" "$protected" | _base64 | _url_replace)" + _debug3 protected64 "$protected64" + + if ! _sig_t="$(printf "%s" "$protected64.$payload64" | _sign "$keyfile" "sha256")"; then + _err "Sign request failed." return 1 fi + _debug3 _sig_t "$_sig_t" - _debug2 _headers "$_headers" + sig="$(printf "%s" "$_sig_t" | _url_replace)" + _debug3 sig "$sig" - _CACHED_NONCE="$(echo "$_headers" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)" - _debug2 _CACHED_NONCE "$_CACHED_NONCE" - else - _debug2 "Use _CACHED_NONCE" "$_CACHED_NONCE" - fi - nonce="$_CACHED_NONCE" - _debug2 nonce "$nonce" + body="{\"header\": $JWK_HEADER, \"protected\": \"$protected64\", \"payload\": \"$payload64\", \"signature\": \"$sig\"}" + _debug3 body "$body" - protected="$JWK_HEADERPLACE_PART1$nonce$JWK_HEADERPLACE_PART2" - _debug3 protected "$protected" + response="$(_post "$body" "$url" "$needbase64")" + _CACHED_NONCE="" - protected64="$(printf "%s" "$protected" | _base64 | _url_replace)" - _debug3 protected64 "$protected64" + if [ "$?" != "0" ]; then + _err "Can not post to $url" + return 1 + fi + _debug2 original "$response" + response="$(echo "$response" | _normalizeJson)" - if ! _sig_t="$(printf "%s" "$protected64.$payload64" | _sign "$keyfile" "sha256")"; then - _err "Sign request failed." - return 1 - fi - _debug3 _sig_t "$_sig_t" + responseHeaders="$(< "$HTTP_HEADER")" - sig="$(printf "%s" "$_sig_t" | _url_replace)" - _debug3 sig "$sig" + _debug2 responseHeaders "$responseHeaders" + _debug2 response "$response" + code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\r\n")" + _debug code "$code" - body="{\"header\": $JWK_HEADER, \"protected\": \"$protected64\", \"payload\": \"$payload64\", \"signature\": \"$sig\"}" - _debug3 body "$body" + _CACHED_NONCE="$(echo "$responseHeaders" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)" - response="$(_post "$body" "$url" "$needbase64")" - _CACHED_NONCE="" - if [ "$?" != "0" ]; then - _err "Can not post to $url" - return 1 - fi - _debug2 original "$response" - - response="$(echo "$response" | _normalizeJson)" - - responseHeaders="$(cat "$HTTP_HEADER")" - - _debug2 responseHeaders "$responseHeaders" - _debug2 response "$response" - code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\r\n")" - _debug code "$code" - - _CACHED_NONCE="$(echo "$responseHeaders" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)" + if _contains "$response" "JWS has invalid anti-replay nonce"; then + _info "It seems the CA server is busy now, let's wait and retry." + _request_retry_times=$(_math "$_request_retry_times" + 1) + _sleep 5 + continue + fi + break; + done } From b7924ce58b09927c606615b7a485d6870073d0b0 Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 17 Feb 2017 14:40:58 +0800 Subject: [PATCH 048/113] fix format --- acme.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index d3d3d507..7eee2909 100755 --- a/acme.sh +++ b/acme.sh @@ -1533,7 +1533,7 @@ _send_signed_request() { MAX_REQUEST_RETRY_TIMES=5 _request_retry_times=0 while [ "${_request_retry_times}" -lt "$MAX_REQUEST_RETRY_TIMES" ]; do - _debug3 _request_retry_times "$_request_retry_times" + _debug3 _request_retry_times "$_request_retry_times" if [ -z "$_CACHED_NONCE" ]; then _debug2 "Get nonce." nonceurl="$API/directory" @@ -1582,7 +1582,7 @@ _send_signed_request() { _debug2 original "$response" response="$(echo "$response" | _normalizeJson)" - responseHeaders="$(< "$HTTP_HEADER")" + responseHeaders="$(<"$HTTP_HEADER")" _debug2 responseHeaders "$responseHeaders" _debug2 response "$response" @@ -1597,7 +1597,7 @@ _send_signed_request() { _sleep 5 continue fi - break; + break done } From c70432996a70c82bdb4af526496bbc9b33408ab3 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 17 Feb 2017 23:06:39 +0800 Subject: [PATCH 049/113] compatible to openssl 0.9 for hmac function --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 7eee2909..d36df7f7 100755 --- a/acme.sh +++ b/acme.sh @@ -740,9 +740,9 @@ _hmac() { if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ]; then if [ "$outputhex" ]; then - $OPENSSL_BIN dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" | cut -d = -f 2 | tr -d ' ' + ($OPENSSL_BIN dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" 2>/dev/null || $OPENSSL_BIN dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)") | cut -d = -f 2 | tr -d ' ' else - $OPENSSL_BIN dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" -binary + $OPENSSL_BIN dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" -binary 2>/dev/null || $OPENSSL_BIN dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)" -binary fi else _err "$alg is not supported yet" From 64802502217e4a4f8694b5e851d83c804b2a2688 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 18 Feb 2017 10:31:18 +0800 Subject: [PATCH 050/113] fix for freebsd --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index d36df7f7..aaf966cb 100755 --- a/acme.sh +++ b/acme.sh @@ -1582,7 +1582,7 @@ _send_signed_request() { _debug2 original "$response" response="$(echo "$response" | _normalizeJson)" - responseHeaders="$(<"$HTTP_HEADER")" + responseHeaders="$(cat "$HTTP_HEADER")" _debug2 responseHeaders "$responseHeaders" _debug2 response "$response" From db5046292075d0988031f33105a062d055c84182 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 18 Feb 2017 12:03:21 +0800 Subject: [PATCH 051/113] minor use interactive _sleep --- dnsapi/dns_gd.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_gd.sh b/dnsapi/dns_gd.sh index 1abeeacf..f2dd1fd5 100755 --- a/dnsapi/dns_gd.sh +++ b/dnsapi/dns_gd.sh @@ -40,7 +40,7 @@ dns_gd_add() { if _gd_rest PUT "domains/$_domain/records/TXT/$_sub_domain" "[{\"data\":\"$txtvalue\"}]"; then if [ "$response" = "{}" ]; then _info "Added, sleeping 10 seconds" - sleep 10 + _sleep 10 #todo: check if the record takes effect return 0 else From fc6cf4d9635544a8f8e6d6d1a6c33254cf16c537 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 19 Feb 2017 12:13:18 +0800 Subject: [PATCH 052/113] fix syslog --- acme.sh | 69 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 19 deletions(-) diff --git a/acme.sh b/acme.sh index aaf966cb..34ca1d9d 100755 --- a/acme.sh +++ b/acme.sh @@ -65,10 +65,31 @@ LOG_LEVEL_2=2 LOG_LEVEL_3=3 DEFAULT_LOG_LEVEL="$LOG_LEVEL_1" -SYSLOG_INFO="user.info" +DEBUG_LEVEL_1=1 +DEBUG_LEVEL_2=2 +DEBUG_LEVEL_3=3 +DEBUG_LEVEL_DEFAULT=$DEBUG_LEVEL_1 +DEBUG_LEVEL_NONE=0 + SYSLOG_ERROR="user.error" +SYSLOG_INFO="user.info" SYSLOG_DEBUG="user.debug" +#error +SYSLOG_LEVEL_1=1 +#info +SYSLOG_LEVEL_2=2 +#debug +SYSLOG_LEVEL_3=3 +#debug2 +SYSLOG_LEVEL_4=4 +#debug3 +SYSLOG_LEVEL_5=5 + +SYSLOG_LEVEL_DEFAULT=$SYSLOG_LEVEL_1 +#none +SYSLOG_LEVEL_NONE=0 + _DEBUG_WIKI="https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh" _PREPARE_LINK="https://github.com/Neilpang/acme.sh/wiki/Install-preparations" @@ -138,7 +159,7 @@ _dlg_versions() { #class _syslog() { - if [ -z "$SYS_LOG" ] || [ "$SYS_LOG" = "0" ]; then + if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" = "$SYSLOG_LEVEL_NONE" ]; then return fi _logclass="$1" @@ -147,19 +168,21 @@ _syslog() { } _log() { - _syslog "$@" [ -z "$LOG_FILE" ] && return - shift _printargs "$@" >>"$LOG_FILE" } _info() { - _log "$SYSLOG_INFO" "$@" + _log "$@" + if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_2" ]; then + _syslog "$SYSLOG_INFO" "$@" + fi _printargs "$@" } _err() { - _log "$SYSLOG_ERROR" "$@" + _syslog "$SYSLOG_ERROR" "$@" + _log "$@" if [ -z "$NO_TIMESTAMP" ] || [ "$NO_TIMESTAMP" = "0" ]; then printf -- "%s" "[$(date)] " >&2 fi @@ -178,29 +201,37 @@ _usage() { } _debug() { - if [ -z "$LOG_LEVEL" ] || [ "$LOG_LEVEL" -ge "$LOG_LEVEL_1" ]; then - _log "$SYSLOG_DEBUG" "$@" + if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_1" ]; then + _log "$@" fi - if [ -z "$DEBUG" ]; then - return + if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_3" ]; then + _syslog "$SYSLOG_DEBUG" "$@" + fi + if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_1" ]; then + _printargs "$@" >&2 fi - _printargs "$@" >&2 } _debug2() { - if [ "$LOG_LEVEL" ] && [ "$LOG_LEVEL" -ge "$LOG_LEVEL_2" ]; then - _log "$SYSLOG_DEBUG" "$@" + if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_2" ]; then + _log "$@" fi - if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then + if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_4" ]; then + _syslog "$SYSLOG_DEBUG" "$@" + fi + if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then _printargs "$@" >&2 fi } _debug3() { - if [ "$LOG_LEVEL" ] && [ "$LOG_LEVEL" -ge "$LOG_LEVEL_3" ]; then - _log "$SYSLOG_DEBUG" "$@" + if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_3" ]; then + _log "$@" fi - if [ "$DEBUG" ] && [ "$DEBUG" -ge "3" ]; then + if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_5" ]; then + _syslog "$SYSLOG_DEBUG" "$@" + fi + if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_3" ]; then _printargs "$@" >&2 fi } @@ -4840,7 +4871,7 @@ _process() { ;; --debug) if [ -z "$2" ] || _startswith "$2" "-"; then - DEBUG="1" + DEBUG="$DEBUG_LEVEL_DEFAULT" else DEBUG="$2" shift @@ -5069,7 +5100,7 @@ _process() { shift fi if [ -z "$_syslog" ]; then - _syslog="1" + _syslog="$SYSLOG_LEVEL_DEFAULT" fi ;; --auto-upgrade) From 113089be5d5310e4d8acce352fcbe592a1c5220f Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 19 Feb 2017 12:42:37 +0800 Subject: [PATCH 053/113] fix syslog level --- acme.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/acme.sh b/acme.sh index 34ca1d9d..f4ee89c9 100755 --- a/acme.sh +++ b/acme.sh @@ -76,17 +76,17 @@ SYSLOG_INFO="user.info" SYSLOG_DEBUG="user.debug" #error -SYSLOG_LEVEL_1=1 +SYSLOG_LEVEL_ERROR=3 #info -SYSLOG_LEVEL_2=2 +SYSLOG_LEVEL_INFO=6 #debug -SYSLOG_LEVEL_3=3 +SYSLOG_LEVEL_DEBUG=7 #debug2 -SYSLOG_LEVEL_4=4 +SYSLOG_LEVEL_DEBUG_2=8 #debug3 -SYSLOG_LEVEL_5=5 +SYSLOG_LEVEL_DEBUG_3=9 -SYSLOG_LEVEL_DEFAULT=$SYSLOG_LEVEL_1 +SYSLOG_LEVEL_DEFAULT=$SYSLOG_LEVEL_ERROR #none SYSLOG_LEVEL_NONE=0 @@ -174,7 +174,7 @@ _log() { _info() { _log "$@" - if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_2" ]; then + if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_INFO" ]; then _syslog "$SYSLOG_INFO" "$@" fi _printargs "$@" @@ -204,7 +204,7 @@ _debug() { if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_1" ]; then _log "$@" fi - if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_3" ]; then + if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG" ]; then _syslog "$SYSLOG_DEBUG" "$@" fi if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_1" ]; then @@ -216,7 +216,7 @@ _debug2() { if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_2" ]; then _log "$@" fi - if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_4" ]; then + if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG_2" ]; then _syslog "$SYSLOG_DEBUG" "$@" fi if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then @@ -228,7 +228,7 @@ _debug3() { if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_3" ]; then _log "$@" fi - if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_5" ]; then + if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG_3" ]; then _syslog "$SYSLOG_DEBUG" "$@" fi if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_3" ]; then From 52765466c12aaeaff6d7c9c9eab1e18f8cb84042 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 19 Feb 2017 12:55:05 +0800 Subject: [PATCH 054/113] 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 055/113] 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 056/113] 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 057/113] 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 058/113] 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 059/113] 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 060/113] 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 061/113] 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 062/113] 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 063/113] 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 064/113] 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 065/113] 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 066/113] 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 067/113] 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 From 044da37c953003e284c2307624c858a4fecbba0c Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 21 Feb 2017 21:34:43 +0800 Subject: [PATCH 068/113] change installcert parameter order --- acme.sh | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/acme.sh b/acme.sh index 43f87e98..e24d4d9a 100755 --- a/acme.sh +++ b/acme.sh @@ -3653,7 +3653,7 @@ issue() { _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 "$_main_domain" "$_real_cert" "$_real_key" "$_real_ca" "$_real_fullchain" "$_reload_cmd" fi } @@ -3964,16 +3964,18 @@ installcert() { _savedomainconf "Le_ReloadCmd" "$_reload_cmd" _savedomainconf "Le_RealFullChainPath" "$_real_fullchain" - _installcert "$_main_domain" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" + _installcert "$_main_domain" "$_real_cert" "$_real_key" "$_real_ca" "$_real_fullchain" "$_reload_cmd" } +#domain cert key ca fullchain reloadcmd backup-prefix _installcert() { _main_domain="$1" _real_cert="$2" _real_key="$3" _real_ca="$4" - _reload_cmd="$5" - _real_fullchain="$6" + _real_fullchain="$5" + _reload_cmd="$6" + _backup_prefix="$7" if [ "$_real_cert" = "$NO_VALUE" ]; then _real_cert="" @@ -3991,11 +3993,13 @@ _installcert() { _real_fullchain="" fi + _backup_path="$DOMAIN_BACKUP_PATH/$_backup_prefix" + mkdir -p "$_backup_path" + if [ "$_real_cert" ]; then _info "Installing cert to:$_real_cert" if [ -f "$_real_cert" ] && [ ! "$IS_RENEW" ]; then - mkdir -p "$DOMAIN_BACKUP_PATH" - cp "$_real_cert" "$DOMAIN_BACKUP_PATH/cert.bak" + cp "$_real_cert" "$_backup_path/cert.bak" fi cat "$CERT_PATH" >"$_real_cert" fi @@ -4007,8 +4011,7 @@ _installcert() { cat "$CA_CERT_PATH" >>"$_real_ca" else if [ -f "$_real_ca" ] && [ ! "$IS_RENEW" ]; then - mkdir -p "$DOMAIN_BACKUP_PATH" - cp "$_real_ca" "$DOMAIN_BACKUP_PATH/ca.bak" + cp "$_real_ca" "$_backup_path/ca.bak" fi cat "$CA_CERT_PATH" >"$_real_ca" fi @@ -4017,8 +4020,7 @@ _installcert() { if [ "$_real_key" ]; then _info "Installing key to:$_real_key" if [ -f "$_real_key" ] && [ ! "$IS_RENEW" ]; then - mkdir -p "$DOMAIN_BACKUP_PATH" - cp "$_real_key" "$DOMAIN_BACKUP_PATH/key.bak" + cp "$_real_key" "$_backup_path/key.bak" fi cat "$CERT_KEY_PATH" >"$_real_key" fi @@ -4026,8 +4028,7 @@ _installcert() { if [ "$_real_fullchain" ]; then _info "Installing full chain to:$_real_fullchain" if [ -f "$_real_fullchain" ] && [ ! "$IS_RENEW" ]; then - mkdir -p "$DOMAIN_BACKUP_PATH" - cp "$_real_fullchain" "$DOMAIN_BACKUP_PATH/fullchain.bak" + cp "$_real_fullchain" "$_backup_path/fullchain.bak" fi cat "$CERT_FULLCHAIN_PATH" >"$_real_fullchain" fi From 6dfc8fe0ea0f0d0889946d3cc54bd5ec21f7e59d Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 21 Feb 2017 23:18:11 +0800 Subject: [PATCH 069/113] support vsftpd hook --- deploy/README.md | 20 +++++++++++++ deploy/vsftpd.sh | 75 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 93 insertions(+), 2 deletions(-) diff --git a/deploy/README.md b/deploy/README.md index fcdf8019..cb500311 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -26,5 +26,25 @@ Before you can deploy your cert, you must [issue the cert first](https://github. (TODO) +## 4. Deploy the cert to local vsftpd server. +```sh +acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd +``` + +The default vsftpd conf file is `/etc/vsftpd.conf`, if your vsftpd conf is not in the default location, you can specify one: + +```sh +export DEPLOY_VSFTPD_CONF="/etc/vsftpd.conf" + +acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd +``` + +The default command to restart vsftpd server is `service vsftpd restart`, if it doesn't work, you can specify one: + +```sh +export DEPLOY_VSFTPD_RELOAD="/etc/init.d/vsftpd restart" + +acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd +``` diff --git a/deploy/vsftpd.sh b/deploy/vsftpd.sh index 5e89ea95..d2d8aa16 100644 --- a/deploy/vsftpd.sh +++ b/deploy/vsftpd.sh @@ -4,6 +4,9 @@ #returns 0 means success, otherwise error. +#DEPLOY_VSFTPD_CONF="/etc/vsftpd.conf" +#DEPLOY_VSFTPD_RELOAD="service vsftpd restart" + ######## Public functions ##################### #domain keyfile certfile cafile fullchain @@ -20,7 +23,75 @@ vsftpd_deploy() { _debug _cca "$_cca" _debug _cfullchain "$_cfullchain" - _err "deploy cert to vsftpd server, Not implemented yet" - return 1 + _ssl_path="/etc/acme.sh/vsftpd" + if ! mkdir -p "$_ssl_path"; then + _err "Can not create folder:$_ssl_path" + return 1 + fi + DEFAULT_VSFTPD_CONF="/etc/vsftpd.conf" + _vsftpd_conf="${DEPLOY_VSFTPD_CONF:-$DEFAULT_VSFTPD_CONF}" + + if [ ! -f "$_vsftpd_conf" ]; then + if [ -z "$DEPLOY_VSFTPD_CONF" ]; then + _err "vsftpd conf is not found, please define DEPLOY_VSFTPD_CONF" + return 1 + else + _err "It seems that the specified vsftpd conf is not valid, please check." + return 1 + fi + fi + + if [ ! -w "$_vsftpd_conf" ]; then + _err "The file $_vsftpd_conf is not writable, please change the permission." + return 1 + fi + + _backup_conf="$DOMAIN_BACKUP_PATH/vsftpd.conf.bak" + _info "Backup $_vsftpd_conf to $_backup_conf" + cp "$_vsftpd_conf" "$_backup_conf" + + _info "Copying key and cert" + _real_key="$_ssl_path/vsftpd.key" + if ! cat "$_ckey" >"$_real_key"; then + _err "Error: write key file to: $_real_key" + return 1 + fi + _real_fullchain="$_ssl_path/vsftpd.chain.pem" + if ! cat "$_cfullchain" >"$_real_fullchain"; then + _err "Error: write key file to: $_real_fullchain" + return 1 + fi + _info "Modify vsftpd conf: $_vsftpd_conf" + + DEFAULT_VSFTPD_RELOAD="service vsftpd restart" + _reload="${DEPLOY_VSFTPD_RELOAD:-$DEFAULT_VSFTPD_RELOAD}" + if _setopt "$_vsftpd_conf" "rsa_cert_file" "=" "$_real_fullchain" \ + && _setopt "$_vsftpd_conf" "rsa_private_key_file" "=" "$_real_key" \ + && _setopt "$_vsftpd_conf" "ssl_enable" "=" "YES" \ + && eval "$_reload"; then + _info "Deploy success!" + if [ "$DEPLOY_VSFTPD_CONF" ]; then + _savedomainconf DEPLOY_VSFTPD_CONF "$DEPLOY_VSFTPD_CONF" + else + _cleardomainconf DEPLOY_VSFTPD_CONF + fi + if [ "$DEPLOY_VSFTPD_RELOAD" ]; then + _savedomainconf DEPLOY_VSFTPD_RELOAD "$DEPLOY_VSFTPD_RELOAD" + else + _cleardomainconf DEPLOY_VSFTPD_RELOAD + fi + return 0 + else + _err "Config vsftpd server error, please report bug to us." + _info "Restoring vsftpd conf" + if cat "$_backup_conf" >"$_vsftpd_conf"; then + _info "Restore conf success" + eval "$_reload" + else + _err "Opps, error restore vsftpd conf, please report bug to us." + fi + return 1 + fi + return 1 } From 45d6e00ff14a48f4ebd9a4a5a5a06cecad6b41d2 Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 22 Feb 2017 20:17:36 +0800 Subject: [PATCH 070/113] fix format --- deploy/vsftpd.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deploy/vsftpd.sh b/deploy/vsftpd.sh index d2d8aa16..cc57f990 100644 --- a/deploy/vsftpd.sh +++ b/deploy/vsftpd.sh @@ -39,7 +39,7 @@ vsftpd_deploy() { else _err "It seems that the specified vsftpd conf is not valid, please check." return 1 - fi + fi fi if [ ! -w "$_vsftpd_conf" ]; then @@ -50,7 +50,7 @@ vsftpd_deploy() { _backup_conf="$DOMAIN_BACKUP_PATH/vsftpd.conf.bak" _info "Backup $_vsftpd_conf to $_backup_conf" cp "$_vsftpd_conf" "$_backup_conf" - + _info "Copying key and cert" _real_key="$_ssl_path/vsftpd.key" if ! cat "$_ckey" >"$_real_key"; then @@ -63,7 +63,7 @@ vsftpd_deploy() { return 1 fi _info "Modify vsftpd conf: $_vsftpd_conf" - + DEFAULT_VSFTPD_RELOAD="service vsftpd restart" _reload="${DEPLOY_VSFTPD_RELOAD:-$DEFAULT_VSFTPD_RELOAD}" if _setopt "$_vsftpd_conf" "rsa_cert_file" "=" "$_real_fullchain" \ From ddf293bbcda2196ea9e7ec18d97d9f5a9a45d4c5 Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 22 Feb 2017 20:40:33 +0800 Subject: [PATCH 071/113] reload only for renewal --- deploy/vsftpd.sh | 75 ++++++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 31 deletions(-) diff --git a/deploy/vsftpd.sh b/deploy/vsftpd.sh index cc57f990..1c6410a6 100644 --- a/deploy/vsftpd.sh +++ b/deploy/vsftpd.sh @@ -29,28 +29,6 @@ vsftpd_deploy() { return 1 fi - DEFAULT_VSFTPD_CONF="/etc/vsftpd.conf" - _vsftpd_conf="${DEPLOY_VSFTPD_CONF:-$DEFAULT_VSFTPD_CONF}" - - if [ ! -f "$_vsftpd_conf" ]; then - if [ -z "$DEPLOY_VSFTPD_CONF" ]; then - _err "vsftpd conf is not found, please define DEPLOY_VSFTPD_CONF" - return 1 - else - _err "It seems that the specified vsftpd conf is not valid, please check." - return 1 - fi - fi - - if [ ! -w "$_vsftpd_conf" ]; then - _err "The file $_vsftpd_conf is not writable, please change the permission." - return 1 - fi - - _backup_conf="$DOMAIN_BACKUP_PATH/vsftpd.conf.bak" - _info "Backup $_vsftpd_conf to $_backup_conf" - cp "$_vsftpd_conf" "$_backup_conf" - _info "Copying key and cert" _real_key="$_ssl_path/vsftpd.key" if ! cat "$_ckey" >"$_real_key"; then @@ -62,15 +40,51 @@ vsftpd_deploy() { _err "Error: write key file to: $_real_fullchain" return 1 fi - _info "Modify vsftpd conf: $_vsftpd_conf" DEFAULT_VSFTPD_RELOAD="service vsftpd restart" _reload="${DEPLOY_VSFTPD_RELOAD:-$DEFAULT_VSFTPD_RELOAD}" - if _setopt "$_vsftpd_conf" "rsa_cert_file" "=" "$_real_fullchain" \ - && _setopt "$_vsftpd_conf" "rsa_private_key_file" "=" "$_real_key" \ - && _setopt "$_vsftpd_conf" "ssl_enable" "=" "YES" \ - && eval "$_reload"; then - _info "Deploy success!" + + if [ -z "$IS_RENEW" ]; then + DEFAULT_VSFTPD_CONF="/etc/vsftpd.conf" + _vsftpd_conf="${DEPLOY_VSFTPD_CONF:-$DEFAULT_VSFTPD_CONF}" + if [ ! -f "$_vsftpd_conf" ]; then + if [ -z "$DEPLOY_VSFTPD_CONF" ]; then + _err "vsftpd conf is not found, please define DEPLOY_VSFTPD_CONF" + return 1 + else + _err "It seems that the specified vsftpd conf is not valid, please check." + return 1 + fi + fi + if [ ! -w "$_vsftpd_conf" ]; then + _err "The file $_vsftpd_conf is not writable, please change the permission." + return 1 + fi + _backup_conf="$DOMAIN_BACKUP_PATH/vsftpd.conf.bak" + _info "Backup $_vsftpd_conf to $_backup_conf" + cp "$_vsftpd_conf" "$_backup_conf" + + _info "Modify vsftpd conf: $_vsftpd_conf" + if _setopt "$_vsftpd_conf" "rsa_cert_file" "=" "$_real_fullchain" \ + && _setopt "$_vsftpd_conf" "rsa_private_key_file" "=" "$_real_key" \ + && _setopt "$_vsftpd_conf" "ssl_enable" "=" "YES"; then + _info "Set config success!" + else + _err "Config vsftpd server error, please report bug to us." + _info "Restoring vsftpd conf" + if cat "$_backup_conf" >"$_vsftpd_conf"; then + _info "Restore conf success" + eval "$_reload" + else + _err "Opps, error restore vsftpd conf, please report bug to us." + fi + return 1 + fi + fi + + _info "Run reload: $_reload" + if eval "$_reload"; then + _info "Reload success!" if [ "$DEPLOY_VSFTPD_CONF" ]; then _savedomainconf DEPLOY_VSFTPD_CONF "$DEPLOY_VSFTPD_CONF" else @@ -83,8 +97,7 @@ vsftpd_deploy() { fi return 0 else - _err "Config vsftpd server error, please report bug to us." - _info "Restoring vsftpd conf" + _err "Reload error, restoring" if cat "$_backup_conf" >"$_vsftpd_conf"; then _info "Restore conf success" eval "$_reload" @@ -93,5 +106,5 @@ vsftpd_deploy() { fi return 1 fi - return 1 + return 0 } From 35ca729cb939fb3a2e4798992fc51eb5b1ddda88 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 23 Feb 2017 19:01:48 +0800 Subject: [PATCH 072/113] fix doc --- deploy/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/README.md b/deploy/README.md index cb500311..40800401 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -13,7 +13,7 @@ Then you can deploy now: ```sh export DEPLOY_CPANEL_USER=myusername export DEPLOY_CPANEL_PASSWORD=PASSWORD -acme.sh --deploy -d example.com --deploy --deploy-hook cpanel +acme.sh --deploy -d example.com --deploy-hook cpanel ``` ## 2. Deploy ssl cert on kong proxy engine based on api. From a239a9efd508aa45d7299df6bb24e216b113251e Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 23 Feb 2017 19:04:08 +0800 Subject: [PATCH 073/113] fix doc --- deploy/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/deploy/README.md b/deploy/README.md index 40800401..a4e9136f 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -1,12 +1,14 @@ # Using deploy api +Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert). + Here are the scripts to deploy the certs/key to the server/services. ## 1. Deploy the certs to your cpanel host. (cpanel deploy hook is not finished yet, this is just an example.) -Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert). + Then you can deploy now: From 1965035166a6259641d3f0c43de930ebb8d8b878 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 23 Feb 2017 20:03:03 +0800 Subject: [PATCH 074/113] support exim4 deploy --- deploy/README.md | 22 ++++++++++++ deploy/exim4.sh | 92 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 112 insertions(+), 2 deletions(-) diff --git a/deploy/README.md b/deploy/README.md index a4e9136f..4a13e096 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -50,3 +50,25 @@ export DEPLOY_VSFTPD_RELOAD="/etc/init.d/vsftpd restart" acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd ``` +## 5. Deploy the cert to local exim4 server. + +```sh +acme.sh --deploy -d ftp.example.com --deploy-hook exim4 +``` + +The default exim4 conf file is `/etc/exim/exim.conf`, if your exim4 conf is not in the default location, you can specify one: + +```sh +export DEPLOY_EXIM4_CONF="/etc/exim4/exim4.conf.template" + +acme.sh --deploy -d ftp.example.com --deploy-hook exim4 +``` + +The default command to restart exim4 server is `service exim4 restart`, if it doesn't work, you can specify one: + +```sh +export DEPLOY_EXIM4_RELOAD="/etc/init.d/exim4 restart" + +acme.sh --deploy -d ftp.example.com --deploy-hook exim4 +``` + diff --git a/deploy/exim4.sh b/deploy/exim4.sh index b53f58ec..bf92b438 100644 --- a/deploy/exim4.sh +++ b/deploy/exim4.sh @@ -4,6 +4,9 @@ #returns 0 means success, otherwise error. +#DEPLOY_EXIM4_CONF="/etc/exim/exim.conf" +#DEPLOY_EXIM4_RELOAD="service exim4 restart" + ######## Public functions ##################### #domain keyfile certfile cafile fullchain @@ -20,7 +23,92 @@ exim4_deploy() { _debug _cca "$_cca" _debug _cfullchain "$_cfullchain" - _err "deploy cert to exim4 server, Not implemented yet" - return 1 + _ssl_path="/etc/acme.sh/exim4" + if ! mkdir -p "$_ssl_path"; then + _err "Can not create folder:$_ssl_path" + return 1 + fi + + _info "Copying key and cert" + _real_key="$_ssl_path/exim4.key" + if ! cat "$_ckey" >"$_real_key"; then + _err "Error: write key file to: $_real_key" + return 1 + fi + _real_fullchain="$_ssl_path/exim4.pem" + if ! cat "$_cfullchain" >"$_real_fullchain"; then + _err "Error: write key file to: $_real_fullchain" + return 1 + fi + + DEFAULT_EXIM4_RELOAD="service exim4 restart" + _reload="${DEPLOY_EXIM4_RELOAD:-$DEFAULT_EXIM4_RELOAD}" + + if [ -z "$IS_RENEW" ]; then + DEFAULT_EXIM4_CONF="/etc/exim/exim.conf" + if [ ! -f "$DEFAULT_EXIM4_CONF" ]; then + DEFAULT_EXIM4_CONF="/etc/exim4/exim4.conf.template" + fi + _exim4_conf="${DEPLOY_EXIM4_CONF:-$DEFAULT_EXIM4_CONF}" + _debug _exim4_conf "$_exim4_conf" + if [ ! -f "$_exim4_conf" ]; then + if [ -z "$DEPLOY_EXIM4_CONF" ]; then + _err "exim4 conf is not found, please define DEPLOY_EXIM4_CONF" + return 1 + else + _err "It seems that the specified exim4 conf is not valid, please check." + return 1 + fi + fi + if [ ! -w "$_exim4_conf" ]; then + _err "The file $_exim4_conf is not writable, please change the permission." + return 1 + fi + _backup_conf="$DOMAIN_BACKUP_PATH/exim4.conf.bak" + _info "Backup $_exim4_conf to $_backup_conf" + cp "$_exim4_conf" "$_backup_conf" + + _info "Modify exim4 conf: $_exim4_conf" + if _setopt "$_exim4_conf" "tls_certificate" "=" "$_real_fullchain" \ + && _setopt "$_exim4_conf" "tls_privatekey" "=" "$_real_key"; then + _info "Set config success!" + else + _err "Config exim4 server error, please report bug to us." + _info "Restoring exim4 conf" + if cat "$_backup_conf" >"$_exim4_conf"; then + _info "Restore conf success" + eval "$_reload" + else + _err "Opps, error restore exim4 conf, please report bug to us." + fi + return 1 + fi + fi + + _info "Run reload: $_reload" + if eval "$_reload"; then + _info "Reload success!" + if [ "$DEPLOY_EXIM4_CONF" ]; then + _savedomainconf DEPLOY_EXIM4_CONF "$DEPLOY_EXIM4_CONF" + else + _cleardomainconf DEPLOY_EXIM4_CONF + fi + if [ "$DEPLOY_EXIM4_RELOAD" ]; then + _savedomainconf DEPLOY_EXIM4_RELOAD "$DEPLOY_EXIM4_RELOAD" + else + _cleardomainconf DEPLOY_EXIM4_RELOAD + fi + return 0 + else + _err "Reload error, restoring" + if cat "$_backup_conf" >"$_exim4_conf"; then + _info "Restore conf success" + eval "$_reload" + else + _err "Opps, error restore exim4 conf, please report bug to us." + fi + return 1 + fi + return 0 } From 7b2fa1edb41a3b8a447cc590d0450a4a60c4029f Mon Sep 17 00:00:00 2001 From: Stefan Seidel Date: Fri, 2 Dec 2016 20:10:13 +0000 Subject: [PATCH 075/113] add API for www.do.de/www.resellerinterface.de --- dnsapi/dns_do.sh | 167 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100755 dnsapi/dns_do.sh diff --git a/dnsapi/dns_do.sh b/dnsapi/dns_do.sh new file mode 100755 index 00000000..43ce678f --- /dev/null +++ b/dnsapi/dns_do.sh @@ -0,0 +1,167 @@ +#!/usr/bin/env sh + +# DNS API for Domain-Offensive / Resellerinterface / Domainrobot + +# DO_PID="KD-1234567" +# DO_PW="cdfkjl3n2" + +DO_URL="https://soap.resellerinterface.de/" + +######## Public functions ##################### + +#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_do_add() { + fulldomain=$1 + txtvalue=$2 + _cookiejar="$(_mktemp)" + if _dns_do_authenticate; then + _info "Adding TXT record to ${_domain} as ${fulldomain}" + _dns_do_soap createRR origin "${_domain}" name "${fulldomain}" type TXT data "${txtvalue}" ttl 300 + if _contains "${response}" '>success<'; then + return 0 + fi + _err "Could not create resource record, check logs" + fi + return 1 +} + +#fulldomain +dns_do_rm() { + fulldomain=$1 + _cookiejar="$(_mktemp)" + if _dns_do_authenticate; then + if _dns_do_list_rrs; then + for _rrid in ${_rr_list}; do + _info "Deleting resource record $_rrid for $_domain" + _dns_do_soap deleteRR origin "${_domain}" rrid "${_rrid}" + if ! _contains "${response}" '>success<'; then + _err "Could not delete resource record for ${_domain}, id ${_rrid}" + fi + done + return 0 + fi + fi + return 1 +} + +#################### Private functions below ################################## +_dns_do_authenticate() { + _info "Authenticating as ${DO_PID}" + _dns_do_soap authPartner partner "${DO_PID}" password "${DO_PW}" + if _contains "${response}" '>success<'; then + _get_root "$fulldomain" + _debug "_domain $_domain" + return 0 + else + _err "Authentication failed, check logs" + fi + return 1 +} + +_dns_do_list_rrs() { + _dns_do_soap getRRList origin "${_domain}" + if ! _contains "${response}" 'SOAP-ENC:Array'; then + _err "getRRList origin ${_domain} failed" + return 1 + fi + _rr_list="$(echo "${response}" \ + | tr -d "\n\r\t" \ + | sed -e 's//\n/g' \ + | grep -F ">${fulldomain}" \ + | sed -e 's//\n\0/g' \ + | grep -F '>id' \ + | sed -re 's/.*]*>([^<]+)<\/value>.*/\1/')" + [ "${_rr_list}" ] +} + +_dns_do_soap() { + func="$1" + shift + # put the parameters to xml + body="" + while [ "$1" ] ; do + _k="$1" + shift + _v="$1" + shift + body="$body<$_k>$_v" + done + body="$body" + _debug2 "SOAP request ${body}" + + # build SOAP XML + _xml=' + + '"$body"' +' + + # set SOAP headers + _H1="SOAPAction: ${DO_URL}#${func}" + # add cookie header if present + [ -s "${_cookiejar}" ] && _H2="$(cat "${_cookiejar}")" + + if ! response="$(_post "${_xml}" "${DO_URL}")"; then + _err "Error <$1>" + return 1 + fi + _debug2 "SOAP response $response" + + # retrieve cookie header + grep -F 'Set-Cookie:' "$HTTP_HEADER" | sed -re 's/^Set-(Cookie: [^;]+).*/\1/' | head -1 > "${_cookiejar}" + + return 0 +} + +_get_root() { + domain=$1 + i=1 + + _all_domains="$(_mktemp)" + _dns_do_soap getDomainList + echo "${response}" | tr -d "\n\r\t " | grep -Eo 'domain]+>[^<]+' | sed -re 's/^domain<\/key>]+>//g' > "${_all_domains}" + + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + if [ -z "$h" ]; then + return 1 + fi + + if grep -qF "$h" "${_all_domains}"; then + _domain="$h" + return 0 + fi + + i=$(_math $i + 1) + done + _debug "$domain not found" + + return 1 +} + +_info() { + if [ -z "$2" ]; then + echo "[$(date)] $1" + else + echo "[$(date)] $1='$2'" + fi +} + +_err() { + _info "$@" >&2 + return 1 +} + +_debug() { + if [ -z "$DEBUG" ]; then + return + fi + _err "$@" + return 0 +} + +_debug2() { + if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then + _debug "$@" + fi + return +} From 76a3371b402b3006ee2f26872debffc8b6dca103 Mon Sep 17 00:00:00 2001 From: Stefan Seidel Date: Sat, 3 Dec 2016 10:07:13 +0000 Subject: [PATCH 076/113] remove non-POSIX sed -r and use built-in functions --- dnsapi/dns_do.sh | 43 ++++++++----------------------------------- 1 file changed, 8 insertions(+), 35 deletions(-) diff --git a/dnsapi/dns_do.sh b/dnsapi/dns_do.sh index 43ce678f..cea1beb3 100755 --- a/dnsapi/dns_do.sh +++ b/dnsapi/dns_do.sh @@ -67,10 +67,11 @@ _dns_do_list_rrs() { _rr_list="$(echo "${response}" \ | tr -d "\n\r\t" \ | sed -e 's//\n/g' \ - | grep -F ">${fulldomain}" \ - | sed -e 's//\n\0/g' \ - | grep -F '>id' \ - | sed -re 's/.*]*>([^<]+)<\/value>.*/\1/')" + | fgrep ">${fulldomain}" \ + | sed -e 's/<\/item>/\n/g' \ + | grep '>id[0-9]{1,16}<' \ + | tr -d '><')" [ "${_rr_list}" ] } @@ -107,7 +108,7 @@ _dns_do_soap() { _debug2 "SOAP response $response" # retrieve cookie header - grep -F 'Set-Cookie:' "$HTTP_HEADER" | sed -re 's/^Set-(Cookie: [^;]+).*/\1/' | head -1 > "${_cookiejar}" + cat "$HTTP_HEADER" | _egrep_o 'Cookie: [^;]+' | head -1 > "${_cookiejar}" return 0 } @@ -118,7 +119,7 @@ _get_root() { _all_domains="$(_mktemp)" _dns_do_soap getDomainList - echo "${response}" | tr -d "\n\r\t " | grep -Eo 'domain]+>[^<]+' | sed -re 's/^domain<\/key>]+>//g' > "${_all_domains}" + echo "${response}" | tr -d "\n\r\t " | _egrep_o 'domain]+>[^<]+' | sed -e 's/^domain<\/key>]+>//g' > "${_all_domains}" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) @@ -126,7 +127,7 @@ _get_root() { return 1 fi - if grep -qF "$h" "${_all_domains}"; then + if fgrep -q "$h" "${_all_domains}"; then _domain="$h" return 0 fi @@ -137,31 +138,3 @@ _get_root() { return 1 } - -_info() { - if [ -z "$2" ]; then - echo "[$(date)] $1" - else - echo "[$(date)] $1='$2'" - fi -} - -_err() { - _info "$@" >&2 - return 1 -} - -_debug() { - if [ -z "$DEBUG" ]; then - return - fi - _err "$@" - return 0 -} - -_debug2() { - if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then - _debug "$@" - fi - return -} From 88ed5e506a9c1f862fc99d4c681bf47b2b97f253 Mon Sep 17 00:00:00 2001 From: Stefan Seidel Date: Sat, 3 Dec 2016 19:04:31 +0000 Subject: [PATCH 077/113] fix whitespace and UUOC --- dnsapi/dns_do.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_do.sh b/dnsapi/dns_do.sh index cea1beb3..034e6aa6 100755 --- a/dnsapi/dns_do.sh +++ b/dnsapi/dns_do.sh @@ -80,7 +80,7 @@ _dns_do_soap() { shift # put the parameters to xml body="" - while [ "$1" ] ; do + while [ "$1" ]; do _k="$1" shift _v="$1" @@ -108,7 +108,7 @@ _dns_do_soap() { _debug2 "SOAP response $response" # retrieve cookie header - cat "$HTTP_HEADER" | _egrep_o 'Cookie: [^;]+' | head -1 > "${_cookiejar}" + _egrep_o 'Cookie: [^;]+' < "$HTTP_HEADER" | head -1 >"${_cookiejar}" return 0 } @@ -119,7 +119,7 @@ _get_root() { _all_domains="$(_mktemp)" _dns_do_soap getDomainList - echo "${response}" | tr -d "\n\r\t " | _egrep_o 'domain]+>[^<]+' | sed -e 's/^domain<\/key>]+>//g' > "${_all_domains}" + echo "${response}" | tr -d "\n\r\t " | _egrep_o 'domain]+>[^<]+' | sed -e 's/^domain<\/key>]+>//g' >"${_all_domains}" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) From 0d4035e99662c737ab4160e6a77e8071f620c4c4 Mon Sep 17 00:00:00 2001 From: Stefan Seidel Date: Sat, 3 Dec 2016 19:24:42 +0000 Subject: [PATCH 078/113] remove fgrep, escape regex chars instead --- dnsapi/dns_do.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_do.sh b/dnsapi/dns_do.sh index 034e6aa6..075cb3b0 100755 --- a/dnsapi/dns_do.sh +++ b/dnsapi/dns_do.sh @@ -67,7 +67,7 @@ _dns_do_list_rrs() { _rr_list="$(echo "${response}" \ | tr -d "\n\r\t" \ | sed -e 's//\n/g' \ - | fgrep ">${fulldomain}" \ + | grep ">$(_regexcape "$fulldomain")" \ | sed -e 's/<\/item>/\n/g' \ | grep '>id[0-9]{1,16}<' \ @@ -127,7 +127,7 @@ _get_root() { return 1 fi - if fgrep -q "$h" "${_all_domains}"; then + if grep -q "$(_regexcape "$h")" "${_all_domains}"; then _domain="$h" return 0 fi @@ -138,3 +138,7 @@ _get_root() { return 1 } + +_regexcape() { + echo "$1" | sed -e 's/\([]\.$*^[]\)/\\\1/g' +} From 3ebbeb103c195737b5d234a60c73056a9a5bb88f Mon Sep 17 00:00:00 2001 From: Stefan Seidel Date: Sat, 3 Dec 2016 19:27:46 +0000 Subject: [PATCH 079/113] old habits --- dnsapi/dns_do.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_do.sh b/dnsapi/dns_do.sh index 075cb3b0..cc8f339e 100755 --- a/dnsapi/dns_do.sh +++ b/dnsapi/dns_do.sh @@ -108,7 +108,7 @@ _dns_do_soap() { _debug2 "SOAP response $response" # retrieve cookie header - _egrep_o 'Cookie: [^;]+' < "$HTTP_HEADER" | head -1 >"${_cookiejar}" + _egrep_o 'Cookie: [^;]+' <"$HTTP_HEADER" | head -1 >"${_cookiejar}" return 0 } From b95a99e0c2c8aa0e31b44df39fbe46119864dd55 Mon Sep 17 00:00:00 2001 From: Stefan Seidel Date: Mon, 5 Dec 2016 20:35:31 +0000 Subject: [PATCH 080/113] remove cookiejar temp file --- dnsapi/dns_do.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dnsapi/dns_do.sh b/dnsapi/dns_do.sh index cc8f339e..17ab23d7 100755 --- a/dnsapi/dns_do.sh +++ b/dnsapi/dns_do.sh @@ -98,8 +98,6 @@ _dns_do_soap() { # set SOAP headers _H1="SOAPAction: ${DO_URL}#${func}" - # add cookie header if present - [ -s "${_cookiejar}" ] && _H2="$(cat "${_cookiejar}")" if ! response="$(_post "${_xml}" "${DO_URL}")"; then _err "Error <$1>" @@ -108,7 +106,7 @@ _dns_do_soap() { _debug2 "SOAP response $response" # retrieve cookie header - _egrep_o 'Cookie: [^;]+' <"$HTTP_HEADER" | head -1 >"${_cookiejar}" + _H2="$(_egrep_o 'Cookie: [^;]+' <"$HTTP_HEADER" | head -1)" return 0 } From 743f821f1ee9e4827e95a4b1c4088949cbfc78ac Mon Sep 17 00:00:00 2001 From: Stefan Seidel Date: Mon, 5 Dec 2016 20:49:46 +0000 Subject: [PATCH 081/113] improve error message on failed authentication --- dnsapi/dns_do.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_do.sh b/dnsapi/dns_do.sh index 17ab23d7..7576092b 100755 --- a/dnsapi/dns_do.sh +++ b/dnsapi/dns_do.sh @@ -53,7 +53,7 @@ _dns_do_authenticate() { _debug "_domain $_domain" return 0 else - _err "Authentication failed, check logs" + _err "Authentication failed, are DO_PID and DO_PW set correctly?" fi return 1 } From d1d2f6f4518cc7332b92ef856471b1a76a6c03e8 Mon Sep 17 00:00:00 2001 From: Stefan Seidel Date: Mon, 5 Dec 2016 20:56:38 +0000 Subject: [PATCH 082/113] avoid temp file for domain list --- dnsapi/dns_do.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_do.sh b/dnsapi/dns_do.sh index 7576092b..1a9458f8 100755 --- a/dnsapi/dns_do.sh +++ b/dnsapi/dns_do.sh @@ -115,9 +115,11 @@ _get_root() { domain=$1 i=1 - _all_domains="$(_mktemp)" _dns_do_soap getDomainList - echo "${response}" | tr -d "\n\r\t " | _egrep_o 'domain]+>[^<]+' | sed -e 's/^domain<\/key>]+>//g' >"${_all_domains}" + _all_domains="/$(echo "${response}" \ + | tr -d "\n\r\t " \ + | _egrep_o 'domain]+>[^<]+' \ + | sed -e 's/^domain<\/key>]*>//g')" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) @@ -125,7 +127,7 @@ _get_root() { return 1 fi - if grep -q "$(_regexcape "$h")" "${_all_domains}"; then + if _contains "${_all_domains}" "^$(_regexcape "$h")\$"; then _domain="$h" return 0 fi From 1cb6e9e7d0653b2920fb6eac0bc11d3abdfa5190 Mon Sep 17 00:00:00 2001 From: seidler2547 Date: Wed, 7 Dec 2016 11:36:22 +0100 Subject: [PATCH 083/113] remove cookiejar file d'oh --- dnsapi/dns_do.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_do.sh b/dnsapi/dns_do.sh index 1a9458f8..edcf4559 100755 --- a/dnsapi/dns_do.sh +++ b/dnsapi/dns_do.sh @@ -13,7 +13,6 @@ DO_URL="https://soap.resellerinterface.de/" dns_do_add() { fulldomain=$1 txtvalue=$2 - _cookiejar="$(_mktemp)" if _dns_do_authenticate; then _info "Adding TXT record to ${_domain} as ${fulldomain}" _dns_do_soap createRR origin "${_domain}" name "${fulldomain}" type TXT data "${txtvalue}" ttl 300 From cdec38ba12a3779f257f321fd8a84b02fee0dbec Mon Sep 17 00:00:00 2001 From: seidler2547 Date: Wed, 7 Dec 2016 11:39:10 +0100 Subject: [PATCH 084/113] return error if any removal failed --- dnsapi/dns_do.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_do.sh b/dnsapi/dns_do.sh index edcf4559..1450ee5a 100755 --- a/dnsapi/dns_do.sh +++ b/dnsapi/dns_do.sh @@ -30,14 +30,16 @@ dns_do_rm() { _cookiejar="$(_mktemp)" if _dns_do_authenticate; then if _dns_do_list_rrs; then + _dns_do_had_error=0 for _rrid in ${_rr_list}; do _info "Deleting resource record $_rrid for $_domain" _dns_do_soap deleteRR origin "${_domain}" rrid "${_rrid}" if ! _contains "${response}" '>success<'; then + _dns_do_had_error=1 _err "Could not delete resource record for ${_domain}, id ${_rrid}" fi done - return 0 + return _dns_do_had_error fi fi return 1 From e55605dbe9b91702f9b93ac0c0a84736fb8e0145 Mon Sep 17 00:00:00 2001 From: seidler2547 Date: Wed, 7 Dec 2016 11:41:32 +0100 Subject: [PATCH 085/113] remove _all_ mktemp --- dnsapi/dns_do.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_do.sh b/dnsapi/dns_do.sh index 1450ee5a..43a73b97 100755 --- a/dnsapi/dns_do.sh +++ b/dnsapi/dns_do.sh @@ -27,7 +27,6 @@ dns_do_add() { #fulldomain dns_do_rm() { fulldomain=$1 - _cookiejar="$(_mktemp)" if _dns_do_authenticate; then if _dns_do_list_rrs; then _dns_do_had_error=0 From 1633d14547ad6d1e5521af0ce814373cd840fc14 Mon Sep 17 00:00:00 2001 From: seidler2547 Date: Wed, 7 Dec 2016 12:07:40 +0100 Subject: [PATCH 086/113] forgot dollar sign --- dnsapi/dns_do.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_do.sh b/dnsapi/dns_do.sh index 43a73b97..bbf86bac 100755 --- a/dnsapi/dns_do.sh +++ b/dnsapi/dns_do.sh @@ -38,7 +38,7 @@ dns_do_rm() { _err "Could not delete resource record for ${_domain}, id ${_rrid}" fi done - return _dns_do_had_error + return $_dns_do_had_error fi fi return 1 From bf8ffade29daca74e15e53cf40cf1b1ba451272f Mon Sep 17 00:00:00 2001 From: seidler2547 Date: Thu, 8 Dec 2016 08:43:29 +0100 Subject: [PATCH 087/113] replace head -1, add link to GitHub --- dnsapi/dns_do.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_do.sh b/dnsapi/dns_do.sh index bbf86bac..b718cd41 100755 --- a/dnsapi/dns_do.sh +++ b/dnsapi/dns_do.sh @@ -2,6 +2,9 @@ # DNS API for Domain-Offensive / Resellerinterface / Domainrobot +# Report bugs at https://github.com/seidler2547/acme.sh/issues + +# set these environment variables to match your customer ID and password: # DO_PID="KD-1234567" # DO_PW="cdfkjl3n2" @@ -106,7 +109,7 @@ _dns_do_soap() { _debug2 "SOAP response $response" # retrieve cookie header - _H2="$(_egrep_o 'Cookie: [^;]+' <"$HTTP_HEADER" | head -1)" + _H2="$(_egrep_o 'Cookie: [^;]+' <"$HTTP_HEADER" | _head_n 1)" return 0 } From 383fa8401d1dffb6d9a325b8df1c3324aba8f3b8 Mon Sep 17 00:00:00 2001 From: seidler2547 Date: Thu, 19 Jan 2017 09:35:47 +0100 Subject: [PATCH 088/113] Remove stray characater fixes issue where the first listed domain would not work --- dnsapi/dns_do.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_do.sh b/dnsapi/dns_do.sh index b718cd41..b08e6f1e 100755 --- a/dnsapi/dns_do.sh +++ b/dnsapi/dns_do.sh @@ -119,7 +119,7 @@ _get_root() { i=1 _dns_do_soap getDomainList - _all_domains="/$(echo "${response}" \ + _all_domains="$(echo "${response}" \ | tr -d "\n\r\t " \ | _egrep_o 'domain]+>[^<]+' \ | sed -e 's/^domain<\/key>]*>//g')" From 9efd40a3662d64c54eeb98858ddbd9bfc589ba2c Mon Sep 17 00:00:00 2001 From: seidler2547 Date: Sun, 19 Feb 2017 21:26:25 +0000 Subject: [PATCH 089/113] use export for headers --- dnsapi/dns_do.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_do.sh b/dnsapi/dns_do.sh index b08e6f1e..06a86b28 100755 --- a/dnsapi/dns_do.sh +++ b/dnsapi/dns_do.sh @@ -100,7 +100,7 @@ _dns_do_soap() { ' # set SOAP headers - _H1="SOAPAction: ${DO_URL}#${func}" + export _H1="SOAPAction: ${DO_URL}#${func}" if ! response="$(_post "${_xml}" "${DO_URL}")"; then _err "Error <$1>" @@ -109,7 +109,7 @@ _dns_do_soap() { _debug2 "SOAP response $response" # retrieve cookie header - _H2="$(_egrep_o 'Cookie: [^;]+' <"$HTTP_HEADER" | _head_n 1)" + export _H2="$(_egrep_o 'Cookie: [^;]+' <"$HTTP_HEADER" | _head_n 1)" return 0 } From 3d6a125bdc08e4419697a1913d00d68e0715b5e8 Mon Sep 17 00:00:00 2001 From: Stefan Seidel Date: Sun, 19 Feb 2017 21:34:10 +0000 Subject: [PATCH 090/113] add documentation --- README.md | 1 + dnsapi/README.md | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/README.md b/README.md index b33f8636..c8aeeb0f 100644 --- a/README.md +++ b/README.md @@ -293,6 +293,7 @@ You don't have to do anything manually! 1. Linode.com API 1. FreeDNS (https://freedns.afraid.org/) 1. cyon.ch +1. Domain-Offensive/Resellerinterface/Domainrobot API **More APIs coming soon...** diff --git a/dnsapi/README.md b/dnsapi/README.md index fd88d579..3be5a7fe 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -240,6 +240,7 @@ acme.sh --issue --dns dns_ispconfig -d example.com -d www.example.com The `ISPC_User`, `ISPC_Password`, `ISPC_Api`and `ISPC_Api_Insecure` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. +<<<<<<< HEAD ## 13. Use Alwaysdata domain API First you need to login to your Alwaysdata account to get your API Key. @@ -323,6 +324,19 @@ acme.sh --issue --dns dns_cyon -d example.com -d www.example.com The `CY_Username`, `CY_Password` and `CY_OTP_Secret` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. +## 17. Use Domain-Offensive/Resellerinterface/Domainrobot API + +You will need your login credentials (Partner ID+Password) to the Resellerinterface, and export them before you run `acme.sh`: +``` +export DO_PID="KD-1234567" +export DO_PW="cdfkjl3n2" +``` + +Ok, let's issue a cert now: +``` +acme.sh --issue --dns dns_do -d example.com -d www.example.com +``` + # Use custom API If your API is not supported yet, you can write your own DNS API. From 2b2b65fe1877725f4c7d400da28847bb31a09fbc Mon Sep 17 00:00:00 2001 From: seidler2547 Date: Sun, 19 Feb 2017 21:42:55 +0000 Subject: [PATCH 091/113] Declare and assign separately to avoid masking return values --- dnsapi/dns_do.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_do.sh b/dnsapi/dns_do.sh index 06a86b28..3a2f8f49 100755 --- a/dnsapi/dns_do.sh +++ b/dnsapi/dns_do.sh @@ -109,7 +109,8 @@ _dns_do_soap() { _debug2 "SOAP response $response" # retrieve cookie header - export _H2="$(_egrep_o 'Cookie: [^;]+' <"$HTTP_HEADER" | _head_n 1)" + _H2="$(_egrep_o 'Cookie: [^;]+' <"$HTTP_HEADER" | _head_n 1)" + export _H2 return 0 } From abf4278d0911be6ff199380c66542b93ecca9824 Mon Sep 17 00:00:00 2001 From: Stefan Seidel Date: Sun, 19 Feb 2017 21:46:33 +0000 Subject: [PATCH 092/113] resolve conflicts --- dnsapi/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/README.md b/dnsapi/README.md index 3be5a7fe..7df7142a 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -240,7 +240,6 @@ acme.sh --issue --dns dns_ispconfig -d example.com -d www.example.com The `ISPC_User`, `ISPC_Password`, `ISPC_Api`and `ISPC_Api_Insecure` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. -<<<<<<< HEAD ## 13. Use Alwaysdata domain API First you need to login to your Alwaysdata account to get your API Key. From e6cd596dc90bf51e3237b420b1715b000b64c3a6 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 25 Feb 2017 18:02:23 +0800 Subject: [PATCH 093/113] add debug info --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index e24d4d9a..b989d246 100755 --- a/acme.sh +++ b/acme.sh @@ -4369,7 +4369,7 @@ _precheck() { fi if ! _exists "$OPENSSL_BIN"; then - _err "Please install openssl first." + _err "Please install openssl first. OPENSSL_BIN=$OPENSSL_BIN" _err "We need openssl to generate keys." return 1 fi From 851fedf7512216c1926f3f64e899167ed6f06f56 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 25 Feb 2017 19:08:00 +0800 Subject: [PATCH 094/113] rename OPENSSL_BIN to ACME_OPENSSL_BIN --- acme.sh | 80 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/acme.sh b/acme.sh index b989d246..937da149 100755 --- a/acme.sh +++ b/acme.sh @@ -137,11 +137,11 @@ _printargs() { _dlg_versions() { echo "Diagnosis versions: " - echo "openssl:$OPENSSL_BIN" - if _exists "$OPENSSL_BIN"; then - $OPENSSL_BIN version 2>&1 + echo "openssl:$ACME_OPENSSL_BIN" + if _exists "$ACME_OPENSSL_BIN"; then + $ACME_OPENSSL_BIN version 2>&1 else - echo "$OPENSSL_BIN doesn't exists." + echo "$ACME_OPENSSL_BIN doesn't exists." fi echo "apache:" @@ -780,19 +780,19 @@ _base64() { [ "" ] #urgly if [ "$1" ]; then _debug3 "base64 multiline:'$1'" - $OPENSSL_BIN base64 -e + $ACME_OPENSSL_BIN base64 -e else _debug3 "base64 single line." - $OPENSSL_BIN base64 -e | tr -d '\r\n' + $ACME_OPENSSL_BIN base64 -e | tr -d '\r\n' fi } #Usage: multiline _dbase64() { if [ "$1" ]; then - $OPENSSL_BIN base64 -d -A + $ACME_OPENSSL_BIN base64 -d -A else - $OPENSSL_BIN base64 -d + $ACME_OPENSSL_BIN base64 -d fi } @@ -809,9 +809,9 @@ _digest() { if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ] || [ "$alg" = "md5" ]; then if [ "$outputhex" ]; then - $OPENSSL_BIN dgst -"$alg" -hex | cut -d = -f 2 | tr -d ' ' + $ACME_OPENSSL_BIN dgst -"$alg" -hex | cut -d = -f 2 | tr -d ' ' else - $OPENSSL_BIN dgst -"$alg" -binary | _base64 + $ACME_OPENSSL_BIN dgst -"$alg" -binary | _base64 fi else _err "$alg is not supported yet" @@ -834,9 +834,9 @@ _hmac() { if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ]; then if [ "$outputhex" ]; then - ($OPENSSL_BIN dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" 2>/dev/null || $OPENSSL_BIN dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)") | cut -d = -f 2 | tr -d ' ' + ($ACME_OPENSSL_BIN dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" 2>/dev/null || $ACME_OPENSSL_BIN dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)") | cut -d = -f 2 | tr -d ' ' else - $OPENSSL_BIN dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" -binary 2>/dev/null || $OPENSSL_BIN dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)" -binary + $ACME_OPENSSL_BIN dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" -binary 2>/dev/null || $ACME_OPENSSL_BIN dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)" -binary fi else _err "$alg is not supported yet" @@ -855,7 +855,7 @@ _sign() { return 1 fi - _sign_openssl="$OPENSSL_BIN dgst -sign $keyfile " + _sign_openssl="$ACME_OPENSSL_BIN dgst -sign $keyfile " if [ "$alg" = "sha256" ]; then _sign_openssl="$_sign_openssl -$alg" else @@ -866,7 +866,7 @@ _sign() { if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then $_sign_openssl | _base64 elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then - if ! _signedECText="$($_sign_openssl | $OPENSSL_BIN asn1parse -inform DER)"; then + if ! _signedECText="$($_sign_openssl | $ACME_OPENSSL_BIN asn1parse -inform DER)"; then _err "Sign failed: $_sign_openssl" _err "Key file: $keyfile" _err "Key content:$(wc -l <"$keyfile") lises" @@ -929,10 +929,10 @@ _createkey() { if _isEccKey "$length"; then _debug "Using ec name: $eccname" - $OPENSSL_BIN ecparam -name "$eccname" -genkey 2>/dev/null >"$f" + $ACME_OPENSSL_BIN ecparam -name "$eccname" -genkey 2>/dev/null >"$f" else _debug "Using RSA: $length" - $OPENSSL_BIN genrsa "$length" 2>/dev/null >"$f" + $ACME_OPENSSL_BIN genrsa "$length" 2>/dev/null >"$f" fi if [ "$?" != "0" ]; then @@ -1019,9 +1019,9 @@ _createcsr() { _csr_cn="$(_idn "$domain")" _debug2 _csr_cn "$_csr_cn" if _contains "$(uname -a)" "MINGW"; then - $OPENSSL_BIN req -new -sha256 -key "$csrkey" -subj "//CN=$_csr_cn" -config "$csrconf" -out "$csr" + $ACME_OPENSSL_BIN req -new -sha256 -key "$csrkey" -subj "//CN=$_csr_cn" -config "$csrconf" -out "$csr" else - $OPENSSL_BIN req -new -sha256 -key "$csrkey" -subj "/CN=$_csr_cn" -config "$csrconf" -out "$csr" + $ACME_OPENSSL_BIN req -new -sha256 -key "$csrkey" -subj "/CN=$_csr_cn" -config "$csrconf" -out "$csr" fi } @@ -1033,7 +1033,7 @@ _signcsr() { cert="$4" _debug "_signcsr" - _msg="$($OPENSSL_BIN x509 -req -days 365 -in "$csr" -signkey "$key" -extensions v3_req -extfile "$conf" -out "$cert" 2>&1)" + _msg="$($ACME_OPENSSL_BIN x509 -req -days 365 -in "$csr" -signkey "$key" -extensions v3_req -extfile "$conf" -out "$cert" 2>&1)" _ret="$?" _debug "$_msg" return $_ret @@ -1046,7 +1046,7 @@ _readSubjectFromCSR() { _usage "_readSubjectFromCSR mycsr.csr" return 1 fi - $OPENSSL_BIN req -noout -in "$_csrfile" -subject | _egrep_o "CN *=.*" | cut -d = -f 2 | cut -d / -f 1 | tr -d '\n' + $ACME_OPENSSL_BIN req -noout -in "$_csrfile" -subject | _egrep_o "CN *=.*" | cut -d = -f 2 | cut -d / -f 1 | tr -d '\n' } #_csrfile @@ -1061,7 +1061,7 @@ _readSubjectAltNamesFromCSR() { _csrsubj="$(_readSubjectFromCSR "$_csrfile")" _debug _csrsubj "$_csrsubj" - _dnsAltnames="$($OPENSSL_BIN req -noout -text -in "$_csrfile" | grep "^ *DNS:.*" | tr -d ' \n')" + _dnsAltnames="$($ACME_OPENSSL_BIN req -noout -text -in "$_csrfile" | grep "^ *DNS:.*" | tr -d ' \n')" _debug _dnsAltnames "$_dnsAltnames" if _contains "$_dnsAltnames," "DNS:$_csrsubj,"; then @@ -1082,7 +1082,7 @@ _readKeyLengthFromCSR() { return 1 fi - _outcsr="$($OPENSSL_BIN req -noout -text -in "$_csrfile")" + _outcsr="$($ACME_OPENSSL_BIN req -noout -text -in "$_csrfile")" if _contains "$_outcsr" "Public Key Algorithm: id-ecPublicKey"; then _debug "ECC CSR" echo "$_outcsr" | _egrep_o "^ *ASN1 OID:.*" | cut -d ':' -f 2 | tr -d ' ' @@ -1136,9 +1136,9 @@ toPkcs() { _initpath "$domain" "$_isEcc" if [ "$pfxPassword" ]; then - $OPENSSL_BIN pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH" -password "pass:$pfxPassword" + $ACME_OPENSSL_BIN pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH" -password "pass:$pfxPassword" else - $OPENSSL_BIN pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH" + $ACME_OPENSSL_BIN pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH" fi if [ "$?" = "0" ]; then @@ -1300,7 +1300,7 @@ _calcjwk() { if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then _debug "RSA key" - pub_exp=$($OPENSSL_BIN rsa -in "$keyfile" -noout -text | grep "^publicExponent:" | cut -d '(' -f 2 | cut -d 'x' -f 2 | cut -d ')' -f 1) + pub_exp=$($ACME_OPENSSL_BIN rsa -in "$keyfile" -noout -text | grep "^publicExponent:" | cut -d '(' -f 2 | cut -d 'x' -f 2 | cut -d ')' -f 1) if [ "${#pub_exp}" = "5" ]; then pub_exp=0$pub_exp fi @@ -1309,7 +1309,7 @@ _calcjwk() { e=$(echo "$pub_exp" | _h2b | _base64) _debug3 e "$e" - modulus=$($OPENSSL_BIN rsa -in "$keyfile" -modulus -noout | cut -d '=' -f 2) + modulus=$($ACME_OPENSSL_BIN rsa -in "$keyfile" -modulus -noout | cut -d '=' -f 2) _debug3 modulus "$modulus" n="$(printf "%s" "$modulus" | _h2b | _base64 | _url_replace)" _debug3 n "$n" @@ -1322,12 +1322,12 @@ _calcjwk() { JWK_HEADERPLACE_PART2='", "alg": "RS256", "jwk": '$jwk'}' elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then _debug "EC key" - crv="$($OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep "^NIST CURVE:" | cut -d ":" -f 2 | tr -d " \r\n")" + crv="$($ACME_OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep "^NIST CURVE:" | cut -d ":" -f 2 | tr -d " \r\n")" _debug3 crv "$crv" if [ -z "$crv" ]; then _debug "Let's try ASN1 OID" - crv_oid="$($OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep "^ASN1 OID:" | cut -d ":" -f 2 | tr -d " \r\n")" + crv_oid="$($ACME_OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep "^ASN1 OID:" | cut -d ":" -f 2 | tr -d " \r\n")" _debug3 crv_oid "$crv_oid" case "${crv_oid}" in "prime256v1") @@ -1347,15 +1347,15 @@ _calcjwk() { _debug3 crv "$crv" fi - pubi="$($OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep -n pub: | cut -d : -f 1)" + pubi="$($ACME_OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep -n pub: | cut -d : -f 1)" pubi=$(_math "$pubi" + 1) _debug3 pubi "$pubi" - pubj="$($OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep -n "ASN1 OID:" | cut -d : -f 1)" + pubj="$($ACME_OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep -n "ASN1 OID:" | cut -d : -f 1)" pubj=$(_math "$pubj" - 1) _debug3 pubj "$pubj" - pubtext="$($OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | sed -n "$pubi,${pubj}p" | tr -d " \n\r")" + pubtext="$($ACME_OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | sed -n "$pubi,${pubj}p" | tr -d " \n\r")" _debug3 pubtext "$pubtext" xlen="$(printf "%s" "$pubtext" | tr -d ':' | wc -c)" @@ -1964,7 +1964,7 @@ _starttlsserver() { return 1 fi - __S_OPENSSL="$OPENSSL_BIN s_server -cert $TLS_CERT -key $TLS_KEY " + __S_OPENSSL="$ACME_OPENSSL_BIN s_server -cert $TLS_CERT -key $TLS_KEY " if [ "$opaddr" ]; then __S_OPENSSL="$__S_OPENSSL -accept $opaddr:$port" else @@ -2143,8 +2143,8 @@ _initpath() { CERT_HOME="$_DEFAULT_CERT_HOME" fi - if [ -z "$OPENSSL_BIN" ]; then - OPENSSL_BIN="$DEFAULT_OPENSSL_BIN" + if [ -z "$ACME_OPENSSL_BIN" ] || [ ! -f "$ACME_OPENSSL_BIN" ] || [ ! -x "$ACME_OPENSSL_BIN" ] ; then + ACME_OPENSSL_BIN="$DEFAULT_OPENSSL_BIN" fi if [ -z "$1" ]; then @@ -4368,8 +4368,8 @@ _precheck() { fi fi - if ! _exists "$OPENSSL_BIN"; then - _err "Please install openssl first. OPENSSL_BIN=$OPENSSL_BIN" + if ! _exists "$ACME_OPENSSL_BIN"; then + _err "Please install openssl first. ACME_OPENSSL_BIN=$ACME_OPENSSL_BIN" _err "We need openssl to generate keys." return 1 fi @@ -4791,9 +4791,9 @@ _processAccountConf() { fi if [ "$_openssl_bin" ]; then - _saveaccountconf "OPENSSL_BIN" "$_openssl_bin" - elif [ "$OPENSSL_BIN" ] && [ "$OPENSSL_BIN" != "$DEFAULT_OPENSSL_BIN" ]; then - _saveaccountconf "OPENSSL_BIN" "$OPENSSL_BIN" + _saveaccountconf "ACME_OPENSSL_BIN" "$_openssl_bin" + elif [ "$ACME_OPENSSL_BIN" ] && [ "$ACME_OPENSSL_BIN" != "$DEFAULT_OPENSSL_BIN" ]; then + _saveaccountconf "ACME_OPENSSL_BIN" "$ACME_OPENSSL_BIN" fi if [ "$_auto_upgrade" ]; then @@ -5219,7 +5219,7 @@ _process() { ;; --openssl-bin) _openssl_bin="$2" - OPENSSL_BIN="$_openssl_bin" + ACME_OPENSSL_BIN="$_openssl_bin" ;; *) _err "Unknown parameter : $1" From 77f1ea40cd02024568b36daebdce55b2f41f565d Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 25 Feb 2017 19:12:20 +0800 Subject: [PATCH 095/113] fix format --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 937da149..d9f5a34e 100755 --- a/acme.sh +++ b/acme.sh @@ -2143,7 +2143,7 @@ _initpath() { CERT_HOME="$_DEFAULT_CERT_HOME" fi - if [ -z "$ACME_OPENSSL_BIN" ] || [ ! -f "$ACME_OPENSSL_BIN" ] || [ ! -x "$ACME_OPENSSL_BIN" ] ; then + if [ -z "$ACME_OPENSSL_BIN" ] || [ ! -f "$ACME_OPENSSL_BIN" ] || [ ! -x "$ACME_OPENSSL_BIN" ]; then ACME_OPENSSL_BIN="$DEFAULT_OPENSSL_BIN" fi From 4410226db1bf51e543ea46d84cdb9d567a93d92a Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 25 Feb 2017 19:31:52 +0800 Subject: [PATCH 096/113] add --toPkcs8 command fix https://github.com/Neilpang/acme.sh/issues/664 --- acme.sh | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/acme.sh b/acme.sh index d9f5a34e..e55265d0 100755 --- a/acme.sh +++ b/acme.sh @@ -1147,6 +1147,27 @@ toPkcs() { } +#domain [isEcc] +toPkcs8() { + domain="$1" + + if [ -z "$domain" ]; then + _usage "Usage: $PROJECT_ENTRY --toPkcs8 -d domain [--ecc]" + return 1 + fi + + _isEcc="$2" + + _initpath "$domain" "$_isEcc" + + $ACME_OPENSSL_BIN pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in "$CERT_KEY_PATH" -out "$CERT_PKCS8_PATH" + + if [ "$?" = "0" ]; then + _info "Success, $CERT_PKCS8_PATH" + fi + +} + #[2048] createAccountKey() { _info "Creating account key" @@ -2200,6 +2221,9 @@ _initpath() { if [ -z "$CERT_PFX_PATH" ]; then CERT_PFX_PATH="$DOMAIN_PATH/$domain.pfx" fi + if [ -z "$CERT_PKCS8_PATH" ]; then + CERT_PKCS8_PATH="$DOMAIN_PATH/$domain.pkcs8" + fi if [ -z "$TLS_CONF" ]; then TLS_CONF="$DOMAIN_PATH/tls.valdation.conf" @@ -4661,6 +4685,7 @@ Commands: --uninstall-cronjob Uninstall the cron job. The 'uninstall' command can do this automatically. --cron Run cron job to renew all the certs. --toPkcs Export the certificate and key to a pfx file. + --toPkcs8 Convert to pkcs8 format. --update-account Update account info. --register-account Register account key. --create-account-key Create an account private key, professional use. @@ -4908,6 +4933,9 @@ _process() { --toPkcs) _CMD="toPkcs" ;; + --toPkcs8) + _CMD="toPkcs8" + ;; --createAccountKey | --createaccountkey | -cak | --create-account-key) _CMD="createAccountKey" ;; @@ -5320,6 +5348,9 @@ _process() { toPkcs) toPkcs "$_domain" "$_password" "$_ecc" ;; + toPkcs8) + toPkcs8 "$_domain" "$_ecc" + ;; createAccountKey) createAccountKey "$_accountkeylength" ;; From 342128a457a5d1124b084d419653dd4957c7c2c8 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 25 Feb 2017 21:09:06 +0800 Subject: [PATCH 097/113] fix format --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index e55265d0..3def82a0 100755 --- a/acme.sh +++ b/acme.sh @@ -4935,7 +4935,7 @@ _process() { ;; --toPkcs8) _CMD="toPkcs8" - ;; + ;; --createAccountKey | --createaccountkey | -cak | --create-account-key) _CMD="createAccountKey" ;; From 4fd63f4e302c381cd167f9e3ed1c4bdc3ba0da2e Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 25 Feb 2017 21:22:56 +0800 Subject: [PATCH 098/113] fix ci --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1d54faed..7f7e120c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,9 +26,9 @@ install: _old_path="$PATH"; echo "PATH=$PATH"; export PATH=""; - export OPENSSL_BIN="/usr/local/openssl"; + export ACME_OPENSSL_BIN="/usr/local/openssl"; openssl version 2>&1 || true; - $OPENSSL_BIN version 2>&1 || true; + $ACME_OPENSSL_BIN version 2>&1 || true; export PATH="$_old_path"; fi @@ -44,7 +44,7 @@ script: - cd .. - git clone https://github.com/Neilpang/acmetest.git && cp -r acme.sh acmetest/ && cd acmetest - if [ "$TRAVIS_OS_NAME" = "linux" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ./letest.sh ; fi - - if [ "$TRAVIS_OS_NAME" = "osx" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" OPENSSL_BIN="$OPENSSL_BIN" ./letest.sh ; fi + - if [ "$TRAVIS_OS_NAME" = "osx" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ACME_OPENSSL_BIN="$ACME_OPENSSL_BIN" ./letest.sh ; fi matrix: From 58e4d337e4eaa93de9ca0fdeb661df5ecdb1e50e Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 26 Feb 2017 12:07:06 +0800 Subject: [PATCH 099/113] clear the pending authz when issue error fix bug https://github.com/Neilpang/acme.sh/issues/663 --- acme.sh | 59 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 15 deletions(-) diff --git a/acme.sh b/acme.sh index 3def82a0..f11f1f07 100755 --- a/acme.sh +++ b/acme.sh @@ -2819,6 +2819,7 @@ _on_before_issue() { _on_issue_err() { _chk_post_hook="$1" + _chk_vlist="$2" _debug _on_issue_err if [ "$LOG_FILE" ]; then _err "Please check log file for more details: $LOG_FILE" @@ -2827,10 +2828,6 @@ _on_issue_err() { _err "See: $_DEBUG_WIKI" fi - if [ "$DEBUG" ] && [ "$DEBUG" -gt "0" ]; then - _debug "$(_dlg_versions)" - fi - #run the post hook if [ "$_chk_post_hook" ]; then _info "Run post hook:'$_chk_post_hook'" @@ -2841,6 +2838,28 @@ _on_issue_err() { return 1 fi fi + + #trigger the validation to flush the pending authz + if [ "$_chk_vlist" ]; then + ( + _debug2 "_chk_vlist" "$_chk_vlist" + _debug2 "start to deactivate authz" + ventries=$(echo "$_chk_vlist" | tr "$dvsep" ' ') + for ventry in $ventries; do + d=$(echo "$ventry" | cut -d "$sep" -f 1) + keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2) + uri=$(echo "$ventry" | cut -d "$sep" -f 3) + vtype=$(echo "$ventry" | cut -d "$sep" -f 4) + _currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5) + __trigger_validaton "$uri" "$keyauthorization" + done + ) + fi + + if [ "$DEBUG" ] && [ "$DEBUG" -gt "0" ]; then + _debug "$(_dlg_versions)" + fi + } _on_issue_success() { @@ -3053,6 +3072,16 @@ __get_domain_new_authz() { } +#uri keyAuthorization +__trigger_validaton() { + _debug2 "tigger domain validation." + _t_url="$1" + _debug2 _t_url "$_t_url" + _t_key_authz="$2" + _debug2 _t_key_authz "$_t_key_authz" + _send_signed_request "$_t_url" "{\"resource\": \"challenge\", \"keyAuthorization\": \"$_t_key_authz\"}" +} + #webroot, domain domainlist keylength issue() { if [ -z "$2" ]; then @@ -3366,7 +3395,7 @@ issue() { _startserver "$keyauthorization" "$_ncaddr" & if [ "$?" != "0" ]; then _clearup - _on_issue_err "$_post_hook" + _on_issue_err "$_post_hook" "$vlist" return 1 fi serverproc="$!" @@ -3382,7 +3411,7 @@ issue() { BACKUP_NGINX_CONF="" if ! _setNginx "$d" "$_currentRoot" "$thumbprint"; then _clearup - _on_issue_err "$_post_hook" + _on_issue_err "$_post_hook" "$vlist" return 1 fi @@ -3417,7 +3446,7 @@ issue() { _err "$d:Can not write token to file : $wellknown_path/$token" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup - _on_issue_err "$_post_hook" + _on_issue_err "$_post_hook" "$vlist" return 1 fi @@ -3462,16 +3491,16 @@ issue() { _err "Start tls server error." _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup - _on_issue_err "$_post_hook" + _on_issue_err "$_post_hook" "$vlist" return 1 fi fi - if ! _send_signed_request "$uri" "{\"resource\": \"challenge\", \"keyAuthorization\": \"$keyauthorization\"}"; then + if ! __trigger_validaton "$uri" "$keyauthorization"; then _err "$d:Can not get challenge: $response" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup - _on_issue_err "$_post_hook" + _on_issue_err "$_post_hook" "$vlist" return 1 fi @@ -3479,7 +3508,7 @@ issue() { _err "$d:Challenge error: $response" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup - _on_issue_err "$_post_hook" + _on_issue_err "$_post_hook" "$vlist" return 1 fi @@ -3494,7 +3523,7 @@ issue() { _err "$d:Timeout" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup - _on_issue_err + _on_issue_err "$_post_hook" "$vlist" return 1 fi @@ -3506,7 +3535,7 @@ issue() { _err "$d:Verify error:$response" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup - _on_issue_err "$_post_hook" + _on_issue_err "$_post_hook" "$vlist" return 1 fi _debug2 original "$response" @@ -3541,7 +3570,7 @@ issue() { fi _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup - _on_issue_err "$_post_hook" + _on_issue_err "$_post_hook" "$vlist" return 1 fi @@ -3551,7 +3580,7 @@ issue() { _err "$d:Verify error:$response" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup - _on_issue_err "$_post_hook" + _on_issue_err "$_post_hook" "$vlist" return 1 fi From c719a61ea70ad1a19337fe0cbb61c1cc0e80540b Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 26 Feb 2017 12:15:39 +0800 Subject: [PATCH 100/113] fix format --- acme.sh | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/acme.sh b/acme.sh index f11f1f07..ecc6cb24 100755 --- a/acme.sh +++ b/acme.sh @@ -2842,17 +2842,17 @@ _on_issue_err() { #trigger the validation to flush the pending authz if [ "$_chk_vlist" ]; then ( - _debug2 "_chk_vlist" "$_chk_vlist" - _debug2 "start to deactivate authz" - ventries=$(echo "$_chk_vlist" | tr "$dvsep" ' ') - for ventry in $ventries; do - d=$(echo "$ventry" | cut -d "$sep" -f 1) - keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2) - uri=$(echo "$ventry" | cut -d "$sep" -f 3) - vtype=$(echo "$ventry" | cut -d "$sep" -f 4) - _currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5) - __trigger_validaton "$uri" "$keyauthorization" - done + _debug2 "_chk_vlist" "$_chk_vlist" + _debug2 "start to deactivate authz" + ventries=$(echo "$_chk_vlist" | tr "$dvsep" ' ') + for ventry in $ventries; do + d=$(echo "$ventry" | cut -d "$sep" -f 1) + keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2) + uri=$(echo "$ventry" | cut -d "$sep" -f 3) + vtype=$(echo "$ventry" | cut -d "$sep" -f 4) + _currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5) + __trigger_validaton "$uri" "$keyauthorization" + done ) fi From 7c2e87549496e18c57253428252f8ff67ed73d53 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 26 Feb 2017 22:20:08 +0800 Subject: [PATCH 101/113] fix https://github.com/Neilpang/acme.sh/issues/675 --- acme.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/acme.sh b/acme.sh index ecc6cb24..724f0e97 100755 --- a/acme.sh +++ b/acme.sh @@ -5277,6 +5277,7 @@ _process() { --openssl-bin) _openssl_bin="$2" ACME_OPENSSL_BIN="$_openssl_bin" + shift ;; *) _err "Unknown parameter : $1" From 81532f375ea6f9b55e19b07bbe1c106f3d164b19 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 27 Feb 2017 13:38:29 +0800 Subject: [PATCH 102/113] fix https://github.com/Neilpang/acme.sh/issues/667#issuecomment-282629936 --- acme.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/acme.sh b/acme.sh index 724f0e97..d2bb6c53 100755 --- a/acme.sh +++ b/acme.sh @@ -927,6 +927,15 @@ _createkey() { _debug "Use length $length" + if ! touch "$f" >/dev/null 2>&1; then + _f_path="$(dirname "$f")" + _debug _f_path "$_f_path" + if ! mkdir -p "$_f_path"; then + _err "Can not create path: $_f_path" + return 1 + fi + fi + if _isEccKey "$length"; then _debug "Using ec name: $eccname" $ACME_OPENSSL_BIN ecparam -name "$eccname" -genkey 2>/dev/null >"$f" From 9b124070286abde59d5afcffe67a6773c3135a78 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 27 Feb 2017 20:48:48 +0800 Subject: [PATCH 103/113] Wget (#678) * --use-wget force to use wget * fix force wget --- acme.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index d2bb6c53..3e9e4d15 100755 --- a/acme.sh +++ b/acme.sh @@ -1505,7 +1505,7 @@ _post() { _inithttp - if [ "$_ACME_CURL" ]; then + if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then _CURL="$_ACME_CURL" if [ "$HTTPS_INSECURE" ]; then _CURL="$_CURL --insecure " @@ -1572,7 +1572,7 @@ _get() { _inithttp - if [ "$_ACME_CURL" ]; then + if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then _CURL="$_ACME_CURL" if [ "$HTTPS_INSECURE" ]; then _CURL="$_CURL --insecure " @@ -4787,6 +4787,7 @@ Parameters: --listen-v4 Force standalone/tls server to listen at ipv4. --listen-v6 Force standalone/tls server to listen at ipv6. --openssl-bin Specifies a custom openssl bin location. + --use-wget Force to use wget, if you have both curl and wget installed. " } @@ -4865,6 +4866,12 @@ _processAccountConf() { _saveaccountconf "AUTO_UPGRADE" "$AUTO_UPGRADE" fi + if [ "$_use_wget" ]; then + _saveaccountconf "ACME_USE_WGET" "$_use_wget" + elif [ "$ACME_USE_WGET" ]; then + _saveaccountconf "ACME_USE_WGET" "$ACME_USE_WGET" + fi + } _process() { @@ -4909,6 +4916,7 @@ _process() { _listen_v6="" _openssl_bin="" _syslog="" + _use_wget="" while [ ${#} -gt 0 ]; do case "${1}" in @@ -5288,6 +5296,10 @@ _process() { ACME_OPENSSL_BIN="$_openssl_bin" shift ;; + --use-wget) + _use_wget="1" + ACME_USE_WGET="1" + ;; *) _err "Unknown parameter : $1" return 1 From 59f7a2f6efb93fd81098146a0f8fe8367c155eb8 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 27 Feb 2017 20:54:38 +0800 Subject: [PATCH 104/113] Wget (#678) (#679) * --use-wget force to use wget * fix force wget --- acme.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index d2bb6c53..3e9e4d15 100755 --- a/acme.sh +++ b/acme.sh @@ -1505,7 +1505,7 @@ _post() { _inithttp - if [ "$_ACME_CURL" ]; then + if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then _CURL="$_ACME_CURL" if [ "$HTTPS_INSECURE" ]; then _CURL="$_CURL --insecure " @@ -1572,7 +1572,7 @@ _get() { _inithttp - if [ "$_ACME_CURL" ]; then + if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then _CURL="$_ACME_CURL" if [ "$HTTPS_INSECURE" ]; then _CURL="$_CURL --insecure " @@ -4787,6 +4787,7 @@ Parameters: --listen-v4 Force standalone/tls server to listen at ipv4. --listen-v6 Force standalone/tls server to listen at ipv6. --openssl-bin Specifies a custom openssl bin location. + --use-wget Force to use wget, if you have both curl and wget installed. " } @@ -4865,6 +4866,12 @@ _processAccountConf() { _saveaccountconf "AUTO_UPGRADE" "$AUTO_UPGRADE" fi + if [ "$_use_wget" ]; then + _saveaccountconf "ACME_USE_WGET" "$_use_wget" + elif [ "$ACME_USE_WGET" ]; then + _saveaccountconf "ACME_USE_WGET" "$ACME_USE_WGET" + fi + } _process() { @@ -4909,6 +4916,7 @@ _process() { _listen_v6="" _openssl_bin="" _syslog="" + _use_wget="" while [ ${#} -gt 0 ]; do case "${1}" in @@ -5288,6 +5296,10 @@ _process() { ACME_OPENSSL_BIN="$_openssl_bin" shift ;; + --use-wget) + _use_wget="1" + ACME_USE_WGET="1" + ;; *) _err "Unknown parameter : $1" return 1 From fab2d9dc6ada42e2ac15abda2bd2f2ea73cf8bfc Mon Sep 17 00:00:00 2001 From: Frederic Crozat Date: Tue, 28 Feb 2017 12:58:04 +0100 Subject: [PATCH 105/113] add API for Gandi LiveDNS (#680) * add API for Gandi LiveDNS * ensure Gandi API key is saved for renewing certificate. * gandi_livedns: use PUT instead of POST for creating DNS record * gandi_livedns: fix formatting * dns_gandi_livedns: fix shellcheck errors --- README.md | 1 + dnsapi/README.md | 12 ++++ dnsapi/dns_gandi_livedns.sh | 120 ++++++++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100755 dnsapi/dns_gandi_livedns.sh diff --git a/README.md b/README.md index c8aeeb0f..fd867015 100644 --- a/README.md +++ b/README.md @@ -294,6 +294,7 @@ You don't have to do anything manually! 1. FreeDNS (https://freedns.afraid.org/) 1. cyon.ch 1. Domain-Offensive/Resellerinterface/Domainrobot API +1. Gandi LiveDNS API **More APIs coming soon...** diff --git a/dnsapi/README.md b/dnsapi/README.md index 7df7142a..7607257d 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -336,6 +336,18 @@ Ok, let's issue a cert now: acme.sh --issue --dns dns_do -d example.com -d www.example.com ``` +## 18. Use Gandi LiveDNS API + +You will need your Gandi API key (on your Account preferences, go to Security and generate your API key) and export it before you run `acme.sh`: +``` +export GANDI_LIVEDNS_KEY="fdmlfsdklmfdkmqsdfk" +``` + +Ok, let's issue a cert now: +``` +acme.sh --issue --dns dns_gandi_livedns -d example.com -d www.example.com +``` + # Use custom API If your API is not supported yet, you can write your own DNS API. diff --git a/dnsapi/dns_gandi_livedns.sh b/dnsapi/dns_gandi_livedns.sh new file mode 100755 index 00000000..9a170b8b --- /dev/null +++ b/dnsapi/dns_gandi_livedns.sh @@ -0,0 +1,120 @@ +#!/usr/bin/env sh + +# Gandi LiveDNS v5 API +# http://doc.livedns.gandi.net/ +# currently under beta +# +# Requires GANDI API KEY set in GANDI_LIVEDNS_KEY set as environment variable +# +#Author: Frédéric Crozat +#Report Bugs here: https://github.com/fcrozat/acme.sh +# +######## Public functions ##################### + +GANDI_LIVEDNS_API="https://dns.beta.gandi.net/api/v5" + +#Usage: dns_gandi_livedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_gandi_livedns_add() { + fulldomain=$1 + txtvalue=$2 + + if [ -z "$GANDI_LIVEDNS_KEY" ]; then + _err "No API key specifed for Gandi LiveDNS." + _err "Create your key and export it as GANDI_LIVEDNS_KEY" + return 1 + fi + + _saveaccountconf GANDI_LIVEDNS_KEY "$GANDI_LIVEDNS_KEY" + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + _debug domain "$_domain" + _debug sub_domain "$_sub_domain" + + _gandi_livedns_rest PUT "domains/$_domain/records/$_sub_domain/TXT" "{\"rrset_ttl\": 300, \"rrset_values\":[\"$txtvalue\"]}" + + return $? +} + +#Usage: fulldomain txtvalue +#Remove the txt record after validation. +dns_gandi_livedns_rm() { + fulldomain=$1 + txtvalue=$2 + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + _debug fulldomain "$fulldomain" + _debug domain "$_domain" + _debug sub_domain "$_sub_domain" + + _gandi_livedns_rest DELETE "domains/$_domain/records/$_sub_domain/TXT" "" + + return $? +} + +#################### Private functions below ################################## +#_acme-challenge.www.domain.com +#returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +_get_root() { + domain=$1 + i=2 + p=1 + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + if [ -z "$h" ]; then + #not valid + return 1 + fi + + if ! _gandi_livedns_rest GET "domains/$h"; then + return 1 + fi + + if _contains "$response" '"code": 404'; then + _debug "$h not found" + else + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain="$h" + return 0 + fi + p="$i" + i=$(_math "$i" + 1) + done + return 1 +} + +_gandi_livedns_rest() { + m=$1 + ep="$2" + data="$3" + _debug "$ep" + + export _H1="Content-Type: application/json" + export _H2="X-Api-Key: $GANDI_LIVEDNS_KEY" + + if [ "$data" ] || [ "$m" = "DELETE" ]; then + _debug data "$data" + response="$(_post "$data" "$GANDI_LIVEDNS_API/$ep" "" "$m")" + else + response="$(_get "$GANDI_LIVEDNS_API/$ep")" + fi + + if [ "$?" != "0" ]; then + _err "error $ep" + return 1 + fi + _debug2 response "$response" + return 0 +} From 9683ffe13a08ffee278c74b7059a190e4084f417 Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 28 Feb 2017 20:39:23 +0800 Subject: [PATCH 106/113] minor fix error message --- dnsapi/README.md | 3 ++- dnsapi/dns_gandi_livedns.sh | 13 +++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/dnsapi/README.md b/dnsapi/README.md index 7607257d..18c1ca9f 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -338,7 +338,8 @@ acme.sh --issue --dns dns_do -d example.com -d www.example.com ## 18. Use Gandi LiveDNS API -You will need your Gandi API key (on your Account preferences, go to Security and generate your API key) and export it before you run `acme.sh`: +You must enable the new Gandi LiveDNS API first and the create your api key, See: http://doc.livedns.gandi.net/ + ``` export GANDI_LIVEDNS_KEY="fdmlfsdklmfdkmqsdfk" ``` diff --git a/dnsapi/dns_gandi_livedns.sh b/dnsapi/dns_gandi_livedns.sh index 9a170b8b..76c4c8a9 100755 --- a/dnsapi/dns_gandi_livedns.sh +++ b/dnsapi/dns_gandi_livedns.sh @@ -38,7 +38,6 @@ dns_gandi_livedns_add() { _gandi_livedns_rest PUT "domains/$_domain/records/$_sub_domain/TXT" "{\"rrset_ttl\": 300, \"rrset_values\":[\"$txtvalue\"]}" - return $? } #Usage: fulldomain txtvalue @@ -59,7 +58,6 @@ dns_gandi_livedns_rm() { _gandi_livedns_rest DELETE "domains/$_domain/records/$_sub_domain/TXT" "" - return $? } #################### Private functions below ################################## @@ -82,7 +80,10 @@ _get_root() { return 1 fi - if _contains "$response" '"code": 404'; then + if _contains "$response" '"code": 401'; then + _err "$response" + return 1 + elif _contains "$response" '"code": 404'; then _debug "$h not found" else _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) @@ -104,11 +105,11 @@ _gandi_livedns_rest() { export _H1="Content-Type: application/json" export _H2="X-Api-Key: $GANDI_LIVEDNS_KEY" - if [ "$data" ] || [ "$m" = "DELETE" ]; then + if [ "$m" = "GET" ]; then + response="$(_get "$GANDI_LIVEDNS_API/$ep")" + else _debug data "$data" response="$(_post "$data" "$GANDI_LIVEDNS_API/$ep" "" "$m")" - else - response="$(_get "$GANDI_LIVEDNS_API/$ep")" fi if [ "$?" != "0" ]; then From d24a87caf189dbcfaa066645f4076d755afb2a87 Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 28 Feb 2017 20:56:11 +0800 Subject: [PATCH 107/113] minor --- dnsapi/dns_gandi_livedns.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_gandi_livedns.sh b/dnsapi/dns_gandi_livedns.sh index 76c4c8a9..d2521941 100755 --- a/dnsapi/dns_gandi_livedns.sh +++ b/dnsapi/dns_gandi_livedns.sh @@ -37,7 +37,7 @@ dns_gandi_livedns_add() { _debug sub_domain "$_sub_domain" _gandi_livedns_rest PUT "domains/$_domain/records/$_sub_domain/TXT" "{\"rrset_ttl\": 300, \"rrset_values\":[\"$txtvalue\"]}" - + _contains "$response" '{"message": "Zone Record Created"}' } #Usage: fulldomain txtvalue @@ -71,6 +71,7 @@ _get_root() { p=1 while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug h "$h" if [ -z "$h" ]; then #not valid return 1 From 39a1f1ef644cef0daeb8fffa94cc8d844e207639 Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 28 Feb 2017 21:04:33 +0800 Subject: [PATCH 108/113] fix 404 for wget --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 3e9e4d15..a8b3e038 100755 --- a/acme.sh +++ b/acme.sh @@ -1610,7 +1610,7 @@ _get() { fi ret=$? if [ "$_ret" = "8" ]; then - _ret=0 + ret=0 _debug "wget returns 8, the server returns a 'Bad request' respons, lets process the response later." fi if [ "$ret" != "0" ]; then From f731a4c7041416612ffdf593f9d5763a850c09ac Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 28 Feb 2017 21:06:02 +0800 Subject: [PATCH 109/113] fix 404 for wget --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index a8b3e038..b87df6d6 100755 --- a/acme.sh +++ b/acme.sh @@ -1609,7 +1609,7 @@ _get() { $_WGET --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" -O - "$url" fi ret=$? - if [ "$_ret" = "8" ]; then + if [ "$ret" = "8" ]; then ret=0 _debug "wget returns 8, the server returns a 'Bad request' respons, lets process the response later." fi From 810c129ca970b7ae26e1e648f90670b8d91d2beb Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 28 Feb 2017 21:08:20 +0800 Subject: [PATCH 110/113] minor fix error message --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index b87df6d6..a18be6f4 100755 --- a/acme.sh +++ b/acme.sh @@ -1546,7 +1546,7 @@ _post() { _ret="$?" if [ "$_ret" = "8" ]; then _ret=0 - _debug "wget returns 8, the server returns a 'Bad request' respons, lets process the response later." + _debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later." fi if [ "$_ret" != "0" ]; then _err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $_ret" @@ -1611,7 +1611,7 @@ _get() { ret=$? if [ "$ret" = "8" ]; then ret=0 - _debug "wget returns 8, the server returns a 'Bad request' respons, lets process the response later." + _debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later." fi if [ "$ret" != "0" ]; then _err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $ret" From 177b57e1c007f185c87e9791c6f31b68ba0b302e Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 28 Feb 2017 21:35:20 +0800 Subject: [PATCH 111/113] fix wget content on 404 error --- acme.sh | 5 +++++ dnsapi/dns_gandi_livedns.sh | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index a18be6f4..7c2875fd 100755 --- a/acme.sh +++ b/acme.sh @@ -1485,6 +1485,11 @@ _inithttp() { fi fi + #from wget 1.14: do not skip body on 404 error + if [ "$_ACME_WGET" ] && _contains "$($_ACME_WGET --help)" "--content-on-error"; then + _ACME_WGET="$_ACME_WGET --content-on-error " + fi + __HTTP_INITIALIZED=1 } diff --git a/dnsapi/dns_gandi_livedns.sh b/dnsapi/dns_gandi_livedns.sh index d2521941..55218a20 100755 --- a/dnsapi/dns_gandi_livedns.sh +++ b/dnsapi/dns_gandi_livedns.sh @@ -36,8 +36,9 @@ dns_gandi_livedns_add() { _debug domain "$_domain" _debug sub_domain "$_sub_domain" - _gandi_livedns_rest PUT "domains/$_domain/records/$_sub_domain/TXT" "{\"rrset_ttl\": 300, \"rrset_values\":[\"$txtvalue\"]}" - _contains "$response" '{"message": "Zone Record Created"}' + _gandi_livedns_rest PUT "domains/$_domain/records/$_sub_domain/TXT" "{\"rrset_ttl\": 300, \"rrset_values\":[\"$txtvalue\"]}" \ + && _contains "$response" '{"message": "Zone Record Created"}' \ + && _info "Add $(__green "success")" } #Usage: fulldomain txtvalue From 58ef6d83852f5bffc6ad00311a139f5f60ec4a2b Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 1 Mar 2017 13:12:29 +0800 Subject: [PATCH 112/113] fix wget error message --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 7c2875fd..0313e0e1 100755 --- a/acme.sh +++ b/acme.sh @@ -1486,7 +1486,7 @@ _inithttp() { fi #from wget 1.14: do not skip body on 404 error - if [ "$_ACME_WGET" ] && _contains "$($_ACME_WGET --help)" "--content-on-error"; then + if [ "$_ACME_WGET" ] && _contains "$($_ACME_WGET --help 2>&1)" "--content-on-error"; then _ACME_WGET="$_ACME_WGET --content-on-error " fi From 839f18d052c0dff1d6e38c098087e68832788f39 Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 1 Mar 2017 19:17:20 +0800 Subject: [PATCH 113/113] fix format --- dnsapi/dns_gandi_livedns.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_gandi_livedns.sh b/dnsapi/dns_gandi_livedns.sh index 55218a20..41f42980 100755 --- a/dnsapi/dns_gandi_livedns.sh +++ b/dnsapi/dns_gandi_livedns.sh @@ -37,8 +37,8 @@ dns_gandi_livedns_add() { _debug sub_domain "$_sub_domain" _gandi_livedns_rest PUT "domains/$_domain/records/$_sub_domain/TXT" "{\"rrset_ttl\": 300, \"rrset_values\":[\"$txtvalue\"]}" \ - && _contains "$response" '{"message": "Zone Record Created"}' \ - && _info "Add $(__green "success")" + && _contains "$response" '{"message": "Zone Record Created"}' \ + && _info "Add $(__green "success")" } #Usage: fulldomain txtvalue