From c6ec8bc0d9f1db2fb0f90c20a5cfbc0ae552e2f9 Mon Sep 17 00:00:00 2001 From: rewqazxv <41326691+rewqazxv@users.noreply.github.com> Date: Wed, 6 Nov 2019 18:57:05 +0800 Subject: [PATCH 001/161] fix sudo issue --- acme.sh | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/acme.sh b/acme.sh index 81a20b0b..4a1ce9b7 100755 --- a/acme.sh +++ b/acme.sh @@ -6362,11 +6362,17 @@ _checkSudo() { #it's root using sudo, no matter it's using sudo or not, just fine return 0 fi - if [ "$SUDO_COMMAND" = "/bin/su" ] || [ "$SUDO_COMMAND" = "/bin/bash" ]; then - #it's a normal user doing "sudo su", or `sudo -i` or `sudo -s` - #fine - return 0 - fi + case "$SUDO_COMMAND" in + */su ) + #it's a normal user doing `sudo su`, no problem + return 0 ;; + esac + for i in `cat /etc/shells`; do + if [ "$SUDO_COMMAND" = "$i" ]; then + #it's a normal user running `sudo -i` or `sudo -s`, fine + return 0 + fi + done #otherwise return 1 fi From 6a5ee72722550c76cb925916cfde2f103bda8b40 Mon Sep 17 00:00:00 2001 From: rewqazxv <41326691+rewqazxv@users.noreply.github.com> Date: Wed, 6 Nov 2019 20:27:12 +0800 Subject: [PATCH 002/161] format code style --- acme.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index 4a1ce9b7..d3c0fc7a 100755 --- a/acme.sh +++ b/acme.sh @@ -6363,11 +6363,12 @@ _checkSudo() { return 0 fi case "$SUDO_COMMAND" in - */su ) + */su) #it's a normal user doing `sudo su`, no problem - return 0 ;; + return 0 + ;; esac - for i in `cat /etc/shells`; do + for i in $(cat /etc/shells); do if [ "$SUDO_COMMAND" = "$i" ]; then #it's a normal user running `sudo -i` or `sudo -s`, fine return 0 From 79ad0ff56baac1a338d4155e40f77bc8eeae8109 Mon Sep 17 00:00:00 2001 From: rewqazxv <41326691+rewqazxv@users.noreply.github.com> Date: Wed, 15 Jan 2020 22:11:34 +0800 Subject: [PATCH 003/161] Simplify code --- acme.sh | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/acme.sh b/acme.sh index d3c0fc7a..00d10fcc 100755 --- a/acme.sh +++ b/acme.sh @@ -6362,18 +6362,11 @@ _checkSudo() { #it's root using sudo, no matter it's using sudo or not, just fine return 0 fi - case "$SUDO_COMMAND" in - */su) - #it's a normal user doing `sudo su`, no problem - return 0 - ;; - esac - for i in $(cat /etc/shells); do - if [ "$SUDO_COMMAND" = "$i" ]; then - #it's a normal user running `sudo -i` or `sudo -s`, fine - return 0 - fi - done + if [ -n "$SUDO_COMMAND" ]; then + #it's a normal user doing "sudo su", or `sudo -i` or `sudo -s` + _endswith "$SUDO_COMMAND" /bin/su || grep "^$SUDO_COMMAND\$" /etc/shells >/dev/null 2>&1 + return $? + fi #otherwise return 1 fi From 3d9608faa086890321ba8d9d630c5b659f89ed46 Mon Sep 17 00:00:00 2001 From: dkerr64 Date: Sat, 22 Feb 2020 20:09:24 -0500 Subject: [PATCH 004/161] Move -T parameter into default ssh command variable --- deploy/ssh.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index 9cb0af9e..783e6f7b 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -12,7 +12,7 @@ # Only a username is required. All others are optional. # # The following examples are for QNAP NAS running QTS 4.2 -# export DEPLOY_SSH_CMD="" # defaults to ssh +# export DEPLOY_SSH_CMD="" # defaults to "ssh -T" # export DEPLOY_SSH_USER="admin" # required # export DEPLOY_SSH_SERVER="qnap" # defaults to domain name # export DEPLOY_SSH_KEYFILE="/etc/stunnel/stunnel.pem" @@ -71,7 +71,7 @@ ssh_deploy() { Le_Deploy_ssh_cmd="$DEPLOY_SSH_CMD" _savedomainconf Le_Deploy_ssh_cmd "$Le_Deploy_ssh_cmd" elif [ -z "$Le_Deploy_ssh_cmd" ]; then - Le_Deploy_ssh_cmd="ssh" + Le_Deploy_ssh_cmd="ssh -T" fi # BACKUP is optional. If not provided then default to yes @@ -194,7 +194,7 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d _info "Submitting sequence of commands to remote server by ssh" # quotations in bash cmd below intended. Squash travis spellcheck error # shellcheck disable=SC2029 - $Le_Deploy_ssh_cmd -T "$Le_Deploy_ssh_user@$Le_Deploy_ssh_server" sh -c "'$_cmdstr'" + $Le_Deploy_ssh_cmd "$Le_Deploy_ssh_user@$Le_Deploy_ssh_server" sh -c "'$_cmdstr'" _ret="$?" if [ "$_ret" != "0" ]; then From 04771e5a4ae243cdc757b7d3159cef92fce40605 Mon Sep 17 00:00:00 2001 From: dkerr64 Date: Sat, 22 Feb 2020 20:16:36 -0500 Subject: [PATCH 005/161] Move call to remote system into separate function --- deploy/ssh.sh | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index 783e6f7b..8c83f0b3 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -31,6 +31,7 @@ ssh_deploy() { _ccert="$3" _cca="$4" _cfullchain="$5" + _err_code=0 _cmdstr="" _homedir='~' _backupprefix="$_homedir/.acme_ssh_deploy/$_cdomain-backup" @@ -190,16 +191,25 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d _info "Backup directories erased after 180 days." fi - _secure_debug "Remote commands to execute: " "$_cmdstr" - _info "Submitting sequence of commands to remote server by ssh" + if ! _ssh_remote_cmd "$_cmdstr"; then + return $_err_code + fi + + return 0 +} + +#cmd +_ssh_remote_cmd() { + _secure_debug "Remote commands to execute: $_cmd" + _info "Submitting sequence of commands to remote server by $Le_Deploy_ssh_cmd" # quotations in bash cmd below intended. Squash travis spellcheck error # shellcheck disable=SC2029 - $Le_Deploy_ssh_cmd "$Le_Deploy_ssh_user@$Le_Deploy_ssh_server" sh -c "'$_cmdstr'" - _ret="$?" + $Le_Deploy_ssh_cmd "$Le_Deploy_ssh_user@$Le_Deploy_ssh_server" sh -c "'$_cmd'" + _err_code="$?" - if [ "$_ret" != "0" ]; then - _err "Error code $_ret returned from $Le_Deploy_ssh_cmd" + if [ "$_err_code" != "0" ]; then + _err "Error code $_err_code returned from $Le_Deploy_ssh_cmd" fi - return $_ret + return $_err_code } From 6420d1239fda00fb5d40299bfbf1b22c4af4762f Mon Sep 17 00:00:00 2001 From: dkerr64 Date: Sat, 22 Feb 2020 20:31:52 -0500 Subject: [PATCH 006/161] Move call to remote system into separate function --- deploy/ssh.sh | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index 783e6f7b..00d9d21d 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -31,6 +31,7 @@ ssh_deploy() { _ccert="$3" _cca="$4" _cfullchain="$5" + _err_code=0 _cmdstr="" _homedir='~' _backupprefix="$_homedir/.acme_ssh_deploy/$_cdomain-backup" @@ -190,16 +191,26 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d _info "Backup directories erased after 180 days." fi - _secure_debug "Remote commands to execute: " "$_cmdstr" - _info "Submitting sequence of commands to remote server by ssh" + if ! _ssh_remote_cmd "$_cmdstr"; then + return $_err_code + fi + + return 0 +} + +#cmd +_ssh_remote_cmd() { + _cmd="$1" + _secure_debug "Remote commands to execute: $_cmd" + _info "Submitting sequence of commands to remote server by $Le_Deploy_ssh_cmd" # quotations in bash cmd below intended. Squash travis spellcheck error # shellcheck disable=SC2029 - $Le_Deploy_ssh_cmd "$Le_Deploy_ssh_user@$Le_Deploy_ssh_server" sh -c "'$_cmdstr'" - _ret="$?" + $Le_Deploy_ssh_cmd "$Le_Deploy_ssh_user@$Le_Deploy_ssh_server" sh -c "'$_cmd'" + _err_code="$?" - if [ "$_ret" != "0" ]; then - _err "Error code $_ret returned from $Le_Deploy_ssh_cmd" + if [ "$_err_code" != "0" ]; then + _err "Error code $_err_code returned from $Le_Deploy_ssh_cmd" fi - return $_ret + return $_err_code } From 283b04df739dff70ed22ee20ffac6a1c576db842 Mon Sep 17 00:00:00 2001 From: dkerr64 Date: Sat, 22 Feb 2020 20:43:28 -0500 Subject: [PATCH 007/161] Move cleanup of backup directory to first step in the function. --- deploy/ssh.sh | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index 00d9d21d..39a0a218 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -85,6 +85,19 @@ ssh_deploy() { _info "Deploy certificates to remote server $Le_Deploy_ssh_user@$Le_Deploy_ssh_server" + if [ "$Le_Deploy_ssh_backup" = "yes" ]; then + # run cleanup on the backup directory, erase all older + # than 180 days (15552000 seconds). + _cmdstr="{ now=\"\$(date -u +%s)\"; for fn in $_backupprefix*; \ +do if [ -d \"\$fn\" ] && [ \"\$(expr \$now - \$(date -ur \$fn +%s) )\" -ge \"15552000\" ]; \ +then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; done; }; $_cmdstr" + # Alternate version of above... _cmdstr="find $_backupprefix* -type d -mtime +180 2>/dev/null | xargs rm -rf; $_cmdstr" + # Create our backup directory for overwritten cert files. + _cmdstr="mkdir -p $_backupdir; $_cmdstr" + _info "Backup of old certificate files will be placed in remote directory $_backupdir" + _info "Backup directories erased after 180 days." + fi + # KEYFILE is optional. # If provided then private key will be copied to provided filename. if [ -n "$DEPLOY_SSH_KEYFILE" ]; then @@ -178,17 +191,6 @@ ssh_deploy() { if [ -z "$_cmdstr" ]; then _err "No remote commands to excute. Failed to deploy certificates to remote server" return 1 - elif [ "$Le_Deploy_ssh_backup" = "yes" ]; then - # run cleanup on the backup directory, erase all older - # than 180 days (15552000 seconds). - _cmdstr="{ now=\"\$(date -u +%s)\"; for fn in $_backupprefix*; \ -do if [ -d \"\$fn\" ] && [ \"\$(expr \$now - \$(date -ur \$fn +%s) )\" -ge \"15552000\" ]; \ -then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; done; }; $_cmdstr" - # Alternate version of above... _cmdstr="find $_backupprefix* -type d -mtime +180 2>/dev/null | xargs rm -rf; $_cmdstr" - # Create our backup directory for overwritten cert files. - _cmdstr="mkdir -p $_backupdir; $_cmdstr" - _info "Backup of old certificate files will be placed in remote directory $_backupdir" - _info "Backup directories erased after 180 days." fi if ! _ssh_remote_cmd "$_cmdstr"; then From cc820e97c6e7cea1d5de0165bd5b7b5d84249843 Mon Sep 17 00:00:00 2001 From: dkerr64 Date: Sat, 22 Feb 2020 21:10:42 -0500 Subject: [PATCH 008/161] Add support for DEPLOY_SSH_BATCH_MODE with default of yes. Before this update all remote commands were bunched together and sent to the remote host in a single SSH command. This could result in a very long sequence of commands that might be rejected by a remote host (example is VMware ESXi that uses busybox sh). With this update you can set DEPLOY_SSH_BATCH_MODE="no" and each remote command is sent as a separate SSH call so now we do not have big long sequence of commands. Defaults to same behaviour as before this update. --- deploy/ssh.sh | 63 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index 39a0a218..92aa43d9 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -21,6 +21,7 @@ # export DEPLOY_SSH_FULLCHAIN="" # export DEPLOY_SSH_REMOTE_CMD="/etc/init.d/stunnel.sh restart" # export DEPLOY_SSH_BACKUP="" # yes or no, default to yes +# export DEPLOY_SSH_BATCH_MODE="yes" # yes or no, default to yes # ######## Public functions ##################### @@ -83,7 +84,20 @@ ssh_deploy() { fi _savedomainconf Le_Deploy_ssh_backup "$Le_Deploy_ssh_backup" + # BATCH_MODE is optional. If not provided then default to yes + if [ "$DEPLOY_SSH_BATCH_MODE" = "no" ]; then + Le_Deploy_ssh_batch_mode="no" + elif [ -z "$Le_Deploy_ssh_batch_mode" ]; then + Le_Deploy_ssh_batch_mode="yes" + fi + _savedomainconf Le_Deploy_ssh_batch_mode "$Le_Deploy_ssh_batch_mode" + _info "Deploy certificates to remote server $Le_Deploy_ssh_user@$Le_Deploy_ssh_server" + if [ "$Le_Deploy_ssh_batch_mode" = "yes" ]; then + _info "Using BATCH MODE... Multiple commands sent in single call to remote host" + else + _info "Commands sent individually in multiple calls to remote host" + fi if [ "$Le_Deploy_ssh_backup" = "yes" ]; then # run cleanup on the backup directory, erase all older @@ -96,6 +110,12 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d _cmdstr="mkdir -p $_backupdir; $_cmdstr" _info "Backup of old certificate files will be placed in remote directory $_backupdir" _info "Backup directories erased after 180 days." + if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if ! _ssh_remote_cmd "$_cmdstr"; then + return $_err_code + fi + _cmdstr="" + fi fi # KEYFILE is optional. @@ -112,6 +132,12 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d # copy new certificate into file. _cmdstr="$_cmdstr echo \"$(cat "$_ckey")\" > $Le_Deploy_ssh_keyfile;" _info "will copy private key to remote file $Le_Deploy_ssh_keyfile" + if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if ! _ssh_remote_cmd "$_cmdstr"; then + return $_err_code + fi + _cmdstr="" + fi fi # CERTFILE is optional. @@ -132,6 +158,12 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d # copy new certificate into file. _cmdstr="$_cmdstr echo \"$(cat "$_ccert")\" $_pipe $Le_Deploy_ssh_certfile;" _info "will copy certificate to remote file $Le_Deploy_ssh_certfile" + if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if ! _ssh_remote_cmd "$_cmdstr"; then + return $_err_code + fi + _cmdstr="" + fi fi # CAFILE is optional. @@ -153,6 +185,12 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d # copy new certificate into file. _cmdstr="$_cmdstr echo \"$(cat "$_cca")\" $_pipe $Le_Deploy_ssh_cafile;" _info "will copy CA file to remote file $Le_Deploy_ssh_cafile" + if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if ! _ssh_remote_cmd "$_cmdstr"; then + return $_err_code + fi + _cmdstr="" + fi fi # FULLCHAIN is optional. @@ -175,6 +213,12 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d # copy new certificate into file. _cmdstr="$_cmdstr echo \"$(cat "$_cfullchain")\" $_pipe $Le_Deploy_ssh_fullchain;" _info "will copy fullchain to remote file $Le_Deploy_ssh_fullchain" + if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if ! _ssh_remote_cmd "$_cmdstr"; then + return $_err_code + fi + _cmdstr="" + fi fi # REMOTE_CMD is optional. @@ -186,17 +230,20 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d if [ -n "$Le_Deploy_ssh_remote_cmd" ]; then _cmdstr="$_cmdstr $Le_Deploy_ssh_remote_cmd;" _info "Will execute remote command $Le_Deploy_ssh_remote_cmd" + if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if ! _ssh_remote_cmd "$_cmdstr"; then + return $_err_code + fi + _cmdstr="" + fi fi - if [ -z "$_cmdstr" ]; then - _err "No remote commands to excute. Failed to deploy certificates to remote server" - return 1 - fi - - if ! _ssh_remote_cmd "$_cmdstr"; then - return $_err_code + # if running as batch mode then all commands sent in a single SSH call now... + if [ -n "$_cmdstr" ]; then + if ! _ssh_remote_cmd "$_cmdstr"; then + return $_err_code + fi fi - return 0 } From 806b746fc0522bed79a1b51f3c0137a0fa721dc5 Mon Sep 17 00:00:00 2001 From: dkerr64 Date: Sat, 22 Feb 2020 21:23:59 -0500 Subject: [PATCH 009/161] Fix bug where backup and batch_mode yes/no values could not be changed. Once set to "no" then they could never be set back to "yes" --- deploy/ssh.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index 92aa43d9..113ae23e 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -79,7 +79,7 @@ ssh_deploy() { # BACKUP is optional. If not provided then default to yes if [ "$DEPLOY_SSH_BACKUP" = "no" ]; then Le_Deploy_ssh_backup="no" - elif [ -z "$Le_Deploy_ssh_backup" ]; then + elif [ -z "$Le_Deploy_ssh_backup" ] || [ "$DEPLOY_SSH_BACKUP" = "yes" ]; then Le_Deploy_ssh_backup="yes" fi _savedomainconf Le_Deploy_ssh_backup "$Le_Deploy_ssh_backup" @@ -87,7 +87,7 @@ ssh_deploy() { # BATCH_MODE is optional. If not provided then default to yes if [ "$DEPLOY_SSH_BATCH_MODE" = "no" ]; then Le_Deploy_ssh_batch_mode="no" - elif [ -z "$Le_Deploy_ssh_batch_mode" ]; then + elif [ -z "$Le_Deploy_ssh_batch_mode" ] || [ "$DEPLOY_SSH_BATCH_MODE" = "yes" ]; then Le_Deploy_ssh_batch_mode="yes" fi _savedomainconf Le_Deploy_ssh_batch_mode "$Le_Deploy_ssh_batch_mode" From 46ee74ed1687bcc5dbb7732bf7483e6c793ec253 Mon Sep 17 00:00:00 2001 From: dkerr64 Date: Sat, 22 Feb 2020 22:05:06 -0500 Subject: [PATCH 010/161] Remove variable from info/error printout that could potentially expose login credentials. --- deploy/ssh.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index 113ae23e..b68dad7e 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -251,14 +251,14 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d _ssh_remote_cmd() { _cmd="$1" _secure_debug "Remote commands to execute: $_cmd" - _info "Submitting sequence of commands to remote server by $Le_Deploy_ssh_cmd" + _info "Submitting sequence of commands to remote server by ssh" # quotations in bash cmd below intended. Squash travis spellcheck error # shellcheck disable=SC2029 $Le_Deploy_ssh_cmd "$Le_Deploy_ssh_user@$Le_Deploy_ssh_server" sh -c "'$_cmd'" _err_code="$?" if [ "$_err_code" != "0" ]; then - _err "Error code $_err_code returned from $Le_Deploy_ssh_cmd" + _err "Error code $_err_code returned from ssh" fi return $_err_code From f73a49440790018aacff9e1d540c937f481cfc20 Mon Sep 17 00:00:00 2001 From: dkerr64 Date: Sat, 22 Feb 2020 22:09:28 -0500 Subject: [PATCH 011/161] Remove spaces on blank line to fix travis error --- deploy/ssh.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index b68dad7e..b3e040b3 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -91,7 +91,7 @@ ssh_deploy() { Le_Deploy_ssh_batch_mode="yes" fi _savedomainconf Le_Deploy_ssh_batch_mode "$Le_Deploy_ssh_batch_mode" - + _info "Deploy certificates to remote server $Le_Deploy_ssh_user@$Le_Deploy_ssh_server" if [ "$Le_Deploy_ssh_batch_mode" = "yes" ]; then _info "Using BATCH MODE... Multiple commands sent in single call to remote host" From 8ba573d1967e13dcdc03631308f5dbdd3acf565c Mon Sep 17 00:00:00 2001 From: dkerr64 Date: Tue, 3 Mar 2020 13:40:33 -0500 Subject: [PATCH 012/161] Change variable name to MULTI_CALL so default can be "no" --- deploy/ssh.sh | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index b3e040b3..7eed8a34 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -21,7 +21,7 @@ # export DEPLOY_SSH_FULLCHAIN="" # export DEPLOY_SSH_REMOTE_CMD="/etc/init.d/stunnel.sh restart" # export DEPLOY_SSH_BACKUP="" # yes or no, default to yes -# export DEPLOY_SSH_BATCH_MODE="yes" # yes or no, default to yes +# export DEPLOY_SSH_MULTI_CALL="" # yes or no, default to no # ######## Public functions ##################### @@ -84,19 +84,19 @@ ssh_deploy() { fi _savedomainconf Le_Deploy_ssh_backup "$Le_Deploy_ssh_backup" - # BATCH_MODE is optional. If not provided then default to yes - if [ "$DEPLOY_SSH_BATCH_MODE" = "no" ]; then - Le_Deploy_ssh_batch_mode="no" - elif [ -z "$Le_Deploy_ssh_batch_mode" ] || [ "$DEPLOY_SSH_BATCH_MODE" = "yes" ]; then - Le_Deploy_ssh_batch_mode="yes" + # MULTI_CALL is optional. If not provided then default to no + if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then + Le_Deploy_ssh_multi_call="yes" + elif [ -z "$Le_Deploy_ssh_multi_call" ] || [ "$DEPLOY_SSH_MULTI_CALL" = "no" ]; then + Le_Deploy_ssh_multi_call="no" fi - _savedomainconf Le_Deploy_ssh_batch_mode "$Le_Deploy_ssh_batch_mode" + _savedomainconf Le_Deploy_ssh_multi_call "$Le_Deploy_ssh_multi_call" _info "Deploy certificates to remote server $Le_Deploy_ssh_user@$Le_Deploy_ssh_server" - if [ "$Le_Deploy_ssh_batch_mode" = "yes" ]; then - _info "Using BATCH MODE... Multiple commands sent in single call to remote host" + if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then + _info "Using MULTI_CALL mode... Required commands sent in multiple calls to remote host" else - _info "Commands sent individually in multiple calls to remote host" + _info "Required commands batched and sent in single call to remote host" fi if [ "$Le_Deploy_ssh_backup" = "yes" ]; then @@ -110,7 +110,7 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d _cmdstr="mkdir -p $_backupdir; $_cmdstr" _info "Backup of old certificate files will be placed in remote directory $_backupdir" _info "Backup directories erased after 180 days." - if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then if ! _ssh_remote_cmd "$_cmdstr"; then return $_err_code fi @@ -132,7 +132,7 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d # copy new certificate into file. _cmdstr="$_cmdstr echo \"$(cat "$_ckey")\" > $Le_Deploy_ssh_keyfile;" _info "will copy private key to remote file $Le_Deploy_ssh_keyfile" - if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then if ! _ssh_remote_cmd "$_cmdstr"; then return $_err_code fi @@ -158,7 +158,7 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d # copy new certificate into file. _cmdstr="$_cmdstr echo \"$(cat "$_ccert")\" $_pipe $Le_Deploy_ssh_certfile;" _info "will copy certificate to remote file $Le_Deploy_ssh_certfile" - if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then if ! _ssh_remote_cmd "$_cmdstr"; then return $_err_code fi @@ -185,7 +185,7 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d # copy new certificate into file. _cmdstr="$_cmdstr echo \"$(cat "$_cca")\" $_pipe $Le_Deploy_ssh_cafile;" _info "will copy CA file to remote file $Le_Deploy_ssh_cafile" - if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then if ! _ssh_remote_cmd "$_cmdstr"; then return $_err_code fi @@ -213,7 +213,7 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d # copy new certificate into file. _cmdstr="$_cmdstr echo \"$(cat "$_cfullchain")\" $_pipe $Le_Deploy_ssh_fullchain;" _info "will copy fullchain to remote file $Le_Deploy_ssh_fullchain" - if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then if ! _ssh_remote_cmd "$_cmdstr"; then return $_err_code fi @@ -230,7 +230,7 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d if [ -n "$Le_Deploy_ssh_remote_cmd" ]; then _cmdstr="$_cmdstr $Le_Deploy_ssh_remote_cmd;" _info "Will execute remote command $Le_Deploy_ssh_remote_cmd" - if [ "$Le_Deploy_ssh_batch_mode" = "no" ]; then + if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then if ! _ssh_remote_cmd "$_cmdstr"; then return $_err_code fi @@ -238,7 +238,7 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d fi fi - # if running as batch mode then all commands sent in a single SSH call now... + # if commands not all sent in multiple calls then all commands sent in a single SSH call now... if [ -n "$_cmdstr" ]; then if ! _ssh_remote_cmd "$_cmdstr"; then return $_err_code From 15b841da06e0f2babf639103e7d0d5615a8d9f7b Mon Sep 17 00:00:00 2001 From: Honza Hommer Date: Sun, 8 Mar 2020 04:47:55 +0100 Subject: [PATCH 013/161] Feat: simplify conditions for bin and command --- notify/mail.sh | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/notify/mail.sh b/notify/mail.sh index ec9aa0de..f992cd4b 100644 --- a/notify/mail.sh +++ b/notify/mail.sh @@ -76,17 +76,16 @@ mail_send() { } _mail_bin() { - if [ -n "$MAIL_BIN" ]; then - _MAIL_BIN="$MAIL_BIN" - elif _exists "sendmail"; then - _MAIL_BIN="sendmail" - elif _exists "ssmtp"; then - _MAIL_BIN="ssmtp" - elif _exists "mutt"; then - _MAIL_BIN="mutt" - elif _exists "mail"; then - _MAIL_BIN="mail" - else + _MAIL_BIN="" + + for b in "$MAIL_BIN" sendmail ssmtp mutt mail; do + if _exists "$b"; then + _MAIL_BIN="$b" + break + fi + done + + if [ -z "$_MAIL_BIN" ]; then _err "Please install sendmail, ssmtp, mutt or mail first." return 1 fi @@ -95,25 +94,22 @@ _mail_bin() { } _mail_cmnd() { + _MAIL_ARGS="" + case $(basename "$_MAIL_BIN") in sendmail) if [ -n "$MAIL_FROM" ]; then - echo "'$_MAIL_BIN' -f '$MAIL_FROM' '$MAIL_TO'" - else - echo "'$_MAIL_BIN' '$MAIL_TO'" + _MAIL_ARGS="-f '$MAIL_FROM'" fi ;; - ssmtp) - echo "'$_MAIL_BIN' '$MAIL_TO'" - ;; mutt | mail) - echo "'$_MAIL_BIN' -s '$_subject' '$MAIL_TO'" + _MAIL_ARGS="-s '$_subject'" ;; *) - _err "Command $MAIL_BIN is not supported, use sendmail, ssmtp, mutt or mail." - return 1 ;; esac + + echo "'$_MAIL_BIN' $_MAIL_ARGS '$MAIL_TO'" } _mail_body() { From 554e083f3d387baacbc151b98463efc697091706 Mon Sep 17 00:00:00 2001 From: dkerr64 Date: Wed, 11 Mar 2020 10:58:36 -0400 Subject: [PATCH 014/161] For MULTI_CALL default to undefined, deleting entry in config file if set to "no" --- deploy/ssh.sh | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index 7eed8a34..5d1ee805 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -20,8 +20,8 @@ # export DEPLOY_SSH_CAFILE="/etc/stunnel/uca.pem" # export DEPLOY_SSH_FULLCHAIN="" # export DEPLOY_SSH_REMOTE_CMD="/etc/init.d/stunnel.sh restart" -# export DEPLOY_SSH_BACKUP="" # yes or no, default to yes -# export DEPLOY_SSH_MULTI_CALL="" # yes or no, default to no +# export DEPLOY_SSH_BACKUP="" # yes or no, default to yes or previously saved value +# export DEPLOY_SSH_MULTI_CALL="" # yes or no, default to no or previously saved value # ######## Public functions ##################### @@ -76,7 +76,7 @@ ssh_deploy() { Le_Deploy_ssh_cmd="ssh -T" fi - # BACKUP is optional. If not provided then default to yes + # BACKUP is optional. If not provided then default to previously saved value or yes. if [ "$DEPLOY_SSH_BACKUP" = "no" ]; then Le_Deploy_ssh_backup="no" elif [ -z "$Le_Deploy_ssh_backup" ] || [ "$DEPLOY_SSH_BACKUP" = "yes" ]; then @@ -84,13 +84,15 @@ ssh_deploy() { fi _savedomainconf Le_Deploy_ssh_backup "$Le_Deploy_ssh_backup" - # MULTI_CALL is optional. If not provided then default to no + # MULTI_CALL is optional. If not provided then default to previously saved + # value (which may be undefined... equivalent to "no"). if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then Le_Deploy_ssh_multi_call="yes" - elif [ -z "$Le_Deploy_ssh_multi_call" ] || [ "$DEPLOY_SSH_MULTI_CALL" = "no" ]; then - Le_Deploy_ssh_multi_call="no" + _savedomainconf Le_Deploy_ssh_multi_call "$Le_Deploy_ssh_multi_call" + elif [ "$DEPLOY_SSH_MULTI_CALL" = "no" ]; then + Le_Deploy_ssh_multi_call="" + _cleardomainconf Le_Deploy_ssh_multi_call fi - _savedomainconf Le_Deploy_ssh_multi_call "$Le_Deploy_ssh_multi_call" _info "Deploy certificates to remote server $Le_Deploy_ssh_user@$Le_Deploy_ssh_server" if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then From 2a8746f6b0702238b28a69a79e8fe4d05ffcaddc Mon Sep 17 00:00:00 2001 From: Honza Hommer Date: Sun, 8 Mar 2020 04:51:39 +0100 Subject: [PATCH 015/161] Feat: add msmtp command --- notify/mail.sh | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/notify/mail.sh b/notify/mail.sh index f992cd4b..54b2a6d4 100644 --- a/notify/mail.sh +++ b/notify/mail.sh @@ -6,6 +6,7 @@ #MAIL_FROM="yyyy@gmail.com" #MAIL_TO="yyyy@gmail.com" #MAIL_NOVALIDATE="" +#MAIL_MSMTP_ACCOUNT="" mail_send() { _subject="$1" @@ -78,7 +79,7 @@ mail_send() { _mail_bin() { _MAIL_BIN="" - for b in "$MAIL_BIN" sendmail ssmtp mutt mail; do + for b in "$MAIL_BIN" sendmail ssmtp mutt mail msmtp; do if _exists "$b"; then _MAIL_BIN="$b" break @@ -86,7 +87,7 @@ _mail_bin() { done if [ -z "$_MAIL_BIN" ]; then - _err "Please install sendmail, ssmtp, mutt or mail first." + _err "Please install sendmail, ssmtp, mutt, mail or msmtp first." return 1 fi @@ -105,8 +106,16 @@ _mail_cmnd() { mutt | mail) _MAIL_ARGS="-s '$_subject'" ;; - *) + msmtp) + if [ -n "$MAIL_FROM" ]; then + _MAIL_ARGS="-f '$MAIL_FROM'" + fi + + if [ -n "$MAIL_MSMTP_ACCOUNT" ]; then + _MAIL_ARGS="$_MAIL_ARGS -a '$MAIL_MSMTP_ACCOUNT'" + fi ;; + *) ;; esac echo "'$_MAIL_BIN' $_MAIL_ARGS '$MAIL_TO'" @@ -114,7 +123,7 @@ _mail_cmnd() { _mail_body() { case $(basename "$_MAIL_BIN") in - sendmail | ssmtp) + sendmail | ssmtp | msmtp) if [ -n "$MAIL_FROM" ]; then echo "From: $MAIL_FROM" fi From f38df4df1151822d50628be22f27ab3eb20429f4 Mon Sep 17 00:00:00 2001 From: dkerr64 Date: Sat, 14 Mar 2020 21:51:21 -0400 Subject: [PATCH 016/161] Make remote backup directory path user configurable. --- deploy/ssh.sh | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index 5d1ee805..d71637a1 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -21,6 +21,7 @@ # export DEPLOY_SSH_FULLCHAIN="" # export DEPLOY_SSH_REMOTE_CMD="/etc/init.d/stunnel.sh restart" # export DEPLOY_SSH_BACKUP="" # yes or no, default to yes or previously saved value +# export DEPLOY_SSH_BACKUP_PATH=".acme_ssh_deploy" # path on remote system. Defaults to .acme_ssh_deploy # export DEPLOY_SSH_MULTI_CALL="" # yes or no, default to no or previously saved value # ######## Public functions ##################### @@ -34,9 +35,8 @@ ssh_deploy() { _cfullchain="$5" _err_code=0 _cmdstr="" - _homedir='~' - _backupprefix="$_homedir/.acme_ssh_deploy/$_cdomain-backup" - _backupdir="$_backupprefix-$(_utc_date | tr ' ' '-')" + _backupprefix="" + _backupdir="" if [ -f "$DOMAIN_CONF" ]; then # shellcheck disable=SC1090 @@ -84,6 +84,14 @@ ssh_deploy() { fi _savedomainconf Le_Deploy_ssh_backup "$Le_Deploy_ssh_backup" + # BACKUP_PATH is optional. If not provided then default to previously saved value or .acme_ssh_deploy + if [ -n "$DEPLOY_SSH_BACKUP_PATH" ]; then + Le_Deploy_ssh_backup_path="$DEPLOY_SSH_BACKUP_PATH" + elif [ -z "$Le_Deploy_ssh_backup_path" ]; then + Le_Deploy_ssh_backup_path=".acme_ssh_deploy" + fi + _savedomainconf Le_Deploy_ssh_backup_path "$Le_Deploy_ssh_backup_path" + # MULTI_CALL is optional. If not provided then default to previously saved # value (which may be undefined... equivalent to "no"). if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then @@ -102,6 +110,8 @@ ssh_deploy() { fi if [ "$Le_Deploy_ssh_backup" = "yes" ]; then + _backupprefix="$Le_Deploy_ssh_backup_path/$_cdomain-backup" + _backupdir="$_backupprefix-$(_utc_date | tr ' ' '-')" # run cleanup on the backup directory, erase all older # than 180 days (15552000 seconds). _cmdstr="{ now=\"\$(date -u +%s)\"; for fn in $_backupprefix*; \ From 4fa59ea04ec8e31777ce4fcd7c4456094518dee4 Mon Sep 17 00:00:00 2001 From: Ehsan Aliakbar Date: Tue, 24 Mar 2020 17:56:50 +0430 Subject: [PATCH 017/161] Adding Arvan Dns Api --- dnsapi/dns_arvan.sh | 163 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 dnsapi/dns_arvan.sh diff --git a/dnsapi/dns_arvan.sh b/dnsapi/dns_arvan.sh new file mode 100644 index 00000000..af9de462 --- /dev/null +++ b/dnsapi/dns_arvan.sh @@ -0,0 +1,163 @@ +#!/usr/bin/env sh + +#Arvan_Token="xxxx" + +ARVAN_API_URL="https://napi.arvancloud.com/cdn/4.0/domains" + +#Author: Ehsan Aliakbar +#Report Bugs here: https://github.com/Neilpang/acme.sh +# +######## Public functions ##################### + +#Usage: dns_arvan_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_arvan_add() { + fulldomain=$1 + txtvalue=$2 + _info "Using Arvan" + + Arvan_Token="${Arvan_Token:-$(_readaccountconf_mutable Arvan_Token)}" + + if [ -z "$Arvan_Token" ]; then + _err "You didn't specify \"Arvan_Token\" token yet." + _err "You can get yours from here https://npanel.arvancloud.com/profile/api-keys" + return 1 + fi + #save the api token to the account conf file. + _saveaccountconf_mutable Arvan_Token "$Arvan_Token" + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + _debug _domain_id "$_domain_id" + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _info "Adding record" + if _arvan_rest POST "$_domain/dns-records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":{\"text\":\"$txtvalue\"},\"ttl\":120}"; then + if _contains "$response" "$txtvalue"; then + _info "Added, OK" + return 0 + elif _contains "$response" "Record Data is Duplicated"; then + _info "Already exists, OK" + return 0 + else + _err "Add txt record error." + return 1 + fi + fi + _err "Add txt record error." + return 1 +} + +#Usage: fulldomain txtvalue +#Remove the txt record after validation. +dns_arvan_rm() { + fulldomain=$1 + txtvalue=$2 + _info "Using Arvan" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + Arvan_Token="${Arvan_Token:-$(_readaccountconf_mutable Arvan_Token)}" + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _domain_id "$_domain_id" + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting txt records" + shorted_txtvalue=$(printf "%s" "$txtvalue" | cut -d "-" -d "_" -f1) + _arvan_rest GET "${_domain}/dns-records?search=$shorted_txtvalue" + + if ! printf "%s" "$response" | grep \"current_page\":1 >/dev/null; then + _err "Error on Arvan Api" + -err "Please create a github issue with debbug log" + return 1 + fi + + count=$(printf "%s\n" "$response" | _egrep_o "\"total\":[^,]*" | cut -d : -f 2) + _debug count "$count" + if [ "$count" = "0" ]; then + _info "Don't need to remove." + else + record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1) + _debug "record_id" "$record_id" + if [ -z "$record_id" ]; then + _err "Can not get record id to remove." + return 1 + fi + if ! _arvan_rest "DELETE" "${_domain}/dns-records/$record_id"; then + _err "Delete record error." + return 1 + fi + _debug "$response" + _contains "$response" 'dns record deleted' + fi +} + +#################### Private functions below ################################## + +#_acme-challenge.www.domain.com +#returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +# _domain_id=sdjkglgdfewsdfg +_get_root() { + domain=$1 + i=1 + p=1 + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug h "$h" + if [ -z "$h" ]; then + #not valid + return 1 + fi + + if ! _arvan_rest GET "?search=$h"; then + return 1 + fi + + if _contains "$response" "\"domain\":\"$h\"" || _contains "$response" '"total":1'; then + _domain_id=$(echo "$response" | _egrep_o "\[.\"id\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \") + if [ "$_domain_id" ]; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain=$h + return 0 + fi + return 1 + fi + p=$i + i=$(_math "$i" + 1) + done + return 1 +} + +_arvan_rest() { + mtd="$1" + ep="$2" + data="$3" + + token_trimmed=$(echo "$Arvan_Token" | tr -d '"') + + export _H1="Authorization: $token_trimmed" + + if [ "$mtd" == "DELETE" ]; then + # DELETE Request shouldn't have Content-Type + _debug data "$data" + response="$(_post "$data" "$ARVAN_API_URL/$ep" "" "$mtd")" + elif [ "$mtd" == "POST" ]; then + export _H2="Content-Type: application/json" + _debug data "$data" + response="$(_post "$data" "$ARVAN_API_URL/$ep" "" "$mtd")" + else + response="$(_get "$ARVAN_API_URL/$ep$data")" + fi +} \ No newline at end of file From 200cd5972aac175a11536218cb2b21c0026a6172 Mon Sep 17 00:00:00 2001 From: Ehsan Aliakbar Date: Sat, 28 Mar 2020 21:50:58 +0430 Subject: [PATCH 018/161] fix shellcheck errors in Arvan Dns Api --- dnsapi/dns_arvan.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_arvan.sh b/dnsapi/dns_arvan.sh index af9de462..341c8c17 100644 --- a/dnsapi/dns_arvan.sh +++ b/dnsapi/dns_arvan.sh @@ -78,7 +78,7 @@ dns_arvan_rm() { if ! printf "%s" "$response" | grep \"current_page\":1 >/dev/null; then _err "Error on Arvan Api" - -err "Please create a github issue with debbug log" + _err "Please create a github issue with debbug log" return 1 fi @@ -149,11 +149,11 @@ _arvan_rest() { export _H1="Authorization: $token_trimmed" - if [ "$mtd" == "DELETE" ]; then + if [ "$mtd" = "DELETE" ]; then # DELETE Request shouldn't have Content-Type _debug data "$data" response="$(_post "$data" "$ARVAN_API_URL/$ep" "" "$mtd")" - elif [ "$mtd" == "POST" ]; then + elif [ "$mtd" = "POST" ]; then export _H2="Content-Type: application/json" _debug data "$data" response="$(_post "$data" "$ARVAN_API_URL/$ep" "" "$mtd")" From 5fac282ee098394ee3cd6eff1975e699bc5ce9b2 Mon Sep 17 00:00:00 2001 From: der-berni Date: Tue, 7 Apr 2020 19:25:39 +0200 Subject: [PATCH 019/161] Update to work with new one.com procedure Since some Months, its no longer possible to add TXT Records with the Name "_acme-challenge" to the base domain. To override the fallback value, you must use a CNAME and proxy it. For example. CNAME _acme-challenge.yourdomain.com => proxy_acme-challenge.yourdomain.com The TXT Records have to be created on proxy_acme-challenge.yourdomain.com Since the default CNAME TTL is 3600 seconds, it is recommended to leave the CNAME record. But if you would like to use the build-in SSL (for your web-site etc.) from one.com, you have to delete the record. A new variable "ONECOM_KeepCnameProxy" you can set in the account.conf is used to keep the CNAME record. By default the CNAME record will be removed. For ex.: SAVED_ONECOM_KeepCnameProxy='1' to keep the CNAME Record and speedup the process. --- dnsapi/dns_one.sh | 189 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 143 insertions(+), 46 deletions(-) diff --git a/dnsapi/dns_one.sh b/dnsapi/dns_one.sh index 0fdc3d5e..4cc159da 100644 --- a/dnsapi/dns_one.sh +++ b/dnsapi/dns_one.sh @@ -5,7 +5,7 @@ # Author: github: @diseq # Created: 2019-02-17 # Fixed by: @der-berni -# Modified: 2019-05-31 +# Modified: 2020-04-07 # # export ONECOM_User="username" # export ONECOM_Password="password" @@ -29,33 +29,46 @@ dns_one_add() { _err "root domain not found" return 1 fi - - mysubdomain=$_sub_domain - mydomain=$_domain - _debug mysubdomain "$mysubdomain" - _debug mydomain "$mydomain" - - # get entries - response="$(_get "https://www.one.com/admin/api/domains/$mydomain/dns/custom_records")" - _debug response "$response" - - # Update the IP address for domain entry - postdata="{\"type\":\"dns_custom_records\",\"attributes\":{\"priority\":0,\"ttl\":600,\"type\":\"TXT\",\"prefix\":\"$mysubdomain\",\"content\":\"$txtvalue\"}}" - _debug postdata "$postdata" - response="$(_post "$postdata" "https://www.one.com/admin/api/domains/$mydomain/dns/custom_records" "" "POST" "application/json")" - response="$(echo "$response" | _normalizeJson)" - _debug response "$response" - - id=$(echo "$response" | sed -n "s/{\"result\":{\"data\":{\"type\":\"dns_custom_records\",\"id\":\"\([^\"]*\)\",\"attributes\":{\"prefix\":\"$mysubdomain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"priority\":0,\"ttl\":600}}},\"metadata\":null}/\1/p") - + + subdomain="${_sub_domain}" + maindomain=${_domain} + + useProxy=0 + if [ "${_sub_domain}" = "_acme-challenge" ]; then + subdomain="proxy${_sub_domain}" + useProxy=1 + fi + + _debug subdomain "$subdomain" + _debug maindomain "$maindomain" + + if [ $useProxy -eq 1 ]; then + #Check if the CNAME exists + _dns_one_getrecord "CNAME" "$_sub_domain" "$subdomain.$maindomain" + if [ -z "$id" ]; then + _info "$(__red "Add CNAME Proxy record: '$(__green "\"$_sub_domain\" => \"$subdomain.$maindomain\"")'")" + _dns_one_addrecord "CNAME" "$_sub_domain" "$subdomain.$maindomain" + + _info "Not valid yet, let's wait 1 hour to take effect." + _sleep 3600 + fi + fi + + #Check if the TXT exists + _dns_one_getrecord "TXT" "$subdomain" "$txtvalue" + if [ ! -z "$id" ]; then + _info "$(__green "Txt record with the same value found. Skip adding.")" + return 0 + fi + + _dns_one_addrecord "TXT" "$subdomain" "$txtvalue" if [ -z "$id" ]; then - _err "Add txt record error." + _err "Add CNAME record error." return 1 else - _info "Added, OK ($id)" + _info "$(__green "Added, OK ($id)")" return 0 fi - } dns_one_rm() { @@ -73,36 +86,46 @@ dns_one_rm() { return 1 fi - mysubdomain=$_sub_domain - mydomain=$_domain - _debug mysubdomain "$mysubdomain" - _debug mydomain "$mydomain" - - # get entries - response="$(_get "https://www.one.com/admin/api/domains/$mydomain/dns/custom_records")" - response="$(echo "$response" | _normalizeJson)" - _debug response "$response" - - id=$(printf -- "%s" "$response" | sed -n "s/.*{\"type\":\"dns_custom_records\",\"id\":\"\([^\"]*\)\",\"attributes\":{\"prefix\":\"$mysubdomain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"priority\":0,\"ttl\":600}.*/\1/p") - + subdomain="${_sub_domain}" + maindomain=${_domain} + + useProxy=0 + if [ "${_sub_domain}" = "_acme-challenge" ]; then + subdomain="proxy${_sub_domain}" + useProxy=1 + fi + + _debug subdomain "$subdomain" + _debug maindomain "$maindomain" + if [ $useProxy -eq 1 ]; then + if [ "$ONECOM_KeepCnameProxy" = "1" ]; then + _info "$(__red "Keeping CNAME Proxy record: '$(__green "\"$_sub_domain\" => \"$subdomain.$maindomain\"")'")" + else + #Check if the CNAME exists + _dns_one_getrecord "CNAME" "$_sub_domain" "$subdomain.$maindomain" + if [ ! -z "$id" ]; then + _info "$(__red "Removing CNAME Proxy record: '$(__green "\"$_sub_domain\" => \"$subdomain.$maindomain\"")'")" + _dns_one_delrecord "$id" + fi + fi + fi + + #Check if the TXT exists + _dns_one_getrecord "TXT" "$subdomain" "$txtvalue" if [ -z "$id" ]; then _err "Txt record not found." return 1 fi - + # delete entry - response="$(_post "$postdata" "https://www.one.com/admin/api/domains/$mydomain/dns/custom_records/$id" "" "DELETE" "application/json")" - response="$(echo "$response" | _normalizeJson)" - _debug response "$response" - - if [ "$response" = '{"result":null,"metadata":null}' ]; then - _info "Removed, OK" - return 0 + + if _dns_one_delrecord "$id"; then + _info "$(__green Removed, OK)" + return 0 else - _err "Removing txt record error." - return 1 + _err "Removing txt record error." + return 1 fi - } #_acme-challenge.www.domain.com @@ -138,6 +161,7 @@ _get_root() { _dns_one_login() { # get credentials + ONECOM_KeepCnameProxy="${ONECOM_KeepCnameProxy:-$(_readaccountconf_mutable ONECOM_KeepCnameProxy)}" ONECOM_User="${ONECOM_User:-$(_readaccountconf_mutable ONECOM_User)}" ONECOM_Password="${ONECOM_Password:-$(_readaccountconf_mutable ONECOM_Password)}" if [ -z "$ONECOM_User" ] || [ -z "$ONECOM_Password" ]; then @@ -177,3 +201,76 @@ _dns_one_login() { return 0 } + +_dns_one_getrecord() { + type="$1" + name="$2" + value="$3" + if [ -z "$type" ]; then + type="TXT" + fi + if [ -z "$name" ]; then + _err "Record name is empty." + return 1 + fi + + response="$(_get "https://www.one.com/admin/api/domains/$maindomain/dns/custom_records")" + response="$(echo "$response" | _normalizeJson)" + _debug response "$response" + + if [ -z "${value}" ]; then + id=$(printf -- "%s" "$response" | sed -n "s/.*{\"type\":\"dns_custom_records\",\"id\":\"\([^\"]*\)\",\"attributes\":{\"prefix\":\"${name}\",\"type\":\"${type}\",\"content\":\"[^\"]*\",\"priority\":0,\"ttl\":600}.*/\1/p") + response=$(printf -- "%s" "$response" | sed -n "s/.*{\"type\":\"dns_custom_records\",\"id\":\"[^\"]*\",\"attributes\":{\"prefix\":\"${name}\",\"type\":\"${type}\",\"content\":\"\([^\"]*\)\",\"priority\":0,\"ttl\":600}.*/\1/p") + else + id=$(printf -- "%s" "$response" | sed -n "s/.*{\"type\":\"dns_custom_records\",\"id\":\"\([^\"]*\)\",\"attributes\":{\"prefix\":\"${name}\",\"type\":\"${type}\",\"content\":\"${value}\",\"priority\":0,\"ttl\":600}.*/\1/p") + fi + if [ -z "$id" ]; then + _err "Record not found." + return 1 + fi + return 0 +} + +_dns_one_addrecord() { + type="$1" + name="$2" + value="$3" + if [ -z "$type" ]; then + type="TXT" + fi + if [ -z "$name" ]; then + _err "Record name is empty." + return 1 + fi + + postdata="{\"type\":\"dns_custom_records\",\"attributes\":{\"priority\":0,\"ttl\":600,\"type\":\"${type}\",\"prefix\":\"${name}\",\"content\":\"${value}\"}}" + _debug postdata "$postdata" + response="$(_post "$postdata" "https://www.one.com/admin/api/domains/$maindomain/dns/custom_records" "" "POST" "application/json")" + response="$(echo "$response" | _normalizeJson)" + _debug response "$response" + + id=$(echo "$response" | sed -n "s/{\"result\":{\"data\":{\"type\":\"dns_custom_records\",\"id\":\"\([^\"]*\)\",\"attributes\":{\"prefix\":\"$subdomain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"priority\":0,\"ttl\":600}}},\"metadata\":null}/\1/p") + + if [ -z "$id" ]; then + return 1 + else + return 0 + fi +} + +_dns_one_delrecord() { + id="$1" + if [ -z "$id" ]; then + return 1 + fi + + response="$(_post "" "https://www.one.com/admin/api/domains/$maindomain/dns/custom_records/$id" "" "DELETE" "application/json")" + response="$(echo "$response" | _normalizeJson)" + _debug response "$response" + + if [ "$response" = '{"result":null,"metadata":null}' ]; then + return 0 + else + return 1 + fi +} From da7b1fb014ceb1791bff30f65967c3aa1af491e4 Mon Sep 17 00:00:00 2001 From: der-berni Date: Thu, 9 Apr 2020 12:17:08 +0200 Subject: [PATCH 020/161] cleanup according to styleguide / ShellCheck --- dnsapi/dns_one.sh | 87 ++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 42 deletions(-) diff --git a/dnsapi/dns_one.sh b/dnsapi/dns_one.sh index 4cc159da..96ef5969 100644 --- a/dnsapi/dns_one.sh +++ b/dnsapi/dns_one.sh @@ -6,7 +6,10 @@ # Created: 2019-02-17 # Fixed by: @der-berni # Modified: 2020-04-07 -# +# +# Use ONECOM_KeepCnameProxy to keep the CNAME DNS record +# export ONECOM_KeepCnameProxy="1" +# # export ONECOM_User="username" # export ONECOM_Password="password" # @@ -29,41 +32,41 @@ dns_one_add() { _err "root domain not found" return 1 fi - + subdomain="${_sub_domain}" maindomain=${_domain} - + useProxy=0 if [ "${_sub_domain}" = "_acme-challenge" ]; then subdomain="proxy${_sub_domain}" useProxy=1 fi - + _debug subdomain "$subdomain" _debug maindomain "$maindomain" - + if [ $useProxy -eq 1 ]; then #Check if the CNAME exists _dns_one_getrecord "CNAME" "$_sub_domain" "$subdomain.$maindomain" if [ -z "$id" ]; then _info "$(__red "Add CNAME Proxy record: '$(__green "\"$_sub_domain\" => \"$subdomain.$maindomain\"")'")" _dns_one_addrecord "CNAME" "$_sub_domain" "$subdomain.$maindomain" - + _info "Not valid yet, let's wait 1 hour to take effect." _sleep 3600 fi fi - + #Check if the TXT exists _dns_one_getrecord "TXT" "$subdomain" "$txtvalue" - if [ ! -z "$id" ]; then + if [ -n "$id" ]; then _info "$(__green "Txt record with the same value found. Skip adding.")" return 0 fi - + _dns_one_addrecord "TXT" "$subdomain" "$txtvalue" if [ -z "$id" ]; then - _err "Add CNAME record error." + _err "Add TXT record error." return 1 else _info "$(__green "Added, OK ($id)")" @@ -88,43 +91,42 @@ dns_one_rm() { subdomain="${_sub_domain}" maindomain=${_domain} - + useProxy=0 if [ "${_sub_domain}" = "_acme-challenge" ]; then subdomain="proxy${_sub_domain}" useProxy=1 fi - + _debug subdomain "$subdomain" _debug maindomain "$maindomain" if [ $useProxy -eq 1 ]; then - if [ "$ONECOM_KeepCnameProxy" = "1" ]; then - _info "$(__red "Keeping CNAME Proxy record: '$(__green "\"$_sub_domain\" => \"$subdomain.$maindomain\"")'")" - else - #Check if the CNAME exists - _dns_one_getrecord "CNAME" "$_sub_domain" "$subdomain.$maindomain" - if [ ! -z "$id" ]; then - _info "$(__red "Removing CNAME Proxy record: '$(__green "\"$_sub_domain\" => \"$subdomain.$maindomain\"")'")" - _dns_one_delrecord "$id" - fi + if [ "$ONECOM_KeepCnameProxy" = "1" ]; then + _info "$(__red "Keeping CNAME Proxy record: '$(__green "\"$_sub_domain\" => \"$subdomain.$maindomain\"")'")" + else + #Check if the CNAME exists + _dns_one_getrecord "CNAME" "$_sub_domain" "$subdomain.$maindomain" + if [ -n "$id" ]; then + _info "$(__red "Removing CNAME Proxy record: '$(__green "\"$_sub_domain\" => \"$subdomain.$maindomain\"")'")" + _dns_one_delrecord "$id" fi + fi fi - + #Check if the TXT exists _dns_one_getrecord "TXT" "$subdomain" "$txtvalue" if [ -z "$id" ]; then _err "Txt record not found." return 1 fi - + # delete entry - if _dns_one_delrecord "$id"; then - _info "$(__green Removed, OK)" - return 0 + _info "$(__green Removed, OK)" + return 0 else - _err "Removing txt record error." - return 1 + _err "Removing txt record error." + return 1 fi } @@ -162,6 +164,7 @@ _dns_one_login() { # get credentials ONECOM_KeepCnameProxy="${ONECOM_KeepCnameProxy:-$(_readaccountconf_mutable ONECOM_KeepCnameProxy)}" + ONECOM_KeepCnameProxy="${ONECOM_KeepCnameProxy:-0}" ONECOM_User="${ONECOM_User:-$(_readaccountconf_mutable ONECOM_User)}" ONECOM_Password="${ONECOM_Password:-$(_readaccountconf_mutable ONECOM_Password)}" if [ -z "$ONECOM_User" ] || [ -z "$ONECOM_Password" ]; then @@ -173,6 +176,7 @@ _dns_one_login() { fi #save the api key and email to the account conf file. + _saveaccountconf_mutable ONECOM_KeepCnameProxy "$ONECOM_KeepCnameProxy" _saveaccountconf_mutable ONECOM_User "$ONECOM_User" _saveaccountconf_mutable ONECOM_Password "$ONECOM_Password" @@ -207,17 +211,17 @@ _dns_one_getrecord() { name="$2" value="$3" if [ -z "$type" ]; then - type="TXT" + type="TXT" fi if [ -z "$name" ]; then - _err "Record name is empty." - return 1 + _err "Record name is empty." + return 1 fi - + response="$(_get "https://www.one.com/admin/api/domains/$maindomain/dns/custom_records")" response="$(echo "$response" | _normalizeJson)" _debug response "$response" - + if [ -z "${value}" ]; then id=$(printf -- "%s" "$response" | sed -n "s/.*{\"type\":\"dns_custom_records\",\"id\":\"\([^\"]*\)\",\"attributes\":{\"prefix\":\"${name}\",\"type\":\"${type}\",\"content\":\"[^\"]*\",\"priority\":0,\"ttl\":600}.*/\1/p") response=$(printf -- "%s" "$response" | sed -n "s/.*{\"type\":\"dns_custom_records\",\"id\":\"[^\"]*\",\"attributes\":{\"prefix\":\"${name}\",\"type\":\"${type}\",\"content\":\"\([^\"]*\)\",\"priority\":0,\"ttl\":600}.*/\1/p") @@ -225,7 +229,6 @@ _dns_one_getrecord() { id=$(printf -- "%s" "$response" | sed -n "s/.*{\"type\":\"dns_custom_records\",\"id\":\"\([^\"]*\)\",\"attributes\":{\"prefix\":\"${name}\",\"type\":\"${type}\",\"content\":\"${value}\",\"priority\":0,\"ttl\":600}.*/\1/p") fi if [ -z "$id" ]; then - _err "Record not found." return 1 fi return 0 @@ -236,13 +239,13 @@ _dns_one_addrecord() { name="$2" value="$3" if [ -z "$type" ]; then - type="TXT" + type="TXT" fi if [ -z "$name" ]; then - _err "Record name is empty." - return 1 + _err "Record name is empty." + return 1 fi - + postdata="{\"type\":\"dns_custom_records\",\"attributes\":{\"priority\":0,\"ttl\":600,\"type\":\"${type}\",\"prefix\":\"${name}\",\"content\":\"${value}\"}}" _debug postdata "$postdata" response="$(_post "$postdata" "https://www.one.com/admin/api/domains/$maindomain/dns/custom_records" "" "POST" "application/json")" @@ -261,16 +264,16 @@ _dns_one_addrecord() { _dns_one_delrecord() { id="$1" if [ -z "$id" ]; then - return 1 + return 1 fi - + response="$(_post "" "https://www.one.com/admin/api/domains/$maindomain/dns/custom_records/$id" "" "DELETE" "application/json")" response="$(echo "$response" | _normalizeJson)" _debug response "$response" if [ "$response" = '{"result":null,"metadata":null}' ]; then - return 0 + return 0 else - return 1 + return 1 fi } From 4dfdfa0b7db773cc46d12c1ff107ee50fef2fb4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=96=B5=E5=96=B5=E5=9B=9B?= Date: Sun, 12 Apr 2020 12:28:07 +0800 Subject: [PATCH 021/161] Fix typo on line 27 --- dnsapi/dns_he.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index caa4d2c4..5829e00e 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -24,7 +24,7 @@ dns_he_add() { if [ -z "$HE_Username" ] || [ -z "$HE_Password" ]; then HE_Username= HE_Password= - _err "No auth details provided. Please set user credentials using the \$HE_Username and \$HE_Password envoronment variables." + _err "No auth details provided. Please set user credentials using the \$HE_Username and \$HE_Password environment variables." return 1 fi _saveaccountconf_mutable HE_Username "$HE_Username" From 2c971a25985049c928597da57e636b5487d19abf Mon Sep 17 00:00:00 2001 From: mod242 <40213799+mod242@users.noreply.github.com> Date: Thu, 16 Apr 2020 20:03:34 +0200 Subject: [PATCH 022/161] Filter out blank lines Response from the provider has changed so that there are blank lines at the end, which leads to the result can not be parsed correctly --- dnsapi/dns_ddnss.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_ddnss.sh b/dnsapi/dns_ddnss.sh index 53781d0d..ecc4f174 100644 --- a/dnsapi/dns_ddnss.sh +++ b/dnsapi/dns_ddnss.sh @@ -119,7 +119,7 @@ _ddnss_rest() { # DDNSS uses GET to update domain info if [ "$method" = "GET" ]; then - response="$(_get "$url" | sed 's/<[a-zA-Z\/][^>]*>//g' | _tail_n 1)" + response="$(_get "$url" | sed 's/<[a-zA-Z\/][^>]*>//g' | tr -s "\n" | _tail_n 1)" else _err "Unsupported method" return 1 From 2febdfc3636614a226e00fe27a419baa8ffe9d6c Mon Sep 17 00:00:00 2001 From: Simon Wydooghe Date: Fri, 17 Apr 2020 15:53:15 +0200 Subject: [PATCH 023/161] Fix: allow removal of email address as contact It seems the current code doesn't allow for removing the email address from the contact field. This fixes that. This only removes the email address if an explicit empty email address is specified on the command line or in the account.conf file. If it is left unspecified on the command line it still just uses whatever was configured in the account.conf. --- acme.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/acme.sh b/acme.sh index f672710d..763d8a1c 100755 --- a/acme.sh +++ b/acme.sh @@ -3512,6 +3512,8 @@ updateaccount() { if [ "$ACME_VERSION" = "2" ]; then if [ "$ACCOUNT_EMAIL" ]; then updjson='{"contact": ["mailto:'$ACCOUNT_EMAIL'"]}' + else + updjson='{"contact": []}' fi else # ACMEv1: Updates happen the same way a registration is done. From d842ccb287588de346c40bcc26c531e0b183e4bb Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 18 Apr 2020 18:51:08 +0800 Subject: [PATCH 024/161] fix format error --- dnsapi/dns_arvan.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_arvan.sh b/dnsapi/dns_arvan.sh index 341c8c17..edeb56ca 100644 --- a/dnsapi/dns_arvan.sh +++ b/dnsapi/dns_arvan.sh @@ -8,7 +8,7 @@ ARVAN_API_URL="https://napi.arvancloud.com/cdn/4.0/domains" #Report Bugs here: https://github.com/Neilpang/acme.sh # ######## Public functions ##################### - + #Usage: dns_arvan_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_arvan_add() { fulldomain=$1 @@ -22,7 +22,7 @@ dns_arvan_add() { _err "You can get yours from here https://npanel.arvancloud.com/profile/api-keys" return 1 fi - #save the api token to the account conf file. + #save the api token to the account conf file. _saveaccountconf_mutable Arvan_Token "$Arvan_Token" _debug "First detect the root zone" @@ -150,7 +150,7 @@ _arvan_rest() { export _H1="Authorization: $token_trimmed" if [ "$mtd" = "DELETE" ]; then - # DELETE Request shouldn't have Content-Type + #DELETE Request shouldn't have Content-Type _debug data "$data" response="$(_post "$data" "$ARVAN_API_URL/$ep" "" "$mtd")" elif [ "$mtd" = "POST" ]; then @@ -160,4 +160,4 @@ _arvan_rest() { else response="$(_get "$ARVAN_API_URL/$ep$data")" fi -} \ No newline at end of file +} From ed7a945261c96d8b721a53c10fd9eaf00ce54182 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 18 Apr 2020 18:59:33 +0800 Subject: [PATCH 025/161] add comment message. --- .github/auto-comment.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/auto-comment.yml b/.github/auto-comment.yml index 1e7b389e..1c3b746e 100644 --- a/.github/auto-comment.yml +++ b/.github/auto-comment.yml @@ -10,8 +10,14 @@ issuesOpened: > please also provide the log with `--debug 2`. + 同时请提供调试输出 `--debug 2` + see: https://github.com/acmesh-official/acme.sh/wiki/How-to-debug-acme.sh - + + Without `--debug 2` log, your issue will NEVER get replied. + + 没有调试输出, 你的 issue 不会得到任何解答. + pullRequestOpened: > First, never send a PR to `master` branch, it will never be accepted. Please send to the `dev` branch instead. From 1564742b76d2e3d20d7c55411d008aaa4cbef402 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 18 Apr 2020 19:38:38 +0800 Subject: [PATCH 026/161] add comments --- .github/auto-comment.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/auto-comment.yml b/.github/auto-comment.yml index 1c3b746e..520b3ce3 100644 --- a/.github/auto-comment.yml +++ b/.github/auto-comment.yml @@ -4,7 +4,7 @@ issuesOpened: > 如果有 bug, 请先更新到最新版试试: - ```sh + ``` acme.sh --upgrade ``` @@ -17,10 +17,10 @@ issuesOpened: > Without `--debug 2` log, your issue will NEVER get replied. 没有调试输出, 你的 issue 不会得到任何解答. - + pullRequestOpened: > - First, never send a PR to `master` branch, it will never be accepted. Please send to the `dev` branch instead. + First, NEVER send a PR to `master` branch, it will NEVER be accepted. Please send to the `dev` branch instead. If this is a PR to support new DNS API or new notification API, please read this guide first: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Dev-Guide @@ -29,6 +29,12 @@ pullRequestOpened: > Then add your usage here: https://github.com/acmesh-official/acme.sh/wiki/dnsapi - + + Or some other wiki pages: + + https://github.com/acmesh-official/acme.sh/wiki/deployhooks + + https://github.com/acmesh-official/acme.sh/wiki/notify + From 1041c9f9fc50eb6aa29de5b882dc7244e9f4024d Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 18 Apr 2020 20:03:48 +0800 Subject: [PATCH 027/161] support revoke reason. https://github.com/acmesh-official/acme.sh/issues/2856 --- acme.sh | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index 763d8a1c..18c8e007 100755 --- a/acme.sh +++ b/acme.sh @@ -138,6 +138,8 @@ _NOTIFY_WIKI="https://github.com/acmesh-official/acme.sh/wiki/notify" _SUDO_WIKI="https://github.com/acmesh-official/acme.sh/wiki/sudo" +_REVOKE_WIKI="https://github.com/acmesh-official/acme.sh/wiki/revokecert" + _DNS_MANUAL_ERR="The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead." _DNS_MANUAL_WARN="It seems that you are using dns manual mode. please take care: $_DNS_MANUAL_ERR" @@ -5456,6 +5458,7 @@ uninstallcronjob() { } +#domain isECC revokeReason revoke() { Le_Domain="$1" if [ -z "$Le_Domain" ]; then @@ -5464,7 +5467,10 @@ revoke() { fi _isEcc="$2" - + _reason="$3" + if [ -z "$_reason" ]; then + _reason="0" + fi _initpath "$Le_Domain" "$_isEcc" if [ ! -f "$DOMAIN_CONF" ]; then _err "$Le_Domain is not a issued domain, skip." @@ -5486,7 +5492,7 @@ revoke() { _initAPI if [ "$ACME_VERSION" = "2" ]; then - data="{\"certificate\": \"$cert\"}" + data="{\"certificate\": \"$cert\",\"reason\":$_reason}" else data="{\"resource\": \"revoke-cert\", \"certificate\": \"$cert\"}" fi @@ -6295,6 +6301,7 @@ Parameters: 0: Bulk mode. Send all the domain's notifications in one message(mail). 1: Cert mode. Send a message for every single cert. --notify-hook [hookname] Set the notify hook + --revoke-reason [0-10] The reason for '--revoke' command. See: $_REVOKE_WIKI " } @@ -6470,6 +6477,7 @@ _process() { _notify_hook="" _notify_level="" _notify_mode="" + _revoke_reason="" while [ ${#} -gt 0 ]; do case "${1}" in @@ -6941,6 +6949,14 @@ _process() { fi _notify_mode="$_nmode" shift + ;; + --revoke-reason) + _revoke_reason="$2" + if _startswith "$_revoke_reason" "-"; then + _err "'$_revoke_reason' is not a integer for '$1'" + return 1 + fi + shift ;; *) _err "Unknown parameter : $1" @@ -7029,7 +7045,7 @@ _process() { renewAll "$_stopRenewOnError" ;; revoke) - revoke "$_domain" "$_ecc" + revoke "$_domain" "$_ecc" "$_revoke_reason" ;; remove) remove "$_domain" "$_ecc" From a995333081876b7f9a06e2c824ed1127d784ebaf Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 18 Apr 2020 22:34:32 +0800 Subject: [PATCH 028/161] fix format --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 18c8e007..57f45905 100755 --- a/acme.sh +++ b/acme.sh @@ -6950,7 +6950,7 @@ _process() { _notify_mode="$_nmode" shift ;; - --revoke-reason) + --revoke-reason) _revoke_reason="$2" if _startswith "$_revoke_reason" "-"; then _err "'$_revoke_reason' is not a integer for '$1'" From 08cc7587ab8042caf4ddab9e4d6910a62797c2ea Mon Sep 17 00:00:00 2001 From: Wolfram Webers Date: Sat, 18 Apr 2020 18:11:24 +0200 Subject: [PATCH 029/161] - Adding fix for latest "os-bind" plugin --- dnsapi/dns_opnsense.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_opnsense.sh b/dnsapi/dns_opnsense.sh index b2a3746f..ec7d2277 100755 --- a/dnsapi/dns_opnsense.sh +++ b/dnsapi/dns_opnsense.sh @@ -150,7 +150,7 @@ _get_root() { return 1 fi _debug h "$h" - id=$(echo "$_domain_response" | _egrep_o "\"[^\"]*\":{\"enabled\":\"1\",\"type\":{\"master\":{\"value\":\"master\",\"selected\":1},\"slave\":{\"value\":\"slave\",\"selected\":0}},\"masterip\":\"[^\"]*\",\"domainname\":\"${h}\"" | cut -d ':' -f 1 | cut -d '"' -f 2) + id=$(echo "$_domain_response" | _egrep_o "\"[^\"]*\":{\"enabled\":\"1\",\"type\":{\"master\":{\"value\":\"master\",\"selected\":1},\"slave\":{\"value\":\"slave\",\"selected\":0}},\"masterip\":\"[^\"]*\",\"allownotifyslave\":{\"\":{[^}]*}},\"domainname\":\"${h}\"" | cut -d ':' -f 1 | cut -d '"' -f 2) if [ -n "$id" ]; then _debug id "$id" From 3bad815982841302a9d55d073fff9d69937cf1ab Mon Sep 17 00:00:00 2001 From: Nils Sandmann Date: Sat, 18 Apr 2020 18:52:08 +0200 Subject: [PATCH 030/161] Better error handling on login, return correct return code --- dnsapi/dns_inwx.sh | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_inwx.sh b/dnsapi/dns_inwx.sh index 7c08d72e..4995ca1d 100755 --- a/dnsapi/dns_inwx.sh +++ b/dnsapi/dns_inwx.sh @@ -148,17 +148,21 @@ _inwx_login() { - ' $INWX_User $INWX_Password) + ' "$INWX_User" "$INWX_Password") response="$(_post "$xml_content" "$INWX_Api" "" "POST")" _H1=$(printf "Cookie: %s" "$(grep "domrobot=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'domrobot=[^;]*;' | tr -d ';')") export _H1 + if ! _contains "$response" "code1000"; then + _err "INWX API: Authentication error (username/password correct?)" + return 1 + fi + #https://github.com/inwx/php-client/blob/master/INWX/Domrobot.php#L71 - if _contains "$response" "code1000" \ - && _contains "$response" "tfaGOOGLE-AUTH"; then + if _contains "$response" "tfaGOOGLE-AUTH"; then if [ -z "$INWX_Shared_Secret" ]; then - _err "Mobile TAN detected." + _err "INWX API: Mobile TAN detected." _err "Please define a shared secret." return 1 fi @@ -191,6 +195,11 @@ _inwx_login() { ' "$tan") response="$(_post "$xml_content" "$INWX_Api" "" "POST")" + + if ! _contains "$response" "code1000"; then + _err "INWX API: Mobile TAN not correct." + return 1 + fi fi } From 5d00edc896dfbd09d961ea6f76843cf7c18b6083 Mon Sep 17 00:00:00 2001 From: Nils Sandmann Date: Sat, 18 Apr 2020 18:54:43 +0200 Subject: [PATCH 031/161] Fix multiple domains with 2FA, reuse session cookie --- dnsapi/dns_inwx.sh | 50 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_inwx.sh b/dnsapi/dns_inwx.sh index 4995ca1d..50b4b10c 100755 --- a/dnsapi/dns_inwx.sh +++ b/dnsapi/dns_inwx.sh @@ -34,6 +34,10 @@ dns_inwx_add() { _saveaccountconf_mutable INWX_Password "$INWX_Password" _saveaccountconf_mutable INWX_Shared_Secret "$INWX_Shared_Secret" + if ! _inwx_login; then + return 1 + fi + _debug "First detect the root zone" if ! _get_root "$fulldomain"; then _err "invalid domain" @@ -64,6 +68,10 @@ dns_inwx_rm() { return 1 fi + if ! _inwx_login; then + return 1 + fi + _debug "First detect the root zone" if ! _get_root "$fulldomain"; then _err "invalid domain" @@ -123,8 +131,42 @@ dns_inwx_rm() { #################### Private functions below ################################## +_inwx_check_cookie() { + INWX_Cookie="${INWX_Cookie:-$(_readaccountconf_mutable INWX_Cookie)}" + if [ -z "$INWX_Cookie" ]; then + _debug "No cached cookie found" + return 1 + fi + _H1="$INWX_Cookie" + export _H1 + + xml_content=$(printf ' + + account.info + ') + + response="$(_post "$xml_content" "$INWX_Api" "" "POST")" + + if _contains "$response" "code1000"; then + _debug "Cached cookie still valid" + return 0 + fi + + _debug "Cached cookie no longer valid" + _H1="" + export _H1 + INWX_Cookie="" + _saveaccountconf_mutable INWX_Cookie "$INWX_Cookie" + return 1 +} + _inwx_login() { + if _inwx_check_cookie; then + _debug "Already logged in" + return 0 + fi + xml_content=$(printf ' account.login @@ -151,8 +193,12 @@ _inwx_login() { ' "$INWX_User" "$INWX_Password") response="$(_post "$xml_content" "$INWX_Api" "" "POST")" - _H1=$(printf "Cookie: %s" "$(grep "domrobot=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'domrobot=[^;]*;' | tr -d ';')") + + INWX_Cookie=$(printf "Cookie: %s" "$(grep "domrobot=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'domrobot=[^;]*;' | tr -d ';')") + _H1=$INWX_Cookie export _H1 + export INWX_Cookie + _saveaccountconf_mutable INWX_Cookie "$INWX_Cookie" if ! _contains "$response" "code1000"; then _err "INWX API: Authentication error (username/password correct?)" @@ -212,8 +258,6 @@ _get_root() { i=2 p=1 - _inwx_login - xml_content=' nameserver.list From a9c4b8dd1a294cfd385a8cc5dd3ea47b3e98156b Mon Sep 17 00:00:00 2001 From: Honza Hommer Date: Sun, 19 Apr 2020 00:44:48 +0200 Subject: [PATCH 032/161] feat: Microsoft Teams notify --- notify/teams.sh | 79 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 notify/teams.sh diff --git a/notify/teams.sh b/notify/teams.sh new file mode 100644 index 00000000..752c24c6 --- /dev/null +++ b/notify/teams.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env sh + +#Support Microsoft Teams webhooks + +#TEAMS_WEBHOOK_URL="" +#TEAMS_THEME_COLOR="" +#TEAMS_SUCCESS_COLOR="" +#TEAMS_ERROR_COLOR="" +#TEAMS_SKIP_COLOR="" + +teams_send() { + _subject="$1" + _content="$2" + _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped + _debug "_statusCode" "$_statusCode" + + TEAMS_WEBHOOK_URL="${TEAMS_WEBHOOK_URL:-$(_readaccountconf_mutable TEAMS_WEBHOOK_URL)}" + if [ -z "$TEAMS_WEBHOOK_URL" ]; then + TEAMS_WEBHOOK_URL="" + _err "You didn't specify a Microsoft Teams webhook url TEAMS_WEBHOOK_URL yet." + return 1 + fi + _saveaccountconf_mutable TEAMS_WEBHOOK_URL "$TEAMS_WEBHOOK_URL" + + TEAMS_THEME_COLOR="${TEAMS_THEME_COLOR:-$(_readaccountconf_mutable TEAMS_THEME_COLOR)}" + if [ -n "$TEAMS_THEME_COLOR" ]; then + _saveaccountconf_mutable TEAMS_THEME_COLOR "$TEAMS_THEME_COLOR" + fi + + TEAMS_SUCCESS_COLOR="${TEAMS_SUCCESS_COLOR:-$(_readaccountconf_mutable TEAMS_SUCCESS_COLOR)}" + if [ -n "$TEAMS_SUCCESS_COLOR" ]; then + _saveaccountconf_mutable TEAMS_SUCCESS_COLOR "$TEAMS_SUCCESS_COLOR" + fi + + TEAMS_ERROR_COLOR="${TEAMS_ERROR_COLOR:-$(_readaccountconf_mutable TEAMS_ERROR_COLOR)}" + if [ -n "$TEAMS_ERROR_COLOR" ]; then + _saveaccountconf_mutable TEAMS_ERROR_COLOR "$TEAMS_ERROR_COLOR" + fi + + TEAMS_SKIP_COLOR="${TEAMS_SKIP_COLOR:-$(_readaccountconf_mutable TEAMS_SKIP_COLOR)}" + if [ -n "$TEAMS_SKIP_COLOR" ]; then + _saveaccountconf_mutable TEAMS_SKIP_COLOR "$TEAMS_SKIP_COLOR" + fi + + export _H1="Content-Type: application/json" + + _subject=$(echo "$_subject" | _json_encode) + _content=$(echo "$_content" | _json_encode) + + case "$_statusCode" in + 0) + _color="$TEAMS_SUCCESS_COLOR" + ;; + 1) + _color="$TEAMS_ERROR_COLOR" + ;; + 2) + _color="$TEAMS_SKIP_COLOR" + ;; + esac + _color="$(echo "${_color:-$TEAMS_THEME_COLOR}" | tr -cd '[:xdigit:]')" + + _data="{\"title\": \"$_subject\"," + if [ -n "$_color" ]; then + _data="$_data\"themeColor\": \"$_color\", " + fi + _data="$_data\"text\": \"$_content\"}" + + if _post "$_data" "$TEAMS_WEBHOOK_URL"; then + # shellcheck disable=SC2154 + if ! _contains "$response" error; then + _info "teams send success." + return 0 + fi + fi + _err "teams send error." + _err "$response" + return 1 +} From 74cdcde4496b17c6cc0a55d98592ce954b875b54 Mon Sep 17 00:00:00 2001 From: Honza Hommer Date: Sun, 19 Apr 2020 23:59:35 +0200 Subject: [PATCH 033/161] fix: remove :xdigit: --- notify/teams.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notify/teams.sh b/notify/teams.sh index 752c24c6..d1de1c57 100644 --- a/notify/teams.sh +++ b/notify/teams.sh @@ -58,7 +58,7 @@ teams_send() { _color="$TEAMS_SKIP_COLOR" ;; esac - _color="$(echo "${_color:-$TEAMS_THEME_COLOR}" | tr -cd '[:xdigit:]')" + _color="$(echo "${_color:-$TEAMS_THEME_COLOR}" | tr -cd 'a-fA-F0-9')" _data="{\"title\": \"$_subject\"," if [ -n "$_color" ]; then From 9bad11ec79e23cf617b9b07c91537a3f7962c4d4 Mon Sep 17 00:00:00 2001 From: wurzelpanzer <32928046+wurzelpanzer@users.noreply.github.com> Date: Mon, 20 Apr 2020 08:49:08 +0200 Subject: [PATCH 034/161] easyDNS API out of beta Added new links to API docs and API access signup --- dnsapi/dns_easydns.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_easydns.sh b/dnsapi/dns_easydns.sh index ca8faab2..f466f1e2 100644 --- a/dnsapi/dns_easydns.sh +++ b/dnsapi/dns_easydns.sh @@ -4,8 +4,7 @@ # # easyDNS REST API for acme.sh by Neilpang based on dns_cf.sh # -# Please note: # API is currently beta and subject to constant change -# http://sandbox.rest.easydns.net:3000/ +# API Documentation: https://sandbox.rest.easydns.net:3001/ # # Author: wurzelpanzer [wurzelpanzer@maximolider.net] # Report Bugs here: https://github.com/acmesh-official/acme.sh/issues/2647 @@ -25,7 +24,7 @@ dns_easydns_add() { EASYDNS_Key="${EASYDNS_Key:-$(_readaccountconf_mutable EASYDNS_Key)}" if [ -z "$EASYDNS_Token" ] || [ -z "$EASYDNS_Key" ]; then - _err "You didn't specify an easydns.net token or api key. Please sign up at http://docs.sandbox.rest.easydns.net/beta_signup.php" + _err "You didn't specify an easydns.net token or api key. Signup at https://cp.easydns.com/manage/security/api/signup.php" return 1 else _saveaccountconf_mutable EASYDNS_Token "$EASYDNS_Token" From c06db30a65d970f914a06020d872573d656cd11a Mon Sep 17 00:00:00 2001 From: Viktor G Date: Mon, 20 Apr 2020 21:05:40 +0300 Subject: [PATCH 035/161] DNS Loopia min 300 TTL --- dnsapi/dns_loopia.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_loopia.sh b/dnsapi/dns_loopia.sh index 1316a274..7760b53e 100644 --- a/dnsapi/dns_loopia.sh +++ b/dnsapi/dns_loopia.sh @@ -217,7 +217,7 @@ _loopia_add_record() { ttl - 60 + 300 rdata From c49b40ee95e28a8bac57e71001f7d65715e98063 Mon Sep 17 00:00:00 2001 From: Jesai Langenbach Date: Tue, 21 Apr 2020 11:43:08 +0200 Subject: [PATCH 036/161] Allow old and new API response CLOSES #2480 --- dnsapi/dns_opnsense.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_opnsense.sh b/dnsapi/dns_opnsense.sh index ec7d2277..069f6c32 100755 --- a/dnsapi/dns_opnsense.sh +++ b/dnsapi/dns_opnsense.sh @@ -150,7 +150,7 @@ _get_root() { return 1 fi _debug h "$h" - id=$(echo "$_domain_response" | _egrep_o "\"[^\"]*\":{\"enabled\":\"1\",\"type\":{\"master\":{\"value\":\"master\",\"selected\":1},\"slave\":{\"value\":\"slave\",\"selected\":0}},\"masterip\":\"[^\"]*\",\"allownotifyslave\":{\"\":{[^}]*}},\"domainname\":\"${h}\"" | cut -d ':' -f 1 | cut -d '"' -f 2) + id=$(echo "$_domain_response" | _egrep_o "\"[^\"]*\":{\"enabled\":\"1\",\"type\":{\"master\":{\"value\":\"master\",\"selected\":1},\"slave\":{\"value\":\"slave\",\"selected\":0}},\"masterip\":\"[^\"]*\"(,\"allownotifyslave\":{\"\":{[^}]*}},|,)\"domainname\":\"${h}\"" | cut -d ':' -f 1 | cut -d '"' -f 2) if [ -n "$id" ]; then _debug id "$id" From 24925a17392147c857d20a6b0272ea7da0bf1843 Mon Sep 17 00:00:00 2001 From: Honza Hommer Date: Wed, 22 Apr 2020 21:13:52 +0200 Subject: [PATCH 037/161] feat: add default colors --- notify/teams.sh | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/notify/teams.sh b/notify/teams.sh index d1de1c57..6b360ae5 100644 --- a/notify/teams.sh +++ b/notify/teams.sh @@ -14,6 +14,10 @@ teams_send() { _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped _debug "_statusCode" "$_statusCode" + _color_success="2cbe4e" # green + _color_danger="cb2431" # red + _color_muted="586069" # gray + TEAMS_WEBHOOK_URL="${TEAMS_WEBHOOK_URL:-$(_readaccountconf_mutable TEAMS_WEBHOOK_URL)}" if [ -z "$TEAMS_WEBHOOK_URL" ]; then TEAMS_WEBHOOK_URL="" @@ -49,16 +53,20 @@ teams_send() { case "$_statusCode" in 0) - _color="$TEAMS_SUCCESS_COLOR" + _color="${TEAMS_SUCCESS_COLOR:-$_color_success}" ;; 1) - _color="$TEAMS_ERROR_COLOR" + _color="${TEAMS_ERROR_COLOR:-$_color_danger}" ;; 2) - _color="$TEAMS_SKIP_COLOR" + _color="${TEAMS_SKIP_COLOR:-$_color_muted}" ;; esac - _color="$(echo "${_color:-$TEAMS_THEME_COLOR}" | tr -cd 'a-fA-F0-9')" + + _color=$(echo "$_color" | tr -cd 'a-fA-F0-9') + if [ -z "$_color" ]; then + _color=$(echo "${TEAMS_THEME_COLOR:-$_color_muted}" | tr -cd 'a-fA-F0-9') + fi _data="{\"title\": \"$_subject\"," if [ -n "$_color" ]; then From 6ba1eda96fb9afb7382794468ee47e3baf61806e Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 25 Apr 2020 22:44:00 +0800 Subject: [PATCH 038/161] fix https://github.com/acmesh-official/acme.sh/issues/2883#issuecomment-619215961 --- acme.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 57f45905..97d71a22 100755 --- a/acme.sh +++ b/acme.sh @@ -1174,9 +1174,8 @@ _createcsr() { _info "Multi domain" "$alt" printf -- "\nsubjectAltName=$alt" >>"$csrconf" fi - if [ "$Le_OCSP_Staple" ] || [ "$Le_OCSP_Stable" ]; then + if [ "$Le_OCSP_Staple" = "1" ]; then _savedomainconf Le_OCSP_Staple "$Le_OCSP_Staple" - _cleardomainconf Le_OCSP_Stable printf -- "\nbasicConstraints = CA:FALSE\n1.3.6.1.5.5.7.1.24=DER:30:03:02:01:05" >>"$csrconf" fi From 3ff48b8559678b0e02e25871eae29694f77d26ce Mon Sep 17 00:00:00 2001 From: Bas van Ritbergen Date: Mon, 27 Apr 2020 15:34:20 +0200 Subject: [PATCH 039/161] Update dns_openprovider.sh #2104 Fix wildcard handling & custom NS config for OpenProvider DNS --- dnsapi/dns_openprovider.sh | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/dnsapi/dns_openprovider.sh b/dnsapi/dns_openprovider.sh index ad1e5838..84058f60 100755 --- a/dnsapi/dns_openprovider.sh +++ b/dnsapi/dns_openprovider.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env sh +#!/bin/bash # This is the OpenProvider API wrapper for acme.sh # @@ -59,16 +59,17 @@ dns_openprovider_add() { break fi - items="$(echo "$items" | sed "s|${item}||")" + tmpitem="$(echo "$item" | sed 's/\*/\\*/g')" + items="$(echo "$items" | sed "s|${tmpitem}||")" results_retrieved="$(_math "$results_retrieved" + 1)" new_item="$(echo "$item" | sed -n 's/.*.*\(\(.*\)\.'"$_domain_name"'\.'"$_domain_extension"'<\/name>.*\(.*<\/type>\).*\(.*<\/value>\).*\(.*<\/prio>\).*\(.*<\/ttl>\)\).*<\/item>.*/\2<\/name>\3\4\5\6<\/item>/p')" if [ -z "$new_item" ]; then - # Base record + # Domain apex new_item="$(echo "$item" | sed -n 's/.*.*\(\(.*\)'"$_domain_name"'\.'"$_domain_extension"'<\/name>.*\(.*<\/type>\).*\(.*<\/value>\).*\(.*<\/prio>\).*\(.*<\/ttl>\)\).*<\/item>.*/\2<\/name>\3\4\5\6<\/item>/p')" fi - if [ -z "$(echo "$new_item" | _egrep_o ".*(A|AAAA|CNAME|MX|SPF|SRV|TXT|TLSA|SSHFP|CAA)<\/type>.*")" ]; then + if [ -z "$(echo "$new_item" | _egrep_o ".*(A|AAAA|CNAME|MX|SPF|SRV|TXT|TLSA|SSHFP|CAA|NS)<\/type>.*")" ]; then _debug "not an allowed record type, skipping" "$new_item" continue fi @@ -86,7 +87,7 @@ dns_openprovider_add() { _debug "Creating acme record" acme_record="$(echo "$fulldomain" | sed -e "s/.$_domain_name.$_domain_extension$//")" - _openprovider_request "$(printf '%s%smaster%s%sTXT%s86400' "$_domain_name" "$_domain_extension" "$existing_items" "$acme_record" "$txtvalue")" + _openprovider_request "$(printf '%s%smaster%s%sTXT%s600' "$_domain_name" "$_domain_extension" "$existing_items" "$acme_record" "$txtvalue")" return 0 } @@ -136,7 +137,8 @@ dns_openprovider_rm() { break fi - items="$(echo "$items" | sed "s|${item}||")" + tmpitem="$(echo "$item" | sed 's/\*/\\*/g')" + items="$(echo "$items" | sed "s|${tmpitem}||")" results_retrieved="$(_math "$results_retrieved" + 1)" if ! echo "$item" | grep -v "$fulldomain"; then @@ -147,11 +149,11 @@ dns_openprovider_rm() { new_item="$(echo "$item" | sed -n 's/.*.*\(\(.*\)\.'"$_domain_name"'\.'"$_domain_extension"'<\/name>.*\(.*<\/type>\).*\(.*<\/value>\).*\(.*<\/prio>\).*\(.*<\/ttl>\)\).*<\/item>.*/\2<\/name>\3\4\5\6<\/item>/p')" if [ -z "$new_item" ]; then - # Base record + # domain apex new_item="$(echo "$item" | sed -n 's/.*.*\(\(.*\)'"$_domain_name"'\.'"$_domain_extension"'<\/name>.*\(.*<\/type>\).*\(.*<\/value>\).*\(.*<\/prio>\).*\(.*<\/ttl>\)\).*<\/item>.*/\2<\/name>\3\4\5\6<\/item>/p')" fi - if [ -z "$(echo "$new_item" | _egrep_o ".*(A|AAAA|CNAME|MX|SPF|SRV|TXT|TLSA|SSHFP|CAA)<\/type>.*")" ]; then + if [ -z "$(echo "$new_item" | _egrep_o ".*(A|AAAA|CNAME|MX|SPF|SRV|TXT|TLSA|SSHFP|CAA|NS)<\/type>.*")" ]; then _debug "not an allowed record type, skipping" "$new_item" continue fi @@ -205,7 +207,8 @@ _get_root() { break fi - items="$(echo "$items" | sed "s|${item}||")" + tmpitem="$(echo "$item" | sed 's/\*/\\*/g')" + items="$(echo "$items" | sed "s|${tmpitem}||")" results_retrieved="$(_math "$results_retrieved" + 1)" From 1bfd0f014984c47b9b97da8709628a030a580fd9 Mon Sep 17 00:00:00 2001 From: Bas van Ritbergen Date: Mon, 27 Apr 2020 15:41:50 +0200 Subject: [PATCH 040/161] Update dns_openprovider.sh fixed shebang shell to be as suggested --- dnsapi/dns_openprovider.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_openprovider.sh b/dnsapi/dns_openprovider.sh index 84058f60..0a9e5ade 100755 --- a/dnsapi/dns_openprovider.sh +++ b/dnsapi/dns_openprovider.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env sh # This is the OpenProvider API wrapper for acme.sh # From da957a3caf587ad82fd0d11b8c5078d9b31f291b Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 29 Apr 2020 10:12:29 +0800 Subject: [PATCH 041/161] fix https://github.com/acmesh-official/acme.sh/issues/2888 --- dnsapi/dns_cf.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_cf.sh b/dnsapi/dns_cf.sh index 43bc1428..3e66a585 100755 --- a/dnsapi/dns_cf.sh +++ b/dnsapi/dns_cf.sh @@ -59,7 +59,7 @@ dns_cf_add() { _debug "Getting txt records" _cf_rest GET "zones/${_domain_id}/dns_records?type=TXT&name=$fulldomain" - if ! printf "%s" "$response" | grep \"success\":true >/dev/null; then + if ! echo "$response" | tr -d " " | grep \"success\":true >/dev/null; then _err "Error" return 1 fi From 1209b9b86eb994f76582aada3083a43806170a8b Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 29 Apr 2020 10:15:13 +0800 Subject: [PATCH 042/161] fix https://github.com/acmesh-official/acme.sh/issues/2888 --- dnsapi/dns_cf.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_cf.sh b/dnsapi/dns_cf.sh index 3e66a585..8d2e23ba 100755 --- a/dnsapi/dns_cf.sh +++ b/dnsapi/dns_cf.sh @@ -110,7 +110,7 @@ dns_cf_rm() { _debug "Getting txt records" _cf_rest GET "zones/${_domain_id}/dns_records?type=TXT&name=$fulldomain&content=$txtvalue" - if ! printf "%s" "$response" | grep \"success\":true >/dev/null; then + if ! echo "$response" | tr -d " " | grep \"success\":true >/dev/null; then _err "Error: $response" return 1 fi From b19799bc72599716f2a9067ecef10f42d0d6372c Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 29 Apr 2020 10:19:35 +0800 Subject: [PATCH 043/161] fix https://github.com/acmesh-official/acme.sh/issues/2888 --- dnsapi/dns_cf.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_cf.sh b/dnsapi/dns_cf.sh index 8d2e23ba..652c3769 100755 --- a/dnsapi/dns_cf.sh +++ b/dnsapi/dns_cf.sh @@ -120,7 +120,7 @@ dns_cf_rm() { if [ "$count" = "0" ]; then _info "Don't need to remove." else - record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1) + record_id=$(echo "$response" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | _head_n 1) _debug "record_id" "$record_id" if [ -z "$record_id" ]; then _err "Can not get record id to remove." From ad9f488df60fa5ceb8f4a269f3119f378395ec46 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 29 Apr 2020 10:38:21 +0800 Subject: [PATCH 044/161] fix https://github.com/acmesh-official/acme.sh/issues/2888 --- dnsapi/dns_cf.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_cf.sh b/dnsapi/dns_cf.sh index 652c3769..b4e9f632 100755 --- a/dnsapi/dns_cf.sh +++ b/dnsapi/dns_cf.sh @@ -115,12 +115,12 @@ dns_cf_rm() { return 1 fi - count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2) + count=$(echo "$response" | _egrep_o "\"count\": *[^,]*" | cut -d : -f 2 | tr -d " ") _debug count "$count" if [ "$count" = "0" ]; then _info "Don't need to remove." else - record_id=$(echo "$response" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | _head_n 1) + record_id=$(echo "$response" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | _head_n 1 | tr -d " ") _debug "record_id" "$record_id" if [ -z "$record_id" ]; then _err "Can not get record id to remove." @@ -152,7 +152,7 @@ _get_root() { return 1 else if _contains "$response" '"success":true'; then - _domain=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1) + _domain=$(echo "$response" | _egrep_o "\"name\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | _head_n 1 | tr -d " ") if [ "$_domain" ]; then _cutlength=$((${#domain} - ${#_domain} - 1)) _sub_domain=$(printf "%s" "$domain" | cut -c "1-$_cutlength") @@ -186,7 +186,7 @@ _get_root() { fi if _contains "$response" "\"name\":\"$h\"" || _contains "$response" '"total_count":1'; then - _domain_id=$(echo "$response" | _egrep_o "\[.\"id\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \") + _domain_id=$(echo "$response" | _egrep_o "\[.\"id\": *\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \" | tr -d " ") if [ "$_domain_id" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain=$h From 58c2c701468b70df258c210ad7daff4a442d57af Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 29 Apr 2020 10:42:17 +0800 Subject: [PATCH 045/161] fix https://github.com/acmesh-official/acme.sh/issues/2888 --- dnsapi/dns_cf.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_cf.sh b/dnsapi/dns_cf.sh index b4e9f632..36799dcd 100755 --- a/dnsapi/dns_cf.sh +++ b/dnsapi/dns_cf.sh @@ -130,7 +130,7 @@ dns_cf_rm() { _err "Delete record error." return 1 fi - _contains "$response" '"success":true' + echo "$response" | tr -d " " | grep \"success\":true >/dev/null fi } @@ -151,7 +151,7 @@ _get_root() { if ! _cf_rest GET "zones/$CF_Zone_ID"; then return 1 else - if _contains "$response" '"success":true'; then + if echo "$response" | tr -d " " | grep \"success\":true >/dev/null; then _domain=$(echo "$response" | _egrep_o "\"name\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | _head_n 1 | tr -d " ") if [ "$_domain" ]; then _cutlength=$((${#domain} - ${#_domain} - 1)) From 45e6000619d65f15caefa6ac738789ae68a16274 Mon Sep 17 00:00:00 2001 From: ThiloGa Date: Fri, 1 May 2020 06:25:19 +0200 Subject: [PATCH 046/161] adding support for dyndnsfree.de --- dnsapi/dns_df.sh | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 dnsapi/dns_df.sh diff --git a/dnsapi/dns_df.sh b/dnsapi/dns_df.sh new file mode 100644 index 00000000..c71f0b44 --- /dev/null +++ b/dnsapi/dns_df.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env sh + +######################################################################## +# https://dyndnsfree.de hook script for acme.sh +# +# Environment variables: +# +# - $DF_user (your dyndnsfree.de API username) +# - $DF_password (your dyndnsfree.de API password) +# +# Author: Thilo Gass +# Git repo: https://github.com/ThiloGa/acme.sh + +#-- dns_df_add() - Add TXT record -------------------------------------- +# Usage: dns_df_add _acme-challenge.subdomain.domain.com "XyZ123..." + +dyndnsfree_api="https://dynup.de/acme.php" + +dns_df_add() { + fulldomain=$1 + txt_value=$2 + _info "Using DNS-01 dyndnsfree.de hook" + + DF_user="${DF_user:-$(_readaccountconf_mutable DF_user)}" + DF_password="${DF_password:-$(_readaccountconf_mutable DF_password)}" + if [ -z "$DF_user" ] || [ -z "$DF_password" ]; then + DF_user="" + DF_password="" + _err "No auth details provided. Please set user credentials using the \$DF_user and \$DF_password environment variables." + return 1 + fi + #save the api user and sha256 password to the account conf file. + _debug "Save user and hash" + _saveaccountconf_mutable DF_user "$DF_user" + _saveaccountconf_mutable DF_password "$DF_password" + + domain="$(printf "%s" "$fulldomain" | cut -d"." -f2-)" + + get="$dyndnsfree_api?username=$DF_user&password=$DF_password&hostname=$domain&add_hostname=$fulldomain&txt=$txt_value" + + if ! erg="$(_get "$get")"; then + _err "error Adding $fulldomain TXT: $txt_value" + return 1 + fi + + if _contains "$erg" "success"; then + _info "Success, TXT Added, OK" + else + _err "error Adding $fulldomain TXT: $txt_value erg: $erg" + return 1 + fi + + _debug "ok Auto $fulldomain TXT: $txt_value erg: $erg" + return 0 +} + +dns_df_rm() { + + fulldomain=$1 + txtvalue=$2 + _info "TXT enrty in $fulldomain is deleted automatically" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + +} From c3d7f5b28b1dd5298dc398e012f2c5cc75b5af3f Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 1 May 2020 23:44:56 +0800 Subject: [PATCH 047/161] build on docker hub --- .github/workflows/dockerhub.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .github/workflows/dockerhub.yml diff --git a/.github/workflows/dockerhub.yml b/.github/workflows/dockerhub.yml new file mode 100644 index 00000000..f1c0025d --- /dev/null +++ b/.github/workflows/dockerhub.yml @@ -0,0 +1,16 @@ + +name: Build DockerHub +on: + push: + branches: [ master, dev ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: trigger + run: curl -X POST https://hub.docker.com/api/build/v1/source/1813a660-2ee5-4583-a238-dd54e9a6ebac/trigger/c8cd9f1f-f269-45bc-9750-a08327257f62/call/ + + + + From 22f8ab110e84d9d6dfbf6223afe4fecddbd4d8b9 Mon Sep 17 00:00:00 2001 From: ThiloGa <61890902+ThiloGa@users.noreply.github.com> Date: Sat, 2 May 2020 08:26:26 +0200 Subject: [PATCH 048/161] typo fixing --- dnsapi/dns_df.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_df.sh b/dnsapi/dns_df.sh index c71f0b44..d5410d95 100644 --- a/dnsapi/dns_df.sh +++ b/dnsapi/dns_df.sh @@ -5,8 +5,8 @@ # # Environment variables: # -# - $DF_user (your dyndnsfree.de API username) -# - $DF_password (your dyndnsfree.de API password) +# - $DF_user (your dyndnsfree.de username) +# - $DF_password (your dyndnsfree.de password) # # Author: Thilo Gass # Git repo: https://github.com/ThiloGa/acme.sh @@ -30,7 +30,7 @@ dns_df_add() { return 1 fi #save the api user and sha256 password to the account conf file. - _debug "Save user and hash" + _debug "Save user and password" _saveaccountconf_mutable DF_user "$DF_user" _saveaccountconf_mutable DF_password "$DF_password" From 3b0d7bc4adaf41e04e5ef78f6c69bd66864055ca Mon Sep 17 00:00:00 2001 From: ThiloGa <61890902+ThiloGa@users.noreply.github.com> Date: Sat, 2 May 2020 08:29:44 +0200 Subject: [PATCH 049/161] typo fixing --- dnsapi/dns_df.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_df.sh b/dnsapi/dns_df.sh index d5410d95..c0499ddf 100644 --- a/dnsapi/dns_df.sh +++ b/dnsapi/dns_df.sh @@ -29,7 +29,7 @@ dns_df_add() { _err "No auth details provided. Please set user credentials using the \$DF_user and \$DF_password environment variables." return 1 fi - #save the api user and sha256 password to the account conf file. + #save the api user and password to the account conf file. _debug "Save user and password" _saveaccountconf_mutable DF_user "$DF_user" _saveaccountconf_mutable DF_password "$DF_password" From cf5952f5081b8f4a1ac7e5e6f6ae993667ae369c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=BCnemann?= Date: Sat, 2 May 2020 22:14:21 +0200 Subject: [PATCH 050/161] fix haproxy deploy hook ocsp update fixes ocsp reponse update failing with `Responder Error: unauthorized (6)` by removing `-no_nonce` switch from `openssl oscp` command . --- deploy/haproxy.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/deploy/haproxy.sh b/deploy/haproxy.sh index 3cd2a80a..0a45ee07 100644 --- a/deploy/haproxy.sh +++ b/deploy/haproxy.sh @@ -233,7 +233,6 @@ haproxy_deploy() { -header Host${_header_sep}\"${_ocsp_host}\" \ -respout \"${_ocsp}\" \ -verify_other \"${_issuer}\" \ - -no_nonce \ ${_cafile_argument} \ | grep -q \"${_pem}: good\"" _debug _openssl_ocsp_cmd "${_openssl_ocsp_cmd}" From eab35605e47331d378292b0e6e32db466954b18e Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 3 May 2020 11:01:02 +0800 Subject: [PATCH 051/161] remove sudo --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 155ec64b..91da2731 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,4 @@ language: shell -sudo: required dist: trusty os: From 9044adecb58e5d7b91056688ce1ca60543d7c3d3 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 4 May 2020 08:43:47 +0800 Subject: [PATCH 052/161] start 2.8.7 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 97d71a22..dd47481d 100755 --- a/acme.sh +++ b/acme.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -VER=2.8.6 +VER=2.8.7 PROJECT_NAME="acme.sh" From 81036894c01d8a3793215f65dfd1f1d03c7d94d5 Mon Sep 17 00:00:00 2001 From: Philipp Bandow <43735306+philband@users.noreply.github.com> Date: Thu, 7 May 2020 15:28:00 +0200 Subject: [PATCH 053/161] Add new DNS Provider: Njalla --- dnsapi/dns_njalla.sh | 169 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 dnsapi/dns_njalla.sh diff --git a/dnsapi/dns_njalla.sh b/dnsapi/dns_njalla.sh new file mode 100644 index 00000000..3b8b9ac7 --- /dev/null +++ b/dnsapi/dns_njalla.sh @@ -0,0 +1,169 @@ +#!/usr/bin/env sh + +# +#NJALLA_Token="sdfsdfsdfljlbjkljlkjsdfoiwje" + +NJALLA_Api="https://njal.la/api/1/" + +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_njalla_add() { + fulldomain=$1 + txtvalue=$2 + + NJALLA_Token="${NJALLA_Token:-$(_readaccountconf_mutable NJALLA_Token)}" + + if [ "$NJALLA_Token" ]; then + _saveaccountconf_mutable NJALLA_Token "$NJALLA_Token" + else + NJALLA_Token="" + _err "You didn't specify a Njalla api token yet." + return 1 + fi + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + # For wildcard cert, the main root domain and the wildcard domain have the same txt subdomain name, so + # we can not use updating anymore. + # count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2) + # _debug count "$count" + # if [ "$count" = "0" ]; then + _info "Adding record" + if _njalla_rest "{\"method\":\"add-record\",\"params\":{\"domain\":\"$_domain\",\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}}"; then + if _contains "$response" "$txtvalue"; then + _info "Added, OK" + return 0 + else + _err "Add txt record error." + return 1 + fi + fi + _err "Add txt record error." + return 1 + +} + +#fulldomain txtvalue +dns_njalla_rm() { + fulldomain=$1 + txtvalue=$2 + + NJALLA_Token="${NJALLA_Token:-$(_readaccountconf_mutable NJALLA_Token)}" + + if [ "$NJALLA_Token" ]; then + _saveaccountconf_mutable NJALLA_Token "$NJALLA_Token" + else + NJALLA_Token="" + _err "You didn't specify a Njalla api token yet." + return 1 + fi + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting records for domain" + if ! _njalla_rest "{\"method\":\"list-records\",\"params\":{\"domain\":\"${_domain}\"}}"; then + return 1 + fi + + if ! echo "$response" | tr -d " " | grep "\"id\":" >/dev/null; then + _err "Error: $response" + return 1 + fi + + records=$(echo "$response" | _egrep_o "\"records\":\s?\[(.*)\]\}" | _egrep_o "\[.*\]" | _egrep_o "\{[^\{\}]*\"id\":[^\{\}]*\}") + count=$(echo "$records" | wc -l) + _debug count "$count" + + if [ "$count" = "0" ]; then + _info "Don't need to remove." + else + echo "$records" | while read -r record ; do + record_name=$(echo "$record" | _egrep_o "\"name\":\s?\"[^\"]*\"" | cut -d : -f 2 | tr -d " " | tr -d \") + record_content=$(echo "$record" | _egrep_o "\"content\":\s?\"[^\"]*\"" | cut -d : -f 2 | tr -d " " | tr -d \") + record_id=$(echo "$record" | _egrep_o "\"id\":\s?[0-9]+" | cut -d : -f 2 | tr -d " " | tr -d \") + if [ "$_sub_domain" = "$record_name" ]; then + if [ "$txtvalue" = "$record_content" ]; then + _debug "record_id" "$record_id" + if ! _njalla_rest "{\"method\":\"remove-record\",\"params\":{\"domain\":\"${_domain}\",\"id\":${record_id}}}"; then + _err "Delete record error." + return 1 + fi + echo "$response" | tr -d " " | grep "\"result\"" >/dev/null + fi + fi + done + fi + +} + +#################### Private functions below ################################## +#_acme-challenge.www.domain.com +#returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +# _domain_id=sdjkglgdfewsdfg +_get_root() { + domain=$1 + i=1 + p=1 + + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug h "$h" + if [ -z "$h" ]; then + #not valid + return 1 + fi + + + if ! _njalla_rest "{\"method\":\"get-domain\",\"params\":{\"domain\":\"${h}\"}}"; then + return 1 + fi + + if _contains "$response" "\"$h\""; then + _domain_returned=$(echo "$response" | _egrep_o "\{\"name\": *\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \" | tr -d " ") + if [ "$_domain_returned" ]; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain=$h + return 0 + fi + return 1 + fi + p=$i + i=$(_math "$i" + 1) + done + return 1 +} + +_njalla_rest() { + data="$1" + + token_trimmed=$(echo "$NJALLA_Token" | tr -d '"') + + export _H1="Content-Type: application/json" + export _H2="Accept: application/json" + export _H3="Authorization: Njalla $token_trimmed" + + _debug data "$data" + response="$(_post "$data" "$NJALLA_Api" "" "POST")" + + if [ "$?" != "0" ]; then + _err "error $ep" + return 1 + fi + _debug2 response "$response" + return 0 +} From 9bbcfead67638bcd602c50a8051e042bfa02360b Mon Sep 17 00:00:00 2001 From: Philipp Bandow <43735306+philband@users.noreply.github.com> Date: Thu, 7 May 2020 15:37:59 +0200 Subject: [PATCH 054/161] Bugfix shell format error --- dnsapi/dns_njalla.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_njalla.sh b/dnsapi/dns_njalla.sh index 3b8b9ac7..f91a1ed5 100644 --- a/dnsapi/dns_njalla.sh +++ b/dnsapi/dns_njalla.sh @@ -90,7 +90,7 @@ dns_njalla_rm() { if [ "$count" = "0" ]; then _info "Don't need to remove." else - echo "$records" | while read -r record ; do + echo "$records" | while read -r record; do record_name=$(echo "$record" | _egrep_o "\"name\":\s?\"[^\"]*\"" | cut -d : -f 2 | tr -d " " | tr -d \") record_content=$(echo "$record" | _egrep_o "\"content\":\s?\"[^\"]*\"" | cut -d : -f 2 | tr -d " " | tr -d \") record_id=$(echo "$record" | _egrep_o "\"id\":\s?[0-9]+" | cut -d : -f 2 | tr -d " " | tr -d \") From d507979ec1b6ad67b82ac36cb23ed52384fae9a3 Mon Sep 17 00:00:00 2001 From: Philipp Bandow <43735306+philband@users.noreply.github.com> Date: Thu, 7 May 2020 15:41:09 +0200 Subject: [PATCH 055/161] Make CI happy: Remove extraneous new line --- dnsapi/dns_njalla.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_njalla.sh b/dnsapi/dns_njalla.sh index f91a1ed5..804b0772 100644 --- a/dnsapi/dns_njalla.sh +++ b/dnsapi/dns_njalla.sh @@ -128,7 +128,6 @@ _get_root() { return 1 fi - if ! _njalla_rest "{\"method\":\"get-domain\",\"params\":{\"domain\":\"${h}\"}}"; then return 1 fi From d904df57ca48cb01e71b0a6c86d7cb3027b8fb3d Mon Sep 17 00:00:00 2001 From: Philipp Bandow <43735306+philband@users.noreply.github.com> Date: Thu, 7 May 2020 15:45:47 +0200 Subject: [PATCH 056/161] Bugfix error message in rest function --- dnsapi/dns_njalla.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_njalla.sh b/dnsapi/dns_njalla.sh index 804b0772..e9243288 100644 --- a/dnsapi/dns_njalla.sh +++ b/dnsapi/dns_njalla.sh @@ -160,7 +160,7 @@ _njalla_rest() { response="$(_post "$data" "$NJALLA_Api" "" "POST")" if [ "$?" != "0" ]; then - _err "error $ep" + _err "error $data" return 1 fi _debug2 response "$response" From 036a37e3511f09c8fd33a18fe4fa3c589134423e Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Thu, 7 May 2020 23:19:02 +0200 Subject: [PATCH 057/161] Nullify output from lexicon_cmd to prevent getting wrong return codes --- dnsapi/dns_lexicon.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_lexicon.sh b/dnsapi/dns_lexicon.sh index 516b6eff..34a95599 100755 --- a/dnsapi/dns_lexicon.sh +++ b/dnsapi/dns_lexicon.sh @@ -92,7 +92,7 @@ dns_lexicon_add() { _savedomainconf LEXICON_OPTS "$LEXICON_OPTS" # shellcheck disable=SC2086 - $lexicon_cmd "$PROVIDER" $LEXICON_OPTS create "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}" + $lexicon_cmd "$PROVIDER" $LEXICON_OPTS create "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}" >/dev/null } @@ -108,6 +108,6 @@ dns_lexicon_rm() { domain=$(printf "%s" "$fulldomain" | cut -d . -f 2-999) # shellcheck disable=SC2086 - $lexicon_cmd "$PROVIDER" $LEXICON_OPTS delete "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}" + $lexicon_cmd "$PROVIDER" $LEXICON_OPTS delete "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}" >/dev/null } From 99793bb2c492a8fe45a6ae8789b304d06be308e0 Mon Sep 17 00:00:00 2001 From: Honza Hommer Date: Sat, 9 May 2020 12:26:16 +0200 Subject: [PATCH 058/161] chore: remove shellcheck disable --- notify/teams.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/notify/teams.sh b/notify/teams.sh index 6b360ae5..e50ea703 100644 --- a/notify/teams.sh +++ b/notify/teams.sh @@ -74,8 +74,7 @@ teams_send() { fi _data="$_data\"text\": \"$_content\"}" - if _post "$_data" "$TEAMS_WEBHOOK_URL"; then - # shellcheck disable=SC2154 + if response=$(_post "$_data" "$TEAMS_WEBHOOK_URL"); then if ! _contains "$response" error; then _info "teams send success." return 0 From 94bf54e7e0f18cbf2e00fd44348c101bd18cfbda Mon Sep 17 00:00:00 2001 From: QDaniel Date: Wed, 13 May 2020 12:14:27 +0200 Subject: [PATCH 059/161] INWX fix Domain Limit #1491 --- dnsapi/dns_inwx.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/dnsapi/dns_inwx.sh b/dnsapi/dns_inwx.sh index 50b4b10c..ba789da9 100755 --- a/dnsapi/dns_inwx.sh +++ b/dnsapi/dns_inwx.sh @@ -261,6 +261,20 @@ _get_root() { xml_content=' nameserver.list + + + + + + pagelimit + + 9999 + + + + + + ' response="$(_post "$xml_content" "$INWX_Api" "" "POST")" From a4c57ee363f253fc9104a449fac957d3ca6cc532 Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Wed, 13 May 2020 15:35:51 +0200 Subject: [PATCH 060/161] Add TransIP provider --- acme.sh | 2 +- dnsapi/dns_transip.sh | 163 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 dnsapi/dns_transip.sh diff --git a/acme.sh b/acme.sh index 97d71a22..df16c1e7 100755 --- a/acme.sh +++ b/acme.sh @@ -1003,7 +1003,7 @@ _sign() { _sign_openssl="${ACME_OPENSSL_BIN:-openssl} dgst -sign $keyfile " - if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then + if egrep -o "BEGIN( RSA)? PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then $_sign_openssl -$alg | _base64 elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then if ! _signedECText="$($_sign_openssl -sha$__ECC_KEY_LEN | ${ACME_OPENSSL_BIN:-openssl} asn1parse -inform DER)"; then diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh new file mode 100644 index 00000000..c828fa66 --- /dev/null +++ b/dnsapi/dns_transip.sh @@ -0,0 +1,163 @@ +#!/usr/bin/env sh +TRANSIP_Api_Url="https://api.transip.nl/v6" +TRANSIP_Key_File="transip2.key" +TRANSIP_Token_Read_Only="false" +TRANSIP_Token_Global_Key="false" +TRANSIP_Token_Expiration="30 minutes" +# You can't reuse a label token, so we leave this empty normally +TRANSIP_Token_Label="" + +######## Public functions ##################### +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_transip_add() { + fulldomain="$1" + _debug fulldomain="$fulldomain" + txtvalue="$2" + _debug txtvalue="$txtvalue" + _transip_setup $fulldomain || return 1 + _info "Creating TXT record." + if ! _transip_rest POST "domains/$_domain/dns" "{\"dnsEntry\":{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"expire\":300}}"; then + _err "Could not add TXT record." + return 1 + fi + return 0 +} + +dns_transip_rm() { + fulldomain=$1 + _debug fulldomain="$fulldomain" + txtvalue=$2 + _debug txtvalue="$txtvalue" + _transip_setup $fulldomain || return 1 + _info "Removing TXT record." + if ! _transip_rest DELETE "domains/$_domain/dns" "{\"dnsEntry\":{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"expire\":300}}"; then + _err "Could not remove TXT record $_sub_domain for $domain" + return 1 + fi + return 0 +} + +#################### 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 + + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain="$h" + + if _transip_rest GET "domains/$h/dns" && _contains $response "dnsEntries"; then + return 0 + fi + + p=$i + i=$(_math "$i" + 1) + done + _err "Unable to parse this domain" + return 1 +} + +_transip_rest() { + m="$1" + ep="$2" + data="$3" + _debug ep "$ep" + export _H1="Accept: application/json" + export _H2="Authorization: Bearer $_token" + export _H4="Content-Type: application/json" + if [ "$m" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$TRANSIP_Api_Url/$ep" "" "$m")" + retcode=$? + else + response="$(_get "$TRANSIP_Api_Url/$ep")" + retcode=$? + fi + + if [ "$retcode" != "0" ]; then + _err "error $ep" + return 1 + fi + _debug2 response "$response" + return 0 +} + +_transip_get_token() { + nonce=$(openssl rand -hex 12) + + data="{\"login\":\"${TRANSIP_Username}\",\"nonce\":\"${nonce}\",\"read_only\":\"${TRANSIP_Token_Read_Only}\",\"expiration_time\":\"${TRANSIP_Token_Expiration}\",\"label\":\"${TRANSIP_Token_Label}\",\"global_key\":\"${TRANSIP_Token_Global_Key}\"}" + _debug data "$data" + + #_signature=$(printf "%s" "$data" | openssl dgst -sha512 -sign "$TRANSIP_Key_File" | _base64) + _signature=$(printf "%s" "$data" | _sign "$TRANSIP_Key_File" "sha512") + _debug2 _signature "$_signature" + + export _H1="Signature: $_signature" + export _H2="Content-Type: application/json" + + response="$(_post "$data" "$TRANSIP_Api_Url/auth" "" "POST")" + retcode=$? + _debug2 response "$response" + if [ "$retcode" != "0" ]; then + _err "Authentication failed." + return 1 + fi + if _contains "$response" "token"; then + _token="$(echo "$response" | _normalizeJson | sed -n 's/^{"token":"\(.*\)"}/\1/p')" + _debug _token "$_token" + return 0 + fi + return 1 +} + +_transip_setup() { + fulldomain=$1 + + # retrieve the transip creds + TRANSIP_Username="${TRANSIP_Username:-$(_readaccountconf_mutable TRANSIP_Username)}" + TRANSIP_Key_File="${TRANSIP_Key_File:-$(_readaccountconf_mutable TRANSIP_Key_File)}" + # check their vals for null + if [ -z "$TRANSIP_Username" ] || [ -z "$TRANSIP_Key_File" ]; then + TRANSIP_Username="" + TRANSIP_Key_File="" + _err "You didn't specify a TransIP username and api key file location" + _err "Please set those values and try again." + return 1 + fi + # save the username and api key to the account conf file. + _saveaccountconf_mutable TRANSIP_Username "$TRANSIP_Username" + _saveaccountconf_mutable TRANSIP_Key_File "$TRANSIP_Key_File" + + if [ -f "$TRANSIP_Key_File"]; then + if ! grep "BEGIN PRIVATE KEY" "$TRANSIP_Key_File" >/dev/null 2>&1; then + _err "Key file doesn't seem to be a valid key: ${TRANSIP_Key_File}" + return 1 + fi + else + _err "Can't read private key file: ${TRANSIP_Key_File}" + return 1 + fi + + + if [ -z "$_token" ]; then + if ! _transip_get_token; then + _err "Can not get token." + return 1 + fi + fi + + _get_root $fulldomain || return 1 + + return 0 +} From 80a636bd14f9b01aca0fb4da6867ef163932e36f Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Wed, 13 May 2020 16:08:34 +0200 Subject: [PATCH 061/161] Fix extra space --- dnsapi/dns_transip.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh index c828fa66..180b278e 100644 --- a/dnsapi/dns_transip.sh +++ b/dnsapi/dns_transip.sh @@ -139,7 +139,7 @@ _transip_setup() { _saveaccountconf_mutable TRANSIP_Username "$TRANSIP_Username" _saveaccountconf_mutable TRANSIP_Key_File "$TRANSIP_Key_File" - if [ -f "$TRANSIP_Key_File"]; then + if [ -f "$TRANSIP_Key_File" ]; then if ! grep "BEGIN PRIVATE KEY" "$TRANSIP_Key_File" >/dev/null 2>&1; then _err "Key file doesn't seem to be a valid key: ${TRANSIP_Key_File}" return 1 From 65e82b03ade1566d74058f5bcb4bcd4526668548 Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Wed, 13 May 2020 16:11:53 +0200 Subject: [PATCH 062/161] Fix CI errors --- dnsapi/dns_transip.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh index 180b278e..5403cc10 100644 --- a/dnsapi/dns_transip.sh +++ b/dnsapi/dns_transip.sh @@ -14,7 +14,7 @@ dns_transip_add() { _debug fulldomain="$fulldomain" txtvalue="$2" _debug txtvalue="$txtvalue" - _transip_setup $fulldomain || return 1 + _transip_setup "$fulldomain" || return 1 _info "Creating TXT record." if ! _transip_rest POST "domains/$_domain/dns" "{\"dnsEntry\":{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"expire\":300}}"; then _err "Could not add TXT record." @@ -28,7 +28,7 @@ dns_transip_rm() { _debug fulldomain="$fulldomain" txtvalue=$2 _debug txtvalue="$txtvalue" - _transip_setup $fulldomain || return 1 + _transip_setup "$fulldomain" || return 1 _info "Removing TXT record." if ! _transip_rest DELETE "domains/$_domain/dns" "{\"dnsEntry\":{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"expire\":300}}"; then _err "Could not remove TXT record $_sub_domain for $domain" @@ -57,7 +57,7 @@ _get_root() { _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain="$h" - if _transip_rest GET "domains/$h/dns" && _contains $response "dnsEntries"; then + if _transip_rest GET "domains/$h/dns" && _contains "$response" "dnsEntries"; then return 0 fi @@ -157,7 +157,7 @@ _transip_setup() { fi fi - _get_root $fulldomain || return 1 + _get_root "$fulldomain" || return 1 return 0 } From a102d775b25ca00b210ab25a246653be65f6ee3b Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Wed, 13 May 2020 16:49:07 +0200 Subject: [PATCH 063/161] Formatting issues --- dnsapi/dns_transip.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh index 5403cc10..1fd8e4c9 100644 --- a/dnsapi/dns_transip.sh +++ b/dnsapi/dns_transip.sh @@ -58,7 +58,7 @@ _get_root() { _domain="$h" if _transip_rest GET "domains/$h/dns" && _contains "$response" "dnsEntries"; then - return 0 + return 0 fi p=$i @@ -140,10 +140,10 @@ _transip_setup() { _saveaccountconf_mutable TRANSIP_Key_File "$TRANSIP_Key_File" if [ -f "$TRANSIP_Key_File" ]; then - if ! grep "BEGIN PRIVATE KEY" "$TRANSIP_Key_File" >/dev/null 2>&1; then - _err "Key file doesn't seem to be a valid key: ${TRANSIP_Key_File}" - return 1 - fi + if ! grep "BEGIN PRIVATE KEY" "$TRANSIP_Key_File" >/dev/null 2>&1; then + _err "Key file doesn't seem to be a valid key: ${TRANSIP_Key_File}" + return 1 + fi else _err "Can't read private key file: ${TRANSIP_Key_File}" return 1 From e768e285ce96ba10a9791485afd5a6a5886d3d4a Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Wed, 13 May 2020 16:49:42 +0200 Subject: [PATCH 064/161] Remove extra newline --- dnsapi/dns_transip.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh index 1fd8e4c9..34fbafa6 100644 --- a/dnsapi/dns_transip.sh +++ b/dnsapi/dns_transip.sh @@ -149,7 +149,6 @@ _transip_setup() { return 1 fi - if [ -z "$_token" ]; then if ! _transip_get_token; then _err "Can not get token." From d5ef3a3f8ca423688062b7177f8320f8719a828e Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Wed, 13 May 2020 17:07:19 +0200 Subject: [PATCH 065/161] Formatting issues --- dnsapi/dns_transip.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh index 34fbafa6..23a7f493 100644 --- a/dnsapi/dns_transip.sh +++ b/dnsapi/dns_transip.sh @@ -145,8 +145,8 @@ _transip_setup() { return 1 fi else - _err "Can't read private key file: ${TRANSIP_Key_File}" - return 1 + _err "Can't read private key file: ${TRANSIP_Key_File}" + return 1 fi if [ -z "$_token" ]; then From 048f754d837a85ee6e7698219f6848702c254890 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Vestergaard=20V=C3=A6rum?= Date: Thu, 14 May 2020 22:49:04 +0200 Subject: [PATCH 066/161] Bug fix: DNS TXT entries will now be removed for dns_gdnsdk.sh --- dnsapi/dns_gdnsdk.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_gdnsdk.sh b/dnsapi/dns_gdnsdk.sh index 8c4962c0..90842b25 100755 --- a/dnsapi/dns_gdnsdk.sh +++ b/dnsapi/dns_gdnsdk.sh @@ -157,9 +157,18 @@ _successful_update() { } _findentry() { + #args $1: fulldomain, $2: txtvalue #returns id of dns entry, if it exists _myget "action=dns_primary_changeDNSsetup&user_domain=$_domain" - _id=$(echo "$_result" | _egrep_o "$1\s*$2[^?]*[^&]*&id=[^&]*" | sed 's/^.*=//') + _debug3 "_result: $_result" + + _tmp_result=$(echo "$_result" | tr -d '\n\r' | _egrep_o "$1\s*$2[^?]*[^&]*&id=[^&]*") + _debug _tmp_result "$_tmp_result" + if [ -z "${_tmp_result:-}" ]; then + _debug "The variable is _tmp_result is not supposed to be empty, there may be something wrong with the script" + fi + + _id=$(echo "$_tmp_result" | sed 's/^.*=//') if [ -n "$_id" ]; then _debug "Entry found with _id=$_id" return 0 From 52b81608a1cbb51409d25e9c97d7a5087f7982c7 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Fri, 15 May 2020 23:48:50 -0600 Subject: [PATCH 067/161] need to _url_encode anything sent in GET requests Fixes issue raised by @tatablack --- deploy/synology_dsm.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 5aef3b93..279b3c4f 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -83,6 +83,9 @@ synology_dsm_deploy() { _info "Logging into $SYNO_Hostname:$SYNO_Port" response=$(_get "$_base_url/webman/login.cgi?username=$SYNO_Username&passwd=$SYNO_Password&enable_syno_token=yes&device_id=$SYNO_DID") token=$(echo "$response" | grep "SynoToken" | sed -n 's/.*"SynoToken" *: *"\([^"]*\).*/\1/p') + encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)" + encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)" + encoded_did="$(printf "%s" "$SYNO_DID" | _url_encode)" _debug3 response "$response" if [ -z "$token" ]; then From d15c14ab939682e0327202a78ef2470df7472181 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Fri, 15 May 2020 23:53:00 -0600 Subject: [PATCH 068/161] Fix support for wget I'm actually not entirely sure why/how this worked with curl but not wget, but it did. The short answer is that using a GET does not result in the HTTP_HEADER file being written, instead you must pass in the http_headers param ($2) which will return the HTTP headers as a string. Luckily, the Token is in both the body and the header. We need it and the id (and smid if 2fa) cookie to proceed. So now we parrse the response for that instead of the HTTP_HEADER file. Interesting side note: wget is fine if the URL contains a \r or \n, but curl will barf on it. So we need to make sure those are stripped from the token as it will be passed in the URL later. --- deploy/synology_dsm.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 279b3c4f..7e77344f 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -22,7 +22,7 @@ ######## Public functions ##################### _syno_get_cookie_data() { - grep "\W$1=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';' + grep "\W$1=" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';' } #domain keyfile certfile cafile fullchain @@ -81,12 +81,13 @@ synology_dsm_deploy() { # Login, get the token from JSON and session id from cookie _info "Logging into $SYNO_Hostname:$SYNO_Port" - response=$(_get "$_base_url/webman/login.cgi?username=$SYNO_Username&passwd=$SYNO_Password&enable_syno_token=yes&device_id=$SYNO_DID") - token=$(echo "$response" | grep "SynoToken" | sed -n 's/.*"SynoToken" *: *"\([^"]*\).*/\1/p') encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)" encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)" encoded_did="$(printf "%s" "$SYNO_DID" | _url_encode)" + response=$(_get "$_base_url/webman/login.cgi?username=$encoded_username&passwd=$encoded_password&enable_syno_token=yes&device_id=$encoded_did" 1) + token=$(echo "$response" | grep "X-SYNO-TOKEN:" | sed -n 's/^X-SYNO-TOKEN: \(.*\)$/\1/p' | tr -d "\r\n") _debug3 response "$response" + _debug token "$token" if [ -z "$token" ]; then _err "Unable to authenticate to $SYNO_Hostname:$SYNO_Port using $SYNO_Scheme." @@ -94,7 +95,7 @@ synology_dsm_deploy() { return 1 fi - _H1="Cookie: $(_syno_get_cookie_data "id"); $(_syno_get_cookie_data "smid")" + _H1="Cookie: $(echo "$response" | _syno_get_cookie_data "id"); $(echo "$response" | _syno_get_cookie_data "smid")" _H2="X-SYNO-TOKEN: $token" export _H1 export _H2 @@ -105,7 +106,6 @@ synology_dsm_deploy() { _savedeployconf SYNO_Username "$SYNO_Username" _savedeployconf SYNO_Password "$SYNO_Password" _savedeployconf SYNO_DID "$SYNO_DID" - _debug token "$token" _info "Getting certificates in Synology DSM" response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1" "$_base_url/webapi/entry.cgi") From 668967a7198c583143d5c63b5aed805fd779ac8e Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sat, 16 May 2020 00:05:35 -0600 Subject: [PATCH 069/161] If SYNO_Create is not set here, print the nice message --- deploy/synology_dsm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 7e77344f..b55d1286 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -113,7 +113,7 @@ synology_dsm_deploy() { id=$(echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\"id\":\"\([^\"]*\).*/\1/p") _debug2 id "$id" - if [ -z "$id" ] && [ -z "${SYNO_Create:?}" ]; then + if [ -z "$id" ] && [ -z "$SYNO_Create" ]; then _err "Unable to find certificate: $SYNO_Certificate and \$SYNO_Create is not set" return 1 fi From 3a7c7fe4e8fc663a4ec913aee1997736918493f5 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sat, 16 May 2020 00:19:18 -0600 Subject: [PATCH 070/161] Fix shellcheck issues --- deploy/synology_dsm.sh | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index b55d1286..06ee2f1e 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -40,9 +40,7 @@ synology_dsm_deploy() { _getdeployconf SYNO_Password _getdeployconf SYNO_Create _getdeployconf SYNO_DID - if [ -z "$SYNO_Username" ] || [ -z "$SYNO_Password" ]; then - SYNO_Username="" - SYNO_Password="" + if [ -z "${SYNO_Username:-}" ] || [ -z "${SYNO_Password:-}" ]; then _err "SYNO_Username & SYNO_Password must be set" return 1 fi @@ -70,7 +68,7 @@ synology_dsm_deploy() { # Get the certificate description, but don't save it until we verfiy it's real _getdeployconf SYNO_Certificate - if [ -z "${SYNO_Certificate:?}" ]; then + if [ -z "${SYNO_Certificate:-}" ]; then _err "SYNO_Certificate needs to be defined (with the Certificate description name)" return 1 fi @@ -113,7 +111,7 @@ synology_dsm_deploy() { id=$(echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\"id\":\"\([^\"]*\).*/\1/p") _debug2 id "$id" - if [ -z "$id" ] && [ -z "$SYNO_Create" ]; then + if [ -z "$id" ] && [ -z "${SYNO_Create:-}" ]; then _err "Unable to find certificate: $SYNO_Certificate and \$SYNO_Create is not set" return 1 fi From c7f61f8b804793aebcc131354b5d0978a2b397ce Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sat, 16 May 2020 01:38:44 -0600 Subject: [PATCH 071/161] Allow rotating the default certificate which has no description This means, by default, we will rotate the default certificate that comes with the DSM --- deploy/synology_dsm.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 06ee2f1e..7ca4375e 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -68,10 +68,6 @@ synology_dsm_deploy() { # Get the certificate description, but don't save it until we verfiy it's real _getdeployconf SYNO_Certificate - if [ -z "${SYNO_Certificate:-}" ]; then - _err "SYNO_Certificate needs to be defined (with the Certificate description name)" - return 1 - fi _debug SYNO_Certificate "$SYNO_Certificate" _base_url="$SYNO_Scheme://$SYNO_Hostname:$SYNO_Port" From 694194be2f1d1e98385f884b0fb0f11ace3b4a77 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sat, 16 May 2020 02:25:53 -0600 Subject: [PATCH 072/161] Shellcheck fix SYNO_Certificate gets set by _getdeployconf, so this may be an empty string but that's fine --- deploy/synology_dsm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 7ca4375e..b93d0187 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -68,7 +68,7 @@ synology_dsm_deploy() { # Get the certificate description, but don't save it until we verfiy it's real _getdeployconf SYNO_Certificate - _debug SYNO_Certificate "$SYNO_Certificate" + _debug SYNO_Certificate "${SYNO_Certificate:-}" _base_url="$SYNO_Scheme://$SYNO_Hostname:$SYNO_Port" _debug _base_url "$_base_url" From 4954b44d8e818ac7b78943d5446d9a7b0aae5410 Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Sat, 16 May 2020 16:18:05 +0200 Subject: [PATCH 073/161] Remove default key file (leave it to the user to explicitly specify) --- dnsapi/dns_transip.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh index 23a7f493..b5cea51b 100644 --- a/dnsapi/dns_transip.sh +++ b/dnsapi/dns_transip.sh @@ -1,6 +1,5 @@ #!/usr/bin/env sh TRANSIP_Api_Url="https://api.transip.nl/v6" -TRANSIP_Key_File="transip2.key" TRANSIP_Token_Read_Only="false" TRANSIP_Token_Global_Key="false" TRANSIP_Token_Expiration="30 minutes" From fa91516dcec14813ad27fc158ebf3c85645d1142 Mon Sep 17 00:00:00 2001 From: Gassan Gousseinov Date: Sun, 17 May 2020 18:54:06 +0200 Subject: [PATCH 074/161] added dnsapi/dns_hetzner.sh --- dnsapi/dns_hetzner.sh | 252 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 dnsapi/dns_hetzner.sh diff --git a/dnsapi/dns_hetzner.sh b/dnsapi/dns_hetzner.sh new file mode 100644 index 00000000..9499501f --- /dev/null +++ b/dnsapi/dns_hetzner.sh @@ -0,0 +1,252 @@ +#!/usr/bin/env sh + +# +#HETZNER_Token="sdfsdfsdfljlbjkljlkjsdfoiwje" +# + +HETZNER_Api="https://dns.hetzner.com/api/v1" + +######## Public functions ##################### + +# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +# Used to add txt record +# Ref: https://dns.hetzner.com/api-docs/ +dns_hetzner_add() { + full_domain=$1 + txt_value=$2 + + HETZNER_Token="${HETZNER_Token:-$(_readaccountconf_mutable HETZNER_Token)}" + + if [ -z "$HETZNER_Token" ]; then + HETZNER_Token="" + _err "You didn't specify a Hetzner api token." + _err "You can get yours from here https://dns.hetzner.com/settings/api-token." + return 1 + fi + + #save the api key and email to the account conf file. + _saveaccountconf_mutable HETZNER_Token "$HETZNER_Token" + + _debug "First detect the root zone" + + if ! _get_root "$full_domain"; then + _err "Invalid domain" + return 1 + fi + _debug _domain_id "$_domain_id" + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting TXT records" + if ! _find_record "$_sub_domain" "$txt_value"; then + return 1 + fi + + if [ -z "$_record_id" ]; then + _info "Adding record" + if _hetzner_rest POST "records" "{\"zone_id\":\"${HETZNER_Zone_ID}\",\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":\"$txt_value\",\"ttl\":120}"; then + if _contains "$response" "$txt_value"; then + _info "Record added, OK" + _sleep 2 + return 0 + fi + fi + _err "Add txt record error${_response_error}" + return 1 + else + _info "Found record id: $_record_id." + _info "Record found, do nothing." + return 0; +# # we could modify a record, if the names for txt records for *.example.com and example.com would be not the same +# if _hetzner_rest PUT "records/${_record_id}" "{\"zone_id\":\"${HETZNER_Zone_ID}\",\"type\":\"TXT\",\"name\":\"$full_domain\",\"value\":\"$txt_value\",\"ttl\":120}"; then +# if _contains "$response" "$txt_value"; then +# _info "Modified, OK" +# return 0 +# fi +# fi +# _err "Add txt record error (modify)." +# return 1 + fi +} + +# Usage: full_domain txt_value +# Used to remove the txt record after validation +dns_hetzner_rm() { + full_domain=$1 + txt_value=$2 + + HETZNER_Token="${HETZNER_Token:-$(_readaccountconf_mutable HETZNER_Token)}" + + _debug "First detect the root zone" + if ! _get_root "$full_domain"; then + _err "Invalid domain" + return 1 + fi + _debug _domain_id "$_domain_id" + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting TXT records" + if ! _find_record "$_sub_domain" "$txt_value"; then + return 1 + fi + + if [ -z "$_record_id" ]; then + _info "Remove not needed. Record not found." + else + if ! _hetzner_rest DELETE "records/$_record_id"; then + _err "Delete record error${_response_error}" + return 1 + fi + _sleep 2 + _info "Record deleted" + fi +} + +#################### Private functions below ################################## +#returns +# _record_id=a8d58f22d6931bf830eaa0ec6464bf81 if found; or 1 if error +_find_record() { + unset _record_id; + _record_name=$1 + _record_value=$2 + + if [ -z "$_record_value" ]; then + _record_value="[^\"]*" + fi + + _debug "Getting all records" + _hetzner_rest GET "records?zone_id=${_domain_id}" + + if _response_has_error; then + _err "Error${_response_error}" + return 1 + else + _record_id=$( + echo "$response" \ + | grep -o "{[^\{\}]*\"name\":\"$_record_name\"[^\}]*}" \ + | grep "\"value\":\"$_record_value\"" \ + | while read -r record; do + # test for type and + if [ -n "$(echo "$record" | _egrep_o '"type":"TXT"')" ]; then + echo "$record" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" + break + fi + done + ) + fi +} + +#_acme-challenge.www.domain.com +#returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +# _domain_id=sdjkglgdfewsdfg +_get_root() { + domain=$1 + i=1 + p=1 + + domain_without_acme=$(echo "$domain" | cut -d . -f 2-) + domain_param_name=$(echo "HETZNER_Zone_ID_for_${domain_without_acme}" | sed 's/[\.\-]/_/g') + + _debug "Reading zone_id for '$domain_without_acme' from config..." + HETZNER_Zone_ID=$(_readdomainconf "$domain_param_name") + if [ "$HETZNER_Zone_ID" ]; then + _debug "Found, using: $HETZNER_Zone_ID" + if ! _hetzner_rest GET "zones/${HETZNER_Zone_ID}"; then + _debug "Zone with id '$HETZNER_Zone_ID' not exists." + _cleardomainconf "$domain_param_name" + unset HETZNER_Zone_ID + else + if _contains "$response" "\"id\":\"$HETZNER_Zone_ID\""; then + _domain=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1) + if [ "$_domain" ]; then + _cut_length=$((${#domain} - ${#_domain} - 1)) + _sub_domain=$(printf "%s" "$domain" | cut -c "1-$_cut_length") + _domain_id="$HETZNER_Zone_ID" + return 0 + else + return 1 + fi + else + return 1 + fi + fi + fi + + _debug "Trying to get zone id by domain name for '$domain_without_acme'." + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + if [ -z "$h" ]; then + #not valid + return 1 + fi + _debug h "$h" + + _hetzner_rest GET "zones?name=$h" + + if _contains "$response" "\"name\":\"$h\"" || _contains "$response" '"total_entries":1'; then + _domain_id=$(echo "$response" | _egrep_o "\[.\"id\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \") + if [ "$_domain_id" ]; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain=$h + HETZNER_Zone_ID=$_domain_id + _savedomainconf "$domain_param_name" "$HETZNER_Zone_ID" + return 0 + fi + return 1 + fi + p=$i + i=$(_math "$i" + 1) + done + return 1 +} + +#returns +# _response_error +_response_has_error() { + unset _response_error + + err_part="$(echo "$response" | _egrep_o '"error":{[^}]*}')" + + if [ -n "$err_part" ]; then + err_code=$(echo "$err_part" | _egrep_o '"code":[0-9]+' | cut -d : -f 2) + err_message=$(echo "$err_part" | _egrep_o '"message":"[^"]+"' | cut -d : -f 2 | tr -d \") + + if [ -n "$err_code" ] && [ -n "$err_message" ]; then + _response_error=" - message: ${err_message}, code: ${err_code}" + return 0 + fi + fi + + return 1 +} + +#returns +# response +_hetzner_rest() { + m=$1 + ep="$2" + data="$3" + _debug "$ep" + + key_trimmed=$(echo "$HETZNER_Token" | tr -d \") + + export _H1="Content-TType: application/json" + export _H2="Auth-API-Token: $key_trimmed" + + if [ "$m" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$HETZNER_Api/$ep" "" "$m")" + else + response="$(_get "$HETZNER_Api/$ep")" + fi + + if [ "$?" != "0" ] || _response_has_error; then + _debug "Error$_response_error" + return 1 + fi + _debug2 response "$response" + return 0 +} From b82c48b66f1c75befb372316bc2cd882d9d9d3a0 Mon Sep 17 00:00:00 2001 From: Gassan Gousseinov Date: Sun, 17 May 2020 22:51:04 +0200 Subject: [PATCH 075/161] shfmt --- dnsapi/dns_hetzner.sh | 52 +++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/dnsapi/dns_hetzner.sh b/dnsapi/dns_hetzner.sh index 9499501f..d994d665 100644 --- a/dnsapi/dns_hetzner.sh +++ b/dnsapi/dns_hetzner.sh @@ -56,16 +56,16 @@ dns_hetzner_add() { else _info "Found record id: $_record_id." _info "Record found, do nothing." - return 0; -# # we could modify a record, if the names for txt records for *.example.com and example.com would be not the same -# if _hetzner_rest PUT "records/${_record_id}" "{\"zone_id\":\"${HETZNER_Zone_ID}\",\"type\":\"TXT\",\"name\":\"$full_domain\",\"value\":\"$txt_value\",\"ttl\":120}"; then -# if _contains "$response" "$txt_value"; then -# _info "Modified, OK" -# return 0 -# fi -# fi -# _err "Add txt record error (modify)." -# return 1 + return 0 + # we could modify a record, if the names for txt records for *.example.com and example.com would be not the same + #if _hetzner_rest PUT "records/${_record_id}" "{\"zone_id\":\"${HETZNER_Zone_ID}\",\"type\":\"TXT\",\"name\":\"$full_domain\",\"value\":\"$txt_value\",\"ttl\":120}"; then + # if _contains "$response" "$txt_value"; then + # _info "Modified, OK" + # return 0 + # fi + #fi + #_err "Add txt record error (modify)." + #return 1 fi } @@ -107,12 +107,12 @@ dns_hetzner_rm() { #returns # _record_id=a8d58f22d6931bf830eaa0ec6464bf81 if found; or 1 if error _find_record() { - unset _record_id; + unset _record_id _record_name=$1 _record_value=$2 if [ -z "$_record_value" ]; then - _record_value="[^\"]*" + _record_value='[^"]*' fi _debug "Getting all records" @@ -129,11 +129,11 @@ _find_record() { | while read -r record; do # test for type and if [ -n "$(echo "$record" | _egrep_o '"type":"TXT"')" ]; then - echo "$record" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" + echo "$record" | _egrep_o '"id":"[^"]*"' | cut -d : -f 2 | tr -d \" break fi done - ) + ) fi } @@ -160,7 +160,7 @@ _get_root() { unset HETZNER_Zone_ID else if _contains "$response" "\"id\":\"$HETZNER_Zone_ID\""; then - _domain=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1) + _domain=$(printf "%s\n" "$response" | _egrep_o '"name":"[^"]*"' | cut -d : -f 2 | tr -d \" | head -n 1) if [ "$_domain" ]; then _cut_length=$((${#domain} - ${#_domain} - 1)) _sub_domain=$(printf "%s" "$domain" | cut -c "1-$_cut_length") @@ -206,21 +206,21 @@ _get_root() { #returns # _response_error _response_has_error() { - unset _response_error + unset _response_error - err_part="$(echo "$response" | _egrep_o '"error":{[^}]*}')" + err_part="$(echo "$response" | _egrep_o '"error":{[^}]*}')" - if [ -n "$err_part" ]; then - err_code=$(echo "$err_part" | _egrep_o '"code":[0-9]+' | cut -d : -f 2) - err_message=$(echo "$err_part" | _egrep_o '"message":"[^"]+"' | cut -d : -f 2 | tr -d \") + if [ -n "$err_part" ]; then + err_code=$(echo "$err_part" | _egrep_o '"code":[0-9]+' | cut -d : -f 2) + err_message=$(echo "$err_part" | _egrep_o '"message":"[^"]+"' | cut -d : -f 2 | tr -d \") - if [ -n "$err_code" ] && [ -n "$err_message" ]; then - _response_error=" - message: ${err_message}, code: ${err_code}" - return 0 - fi - fi + if [ -n "$err_code" ] && [ -n "$err_message" ]; then + _response_error=" - message: ${err_message}, code: ${err_code}" + return 0 + fi + fi - return 1 + return 1 } #returns From 8b3d792bec2061fb6ad18ee5eb2f22b58b92cd54 Mon Sep 17 00:00:00 2001 From: Ian Wienand Date: Mon, 18 May 2020 15:24:54 +1000 Subject: [PATCH 076/161] dns_rackspace: search for domain The current call uses the /domains end-point which lists all domains. This only returns 100 domains at a time, so for long domain lists you may not match and find the required ID. Switch to using the search interface that only returns values matching the requested domain. This will avoid missing results. Reported by @jjamfd. Closes: #2944 --- dnsapi/dns_rackspace.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_rackspace.sh b/dnsapi/dns_rackspace.sh index 159671f9..03e1fa68 100644 --- a/dnsapi/dns_rackspace.sh +++ b/dnsapi/dns_rackspace.sh @@ -73,7 +73,7 @@ _get_root_zone() { #not valid return 1 fi - if ! _rackspace_rest GET "$RACKSPACE_Tenant/domains"; then + if ! _rackspace_rest GET "$RACKSPACE_Tenant/domains/search?name=$h"; then return 1 fi _debug2 response "$response" From 0deea5393124f4ab34822932f8cf80e464046342 Mon Sep 17 00:00:00 2001 From: kref Date: Tue, 19 May 2020 13:27:00 +0800 Subject: [PATCH 077/161] fix octal escapes for printf %b format Stop it from misinterpreting a following digit as part of the escape sequence --- deploy/synology_dsm.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index 5aef3b93..c8458c0a 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -125,11 +125,11 @@ synology_dsm_deploy() { _debug2 default "$default" _info "Generate form POST request" - nl="\015\012" + nl="\0015\0012" delim="--------------------------$(_utc_date | tr -d -- '-: ')" - content="--$delim${nl}Content-Disposition: form-data; name=\"key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")\012" - content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"cert\"; filename=\"$(basename "$_ccert")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ccert")\012" - content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"inter_cert\"; filename=\"$(basename "$_cca")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cca")\012" + content="--$delim${nl}Content-Disposition: form-data; name=\"key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")\0012" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"cert\"; filename=\"$(basename "$_ccert")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ccert")\0012" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"inter_cert\"; filename=\"$(basename "$_cca")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cca")\0012" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"id\"${nl}${nl}$id" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"desc\"${nl}${nl}${SYNO_Certificate}" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"as_default\"${nl}${nl}${default}" From adfa1704e2188828562004e5fab05b1a731749c2 Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Tue, 19 May 2020 16:38:23 +0200 Subject: [PATCH 078/161] Update nonce calculation to use acme.sh methods instead of openssl command --- dnsapi/dns_transip.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh index b5cea51b..8764c1c4 100644 --- a/dnsapi/dns_transip.sh +++ b/dnsapi/dns_transip.sh @@ -93,7 +93,7 @@ _transip_rest() { } _transip_get_token() { - nonce=$(openssl rand -hex 12) + nonce=$(echo "TRANSIP$(_time)" | _digest sha1 hex) data="{\"login\":\"${TRANSIP_Username}\",\"nonce\":\"${nonce}\",\"read_only\":\"${TRANSIP_Token_Read_Only}\",\"expiration_time\":\"${TRANSIP_Token_Expiration}\",\"label\":\"${TRANSIP_Token_Label}\",\"global_key\":\"${TRANSIP_Token_Global_Key}\"}" _debug data "$data" From 2d5b4a00032ef6ed03f1b5b6baea3027dfef65c5 Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Tue, 19 May 2020 16:39:49 +0200 Subject: [PATCH 079/161] Change if-statement for private keys to more portable version --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index df16c1e7..80f5c241 100755 --- a/acme.sh +++ b/acme.sh @@ -1003,7 +1003,7 @@ _sign() { _sign_openssl="${ACME_OPENSSL_BIN:-openssl} dgst -sign $keyfile " - if egrep -o "BEGIN( RSA)? PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then + if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; || if grep "BEGIN PRIVATE KEY" "$keyfile" >/dev/null 2>&1; $_sign_openssl -$alg | _base64 elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then if ! _signedECText="$($_sign_openssl -sha$__ECC_KEY_LEN | ${ACME_OPENSSL_BIN:-openssl} asn1parse -inform DER)"; then From 5d2777634a05cf71391e5e168e1f382d7964fe32 Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Tue, 19 May 2020 16:43:39 +0200 Subject: [PATCH 080/161] Fix forgotten then --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 80f5c241..d3c357fc 100755 --- a/acme.sh +++ b/acme.sh @@ -1003,7 +1003,7 @@ _sign() { _sign_openssl="${ACME_OPENSSL_BIN:-openssl} dgst -sign $keyfile " - if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; || if grep "BEGIN PRIVATE KEY" "$keyfile" >/dev/null 2>&1; + if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; || if grep "BEGIN PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then $_sign_openssl -$alg | _base64 elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then if ! _signedECText="$($_sign_openssl -sha$__ECC_KEY_LEN | ${ACME_OPENSSL_BIN:-openssl} asn1parse -inform DER)"; then From 114f2a146542fe06ff7db6a763263e034debbedc Mon Sep 17 00:00:00 2001 From: neil Date: Tue, 19 May 2020 23:26:58 +0800 Subject: [PATCH 081/161] fix https://github.com/acmesh-official/acme.sh/issues/2880 --- acme.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index dd47481d..c92a9980 100755 --- a/acme.sh +++ b/acme.sh @@ -1986,7 +1986,9 @@ _send_signed_request() { continue fi if [ "$ACME_VERSION" = "2" ]; then - if [ "$url" = "$ACME_NEW_ACCOUNT" ] || [ "$url" = "$ACME_REVOKE_CERT" ]; then + if [ "$url" = "$ACME_NEW_ACCOUNT" ]; then + protected="$JWK_HEADERPLACE_PART1$nonce\", \"url\": \"${url}$JWK_HEADERPLACE_PART2, \"jwk\": $jwk"'}' + elif [ "$url" = "$ACME_REVOKE_CERT" ] && [ "$keyfile" != "$ACCOUNT_KEY_PATH" ]; then protected="$JWK_HEADERPLACE_PART1$nonce\", \"url\": \"${url}$JWK_HEADERPLACE_PART2, \"jwk\": $jwk"'}' else protected="$JWK_HEADERPLACE_PART1$nonce\", \"url\": \"${url}$JWK_HEADERPLACE_PART2, \"kid\": \"${ACCOUNT_URL}\""'}' From 63031fb278f8a627351d633a295d39432cb47b30 Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Tue, 19 May 2020 20:04:23 +0200 Subject: [PATCH 082/161] bugfixes --- acme.sh | 2 +- dnsapi/dns_transip.sh | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index d3c357fc..8a29cebf 100755 --- a/acme.sh +++ b/acme.sh @@ -1003,7 +1003,7 @@ _sign() { _sign_openssl="${ACME_OPENSSL_BIN:-openssl} dgst -sign $keyfile " - if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; || if grep "BEGIN PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then + if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1 || grep "BEGIN PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then $_sign_openssl -$alg | _base64 elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then if ! _signedECText="$($_sign_openssl -sha$__ECC_KEY_LEN | ${ACME_OPENSSL_BIN:-openssl} asn1parse -inform DER)"; then diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh index 8764c1c4..36c48ce3 100644 --- a/dnsapi/dns_transip.sh +++ b/dnsapi/dns_transip.sh @@ -94,6 +94,10 @@ _transip_rest() { _transip_get_token() { nonce=$(echo "TRANSIP$(_time)" | _digest sha1 hex) + nonce_old=$(openssl rand -hex 12) + nonce=${nonce:0:32} + _debug nonce "$nonce" + _debug nonce_old "$nonce_old" data="{\"login\":\"${TRANSIP_Username}\",\"nonce\":\"${nonce}\",\"read_only\":\"${TRANSIP_Token_Read_Only}\",\"expiration_time\":\"${TRANSIP_Token_Expiration}\",\"label\":\"${TRANSIP_Token_Label}\",\"global_key\":\"${TRANSIP_Token_Global_Key}\"}" _debug data "$data" From 70619dd0b77f33ad2358b8adcde9aee555c8e44b Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Tue, 19 May 2020 20:07:14 +0200 Subject: [PATCH 083/161] Remove debugging --- dnsapi/dns_transip.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh index 36c48ce3..2b1d2284 100644 --- a/dnsapi/dns_transip.sh +++ b/dnsapi/dns_transip.sh @@ -94,10 +94,8 @@ _transip_rest() { _transip_get_token() { nonce=$(echo "TRANSIP$(_time)" | _digest sha1 hex) - nonce_old=$(openssl rand -hex 12) nonce=${nonce:0:32} _debug nonce "$nonce" - _debug nonce_old "$nonce_old" data="{\"login\":\"${TRANSIP_Username}\",\"nonce\":\"${nonce}\",\"read_only\":\"${TRANSIP_Token_Read_Only}\",\"expiration_time\":\"${TRANSIP_Token_Expiration}\",\"label\":\"${TRANSIP_Token_Label}\",\"global_key\":\"${TRANSIP_Token_Global_Key}\"}" _debug data "$data" From 063562261e97e435e73a05ccfe7340c36b10d512 Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Tue, 19 May 2020 23:09:16 +0200 Subject: [PATCH 084/161] Fix string truncation for POSIX --- dnsapi/dns_transip.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dnsapi/dns_transip.sh b/dnsapi/dns_transip.sh index 2b1d2284..23debe0d 100644 --- a/dnsapi/dns_transip.sh +++ b/dnsapi/dns_transip.sh @@ -93,8 +93,7 @@ _transip_rest() { } _transip_get_token() { - nonce=$(echo "TRANSIP$(_time)" | _digest sha1 hex) - nonce=${nonce:0:32} + nonce=$(echo "TRANSIP$(_time)" | _digest sha1 hex | cut -c 1-32) _debug nonce "$nonce" data="{\"login\":\"${TRANSIP_Username}\",\"nonce\":\"${nonce}\",\"read_only\":\"${TRANSIP_Token_Read_Only}\",\"expiration_time\":\"${TRANSIP_Token_Expiration}\",\"label\":\"${TRANSIP_Token_Label}\",\"global_key\":\"${TRANSIP_Token_Global_Key}\"}" From 59fd48cfe27219af0737b0735f66a35f209a2042 Mon Sep 17 00:00:00 2001 From: neil Date: Tue, 19 May 2020 22:34:19 +0800 Subject: [PATCH 085/161] support Retry-After header https://github.com/acmesh-official/acme.sh/issues/2939 --- acme.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/acme.sh b/acme.sh index 48c71df3..419e23df 100755 --- a/acme.sh +++ b/acme.sh @@ -4517,6 +4517,12 @@ $_authorizations_map" _info "Pending" elif [ "$status" = "processing" ]; then _info "Processing" + _retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *:" | cut -d : -f 2 | tr -d ' ') + _debug "_retryafter" "$_retryafter" + if [ "$_retryafter" ]; then + _info "Retry after: $_retryafter" + _sleep $_retryafter + fi else _err "$d:Verify error:$response" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" From a78a09f594936b503823c99f180acea79ba6355a Mon Sep 17 00:00:00 2001 From: PM Extra Date: Thu, 14 May 2020 17:15:31 +0800 Subject: [PATCH 086/161] Support multiple servers for SSH deployment. --- deploy/ssh.sh | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/deploy/ssh.sh b/deploy/ssh.sh index d71637a1..06d4b2b4 100644 --- a/deploy/ssh.sh +++ b/deploy/ssh.sh @@ -33,10 +33,7 @@ ssh_deploy() { _ccert="$3" _cca="$4" _cfullchain="$5" - _err_code=0 - _cmdstr="" - _backupprefix="" - _backupdir="" + _deploy_ssh_servers="" if [ -f "$DOMAIN_CONF" ]; then # shellcheck disable=SC1090 @@ -102,6 +99,18 @@ ssh_deploy() { _cleardomainconf Le_Deploy_ssh_multi_call fi + _deploy_ssh_servers=$Le_Deploy_ssh_server + for Le_Deploy_ssh_server in $_deploy_ssh_servers; do + _ssh_deploy + done +} + +_ssh_deploy() { + _err_code=0 + _cmdstr="" + _backupprefix="" + _backupdir="" + _info "Deploy certificates to remote server $Le_Deploy_ssh_user@$Le_Deploy_ssh_server" if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then _info "Using MULTI_CALL mode... Required commands sent in multiple calls to remote host" From 427c278012cb40e9b5d5fb11f46b704941f33605 Mon Sep 17 00:00:00 2001 From: Dan Dascalescu Date: Fri, 22 May 2020 10:28:29 -0700 Subject: [PATCH 087/161] Fix sloppy English --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 419e23df..5539b32c 100755 --- a/acme.sh +++ b/acme.sh @@ -4299,7 +4299,7 @@ $_authorizations_map" if [ "$dns_entries" ]; then if [ -z "$Le_DNSSleep" ]; then - _info "Let's check each dns records now. Sleep 20 seconds first." + _info "Let's check each DNS record now. Sleep 20 seconds first." _sleep 20 if ! _check_dns_entries; then _err "check dns error." From e8defd821a9d6f838ea1591d8c719db879a726c8 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 23 May 2020 20:37:06 +0800 Subject: [PATCH 088/161] update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 249dc85f..d27a024e 100644 --- a/README.md +++ b/README.md @@ -246,7 +246,7 @@ More examples: https://github.com/acmesh-official/acme.sh/wiki/How-to-issue-a-ce **(requires you to be root/sudoer, since it is required to interact with Apache server)** -If you are running a web server, Apache or Nginx, it is recommended to use the `Webroot mode`. +If you are running a web server, it is recommended to use the `Webroot mode`. Particularly, if you are running an Apache server, you can use Apache mode instead. This mode doesn't write any files to your web root folder. @@ -266,7 +266,7 @@ More examples: https://github.com/acmesh-official/acme.sh/wiki/How-to-issue-a-ce **(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`. +If you are running a web server, 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. From 15dded712c6c255715887be7ee5b29775257c18b Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 24 May 2020 18:04:47 +0800 Subject: [PATCH 089/161] fix retry https://github.com/acmesh-official/acme.sh/issues/2939#issuecomment-632481658 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 5539b32c..682456a1 100755 --- a/acme.sh +++ b/acme.sh @@ -4517,7 +4517,7 @@ $_authorizations_map" _info "Pending" elif [ "$status" = "processing" ]; then _info "Processing" - _retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *:" | cut -d : -f 2 | tr -d ' ') + _retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *:" | cut -d : -f 2 | tr -d ' ' | tr -d '\r') _debug "_retryafter" "$_retryafter" if [ "$_retryafter" ]; then _info "Retry after: $_retryafter" From 0ab14399ae1863e949639f78e5b3ac60501c9e46 Mon Sep 17 00:00:00 2001 From: DerVerruckteFuchs Date: Mon, 25 May 2020 12:00:54 -0400 Subject: [PATCH 090/161] Fix broken grep so that One984HOSTING_COOKIE actually gets set, and isn't left empty. --- dnsapi/dns_1984hosting.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_1984hosting.sh b/dnsapi/dns_1984hosting.sh index b7cb36d7..d84ea1f7 100755 --- a/dnsapi/dns_1984hosting.sh +++ b/dnsapi/dns_1984hosting.sh @@ -168,7 +168,7 @@ _1984hosting_login() { _debug2 response "$response" if [ "$response" = '{"loggedin": true, "ok": true}' ]; then - One984HOSTING_COOKIE="$(grep '^Set-Cookie:' "$HTTP_HEADER" | _tail_n 1 | _egrep_o 'sessionid=[^;]*;' | tr -d ';')" + One984HOSTING_COOKIE="$(grep '^set-cookie:' "$HTTP_HEADER" | _tail_n 1 | _egrep_o 'sessionid=[^;]*;' | tr -d ';')" export One984HOSTING_COOKIE _saveaccountconf_mutable One984HOSTING_COOKIE "$One984HOSTING_COOKIE" return 0 From 1fe8235a85821561ca49e3c563410870b81ea4ca Mon Sep 17 00:00:00 2001 From: grindsa Date: Mon, 25 May 2020 20:28:05 +0200 Subject: [PATCH 091/161] Update acme.sh --- acme.sh | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/acme.sh b/acme.sh index 682456a1..0e3110a6 100755 --- a/acme.sh +++ b/acme.sh @@ -4517,12 +4517,6 @@ $_authorizations_map" _info "Pending" elif [ "$status" = "processing" ]; then _info "Processing" - _retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *:" | cut -d : -f 2 | tr -d ' ' | tr -d '\r') - _debug "_retryafter" "$_retryafter" - if [ "$_retryafter" ]; then - _info "Retry after: $_retryafter" - _sleep $_retryafter - fi else _err "$d:Verify error:$response" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" @@ -4574,7 +4568,14 @@ $_authorizations_map" break elif _contains "$response" "\"processing\""; then _info "Order status is processing, lets sleep and retry." - _sleep 2 + _retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *:" | cut -d : -f 2 | tr -d ' ' | tr -d '\r') + _debug "_retryafter" "$_retryafter" + if [ "$_retryafter" ]; then + _info "Retry after: $_retryafter" + _sleep $_retryafter + else + _sleep 2 + fi else _err "Sign error, wrong status" _err "$response" From 025da9245039d897a46edbcb74604c029da08f91 Mon Sep 17 00:00:00 2001 From: DerVerruckteFuchs Date: Tue, 26 May 2020 02:00:05 -0400 Subject: [PATCH 092/161] Handle case insensitivity for HTTP/1.1 headers. --- dnsapi/dns_1984hosting.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_1984hosting.sh b/dnsapi/dns_1984hosting.sh index d84ea1f7..09f02796 100755 --- a/dnsapi/dns_1984hosting.sh +++ b/dnsapi/dns_1984hosting.sh @@ -168,7 +168,7 @@ _1984hosting_login() { _debug2 response "$response" if [ "$response" = '{"loggedin": true, "ok": true}' ]; then - One984HOSTING_COOKIE="$(grep '^set-cookie:' "$HTTP_HEADER" | _tail_n 1 | _egrep_o 'sessionid=[^;]*;' | tr -d ';')" + One984HOSTING_COOKIE="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _tail_n 1 | _egrep_o 'sessionid=[^;]*;' | tr -d ';')" export One984HOSTING_COOKIE _saveaccountconf_mutable One984HOSTING_COOKIE "$One984HOSTING_COOKIE" return 0 From f03904ebceaf77cede8bd99bee2917a334095751 Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Tue, 9 Jun 2020 09:57:36 +0200 Subject: [PATCH 093/161] change to --output QUIET --- dnsapi/dns_lexicon.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_lexicon.sh b/dnsapi/dns_lexicon.sh index 34a95599..44bfa735 100755 --- a/dnsapi/dns_lexicon.sh +++ b/dnsapi/dns_lexicon.sh @@ -92,7 +92,7 @@ dns_lexicon_add() { _savedomainconf LEXICON_OPTS "$LEXICON_OPTS" # shellcheck disable=SC2086 - $lexicon_cmd "$PROVIDER" $LEXICON_OPTS create "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}" >/dev/null + $lexicon_cmd "$PROVIDER" $LEXICON_OPTS create "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}" --output QUIET } @@ -108,6 +108,6 @@ dns_lexicon_rm() { domain=$(printf "%s" "$fulldomain" | cut -d . -f 2-999) # shellcheck disable=SC2086 - $lexicon_cmd "$PROVIDER" $LEXICON_OPTS delete "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}" >/dev/null + $lexicon_cmd "$PROVIDER" $LEXICON_OPTS delete "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}" --output QUIET } From e9edecf34ab828ee257a0c0563969329d437e4e0 Mon Sep 17 00:00:00 2001 From: msamoylych Date: Wed, 24 Jun 2020 12:25:23 +0300 Subject: [PATCH 094/161] Update dns_hexonet.sh Remove useless & --- dnsapi/dns_hexonet.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_hexonet.sh b/dnsapi/dns_hexonet.sh index f1503118..a8ffd3d1 100755 --- a/dnsapi/dns_hexonet.sh +++ b/dnsapi/dns_hexonet.sh @@ -42,7 +42,7 @@ dns_hexonet_add() { _debug _domain "$_domain" _debug "Getting txt records" - _hexonet_rest "&command=QueryDNSZoneRRList&dnszone=${h}.&RRTYPE=TXT" + _hexonet_rest "command=QueryDNSZoneRRList&dnszone=${h}.&RRTYPE=TXT" if ! _contains "$response" "CODE=200"; then _err "Error" @@ -88,7 +88,7 @@ dns_hexonet_rm() { _debug _domain "$_domain" _debug "Getting txt records" - _hexonet_rest "&command=QueryDNSZoneRRList&dnszone=${h}.&RRTYPE=TXT&RR=${txtvalue}" + _hexonet_rest "command=QueryDNSZoneRRList&dnszone=${h}.&RRTYPE=TXT&RR=${txtvalue}" if ! _contains "$response" "CODE=200"; then _err "Error" @@ -100,7 +100,7 @@ dns_hexonet_rm() { if [ "$count" = "0" ]; then _info "Don't need to remove." else - if ! _hexonet_rest "&command=UpdateDNSZone&dnszone=${_domain}.&delrr0='${_sub_domain}%20IN%20TXT%20\"${txtvalue}\""; then + if ! _hexonet_rest "command=UpdateDNSZone&dnszone=${_domain}.&delrr0='${_sub_domain}%20IN%20TXT%20\"${txtvalue}\""; then _err "Delete record error." return 1 fi @@ -126,7 +126,7 @@ _get_root() { return 1 fi - if ! _hexonet_rest "&command=QueryDNSZoneRRList&dnszone=${h}."; then + if ! _hexonet_rest "command=QueryDNSZoneRRList&dnszone=${h}."; then return 1 fi From a9d46297c402e93bb286083840f84514ab9f7c74 Mon Sep 17 00:00:00 2001 From: msamoylych Date: Wed, 24 Jun 2020 12:26:11 +0300 Subject: [PATCH 095/161] Update dns_hexonet.sh Fix removing DNS records --- dnsapi/dns_hexonet.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_hexonet.sh b/dnsapi/dns_hexonet.sh index a8ffd3d1..525efe73 100755 --- a/dnsapi/dns_hexonet.sh +++ b/dnsapi/dns_hexonet.sh @@ -88,7 +88,7 @@ dns_hexonet_rm() { _debug _domain "$_domain" _debug "Getting txt records" - _hexonet_rest "command=QueryDNSZoneRRList&dnszone=${h}.&RRTYPE=TXT&RR=${txtvalue}" + _hexonet_rest "command=QueryDNSZoneRRList&dnszone=${h}.&RRTYPE=TXT&RR=${_sub_domain}%20IN%20TXT%20\"${txtvalue}\"" if ! _contains "$response" "CODE=200"; then _err "Error" @@ -100,7 +100,7 @@ dns_hexonet_rm() { if [ "$count" = "0" ]; then _info "Don't need to remove." else - if ! _hexonet_rest "command=UpdateDNSZone&dnszone=${_domain}.&delrr0='${_sub_domain}%20IN%20TXT%20\"${txtvalue}\""; then + if ! _hexonet_rest "command=UpdateDNSZone&dnszone=${_domain}.&delrr0=${_sub_domain}%20IN%20TXT%20\"${txtvalue}\""; then _err "Delete record error." return 1 fi From eca57beec178f39db00175ba63c3b0728a48d5ad Mon Sep 17 00:00:00 2001 From: Tony Gravagno Date: Mon, 29 Jun 2020 11:29:10 -0700 Subject: [PATCH 096/161] Issue #2850 : grammar corrections for "exists" and "exist". --- acme.sh | 10 +++++----- deploy/kong.sh | 4 ++-- dnsapi/dns_ali.sh | 1 + dnsapi/dns_dgon.sh | 4 ++-- dnsapi/dns_dynv6.sh | 4 ++-- dnsapi/dns_gd.sh | 2 +- dnsapi/dns_hetzner.sh | 2 +- dnsapi/dns_kinghost.sh | 2 +- 8 files changed, 15 insertions(+), 14 deletions(-) diff --git a/acme.sh b/acme.sh index 0e3110a6..9b67b9f7 100755 --- a/acme.sh +++ b/acme.sh @@ -188,28 +188,28 @@ _dlg_versions() { if _exists "${ACME_OPENSSL_BIN:-openssl}"; then ${ACME_OPENSSL_BIN:-openssl} version 2>&1 else - echo "$ACME_OPENSSL_BIN doesn't exists." + echo "$ACME_OPENSSL_BIN doesn't exist." fi echo "apache:" if [ "$_APACHECTL" ] && _exists "$_APACHECTL"; then $_APACHECTL -V 2>&1 else - echo "apache doesn't exists." + echo "apache doesn't exist." fi echo "nginx:" if _exists "nginx"; then nginx -V 2>&1 else - echo "nginx doesn't exists." + echo "nginx doesn't exist." fi echo "socat:" if _exists "socat"; then socat -V 2>&1 else - _debug "socat doesn't exists." + _debug "socat doesn't exist." fi } @@ -5519,7 +5519,7 @@ revoke() { fi fi else - _info "Domain key file doesn't exists." + _info "Domain key file doesn't exist." fi _info "Try account key." diff --git a/deploy/kong.sh b/deploy/kong.sh index d3a6bc47..1e1e310c 100755 --- a/deploy/kong.sh +++ b/deploy/kong.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -# If certificate already exist it will update only cert and key not touching other parameter -# If certificate doesn't exist it will only upload cert and key and not set other parameter +# If certificate already exists it will update only cert and key, not touching other parameters +# If certificate doesn't exist it will only upload cert and key, and not set other parameters # Note that we deploy full chain # Written by Geoffroi Genot diff --git a/dnsapi/dns_ali.sh b/dnsapi/dns_ali.sh index 0c2365d7..c2105672 100755 --- a/dnsapi/dns_ali.sh +++ b/dnsapi/dns_ali.sh @@ -181,6 +181,7 @@ _describe_records_query() { _clean() { _check_exist_query "$_domain" "$_sub_domain" + # do not correct grammar here if ! _ali_rest "Check exist records" "ignore"; then return 1 fi diff --git a/dnsapi/dns_dgon.sh b/dnsapi/dns_dgon.sh index c176afd3..515e87d5 100755 --- a/dnsapi/dns_dgon.sh +++ b/dnsapi/dns_dgon.sh @@ -22,7 +22,7 @@ dns_dgon_add() { txtvalue=$2 DO_API_KEY="${DO_API_KEY:-$(_readaccountconf_mutable DO_API_KEY)}" - # Check if API Key Exist + # Check if API Key Exists if [ -z "$DO_API_KEY" ]; then DO_API_KEY="" _err "You did not specify DigitalOcean API key." @@ -77,7 +77,7 @@ dns_dgon_rm() { txtvalue=$2 DO_API_KEY="${DO_API_KEY:-$(_readaccountconf_mutable DO_API_KEY)}" - # Check if API Key Exist + # Check if API Key Exists if [ -z "$DO_API_KEY" ]; then DO_API_KEY="" _err "You did not specify DigitalOcean API key." diff --git a/dnsapi/dns_dynv6.sh b/dnsapi/dns_dynv6.sh index cf39282b..819372c2 100644 --- a/dnsapi/dns_dynv6.sh +++ b/dnsapi/dns_dynv6.sh @@ -18,7 +18,7 @@ dns_dynv6_add() { if ! _contains "$_your_hosts" "$_host"; then _debug "The host is $_host and the record $_record" _debug "Dynv6 returned $_your_hosts" - _err "The host $_host does not exists on your dynv6 account" + _err "The host $_host does not exist on your dynv6 account" return 1 fi _debug "found host on your account" @@ -49,7 +49,7 @@ dns_dynv6_rm() { if ! _contains "$_your_hosts" "$_host"; then _debug "The host is $_host and the record $_record" _debug "Dynv6 returned $_your_hosts" - _err "The host $_host does not exists on your dynv6 account" + _err "The host $_host does not exist on your dynv6 account" return 1 fi _debug "found host on your account" diff --git a/dnsapi/dns_gd.sh b/dnsapi/dns_gd.sh index 7cf47386..7f8efca9 100755 --- a/dnsapi/dns_gd.sh +++ b/dnsapi/dns_gd.sh @@ -91,7 +91,7 @@ dns_gd_rm() { fi if ! _contains "$response" "$txtvalue"; then - _info "The record is not existing, skip" + _info "The record does not exist, skip" return 0 fi diff --git a/dnsapi/dns_hetzner.sh b/dnsapi/dns_hetzner.sh index d994d665..5db0418c 100644 --- a/dnsapi/dns_hetzner.sh +++ b/dnsapi/dns_hetzner.sh @@ -155,7 +155,7 @@ _get_root() { if [ "$HETZNER_Zone_ID" ]; then _debug "Found, using: $HETZNER_Zone_ID" if ! _hetzner_rest GET "zones/${HETZNER_Zone_ID}"; then - _debug "Zone with id '$HETZNER_Zone_ID' not exists." + _debug "Zone with id '$HETZNER_Zone_ID' does not exist." _cleardomainconf "$domain_param_name" unset HETZNER_Zone_ID else diff --git a/dnsapi/dns_kinghost.sh b/dnsapi/dns_kinghost.sh index 898ab286..6253c71d 100644 --- a/dnsapi/dns_kinghost.sh +++ b/dnsapi/dns_kinghost.sh @@ -37,7 +37,7 @@ dns_kinghost_add() { _debug "Getting txt records" _kinghost_rest GET "dns" "name=$fulldomain&content=$txtvalue" - #This API call returns "status":"ok" if dns record does not exists + #This API call returns "status":"ok" if dns record does not exist #We are creating a new txt record here, so we expect the "ok" status if ! echo "$response" | grep '"status":"ok"' >/dev/null; then _err "Error" From 94787d537abad243a1a5787326e5fba86c972c06 Mon Sep 17 00:00:00 2001 From: Tony Gravagno Date: Mon, 29 Jun 2020 11:51:55 -0700 Subject: [PATCH 097/161] Issue #2849 Trivial variable name fix from apacheMajer to apacheMajor --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 9b67b9f7..28c39db4 100755 --- a/acme.sh +++ b/acme.sh @@ -2801,10 +2801,10 @@ _setApache() { apacheVer="$($_APACHECTL -V | grep "Server version:" | cut -d : -f 2 | cut -d " " -f 2 | cut -d '/' -f 2)" _debug "apacheVer" "$apacheVer" - apacheMajer="$(echo "$apacheVer" | cut -d . -f 1)" + apacheMajor="$(echo "$apacheVer" | cut -d . -f 1)" apacheMinor="$(echo "$apacheVer" | cut -d . -f 2)" - if [ "$apacheVer" ] && [ "$apacheMajer$apacheMinor" -ge "24" ]; then + if [ "$apacheVer" ] && [ "$apacheMajor$apacheMinor" -ge "24" ]; then echo " Alias /.well-known/acme-challenge $ACME_DIR From 8718ac0c4bf17372e7daff6b93c57cca1001c12a Mon Sep 17 00:00:00 2001 From: Matthew Date: Tue, 30 Jun 2020 02:22:08 -0400 Subject: [PATCH 098/161] duckdns doesn't permit subdomains or underscores --- dnsapi/dns_duckdns.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index 711b81ee..aa7911d3 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -91,13 +91,13 @@ dns_duckdns_rm() { #################### Private functions below ################################## -#fulldomain=_acme-challenge.domain.duckdns.org +#fulldomain=acme-challenge-domain.duckdns.org #returns -# _duckdns_domain=domain +# _duckdns_domain=acme-challenge-domain _duckdns_get_domain() { # We'll extract the domain/username from full domain - _duckdns_domain="$(printf "%s" "$fulldomain" | _lower_case | _egrep_o '[.][^.][^.]*[.]duckdns.org' | cut -d . -f 2)" + _duckdns_domain="$(printf "%s" "$fulldomain" | _lower_case | sed 's/^\([a-z0-9-]*\)\.duckdns\.org/\1/')" if [ -z "$_duckdns_domain" ]; then _err "Error extracting the domain." From 4539d236df65f8cc0592cfbe1f044141c251f270 Mon Sep 17 00:00:00 2001 From: Matthew Date: Tue, 30 Jun 2020 07:19:41 -0400 Subject: [PATCH 099/161] dns_duckdns.sh - correctly extract domain $fulldomain could be just 'domain.duckdns.org' if provided with --domain-alias or '_acme-challenge.domain.duckdns.org' otherwise. In the latter case, '_acme-challenge' is thrown away. Correctly extract 'domain' in both cases. --- dnsapi/dns_duckdns.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index aa7911d3..edfc48b0 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -91,13 +91,12 @@ dns_duckdns_rm() { #################### Private functions below ################################## -#fulldomain=acme-challenge-domain.duckdns.org -#returns -# _duckdns_domain=acme-challenge-domain +# fulldomain may be 'domain.duckdns.org' (if using --domain-alias) or '_acme-challenge.domain.duckdns.org' +# either way, return 'domain'. (duckdns does not allow further subdomains and restricts domains to [a-z0-9-].) _duckdns_get_domain() { # We'll extract the domain/username from full domain - _duckdns_domain="$(printf "%s" "$fulldomain" | _lower_case | sed 's/^\([a-z0-9-]*\)\.duckdns\.org/\1/')" + _duckdns_domain="$(printf "%s" "$fulldomain" | _lower_case | _egrep_o '^(_acme-challenge\.)?[a-z0-9-]*\.duckdns\.org' | sed -E 's/^(_acme-challenge\.)?([a-z0-9-]*)\.duckdns\.org/\2/')" if [ -z "$_duckdns_domain" ]; then _err "Error extracting the domain." From cdf8f78962d45b856b9e28c7e95a3cae37f46cf1 Mon Sep 17 00:00:00 2001 From: Tom Sommer Date: Thu, 2 Jul 2020 09:47:05 +0200 Subject: [PATCH 100/161] unoeuro.com is now simply.com Maintaining the naming of the API (for backwards compatibility), but renaming hostname. --- dnsapi/dns_unoeuro.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_unoeuro.sh b/dnsapi/dns_unoeuro.sh index c4593a63..fb6ba4fd 100644 --- a/dnsapi/dns_unoeuro.sh +++ b/dnsapi/dns_unoeuro.sh @@ -5,7 +5,7 @@ # #UNO_User="UExxxxxx" -Uno_Api="https://api.unoeuro.com/1" +Uno_Api="https://api.simply.com/1" ######## Public functions ##################### From f60356e8c7f1bccc573f30a2cedc33c2d3771e64 Mon Sep 17 00:00:00 2001 From: Tom Sommer Date: Thu, 2 Jul 2020 09:48:05 +0200 Subject: [PATCH 101/161] Username not required to contain "UE" --- dnsapi/dns_unoeuro.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/dnsapi/dns_unoeuro.sh b/dnsapi/dns_unoeuro.sh index fb6ba4fd..13ba8a00 100644 --- a/dnsapi/dns_unoeuro.sh +++ b/dnsapi/dns_unoeuro.sh @@ -24,12 +24,6 @@ dns_unoeuro_add() { return 1 fi - if ! _contains "$UNO_User" "UE"; then - _err "It seems that the UNO_User=$UNO_User is not a valid username." - _err "Please check and retry." - return 1 - fi - #save the api key and email to the account conf file. _saveaccountconf_mutable UNO_Key "$UNO_Key" _saveaccountconf_mutable UNO_User "$UNO_User" From 5d0dde5c154604f6a5420b8e6181573510a5631d Mon Sep 17 00:00:00 2001 From: snv Date: Thu, 2 Jul 2020 12:23:46 +0400 Subject: [PATCH 102/161] main changes --- dnsapi/dns_regru.sh | 67 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 5 deletions(-) diff --git a/dnsapi/dns_regru.sh b/dnsapi/dns_regru.sh index 369f62ad..a952e31f 100644 --- a/dnsapi/dns_regru.sh +++ b/dnsapi/dns_regru.sh @@ -5,7 +5,6 @@ # # REGRU_API_Password="test" # -_domain=$_domain REGRU_API_URL="https://api.reg.ru/api/regru2" @@ -27,10 +26,17 @@ dns_regru_add() { _saveaccountconf_mutable REGRU_API_Username "$REGRU_API_Username" _saveaccountconf_mutable REGRU_API_Password "$REGRU_API_Password" + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _domain "$_domain" + _info "Adding TXT record to ${fulldomain}" - response="$(_get "$REGRU_API_URL/zone/add_txt?input_data={%22username%22:%22${REGRU_API_Username}%22,%22password%22:%22${REGRU_API_Password}%22,%22domains%22:[{%22dname%22:%22${_domain}%22}],%22subdomain%22:%22_acme-challenge%22,%22text%22:%22${txtvalue}%22,%22output_content_type%22:%22plain%22}&input_format=json")" + _regru_rest POST "zone/add_txt" "input_data={%22username%22:%22${REGRU_API_Username}%22,%22password%22:%22${REGRU_API_Password}%22,%22domains%22:[{%22dname%22:%22${_domain}%22}],%22subdomain%22:%22_acme-challenge%22,%22text%22:%22${txtvalue}%22,%22output_content_type%22:%22plain%22}&input_format=json" - if _contains "${response}" 'success'; then + if ! _contains "${response}" 'error'; then return 0 fi _err "Could not create resource record, check logs" @@ -51,13 +57,64 @@ dns_regru_rm() { return 1 fi + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _domain "$_domain" + _info "Deleting resource record $fulldomain" - response="$(_get "$REGRU_API_URL/zone/remove_record?input_data={%22username%22:%22${REGRU_API_Username}%22,%22password%22:%22${REGRU_API_Password}%22,%22domains%22:[{%22dname%22:%22${_domain}%22}],%22subdomain%22:%22_acme-challenge%22,%22content%22:%22${txtvalue}%22,%22record_type%22:%22TXT%22,%22output_content_type%22:%22plain%22}&input_format=json")" + _regru_rest POST "zone/remove_record" "input_data={%22username%22:%22${REGRU_API_Username}%22,%22password%22:%22${REGRU_API_Password}%22,%22domains%22:[{%22dname%22:%22${_domain}%22}],%22subdomain%22:%22_acme-challenge%22,%22content%22:%22${txtvalue}%22,%22record_type%22:%22TXT%22,%22output_content_type%22:%22plain%22}&input_format=json" - if _contains "${response}" 'success'; then + if ! _contains "${response}" 'error'; then return 0 fi _err "Could not delete resource record, check logs" _err "${response}" return 1 } + +#################### Private functions below ################################## +#_acme-challenge.www.domain.com +#returns +# _domain=domain.com +_get_root() { + domain=$1 + + _regru_rest POST "service/get_list" "username=${REGRU_API_Username}&password=${REGRU_API_Password}&output_format=xml&servtype=domain" + domains_list=$(echo "${response}" | grep dname | sed -r "s/.*dname=\"([^\"]+)\".*/\\1/g") + + for ITEM in ${domains_list} + do + case "${domain}" in + *${ITEM}*) + _domain=${ITEM} + return 0 + ;; + esac + done + + return 1 +} + +#returns +# response +_regru_rest() { + m=$1 + ep="$2" + data="$3" + _debug "$ep" + + export _H1="Content-Type: application/x-www-form-urlencoded" + + if [ "$m" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$REGRU_API_URL/$ep" "" "$m")" + else + response="$(_get "$REGRU_API_URL/$ep")" + fi + + _debug2 response "${response}" + return 0 +} \ No newline at end of file From c16757b03abae5ec9f0e8c8b32f2014ff4c56bbe Mon Sep 17 00:00:00 2001 From: snv Date: Thu, 2 Jul 2020 12:59:24 +0400 Subject: [PATCH 103/161] add some debug output and fix data in GET request --- dnsapi/dns_regru.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_regru.sh b/dnsapi/dns_regru.sh index a952e31f..1848480a 100644 --- a/dnsapi/dns_regru.sh +++ b/dnsapi/dns_regru.sh @@ -90,6 +90,7 @@ _get_root() { case "${domain}" in *${ITEM}*) _domain=${ITEM} + _debug _domain "${_domain}" return 0 ;; esac @@ -112,9 +113,9 @@ _regru_rest() { _debug data "$data" response="$(_post "$data" "$REGRU_API_URL/$ep" "" "$m")" else - response="$(_get "$REGRU_API_URL/$ep")" + response="$(_get "$REGRU_API_URL/$ep?$data")" fi - _debug2 response "${response}" + _debug response "${response}" return 0 } \ No newline at end of file From 44b9a8e7ed9a6ba0550d0d54bec4757148cff9a6 Mon Sep 17 00:00:00 2001 From: snv Date: Thu, 2 Jul 2020 13:18:37 +0400 Subject: [PATCH 104/161] fix new line at end of file --- dnsapi/dns_regru.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_regru.sh b/dnsapi/dns_regru.sh index 1848480a..f1a2b5ed 100644 --- a/dnsapi/dns_regru.sh +++ b/dnsapi/dns_regru.sh @@ -118,4 +118,4 @@ _regru_rest() { _debug response "${response}" return 0 -} \ No newline at end of file +} From 21718a69d39106b689faae151dbf7aeb259b5597 Mon Sep 17 00:00:00 2001 From: Matthew Date: Fri, 3 Jul 2020 07:48:38 -0400 Subject: [PATCH 105/161] Update dns_duckdns.sh Don't depend on eregex in sed --- dnsapi/dns_duckdns.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index edfc48b0..11b685c0 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -96,7 +96,7 @@ dns_duckdns_rm() { _duckdns_get_domain() { # We'll extract the domain/username from full domain - _duckdns_domain="$(printf "%s" "$fulldomain" | _lower_case | _egrep_o '^(_acme-challenge\.)?[a-z0-9-]*\.duckdns\.org' | sed -E 's/^(_acme-challenge\.)?([a-z0-9-]*)\.duckdns\.org/\2/')" + _duckdns_domain="$(printf "%s" "$fulldomain" | _lower_case | _egrep_o '^(_acme-challenge\.)?[a-z0-9-]*\.duckdns\.org' | sed 's/^\(_acme-challenge\.\)\?\([a-z0-9-]*\)\.duckdns\.org/\2/')" if [ -z "$_duckdns_domain" ]; then _err "Error extracting the domain." From 1dffaba266b43401f93bfabb37080ea783ca1abf Mon Sep 17 00:00:00 2001 From: neil Date: Tue, 7 Jul 2020 19:58:02 +0800 Subject: [PATCH 106/161] fix format --- dnsapi/dns_regru.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_regru.sh b/dnsapi/dns_regru.sh index f1a2b5ed..1f9eeafe 100644 --- a/dnsapi/dns_regru.sh +++ b/dnsapi/dns_regru.sh @@ -89,10 +89,10 @@ _get_root() { do case "${domain}" in *${ITEM}*) - _domain=${ITEM} - _debug _domain "${_domain}" - return 0 - ;; + _domain=${ITEM} + _debug _domain "${_domain}" + return 0 + ;; esac done From f00e289014e9001a19d44146be8eb8a0e89ff87d Mon Sep 17 00:00:00 2001 From: neil Date: Tue, 7 Jul 2020 20:02:48 +0800 Subject: [PATCH 107/161] fix format --- dnsapi/dns_regru.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dnsapi/dns_regru.sh b/dnsapi/dns_regru.sh index 1f9eeafe..b5729fda 100644 --- a/dnsapi/dns_regru.sh +++ b/dnsapi/dns_regru.sh @@ -85,8 +85,7 @@ _get_root() { _regru_rest POST "service/get_list" "username=${REGRU_API_Username}&password=${REGRU_API_Password}&output_format=xml&servtype=domain" domains_list=$(echo "${response}" | grep dname | sed -r "s/.*dname=\"([^\"]+)\".*/\\1/g") - for ITEM in ${domains_list} - do + for ITEM in ${domains_list}; do case "${domain}" in *${ITEM}*) _domain=${ITEM} From dbc435506c90d5df5a676e39bf1ad1225e8975e4 Mon Sep 17 00:00:00 2001 From: Licaon_Kter Date: Tue, 7 Jul 2020 12:06:37 +0000 Subject: [PATCH 108/161] Fix typo candindates --- acme.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/acme.sh b/acme.sh index 28c39db4..d9df3a6f 100755 --- a/acme.sh +++ b/acme.sh @@ -4098,17 +4098,17 @@ $_authorizations_map" if [ "$ACME_VERSION" = "2" ]; then _idn_d="$(_idn "$d")" - _candindates="$(echo "$_authorizations_map" | grep -i "^$_idn_d,")" - _debug2 _candindates "$_candindates" - if [ "$(echo "$_candindates" | wc -l)" -gt 1 ]; then - for _can in $_candindates; do + _candidates="$(echo "$_authorizations_map" | grep -i "^$_idn_d,")" + _debug2 _candidates "$_candidates" + if [ "$(echo "$_candidates" | wc -l)" -gt 1 ]; then + for _can in $_candidates; do if _startswith "$(echo "$_can" | tr '.' '|')" "$(echo "$_idn_d" | tr '.' '|'),"; then - _candindates="$_can" + _candidates="$_can" break fi done fi - response="$(echo "$_candindates" | sed "s/$_idn_d,//")" + response="$(echo "$_candidates" | sed "s/$_idn_d,//")" _debug2 "response" "$response" if [ -z "$response" ]; then _err "get to authz error." From dd6c067832383c6b1b0552fe0e6eec404f455d5b Mon Sep 17 00:00:00 2001 From: neil Date: Tue, 7 Jul 2020 20:52:00 +0800 Subject: [PATCH 109/161] fix format --- dnsapi/dns_lexicon.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_lexicon.sh b/dnsapi/dns_lexicon.sh index 44bfa735..19702343 100755 --- a/dnsapi/dns_lexicon.sh +++ b/dnsapi/dns_lexicon.sh @@ -92,7 +92,7 @@ dns_lexicon_add() { _savedomainconf LEXICON_OPTS "$LEXICON_OPTS" # shellcheck disable=SC2086 - $lexicon_cmd "$PROVIDER" $LEXICON_OPTS create "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}" --output QUIET + $lexicon_cmd "$PROVIDER" $LEXICON_OPTS create "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}" --output QUIET } From f02af8d481e0118419f4ac58ee8c006d5d9d4456 Mon Sep 17 00:00:00 2001 From: peterkelm Date: Tue, 7 Jul 2020 22:56:51 +0200 Subject: [PATCH 110/161] Reflect recent Variomedia API changes Spaces were recently removed from the JSON "response" returned by Variomedia's API. --- dnsapi/dns_variomedia.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_variomedia.sh b/dnsapi/dns_variomedia.sh index 729cda5e..a35b8f0f 100644 --- a/dnsapi/dns_variomedia.sh +++ b/dnsapi/dns_variomedia.sh @@ -107,7 +107,7 @@ _get_root() { fi if _startswith "$response" "\{\"data\":"; then - if _contains "$response" "\"id\": \"$h\""; then + if _contains "$response" "\"id\":\"$h\""; then _sub_domain="$(echo "$fulldomain" | sed "s/\\.$h\$//")" _domain=$h return 0 From a3295476828342642ba65111ccd7ec98056b5917 Mon Sep 17 00:00:00 2001 From: grindsa Date: Wed, 8 Jul 2020 11:59:20 +0200 Subject: [PATCH 111/161] prepending for ecc signature leftpadding "0" if _ec_s and _ec_r are to short --- acme.sh | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 28c39db4..eb13f652 100755 --- a/acme.sh +++ b/acme.sh @@ -1014,8 +1014,32 @@ _sign() { fi _debug3 "_signedECText" "$_signedECText" _ec_r="$(echo "$_signedECText" | _head_n 2 | _tail_n 1 | cut -d : -f 4 | tr -d "\r\n")" - _debug3 "_ec_r" "$_ec_r" _ec_s="$(echo "$_signedECText" | _head_n 3 | _tail_n 1 | cut -d : -f 4 | tr -d "\r\n")" + if [ "$__ECC_KEY_LEN" -eq "256" ]; then + while [ "${#_ec_r}" -lt "64" ]; do + _ec_r="0${_ec_r}" + done + while [ "${#_ec_s}" -lt "64" ]; do + _ec_s="0${_ec_s}" + done + fi + if [ "$__ECC_KEY_LEN" -eq "384" ]; then + while [ "${#_ec_r}" -lt "96" ]; do + _ec_r="0${_ec_r}" + done + while [ "${#_ec_s}" -lt "96" ]; do + _ec_s="0${_ec_s}" + done + fi + if [ "$__ECC_KEY_LEN" -eq "512" ]; then + while [ "${#_ec_r}" -lt "132" ]; do + _ec_r="0${_ec_r}" + done + while [ "${#_ec_s}" -lt "132" ]; do + _ec_s="0${_ec_s}" + done + fi + _debug3 "_ec_r" "$_ec_r" _debug3 "_ec_s" "$_ec_s" printf "%s" "$_ec_r$_ec_s" | _h2b | _base64 else From d8042289564c5207fd5fe4170ce49c2bb0d699a0 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 8 Jul 2020 22:22:06 +0800 Subject: [PATCH 112/161] fix https://github.com/acmesh-official/acme.sh/issues/3032 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 5112bf07..f00d03bd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.10 +FROM alpine:3.12 RUN apk update -f \ && apk --no-cache add -f \ From aaca0b6f76c0725b6aa439d8128e5f17af78fa67 Mon Sep 17 00:00:00 2001 From: Vinton Huang Date: Sat, 11 Jul 2020 19:50:16 +0800 Subject: [PATCH 113/161] Update "Tested OS" section of README.md - Update openSUSE build badge file name (opensuse-leap.svg -> opensuse-leap-latest.svg) - Update link target of build badge (letest -> acmetest), for item 1-12, 15, 16, 18, 19, 21 - Update Proxmox document link for 5.2 and later --- README.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index d27a024e..67402f29 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa) # Who: - [FreeBSD.org](https://blog.crashed.org/letsencrypt-in-freebsd-org/) - [ruby-china.org](https://ruby-china.org/topics/31983) -- [Proxmox](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x_and_newer)) +- [Proxmox](https://pve.proxmox.com/wiki/Certificate_Management) - [pfsense](https://github.com/pfsense/FreeBSD-ports/pull/89) - [webfaction](https://community.webfaction.com/questions/19988/using-letsencrypt) - [Loadbalancer.org](https://www.loadbalancer.org/blog/loadbalancer-org-with-lets-encrypt-quick-and-dirty) @@ -46,27 +46,27 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa) | NO | Status| Platform| |----|-------|---------| -|1|[![](https://acmesh-official.github.io/acmetest/status/ubuntu-latest.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Ubuntu -|2|[![](https://acmesh-official.github.io/acmetest/status/debian-latest.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Debian -|3|[![](https://acmesh-official.github.io/acmetest/status/centos-latest.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|CentOS -|4|[![](https://acmesh-official.github.io/acmetest/status/windows-cygwin.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Windows (cygwin with curl, openssl and crontab included) -|5|[![](https://acmesh-official.github.io/acmetest/status/freebsd.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|FreeBSD -|6|[![](https://acmesh-official.github.io/acmetest/status/pfsense.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|pfsense -|7|[![](https://acmesh-official.github.io/acmetest/status/opensuse-leap.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|openSUSE -|8|[![](https://acmesh-official.github.io/acmetest/status/alpine-latest.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Alpine Linux (with curl) -|9|[![](https://acmesh-official.github.io/acmetest/status/archlinux-latest.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Archlinux -|10|[![](https://acmesh-official.github.io/acmetest/status/fedora-latest.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|fedora -|11|[![](https://acmesh-official.github.io/acmetest/status/kalilinux-kali.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Kali Linux -|12|[![](https://acmesh-official.github.io/acmetest/status/oraclelinux-latest.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Oracle Linux -|13|[![](https://acmesh-official.github.io/acmetest/status/proxmox.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Proxmox https://pve.proxmox.com/wiki/HTTPSCertificateConfiguration#Let.27s_Encrypt_using_acme.sh +|1|[![](https://acmesh-official.github.io/acmetest/status/ubuntu-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)| Ubuntu +|2|[![](https://acmesh-official.github.io/acmetest/status/debian-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)| Debian +|3|[![](https://acmesh-official.github.io/acmetest/status/centos-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|CentOS +|4|[![](https://acmesh-official.github.io/acmetest/status/windows-cygwin.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Windows (cygwin with curl, openssl and crontab included) +|5|[![](https://acmesh-official.github.io/acmetest/status/freebsd.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|FreeBSD +|6|[![](https://acmesh-official.github.io/acmetest/status/pfsense.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|pfsense +|7|[![](https://acmesh-official.github.io/acmetest/status/opensuse-leap-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|openSUSE +|8|[![](https://acmesh-official.github.io/acmetest/status/alpine-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Alpine Linux (with curl) +|9|[![](https://acmesh-official.github.io/acmetest/status/archlinux-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Archlinux +|10|[![](https://acmesh-official.github.io/acmetest/status/fedora-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|fedora +|11|[![](https://acmesh-official.github.io/acmetest/status/kalilinux-kali.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Kali Linux +|12|[![](https://acmesh-official.github.io/acmetest/status/oraclelinux-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Oracle Linux +|13|[![](https://acmesh-official.github.io/acmetest/status/proxmox.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Proxmox: See Proxmox VE Wiki. Version [4.x, 5.0, 5.1](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x,_5.0_and_5.1)#Let.27s_Encrypt_using_acme.sh), version [5.2 and up](https://pve.proxmox.com/wiki/Certificate_Management) |14|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111 -|15|[![](https://acmesh-official.github.io/acmetest/status/openbsd.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|OpenBSD -|16|[![](https://acmesh-official.github.io/acmetest/status/mageia.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Mageia +|15|[![](https://acmesh-official.github.io/acmetest/status/openbsd.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|OpenBSD +|16|[![](https://acmesh-official.github.io/acmetest/status/mageia.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Mageia |17|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT) -|18|[![](https://acmesh-official.github.io/acmetest/status/solaris.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|SunOS/Solaris -|19|[![](https://acmesh-official.github.io/acmetest/status/gentoo-stage3-amd64.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|Gentoo Linux +|18|[![](https://acmesh-official.github.io/acmetest/status/solaris.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|SunOS/Solaris +|19|[![](https://acmesh-official.github.io/acmetest/status/gentoo-stage3-amd64.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Gentoo Linux |20|[![Build Status](https://travis-ci.org/acmesh-official/acme.sh.svg?branch=master)](https://travis-ci.org/acmesh-official/acme.sh)|Mac OSX -|21|[![](https://acmesh-official.github.io/acmetest/status/clearlinux-latest.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)|ClearLinux +|21|[![](https://acmesh-official.github.io/acmetest/status/clearlinux-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|ClearLinux For all build statuses, check our [weekly build project](https://github.com/acmesh-official/acmetest): From 01ebb6576d0b77367bd59f78c408832be9b85cc8 Mon Sep 17 00:00:00 2001 From: andrewheberle Date: Mon, 13 Jul 2020 09:31:47 +0800 Subject: [PATCH 114/161] Use base64 for reload Ensure that reload command is encoded with base64 so special characters in command do not wreck config on renewals --- deploy/docker.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/docker.sh b/deploy/docker.sh index 06d79855..451d5d00 100755 --- a/deploy/docker.sh +++ b/deploy/docker.sh @@ -91,7 +91,7 @@ docker_deploy() { _getdeployconf DEPLOY_DOCKER_CONTAINER_RELOAD_CMD _debug2 DEPLOY_DOCKER_CONTAINER_RELOAD_CMD "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD" if [ "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD" ]; then - _savedeployconf DEPLOY_DOCKER_CONTAINER_RELOAD_CMD "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD" + _savedeployconf DEPLOY_DOCKER_CONTAINER_RELOAD_CMD "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD" "base64" fi _cid="$(_get_id "$DEPLOY_DOCKER_CONTAINER_LABEL")" From f80276584f4f1579e8c6736b03ba002460f30cf6 Mon Sep 17 00:00:00 2001 From: robertoetcheverryr Date: Sun, 12 Jul 2020 23:43:03 -0300 Subject: [PATCH 115/161] Added check for Authentication failure in dns_dynu module --- dnsapi/dns_dynu.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dnsapi/dns_dynu.sh b/dnsapi/dns_dynu.sh index 506ef53e..406ef17d 100644 --- a/dnsapi/dns_dynu.sh +++ b/dnsapi/dns_dynu.sh @@ -216,6 +216,10 @@ _dynu_authentication() { _err "Authentication failed." return 1 fi + if _contains "$response" "Authentication Exception"; then + _err "Authentication failed." + return 1 + fi if _contains "$response" "access_token"; then Dynu_Token=$(printf "%s" "$response" | tr -d "{}" | cut -d , -f 1 | cut -d : -f 2 | cut -d '"' -f 2) fi From 6654d7a919686914d1db24e85f020dbdabc8b5ff Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 13 Jul 2020 20:56:58 +0800 Subject: [PATCH 116/161] fix format --- acme.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index 52ea30a5..80aba9ae 100755 --- a/acme.sh +++ b/acme.sh @@ -1018,7 +1018,7 @@ _sign() { if [ "$__ECC_KEY_LEN" -eq "256" ]; then while [ "${#_ec_r}" -lt "64" ]; do _ec_r="0${_ec_r}" - done + done while [ "${#_ec_s}" -lt "64" ]; do _ec_s="0${_ec_s}" done @@ -1026,7 +1026,7 @@ _sign() { if [ "$__ECC_KEY_LEN" -eq "384" ]; then while [ "${#_ec_r}" -lt "96" ]; do _ec_r="0${_ec_r}" - done + done while [ "${#_ec_s}" -lt "96" ]; do _ec_s="0${_ec_s}" done @@ -1034,7 +1034,7 @@ _sign() { if [ "$__ECC_KEY_LEN" -eq "512" ]; then while [ "${#_ec_r}" -lt "132" ]; do _ec_r="0${_ec_r}" - done + done while [ "${#_ec_s}" -lt "132" ]; do _ec_s="0${_ec_s}" done From f31debc09c1e7f727c3cb0dabb7fd58a68275c0b Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 13 Jul 2020 21:03:57 +0800 Subject: [PATCH 117/161] fix format --- acme.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/acme.sh b/acme.sh index 80aba9ae..22eaaa86 100755 --- a/acme.sh +++ b/acme.sh @@ -1017,26 +1017,26 @@ _sign() { _ec_s="$(echo "$_signedECText" | _head_n 3 | _tail_n 1 | cut -d : -f 4 | tr -d "\r\n")" if [ "$__ECC_KEY_LEN" -eq "256" ]; then while [ "${#_ec_r}" -lt "64" ]; do - _ec_r="0${_ec_r}" + _ec_r="0${_ec_r}" done while [ "${#_ec_s}" -lt "64" ]; do - _ec_s="0${_ec_s}" + _ec_s="0${_ec_s}" done fi if [ "$__ECC_KEY_LEN" -eq "384" ]; then while [ "${#_ec_r}" -lt "96" ]; do - _ec_r="0${_ec_r}" + _ec_r="0${_ec_r}" done while [ "${#_ec_s}" -lt "96" ]; do - _ec_s="0${_ec_s}" + _ec_s="0${_ec_s}" done fi if [ "$__ECC_KEY_LEN" -eq "512" ]; then while [ "${#_ec_r}" -lt "132" ]; do - _ec_r="0${_ec_r}" + _ec_r="0${_ec_r}" done while [ "${#_ec_s}" -lt "132" ]; do - _ec_s="0${_ec_s}" + _ec_s="0${_ec_s}" done fi _debug3 "_ec_r" "$_ec_r" From e2a5af1cf7355f0c58d2f64b7c9579a5b6f32dea Mon Sep 17 00:00:00 2001 From: neil Date: Tue, 14 Jul 2020 21:49:50 +0800 Subject: [PATCH 118/161] fix format --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 22eaaa86..f766ef2f 100755 --- a/acme.sh +++ b/acme.sh @@ -1039,7 +1039,7 @@ _sign() { _ec_s="0${_ec_s}" done fi - _debug3 "_ec_r" "$_ec_r" + _debug3 "_ec_r" "$_ec_r" _debug3 "_ec_s" "$_ec_s" printf "%s" "$_ec_r$_ec_s" | _h2b | _base64 else From 236e8cc95c28279d292706358e011f790912e1c2 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 15 Jul 2020 21:30:17 +0800 Subject: [PATCH 119/161] add gitads --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 67402f29..73532c65 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,13 @@ # An ACME Shell script: acme.sh [![Build Status](https://travis-ci.org/acmesh-official/acme.sh.svg?branch=master)](https://travis-ci.org/acmesh-official/acme.sh) [![Join the chat at https://gitter.im/acme-sh/Lobby](https://badges.gitter.im/acme-sh/Lobby.svg)](https://gitter.im/acme-sh/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + + +acme.sh is being sponsored by the following tool; please help to support us by taking a look and signing up to a free trial + GitAds + + + - An ACME protocol client written purely in Shell (Unix shell) language. - Full ACME protocol implementation. - Support ACME v1 and ACME v2 From 5c295254bf73ae551869aede25c710efeabfaacb Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 15 Jul 2020 21:31:14 +0800 Subject: [PATCH 120/161] fix format --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 73532c65..0c69fb44 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ acme.sh is being sponsored by the following tool; please help to support us by taking a look and signing up to a free trial + + GitAds From d94f241d3cccf05589ac69d225b3cd4e442e357b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Sz=C3=A9pe?= Date: Wed, 15 Jul 2020 20:45:11 +0200 Subject: [PATCH 121/161] Upgrade Travis image --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 91da2731..a9785d0c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: shell -dist: trusty +dist: bionic os: - linux From 9b23cd6d1998fada386cb8feeee5e73da578497e Mon Sep 17 00:00:00 2001 From: Andy Botting Date: Mon, 13 Jul 2020 15:53:15 +1000 Subject: [PATCH 122/161] Add OpenStack Barbican deploy support This provider relies on the the python-openstackclient and python-designateclient tools be installed and working, with either password or application credentials loaded in your env. --- deploy/openstack.sh | 262 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 deploy/openstack.sh diff --git a/deploy/openstack.sh b/deploy/openstack.sh new file mode 100644 index 00000000..42cf7848 --- /dev/null +++ b/deploy/openstack.sh @@ -0,0 +1,262 @@ +#!/usr/bin/env sh + +# OpenStack Barbican deploy hook +# +# This requires you to have OpenStackClient and python-barbicanclient +# installed. +# +# You will require Keystone V3 credentials loaded into your environment, which +# could be either password or v3applicationcredential type. +# +# Author: Andy Botting + +openstack_deploy() { + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + + if ! _exists openstack; then + _err "OpenStack client not found" + return 1 + fi + + _openstack_credentials || return $? + + _info "Generate import pkcs12" + _import_pkcs12="$(_mktemp)" + if ! _openstack_to_pkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca"; then + _err "Error creating pkcs12 certificate" + return 1 + fi + _debug _import_pkcs12 "$_import_pkcs12" + _base64_pkcs12=$(_base64 "multiline" < "$_import_pkcs12") + + secretHrefs=$(_openstack_get_secrets) + _debug secretHrefs "$secretHrefs" + _openstack_store_secret || return $? + + if [ -n "$secretHrefs" ]; then + _info "Cleaning up existing secret" + _openstack_delete_secrets || return $? + fi + + _info "Certificate successfully deployed" + return 0 +} + +_openstack_store_secret() { + if ! openstack secret store --name "$_cdomain." -t 'application/octet-stream' -e base64 --payload "$_base64_pkcs12"; then + _err "Failed to create OpenStack secret" + return 1 + fi + return +} + +_openstack_delete_secrets() { + echo "$secretHrefs" | while read -r secretHref; do + _info "Deleting old secret $secretHref" + if ! openstack secret delete "$secretHref"; then + _err "Failed to delete OpenStack secret" + return 1 + fi + done + return +} + +_openstack_get_secrets() { + if ! secretHrefs=$(openstack secret list -f value --name "$_cdomain." | cut -d' ' -f1); then + _err "Failed to list secrets" + return 1 + fi + echo "$secretHrefs" +} + +_openstack_to_pkcs() { + # The existing _toPkcs command can't allow an empty password, due to sh + # -z test, so copied here and forcing the empty password. + _cpfx="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + + ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" -password "pass:" +} + +_openstack_credentials() { + _debug "Check OpenStack credentials" + + # If we have OS_AUTH_URL already set in the environment, then assume we want + # to use those, otherwise use stored credentials + if [ -n "$OS_AUTH_URL" ]; then + _debug "OS_AUTH_URL env var found, using environment" + else + _debug "OS_AUTH_URL not found, loading stored credentials" + OS_AUTH_URL="${OS_AUTH_URL:-$(_readaccountconf_mutable OS_AUTH_URL)}" + OS_IDENTITY_API_VERSION="${OS_IDENTITY_API_VERSION:-$(_readaccountconf_mutable OS_IDENTITY_API_VERSION)}" + OS_AUTH_TYPE="${OS_AUTH_TYPE:-$(_readaccountconf_mutable OS_AUTH_TYPE)}" + OS_APPLICATION_CREDENTIAL_ID="${OS_APPLICATION_CREDENTIAL_ID:-$(_readaccountconf_mutable OS_APPLICATION_CREDENTIAL_ID)}" + OS_APPLICATION_CREDENTIAL_SECRET="${OS_APPLICATION_CREDENTIAL_SECRET:-$(_readaccountconf_mutable OS_APPLICATION_CREDENTIAL_SECRET)}" + OS_USERNAME="${OS_USERNAME:-$(_readaccountconf_mutable OS_USERNAME)}" + OS_PASSWORD="${OS_PASSWORD:-$(_readaccountconf_mutable OS_PASSWORD)}" + OS_PROJECT_NAME="${OS_PROJECT_NAME:-$(_readaccountconf_mutable OS_PROJECT_NAME)}" + OS_PROJECT_ID="${OS_PROJECT_ID:-$(_readaccountconf_mutable OS_PROJECT_ID)}" + OS_USER_DOMAIN_NAME="${OS_USER_DOMAIN_NAME:-$(_readaccountconf_mutable OS_USER_DOMAIN_NAME)}" + OS_USER_DOMAIN_ID="${OS_USER_DOMAIN_ID:-$(_readaccountconf_mutable OS_USER_DOMAIN_ID)}" + OS_PROJECT_DOMAIN_NAME="${OS_PROJECT_DOMAIN_NAME:-$(_readaccountconf_mutable OS_PROJECT_DOMAIN_NAME)}" + OS_PROJECT_DOMAIN_ID="${OS_PROJECT_DOMAIN_ID:-$(_readaccountconf_mutable OS_PROJECT_DOMAIN_ID)}" + fi + + # Check each var and either save or clear it depending on whether its set. + # The helps us clear out old vars in the case where a user may want + # to switch between password and app creds + _debug "OS_AUTH_URL" "$OS_AUTH_URL" + if [ -n "$OS_AUTH_URL" ]; then + export OS_AUTH_URL + _saveaccountconf_mutable OS_AUTH_URL "$OS_AUTH_URL" + else + unset OS_AUTH_URL + _clearaccountconf SAVED_OS_AUTH_URL + fi + + _debug "OS_IDENTITY_API_VERSION" "$OS_IDENTITY_API_VERSION" + if [ -n "$OS_IDENTITY_API_VERSION" ]; then + export OS_IDENTITY_API_VERSION + _saveaccountconf_mutable OS_IDENTITY_API_VERSION "$OS_IDENTITY_API_VERSION" + else + unset OS_IDENTITY_API_VERSION + _clearaccountconf SAVED_OS_IDENTITY_API_VERSION + fi + + _debug "OS_AUTH_TYPE" "$OS_AUTH_TYPE" + if [ -n "$OS_AUTH_TYPE" ]; then + export OS_AUTH_TYPE + _saveaccountconf_mutable OS_AUTH_TYPE "$OS_AUTH_TYPE" + else + unset OS_AUTH_TYPE + _clearaccountconf SAVED_OS_AUTH_TYPE + fi + + _debug "OS_APPLICATION_CREDENTIAL_ID" "$OS_APPLICATION_CREDENTIAL_ID" + if [ -n "$OS_APPLICATION_CREDENTIAL_ID" ]; then + export OS_APPLICATION_CREDENTIAL_ID + _saveaccountconf_mutable OS_APPLICATION_CREDENTIAL_ID "$OS_APPLICATION_CREDENTIAL_ID" + else + unset OS_APPLICATION_CREDENTIAL_ID + _clearaccountconf SAVED_OS_APPLICATION_CREDENTIAL_ID + fi + + _secure_debug "OS_APPLICATION_CREDENTIAL_SECRET" "$OS_APPLICATION_CREDENTIAL_SECRET" + if [ -n "$OS_APPLICATION_CREDENTIAL_SECRET" ]; then + export OS_APPLICATION_CREDENTIAL_SECRET + _saveaccountconf_mutable OS_APPLICATION_CREDENTIAL_SECRET "$OS_APPLICATION_CREDENTIAL_SECRET" + else + unset OS_APPLICATION_CREDENTIAL_SECRET + _clearaccountconf SAVED_OS_APPLICATION_CREDENTIAL_SECRET + fi + + _debug "OS_USERNAME" "$OS_USERNAME" + if [ -n "$OS_USERNAME" ]; then + export OS_USERNAME + _saveaccountconf_mutable OS_USERNAME "$OS_USERNAME" + else + unset OS_USERNAME + _clearaccountconf SAVED_OS_USERNAME + fi + + _secure_debug "OS_PASSWORD" "$OS_PASSWORD" + if [ -n "$OS_PASSWORD" ]; then + export OS_PASSWORD + _saveaccountconf_mutable OS_PASSWORD "$OS_PASSWORD" + else + unset OS_PASSWORD + _clearaccountconf SAVED_OS_PASSWORD + fi + + _debug "OS_PROJECT_NAME" "$OS_PROJECT_NAME" + if [ -n "$OS_PROJECT_NAME" ]; then + export OS_PROJECT_NAME + _saveaccountconf_mutable OS_PROJECT_NAME "$OS_PROJECT_NAME" + else + unset OS_PROJECT_NAME + _clearaccountconf SAVED_OS_PROJECT_NAME + fi + + _debug "OS_PROJECT_ID" "$OS_PROJECT_ID" + if [ -n "$OS_PROJECT_ID" ]; then + export OS_PROJECT_ID + _saveaccountconf_mutable OS_PROJECT_ID "$OS_PROJECT_ID" + else + unset OS_PROJECT_ID + _clearaccountconf SAVED_OS_PROJECT_ID + fi + + _debug "OS_USER_DOMAIN_NAME" "$OS_USER_DOMAIN_NAME" + if [ -n "$OS_USER_DOMAIN_NAME" ]; then + export OS_USER_DOMAIN_NAME + _saveaccountconf_mutable OS_USER_DOMAIN_NAME "$OS_USER_DOMAIN_NAME" + else + unset OS_USER_DOMAIN_NAME + _clearaccountconf SAVED_OS_USER_DOMAIN_NAME + fi + + _debug "OS_USER_DOMAIN_ID" "$OS_USER_DOMAIN_ID" + if [ -n "$OS_USER_DOMAIN_ID" ]; then + export OS_USER_DOMAIN_ID + _saveaccountconf_mutable OS_USER_DOMAIN_ID "$OS_USER_DOMAIN_ID" + else + unset OS_USER_DOMAIN_ID + _clearaccountconf SAVED_OS_USER_DOMAIN_ID + fi + + _debug "OS_PROJECT_DOMAIN_NAME" "$OS_PROJECT_DOMAIN_NAME" + if [ -n "$OS_PROJECT_DOMAIN_NAME" ]; then + export OS_PROJECT_DOMAIN_NAME + _saveaccountconf_mutable OS_PROJECT_DOMAIN_NAME "$OS_PROJECT_DOMAIN_NAME" + else + unset OS_PROJECT_DOMAIN_NAME + _clearaccountconf SAVED_OS_PROJECT_DOMAIN_NAME + fi + + _debug "OS_PROJECT_DOMAIN_ID" "$OS_PROJECT_DOMAIN_ID" + if [ -n "$OS_PROJECT_DOMAIN_ID" ]; then + export OS_PROJECT_DOMAIN_ID + _saveaccountconf_mutable OS_PROJECT_DOMAIN_ID "$OS_PROJECT_DOMAIN_ID" + else + unset OS_PROJECT_DOMAIN_ID + _clearaccountconf SAVED_OS_PROJECT_DOMAIN_ID + fi + + if [ "$OS_AUTH_TYPE" = "v3applicationcredential" ]; then + # Application Credential auth + if [ -z "$OS_APPLICATION_CREDENTIAL_ID" ] || [ -z "$OS_APPLICATION_CREDENTIAL_SECRET" ]; then + _err "When using OpenStack application credentials, OS_APPLICATION_CREDENTIAL_ID" + _err "and OS_APPLICATION_CREDENTIAL_SECRET must be set." + _err "Please check your credentials and try again." + return 1 + fi + else + # Password auth + if [ -z "$OS_USERNAME" ] || [ -z "$OS_PASSWORD" ]; then + _err "OpenStack username or password not found." + _err "Please check your credentials and try again." + return 1 + fi + + if [ -z "$OS_PROJECT_NAME" ] && [ -z "$OS_PROJECT_ID" ]; then + _err "When using password authentication, OS_PROJECT_NAME or" + _err "OS_PROJECT_ID must be set." + _err "Please check your credentials and try again." + return 1 + fi + fi + + return 0 +} From aad9afad59fc5efd1c4da2de731324041de4ae76 Mon Sep 17 00:00:00 2001 From: Andy Botting Date: Mon, 13 Jul 2020 13:18:57 +1000 Subject: [PATCH 123/161] Add OpenStack Designate DNS API support This provider relies on the the python-openstackclient and python-designateclient tools be installed and working, with either password or application credentials loaded in your env. --- dnsapi/openstack.sh | 348 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 348 insertions(+) create mode 100755 dnsapi/openstack.sh diff --git a/dnsapi/openstack.sh b/dnsapi/openstack.sh new file mode 100755 index 00000000..38619e6f --- /dev/null +++ b/dnsapi/openstack.sh @@ -0,0 +1,348 @@ +#!/usr/bin/env sh + +# OpenStack Designate API plugin +# +# This requires you to have OpenStackClient and python-desginateclient +# installed. +# +# You will require Keystone V3 credentials loaded into your environment, which +# could be either password or v3applicationcredential type. +# +# Author: Andy Botting + +######## Public functions ##################### + +# Usage: dns_openstack_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_openstack_add() { + fulldomain=$1 + txtvalue=$2 + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + _dns_openstack_credentials || return $? + _dns_openstack_check_setup || return $? + _dns_openstack_find_zone || return $? + _dns_openstack_get_recordset || return $? + _debug _recordset_id "$_recordset_id" + if [ -n "$_recordset_id" ]; then + _dns_openstack_get_records || return $? + _debug _records "$_records" + fi + _dns_openstack_create_recordset || return $? +} + +# Usage: dns_openstack_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +# Remove the txt record after validation. +dns_openstack_rm() { + fulldomain=$1 + txtvalue=$2 + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + _dns_openstack_credentials || return $? + _dns_openstack_check_setup || return $? + _dns_openstack_find_zone || return $? + _dns_openstack_get_recordset || return $? + _debug _recordset_id "$_recordset_id" + if [ -n "$_recordset_id" ]; then + _dns_openstack_get_records || return $? + _debug _records "$_records" + fi + _dns_openstack_delete_recordset || return $? +} + +#################### Private functions below ################################## + +_dns_openstack_create_recordset() { + + if [ -z "$_recordset_id" ]; then + _info "Creating a new recordset" + if ! _recordset_id=$(openstack recordset create -c id -f value --type TXT --record "$txtvalue" "$_zone_id" "$fulldomain."); then + _err "No recordset ID found after create" + return 1 + fi + else + _info "Updating existing recordset" + # Build new list of --record args for update + _record_args="--record $txtvalue" + for _rec in $_records; do + _record_args="$_record_args --record $_rec" + done + # shellcheck disable=SC2086 + if ! _recordset_id=$(openstack recordset set -c id -f value $_record_args "$_zone_id" "$fulldomain."); then + _err "Recordset update failed" + return 1 + fi + fi + + _max_retries=60 + _sleep_sec=5 + _retry_times=0 + while [ "$_retry_times" -lt "$_max_retries" ]; do + _retry_times=$(_math "$_retry_times" + 1) + _debug3 _retry_times "$_retry_times" + + _record_status=$(openstack recordset show -c status -f value "$_zone_id" "$_recordset_id") + _info "Recordset status is $_record_status" + if [ "$_record_status" = "ACTIVE" ]; then + return 0 + elif [ "$_record_status" = "ERROR" ]; then + return 1 + else + _sleep $_sleep_sec + fi + done + + _err "Recordset failed to become ACTIVE" + return 1 +} + +_dns_openstack_delete_recordset() { + + if [ "$_records" = "$txtvalue" ]; then + _info "Only one record found, deleting recordset" + if ! openstack recordset delete "$_zone_id" "$fulldomain." >/dev/null; then + _err "Failed to delete recordset" + return 1 + fi + else + _info "Found existing records, updating recordset" + # Build new list of --record args for update + _record_args="" + for _rec in $_records; do + if [ "$_rec" = "$txtvalue" ]; then + continue + fi + _record_args="$_record_args --record $_rec" + done + # shellcheck disable=SC2086 + if ! openstack recordset set -c id -f value $_record_args "$_zone_id" "$fulldomain." >/dev/null; then + _err "Recordset update failed" + return 1 + fi + fi +} + +_dns_openstack_get_root() { + # Take the full fqdn and strip away pieces until we get an exact zone name + # match. For example, _acme-challenge.something.domain.com might need to go + # into something.domain.com or domain.com + _zone_name=$1 + _zone_list=$2 + while [ "$_zone_name" != "" ]; do + _zone_name="$(echo "$_zone_name" | sed 's/[^.]*\.*//')" + echo "$_zone_list" | while read -r id name; do + if _startswith "$_zone_name." "$name"; then + echo "$id" + fi + done + done | _head_n 1 +} + +_dns_openstack_find_zone() { + if ! _zone_list="$(openstack zone list -c id -c name -f value)"; then + _err "Can't list zones. Check your OpenStack credentials" + return 1 + fi + _debug _zone_list "$_zone_list" + + if ! _zone_id="$(_dns_openstack_get_root "$fulldomain" "$_zone_list")"; then + _err "Can't find a matching zone. Check your OpenStack credentials" + return 1 + fi + _debug _zone_id "$_zone_id" +} + +_dns_openstack_get_records() { + if ! _records=$(openstack recordset show -c records -f value "$_zone_id" "$fulldomain."); then + _err "Failed to get records" + return 1 + fi + return 0 +} + +_dns_openstack_get_recordset() { + if ! _recordset_id=$(openstack recordset list -c id -f value --name "$fulldomain." "$_zone_id"); then + _err "Failed to get recordset" + return 1 + fi + return 0 +} + +_dns_openstack_check_setup() { + if ! _exists openstack; then + _err "OpenStack client not found" + return 1 + fi +} + +_dns_openstack_credentials() { + _debug "Check OpenStack credentials" + + # If we have OS_AUTH_URL already set in the environment, then assume we want + # to use those, otherwise use stored credentials + if [ -n "$OS_AUTH_URL" ]; then + _debug "OS_AUTH_URL env var found, using environment" + else + _debug "OS_AUTH_URL not found, loading stored credentials" + OS_AUTH_URL="${OS_AUTH_URL:-$(_readaccountconf_mutable OS_AUTH_URL)}" + OS_IDENTITY_API_VERSION="${OS_IDENTITY_API_VERSION:-$(_readaccountconf_mutable OS_IDENTITY_API_VERSION)}" + OS_AUTH_TYPE="${OS_AUTH_TYPE:-$(_readaccountconf_mutable OS_AUTH_TYPE)}" + OS_APPLICATION_CREDENTIAL_ID="${OS_APPLICATION_CREDENTIAL_ID:-$(_readaccountconf_mutable OS_APPLICATION_CREDENTIAL_ID)}" + OS_APPLICATION_CREDENTIAL_SECRET="${OS_APPLICATION_CREDENTIAL_SECRET:-$(_readaccountconf_mutable OS_APPLICATION_CREDENTIAL_SECRET)}" + OS_USERNAME="${OS_USERNAME:-$(_readaccountconf_mutable OS_USERNAME)}" + OS_PASSWORD="${OS_PASSWORD:-$(_readaccountconf_mutable OS_PASSWORD)}" + OS_PROJECT_NAME="${OS_PROJECT_NAME:-$(_readaccountconf_mutable OS_PROJECT_NAME)}" + OS_PROJECT_ID="${OS_PROJECT_ID:-$(_readaccountconf_mutable OS_PROJECT_ID)}" + OS_USER_DOMAIN_NAME="${OS_USER_DOMAIN_NAME:-$(_readaccountconf_mutable OS_USER_DOMAIN_NAME)}" + OS_USER_DOMAIN_ID="${OS_USER_DOMAIN_ID:-$(_readaccountconf_mutable OS_USER_DOMAIN_ID)}" + OS_PROJECT_DOMAIN_NAME="${OS_PROJECT_DOMAIN_NAME:-$(_readaccountconf_mutable OS_PROJECT_DOMAIN_NAME)}" + OS_PROJECT_DOMAIN_ID="${OS_PROJECT_DOMAIN_ID:-$(_readaccountconf_mutable OS_PROJECT_DOMAIN_ID)}" + fi + + # Check each var and either save or clear it depending on whether its set. + # The helps us clear out old vars in the case where a user may want + # to switch between password and app creds + _debug "OS_AUTH_URL" "$OS_AUTH_URL" + if [ -n "$OS_AUTH_URL" ]; then + export OS_AUTH_URL + _saveaccountconf_mutable OS_AUTH_URL "$OS_AUTH_URL" + else + unset OS_AUTH_URL + _clearaccountconf SAVED_OS_AUTH_URL + fi + + _debug "OS_IDENTITY_API_VERSION" "$OS_IDENTITY_API_VERSION" + if [ -n "$OS_IDENTITY_API_VERSION" ]; then + export OS_IDENTITY_API_VERSION + _saveaccountconf_mutable OS_IDENTITY_API_VERSION "$OS_IDENTITY_API_VERSION" + else + unset OS_IDENTITY_API_VERSION + _clearaccountconf SAVED_OS_IDENTITY_API_VERSION + fi + + _debug "OS_AUTH_TYPE" "$OS_AUTH_TYPE" + if [ -n "$OS_AUTH_TYPE" ]; then + export OS_AUTH_TYPE + _saveaccountconf_mutable OS_AUTH_TYPE "$OS_AUTH_TYPE" + else + unset OS_AUTH_TYPE + _clearaccountconf SAVED_OS_AUTH_TYPE + fi + + _debug "OS_APPLICATION_CREDENTIAL_ID" "$OS_APPLICATION_CREDENTIAL_ID" + if [ -n "$OS_APPLICATION_CREDENTIAL_ID" ]; then + export OS_APPLICATION_CREDENTIAL_ID + _saveaccountconf_mutable OS_APPLICATION_CREDENTIAL_ID "$OS_APPLICATION_CREDENTIAL_ID" + else + unset OS_APPLICATION_CREDENTIAL_ID + _clearaccountconf SAVED_OS_APPLICATION_CREDENTIAL_ID + fi + + _secure_debug "OS_APPLICATION_CREDENTIAL_SECRET" "$OS_APPLICATION_CREDENTIAL_SECRET" + if [ -n "$OS_APPLICATION_CREDENTIAL_SECRET" ]; then + export OS_APPLICATION_CREDENTIAL_SECRET + _saveaccountconf_mutable OS_APPLICATION_CREDENTIAL_SECRET "$OS_APPLICATION_CREDENTIAL_SECRET" + else + unset OS_APPLICATION_CREDENTIAL_SECRET + _clearaccountconf SAVED_OS_APPLICATION_CREDENTIAL_SECRET + fi + + _debug "OS_USERNAME" "$OS_USERNAME" + if [ -n "$OS_USERNAME" ]; then + export OS_USERNAME + _saveaccountconf_mutable OS_USERNAME "$OS_USERNAME" + else + unset OS_USERNAME + _clearaccountconf SAVED_OS_USERNAME + fi + + _secure_debug "OS_PASSWORD" "$OS_PASSWORD" + if [ -n "$OS_PASSWORD" ]; then + export OS_PASSWORD + _saveaccountconf_mutable OS_PASSWORD "$OS_PASSWORD" + else + unset OS_PASSWORD + _clearaccountconf SAVED_OS_PASSWORD + fi + + _debug "OS_PROJECT_NAME" "$OS_PROJECT_NAME" + if [ -n "$OS_PROJECT_NAME" ]; then + export OS_PROJECT_NAME + _saveaccountconf_mutable OS_PROJECT_NAME "$OS_PROJECT_NAME" + else + unset OS_PROJECT_NAME + _clearaccountconf SAVED_OS_PROJECT_NAME + fi + + _debug "OS_PROJECT_ID" "$OS_PROJECT_ID" + if [ -n "$OS_PROJECT_ID" ]; then + export OS_PROJECT_ID + _saveaccountconf_mutable OS_PROJECT_ID "$OS_PROJECT_ID" + else + unset OS_PROJECT_ID + _clearaccountconf SAVED_OS_PROJECT_ID + fi + + _debug "OS_USER_DOMAIN_NAME" "$OS_USER_DOMAIN_NAME" + if [ -n "$OS_USER_DOMAIN_NAME" ]; then + export OS_USER_DOMAIN_NAME + _saveaccountconf_mutable OS_USER_DOMAIN_NAME "$OS_USER_DOMAIN_NAME" + else + unset OS_USER_DOMAIN_NAME + _clearaccountconf SAVED_OS_USER_DOMAIN_NAME + fi + + _debug "OS_USER_DOMAIN_ID" "$OS_USER_DOMAIN_ID" + if [ -n "$OS_USER_DOMAIN_ID" ]; then + export OS_USER_DOMAIN_ID + _saveaccountconf_mutable OS_USER_DOMAIN_ID "$OS_USER_DOMAIN_ID" + else + unset OS_USER_DOMAIN_ID + _clearaccountconf SAVED_OS_USER_DOMAIN_ID + fi + + _debug "OS_PROJECT_DOMAIN_NAME" "$OS_PROJECT_DOMAIN_NAME" + if [ -n "$OS_PROJECT_DOMAIN_NAME" ]; then + export OS_PROJECT_DOMAIN_NAME + _saveaccountconf_mutable OS_PROJECT_DOMAIN_NAME "$OS_PROJECT_DOMAIN_NAME" + else + unset OS_PROJECT_DOMAIN_NAME + _clearaccountconf SAVED_OS_PROJECT_DOMAIN_NAME + fi + + _debug "OS_PROJECT_DOMAIN_ID" "$OS_PROJECT_DOMAIN_ID" + if [ -n "$OS_PROJECT_DOMAIN_ID" ]; then + export OS_PROJECT_DOMAIN_ID + _saveaccountconf_mutable OS_PROJECT_DOMAIN_ID "$OS_PROJECT_DOMAIN_ID" + else + unset OS_PROJECT_DOMAIN_ID + _clearaccountconf SAVED_OS_PROJECT_DOMAIN_ID + fi + + if [ "$OS_AUTH_TYPE" = "v3applicationcredential" ]; then + # Application Credential auth + if [ -z "$OS_APPLICATION_CREDENTIAL_ID" ] || [ -z "$OS_APPLICATION_CREDENTIAL_SECRET" ]; then + _err "When using OpenStack application credentials, OS_APPLICATION_CREDENTIAL_ID" + _err "and OS_APPLICATION_CREDENTIAL_SECRET must be set." + _err "Please check your credentials and try again." + return 1 + fi + else + # Password auth + if [ -z "$OS_USERNAME" ] || [ -z "$OS_PASSWORD" ]; then + _err "OpenStack username or password not found." + _err "Please check your credentials and try again." + return 1 + fi + + if [ -z "$OS_PROJECT_NAME" ] && [ -z "$OS_PROJECT_ID" ]; then + _err "When using password authentication, OS_PROJECT_NAME or" + _err "OS_PROJECT_ID must be set." + _err "Please check your credentials and try again." + return 1 + fi + fi + + return 0 +} From 3ce967d8e52df4d934fda63363953311f31d3932 Mon Sep 17 00:00:00 2001 From: Andy Botting Date: Thu, 16 Jul 2020 13:53:21 +1000 Subject: [PATCH 124/161] Fix CI test failure for deploy/openstack.sh --- deploy/openstack.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/openstack.sh b/deploy/openstack.sh index 42cf7848..f2058853 100644 --- a/deploy/openstack.sh +++ b/deploy/openstack.sh @@ -37,7 +37,7 @@ openstack_deploy() { return 1 fi _debug _import_pkcs12 "$_import_pkcs12" - _base64_pkcs12=$(_base64 "multiline" < "$_import_pkcs12") + _base64_pkcs12=$(_base64 "multiline" <"$_import_pkcs12") secretHrefs=$(_openstack_get_secrets) _debug secretHrefs "$secretHrefs" From 61613bee98b5d69c054f2842d01b71cb9bf2b890 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Sz=C3=A9pe?= Date: Thu, 16 Jul 2020 06:13:15 +0200 Subject: [PATCH 125/161] Fix SC2230 --- deploy/vault_cli.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/vault_cli.sh b/deploy/vault_cli.sh index 5395d87e..8b854137 100644 --- a/deploy/vault_cli.sh +++ b/deploy/vault_cli.sh @@ -43,7 +43,7 @@ vault_cli_deploy() { return 1 fi - VAULT_CMD=$(which vault) + VAULT_CMD=$(command -v vault) if [ ! $? ]; then _err "cannot find vault binary!" return 1 From fe4111a9f52382b138af2536426dab3c2588b79a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Sz=C3=A9pe?= Date: Thu, 16 Jul 2020 06:14:50 +0200 Subject: [PATCH 126/161] Fix SC2236 --- dnsapi/dns_cloudns.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_cloudns.sh b/dnsapi/dns_cloudns.sh index df824e86..381d17ec 100755 --- a/dnsapi/dns_cloudns.sh +++ b/dnsapi/dns_cloudns.sh @@ -69,7 +69,7 @@ dns_cloudns_rm() { for i in $(echo "$response" | tr '{' "\n" | grep "$record"); do record_id=$(echo "$i" | tr ',' "\n" | grep -E '^"id"' | sed -re 's/^\"id\"\:\"([0-9]+)\"$/\1/g') - if [ ! -z "$record_id" ]; then + if [ -n "$record_id" ]; then _debug zone "$zone" _debug host "$host" _debug record "$record" @@ -91,7 +91,7 @@ dns_cloudns_rm() { #################### Private functions below ################################## _dns_cloudns_init_check() { - if [ ! -z "$CLOUDNS_INIT_CHECK_COMPLETED" ]; then + if [ -n "$CLOUDNS_INIT_CHECK_COMPLETED" ]; then return 0 fi @@ -164,7 +164,7 @@ _dns_cloudns_http_api_call() { _debug CLOUDNS_SUB_AUTH_ID "$CLOUDNS_SUB_AUTH_ID" _debug CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD" - if [ ! -z "$CLOUDNS_SUB_AUTH_ID" ]; then + if [ -n "$CLOUDNS_SUB_AUTH_ID" ]; then auth_user="sub-auth-id=$CLOUDNS_SUB_AUTH_ID" else auth_user="auth-id=$CLOUDNS_AUTH_ID" From 49094120d927d4e846555564fb292212f4899a76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Sz=C3=A9pe?= Date: Thu, 16 Jul 2020 06:17:11 +0200 Subject: [PATCH 127/161] Fix SC2236 --- dnsapi/dns_cyon.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_cyon.sh b/dnsapi/dns_cyon.sh index 8db3011d..2dca90c0 100644 --- a/dnsapi/dns_cyon.sh +++ b/dnsapi/dns_cyon.sh @@ -66,7 +66,7 @@ _cyon_load_credentials() { _debug "Save credentials to account.conf" _saveaccountconf CY_Username "${CY_Username}" _saveaccountconf CY_Password_B64 "$CY_Password_B64" - if [ ! -z "${CY_OTP_Secret}" ]; then + if [ -n "${CY_OTP_Secret}" ]; then _saveaccountconf CY_OTP_Secret "$CY_OTP_Secret" else _clearaccountconf CY_OTP_Secret @@ -164,7 +164,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 "${CY_OTP_Secret}" ]; then + if [ -n "${CY_OTP_Secret}" ]; then _info " - Authorising with OTP code..." if ! _exists oathtool; then From 14089f8c6af3c8808702e4f58801deb10e492ca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Sz=C3=A9pe?= Date: Thu, 16 Jul 2020 06:18:12 +0200 Subject: [PATCH 128/161] Fix SC2236 --- dnsapi/dns_dgon.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_dgon.sh b/dnsapi/dns_dgon.sh index 515e87d5..ac14da48 100755 --- a/dnsapi/dns_dgon.sh +++ b/dnsapi/dns_dgon.sh @@ -122,12 +122,12 @@ dns_dgon_rm() { ## check for what we are looking for: "type":"A","name":"$_sub_domain" record="$(echo "$domain_list" | _egrep_o "\"id\"\s*\:\s*\"*[0-9]+\"*[^}]*\"name\"\s*\:\s*\"$_sub_domain\"[^}]*\"data\"\s*\:\s*\"$txtvalue\"")" - if [ ! -z "$record" ]; then + if [ -n "$record" ]; then ## we found records rec_ids="$(echo "$record" | _egrep_o "id\"\s*\:\s*\"*[0-9]+" | _egrep_o "[0-9]+")" _debug rec_ids "$rec_ids" - if [ ! -z "$rec_ids" ]; then + if [ -n "$rec_ids" ]; then echo "$rec_ids" | while IFS= read -r rec_id; do ## delete the record ## delete URL for removing the one we dont want @@ -218,7 +218,7 @@ _get_base_domain() { ## we got part of a domain back - grep it out found="$(echo "$domain_list" | _egrep_o "\"name\"\s*\:\s*\"$_domain\"")" ## check if it exists - if [ ! -z "$found" ]; then + if [ -n "$found" ]; then ## exists - exit loop returning the parts sub_point=$(_math $i - 1) _sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-"$sub_point") From eb9005ad744224e54b291532328b52d8d87e3431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Sz=C3=A9pe?= Date: Thu, 16 Jul 2020 06:18:46 +0200 Subject: [PATCH 129/161] Fix SC2236 --- dnsapi/dns_yandex.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index 5721f994..0a2c3330 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -25,7 +25,7 @@ dns_yandex_add() { _PDD_get_record_ids || return 1 _debug "Record_ids: $record_ids" - if [ ! -z "$record_ids" ]; then + if [ -n "$record_ids" ]; then _info "All existing $subdomain records from $domain will be removed at the very end." fi From 6a0ed51f5ee7c1af00652890b34603dc5f4d201d Mon Sep 17 00:00:00 2001 From: Adrian Fedoreanu Date: Fri, 24 Jul 2020 16:28:34 +0200 Subject: [PATCH 130/161] replace response equals with contains --- dnsapi/dns_1984hosting.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_1984hosting.sh b/dnsapi/dns_1984hosting.sh index 09f02796..bcb675ab 100755 --- a/dnsapi/dns_1984hosting.sh +++ b/dnsapi/dns_1984hosting.sh @@ -3,7 +3,7 @@ #So, here must be a method dns_1984hosting_add() #Which will be called by acme.sh to add the txt record to your api system. #returns 0 means success, otherwise error. -# + #Author: Adrian Fedoreanu #Report Bugs here: https://github.com/acmesh-official/acme.sh # or here... https://github.com/acmesh-official/acme.sh/issues/2851 @@ -100,7 +100,7 @@ _1984hosting_add_txt_record() { elif _contains "$response" ""; then _err "1984Hosting failed to add TXT record for $subdomain. Check $HTTP_HEADER file" return 1 - elif [ "$response" = '{"auth": false, "ok": false}' ]; then + elif _contains "$response" '"auth": false'; then _err "1984Hosting failed to add TXT record for $subdomain. Invalid or expired cookie" return 1 fi @@ -167,7 +167,7 @@ _1984hosting_login() { response="$(echo "$response" | _normalizeJson)" _debug2 response "$response" - if [ "$response" = '{"loggedin": true, "ok": true}' ]; then + if _contains "$response" '"loggedin": true'; then One984HOSTING_COOKIE="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _tail_n 1 | _egrep_o 'sessionid=[^;]*;' | tr -d ';')" export One984HOSTING_COOKIE _saveaccountconf_mutable One984HOSTING_COOKIE "$One984HOSTING_COOKIE" @@ -196,7 +196,7 @@ _check_cookie() { _authget "https://management.1984hosting.com/accounts/loginstatus/" response="$(echo "$_response" | _normalizeJson)" - if [ "$_response" = '{"ok": true}' ]; then + if _contains "$response" '"ok": true'; then _debug "Cached cookie still valid" return 0 fi From 4b35aef728eb3d35f3faac08f44e0615b6797e3e Mon Sep 17 00:00:00 2001 From: 12bbf7608ae1 <33011786+pdxgf1208@users.noreply.github.com> Date: Sat, 25 Jul 2020 21:48:11 +0800 Subject: [PATCH 131/161] Update dns_dynv6.sh Add support for domains like '*.v6.rocks' --- dnsapi/dns_dynv6.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_dynv6.sh b/dnsapi/dns_dynv6.sh index 819372c2..50eda74b 100644 --- a/dnsapi/dns_dynv6.sh +++ b/dnsapi/dns_dynv6.sh @@ -80,7 +80,7 @@ _generate_new_key() { _get_domain() { _full_domain="$1" _debug "getting domain for $_full_domain" - if ! _contains "$_full_domain" 'dynv6.net' && ! _contains "$_full_domain" 'dns.army' && ! _contains "$_full_domain" 'dns.navy'; then + if ! _contains "$_full_domain" 'dynv6.net' && ! _contains "$_full_domain" 'dns.army' && ! _contains "$_full_domain" 'dns.navy' && ! _contains "$_full_domain" 'v6.rocks' ; then _err "The hosts does not seem to be a dynv6 host" return 1 fi From 5f5096e1d40f17acd414f20d582f43a634831e56 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Sat, 25 Jul 2020 21:48:35 -0600 Subject: [PATCH 132/161] Addressing issues found in DS218+ DSM DS218+ appears to have a slighly different DSM that sends back headers in lowercase. Reported by @BartSiwek in #2727 --- deploy/synology_dsm.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/synology_dsm.sh b/deploy/synology_dsm.sh index c57d50bc..2ec0ceb3 100644 --- a/deploy/synology_dsm.sh +++ b/deploy/synology_dsm.sh @@ -22,7 +22,7 @@ ######## Public functions ##################### _syno_get_cookie_data() { - grep "\W$1=" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';' + grep -i "\W$1=" | grep -i "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';' } #domain keyfile certfile cafile fullchain @@ -79,7 +79,7 @@ synology_dsm_deploy() { encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)" encoded_did="$(printf "%s" "$SYNO_DID" | _url_encode)" response=$(_get "$_base_url/webman/login.cgi?username=$encoded_username&passwd=$encoded_password&enable_syno_token=yes&device_id=$encoded_did" 1) - token=$(echo "$response" | grep "X-SYNO-TOKEN:" | sed -n 's/^X-SYNO-TOKEN: \(.*\)$/\1/p' | tr -d "\r\n") + token=$(echo "$response" | grep -i "X-SYNO-TOKEN:" | sed -n 's/^X-SYNO-TOKEN: \(.*\)$/\1/pI' | tr -d "\r\n") _debug3 response "$response" _debug token "$token" From 4f3f4e23e4f9ca5c11d381c435944c9229128f74 Mon Sep 17 00:00:00 2001 From: Vinton Huang Date: Mon, 27 Jul 2020 03:55:07 +0800 Subject: [PATCH 133/161] Fix failed test in acmetest. Item alpine:latest - test 12: le_test_standandalone_deactivate_v2 - Message of failed test [1]: /root/.acme.sh/acme.sh --deactivate -d testdocker.acme.sh [FAIL] - Reason of failure: left brace was not escaped. According to the standard [2], if special chars appear first in an ERE, it will produce undefined results. - egrep from busybox (and thus alpine) take it as an error, but egrep from GNU grep (included in most distros) and *BSD are more tolerant, just ignore it. - Fix: consider the right brace at the right-hand side of the ERE, the result string will not contain right brace. So the left-hand side should not contain left brace, too. [1] https://github.com/acmesh-official/acmetest/blob/446939706e07c26267d83f71e4d0b8b152b0d3de/logs/alpine-latest.out#L119 [2] 9.4.3 ERE Special Characters, The Open Group Base Specifications. https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index f766ef2f..04c60ee6 100755 --- a/acme.sh +++ b/acme.sh @@ -5642,7 +5642,7 @@ _deactivate() { _URL_NAME="uri" fi - entries="$(echo "$response" | _egrep_o "{ *\"type\":\"[^\"]*\", *\"status\": *\"valid\", *\"$_URL_NAME\"[^}]*")" + entries="$(echo "$response" | _egrep_o "[^{]*\"type\":\"[^\"]*\", *\"status\": *\"valid\", *\"$_URL_NAME\"[^}]*")" if [ -z "$entries" ]; then _info "No valid entries found." if [ -z "$thumbprint" ]; then From f190de39a6de6451a3922b745cc825898595f20b Mon Sep 17 00:00:00 2001 From: JP Mens Date: Mon, 27 Jul 2020 14:34:35 +0200 Subject: [PATCH 134/161] Remove unecessary word from README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0c69fb44..7e49a714 100644 --- a/README.md +++ b/README.md @@ -309,7 +309,7 @@ https://github.com/acmesh-official/acme.sh/wiki/dnsapi See: https://github.com/acmesh-official/acme.sh/wiki/dns-manual-mode first. -If your dns provider doesn't support any api access, you can add the txt record by your hand. +If your dns provider doesn't support any api access, you can add the txt record by hand. ```bash acme.sh --issue --dns -d example.com -d www.example.com -d cp.example.com From 1f5cafc2d15eb60fef724f1854d731725b6d2bd2 Mon Sep 17 00:00:00 2001 From: neil <8305679+Neilpang@users.noreply.github.com> Date: Tue, 28 Jul 2020 09:32:15 +0800 Subject: [PATCH 135/161] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 0c69fb44..953b2c0e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # An ACME Shell script: acme.sh [![Build Status](https://travis-ci.org/acmesh-official/acme.sh.svg?branch=master)](https://travis-ci.org/acmesh-official/acme.sh) [![Join the chat at https://gitter.im/acme-sh/Lobby](https://badges.gitter.im/acme-sh/Lobby.svg)](https://gitter.im/acme-sh/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Docker stars](https://img.shields.io/docker/stars/neilpang/acme.sh.svg)](https://hub.docker.com/r/neilpang/acme.sh "Click to view the image on Docker Hub") +[![Docker pulls](https://img.shields.io/docker/pulls/neilpang/acme.sh.svg)](https://hub.docker.com/r/neilpang/acme.sh "Click to view the image on Docker Hub") acme.sh is being sponsored by the following tool; please help to support us by taking a look and signing up to a free trial From 5207e111e112cee233911873c21323d43db92bd5 Mon Sep 17 00:00:00 2001 From: "kapper.net support account" Date: Sun, 2 Aug 2020 00:19:28 +0200 Subject: [PATCH 136/161] initial kapper.net DNS API support hopefully this time we get it right ;) Co-Authored-By: Harald Kapper --- dnsapi/dns_kappernet.sh | 141 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 dnsapi/dns_kappernet.sh diff --git a/dnsapi/dns_kappernet.sh b/dnsapi/dns_kappernet.sh new file mode 100644 index 00000000..71dae73d --- /dev/null +++ b/dnsapi/dns_kappernet.sh @@ -0,0 +1,141 @@ +#!/usr/bin/env sh + +# kapper.net domain api +# for further questions please contact: support@kapper.net + +#KAPPERNETDNS_Key="yourKAPPERNETapikey" +#KAPPERNETDNS_Secret="yourKAPPERNETapisecret" + +KAPPERNETDNS_Api="https://dnspanel.kapper.net/API/1.1?APIKey=$KAPPERNETDNS_Key&APISecret=$KAPPERNETDNS_Secret" + +############################################################################### +# called with +# fullhostname: something.example.com +# txtvalue: someacmegenerated string +dns_kappernet_add() { + fullhostname=$1 + txtvalue=$2 + + if [ -z "$KAPPERNETDNS_Key" ] || [ -z "$KAPPERNETDNS_Secret" ]; then + KAPPERNETDNS_Key="" + KAPPERNETDNS_Secret="" + _err "You haven't defined kapper.net api key and secret yet." + _err "Please send us mail to support@kapper.net get your key and secret." + return 1 + fi + + #store the api key and email to the account conf file. + _saveaccountconf KAPPERNETDNS_Key "$KAPPERNETDNS_Key" + _saveaccountconf KAPPERNETDNS_Secret "$KAPPERNETDNS_Secret" + _debug "Checking Domain ..." + if ! _get_root "$fullhostname"; then + _err "invalid domain" + return 1 + fi + _debug _sub_domain "SUBDOMAIN: $_sub_domain" + _debug _domain "DOMAIN: $_domain" + + _info "Trying to add TXT DNS Record" + data="%7B%22name%22%3A%22$fullhostname%22%2C%22type%22%3A%22TXT%22%2C%22content%22%3A%22$txtvalue%22%2C%22ttl%22%3A%223600%22%2C%22prio%22%3A%22%22%7D" + if _kappernet_api GET "action=new&subject=$_domain&data=$data"; then + + if _contains "$response" "{\"OK\":true"; then + _info "Waiting 120 seconds for DNS to spread the new record" + _sleep 120 + return 0 + else + _err "Error creating a TXT DNS Record: $fullhostname TXT $txtvalue" + _err "Error Message: $response" + return 1 + fi + fi + _err "Failed creating TXT Record" +} + +############################################################################### +# called with +# fullhostname: something.example.com +dns_kappernet_rm() { + fullhostname=$1 + txtvalue=$2 + + if [ -z "$KAPPERNETDNS_Key" ] || [ -z "$KAPPERNETDNS_Secret" ]; then + KAPPERNETDNS_Key="" + KAPPERNETDNS_Secret="" + _err "You haven't defined kapper.net api key and secret yet." + _err "Please send us mail to get your key and secret." + return 1 + fi + + #store the api key and email to the account conf file. + _saveaccountconf KAPPERNETDNS_Key "$KAPPERNETDNS_Key" + _saveaccountconf KAPPERNETDNS_Secret "$KAPPERNETDNS_Secret" + + _info "Trying to remove the TXT Record: $fullhostname" + + if _kappernet_api GET "action=del&subject=$fullhostname"; then + if _contains "$response" "{\"OK\":true"; then + return 0 + else + _err "Error deleting DNS Record: $fullhostname" + _err "Problem: $response" + return 1 + fi + fi + _err "Problem creating TXT DNS record" +} + +#################### Private functions below ################################## +# called with hostname +# e.g._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 ! _kappernet_api GET "action=list&subject=$h"; then + return 1 + fi + if _contains "$response" '"OK":false'; 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 +} + +################################################################################ +# calls the kapper.net DNS Panel API +# with +# method +# param +_kappernet_api() { + method=$1 + param="$2" + + _debug param "PARAMETER=$param" + url="$KAPPERNETDNS_Api&$param" + _debug url "URL=$url" + + if [ "$method" = "GET" ]; then + response="$(_get "$url")" + else + _err "Unsupported method" + return 1 + fi + + _debug2 response "$response" + return 0 +} From 494a1603e4a49cc894ac9a9a239e1fc29dc99fd1 Mon Sep 17 00:00:00 2001 From: "kapper.net support account" Date: Sun, 2 Aug 2020 01:41:26 +0200 Subject: [PATCH 137/161] Update dns_kappernet.sh add issue-link in sourcecode Co-Authored-By: Harald Kapper --- dnsapi/dns_kappernet.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/dnsapi/dns_kappernet.sh b/dnsapi/dns_kappernet.sh index 71dae73d..75450549 100644 --- a/dnsapi/dns_kappernet.sh +++ b/dnsapi/dns_kappernet.sh @@ -2,6 +2,7 @@ # kapper.net domain api # for further questions please contact: support@kapper.net +# please report issues here: https://github.com/acmesh-official/acme.sh/issues/2977 #KAPPERNETDNS_Key="yourKAPPERNETapikey" #KAPPERNETDNS_Secret="yourKAPPERNETapisecret" From 2ba6a85eca0ab2aa1fe869f37639d87a9d22eb28 Mon Sep 17 00:00:00 2001 From: "kapper.net support account" Date: Sun, 2 Aug 2020 15:59:46 +0200 Subject: [PATCH 138/161] fix multiple txt-records delete + API update new API version fix to delete specific TXT records for wildcard-certs with LE Co-Authored-By: Harald Kapper --- dnsapi/dns_kappernet.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_kappernet.sh b/dnsapi/dns_kappernet.sh index 75450549..a059447a 100644 --- a/dnsapi/dns_kappernet.sh +++ b/dnsapi/dns_kappernet.sh @@ -7,7 +7,7 @@ #KAPPERNETDNS_Key="yourKAPPERNETapikey" #KAPPERNETDNS_Secret="yourKAPPERNETapisecret" -KAPPERNETDNS_Api="https://dnspanel.kapper.net/API/1.1?APIKey=$KAPPERNETDNS_Key&APISecret=$KAPPERNETDNS_Secret" +KAPPERNETDNS_Api="https://dnspanel.kapper.net/API/1.2?APIKey=$KAPPERNETDNS_Key&APISecret=$KAPPERNETDNS_Secret" ############################################################################### # called with @@ -73,8 +73,8 @@ dns_kappernet_rm() { _saveaccountconf KAPPERNETDNS_Secret "$KAPPERNETDNS_Secret" _info "Trying to remove the TXT Record: $fullhostname" - - if _kappernet_api GET "action=del&subject=$fullhostname"; then + data="%7B%22name%22%3A%22$fullhostname%22%2C%22type%22%3A%22TXT%22%2C%22content%22%3A%22$txtvalue%22%2C%22ttl%22%3A%223600%22%2C%22prio%22%3A%22%22%7D" + if _kappernet_api GET "action=del&subject=$fullhostname&data=$data"; then if _contains "$response" "{\"OK\":true"; then return 0 else From 40cda9220aa3902b11cb9f38a7dc38b3efd89fc1 Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 3 Aug 2020 21:22:32 +0800 Subject: [PATCH 139/161] fix https://github.com/acmesh-official/acme.sh/issues/3077 --- dnsapi/dns_azure.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_azure.sh b/dnsapi/dns_azure.sh index bf7cf2bf..28b6572a 100644 --- a/dnsapi/dns_azure.sh +++ b/dnsapi/dns_azure.sh @@ -172,7 +172,7 @@ dns_azure_rm() { _azure_rest GET "$acmeRecordURI" "" "$accesstoken" timestamp="$(_time)" if [ "$_code" = "200" ]; then - vlist="$(echo "$response" | _egrep_o "\"value\"\\s*:\\s*\\[\\s*\"[^\"]*\"\\s*]" | cut -d : -f 2 | tr -d "[]\"" | grep -v "$txtvalue")" + vlist="$(echo "$response" | _egrep_o "\"value\"\\s*:\\s*\\[\\s*\"[^\"]*\"\\s*]" | cut -d : -f 2 | tr -d "[]\"" | grep -v -- "$txtvalue")" values="" comma="" for v in $vlist; do From e8bcde31b778ecf1d3c880805b99c3caf322ccc2 Mon Sep 17 00:00:00 2001 From: Draevin Luke Date: Tue, 4 Aug 2020 16:33:24 -0700 Subject: [PATCH 140/161] Add Netlify API support --- dnsapi/dns_netlify.sh | 160 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 dnsapi/dns_netlify.sh diff --git a/dnsapi/dns_netlify.sh b/dnsapi/dns_netlify.sh new file mode 100644 index 00000000..4da97f48 --- /dev/null +++ b/dnsapi/dns_netlify.sh @@ -0,0 +1,160 @@ +#!/usr/bin/env sh + +#NETLIFY_ACCESS_TOKEN="xxxx" + +NETLIFY_HOST="api.netlify.com/api/v1/" +NETLIFY_URL="https://$NETLIFY_HOST" + +######## Public functions ##################### + +#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_netlify_add() { + fulldomain=$1 + txtvalue=$2 + + NETLIFY_ACCESS_TOKEN="${NETLIFY_ACCESS_TOKEN:-$(_readaccountconf_mutable NETLIFY_ACCESS_TOKEN)}" + + if [ -z "$NETLIFY_ACCESS_TOKEN" ]; then + NETLIFY_ACCESS_TOKEN="" + _err "Please specify your Netlify Access Token and try again." + return 1 + fi + + _info "Using Netlify" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + _saveaccountconf_mutable NETLIFY_ACCESS_TOKEN "$NETLIFY_ACCESS_TOKEN" + + if ! _get_root "$fulldomain" "$accesstoken"; then + _err "invalid domain" + return 1 + fi + + _debug _domain_id "$_domain_id" + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + dnsRecordURI="dns_zones/$_domain_id/dns_records" + + body="{\"type\":\"TXT\", \"hostname\":\"$_sub_domain\", \"value\":\"$txtvalue\", \"ttl\":\"10\"}" + + _netlify_rest POST "$dnsRecordURI" "$body" "$NETLIFY_ACCESS_TOKEN" + _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" + if [ "$_code" = "200" ] || [ "$_code" = '201' ]; then + _info "validation value added" + return 0 + else + _err "error adding validation value ($_code)" + return 1 + fi + + _err "Not fully implemented!" + return 1 +} + +#Usage: dns_myapi_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +#Remove the txt record after validation. +dns_netlify_rm() { + _info "Using Netlify" + _debug txtdomain "$txtdomain" + _debug txt "$txt" + + _saveaccountconf_mutable NETLIFY_ACCESS_TOKEN "$NETLIFY_ACCESS_TOKEN" + + if ! _get_root "$txtdomain" "$accesstoken"; then + _err "invalid domain" + return 1 + fi + + _debug _domain_id "$_domain_id" + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + dnsRecordURI="dns_zones/$_domain_id/dns_records" + + _netlify_rest GET "$dnsRecordURI" "" "$NETLIFY_ACCESS_TOKEN" + + _record_id=$(echo "$response" | _egrep_o "\"type\":\"TXT\",[^\}]*\"value\":\"$txt\"" | head -n 1 | _egrep_o "\"id\":\"[^\"\}]*\"" | cut -d : -f 2 | tr -d \" ) + _debug _record_id "$_record_id" + if [ "$_record_id" ]; then + _netlify_rest DELETE "$dnsRecordURI/$_record_id" "" "$NETLIFY_ACCESS_TOKEN" + _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" + if [ "$_code" = "200" ] || [ "$_code" = '204' ]; then + _info "validation value removed" + return 0 + else + _err "error removing validation value ($_code)" + return 1 + fi + return 0 + fi + return 1 +} + +#################### Private functions below ################################## + +_get_root() { + domain=$1 + accesstoken=$2 + i=1 + p=1 + + _netlify_rest GET "dns_zones" "" "$accesstoken" + + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug2 "Checking domain: $h" + if [ -z "$h" ]; then + #not valid + _err "Invalid domain" + return 1 + fi + + if _contains "$response" "\"name\":\"$h\"" >/dev/null; then + _domain_id=$(echo "$response" | _egrep_o "\"[^\"]*\",\"name\":\"$h" | cut -d , -f 1 | tr -d \" ) + if [ "$_domain_id" ]; then + if [ "$i" = 1 ]; then + #create the record at the domain apex (@) if only the domain name was provided as --domain-alias + _sub_domain="@" + else + _sub_domain=$(echo "$domain" | cut -d . -f 1-$p) + fi + _domain=$h + return 0 + fi + return 1 + fi + p=$i + i=$(_math "$i" + 1) + done + return 1 +} + +_netlify_rest() { + m=$1 + ep="$2" + data="$3" + _debug "$ep" + + token_trimmed=$(echo "$NETLIFY_ACCESS_TOKEN" | tr -d '"') + + export _H1="Content-Type: application/json" + export _H2="Authorization: Bearer $token_trimmed" + + :>"$HTTP_HEADER" + + if [ "$m" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$NETLIFY_URL$ep" "" "$m")" + else + response="$(_get "$NETLIFY_URL$ep")" + fi + + if [ "$?" != "0" ]; then + _err "error $ep" + return 1 + fi + _debug2 response "$response" + return 0 +} \ No newline at end of file From 70b49980cbed1f1c98d916dfe469512872aae171 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 9 Aug 2020 09:40:22 +0800 Subject: [PATCH 141/161] fix format --- dnsapi/dns_dynv6.sh | 2 +- dnsapi/dns_netlify.sh | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/dnsapi/dns_dynv6.sh b/dnsapi/dns_dynv6.sh index 50eda74b..3c222d3a 100644 --- a/dnsapi/dns_dynv6.sh +++ b/dnsapi/dns_dynv6.sh @@ -80,7 +80,7 @@ _generate_new_key() { _get_domain() { _full_domain="$1" _debug "getting domain for $_full_domain" - if ! _contains "$_full_domain" 'dynv6.net' && ! _contains "$_full_domain" 'dns.army' && ! _contains "$_full_domain" 'dns.navy' && ! _contains "$_full_domain" 'v6.rocks' ; then + if ! _contains "$_full_domain" 'dynv6.net' && ! _contains "$_full_domain" 'dns.army' && ! _contains "$_full_domain" 'dns.navy' && ! _contains "$_full_domain" 'v6.rocks'; then _err "The hosts does not seem to be a dynv6 host" return 1 fi diff --git a/dnsapi/dns_netlify.sh b/dnsapi/dns_netlify.sh index 4da97f48..137ac1fb 100644 --- a/dnsapi/dns_netlify.sh +++ b/dnsapi/dns_netlify.sh @@ -57,6 +57,8 @@ dns_netlify_add() { #Remove the txt record after validation. dns_netlify_rm() { _info "Using Netlify" + txtdomain="$1" + txt="$2" _debug txtdomain "$txtdomain" _debug txt "$txt" @@ -70,12 +72,12 @@ dns_netlify_rm() { _debug _domain_id "$_domain_id" _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - + dnsRecordURI="dns_zones/$_domain_id/dns_records" _netlify_rest GET "$dnsRecordURI" "" "$NETLIFY_ACCESS_TOKEN" - _record_id=$(echo "$response" | _egrep_o "\"type\":\"TXT\",[^\}]*\"value\":\"$txt\"" | head -n 1 | _egrep_o "\"id\":\"[^\"\}]*\"" | cut -d : -f 2 | tr -d \" ) + _record_id=$(echo "$response" | _egrep_o "\"type\":\"TXT\",[^\}]*\"value\":\"$txt\"" | head -n 1 | _egrep_o "\"id\":\"[^\"\}]*\"" | cut -d : -f 2 | tr -d \") _debug _record_id "$_record_id" if [ "$_record_id" ]; then _netlify_rest DELETE "$dnsRecordURI/$_record_id" "" "$NETLIFY_ACCESS_TOKEN" @@ -101,7 +103,7 @@ _get_root() { p=1 _netlify_rest GET "dns_zones" "" "$accesstoken" - + while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug2 "Checking domain: $h" @@ -112,7 +114,7 @@ _get_root() { fi if _contains "$response" "\"name\":\"$h\"" >/dev/null; then - _domain_id=$(echo "$response" | _egrep_o "\"[^\"]*\",\"name\":\"$h" | cut -d , -f 1 | tr -d \" ) + _domain_id=$(echo "$response" | _egrep_o "\"[^\"]*\",\"name\":\"$h" | cut -d , -f 1 | tr -d \") if [ "$_domain_id" ]; then if [ "$i" = 1 ]; then #create the record at the domain apex (@) if only the domain name was provided as --domain-alias @@ -157,4 +159,4 @@ _netlify_rest() { fi _debug2 response "$response" return 0 -} \ No newline at end of file +} From e932be0fb3b145a6c6cf161de74d29a96ea8a3d0 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 9 Aug 2020 09:34:43 +0800 Subject: [PATCH 142/161] eab --- acme.sh | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 67 insertions(+), 6 deletions(-) diff --git a/acme.sh b/acme.sh index 6a600087..1f6d2605 100755 --- a/acme.sh +++ b/acme.sh @@ -1507,6 +1507,19 @@ _url_replace() { tr '/+' '_-' | tr -d '= ' } +#base64 string +_durl_replace_base64() { + _l=$((${#1} % 4)) + if [ $_l -eq 2 ]; then + _s="$1"'==' + elif [ $_l -eq 3 ]; then + _s="$1"'=' + else + _s="$1" + fi + echo "$_s" | tr '_-' '/+' +} + _time2str() { #BSD if date -u -r "$1" 2>/dev/null; then @@ -3406,10 +3419,13 @@ _on_issue_success() { } +#account_key_length eab-kid eab-hmac-key registeraccount() { - _reg_length="$1" + _account_key_length="$1" + _eab_id="$2" + _eab_hmac_key="$3" _initpath - _regAccount "$_reg_length" + _regAccount "$_account_key_length" "$_eab_id" "$_eab_hmac_key" } __calcAccountKeyHash() { @@ -3424,6 +3440,8 @@ __calc_account_thumbprint() { _regAccount() { _initpath _reg_length="$1" + _eab_id="$2" + _eab_hmac_key="$3" _debug3 _regAccount "$_regAccount" _initAPI @@ -3448,12 +3466,41 @@ _regAccount() { if ! _calcjwk "$ACCOUNT_KEY_PATH"; then return 1 fi - + if [ "$_eab_id" ] && [ "$_eab_hmac_key" ]; then + _savecaconf CA_EAB_KEY_ID "$_eab_id" + _savecaconf CA_EAB_HMAC_KEY "$_eab_hmac_key" + fi + _eab_id=$(_readcaconf "CA_EAB_KEY_ID") + _eab_hmac_key=$(_readcaconf "CA_EAB_HMAC_KEY") + _secure_debug3 _eab_id "$_eab_id" + _secure_debug3 _eab_hmac_key "$_eab_hmac_key" if [ "$ACME_VERSION" = "2" ]; then - regjson='{"termsOfServiceAgreed": true}' + if [ "$_eab_id" ] && [ "$_eab_hmac_key" ]; then + eab_protected="{\"alg\":\"HS256\",\"kid\":\"$_eab_id\",\"url\":\"${ACME_NEW_ACCOUNT}\"}" + _debug3 eab_protected "$eab_protected" + + eab_protected64=$(printf "%s" "$eab_protected" | _base64 | _url_replace) + _debug3 eab_protected64 "$eab_protected64" + + eab_payload64=$(printf "%s" "$jwk" | _base64 | _url_replace) + _debug3 eab_payload64 "$eab_payload64" + + eab_sign_t="$eab_protected64.$eab_payload64" + _debug3 eab_sign_t "$eab_sign_t" + + key_hex="$(_durl_replace_base64 "$_eab_hmac_key" | _dbase64 | _hex_dump | tr -d ' ')" + _debug3 key_hex "$key_hex" + + eab_signature=$(printf "%s" "$eab_sign_t" | _hmac sha256 $key_hex | _base64 | _url_replace) + _debug3 eab_signature "$eab_signature" + + externalBinding=",\"externalAccountBinding\":{\"protected\":\"$eab_protected64\", \"payload\":\"$eab_payload64\", \"signature\":\"$eab_signature\"}" + _debug3 externalBinding "$externalBinding" + fi if [ "$ACCOUNT_EMAIL" ]; then - regjson='{"contact": ["mailto:'$ACCOUNT_EMAIL'"], "termsOfServiceAgreed": true}' + email_sg="\"contact\": [\"mailto:$ACCOUNT_EMAIL\"], " fi + regjson="{$email_sg\"termsOfServiceAgreed\": true$externalBinding}" else _reg_res="$ACME_NEW_ACCOUNT_RES" regjson='{"resource": "'$_reg_res'", "terms-of-service-agreed": true, "agreement": "'$ACME_AGREEMENT'"}' @@ -6278,6 +6325,10 @@ Parameters: --log-level 1|2 Specifies the log level, default is 1. --syslog [0|3|6|7] Syslog level, 0: disable syslog, 3: error, 6: info, 7: debug. + --eab-kid EAB_KID Key Identifier for External Account Binding. + --eab-hmac-key EAB_HMAC_KEY HMAC key for External Account Binding. + + These parameters are to install the cert to nginx/apache or any other server after issue/renew a cert: --cert-file After issue/renew, the cert will be copied to this path. @@ -6510,6 +6561,8 @@ _process() { _notify_level="" _notify_mode="" _revoke_reason="" + _eab_kid="" + _eab_hmac_key="" while [ ${#} -gt 0 ]; do case "${1}" in @@ -6990,6 +7043,14 @@ _process() { fi shift ;; + --eab-kid) + _eab_kid="$2" + shift + ;; + --eab-hmac-key) + _eab_hmac_key="$2" + shift + ;; *) _err "Unknown parameter : $1" return 1 @@ -7086,7 +7147,7 @@ _process() { deactivate "$_domain,$_altdomains" ;; registeraccount) - registeraccount "$_accountkeylength" + registeraccount "$_accountkeylength" "$_eab_kid" "$_eab_hmac_key" ;; updateaccount) updateaccount From 7d20db93d3711b53dfc3bb435112f7ad1eaf1a9e Mon Sep 17 00:00:00 2001 From: neil Date: Tue, 11 Aug 2020 23:28:52 +0800 Subject: [PATCH 143/161] 1. Support short names for `--server` parameter, The valid values are: letsencrypt, letsencrypt_test, buypass, buypass_test and zerossl 2. Support Zerossl.com acme protocol. 3. Add "--set-default-ca --server xxxx" command to set the default CA to use. --- acme.sh | 93 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 78 insertions(+), 15 deletions(-) diff --git a/acme.sh b/acme.sh index 1f6d2605..4bddab25 100755 --- a/acme.sh +++ b/acme.sh @@ -23,11 +23,27 @@ _SUB_FOLDERS="$_SUB_FOLDER_DNSAPI $_SUB_FOLDER_DEPLOY $_SUB_FOLDER_NOTIFY" LETSENCRYPT_CA_V1="https://acme-v01.api.letsencrypt.org/directory" LETSENCRYPT_STAGING_CA_V1="https://acme-staging.api.letsencrypt.org/directory" -LETSENCRYPT_CA_V2="https://acme-v02.api.letsencrypt.org/directory" -LETSENCRYPT_STAGING_CA_V2="https://acme-staging-v02.api.letsencrypt.org/directory" +CA_LETSENCRYPT_V2="https://acme-v02.api.letsencrypt.org/directory" +CA_LETSENCRYPT_V2_TEST="https://acme-staging-v02.api.letsencrypt.org/directory" -DEFAULT_CA=$LETSENCRYPT_CA_V2 -DEFAULT_STAGING_CA=$LETSENCRYPT_STAGING_CA_V2 +CA_BUYPASS="https://api.buypass.com/acme/directory" +CA_BUYPASS_TEST="https://api.test4.buypass.no/acme/directory" + +CA_ZEROSSL="https://acme.zerossl.com/v2/DV90" + + +DEFAULT_CA=$CA_LETSENCRYPT_V2 +DEFAULT_STAGING_CA=$CA_LETSENCRYPT_V2_TEST + +CA_NAMES=" +letsencrypt +letsencrypt_test,letsencrypttest +buypass +buypass_test,buypasstest +zerossl +" + +CA_SERVERS="$CA_LETSENCRYPT_V2,$CA_LETSENCRYPT_V2_TEST,$CA_BUYPASS,$CA_BUYPASS_TEST,$CA_ZEROSSL" DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)" DEFAULT_ACCOUNT_EMAIL="" @@ -140,6 +156,8 @@ _SUDO_WIKI="https://github.com/acmesh-official/acme.sh/wiki/sudo" _REVOKE_WIKI="https://github.com/acmesh-official/acme.sh/wiki/revokecert" +_ZEROSSL_WIKI="https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA" + _DNS_MANUAL_ERR="The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead." _DNS_MANUAL_WARN="It seems that you are using dns manual mode. please take care: $_DNS_MANUAL_ERR" @@ -2577,16 +2595,22 @@ _initpath() { fi if [ "$ACME_VERSION" = "2" ]; then - DEFAULT_CA="$LETSENCRYPT_CA_V2" - DEFAULT_STAGING_CA="$LETSENCRYPT_STAGING_CA_V2" + DEFAULT_CA="$CA_LETSENCRYPT_V2" + DEFAULT_STAGING_CA="$CA_LETSENCRYPT_V2_TEST" fi if [ -z "$ACME_DIRECTORY" ]; then - if [ -z "$STAGE" ]; then - ACME_DIRECTORY="$DEFAULT_CA" + default_acme_server=$(_readaccountconf "DEFAULT_ACME_SERVER") + _debug default_acme_server "$default_acme_server" + if [ "$default_acme_server" ]; then + ACME_DIRECTORY="$default_acme_server" else - ACME_DIRECTORY="$DEFAULT_STAGING_CA" - _info "Using stage ACME_DIRECTORY: $ACME_DIRECTORY" + if [ -z "$STAGE" ]; then + ACME_DIRECTORY="$DEFAULT_CA" + else + ACME_DIRECTORY="$DEFAULT_STAGING_CA" + _info "Using stage ACME_DIRECTORY: $ACME_DIRECTORY" + fi fi fi @@ -6301,6 +6325,7 @@ Commands: --createCSR, -ccsr Create CSR , professional use. --deactivate Deactivate the domain authz, professional use. --set-notify Set the cron notification hook, level or mode. + --set-default-ca Used with '--server' , to set the default CA to use to use. Parameters: @@ -6344,7 +6369,7 @@ Parameters: --cert-home Specifies the home dir to save all the certs, only valid for '--install' command. --config-home Specifies the home dir to save all the configurations. --useragent Specifies the user agent string. it will be saved for future use too. - --accountemail Specifies the account email, only valid for the '--install' and '--update-account' command. + --accountemail, -m Specifies the account email, only valid for the '--install' and '--update-account' command. --accountkey Specifies the account key path, only valid for the '--install' command. --days Specifies the days to renew the cert when using '--issue' command. The default value is $DEFAULT_RENEW days. --httpport Specifies the standalone listening port. Only valid if the server is behind a reverse proxy or load balancer. @@ -6510,6 +6535,39 @@ _checkSudo() { return 0 } +#server +_selectServer() { + _server="$1" + _server_lower="$(echo "$_server" | _lower_case)" + _sindex=0 + for snames in $CA_NAMES; do + snames="$(echo "$snames" | _lower_case)" + _sindex="$(_math $_sindex + 1)" + _debug2 "_selectServer try snames" "$snames" + for sname in $(echo "$snames" | tr ',' ' '); do + if [ "$_server_lower" = "$sname" ]; then + _debug2 "_selectServer match $sname" + _serverdir="$(_getfield "$CA_SERVERS" $_sindex)" + _debug "Selected server: $_serverdir" + ACME_DIRECTORY="$_serverdir" + export ACME_DIRECTORY + return + fi + done + done + ACME_DIRECTORY="$_server" + export ACME_DIRECTORY +} + +#set default ca to $ACME_DIRECTORY +setdefaultca() { + if [ -z "$ACME_DIRECTORY" ]; then + _err "Please give a --server parameter." + return 1 + fi + _saveaccountconf "DEFAULT_ACME_SERVER" "$ACME_DIRECTORY" +} + _process() { _CMD="" _domain="" @@ -6652,6 +6710,9 @@ _process() { --set-notify) _CMD="setnotify" ;; + --set-default-ca) + _CMD="setdefaultca" + ;; --domain | -d) _dvalue="$2" @@ -6690,9 +6751,8 @@ _process() { STAGE="1" ;; --server) - ACME_DIRECTORY="$2" - _server="$ACME_DIRECTORY" - export ACME_DIRECTORY + _server="$2" + _selectServer "$_server" shift ;; --debug) @@ -6849,7 +6909,7 @@ _process() { USER_AGENT="$_useragent" shift ;; - --accountemail) + --accountemail | -m) _accountemail="$2" ACCOUNT_EMAIL="$_accountemail" shift @@ -7179,6 +7239,9 @@ _process() { setnotify) setnotify "$_notify_hook" "$_notify_level" "$_notify_mode" ;; + setdefaultca) + setdefaultca + ;; *) if [ "$_CMD" ]; then _err "Invalid command: $_CMD" From 1e967eceef105f55e3e68c649ff6e77cf1c6e896 Mon Sep 17 00:00:00 2001 From: neil Date: Tue, 11 Aug 2020 23:45:12 +0800 Subject: [PATCH 144/161] fix format --- acme.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/acme.sh b/acme.sh index 4bddab25..70795ff3 100755 --- a/acme.sh +++ b/acme.sh @@ -31,7 +31,6 @@ CA_BUYPASS_TEST="https://api.test4.buypass.no/acme/directory" CA_ZEROSSL="https://acme.zerossl.com/v2/DV90" - DEFAULT_CA=$CA_LETSENCRYPT_V2 DEFAULT_STAGING_CA=$CA_LETSENCRYPT_V2_TEST @@ -3512,10 +3511,10 @@ _regAccount() { eab_sign_t="$eab_protected64.$eab_payload64" _debug3 eab_sign_t "$eab_sign_t" - key_hex="$(_durl_replace_base64 "$_eab_hmac_key" | _dbase64 | _hex_dump | tr -d ' ')" + key_hex="$(_durl_replace_base64 "$_eab_hmac_key" | _dbase64 | _hex_dump | tr -d ' ')" _debug3 key_hex "$key_hex" - eab_signature=$(printf "%s" "$eab_sign_t" | _hmac sha256 $key_hex | _base64 | _url_replace) + eab_signature=$(printf "%s" "$eab_sign_t" | _hmac sha256 $key_hex | _base64 | _url_replace) _debug3 eab_signature "$eab_signature" externalBinding=",\"externalAccountBinding\":{\"protected\":\"$eab_protected64\", \"payload\":\"$eab_payload64\", \"signature\":\"$eab_signature\"}" @@ -7110,7 +7109,7 @@ _process() { --eab-hmac-key) _eab_hmac_key="$2" shift - ;; + ;; *) _err "Unknown parameter : $1" return 1 From edbe026b490d7da30a37a21d86142fc0bc31dcde Mon Sep 17 00:00:00 2001 From: Andy Botting Date: Wed, 12 Aug 2020 11:24:45 +1000 Subject: [PATCH 145/161] Rename openstack to dns_openstack Although the DNS API dev guide at https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Dev-Guide says `The script file name must be myapi.sh`, it should really be names dns_myapi.sh for consistency. --- dnsapi/{openstack.sh => dns_openstack.sh} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename dnsapi/{openstack.sh => dns_openstack.sh} (100%) diff --git a/dnsapi/openstack.sh b/dnsapi/dns_openstack.sh similarity index 100% rename from dnsapi/openstack.sh rename to dnsapi/dns_openstack.sh From 8d811760a91be47927ed842b8d7f056704c13574 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 12 Aug 2020 20:43:44 +0800 Subject: [PATCH 146/161] 1. move email to ca conf 2. get EAB credentials from Zerossl by email automatically --- README.md | 1 + acme.sh | 94 ++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 73 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 2da103b2..f5631475 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ https://github.com/acmesh-official/acmetest # Supported CA - Letsencrypt.org CA(default) +- [ZeroSSL.com CA](https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA) - [BuyPass.com CA](https://github.com/acmesh-official/acme.sh/wiki/BuyPass.com-CA) - [Pebble strict Mode](https://github.com/letsencrypt/pebble) diff --git a/acme.sh b/acme.sh index 70795ff3..d359a4bb 100755 --- a/acme.sh +++ b/acme.sh @@ -30,6 +30,8 @@ CA_BUYPASS="https://api.buypass.com/acme/directory" CA_BUYPASS_TEST="https://api.test4.buypass.no/acme/directory" CA_ZEROSSL="https://acme.zerossl.com/v2/DV90" +_ZERO_EAB_ENDPOINT="http://api.zerossl.com/acme/eab-credentials-email" + DEFAULT_CA=$CA_LETSENCRYPT_V2 DEFAULT_STAGING_CA=$CA_LETSENCRYPT_V2_TEST @@ -45,7 +47,6 @@ zerossl CA_SERVERS="$CA_LETSENCRYPT_V2,$CA_LETSENCRYPT_V2_TEST,$CA_BUYPASS,$CA_BUYPASS_TEST,$CA_ZEROSSL" DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)" -DEFAULT_ACCOUNT_EMAIL="" DEFAULT_ACCOUNT_KEY_LENGTH=2048 DEFAULT_DOMAIN_KEY_LENGTH=2048 @@ -3459,6 +3460,21 @@ __calc_account_thumbprint() { printf "%s" "$jwk" | tr -d ' ' | _digest "sha256" | _url_replace } +_getAccountEmail() { + if [ "$ACCOUNT_EMAIL" ]; then + echo "$ACCOUNT_EMAIL" + return 0 + fi + if [ -z "$CA_EMAIL" ]; then + CA_EMAIL="$(_readcaconf CA_EMAIL)" + fi + if [ "$CA_EMAIL" ]; then + echo "$CA_EMAIL" + return 0 + fi + _readaccountconf "ACCOUNT_EMAIL" +} + #keylength _regAccount() { _initpath @@ -3497,7 +3513,38 @@ _regAccount() { _eab_hmac_key=$(_readcaconf "CA_EAB_HMAC_KEY") _secure_debug3 _eab_id "$_eab_id" _secure_debug3 _eab_hmac_key "$_eab_hmac_key" + _email="$(_getAccountEmail)" + if [ "$_email" ]; then + _savecaconf "CA_EMAIL" "$_email" + fi if [ "$ACME_VERSION" = "2" ]; then + if [ "$ACME_DIRECTORY" = "$CA_ZEROSSL" ]; then + if [ -z "$_eab_id" ] || [ -z "$_eab_hmac_key" ]; then + _info "No EAB credentials found for ZeroSSL, let's get one" + if [ -z "$_email" ]; then + _err "Please provide a email address for zerossl account." + return 1 + fi + _eabresp=$(_post "email=$_email" $_ZERO_EAB_ENDPOINT) + if [ "$?" != "0" ]; then + _debug2 "$_eabresp" + _err "Can not get EAB credentials from zerossl." + return 1 + fi + _eab_id="$(echo "$_eabresp" | tr ',}' '\n' | grep '"eab_kid"' | cut -d : -f 2 | tr -d '"')" + if [ -z "$_eab_id" ]; then + _err "Can not resolve _eab_id"; + return 1 + fi + _eab_hmac_key="$(echo "$_eabresp" | tr ',}' '\n' | grep '"eab_hmac_key"' | cut -d : -f 2 | tr -d '"')" + if [ -z "$_eab_hmac_key" ]; then + _err "Can not resolve _eab_hmac_key"; + return 1 + fi + _savecaconf CA_EAB_KEY_ID "$_eab_id" + _savecaconf CA_EAB_HMAC_KEY "$_eab_hmac_key" + fi + fi if [ "$_eab_id" ] && [ "$_eab_hmac_key" ]; then eab_protected="{\"alg\":\"HS256\",\"kid\":\"$_eab_id\",\"url\":\"${ACME_NEW_ACCOUNT}\"}" _debug3 eab_protected "$eab_protected" @@ -3520,44 +3567,52 @@ _regAccount() { externalBinding=",\"externalAccountBinding\":{\"protected\":\"$eab_protected64\", \"payload\":\"$eab_payload64\", \"signature\":\"$eab_signature\"}" _debug3 externalBinding "$externalBinding" fi - if [ "$ACCOUNT_EMAIL" ]; then - email_sg="\"contact\": [\"mailto:$ACCOUNT_EMAIL\"], " + if [ "$_email" ]; then + email_sg="\"contact\": [\"mailto:$_email\"], " fi regjson="{$email_sg\"termsOfServiceAgreed\": true$externalBinding}" else _reg_res="$ACME_NEW_ACCOUNT_RES" regjson='{"resource": "'$_reg_res'", "terms-of-service-agreed": true, "agreement": "'$ACME_AGREEMENT'"}' - if [ "$ACCOUNT_EMAIL" ]; then - regjson='{"resource": "'$_reg_res'", "contact": ["mailto:'$ACCOUNT_EMAIL'"], "terms-of-service-agreed": true, "agreement": "'$ACME_AGREEMENT'"}' + if [ "$_email" ]; then + regjson='{"resource": "'$_reg_res'", "contact": ["mailto:'$_email'"], "terms-of-service-agreed": true, "agreement": "'$ACME_AGREEMENT'"}' fi fi - _info "Registering account" + _info "Registering account: $ACME_DIRECTORY" if ! _send_signed_request "${ACME_NEW_ACCOUNT}" "$regjson"; then _err "Register account Error: $response" return 1 fi + _eabAlreadyBound="" if [ "$code" = "" ] || [ "$code" = '201' ]; then echo "$response" >"$ACCOUNT_JSON_PATH" _info "Registered" elif [ "$code" = '409' ] || [ "$code" = '200' ]; then _info "Already registered" + elif [ "$code" = '400' ] && _contains "$response" 'The account is not awaiting external account binding'; then + _info "Already register EAB." + _eabAlreadyBound=1 else _err "Register account Error: $response" return 1 fi - _debug2 responseHeaders "$responseHeaders" - _accUri="$(echo "$responseHeaders" | grep -i "^Location:" | _head_n 1 | cut -d ':' -f 2- | tr -d "\r\n ")" - _debug "_accUri" "$_accUri" - if [ -z "$_accUri" ]; then - _err "Can not find account id url." - _err "$responseHeaders" - return 1 + if [ -z "$_eabAlreadyBound" ]; then + _debug2 responseHeaders "$responseHeaders" + _accUri="$(echo "$responseHeaders" | grep -i "^Location:" | _head_n 1 | cut -d ':' -f 2- | tr -d "\r\n ")" + _debug "_accUri" "$_accUri" + if [ -z "$_accUri" ]; then + _err "Can not find account id url." + _err "$responseHeaders" + return 1 + fi + _savecaconf "ACCOUNT_URL" "$_accUri" + else + ACCOUNT_URL="$(_readcaconf ACCOUNT_URL)" fi - _savecaconf "ACCOUNT_URL" "$_accUri" export ACCOUNT_URL="$_accUri" CA_KEY_HASH="$(__calcAccountKeyHash)" @@ -3606,9 +3661,10 @@ updateaccount() { fi _initAPI + _email="$(_getAccountEmail)" if [ "$ACME_VERSION" = "2" ]; then if [ "$ACCOUNT_EMAIL" ]; then - updjson='{"contact": ["mailto:'$ACCOUNT_EMAIL'"]}' + updjson='{"contact": ["mailto:'$_email'"]}' else updjson='{"contact": []}' fi @@ -4036,7 +4092,7 @@ issue() { else _cleardomainconf Le_API fi - + _info "Using CA: $ACME_DIRECTORY" if [ "$_alt_domains" = "$NO_VALUE" ]; then _alt_domains="" fi @@ -6491,12 +6547,6 @@ _processAccountConf() { _saveaccountconf "USER_AGENT" "$USER_AGENT" fi - if [ "$_accountemail" ]; then - _saveaccountconf "ACCOUNT_EMAIL" "$_accountemail" - elif [ "$ACCOUNT_EMAIL" ] && [ "$ACCOUNT_EMAIL" != "$DEFAULT_ACCOUNT_EMAIL" ]; then - _saveaccountconf "ACCOUNT_EMAIL" "$ACCOUNT_EMAIL" - fi - if [ "$_openssl_bin" ]; then _saveaccountconf "ACME_OPENSSL_BIN" "$_openssl_bin" elif [ "$ACME_OPENSSL_BIN" ] && [ "$ACME_OPENSSL_BIN" != "$DEFAULT_OPENSSL_BIN" ]; then From 85503655ab3a98854e69a302c1eaad370711c1e3 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 12 Aug 2020 20:47:17 +0800 Subject: [PATCH 147/161] Display ZeroSSL usage --- acme.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index d359a4bb..544555b9 100755 --- a/acme.sh +++ b/acme.sh @@ -3522,13 +3522,14 @@ _regAccount() { if [ -z "$_eab_id" ] || [ -z "$_eab_hmac_key" ]; then _info "No EAB credentials found for ZeroSSL, let's get one" if [ -z "$_email" ]; then - _err "Please provide a email address for zerossl account." + _err "Please provide a email address for ZeroSSL account." + _err "See ZeroSSL usage: $_ZEROSSL_WIKI" return 1 fi _eabresp=$(_post "email=$_email" $_ZERO_EAB_ENDPOINT) if [ "$?" != "0" ]; then _debug2 "$_eabresp" - _err "Can not get EAB credentials from zerossl." + _err "Can not get EAB credentials from ZeroSSL." return 1 fi _eab_id="$(echo "$_eabresp" | tr ',}' '\n' | grep '"eab_kid"' | cut -d : -f 2 | tr -d '"')" From f96d91cb6c518c93ba93c827228892b9ed36bc82 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 9 Aug 2020 09:34:43 +0800 Subject: [PATCH 148/161] eab --- acme.sh | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 67 insertions(+), 6 deletions(-) diff --git a/acme.sh b/acme.sh index 6a600087..1f6d2605 100755 --- a/acme.sh +++ b/acme.sh @@ -1507,6 +1507,19 @@ _url_replace() { tr '/+' '_-' | tr -d '= ' } +#base64 string +_durl_replace_base64() { + _l=$((${#1} % 4)) + if [ $_l -eq 2 ]; then + _s="$1"'==' + elif [ $_l -eq 3 ]; then + _s="$1"'=' + else + _s="$1" + fi + echo "$_s" | tr '_-' '/+' +} + _time2str() { #BSD if date -u -r "$1" 2>/dev/null; then @@ -3406,10 +3419,13 @@ _on_issue_success() { } +#account_key_length eab-kid eab-hmac-key registeraccount() { - _reg_length="$1" + _account_key_length="$1" + _eab_id="$2" + _eab_hmac_key="$3" _initpath - _regAccount "$_reg_length" + _regAccount "$_account_key_length" "$_eab_id" "$_eab_hmac_key" } __calcAccountKeyHash() { @@ -3424,6 +3440,8 @@ __calc_account_thumbprint() { _regAccount() { _initpath _reg_length="$1" + _eab_id="$2" + _eab_hmac_key="$3" _debug3 _regAccount "$_regAccount" _initAPI @@ -3448,12 +3466,41 @@ _regAccount() { if ! _calcjwk "$ACCOUNT_KEY_PATH"; then return 1 fi - + if [ "$_eab_id" ] && [ "$_eab_hmac_key" ]; then + _savecaconf CA_EAB_KEY_ID "$_eab_id" + _savecaconf CA_EAB_HMAC_KEY "$_eab_hmac_key" + fi + _eab_id=$(_readcaconf "CA_EAB_KEY_ID") + _eab_hmac_key=$(_readcaconf "CA_EAB_HMAC_KEY") + _secure_debug3 _eab_id "$_eab_id" + _secure_debug3 _eab_hmac_key "$_eab_hmac_key" if [ "$ACME_VERSION" = "2" ]; then - regjson='{"termsOfServiceAgreed": true}' + if [ "$_eab_id" ] && [ "$_eab_hmac_key" ]; then + eab_protected="{\"alg\":\"HS256\",\"kid\":\"$_eab_id\",\"url\":\"${ACME_NEW_ACCOUNT}\"}" + _debug3 eab_protected "$eab_protected" + + eab_protected64=$(printf "%s" "$eab_protected" | _base64 | _url_replace) + _debug3 eab_protected64 "$eab_protected64" + + eab_payload64=$(printf "%s" "$jwk" | _base64 | _url_replace) + _debug3 eab_payload64 "$eab_payload64" + + eab_sign_t="$eab_protected64.$eab_payload64" + _debug3 eab_sign_t "$eab_sign_t" + + key_hex="$(_durl_replace_base64 "$_eab_hmac_key" | _dbase64 | _hex_dump | tr -d ' ')" + _debug3 key_hex "$key_hex" + + eab_signature=$(printf "%s" "$eab_sign_t" | _hmac sha256 $key_hex | _base64 | _url_replace) + _debug3 eab_signature "$eab_signature" + + externalBinding=",\"externalAccountBinding\":{\"protected\":\"$eab_protected64\", \"payload\":\"$eab_payload64\", \"signature\":\"$eab_signature\"}" + _debug3 externalBinding "$externalBinding" + fi if [ "$ACCOUNT_EMAIL" ]; then - regjson='{"contact": ["mailto:'$ACCOUNT_EMAIL'"], "termsOfServiceAgreed": true}' + email_sg="\"contact\": [\"mailto:$ACCOUNT_EMAIL\"], " fi + regjson="{$email_sg\"termsOfServiceAgreed\": true$externalBinding}" else _reg_res="$ACME_NEW_ACCOUNT_RES" regjson='{"resource": "'$_reg_res'", "terms-of-service-agreed": true, "agreement": "'$ACME_AGREEMENT'"}' @@ -6278,6 +6325,10 @@ Parameters: --log-level 1|2 Specifies the log level, default is 1. --syslog [0|3|6|7] Syslog level, 0: disable syslog, 3: error, 6: info, 7: debug. + --eab-kid EAB_KID Key Identifier for External Account Binding. + --eab-hmac-key EAB_HMAC_KEY HMAC key for External Account Binding. + + These parameters are to install the cert to nginx/apache or any other server after issue/renew a cert: --cert-file After issue/renew, the cert will be copied to this path. @@ -6510,6 +6561,8 @@ _process() { _notify_level="" _notify_mode="" _revoke_reason="" + _eab_kid="" + _eab_hmac_key="" while [ ${#} -gt 0 ]; do case "${1}" in @@ -6990,6 +7043,14 @@ _process() { fi shift ;; + --eab-kid) + _eab_kid="$2" + shift + ;; + --eab-hmac-key) + _eab_hmac_key="$2" + shift + ;; *) _err "Unknown parameter : $1" return 1 @@ -7086,7 +7147,7 @@ _process() { deactivate "$_domain,$_altdomains" ;; registeraccount) - registeraccount "$_accountkeylength" + registeraccount "$_accountkeylength" "$_eab_kid" "$_eab_hmac_key" ;; updateaccount) updateaccount From 737e9e48cac1e415d8405f9e7e9cabf131da52df Mon Sep 17 00:00:00 2001 From: neil Date: Tue, 11 Aug 2020 23:28:52 +0800 Subject: [PATCH 149/161] 1. Support short names for `--server` parameter, The valid values are: letsencrypt, letsencrypt_test, buypass, buypass_test and zerossl 2. Support Zerossl.com acme protocol. 3. Add "--set-default-ca --server xxxx" command to set the default CA to use. --- acme.sh | 93 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 78 insertions(+), 15 deletions(-) diff --git a/acme.sh b/acme.sh index 1f6d2605..4bddab25 100755 --- a/acme.sh +++ b/acme.sh @@ -23,11 +23,27 @@ _SUB_FOLDERS="$_SUB_FOLDER_DNSAPI $_SUB_FOLDER_DEPLOY $_SUB_FOLDER_NOTIFY" LETSENCRYPT_CA_V1="https://acme-v01.api.letsencrypt.org/directory" LETSENCRYPT_STAGING_CA_V1="https://acme-staging.api.letsencrypt.org/directory" -LETSENCRYPT_CA_V2="https://acme-v02.api.letsencrypt.org/directory" -LETSENCRYPT_STAGING_CA_V2="https://acme-staging-v02.api.letsencrypt.org/directory" +CA_LETSENCRYPT_V2="https://acme-v02.api.letsencrypt.org/directory" +CA_LETSENCRYPT_V2_TEST="https://acme-staging-v02.api.letsencrypt.org/directory" -DEFAULT_CA=$LETSENCRYPT_CA_V2 -DEFAULT_STAGING_CA=$LETSENCRYPT_STAGING_CA_V2 +CA_BUYPASS="https://api.buypass.com/acme/directory" +CA_BUYPASS_TEST="https://api.test4.buypass.no/acme/directory" + +CA_ZEROSSL="https://acme.zerossl.com/v2/DV90" + + +DEFAULT_CA=$CA_LETSENCRYPT_V2 +DEFAULT_STAGING_CA=$CA_LETSENCRYPT_V2_TEST + +CA_NAMES=" +letsencrypt +letsencrypt_test,letsencrypttest +buypass +buypass_test,buypasstest +zerossl +" + +CA_SERVERS="$CA_LETSENCRYPT_V2,$CA_LETSENCRYPT_V2_TEST,$CA_BUYPASS,$CA_BUYPASS_TEST,$CA_ZEROSSL" DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)" DEFAULT_ACCOUNT_EMAIL="" @@ -140,6 +156,8 @@ _SUDO_WIKI="https://github.com/acmesh-official/acme.sh/wiki/sudo" _REVOKE_WIKI="https://github.com/acmesh-official/acme.sh/wiki/revokecert" +_ZEROSSL_WIKI="https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA" + _DNS_MANUAL_ERR="The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead." _DNS_MANUAL_WARN="It seems that you are using dns manual mode. please take care: $_DNS_MANUAL_ERR" @@ -2577,16 +2595,22 @@ _initpath() { fi if [ "$ACME_VERSION" = "2" ]; then - DEFAULT_CA="$LETSENCRYPT_CA_V2" - DEFAULT_STAGING_CA="$LETSENCRYPT_STAGING_CA_V2" + DEFAULT_CA="$CA_LETSENCRYPT_V2" + DEFAULT_STAGING_CA="$CA_LETSENCRYPT_V2_TEST" fi if [ -z "$ACME_DIRECTORY" ]; then - if [ -z "$STAGE" ]; then - ACME_DIRECTORY="$DEFAULT_CA" + default_acme_server=$(_readaccountconf "DEFAULT_ACME_SERVER") + _debug default_acme_server "$default_acme_server" + if [ "$default_acme_server" ]; then + ACME_DIRECTORY="$default_acme_server" else - ACME_DIRECTORY="$DEFAULT_STAGING_CA" - _info "Using stage ACME_DIRECTORY: $ACME_DIRECTORY" + if [ -z "$STAGE" ]; then + ACME_DIRECTORY="$DEFAULT_CA" + else + ACME_DIRECTORY="$DEFAULT_STAGING_CA" + _info "Using stage ACME_DIRECTORY: $ACME_DIRECTORY" + fi fi fi @@ -6301,6 +6325,7 @@ Commands: --createCSR, -ccsr Create CSR , professional use. --deactivate Deactivate the domain authz, professional use. --set-notify Set the cron notification hook, level or mode. + --set-default-ca Used with '--server' , to set the default CA to use to use. Parameters: @@ -6344,7 +6369,7 @@ Parameters: --cert-home Specifies the home dir to save all the certs, only valid for '--install' command. --config-home Specifies the home dir to save all the configurations. --useragent Specifies the user agent string. it will be saved for future use too. - --accountemail Specifies the account email, only valid for the '--install' and '--update-account' command. + --accountemail, -m Specifies the account email, only valid for the '--install' and '--update-account' command. --accountkey Specifies the account key path, only valid for the '--install' command. --days Specifies the days to renew the cert when using '--issue' command. The default value is $DEFAULT_RENEW days. --httpport Specifies the standalone listening port. Only valid if the server is behind a reverse proxy or load balancer. @@ -6510,6 +6535,39 @@ _checkSudo() { return 0 } +#server +_selectServer() { + _server="$1" + _server_lower="$(echo "$_server" | _lower_case)" + _sindex=0 + for snames in $CA_NAMES; do + snames="$(echo "$snames" | _lower_case)" + _sindex="$(_math $_sindex + 1)" + _debug2 "_selectServer try snames" "$snames" + for sname in $(echo "$snames" | tr ',' ' '); do + if [ "$_server_lower" = "$sname" ]; then + _debug2 "_selectServer match $sname" + _serverdir="$(_getfield "$CA_SERVERS" $_sindex)" + _debug "Selected server: $_serverdir" + ACME_DIRECTORY="$_serverdir" + export ACME_DIRECTORY + return + fi + done + done + ACME_DIRECTORY="$_server" + export ACME_DIRECTORY +} + +#set default ca to $ACME_DIRECTORY +setdefaultca() { + if [ -z "$ACME_DIRECTORY" ]; then + _err "Please give a --server parameter." + return 1 + fi + _saveaccountconf "DEFAULT_ACME_SERVER" "$ACME_DIRECTORY" +} + _process() { _CMD="" _domain="" @@ -6652,6 +6710,9 @@ _process() { --set-notify) _CMD="setnotify" ;; + --set-default-ca) + _CMD="setdefaultca" + ;; --domain | -d) _dvalue="$2" @@ -6690,9 +6751,8 @@ _process() { STAGE="1" ;; --server) - ACME_DIRECTORY="$2" - _server="$ACME_DIRECTORY" - export ACME_DIRECTORY + _server="$2" + _selectServer "$_server" shift ;; --debug) @@ -6849,7 +6909,7 @@ _process() { USER_AGENT="$_useragent" shift ;; - --accountemail) + --accountemail | -m) _accountemail="$2" ACCOUNT_EMAIL="$_accountemail" shift @@ -7179,6 +7239,9 @@ _process() { setnotify) setnotify "$_notify_hook" "$_notify_level" "$_notify_mode" ;; + setdefaultca) + setdefaultca + ;; *) if [ "$_CMD" ]; then _err "Invalid command: $_CMD" From d42ff227f1ce31f881d6f783874bc89733d0f007 Mon Sep 17 00:00:00 2001 From: neil Date: Tue, 11 Aug 2020 23:45:12 +0800 Subject: [PATCH 150/161] fix format --- acme.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/acme.sh b/acme.sh index 4bddab25..70795ff3 100755 --- a/acme.sh +++ b/acme.sh @@ -31,7 +31,6 @@ CA_BUYPASS_TEST="https://api.test4.buypass.no/acme/directory" CA_ZEROSSL="https://acme.zerossl.com/v2/DV90" - DEFAULT_CA=$CA_LETSENCRYPT_V2 DEFAULT_STAGING_CA=$CA_LETSENCRYPT_V2_TEST @@ -3512,10 +3511,10 @@ _regAccount() { eab_sign_t="$eab_protected64.$eab_payload64" _debug3 eab_sign_t "$eab_sign_t" - key_hex="$(_durl_replace_base64 "$_eab_hmac_key" | _dbase64 | _hex_dump | tr -d ' ')" + key_hex="$(_durl_replace_base64 "$_eab_hmac_key" | _dbase64 | _hex_dump | tr -d ' ')" _debug3 key_hex "$key_hex" - eab_signature=$(printf "%s" "$eab_sign_t" | _hmac sha256 $key_hex | _base64 | _url_replace) + eab_signature=$(printf "%s" "$eab_sign_t" | _hmac sha256 $key_hex | _base64 | _url_replace) _debug3 eab_signature "$eab_signature" externalBinding=",\"externalAccountBinding\":{\"protected\":\"$eab_protected64\", \"payload\":\"$eab_payload64\", \"signature\":\"$eab_signature\"}" @@ -7110,7 +7109,7 @@ _process() { --eab-hmac-key) _eab_hmac_key="$2" shift - ;; + ;; *) _err "Unknown parameter : $1" return 1 From 389518e1b89e5bf9b353b10026d3f4b203410ff9 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 12 Aug 2020 20:43:44 +0800 Subject: [PATCH 151/161] 1. move email to ca conf 2. get EAB credentials from Zerossl by email automatically --- README.md | 1 + acme.sh | 94 ++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 73 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 2da103b2..f5631475 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ https://github.com/acmesh-official/acmetest # Supported CA - Letsencrypt.org CA(default) +- [ZeroSSL.com CA](https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA) - [BuyPass.com CA](https://github.com/acmesh-official/acme.sh/wiki/BuyPass.com-CA) - [Pebble strict Mode](https://github.com/letsencrypt/pebble) diff --git a/acme.sh b/acme.sh index 70795ff3..d359a4bb 100755 --- a/acme.sh +++ b/acme.sh @@ -30,6 +30,8 @@ CA_BUYPASS="https://api.buypass.com/acme/directory" CA_BUYPASS_TEST="https://api.test4.buypass.no/acme/directory" CA_ZEROSSL="https://acme.zerossl.com/v2/DV90" +_ZERO_EAB_ENDPOINT="http://api.zerossl.com/acme/eab-credentials-email" + DEFAULT_CA=$CA_LETSENCRYPT_V2 DEFAULT_STAGING_CA=$CA_LETSENCRYPT_V2_TEST @@ -45,7 +47,6 @@ zerossl CA_SERVERS="$CA_LETSENCRYPT_V2,$CA_LETSENCRYPT_V2_TEST,$CA_BUYPASS,$CA_BUYPASS_TEST,$CA_ZEROSSL" DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)" -DEFAULT_ACCOUNT_EMAIL="" DEFAULT_ACCOUNT_KEY_LENGTH=2048 DEFAULT_DOMAIN_KEY_LENGTH=2048 @@ -3459,6 +3460,21 @@ __calc_account_thumbprint() { printf "%s" "$jwk" | tr -d ' ' | _digest "sha256" | _url_replace } +_getAccountEmail() { + if [ "$ACCOUNT_EMAIL" ]; then + echo "$ACCOUNT_EMAIL" + return 0 + fi + if [ -z "$CA_EMAIL" ]; then + CA_EMAIL="$(_readcaconf CA_EMAIL)" + fi + if [ "$CA_EMAIL" ]; then + echo "$CA_EMAIL" + return 0 + fi + _readaccountconf "ACCOUNT_EMAIL" +} + #keylength _regAccount() { _initpath @@ -3497,7 +3513,38 @@ _regAccount() { _eab_hmac_key=$(_readcaconf "CA_EAB_HMAC_KEY") _secure_debug3 _eab_id "$_eab_id" _secure_debug3 _eab_hmac_key "$_eab_hmac_key" + _email="$(_getAccountEmail)" + if [ "$_email" ]; then + _savecaconf "CA_EMAIL" "$_email" + fi if [ "$ACME_VERSION" = "2" ]; then + if [ "$ACME_DIRECTORY" = "$CA_ZEROSSL" ]; then + if [ -z "$_eab_id" ] || [ -z "$_eab_hmac_key" ]; then + _info "No EAB credentials found for ZeroSSL, let's get one" + if [ -z "$_email" ]; then + _err "Please provide a email address for zerossl account." + return 1 + fi + _eabresp=$(_post "email=$_email" $_ZERO_EAB_ENDPOINT) + if [ "$?" != "0" ]; then + _debug2 "$_eabresp" + _err "Can not get EAB credentials from zerossl." + return 1 + fi + _eab_id="$(echo "$_eabresp" | tr ',}' '\n' | grep '"eab_kid"' | cut -d : -f 2 | tr -d '"')" + if [ -z "$_eab_id" ]; then + _err "Can not resolve _eab_id"; + return 1 + fi + _eab_hmac_key="$(echo "$_eabresp" | tr ',}' '\n' | grep '"eab_hmac_key"' | cut -d : -f 2 | tr -d '"')" + if [ -z "$_eab_hmac_key" ]; then + _err "Can not resolve _eab_hmac_key"; + return 1 + fi + _savecaconf CA_EAB_KEY_ID "$_eab_id" + _savecaconf CA_EAB_HMAC_KEY "$_eab_hmac_key" + fi + fi if [ "$_eab_id" ] && [ "$_eab_hmac_key" ]; then eab_protected="{\"alg\":\"HS256\",\"kid\":\"$_eab_id\",\"url\":\"${ACME_NEW_ACCOUNT}\"}" _debug3 eab_protected "$eab_protected" @@ -3520,44 +3567,52 @@ _regAccount() { externalBinding=",\"externalAccountBinding\":{\"protected\":\"$eab_protected64\", \"payload\":\"$eab_payload64\", \"signature\":\"$eab_signature\"}" _debug3 externalBinding "$externalBinding" fi - if [ "$ACCOUNT_EMAIL" ]; then - email_sg="\"contact\": [\"mailto:$ACCOUNT_EMAIL\"], " + if [ "$_email" ]; then + email_sg="\"contact\": [\"mailto:$_email\"], " fi regjson="{$email_sg\"termsOfServiceAgreed\": true$externalBinding}" else _reg_res="$ACME_NEW_ACCOUNT_RES" regjson='{"resource": "'$_reg_res'", "terms-of-service-agreed": true, "agreement": "'$ACME_AGREEMENT'"}' - if [ "$ACCOUNT_EMAIL" ]; then - regjson='{"resource": "'$_reg_res'", "contact": ["mailto:'$ACCOUNT_EMAIL'"], "terms-of-service-agreed": true, "agreement": "'$ACME_AGREEMENT'"}' + if [ "$_email" ]; then + regjson='{"resource": "'$_reg_res'", "contact": ["mailto:'$_email'"], "terms-of-service-agreed": true, "agreement": "'$ACME_AGREEMENT'"}' fi fi - _info "Registering account" + _info "Registering account: $ACME_DIRECTORY" if ! _send_signed_request "${ACME_NEW_ACCOUNT}" "$regjson"; then _err "Register account Error: $response" return 1 fi + _eabAlreadyBound="" if [ "$code" = "" ] || [ "$code" = '201' ]; then echo "$response" >"$ACCOUNT_JSON_PATH" _info "Registered" elif [ "$code" = '409' ] || [ "$code" = '200' ]; then _info "Already registered" + elif [ "$code" = '400' ] && _contains "$response" 'The account is not awaiting external account binding'; then + _info "Already register EAB." + _eabAlreadyBound=1 else _err "Register account Error: $response" return 1 fi - _debug2 responseHeaders "$responseHeaders" - _accUri="$(echo "$responseHeaders" | grep -i "^Location:" | _head_n 1 | cut -d ':' -f 2- | tr -d "\r\n ")" - _debug "_accUri" "$_accUri" - if [ -z "$_accUri" ]; then - _err "Can not find account id url." - _err "$responseHeaders" - return 1 + if [ -z "$_eabAlreadyBound" ]; then + _debug2 responseHeaders "$responseHeaders" + _accUri="$(echo "$responseHeaders" | grep -i "^Location:" | _head_n 1 | cut -d ':' -f 2- | tr -d "\r\n ")" + _debug "_accUri" "$_accUri" + if [ -z "$_accUri" ]; then + _err "Can not find account id url." + _err "$responseHeaders" + return 1 + fi + _savecaconf "ACCOUNT_URL" "$_accUri" + else + ACCOUNT_URL="$(_readcaconf ACCOUNT_URL)" fi - _savecaconf "ACCOUNT_URL" "$_accUri" export ACCOUNT_URL="$_accUri" CA_KEY_HASH="$(__calcAccountKeyHash)" @@ -3606,9 +3661,10 @@ updateaccount() { fi _initAPI + _email="$(_getAccountEmail)" if [ "$ACME_VERSION" = "2" ]; then if [ "$ACCOUNT_EMAIL" ]; then - updjson='{"contact": ["mailto:'$ACCOUNT_EMAIL'"]}' + updjson='{"contact": ["mailto:'$_email'"]}' else updjson='{"contact": []}' fi @@ -4036,7 +4092,7 @@ issue() { else _cleardomainconf Le_API fi - + _info "Using CA: $ACME_DIRECTORY" if [ "$_alt_domains" = "$NO_VALUE" ]; then _alt_domains="" fi @@ -6491,12 +6547,6 @@ _processAccountConf() { _saveaccountconf "USER_AGENT" "$USER_AGENT" fi - if [ "$_accountemail" ]; then - _saveaccountconf "ACCOUNT_EMAIL" "$_accountemail" - elif [ "$ACCOUNT_EMAIL" ] && [ "$ACCOUNT_EMAIL" != "$DEFAULT_ACCOUNT_EMAIL" ]; then - _saveaccountconf "ACCOUNT_EMAIL" "$ACCOUNT_EMAIL" - fi - if [ "$_openssl_bin" ]; then _saveaccountconf "ACME_OPENSSL_BIN" "$_openssl_bin" elif [ "$ACME_OPENSSL_BIN" ] && [ "$ACME_OPENSSL_BIN" != "$DEFAULT_OPENSSL_BIN" ]; then From 578c338d40781689dc6e1ce9ae6d12da92f03893 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 12 Aug 2020 20:47:17 +0800 Subject: [PATCH 152/161] Display ZeroSSL usage --- acme.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index d359a4bb..544555b9 100755 --- a/acme.sh +++ b/acme.sh @@ -3522,13 +3522,14 @@ _regAccount() { if [ -z "$_eab_id" ] || [ -z "$_eab_hmac_key" ]; then _info "No EAB credentials found for ZeroSSL, let's get one" if [ -z "$_email" ]; then - _err "Please provide a email address for zerossl account." + _err "Please provide a email address for ZeroSSL account." + _err "See ZeroSSL usage: $_ZEROSSL_WIKI" return 1 fi _eabresp=$(_post "email=$_email" $_ZERO_EAB_ENDPOINT) if [ "$?" != "0" ]; then _debug2 "$_eabresp" - _err "Can not get EAB credentials from zerossl." + _err "Can not get EAB credentials from ZeroSSL." return 1 fi _eab_id="$(echo "$_eabresp" | tr ',}' '\n' | grep '"eab_kid"' | cut -d : -f 2 | tr -d '"')" From 365aa69afd04d732c14c6e0b8bf7509fcd0ffafb Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 12 Aug 2020 20:48:21 +0800 Subject: [PATCH 153/161] fix format --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 544555b9..d57ff9a8 100755 --- a/acme.sh +++ b/acme.sh @@ -3534,12 +3534,12 @@ _regAccount() { fi _eab_id="$(echo "$_eabresp" | tr ',}' '\n' | grep '"eab_kid"' | cut -d : -f 2 | tr -d '"')" if [ -z "$_eab_id" ]; then - _err "Can not resolve _eab_id"; + _err "Can not resolve _eab_id" return 1 fi _eab_hmac_key="$(echo "$_eabresp" | tr ',}' '\n' | grep '"eab_hmac_key"' | cut -d : -f 2 | tr -d '"')" if [ -z "$_eab_hmac_key" ]; then - _err "Can not resolve _eab_hmac_key"; + _err "Can not resolve _eab_hmac_key" return 1 fi _savecaconf CA_EAB_KEY_ID "$_eab_id" From df22f68088d28a6f7f020259afc222c989f6f9cd Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 12 Aug 2020 21:25:35 +0800 Subject: [PATCH 154/161] Add info for set-default-ca --- acme.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/acme.sh b/acme.sh index ea5676f9..bcfaa8b1 100755 --- a/acme.sh +++ b/acme.sh @@ -6618,6 +6618,7 @@ setdefaultca() { return 1 fi _saveaccountconf "DEFAULT_ACME_SERVER" "$ACME_DIRECTORY" + _info "Changed default CA to: $(__green "$ACME_DIRECTORY")" } _process() { From 269847d19dd396ca0c4885ff57e737839fa98296 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 12 Aug 2020 21:45:20 +0800 Subject: [PATCH 155/161] Add CA name to the `--list` command output. --- acme.sh | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/acme.sh b/acme.sh index bcfaa8b1..b7d45f5d 100755 --- a/acme.sh +++ b/acme.sh @@ -37,11 +37,11 @@ DEFAULT_CA=$CA_LETSENCRYPT_V2 DEFAULT_STAGING_CA=$CA_LETSENCRYPT_V2_TEST CA_NAMES=" -letsencrypt -letsencrypt_test,letsencrypttest -buypass -buypass_test,buypasstest -zerossl +Letsencrypt.org,letsencrypt +Letsencrypt.org_test,letsencrypt_test,letsencrypttest +BuyPass.com,buypass +BuyPass.com_test,buypass_test,buypasstest +ZeroSSL.com,zerossl " CA_SERVERS="$CA_LETSENCRYPT_V2,$CA_LETSENCRYPT_V2_TEST,$CA_BUYPASS,$CA_BUYPASS_TEST,$CA_ZEROSSL" @@ -5254,7 +5254,7 @@ list() { _sep="|" if [ "$_raw" ]; then - printf "%s\n" "Main_Domain${_sep}KeyLength${_sep}SAN_Domains${_sep}Created${_sep}Renew" + printf "%s\n" "Main_Domain${_sep}KeyLength${_sep}SAN_Domains${_sep}CA${_sep}Created${_sep}Renew" for di in "${CERT_HOME}"/*.*/; do d=$(basename "$di") _debug d "$d" @@ -5266,7 +5266,8 @@ list() { DOMAIN_CONF="$di/$d.conf" if [ -f "$DOMAIN_CONF" ]; then . "$DOMAIN_CONF" - printf "%s\n" "$Le_Domain${_sep}\"$Le_Keylength\"${_sep}$Le_Alt${_sep}$Le_CertCreateTimeStr${_sep}$Le_NextRenewTimeStr" + _ca="$(_getCAShortName "$Le_API")" + printf "%s\n" "$Le_Domain${_sep}\"$Le_Keylength\"${_sep}$Le_Alt${_sep}$_ca${_sep}$Le_CertCreateTimeStr${_sep}$Le_NextRenewTimeStr" fi ) done @@ -6611,6 +6612,27 @@ _selectServer() { export ACME_DIRECTORY } +#url +_getCAShortName() { + caurl="$1" + caurl_lower="$(echo $caurl | _lower_case)" + _sindex=0 + for surl in $(echo "$CA_SERVERS" | _lower_case | tr , ' '); do + _sindex="$(_math $_sindex + 1)" + if [ "$caurl_lower" = "$surl" ]; then + _nindex=0 + for snames in $CA_NAMES; do + _nindex="$(_math $_nindex + 1)" + if [ $_nindex -ge $_sindex ]; then + _getfield "$snames" 1 + return + fi + done + fi + done + echo "$caurl" +} + #set default ca to $ACME_DIRECTORY setdefaultca() { if [ -z "$ACME_DIRECTORY" ]; then From 1177cc3f29964db6983143a1d25d6758e7798e6d Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 12 Aug 2020 22:09:37 +0800 Subject: [PATCH 156/161] fix format --- acme.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/acme.sh b/acme.sh index b7d45f5d..9505ae2c 100755 --- a/acme.sh +++ b/acme.sh @@ -32,7 +32,6 @@ CA_BUYPASS_TEST="https://api.test4.buypass.no/acme/directory" CA_ZEROSSL="https://acme.zerossl.com/v2/DV90" _ZERO_EAB_ENDPOINT="http://api.zerossl.com/acme/eab-credentials-email" - DEFAULT_CA=$CA_LETSENCRYPT_V2 DEFAULT_STAGING_CA=$CA_LETSENCRYPT_V2_TEST From f1318636428eefaa0472f28902d2fd19a832a0c4 Mon Sep 17 00:00:00 2001 From: "kapper.net support account" Date: Wed, 12 Aug 2020 23:48:11 +0200 Subject: [PATCH 157/161] now with "_saveaccountconf_mutable" _saveaccountconf_mutable instead of _saveaccountconf now used. Co-Authored-By: kapper.net support account <33451837+kappernet@users.noreply.github.com> --- dnsapi/dns_kappernet.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_kappernet.sh b/dnsapi/dns_kappernet.sh index a059447a..70a3ea23 100644 --- a/dnsapi/dns_kappernet.sh +++ b/dnsapi/dns_kappernet.sh @@ -26,8 +26,8 @@ dns_kappernet_add() { fi #store the api key and email to the account conf file. - _saveaccountconf KAPPERNETDNS_Key "$KAPPERNETDNS_Key" - _saveaccountconf KAPPERNETDNS_Secret "$KAPPERNETDNS_Secret" + _saveaccountconf_mutable KAPPERNETDNS_Key "$KAPPERNETDNS_Key" + _saveaccountconf_mutable KAPPERNETDNS_Secret "$KAPPERNETDNS_Secret" _debug "Checking Domain ..." if ! _get_root "$fullhostname"; then _err "invalid domain" @@ -69,8 +69,8 @@ dns_kappernet_rm() { fi #store the api key and email to the account conf file. - _saveaccountconf KAPPERNETDNS_Key "$KAPPERNETDNS_Key" - _saveaccountconf KAPPERNETDNS_Secret "$KAPPERNETDNS_Secret" + _saveaccountconf_mutable KAPPERNETDNS_Key "$KAPPERNETDNS_Key" + _saveaccountconf_mutable KAPPERNETDNS_Secret "$KAPPERNETDNS_Secret" _info "Trying to remove the TXT Record: $fullhostname" data="%7B%22name%22%3A%22$fullhostname%22%2C%22type%22%3A%22TXT%22%2C%22content%22%3A%22$txtvalue%22%2C%22ttl%22%3A%223600%22%2C%22prio%22%3A%22%22%7D" From 0052ab7148a930183e39db4192ec250a3b84bfc0 Mon Sep 17 00:00:00 2001 From: "kapper.net support account" Date: Thu, 13 Aug 2020 00:23:57 +0200 Subject: [PATCH 158/161] more mutable + style-update more mutable config-read-calls more details for TXT records info + errors; typo fixed (create instead of delete) --- dnsapi/dns_kappernet.sh | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/dnsapi/dns_kappernet.sh b/dnsapi/dns_kappernet.sh index 70a3ea23..47a871c1 100644 --- a/dnsapi/dns_kappernet.sh +++ b/dnsapi/dns_kappernet.sh @@ -17,11 +17,15 @@ dns_kappernet_add() { fullhostname=$1 txtvalue=$2 + KAPPERNETDNS_Key="${KAPPERNETDNS_Key:-$(_readaccountconf_mutable KAPPERNETDNS_Key)}" + KAPPERNETDNS_Secret="${KAPPERNETDNS_Secret:-$(_readaccountconf_mutable KAPPERNETDNS_Secret)}" + if [ -z "$KAPPERNETDNS_Key" ] || [ -z "$KAPPERNETDNS_Secret" ]; then KAPPERNETDNS_Key="" KAPPERNETDNS_Secret="" - _err "You haven't defined kapper.net api key and secret yet." - _err "Please send us mail to support@kapper.net get your key and secret." + _err "Please specify your kapper.net api key and secret." + _err "If you have not received yours - send your mail to" + _err "support@kapper.net to get your key and secret." return 1 fi @@ -60,11 +64,15 @@ dns_kappernet_rm() { fullhostname=$1 txtvalue=$2 + KAPPERNETDNS_Key="${KAPPERNETDNS_Key:-$(_readaccountconf_mutable KAPPERNETDNS_Key)}" + KAPPERNETDNS_Secret="${KAPPERNETDNS_Secret:-$(_readaccountconf_mutable KAPPERNETDNS_Secret)}" + if [ -z "$KAPPERNETDNS_Key" ] || [ -z "$KAPPERNETDNS_Secret" ]; then KAPPERNETDNS_Key="" KAPPERNETDNS_Secret="" - _err "You haven't defined kapper.net api key and secret yet." - _err "Please send us mail to get your key and secret." + _err "Please specify your kapper.net api key and secret." + _err "If you have not received yours - send your mail to" + _err "support@kapper.net to get your key and secret." return 1 fi @@ -72,18 +80,18 @@ dns_kappernet_rm() { _saveaccountconf_mutable KAPPERNETDNS_Key "$KAPPERNETDNS_Key" _saveaccountconf_mutable KAPPERNETDNS_Secret "$KAPPERNETDNS_Secret" - _info "Trying to remove the TXT Record: $fullhostname" + _info "Trying to remove the TXT Record: $fullhostname containing $txtvalue" data="%7B%22name%22%3A%22$fullhostname%22%2C%22type%22%3A%22TXT%22%2C%22content%22%3A%22$txtvalue%22%2C%22ttl%22%3A%223600%22%2C%22prio%22%3A%22%22%7D" if _kappernet_api GET "action=del&subject=$fullhostname&data=$data"; then if _contains "$response" "{\"OK\":true"; then return 0 else - _err "Error deleting DNS Record: $fullhostname" + _err "Error deleting DNS Record: $fullhostname containing $txtvalue" _err "Problem: $response" return 1 fi fi - _err "Problem creating TXT DNS record" + _err "Problem deleting TXT DNS record" } #################### Private functions below ################################## From 0415c050a5dbce75ed8bf89abb9ef2d361a1e589 Mon Sep 17 00:00:00 2001 From: neil Date: Thu, 13 Aug 2020 23:04:19 +0800 Subject: [PATCH 159/161] remove gitads --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index f5631475..e50489dc 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,6 @@ acme.sh is being sponsored by the following tool; please help to support us by taking a look and signing up to a free trial - GitAds - - - - An ACME protocol client written purely in Shell (Unix shell) language. - Full ACME protocol implementation. - Support ACME v1 and ACME v2 From a6d22e3b2215f85ca1f5cae7fa73adbc34697125 Mon Sep 17 00:00:00 2001 From: neil Date: Thu, 13 Aug 2020 23:12:30 +0800 Subject: [PATCH 160/161] 1. save the CA url anyway. 2. clear some code. --- acme.sh | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/acme.sh b/acme.sh index 9505ae2c..406a158d 100755 --- a/acme.sh +++ b/acme.sh @@ -52,9 +52,6 @@ DEFAULT_DOMAIN_KEY_LENGTH=2048 DEFAULT_OPENSSL_BIN="openssl" -_OLD_CA_HOST="https://acme-v01.api.letsencrypt.org" -_OLD_STAGE_CA_HOST="https://acme-staging.api.letsencrypt.org" - VTYPE_HTTP="http-01" VTYPE_DNS="dns-01" VTYPE_ALPN="tls-alpn-01" @@ -2595,11 +2592,6 @@ _initpath() { CA_HOME="$DEFAULT_CA_HOME" fi - if [ "$ACME_VERSION" = "2" ]; then - DEFAULT_CA="$CA_LETSENCRYPT_V2" - DEFAULT_STAGING_CA="$CA_LETSENCRYPT_V2_TEST" - fi - if [ -z "$ACME_DIRECTORY" ]; then default_acme_server=$(_readaccountconf "DEFAULT_ACME_SERVER") _debug default_acme_server "$default_acme_server" @@ -4088,12 +4080,9 @@ issue() { _cleardomainconf "Le_ChallengeAlias" fi - if [ "$ACME_DIRECTORY" != "$DEFAULT_CA" ]; then - Le_API="$ACME_DIRECTORY" - _savedomainconf "Le_API" "$Le_API" - else - _cleardomainconf Le_API - fi + Le_API="$ACME_DIRECTORY" + _savedomainconf "Le_API" "$Le_API" + _info "Using CA: $ACME_DIRECTORY" if [ "$_alt_domains" = "$NO_VALUE" ]; then _alt_domains="" @@ -4980,14 +4969,6 @@ renew() { fi if [ "$Le_API" ]; then - if [ "$_OLD_CA_HOST" = "$Le_API" ]; then - export Le_API="$DEFAULT_CA" - _savedomainconf Le_API "$Le_API" - fi - if [ "$_OLD_STAGE_CA_HOST" = "$Le_API" ]; then - export Le_API="$DEFAULT_STAGING_CA" - _savedomainconf Le_API "$Le_API" - fi export ACME_DIRECTORY="$Le_API" #reload ca configs ACCOUNT_KEY_PATH="" From b3a801df110d75886e15e8f6f10e8b1c77b0301a Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 15 Aug 2020 10:33:24 +0800 Subject: [PATCH 161/161] fix test endpoint --- acme.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/acme.sh b/acme.sh index 406a158d..a7e6d7ef 100755 --- a/acme.sh +++ b/acme.sh @@ -2593,16 +2593,16 @@ _initpath() { fi if [ -z "$ACME_DIRECTORY" ]; then - default_acme_server=$(_readaccountconf "DEFAULT_ACME_SERVER") - _debug default_acme_server "$default_acme_server" - if [ "$default_acme_server" ]; then - ACME_DIRECTORY="$default_acme_server" + if [ "$STAGE" ]; then + ACME_DIRECTORY="$DEFAULT_STAGING_CA" + _info "Using stage ACME_DIRECTORY: $ACME_DIRECTORY" else - if [ -z "$STAGE" ]; then - ACME_DIRECTORY="$DEFAULT_CA" + default_acme_server=$(_readaccountconf "DEFAULT_ACME_SERVER") + _debug default_acme_server "$default_acme_server" + if [ "$default_acme_server" ]; then + ACME_DIRECTORY="$default_acme_server" else - ACME_DIRECTORY="$DEFAULT_STAGING_CA" - _info "Using stage ACME_DIRECTORY: $ACME_DIRECTORY" + ACME_DIRECTORY="$DEFAULT_CA" fi fi fi