From 6c3430b6e592b0dad0783c4daee0ee692d5e0484 Mon Sep 17 00:00:00 2001 From: 2globalnomads Date: Sun, 2 Jul 2017 23:24:14 +0400 Subject: [PATCH 01/90] Wrote missing cpanel.sh This script I wrote works for me on GoDaddy, but I don't have any other hosting services or cpanel version to test it. Hope it's better than nothing for you. Thanks for your great script! Cheers, Santeri --- deploy/cpanel.sh | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/deploy/cpanel.sh b/deploy/cpanel.sh index bf1332ff..6ab012a3 100644 --- a/deploy/cpanel.sh +++ b/deploy/cpanel.sh @@ -1,8 +1,9 @@ -#!/usr/bin/env sh - -#Here is the script to deploy the cert to your cpanel account by the cpanel APIs. - -#returns 0 means success, otherwise error. +#!/bin/bash +# Here is the script to deploy the cert to your cpanel using the cpanel API. +# Uses command line uapi. Cpanel username is needed only when run as root. +# Returns 0 when success, otherwise error. +# Written by Santeri Kannisto +# Public domain, 2017 #export DEPLOY_CPANEL_USER=myusername #export DEPLOY_CPANEL_PASSWORD=PASSWORD @@ -10,6 +11,7 @@ ######## Public functions ##################### #domain keyfile certfile cafile fullchain + cpanel_deploy() { _cdomain="$1" _ckey="$2" @@ -23,7 +25,33 @@ cpanel_deploy() { _debug _cca "$_cca" _debug _cfullchain "$_cfullchain" - _err "Not implemented yet" - return 1 + # read cert and key files and urlencode both + _certstr=`cat "$_ccert"` + _keystr=`cat "$_ckey"` + _cert=$(php -r "echo urlencode(\"$_certstr\");") + _key=$(php -r "echo urlencode(\"$_keystr\");") + + _debug _cert "$_cert" + _debug _key "$_key" + + if [[ $EUID -eq 0 ]] + then + _opt="--user=$DEPLOY_CPANEL_USER SSL install_ssl" + else + _opt="SSL install_ssl" + fi + + _debug _opt "$_opt" + + response=$(uapi $_opt domain="$_cdommain" cert="$_cert" key="$_key") + + if [ $? -ne 0 ] + then + _err "Error in deploying certificate:" + _err "$response" + return 1 + fi + _debug response "$response" + _info "Certificate successfully deployed" } From 796647158ea23ebf673d817a254e1d61c7ce652c Mon Sep 17 00:00:00 2001 From: Santeri Date: Mon, 10 Jul 2017 15:36:16 +0400 Subject: [PATCH 02/90] Removed double quotes from _opt Broke GoDaddy cpanel causing error (thanks Hedgehog) --- deploy/cpanel.sh | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/deploy/cpanel.sh b/deploy/cpanel.sh index 6ab012a3..b9552397 100644 --- a/deploy/cpanel.sh +++ b/deploy/cpanel.sh @@ -1,12 +1,12 @@ -#!/bin/bash +#!/usr/bin/env sh # Here is the script to deploy the cert to your cpanel using the cpanel API. -# Uses command line uapi. Cpanel username is needed only when run as root. -# Returns 0 when success, otherwise error. +# Uses command line uapi. +# Cpanel username is needed only when run as root (I did not test this). +# Returns 0 when success. # Written by Santeri Kannisto # Public domain, 2017 #export DEPLOY_CPANEL_USER=myusername -#export DEPLOY_CPANEL_PASSWORD=PASSWORD ######## Public functions ##################### @@ -26,32 +26,28 @@ cpanel_deploy() { _debug _cfullchain "$_cfullchain" # read cert and key files and urlencode both - _certstr=`cat "$_ccert"` - _keystr=`cat "$_ckey"` + _certstr=$(cat "$_ccert") + _keystr=$(cat "$_ckey") _cert=$(php -r "echo urlencode(\"$_certstr\");") _key=$(php -r "echo urlencode(\"$_keystr\");") _debug _cert "$_cert" _debug _key "$_key" - if [[ $EUID -eq 0 ]] - then - _opt="--user=$DEPLOY_CPANEL_USER SSL install_ssl" - else - _opt="SSL install_ssl" - fi - - _debug _opt "$_opt" + if [ "$(id -u)" = 0 ]; then + _opt="--user=$DEPLOY_CPANEL_USER" + _debug _opt "$_opt" + fi - response=$(uapi $_opt domain="$_cdommain" cert="$_cert" key="$_key") + _response=$(uapi $_opt SSL install_ssl domain="$_cdomain" cert="$_cert" key="$_key") - if [ $? -ne 0 ] - then + if [ $? -ne 0 ]; then _err "Error in deploying certificate:" - _err "$response" + _err "$_response" return 1 fi - _debug response "$response" + _debug response "$_response" _info "Certificate successfully deployed" + return 0 } From a577c7215f0b2a5ad6729b175fb6e0033abeb4d5 Mon Sep 17 00:00:00 2001 From: Santeri Date: Mon, 10 Jul 2017 16:43:42 +0400 Subject: [PATCH 03/90] One more change to pass the check shellcheck test Now it is tested and works also when run as a root. --- deploy/cpanel.sh | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/deploy/cpanel.sh b/deploy/cpanel.sh index b9552397..9de8dbbb 100644 --- a/deploy/cpanel.sh +++ b/deploy/cpanel.sh @@ -1,7 +1,6 @@ #!/usr/bin/env sh # Here is the script to deploy the cert to your cpanel using the cpanel API. -# Uses command line uapi. -# Cpanel username is needed only when run as root (I did not test this). +# Uses command line uapi. --user option is needed only if run as root. # Returns 0 when success. # Written by Santeri Kannisto # Public domain, 2017 @@ -35,12 +34,11 @@ cpanel_deploy() { _debug _key "$_key" if [ "$(id -u)" = 0 ]; then - _opt="--user=$DEPLOY_CPANEL_USER" - _debug _opt "$_opt" + _response=$(uapi --user="$DEPLOY_CPANEL_USER" SSL install_ssl domain="$_cdomain" cert="$_cert" key="$_key") + else + _response=$(uapi SSL install_ssl domain="$_cdomain" cert="$_cert" key="$_key") fi - _response=$(uapi $_opt SSL install_ssl domain="$_cdomain" cert="$_cert" key="$_key") - if [ $? -ne 0 ]; then _err "Error in deploying certificate:" _err "$_response" From 7d64e141e45be32479773f8a4fb44bd8304dacc1 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Wed, 12 Jul 2017 20:24:54 +0200 Subject: [PATCH 04/90] Add dns_he - DNS API script for Hurricane Electric DNS service ... Although not yet fully Posix compatible. --- dnsapi/README.md | 18 +++++ dnsapi/dns_he.sh | 200 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 218 insertions(+) create mode 100755 dnsapi/dns_he.sh diff --git a/dnsapi/README.md b/dnsapi/README.md index 41f89a88..15399048 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -572,6 +572,24 @@ acme.sh --issue --dns dns_dyn -d example.com -d www.example.com The `DYN_Customer`, `DYN_Username` and `DYN_Password` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. +# 30. Use Hurricane Electric + +Hurricane Electric doesn't have an API so just set your login credentials like so: + +``` +export HE_Username="yourusername" +export HE_Password="password" +``` + +Then you can issue your certificate: + +``` +acme.sh --issue --dns dns_he -d example.com -d www.example.com +``` + +The `HE_Username` and `HE_Password` settings will be saved in `~/.acme.sh/account.conf` and will be reused when needed. + +Please report any issues to https://github.com/angel333/acme.sh or to . # Use custom API diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh new file mode 100755 index 00000000..269db8d2 --- /dev/null +++ b/dnsapi/dns_he.sh @@ -0,0 +1,200 @@ +#!/usr/bin/env sh + +# TODO Somehow use _get instead of curl - not sure how to support +# cookies though... + +######################################################################## +# Hurricane Electric hook script for acme.sh +# +# Environment variables: +# +# - $HE_Username (your dns.he.net username) +# - $HE_Password (your dns.he.net password) +# +# Author: Ondrej Simek +# Git repo: https://github.com/angel333/acme.sh + + +#-- dns_he_add() - Add TXT record -------------------------------------- +# Usage: dns_he_add _acme-challenge.subdomain.domain.com "XyZ123..." + +dns_he_add() { + _full_domain=$1 + _txt_value=$2 + _info "Using DNS-01 Hurricane Electric hook" + + _authenticate || return 1 + _saveaccountconf HE_Username "$HE_Username" + _saveaccountconf HE_Password "$HE_Password" + + # fills in the $_zone_id + _find_zone $_full_domain || return 1 + _debug "Zone id \"$_zone_id\" will be used." + + curl -L --silent --show-error --cookie "$_he_cookie" \ + --form "account=" \ + --form "menu=edit_zone" \ + --form "Type=TXT" \ + --form "hosted_dns_zoneid=$_zone_id" \ + --form "hosted_dns_recordid=" \ + --form "hosted_dns_editzone=1" \ + --form "Priority=" \ + --form "Name=$_full_domain" \ + --form "Content=$_txt_value" \ + --form "TTL=300" \ + --form "hosted_dns_editrecord=Submit" \ + "https://dns.he.net/" \ + > /dev/null +} + + +#-- dns_he_rm() - Remove TXT record ------------------------------------ +# Usage: dns_he_rm _acme-challenge.subdomain.domain.com "XyZ123..." + +dns_he_rm() { + _full_domain=$1 + _txt_value=$2 + _info "Cleaning up after DNS-01 Hurricane Electric hook" + + _authenticate || return 1 + + # fills in the $_zone_id + _find_zone $_full_domain || return 1 + _debug "Zone id \"$_zone_id\" will be used." + + # Find the record id to clean + _record_id=$( \ + curl -L --silent --show-error --cookie "$_he_cookie" \ + "https://dns.he.net/?hosted_dns_zoneid=$_zone_id&menu=edit_zone&hosted_dns_editzone" \ + | grep -A 1 "data=\"\("\)\?${_txt_value}\("\)\?\"" \ + | tail -n 1 \ + | _egrep_o "'[[:digit:]]+','[^']+','TXT'" \ + | cut -b 2- \ + | _egrep_o "[[:digit:]]+" \ + | head -n1) # ... oh my, what have I done... + + # Remove the record + curl -L --silent --show-error --cookie "$_he_cookie" \ + --form "menu=edit_zone" \ + --form "hosted_dns_zoneid=$_zone_id" \ + --form "hosted_dns_recordid=$_record_id" \ + --form "hosted_dns_editzone=1" \ + --form "hosted_dns_delrecord=1" \ + --form "hosted_dns_delconfirm=delete" \ + --form "hosted_dns_editzone=1" \ + "https://dns.he.net/" \ + | grep '
Successfully removed record.
' \ + > /dev/null + if [ $? -eq 0 ]; then + _info "Record removed successfuly." + else + _err \ + "Could not clean (remove) up the record. Please go to HE" \ + "administration interface and clean it by hand." + fi +} + + +########################## PRIVATE FUNCTIONS ########################### + + +#-- _find_zone() ------------------------------------------------------- + +# Usage: _authenticate +# +# - needs $HE_Username and $HE_Password +# - sets the $_he_cookie + +_authenticate() { + if [ -z "$HE_Username" ] && [ -z "$HE_Password" ]; then + _err \ + 'No auth details provided. Please set user credentials using the \ + \$HE_Username and \$HE_Password envoronment variables.' + return 1 + fi + # Just get a session + _he_cookie=$( \ + curl -L --silent --show-error -I "https://dns.he.net/" \ + | grep '^Set-Cookie:' \ + | _egrep_o 'CGISESSID=[a-z0-9]*') + # Attempt login + curl -L --silent --show-error --cookie "$_he_cookie" \ + --form "email=${HE_Username}" \ + --form "pass=${HE_Password}" \ + "https://dns.he.net/" \ + > /dev/null + # TODO detect unsuccessful logins +} + + +#-- _find_zone() ------------------------------------------------------- + +# Returns the most specific zone found in administration interface. +# +# - needs $_he_cookie +# +# Example: +# +# _find_zone first.second.third.co.uk +# +# ... will return the first zone that exists in admin out of these: +# - "first.second.third.co.uk" +# - "second.third.co.uk" +# - "third.co.uk" +# - "co.uk" <-- unlikely +# - "uk" <-' +# +# (another approach would be something like this: +# https://github.com/hlandau/acme/blob/master/_doc/dns.hook +# - that's better if there are multiple pages. It's so much simpler. +# ) + +_find_zone() { + + _domain="$1" + + ## _all_zones is an array that looks like this: + ## ( zone1:id zone2:id ... ) + _all_zones=( $(curl -L --silent --show-error --cookie "$_he_cookie" \ + "https://dns.he.net/" \ + | _egrep_o "delete_dom.*name=\"[^\"]+\" value=\"[0-9]+" \ + | cut -d '"' -f 3,5 --output-delimiter=":" \ + ) ) + + _strip_counter=1 + while [ true ] + do + _attempted_zone=$(echo $_domain | cut -d . -f ${_strip_counter}-) + + # All possible zone names have been tried + if [ "$_attempted_zone" == "" ] + then + _err "No zone for domain \"$_domain\" found." + break + fi + + # Walk through all zones on the account + #echo "$_all_zones" | while IFS=' ' read _zone_name _zone_id + for i in ${_all_zones[@]} + do + _zone_name=$(echo $i | cut -d ':' -f 1) + _zone_id=$(echo $i | cut -d ':' -f 2) + if [ "$_zone_name" == "$_attempted_zone" ] + then + # Zone found - we got $_zone_name and $_zone_id, let's get out... + _debug "Found relevant zone \"$_zone_name\" with id" \ + "\"$_zone_id\" - will be used for domain \"$_domain\"." + return 0 + fi + done + + _debug "Zone \"$_attempted_zone\" doesn't exist, let's try another \ + variation." + _strip_counter=$(expr $_strip_counter + 1) + done + + # No zone found. + return 1 +} + +# vim: et:ts=2:sw=2: From 90fd18bf423b91e6c48aa38ed1fa6dba52cde5e7 Mon Sep 17 00:00:00 2001 From: Santeri Date: Tue, 18 Jul 2017 15:48:17 +0400 Subject: [PATCH 05/90] Renamed script to cpanel_uapi.sh As per Neil's request. --- deploy/{cpanel.sh => cpanel_uapi.sh} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename deploy/{cpanel.sh => cpanel_uapi.sh} (100%) diff --git a/deploy/cpanel.sh b/deploy/cpanel_uapi.sh similarity index 100% rename from deploy/cpanel.sh rename to deploy/cpanel_uapi.sh From d09b5cb80eab19fb5e14a484cca5de09fb5c01ef Mon Sep 17 00:00:00 2001 From: Santeri Date: Wed, 19 Jul 2017 07:39:21 +0400 Subject: [PATCH 06/90] Rename cpanel_uapi.sh to cpanel_deploy.sh --- deploy/{cpanel_uapi.sh => cpanel_deploy.sh} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename deploy/{cpanel_uapi.sh => cpanel_deploy.sh} (100%) diff --git a/deploy/cpanel_uapi.sh b/deploy/cpanel_deploy.sh similarity index 100% rename from deploy/cpanel_uapi.sh rename to deploy/cpanel_deploy.sh From 4286b2917ef97ab44d0fd6208d183979633a401a Mon Sep 17 00:00:00 2001 From: Santeri Date: Wed, 19 Jul 2017 12:22:00 +0400 Subject: [PATCH 07/90] renamed function --- deploy/{cpanel_deploy.sh => cpanel_uapi.sh} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename deploy/{cpanel_deploy.sh => cpanel_uapi.sh} (98%) diff --git a/deploy/cpanel_deploy.sh b/deploy/cpanel_uapi.sh similarity index 98% rename from deploy/cpanel_deploy.sh rename to deploy/cpanel_uapi.sh index 9de8dbbb..ded50d0c 100644 --- a/deploy/cpanel_deploy.sh +++ b/deploy/cpanel_uapi.sh @@ -11,7 +11,7 @@ #domain keyfile certfile cafile fullchain -cpanel_deploy() { +cpanel_uapi() { _cdomain="$1" _ckey="$2" _ccert="$3" From 4285d81ca9d2805e99cf4ed0b601891b4ffd77ce Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Sun, 23 Jul 2017 05:00:02 +0200 Subject: [PATCH 08/90] Get rid of curl. --- dnsapi/dns_he.sh | 102 +++++++++++++++++------------------------------ 1 file changed, 37 insertions(+), 65 deletions(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 269db8d2..141268ac 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -1,8 +1,5 @@ #!/usr/bin/env sh -# TODO Somehow use _get instead of curl - not sure how to support -# cookies though... - ######################################################################## # Hurricane Electric hook script for acme.sh # @@ -23,7 +20,12 @@ dns_he_add() { _txt_value=$2 _info "Using DNS-01 Hurricane Electric hook" - _authenticate || return 1 + if [ -z "$HE_Username" ] && [ -z "$HE_Password" ]; then + _err \ + 'No auth details provided. Please set user credentials using the \ + \$HE_Username and \$HE_Password envoronment variables.' + return 1 + fi _saveaccountconf HE_Username "$HE_Username" _saveaccountconf HE_Password "$HE_Password" @@ -31,20 +33,20 @@ dns_he_add() { _find_zone $_full_domain || return 1 _debug "Zone id \"$_zone_id\" will be used." - curl -L --silent --show-error --cookie "$_he_cookie" \ - --form "account=" \ - --form "menu=edit_zone" \ - --form "Type=TXT" \ - --form "hosted_dns_zoneid=$_zone_id" \ - --form "hosted_dns_recordid=" \ - --form "hosted_dns_editzone=1" \ - --form "Priority=" \ - --form "Name=$_full_domain" \ - --form "Content=$_txt_value" \ - --form "TTL=300" \ - --form "hosted_dns_editrecord=Submit" \ - "https://dns.he.net/" \ - > /dev/null + body="email=${HE_Username}&pass=${HE_Password}" + body="$body&account=" + body="$body&account=" + body="$body&menu=edit_zone" + body="$body&Type=TXT" + body="$body&hosted_dns_zoneid=$_zone_id" + body="$body&hosted_dns_recordid=" + body="$body&hosted_dns_editzone=1" + body="$body&Priority=" + body="$body&Name=$_full_domain" + body="$body&Content=$_txt_value" + body="$body&TTL=300" + body="$body&hosted_dns_editrecord=Submit" + _post $body "https://dns.he.net/" >/dev/null } @@ -56,16 +58,16 @@ dns_he_rm() { _txt_value=$2 _info "Cleaning up after DNS-01 Hurricane Electric hook" - _authenticate || return 1 - # fills in the $_zone_id _find_zone $_full_domain || return 1 _debug "Zone id \"$_zone_id\" will be used." # Find the record id to clean - _record_id=$( \ - curl -L --silent --show-error --cookie "$_he_cookie" \ - "https://dns.he.net/?hosted_dns_zoneid=$_zone_id&menu=edit_zone&hosted_dns_editzone" \ + body="email=${HE_Username}&pass=${HE_Password}" + body="$body&hosted_dns_zoneid=$_zone_id" + body="$body&menu=edit_zone" + body="$body&hosted_dns_editzone=" + _record_id=$(_post $body "https://dns.he.net/" \ | grep -A 1 "data=\"\("\)\?${_txt_value}\("\)\?\"" \ | tail -n 1 \ | _egrep_o "'[[:digit:]]+','[^']+','TXT'" \ @@ -74,15 +76,15 @@ dns_he_rm() { | head -n1) # ... oh my, what have I done... # Remove the record - curl -L --silent --show-error --cookie "$_he_cookie" \ - --form "menu=edit_zone" \ - --form "hosted_dns_zoneid=$_zone_id" \ - --form "hosted_dns_recordid=$_record_id" \ - --form "hosted_dns_editzone=1" \ - --form "hosted_dns_delrecord=1" \ - --form "hosted_dns_delconfirm=delete" \ - --form "hosted_dns_editzone=1" \ - "https://dns.he.net/" \ + body="email=${HE_Username}&pass=${HE_Password}" + body="$body&menu=edit_zone" + body="$body&hosted_dns_zoneid=$_zone_id" + body="$body&hosted_dns_recordid=$_record_id" + body="$body&hosted_dns_editzone=1" + body="$body&hosted_dns_delrecord=1" + body="$body&hosted_dns_delconfirm=delete" + body="$body&hosted_dns_editzone=1" + _post $body "https://dns.he.net/" \ | grep '
Successfully removed record.
' \ > /dev/null if [ $? -eq 0 ]; then @@ -98,41 +100,10 @@ dns_he_rm() { ########################## PRIVATE FUNCTIONS ########################### -#-- _find_zone() ------------------------------------------------------- - -# Usage: _authenticate -# -# - needs $HE_Username and $HE_Password -# - sets the $_he_cookie - -_authenticate() { - if [ -z "$HE_Username" ] && [ -z "$HE_Password" ]; then - _err \ - 'No auth details provided. Please set user credentials using the \ - \$HE_Username and \$HE_Password envoronment variables.' - return 1 - fi - # Just get a session - _he_cookie=$( \ - curl -L --silent --show-error -I "https://dns.he.net/" \ - | grep '^Set-Cookie:' \ - | _egrep_o 'CGISESSID=[a-z0-9]*') - # Attempt login - curl -L --silent --show-error --cookie "$_he_cookie" \ - --form "email=${HE_Username}" \ - --form "pass=${HE_Password}" \ - "https://dns.he.net/" \ - > /dev/null - # TODO detect unsuccessful logins -} - - #-- _find_zone() ------------------------------------------------------- # Returns the most specific zone found in administration interface. # -# - needs $_he_cookie -# # Example: # # _find_zone first.second.third.co.uk @@ -155,8 +126,9 @@ _find_zone() { ## _all_zones is an array that looks like this: ## ( zone1:id zone2:id ... ) - _all_zones=( $(curl -L --silent --show-error --cookie "$_he_cookie" \ - "https://dns.he.net/" \ + + body="email=${HE_Username}&pass=${HE_Password}" + _all_zones=( $(_post $body "https://dns.he.net/" \ | _egrep_o "delete_dom.*name=\"[^\"]+\" value=\"[0-9]+" \ | cut -d '"' -f 3,5 --output-delimiter=":" \ ) ) From 8ca45d3d03718c4ba7dc89eb030209ebe2be9ac7 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Sun, 23 Jul 2017 05:13:33 +0200 Subject: [PATCH 09/90] Add HE to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5a3a3adf..7d4353c6 100644 --- a/README.md +++ b/README.md @@ -338,6 +338,7 @@ You don't have to do anything manually! 1. Name.com API 1. Dyn Managed DNS API 1. Yandex PDD API (https://pdd.yandex.ru) +1. Hurricane Electric DNS service (https://dns.he.net) And: From f7299403f7b7c0642fee665a7780ef0d8794681f Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Sun, 23 Jul 2017 07:31:55 +0200 Subject: [PATCH 10/90] Incorporate Neilpang's comments --- dnsapi/dns_he.sh | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 141268ac..019a7a0b 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -20,7 +20,7 @@ dns_he_add() { _txt_value=$2 _info "Using DNS-01 Hurricane Electric hook" - if [ -z "$HE_Username" ] && [ -z "$HE_Password" ]; then + if [ -z "$HE_Username" ] || [ -z "$HE_Password" ]; then _err \ 'No auth details provided. Please set user credentials using the \ \$HE_Username and \$HE_Password envoronment variables.' @@ -46,7 +46,8 @@ dns_he_add() { body="$body&Content=$_txt_value" body="$body&TTL=300" body="$body&hosted_dns_editrecord=Submit" - _post $body "https://dns.he.net/" >/dev/null + response="$(_post $body "https://dns.he.net/")" + _debug2 response "$response" } @@ -68,12 +69,14 @@ dns_he_rm() { body="$body&menu=edit_zone" body="$body&hosted_dns_editzone=" _record_id=$(_post $body "https://dns.he.net/" \ - | grep -A 1 "data=\"\("\)\?${_txt_value}\("\)\?\"" \ - | tail -n 1 \ - | _egrep_o "'[[:digit:]]+','[^']+','TXT'" \ - | cut -b 2- \ - | _egrep_o "[[:digit:]]+" \ - | head -n1) # ... oh my, what have I done... + | tr -d '\n' \ + | _egrep_o "data=\""${_txt_value}"([^>]+>){6}[^<]+<[^;]+;deleteRecord\('[0-9]+','${_full_domain}','TXT'\)" \ + | _egrep_o "[0-9]+','${_full_domain}','TXT'\)$" \ + | _egrep_o "^[0-9]+" + ) + # The series of egreps above could have been done a bit shorter but + # I wanted to double-check whether it's the correct record (in case + # HE changes their website somehow). # Remove the record body="email=${HE_Username}&pass=${HE_Password}" @@ -134,12 +137,12 @@ _find_zone() { ) ) _strip_counter=1 - while [ true ] + while true do _attempted_zone=$(echo $_domain | cut -d . -f ${_strip_counter}-) # All possible zone names have been tried - if [ "$_attempted_zone" == "" ] + if [ -z "$_attempted_zone" ] then _err "No zone for domain \"$_domain\" found." break @@ -151,7 +154,7 @@ _find_zone() { do _zone_name=$(echo $i | cut -d ':' -f 1) _zone_id=$(echo $i | cut -d ':' -f 2) - if [ "$_zone_name" == "$_attempted_zone" ] + if [ "$_zone_name" = "$_attempted_zone" ] then # Zone found - we got $_zone_name and $_zone_id, let's get out... _debug "Found relevant zone \"$_zone_name\" with id" \ @@ -162,7 +165,7 @@ _find_zone() { _debug "Zone \"$_attempted_zone\" doesn't exist, let's try another \ variation." - _strip_counter=$(expr $_strip_counter + 1) + _strip_counter=$(_math $_strip_counter + 1) done # No zone found. From 3281043e2784154345b10aef7b107893ea7ff78b Mon Sep 17 00:00:00 2001 From: Brian Candler Date: Tue, 25 Jul 2017 09:39:15 +0100 Subject: [PATCH 11/90] Clarify keylength parameter to _isEccKey() and _initpath() Closes #950 --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 486f8678..38965ddc 100755 --- a/acme.sh +++ b/acme.sh @@ -926,7 +926,7 @@ _sign() { } -#keylength +#keylength or isEcc flag (empty str => not ecc) _isEccKey() { _length="$1" @@ -2251,7 +2251,7 @@ _initAPI() { _debug "ACME_REVOKE_CERT" "$ACME_REVOKE_CERT" } -#[domain] [keylength] +#[domain] [keylength or isEcc flag] _initpath() { __initHome From 29b21b828b01b37ad9f6536cba27af79a1f6aac3 Mon Sep 17 00:00:00 2001 From: Jeremy Knope Date: Wed, 26 Jul 2017 09:44:11 -0400 Subject: [PATCH 12/90] Fix DNS API scripts on *BSD \n isn't available in all regex/sed --- dnsapi/dns_ad.sh | 3 ++- dnsapi/dns_do.sh | 6 ++++-- dnsapi/dns_freedns.sh | 6 ++++-- dnsapi/dns_linode.sh | 6 ++++-- dnsapi/dns_vscale.sh | 3 ++- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_ad.sh b/dnsapi/dns_ad.sh index fc4a664b..79b8c2ab 100755 --- a/dnsapi/dns_ad.sh +++ b/dnsapi/dns_ad.sh @@ -92,7 +92,8 @@ _get_root() { p=1 if _ad_rest GET "domain/"; then - response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" + response="$(echo "$response" | tr -d "\n" | sed 's/{/\ +&/g')" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug h "$h" diff --git a/dnsapi/dns_do.sh b/dnsapi/dns_do.sh index 3a2f8f49..fb6d7dec 100755 --- a/dnsapi/dns_do.sh +++ b/dnsapi/dns_do.sh @@ -69,9 +69,11 @@ _dns_do_list_rrs() { fi _rr_list="$(echo "${response}" \ | tr -d "\n\r\t" \ - | sed -e 's//\n/g' \ + | sed -e 's//\ +/g' \ | grep ">$(_regexcape "$fulldomain")" \ - | sed -e 's/<\/item>/\n/g' \ + | sed -e 's/<\/item>/\ +/g' \ | grep '>id[0-9]{1,16}<' \ | tr -d '><')" diff --git a/dnsapi/dns_freedns.sh b/dnsapi/dns_freedns.sh index 53da4118..d9677632 100755 --- a/dnsapi/dns_freedns.sh +++ b/dnsapi/dns_freedns.sh @@ -77,7 +77,8 @@ dns_freedns_add() { | grep -i -e ']*>/\n/Ig' \ + | sed 's/<\/TR[^>]*>/\ +/Ig' \ | sed 's/<\/\?\(TABLE\|TR\)[^>]*>//Ig' \ | sed 's/^]*>\|<\/\?T[DH][^>]*>$//Ig' \ | sed 's/<\/T[DH][^>]*>]*>/,/Ig' \ @@ -216,7 +217,8 @@ dns_freedns_rm() { | grep -i -e ']*>/\n/Ig' \ + | sed 's/<\/TR[^>]*>/\ +/Ig' \ | sed 's/<\/\?\(TABLE\|TR\)[^>]*>//Ig' \ | sed 's/^]*>\|<\/\?T[DH][^>]*>$//Ig' \ | sed 's/<\/T[DH][^>]*>]*>/,/Ig' \ diff --git a/dnsapi/dns_linode.sh b/dnsapi/dns_linode.sh index 6d54e6c1..d84ad5fb 100755 --- a/dnsapi/dns_linode.sh +++ b/dnsapi/dns_linode.sh @@ -68,7 +68,8 @@ dns_linode_rm() { _parameters="&DomainID=$_domain_id" if _rest GET "domain.resource.list" "$_parameters" && [ -n "$response" ]; then - response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" + response="$(echo "$response" | tr -d "\n" | sed 's/{/\ +&/g')" resource="$(echo "$response" | _egrep_o "{.*\"NAME\":\s*\"$_sub_domain\".*}")" if [ "$resource" ]; then @@ -128,7 +129,8 @@ _get_root() { p=1 if _rest GET "domain.list"; then - response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" + response="$(echo "$response" | tr -d "\n" | sed 's/{/\ +&/g')" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug h "$h" diff --git a/dnsapi/dns_vscale.sh b/dnsapi/dns_vscale.sh index e50b7d8b..fcd162c9 100755 --- a/dnsapi/dns_vscale.sh +++ b/dnsapi/dns_vscale.sh @@ -93,7 +93,8 @@ _get_root() { p=1 if _vscale_rest GET "domains/"; then - response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" + response="$(echo "$response" | tr -d "\n" | sed 's/{/\ +&/g')" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug h "$h" From ff74778dea38ef22fb13fbdf452991c4a70135a1 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Wed, 26 Jul 2017 20:15:34 +0200 Subject: [PATCH 13/90] Fix few issues from Travis --- dnsapi/dns_he.sh | 45 ++++++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 019a7a0b..1a6f8dbc 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -21,16 +21,14 @@ dns_he_add() { _info "Using DNS-01 Hurricane Electric hook" if [ -z "$HE_Username" ] || [ -z "$HE_Password" ]; then - _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 envoronment variables." return 1 fi _saveaccountconf HE_Username "$HE_Username" _saveaccountconf HE_Password "$HE_Password" # fills in the $_zone_id - _find_zone $_full_domain || return 1 + _find_zone "$_full_domain" || return 1 _debug "Zone id \"$_zone_id\" will be used." body="email=${HE_Username}&pass=${HE_Password}" @@ -46,11 +44,10 @@ dns_he_add() { body="$body&Content=$_txt_value" body="$body&TTL=300" body="$body&hosted_dns_editrecord=Submit" - response="$(_post $body "https://dns.he.net/")" + response="$(_post "$body" "https://dns.he.net/")" _debug2 response "$response" } - #-- dns_he_rm() - Remove TXT record ------------------------------------ # Usage: dns_he_rm _acme-challenge.subdomain.domain.com "XyZ123..." @@ -60,7 +57,7 @@ dns_he_rm() { _info "Cleaning up after DNS-01 Hurricane Electric hook" # fills in the $_zone_id - _find_zone $_full_domain || return 1 + _find_zone "$_full_domain" || return 1 _debug "Zone id \"$_zone_id\" will be used." # Find the record id to clean @@ -68,7 +65,7 @@ dns_he_rm() { body="$body&hosted_dns_zoneid=$_zone_id" body="$body&menu=edit_zone" body="$body&hosted_dns_editzone=" - _record_id=$(_post $body "https://dns.he.net/" \ + _record_id=$(_post "$body" "https://dns.he.net/" \ | tr -d '\n' \ | _egrep_o "data=\""${_txt_value}"([^>]+>){6}[^<]+<[^;]+;deleteRecord\('[0-9]+','${_full_domain}','TXT'\)" \ | _egrep_o "[0-9]+','${_full_domain}','TXT'\)$" \ @@ -87,9 +84,9 @@ dns_he_rm() { body="$body&hosted_dns_delrecord=1" body="$body&hosted_dns_delconfirm=delete" body="$body&hosted_dns_editzone=1" - _post $body "https://dns.he.net/" \ + _post "$body" "https://dns.he.net/" \ | grep '
Successfully removed record.
' \ - > /dev/null + >/dev/null if [ $? -eq 0 ]; then _info "Record removed successfuly." else @@ -99,12 +96,9 @@ dns_he_rm() { fi } - ########################## PRIVATE FUNCTIONS ########################### - #-- _find_zone() ------------------------------------------------------- - # Returns the most specific zone found in administration interface. # # Example: @@ -131,31 +125,28 @@ _find_zone() { ## ( zone1:id zone2:id ... ) body="email=${HE_Username}&pass=${HE_Password}" - _all_zones=( $(_post $body "https://dns.he.net/" \ + # TODO arrays aren't supported in POSIX sh + _all_zones=($(_post $body "https://dns.he.net/" \ | _egrep_o "delete_dom.*name=\"[^\"]+\" value=\"[0-9]+" \ - | cut -d '"' -f 3,5 --output-delimiter=":" \ - ) ) + | cut -d '"' -f 3,5 --output-delimiter=":" + )) _strip_counter=1 - while true - do - _attempted_zone=$(echo $_domain | cut -d . -f ${_strip_counter}-) + while true; do + _attempted_zone=$(echo "$_domain" | cut -d . -f ${_strip_counter}-) # All possible zone names have been tried - if [ -z "$_attempted_zone" ] - then + if [ -z "$_attempted_zone" ]; then _err "No zone for domain \"$_domain\" found." break fi # Walk through all zones on the account #echo "$_all_zones" | while IFS=' ' read _zone_name _zone_id - for i in ${_all_zones[@]} - do - _zone_name=$(echo $i | cut -d ':' -f 1) - _zone_id=$(echo $i | cut -d ':' -f 2) - if [ "$_zone_name" = "$_attempted_zone" ] - then + for i in ${_all_zones[@]}; do + _zone_name=$(echo "$i" | cut -d ':' -f 1) + _zone_id=$(echo "$i" | cut -d ':' -f 2) + if [ "$_zone_name" = "$_attempted_zone" ]; then # Zone found - we got $_zone_name and $_zone_id, let's get out... _debug "Found relevant zone \"$_zone_name\" with id" \ "\"$_zone_id\" - will be used for domain \"$_domain\"." From 1546b7e5a971578cef11f960a44aadad3a45b754 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Wed, 26 Jul 2017 20:21:36 +0200 Subject: [PATCH 14/90] Missing quotes --- 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 1a6f8dbc..3e23b2e0 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -126,7 +126,7 @@ _find_zone() { body="email=${HE_Username}&pass=${HE_Password}" # TODO arrays aren't supported in POSIX sh - _all_zones=($(_post $body "https://dns.he.net/" \ + _all_zones=($(_post "$body" "https://dns.he.net/" \ | _egrep_o "delete_dom.*name=\"[^\"]+\" value=\"[0-9]+" \ | cut -d '"' -f 3,5 --output-delimiter=":" )) From d39649f30d6718d7b0ec7e1e746a518b23bfd9be Mon Sep 17 00:00:00 2001 From: Jeremy Knope Date: Thu, 27 Jul 2017 08:52:46 -0400 Subject: [PATCH 15/90] Revert non-linode scripts since they're untested --- dnsapi/dns_ad.sh | 3 +-- dnsapi/dns_do.sh | 6 ++---- dnsapi/dns_freedns.sh | 6 ++---- dnsapi/dns_vscale.sh | 3 +-- 4 files changed, 6 insertions(+), 12 deletions(-) diff --git a/dnsapi/dns_ad.sh b/dnsapi/dns_ad.sh index 79b8c2ab..fc4a664b 100755 --- a/dnsapi/dns_ad.sh +++ b/dnsapi/dns_ad.sh @@ -92,8 +92,7 @@ _get_root() { p=1 if _ad_rest GET "domain/"; then - response="$(echo "$response" | tr -d "\n" | sed 's/{/\ -&/g')" + response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug h "$h" diff --git a/dnsapi/dns_do.sh b/dnsapi/dns_do.sh index fb6d7dec..3a2f8f49 100755 --- a/dnsapi/dns_do.sh +++ b/dnsapi/dns_do.sh @@ -69,11 +69,9 @@ _dns_do_list_rrs() { fi _rr_list="$(echo "${response}" \ | tr -d "\n\r\t" \ - | sed -e 's//\ -/g' \ + | sed -e 's//\n/g' \ | grep ">$(_regexcape "$fulldomain")" \ - | sed -e 's/<\/item>/\ -/g' \ + | sed -e 's/<\/item>/\n/g' \ | grep '>id[0-9]{1,16}<' \ | tr -d '><')" diff --git a/dnsapi/dns_freedns.sh b/dnsapi/dns_freedns.sh index d9677632..53da4118 100755 --- a/dnsapi/dns_freedns.sh +++ b/dnsapi/dns_freedns.sh @@ -77,8 +77,7 @@ dns_freedns_add() { | grep -i -e ']*>/\ -/Ig' \ + | sed 's/<\/TR[^>]*>/\n/Ig' \ | sed 's/<\/\?\(TABLE\|TR\)[^>]*>//Ig' \ | sed 's/^]*>\|<\/\?T[DH][^>]*>$//Ig' \ | sed 's/<\/T[DH][^>]*>]*>/,/Ig' \ @@ -217,8 +216,7 @@ dns_freedns_rm() { | grep -i -e ']*>/\ -/Ig' \ + | sed 's/<\/TR[^>]*>/\n/Ig' \ | sed 's/<\/\?\(TABLE\|TR\)[^>]*>//Ig' \ | sed 's/^]*>\|<\/\?T[DH][^>]*>$//Ig' \ | sed 's/<\/T[DH][^>]*>]*>/,/Ig' \ diff --git a/dnsapi/dns_vscale.sh b/dnsapi/dns_vscale.sh index fcd162c9..e50b7d8b 100755 --- a/dnsapi/dns_vscale.sh +++ b/dnsapi/dns_vscale.sh @@ -93,8 +93,7 @@ _get_root() { p=1 if _vscale_rest GET "domains/"; then - response="$(echo "$response" | tr -d "\n" | sed 's/{/\ -&/g')" + response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug h "$h" From aefed1d1b9a5264f460aa94e119cb8a40f8bdddd Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Thu, 27 Jul 2017 18:04:53 +0200 Subject: [PATCH 16/90] Get rid of shell arrays. --- dnsapi/dns_he.sh | 73 +++++++++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 3e23b2e0..ada5f794 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -121,16 +121,19 @@ _find_zone() { _domain="$1" - ## _all_zones is an array that looks like this: - ## ( zone1:id zone2:id ... ) - body="email=${HE_Username}&pass=${HE_Password}" - # TODO arrays aren't supported in POSIX sh - _all_zones=($(_post "$body" "https://dns.he.net/" \ - | _egrep_o "delete_dom.*name=\"[^\"]+\" value=\"[0-9]+" \ - | cut -d '"' -f 3,5 --output-delimiter=":" - )) - + _matches=$(_post "$body" "https://dns.he.net/" \ + | _egrep_o "delete_dom.*name=\"[^\"]+\" value=\"[0-9]+" + ) + # Zone names and zone IDs are in same order + _zone_ids=$(echo "$_matches" | cut -d '"' -f 5 --output-delimiter=":") + _zone_names=$(echo "$_matches" | cut -d '"' -f 3 --output-delimiter=":") + _debug2 "These are the zones on this HE account:" + _debug2 "$_zone_names" + _debug2 "And these are their respective IDs:" + _debug2 "$_zone_ids" + + # Walk through all possible zone names _strip_counter=1 while true; do _attempted_zone=$(echo "$_domain" | cut -d . -f ${_strip_counter}-) @@ -138,28 +141,46 @@ _find_zone() { # All possible zone names have been tried if [ -z "$_attempted_zone" ]; then _err "No zone for domain \"$_domain\" found." - break + return 1 fi - # Walk through all zones on the account - #echo "$_all_zones" | while IFS=' ' read _zone_name _zone_id - for i in ${_all_zones[@]}; do - _zone_name=$(echo "$i" | cut -d ':' -f 1) - _zone_id=$(echo "$i" | cut -d ':' -f 2) - if [ "$_zone_name" = "$_attempted_zone" ]; then - # Zone found - we got $_zone_name and $_zone_id, let's get out... - _debug "Found relevant zone \"$_zone_name\" with id" \ - "\"$_zone_id\" - will be used for domain \"$_domain\"." - return 0 - fi - done - - _debug "Zone \"$_attempted_zone\" doesn't exist, let's try another \ - variation." + _debug "Looking for zone \"${_attempted_zone}\"" + _line_num=$(echo "$_zone_names" | _find_linenum "$_attempted_zone") + if [ -n "$_line_num" ]; then + _zone_id=$(echo "$_zone_ids" | sed "${_line_num}q;d") + _debug "Found relevant zone \"$_attempted_zone\" with id" \ + "\"$_zone_id\" - will be used for domain \"$_domain\"." + return 0 + fi + + _debug "Zone \"$_attempted_zone\" doesn't exist, let's try a less" \ + "specific zone." _strip_counter=$(_math $_strip_counter + 1) done +} - # No zone found. +#-- _find_linenum()----------------------------------------------------- +# Returns line number of line (supplied as an argument) in STDIN. +# +# Example: +# +# printf "a\nb\nc" | _find_linenum "b" +# +# This will: +# - print out 2 because that's the line number of "b" +# - return code 0 because it was found + +_find_linenum() { + _current_line_num=0 + while read line; do + _current_line_num=$(expr "$_current_line_num" + 1) + if [ "$line" = "$1" ]; then + # Found! Let's echo the line number and quit + echo $_current_line_num + return 0 + fi + done + # Not found return 1 } From 235b5b0c154331879b70fd149d1fe7df19eac4c8 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Thu, 27 Jul 2017 18:06:19 +0200 Subject: [PATCH 17/90] Small cosmetic fixes. --- dnsapi/dns_he.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index ada5f794..51418aa9 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -11,7 +11,6 @@ # Author: Ondrej Simek # Git repo: https://github.com/angel333/acme.sh - #-- dns_he_add() - Add TXT record -------------------------------------- # Usage: dns_he_add _acme-challenge.subdomain.domain.com "XyZ123..." @@ -86,7 +85,7 @@ dns_he_rm() { body="$body&hosted_dns_editzone=1" _post "$body" "https://dns.he.net/" \ | grep '
Successfully removed record.
' \ - >/dev/null + >/dev/null if [ $? -eq 0 ]; then _info "Record removed successfuly." else From 577380e98e33c32f87d74df07d0d9d862b89b5be Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Thu, 27 Jul 2017 18:44:55 +0200 Subject: [PATCH 18/90] Few fixes for shellcheck --- dnsapi/dns_he.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 51418aa9..9b789d35 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -154,7 +154,7 @@ _find_zone() { _debug "Zone \"$_attempted_zone\" doesn't exist, let's try a less" \ "specific zone." - _strip_counter=$(_math $_strip_counter + 1) + _strip_counter=$(_math "$_strip_counter" + 1) done } @@ -171,11 +171,11 @@ _find_zone() { _find_linenum() { _current_line_num=0 - while read line; do - _current_line_num=$(expr "$_current_line_num" + 1) + while read -r line; do + _current_line_num=$(_math "$_current_line_num" + 1) if [ "$line" = "$1" ]; then # Found! Let's echo the line number and quit - echo $_current_line_num + echo "$_current_line_num" return 0 fi done From 8e6cf669ad01905d4d9e22f7a2874dcba8c7e263 Mon Sep 17 00:00:00 2001 From: Jeremy Knope Date: Thu, 27 Jul 2017 14:15:19 -0400 Subject: [PATCH 19/90] Try awk instead for \n replacements --- dnsapi/dns_linode.sh | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_linode.sh b/dnsapi/dns_linode.sh index d84ad5fb..ee3b1c8b 100755 --- a/dnsapi/dns_linode.sh +++ b/dnsapi/dns_linode.sh @@ -68,8 +68,7 @@ dns_linode_rm() { _parameters="&DomainID=$_domain_id" if _rest GET "domain.resource.list" "$_parameters" && [ -n "$response" ]; then - response="$(echo "$response" | tr -d "\n" | sed 's/{/\ -&/g')" + response="$(echo "$response" | tr -d "\n" | awk '{ gsub("{","\n{",$1); print $1 }')" resource="$(echo "$response" | _egrep_o "{.*\"NAME\":\s*\"$_sub_domain\".*}")" if [ "$resource" ]; then @@ -129,8 +128,7 @@ _get_root() { p=1 if _rest GET "domain.list"; then - response="$(echo "$response" | tr -d "\n" | sed 's/{/\ -&/g')" + response="$(echo "$response" | tr -d "\n" | awk '{ gsub("{","\n{",$1); print $1 }')" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug h "$h" From 8534e3b2f7fd16477b811c262f60e9b63cb85e32 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Fri, 28 Jul 2017 13:58:47 +0200 Subject: [PATCH 20/90] Make shellcheck happier --- dnsapi/dns_he.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 9b789d35..3ca00af9 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -20,6 +20,8 @@ dns_he_add() { _info "Using DNS-01 Hurricane Electric hook" 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." return 1 fi From d6780f9e49f18bf503f46c5d4859289e593935c0 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Fri, 28 Jul 2017 15:29:35 +0200 Subject: [PATCH 21/90] Retain an exit code --- dnsapi/dns_he.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 3ca00af9..ab4393c7 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -46,7 +46,9 @@ dns_he_add() { body="$body&TTL=300" body="$body&hosted_dns_editrecord=Submit" response="$(_post "$body" "https://dns.he.net/")" + exitcode=$? _debug2 response "$response" + return $exitvalue } #-- dns_he_rm() - Remove TXT record ------------------------------------ From ab1efd923b56b9014f07e7fcac7a81325d93d0b8 Mon Sep 17 00:00:00 2001 From: Jeremy Knope Date: Fri, 28 Jul 2017 10:26:56 -0400 Subject: [PATCH 22/90] back to sed --- dnsapi/dns_linode.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_linode.sh b/dnsapi/dns_linode.sh index ee3b1c8b..00634d5d 100755 --- a/dnsapi/dns_linode.sh +++ b/dnsapi/dns_linode.sh @@ -68,7 +68,7 @@ dns_linode_rm() { _parameters="&DomainID=$_domain_id" if _rest GET "domain.resource.list" "$_parameters" && [ -n "$response" ]; then - response="$(echo "$response" | tr -d "\n" | awk '{ gsub("{","\n{",$1); print $1 }')" + response="$(echo "$response" | tr -d "\n" | sed $'s/{/\\\n&/g')" resource="$(echo "$response" | _egrep_o "{.*\"NAME\":\s*\"$_sub_domain\".*}")" if [ "$resource" ]; then @@ -128,7 +128,7 @@ _get_root() { p=1 if _rest GET "domain.list"; then - response="$(echo "$response" | tr -d "\n" | awk '{ gsub("{","\n{",$1); print $1 }')" + response="$(echo "$response" | tr -d "\n" | sed $'s/{/\\\n&/g')" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug h "$h" From ccf9a9976c1b7cf31c60a4b74ead0f30fba1de28 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Fri, 28 Jul 2017 18:33:25 +0200 Subject: [PATCH 23/90] Fix the previous rushed commit. --- dnsapi/dns_he.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index ab4393c7..2fb1101e 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -46,9 +46,14 @@ dns_he_add() { body="$body&TTL=300" body="$body&hosted_dns_editrecord=Submit" response="$(_post "$body" "https://dns.he.net/")" - exitcode=$? + exit_code="$?" + if [ "$exit_code" -eq 0 ]; then + _info "TXT record added successfuly." + else + _err "Couldn't add the TXT record." + return "$exit_code" + fi _debug2 response "$response" - return $exitvalue } #-- dns_he_rm() - Remove TXT record ------------------------------------ @@ -90,7 +95,7 @@ dns_he_rm() { _post "$body" "https://dns.he.net/" \ | grep '
Successfully removed record.
' \ >/dev/null - if [ $? -eq 0 ]; then + if [ "$?" -eq 0 ]; then _info "Record removed successfuly." else _err \ From a5c56c547d024493bb90732cda20108d09392715 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 29 Jul 2017 15:23:31 +0800 Subject: [PATCH 24/90] minor, fix dns param --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 38965ddc..9486bcc5 100755 --- a/acme.sh +++ b/acme.sh @@ -5440,7 +5440,7 @@ _process() { ;; --dns) wvalue="dns" - if ! _startswith "$2" "-"; then + if [ "$2" ] && ! _startswith "$2" "-"; then wvalue="$2" shift fi From 31b67ab92efd23802acb8510126418b83e1af8db Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Sat, 29 Jul 2017 13:52:28 +0200 Subject: [PATCH 25/90] Few non-critical fixes. --- dnsapi/dns_he.sh | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 2fb1101e..a160e16a 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -28,13 +28,12 @@ dns_he_add() { _saveaccountconf HE_Username "$HE_Username" _saveaccountconf HE_Password "$HE_Password" - # fills in the $_zone_id + # Fills in the $_zone_id _find_zone "$_full_domain" || return 1 _debug "Zone id \"$_zone_id\" will be used." body="email=${HE_Username}&pass=${HE_Password}" body="$body&account=" - body="$body&account=" body="$body&menu=edit_zone" body="$body&Type=TXT" body="$body&hosted_dns_zoneid=$_zone_id" @@ -91,16 +90,13 @@ dns_he_rm() { body="$body&hosted_dns_editzone=1" body="$body&hosted_dns_delrecord=1" body="$body&hosted_dns_delconfirm=delete" - body="$body&hosted_dns_editzone=1" _post "$body" "https://dns.he.net/" \ | grep '
Successfully removed record.
' \ >/dev/null if [ "$?" -eq 0 ]; then _info "Record removed successfuly." else - _err \ - "Could not clean (remove) up the record. Please go to HE" \ - "administration interface and clean it by hand." + _err "Could not clean (remove) up the record. Please go to HE administration interface and clean it by hand." fi } @@ -134,8 +130,8 @@ _find_zone() { | _egrep_o "delete_dom.*name=\"[^\"]+\" value=\"[0-9]+" ) # Zone names and zone IDs are in same order - _zone_ids=$(echo "$_matches" | cut -d '"' -f 5 --output-delimiter=":") - _zone_names=$(echo "$_matches" | cut -d '"' -f 3 --output-delimiter=":") + _zone_ids=$(echo "$_matches" | cut -d '"' -f 5) + _zone_names=$(echo "$_matches" | cut -d '"' -f 3) _debug2 "These are the zones on this HE account:" _debug2 "$_zone_names" _debug2 "And these are their respective IDs:" @@ -156,13 +152,11 @@ _find_zone() { _line_num=$(echo "$_zone_names" | _find_linenum "$_attempted_zone") if [ -n "$_line_num" ]; then _zone_id=$(echo "$_zone_ids" | sed "${_line_num}q;d") - _debug "Found relevant zone \"$_attempted_zone\" with id" \ - "\"$_zone_id\" - will be used for domain \"$_domain\"." + _debug "Found relevant zone \"$_attempted_zone\" with id \"$_zone_id\" - will be used for domain \"$_domain\"." return 0 fi - _debug "Zone \"$_attempted_zone\" doesn't exist, let's try a less" \ - "specific zone." + _debug "Zone \"$_attempted_zone\" doesn't exist, let's try a less specific zone." _strip_counter=$(_math "$_strip_counter" + 1) done } From a25b2af66cd6a4c69ee673ec32aaebd068079042 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Sat, 29 Jul 2017 14:25:07 +0200 Subject: [PATCH 26/90] Get rid of _find_num --- dnsapi/dns_he.sh | 41 ++++++++++++----------------------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index a160e16a..7dde55d4 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -149,9 +149,18 @@ _find_zone() { fi _debug "Looking for zone \"${_attempted_zone}\"" - _line_num=$(echo "$_zone_names" | _find_linenum "$_attempted_zone") - if [ -n "$_line_num" ]; then - _zone_id=$(echo "$_zone_ids" | sed "${_line_num}q;d") + + # Take care of "." and only match whole lines. Note that grep -F + # cannot be used because there's no way to make it match whole + # lines. + regex="^$(echo "$_attempted_zone" | sed 's/\./\\./g')$" + line_num=$(echo "$_zone_names" \ + | grep -n "$regex" \ + | cut -d : -f 1 + ) + + if [ -n "$line_num" ]; then + _zone_id=$(echo "$_zone_ids" | sed "${line_num}q;d") _debug "Found relevant zone \"$_attempted_zone\" with id \"$_zone_id\" - will be used for domain \"$_domain\"." return 0 fi @@ -160,30 +169,4 @@ _find_zone() { _strip_counter=$(_math "$_strip_counter" + 1) done } - -#-- _find_linenum()----------------------------------------------------- -# Returns line number of line (supplied as an argument) in STDIN. -# -# Example: -# -# printf "a\nb\nc" | _find_linenum "b" -# -# This will: -# - print out 2 because that's the line number of "b" -# - return code 0 because it was found - -_find_linenum() { - _current_line_num=0 - while read -r line; do - _current_line_num=$(_math "$_current_line_num" + 1) - if [ "$line" = "$1" ]; then - # Found! Let's echo the line number and quit - echo "$_current_line_num" - return 0 - fi - done - # Not found - return 1 -} - # vim: et:ts=2:sw=2: From f438ff4bab695818932149d5b6bcecb1b6bed712 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Sat, 29 Jul 2017 14:29:13 +0200 Subject: [PATCH 27/90] Fix an improbable corner case. --- dnsapi/dns_he.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 7dde55d4..152d469c 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -72,10 +72,11 @@ dns_he_rm() { body="$body&hosted_dns_zoneid=$_zone_id" body="$body&menu=edit_zone" body="$body&hosted_dns_editzone=" + domain_regex="$(echo "$_full_domain" | sed 's/\./\\./g')" # escape dots _record_id=$(_post "$body" "https://dns.he.net/" \ | tr -d '\n' \ - | _egrep_o "data=\""${_txt_value}"([^>]+>){6}[^<]+<[^;]+;deleteRecord\('[0-9]+','${_full_domain}','TXT'\)" \ - | _egrep_o "[0-9]+','${_full_domain}','TXT'\)$" \ + | _egrep_o "data=\""${_txt_value}"([^>]+>){6}[^<]+<[^;]+;deleteRecord\('[0-9]+','${domain_regex}','TXT'\)" \ + | _egrep_o "[0-9]+','${domain_regex}','TXT'\)$" \ | _egrep_o "^[0-9]+" ) # The series of egreps above could have been done a bit shorter but From baa1160594921e465ee798b77c5add4ed6b1d907 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Sat, 29 Jul 2017 14:31:27 +0200 Subject: [PATCH 28/90] Make Shellcheck happier about exit codes --- dnsapi/dns_he.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 152d469c..3a1e6979 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -94,10 +94,12 @@ dns_he_rm() { _post "$body" "https://dns.he.net/" \ | grep '
Successfully removed record.
' \ >/dev/null - if [ "$?" -eq 0 ]; then + exit_code="$?" + if [ "$exit_code" -eq 0 ]; then _info "Record removed successfuly." else _err "Could not clean (remove) up the record. Please go to HE administration interface and clean it by hand." + return "$exit_code" fi } From 4dd69a8b1adaacfbb5a4894a8a5fc0403e3b4e88 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Sat, 29 Jul 2017 14:40:56 +0200 Subject: [PATCH 29/90] Exit codes, exit codes... Exit codes everywhere... --- 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 3a1e6979..7d86eb7a 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -50,9 +50,9 @@ dns_he_add() { _info "TXT record added successfuly." else _err "Couldn't add the TXT record." - return "$exit_code" fi _debug2 response "$response" + return "$exit_code" } #-- dns_he_rm() - Remove TXT record ------------------------------------ From 8eab77f3c607075ff1cd59b59f76b074f1d46605 Mon Sep 17 00:00:00 2001 From: Brian Candler Date: Mon, 24 Jul 2017 14:23:01 +0100 Subject: [PATCH 30/90] Add deployment script for unifi controller --- acme.sh | 28 +++++++++++--- deploy/unifi.sh | 100 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 5 deletions(-) create mode 100644 deploy/unifi.sh diff --git a/acme.sh b/acme.sh index 9486bcc5..60eef4bb 100755 --- a/acme.sh +++ b/acme.sh @@ -1182,6 +1182,28 @@ _ss() { return 1 } +#outfile key cert cacert [password [name [caname]]] +_toPkcs() { + _cpfx="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + pfxPassword="$5" + pfxName="$6" + pfxCaname="$7" + + if [ "$pfxCaname" ]; then + ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" -password "pass:$pfxPassword" -name "$pfxName" -caname "$pfxCaname" + elif [ "$pfxName" ]; then + ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" -password "pass:$pfxPassword" -name "$pfxName" + elif [ "$pfxPassword" ]; then + ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" -password "pass:$pfxPassword" + else + ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" + fi + +} + #domain [password] [isEcc] toPkcs() { domain="$1" @@ -1195,11 +1217,7 @@ toPkcs() { _initpath "$domain" "$_isEcc" - if [ "$pfxPassword" ]; then - ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH" -password "pass:$pfxPassword" - else - ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH" - fi + _toPkcs "$CERT_PFX_PATH" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$pfxPassword" if [ "$?" = "0" ]; then _info "Success, Pfx is exported to: $CERT_PFX_PATH" diff --git a/deploy/unifi.sh b/deploy/unifi.sh new file mode 100644 index 00000000..184aa62e --- /dev/null +++ b/deploy/unifi.sh @@ -0,0 +1,100 @@ +#!/usr/bin/env sh + +#Here is a script to deploy cert to unifi server. + +#returns 0 means success, otherwise error. + +#DEPLOY_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore" +#DEPLOY_UNIFI_KEYPASS="aircontrolenterprise" +#DEPLOY_UNIFI_RELOAD="service unifi restart" + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +unifi_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 keytool; then + _err "keytool not found" + return 1 + fi + + DEFAULT_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore" + _unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-$DEFAULT_UNIFI_KEYSTORE}" + DEFAULT_UNIFI_KEYPASS="aircontrolenterprise" + _unifi_keypass="${DEPLOY_UNIFI_KEYPASS:-$DEFAULT_UNIFI_KEYPASS}" + DEFAULT_UNIFI_RELOAD="service unifi restart" + _reload="${DEPLOY_UNIFI_RELOAD:-$DEFAULT_UNIFI_RELOAD}" + + _debug _unifi_keystore "$_unifi_keystore" + if [ ! -f "$_unifi_keystore" ]; then + if [ -z "$DEPLOY_UNIFI_KEYSTORE" ]; then + _err "unifi keystore is not found, please define DEPLOY_UNIFI_KEYSTORE" + return 1 + else + _err "It seems that the specified unifi keystore is not valid, please check." + return 1 + fi + fi + if [ ! -w "$_unifi_keystore" ]; then + _err "The file $_unifi_keystore is not writable, please change the permission." + return 1 + fi + + _info "Generate import pkcs12" + _import_pkcs12="$(_mktemp)" + _toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root + if [ "$?" != "0" ]; then + _err "Oops, error creating import pkcs12, please report bug to us." + return 1 + fi + + _info "Modify unifi keystore: $_unifi_keystore" + if keytool -importkeystore \ + -deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \ + -srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \ + -alias unifi -noprompt; then + _info "Import keystore success!" + rm "$_import_pkcs12" + else + _err "Import unifi keystore error, please report bug to us." + rm "$_import_pkcs12" + return 1 + fi + + _info "Run reload: $_reload" + if eval "$_reload"; then + _info "Reload success!" + if [ "$DEPLOY_UNIFI_KEYSTORE" ]; then + _savedomainconf DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" + else + _cleardomainconf DEPLOY_UNIFI_KEYSTORE + fi + if [ "$DEPLOY_UNIFI_KEYPASS" ]; then + _savedomainconf DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" + else + _cleardomainconf DEPLOY_UNIFI_KEYPASS + fi + if [ "$DEPLOY_UNIFI_RELOAD" ]; then + _savedomainconf DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" + else + _cleardomainconf DEPLOY_UNIFI_RELOAD + fi + return 0 + else + _err "Reload error" + return 1 + fi + return 0 + +} From cd3a4573f26c03315121f505ac97b45c511d9cb9 Mon Sep 17 00:00:00 2001 From: Jeremy Knope Date: Mon, 31 Jul 2017 08:37:30 -0400 Subject: [PATCH 31/90] Fix shell check errors --- dnsapi/dns_linode.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_linode.sh b/dnsapi/dns_linode.sh index 00634d5d..26ca53e4 100755 --- a/dnsapi/dns_linode.sh +++ b/dnsapi/dns_linode.sh @@ -68,7 +68,7 @@ dns_linode_rm() { _parameters="&DomainID=$_domain_id" if _rest GET "domain.resource.list" "$_parameters" && [ -n "$response" ]; then - response="$(echo "$response" | tr -d "\n" | sed $'s/{/\\\n&/g')" + response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")" resource="$(echo "$response" | _egrep_o "{.*\"NAME\":\s*\"$_sub_domain\".*}")" if [ "$resource" ]; then @@ -128,7 +128,7 @@ _get_root() { p=1 if _rest GET "domain.list"; then - response="$(echo "$response" | tr -d "\n" | sed $'s/{/\\\n&/g')" + response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug h "$h" From c145f24621455f8608c179fc253d1fd00244bb6f Mon Sep 17 00:00:00 2001 From: Jeremy Knope Date: Thu, 3 Aug 2017 09:47:45 -0400 Subject: [PATCH 32/90] Remove extra space --- dnsapi/dns_linode.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_linode.sh b/dnsapi/dns_linode.sh index 26ca53e4..ead5b164 100755 --- a/dnsapi/dns_linode.sh +++ b/dnsapi/dns_linode.sh @@ -68,7 +68,7 @@ dns_linode_rm() { _parameters="&DomainID=$_domain_id" if _rest GET "domain.resource.list" "$_parameters" && [ -n "$response" ]; then - response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")" + response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")" resource="$(echo "$response" | _egrep_o "{.*\"NAME\":\s*\"$_sub_domain\".*}")" if [ "$resource" ]; then @@ -128,7 +128,7 @@ _get_root() { p=1 if _rest GET "domain.list"; then - response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")" + response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug h "$h" From 5c3b41bd93c2c4e6da40c445cd5f15a1ba3f7274 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 4 Aug 2017 21:57:45 +0800 Subject: [PATCH 33/90] format --- dnsapi/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/README.md b/dnsapi/README.md index 0888517b..b3b6344e 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -585,7 +585,7 @@ acme.sh --issue --dns dns_yandex -d mydomain.example.org For issues, please report to https://github.com/non7top/acme.sh/issues. -# 31. Use Hurricane Electric +## 31. Use Hurricane Electric Hurricane Electric doesn't have an API so just set your login credentials like so: From 415f375ce6f0de5a20545ba7ff6a9a7aa044c484 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 10 Aug 2017 21:31:28 +0800 Subject: [PATCH 34/90] support fcrontab, fix https://github.com/Neilpang/acme.sh/issues/966 --- acme.sh | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/acme.sh b/acme.sh index 60eef4bb..fe884e33 100755 --- a/acme.sh +++ b/acme.sh @@ -4417,15 +4417,19 @@ _installcert() { installcronjob() { _c_home="$1" _initpath - if ! _exists "crontab"; then - _err "crontab doesn't exist, so, we can not install cron jobs." + _CRONTAB="crontab" + if ! _exists "$_CRONTAB" && _exists "fcrontab"; then + _CRONTAB="fcrontab" + fi + if ! _exists "$_CRONTAB"; then + _err "crontab/fcrontab doesn't exist, so, we can not install cron jobs." _err "All your certs will not be renewed automatically." _err "You must add your own cron job to call '$PROJECT_ENTRY --cron' everyday." return 1 fi _info "Installing cron job" - if ! crontab -l | grep "$PROJECT_ENTRY --cron"; then + if ! $_CRONTAB -l | grep "$PROJECT_ENTRY --cron"; then if [ -f "$LE_WORKING_DIR/$PROJECT_ENTRY" ]; then lesh="\"$LE_WORKING_DIR\"/$PROJECT_ENTRY" else @@ -4439,15 +4443,15 @@ installcronjob() { _t=$(_time) random_minute=$(_math $_t % 60) if _exists uname && uname -a | grep SunOS >/dev/null; then - crontab -l | { + $_CRONTAB -l | { cat echo "$random_minute 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" $_c_entry> /dev/null" - } | crontab -- + } | $_CRONTAB -- else - crontab -l | { + $_CRONTAB -l | { cat echo "$random_minute 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" $_c_entry> /dev/null" - } | crontab - + } | $_CRONTAB - fi fi if [ "$?" != "0" ]; then @@ -4459,16 +4463,21 @@ installcronjob() { } uninstallcronjob() { - if ! _exists "crontab"; then + _CRONTAB="crontab" + if ! _exists "$_CRONTAB" && _exists "fcrontab"; then + _CRONTAB="fcrontab" + fi + + if ! _exists "$_CRONTAB"; then return fi _info "Removing cron job" - cr="$(crontab -l | grep "$PROJECT_ENTRY --cron")" + cr="$($_CRONTAB -l | grep "$PROJECT_ENTRY --cron")" if [ "$cr" ]; then if _exists uname && uname -a | grep solaris >/dev/null; then - crontab -l | sed "/$PROJECT_ENTRY --cron/d" | crontab -- + $_CRONTAB -l | sed "/$PROJECT_ENTRY --cron/d" | $_CRONTAB -- else - crontab -l | sed "/$PROJECT_ENTRY --cron/d" | crontab - + $_CRONTAB -l | sed "/$PROJECT_ENTRY --cron/d" | $_CRONTAB - fi LE_WORKING_DIR="$(echo "$cr" | cut -d ' ' -f 9 | tr -d '"')" _info LE_WORKING_DIR "$LE_WORKING_DIR" @@ -4745,7 +4754,7 @@ _precheck() { fi if [ -z "$_nocron" ]; then - if ! _exists "crontab"; then + if ! _exists "crontab" && ! _exists "fcrontab"; then _err "It is recommended to install crontab first. try to install 'cron, crontab, crontabs or vixie-cron'." _err "We need to set cron job to renew the certs automatically." _err "Otherwise, your certs will not be able to be renewed automatically." From 96801e3478d64427f8ec0937de1d30ec05b9432a Mon Sep 17 00:00:00 2001 From: Lonnie Abelbeck Date: Fri, 11 Aug 2017 16:46:29 -0500 Subject: [PATCH 35/90] Update DuckDNS support, fix failure on first call, no longer save the domain/username as a global, and other tweaks --- dnsapi/README.md | 5 +-- dnsapi/dns_duckdns.sh | 79 +++++++++++++++++++++++++++++++------------ 2 files changed, 59 insertions(+), 25 deletions(-) diff --git a/dnsapi/README.md b/dnsapi/README.md index b3b6344e..34b38678 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -512,14 +512,11 @@ export DuckDNS_Token="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" ``` Please note that since DuckDNS uses StartSSL as their cert provider, thus ---insecure must be used when issuing certs: +--insecure may need to be used when issuing certs: ``` acme.sh --insecure --issue --dns dns_duckdns -d mydomain.duckdns.org ``` -Also, DuckDNS uses the domain name as username for recording changing, so the -account file will always store the lastly used domain name. - For issues, please report to https://github.com/raidenii/acme.sh/issues. ## 28. Use Name.com API diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index d6987352..711b81ee 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -3,11 +3,14 @@ #Created by RaidenII, to use DuckDNS's API to add/remove text records #06/27/2017 -# Currently only support single domain access -# Due to the fact that DuckDNS uses StartSSL as cert provider, --insecure must be used with acme.sh +# Pass credentials before "acme.sh --issue --dns dns_duckdns ..." +# -- +# export DuckDNS_Token="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" +# -- +# +# Due to the fact that DuckDNS uses StartSSL as cert provider, --insecure may need to be used with acme.sh DuckDNS_API="https://www.duckdns.org/update" -API_Params="domains=$DuckDNS_Domain&token=$DuckDNS_Token" ######## Public functions ##################### @@ -16,35 +19,36 @@ dns_duckdns_add() { fulldomain=$1 txtvalue=$2 - # We'll extract the domain/username from full domain - DuckDNS_Domain=$(echo "$fulldomain" | _lower_case | _egrep_o '.[^.]*.duckdns.org' | cut -d . -f 2) - - if [ -z "$DuckDNS_Domain" ]; then - _err "Error extracting the domain." - return 1 - fi - + DuckDNS_Token="${DuckDNS_Token:-$(_readaccountconf_mutable DuckDNS_Token)}" if [ -z "$DuckDNS_Token" ]; then - DuckDNS_Token="" + _err "You must export variable: DuckDNS_Token" _err "The token for your DuckDNS account is necessary." _err "You can look it up in your DuckDNS account." return 1 fi # Now save the credentials. - _saveaccountconf DuckDNS_Domain "$DuckDNS_Domain" - _saveaccountconf DuckDNS_Token "$DuckDNS_Token" + _saveaccountconf_mutable DuckDNS_Token "$DuckDNS_Token" # Unfortunately, DuckDNS does not seems to support lookup domain through API # So I assume your credentials (which are your domain and token) are correct # If something goes wrong, we will get a KO response from DuckDNS + if ! _duckdns_get_domain; then + return 1 + fi + # Now add the TXT record to DuckDNS _info "Trying to add TXT record" - if _duckdns_rest GET "$API_Params&txt=$txtvalue" && [ "$response" = "OK" ]; then - _info "TXT record has been successfully added to your DuckDNS domain." - _info "Note that all subdomains under this domain uses the same TXT record." - return 0 + if _duckdns_rest GET "domains=$_duckdns_domain&token=$DuckDNS_Token&txt=$txtvalue"; then + if [ "$response" = "OK" ]; then + _info "TXT record has been successfully added to your DuckDNS domain." + _info "Note that all subdomains under this domain uses the same TXT record." + return 0 + else + _err "Errors happened during adding the TXT record, response=$response" + return 1 + fi else _err "Errors happened during adding the TXT record." return 1 @@ -57,11 +61,28 @@ dns_duckdns_rm() { fulldomain=$1 txtvalue=$2 + DuckDNS_Token="${DuckDNS_Token:-$(_readaccountconf_mutable DuckDNS_Token)}" + if [ -z "$DuckDNS_Token" ]; then + _err "You must export variable: DuckDNS_Token" + _err "The token for your DuckDNS account is necessary." + _err "You can look it up in your DuckDNS account." + return 1 + fi + + if ! _duckdns_get_domain; then + return 1 + fi + # Now remove the TXT record from DuckDNS _info "Trying to remove TXT record" - if _duckdns_rest GET "$API_Params&txt=&clear=true" && [ "$response" = "OK" ]; then - _info "TXT record has been successfully removed from your DuckDNS domain." - return 0 + if _duckdns_rest GET "domains=$_duckdns_domain&token=$DuckDNS_Token&txt=&clear=true"; then + if [ "$response" = "OK" ]; then + _info "TXT record has been successfully removed from your DuckDNS domain." + return 0 + else + _err "Errors happened during removing the TXT record, response=$response" + return 1 + fi else _err "Errors happened during removing the TXT record." return 1 @@ -70,6 +91,22 @@ dns_duckdns_rm() { #################### Private functions below ################################## +#fulldomain=_acme-challenge.domain.duckdns.org +#returns +# _duckdns_domain=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)" + + if [ -z "$_duckdns_domain" ]; then + _err "Error extracting the domain." + return 1 + fi + + return 0 +} + #Usage: method URI _duckdns_rest() { method=$1 From a07395fb563faff04f786e2e352aacf4dc7840ce Mon Sep 17 00:00:00 2001 From: Michele Date: Thu, 17 Aug 2017 12:50:28 +0200 Subject: [PATCH 36/90] Added support for busybox in time2str() awk fallback if none of preceding method works --- acme.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/acme.sh b/acme.sh index fe884e33..9bf9e1e0 100755 --- a/acme.sh +++ b/acme.sh @@ -1367,6 +1367,10 @@ _time2str() { echo "$_t_s_a" fi + #Busybox + if echo "$1" | awk '{ print strftime("%c", $0); }' 2>/dev/null; then + return + fi } _normalizeJson() { From 309bec474f11c1c9a2be472c44818703bfe6d911 Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 22 Aug 2017 20:27:13 +0800 Subject: [PATCH 37/90] add warning for dns manual mode --- acme.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/acme.sh b/acme.sh index 9bf9e1e0..cd2f981c 100755 --- a/acme.sh +++ b/acme.sh @@ -100,6 +100,10 @@ _PREPARE_LINK="https://github.com/Neilpang/acme.sh/wiki/Install-preparations" _STATELESS_WIKI="https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode" +_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" + __INTERACTIVE="" if [ -t 1 ]; then __INTERACTIVE="1" @@ -3046,6 +3050,10 @@ _on_issue_err() { ) fi + if [ "$IS_RENEW" = "1" ] && _hasfield "$Le_Webroot" "dns"; then + _err "$_DNS_MANUAL_ERR" + fi + if [ "$DEBUG" ] && [ "$DEBUG" -gt "0" ]; then _debug "$(_dlg_versions)" fi @@ -3078,6 +3086,10 @@ _on_issue_success() { fi fi + if _hasfield "$Le_Webroot" "dns"; then + _err "$_DNS_MANUAL_WARN" + fi + } updateaccount() { From 48e9006cd120317b62ee17e207c82517cc629d31 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 25 Aug 2017 20:51:31 +0800 Subject: [PATCH 38/90] fix cpanel uapi --- deploy/README.md | 18 ++++++++++++++++++ deploy/cpanel_uapi.sh | 15 ++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/deploy/README.md b/deploy/README.md index 232fdb4a..e026cadf 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -80,3 +80,21 @@ acme.sh --deploy -d ftp.example.com --deploy-hook exim4 ```sh acme.sh --deploy -d ftp.example.com --deploy-hook keychain ``` + +## 7. Deploy to cpanel host. + +``` +acme.sh --deploy -d example.com --deploy-hook cpanel_uapi +``` + +If you are login as root, please specify the username to deploy cert to: + +```sh +export DEPLOY_CPANEL_USER=username +acme.sh --deploy -d example.com --deploy-hook cpanel_uapi +``` + + + + + diff --git a/deploy/cpanel_uapi.sh b/deploy/cpanel_uapi.sh index ded50d0c..89ce1988 100644 --- a/deploy/cpanel_uapi.sh +++ b/deploy/cpanel_uapi.sh @@ -11,7 +11,7 @@ #domain keyfile certfile cafile fullchain -cpanel_uapi() { +cpanel_uapi_deploy() { _cdomain="$1" _ckey="$2" _ccert="$3" @@ -24,6 +24,14 @@ cpanel_uapi() { _debug _cca "$_cca" _debug _cfullchain "$_cfullchain" + if ! _exists uapi; then + _err "The command uapi is not found." + return 1 + fi + if ! _exists php; then + _err "The command php is not found." + return 1 + fi # read cert and key files and urlencode both _certstr=$(cat "$_ccert") _keystr=$(cat "$_ckey") @@ -34,6 +42,11 @@ cpanel_uapi() { _debug _key "$_key" if [ "$(id -u)" = 0 ]; then + if [ -z "$DEPLOY_CPANEL_USER" ]; then + _err "It seems that you are root, please define the target user name: export DEPLOY_CPANEL_USER=username" + return 1; + fi + _savedomainconf DEPLOY_CPANEL_USER "$DEPLOY_CPANEL_USER" _response=$(uapi --user="$DEPLOY_CPANEL_USER" SSL install_ssl domain="$_cdomain" cert="$_cert" key="$_key") else _response=$(uapi SSL install_ssl domain="$_cdomain" cert="$_cert" key="$_key") From a2d6daaef47feec91dcbf4dc1c4caec8630c1484 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 25 Aug 2017 20:54:10 +0800 Subject: [PATCH 39/90] fix cpanel_uapi.sh --- deploy/cpanel_uapi.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/cpanel_uapi.sh b/deploy/cpanel_uapi.sh index 89ce1988..2ba112c4 100644 --- a/deploy/cpanel_uapi.sh +++ b/deploy/cpanel_uapi.sh @@ -44,7 +44,7 @@ cpanel_uapi_deploy() { if [ "$(id -u)" = 0 ]; then if [ -z "$DEPLOY_CPANEL_USER" ]; then _err "It seems that you are root, please define the target user name: export DEPLOY_CPANEL_USER=username" - return 1; + return 1 fi _savedomainconf DEPLOY_CPANEL_USER "$DEPLOY_CPANEL_USER" _response=$(uapi --user="$DEPLOY_CPANEL_USER" SSL install_ssl domain="$_cdomain" cert="$_cert" key="$_key") From 88bb7b780d445d1874611aa841b51bdb153f1bfb Mon Sep 17 00:00:00 2001 From: fritteli Date: Tue, 29 Aug 2017 22:35:11 +0200 Subject: [PATCH 40/90] Typos --- dnsapi/dns_he.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 7d86eb7a..4d1973ad 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -47,7 +47,7 @@ dns_he_add() { response="$(_post "$body" "https://dns.he.net/")" exit_code="$?" if [ "$exit_code" -eq 0 ]; then - _info "TXT record added successfuly." + _info "TXT record added successfully." else _err "Couldn't add the TXT record." fi @@ -96,7 +96,7 @@ dns_he_rm() { >/dev/null exit_code="$?" if [ "$exit_code" -eq 0 ]; then - _info "Record removed successfuly." + _info "Record removed successfully." else _err "Could not clean (remove) up the record. Please go to HE administration interface and clean it by hand." return "$exit_code" From f6da19ba835e52fba79caec2544aa89af0116c62 Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Tue, 29 Aug 2017 23:13:29 +0200 Subject: [PATCH 41/90] add deploy script for the AVM FRITZ!Box --- deploy/fritzbox.sh | 85 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 deploy/fritzbox.sh diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh new file mode 100644 index 00000000..1290dc7a --- /dev/null +++ b/deploy/fritzbox.sh @@ -0,0 +1,85 @@ +#!/usr/bin/env sh + +#Here is a script to deploy cert to an AVM FRITZ!Box router. + +#returns 0 means success, otherwise error. + +#DEPLOY_FRITZBOX_USERNAME="username" +#DEPLOY_FRITZBOX_PASSWORD="password" +#DEPLOY_FRITZBOX_URL="https://fritz.box" + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +fritzbox_deploy() { + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + + if ! _exists wget; then + _err "wget not found" + return 1 + fi + if ! exists iconv; then + _err "iconv not found" + return 1 + fi + + _fritzbox_username="${DEPLOY_FRITZBOX_USERNAME}" + _fritzbox_password="${DEPLOY_FRITZBOX_PASSWORD}" + _fritzbox_url="${DEPLOY_FRITZBOX_URL}" + + _debug _fritzbox_url "$_fritzbox_url" + _debug _fritzbox_usename "$_fritzbox_username" + _secure_debug _fritzbox_password "$_fritzbox_password" + if [ ! -z "$_fritzbox_username" ]; then + _err "FRITZ!Box username is not found, please define DEPLOY_FRITZBOX_USERNAME." + return 1 + fi + if [ ! -z "$_fritzbox_password" ]; then + _err "FRITZ!Box password is not found, please define DEPLOY_FRITZBOX_PASSWORD." + return 1 + fi + if [ ! -z "$_fritzbox_url" ]; then + _err "FRITZ!Box url is not found, please define DEPLOY_FRITZBOX_URL." + return 1 + fi + + _info "Log in in to the FRITZ!Box" + _fritzbox_challenge="$(wget -q -O - ${_fritzbox_url}/login_sid.lua | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" + _fritzbox_hash="$(echo -n ${_fritzbox_challenge}-${_fritzbox_password} | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" + _fritzbox_sid="$(wget -q -O - ${_fritzbox_url}/login_sid.lua?sid=0000000000000000\&username=${_frithbox_username}\&response=${_fritzbox_challenge}-${_fritzbox_hash} | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" + + _info "Generate form POST request" + _post_request="$(_mktemp)" + _post_boundary="---------------------------$(date +%Y%m%d%H%M%S)" + printf -- "--${_post_boundary}\r\n" >> "${_post_request}" + printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n${_fritzbox_sid}\r\n" >> "${_post_request}" + printf -- "--${_post_boundary}\r\n" >> "${_post_request}" + # _CERTPASSWORD_ is unset because Let's Encrypt certificates don't have a passwort. But if they ever do, here's the place to use it! + printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n${_CERTPASSWORD_}\r\n" >> "${_post_request}" + printf -- "--${_post_boundary}\r\n" >> "${_post_request}" + printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n" >> "${_post_request}" + printf "Content-Type: application/octet-stream\r\n\r\n" >> "${_post_request}" + cat "${_ckey}" >> "${_post_request}" + cat "${_cfullchain}" >> "${_post_request}" + printf "\r\n" >> "${_post_request}" + printf -- "--${_post_boundary}--" >> "${_post_request}" + + _info "Upload certificate to the FRITZ!Box" + wget -q -O - "${_fritzbox_url}/cgi-bin/firmwarecfg" --header="Content-type: multipart/form-data boundary=${_post_boundary}" --post-file "${_post_request}" + + _info "Upload successful" + rm "${_post_request}" + + return 0 +} + From 4bb488258d24159284fc55b5b81d7a146880f0fc Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Tue, 29 Aug 2017 23:53:41 +0200 Subject: [PATCH 42/90] - Bugfixes - Make sure the login actually worked - Less output --- deploy/fritzbox.sh | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index 1290dc7a..c6a730c5 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -28,7 +28,7 @@ fritzbox_deploy() { _err "wget not found" return 1 fi - if ! exists iconv; then + if ! _exists iconv; then _err "iconv not found" return 1 fi @@ -40,23 +40,32 @@ fritzbox_deploy() { _debug _fritzbox_url "$_fritzbox_url" _debug _fritzbox_usename "$_fritzbox_username" _secure_debug _fritzbox_password "$_fritzbox_password" - if [ ! -z "$_fritzbox_username" ]; then + if [ -z "$_fritzbox_username" ]; then _err "FRITZ!Box username is not found, please define DEPLOY_FRITZBOX_USERNAME." return 1 fi - if [ ! -z "$_fritzbox_password" ]; then + if [ -z "$_fritzbox_password" ]; then _err "FRITZ!Box password is not found, please define DEPLOY_FRITZBOX_PASSWORD." return 1 fi - if [ ! -z "$_fritzbox_url" ]; then + if [ -z "$_fritzbox_url" ]; then _err "FRITZ!Box url is not found, please define DEPLOY_FRITZBOX_URL." return 1 fi - _info "Log in in to the FRITZ!Box" + _saveaccountconf DEPLOY_FRITZBOX_USERNAME "${_fritzbox_username}" + _saveaccountconf DEPLOY_FRITZBOX_PASSWORD "${_fritzbox_password}" + _saveaccountconf DEPLOY_FRITZBOX_URL "${_fritzbox_url}" + + _info "Log in to the FRITZ!Box" _fritzbox_challenge="$(wget -q -O - ${_fritzbox_url}/login_sid.lua | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" _fritzbox_hash="$(echo -n ${_fritzbox_challenge}-${_fritzbox_password} | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" - _fritzbox_sid="$(wget -q -O - ${_fritzbox_url}/login_sid.lua?sid=0000000000000000\&username=${_frithbox_username}\&response=${_fritzbox_challenge}-${_fritzbox_hash} | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" + _fritzbox_sid="$(wget -q -O - ${_fritzbox_url}/login_sid.lua?sid=0000000000000000\&username=${_fritzbox_username}\&response=${_fritzbox_challenge}-${_fritzbox_hash} | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" + + if [ -z "${_fritzbox_sid}" -o "${_fritzbox_sid}" = "0000000000000000" ] ; then + _err "Logging in to the FRITZ!Box failed. Please check username, password and URL." + return 1 + fi _info "Generate form POST request" _post_request="$(_mktemp)" @@ -65,6 +74,7 @@ fritzbox_deploy() { printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n${_fritzbox_sid}\r\n" >> "${_post_request}" printf -- "--${_post_boundary}\r\n" >> "${_post_request}" # _CERTPASSWORD_ is unset because Let's Encrypt certificates don't have a passwort. But if they ever do, here's the place to use it! + _CERTPASSWORD_= printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n${_CERTPASSWORD_}\r\n" >> "${_post_request}" printf -- "--${_post_boundary}\r\n" >> "${_post_request}" printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n" >> "${_post_request}" @@ -75,11 +85,10 @@ fritzbox_deploy() { printf -- "--${_post_boundary}--" >> "${_post_request}" _info "Upload certificate to the FRITZ!Box" - wget -q -O - "${_fritzbox_url}/cgi-bin/firmwarecfg" --header="Content-type: multipart/form-data boundary=${_post_boundary}" --post-file "${_post_request}" + wget -q -O - "${_fritzbox_url}/cgi-bin/firmwarecfg" --header="Content-type: multipart/form-data boundary=${_post_boundary}" --post-file "${_post_request}" | grep SSL _info "Upload successful" rm "${_post_request}" return 0 } - From d50281453d6bc704c0a647b523073f06b002ca34 Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Tue, 29 Aug 2017 23:57:24 +0200 Subject: [PATCH 43/90] Add --no-check-certificate option to wget, or else the initial deployment won't work because there isn't a valid certificate installed on the router yet. --- deploy/fritzbox.sh | 6 +-- deploy/fritzbox.sh~ | 94 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 deploy/fritzbox.sh~ diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index c6a730c5..16c310bc 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -58,9 +58,9 @@ fritzbox_deploy() { _saveaccountconf DEPLOY_FRITZBOX_URL "${_fritzbox_url}" _info "Log in to the FRITZ!Box" - _fritzbox_challenge="$(wget -q -O - ${_fritzbox_url}/login_sid.lua | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" + _fritzbox_challenge="$(wget --no-check-certificate -q -O - ${_fritzbox_url}/login_sid.lua | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" _fritzbox_hash="$(echo -n ${_fritzbox_challenge}-${_fritzbox_password} | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" - _fritzbox_sid="$(wget -q -O - ${_fritzbox_url}/login_sid.lua?sid=0000000000000000\&username=${_fritzbox_username}\&response=${_fritzbox_challenge}-${_fritzbox_hash} | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" + _fritzbox_sid="$(wget --no-check-certificate -q -O - ${_fritzbox_url}/login_sid.lua?sid=0000000000000000\&username=${_fritzbox_username}\&response=${_fritzbox_challenge}-${_fritzbox_hash} | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" if [ -z "${_fritzbox_sid}" -o "${_fritzbox_sid}" = "0000000000000000" ] ; then _err "Logging in to the FRITZ!Box failed. Please check username, password and URL." @@ -85,7 +85,7 @@ fritzbox_deploy() { printf -- "--${_post_boundary}--" >> "${_post_request}" _info "Upload certificate to the FRITZ!Box" - wget -q -O - "${_fritzbox_url}/cgi-bin/firmwarecfg" --header="Content-type: multipart/form-data boundary=${_post_boundary}" --post-file "${_post_request}" | grep SSL + wget --no-check-certificate -q -O - "${_fritzbox_url}/cgi-bin/firmwarecfg" --header="Content-type: multipart/form-data boundary=${_post_boundary}" --post-file "${_post_request}" | grep SSL _info "Upload successful" rm "${_post_request}" diff --git a/deploy/fritzbox.sh~ b/deploy/fritzbox.sh~ new file mode 100644 index 00000000..c6a730c5 --- /dev/null +++ b/deploy/fritzbox.sh~ @@ -0,0 +1,94 @@ +#!/usr/bin/env sh + +#Here is a script to deploy cert to an AVM FRITZ!Box router. + +#returns 0 means success, otherwise error. + +#DEPLOY_FRITZBOX_USERNAME="username" +#DEPLOY_FRITZBOX_PASSWORD="password" +#DEPLOY_FRITZBOX_URL="https://fritz.box" + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +fritzbox_deploy() { + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + + if ! _exists wget; then + _err "wget not found" + return 1 + fi + if ! _exists iconv; then + _err "iconv not found" + return 1 + fi + + _fritzbox_username="${DEPLOY_FRITZBOX_USERNAME}" + _fritzbox_password="${DEPLOY_FRITZBOX_PASSWORD}" + _fritzbox_url="${DEPLOY_FRITZBOX_URL}" + + _debug _fritzbox_url "$_fritzbox_url" + _debug _fritzbox_usename "$_fritzbox_username" + _secure_debug _fritzbox_password "$_fritzbox_password" + if [ -z "$_fritzbox_username" ]; then + _err "FRITZ!Box username is not found, please define DEPLOY_FRITZBOX_USERNAME." + return 1 + fi + if [ -z "$_fritzbox_password" ]; then + _err "FRITZ!Box password is not found, please define DEPLOY_FRITZBOX_PASSWORD." + return 1 + fi + if [ -z "$_fritzbox_url" ]; then + _err "FRITZ!Box url is not found, please define DEPLOY_FRITZBOX_URL." + return 1 + fi + + _saveaccountconf DEPLOY_FRITZBOX_USERNAME "${_fritzbox_username}" + _saveaccountconf DEPLOY_FRITZBOX_PASSWORD "${_fritzbox_password}" + _saveaccountconf DEPLOY_FRITZBOX_URL "${_fritzbox_url}" + + _info "Log in to the FRITZ!Box" + _fritzbox_challenge="$(wget -q -O - ${_fritzbox_url}/login_sid.lua | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" + _fritzbox_hash="$(echo -n ${_fritzbox_challenge}-${_fritzbox_password} | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" + _fritzbox_sid="$(wget -q -O - ${_fritzbox_url}/login_sid.lua?sid=0000000000000000\&username=${_fritzbox_username}\&response=${_fritzbox_challenge}-${_fritzbox_hash} | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" + + if [ -z "${_fritzbox_sid}" -o "${_fritzbox_sid}" = "0000000000000000" ] ; then + _err "Logging in to the FRITZ!Box failed. Please check username, password and URL." + return 1 + fi + + _info "Generate form POST request" + _post_request="$(_mktemp)" + _post_boundary="---------------------------$(date +%Y%m%d%H%M%S)" + printf -- "--${_post_boundary}\r\n" >> "${_post_request}" + printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n${_fritzbox_sid}\r\n" >> "${_post_request}" + printf -- "--${_post_boundary}\r\n" >> "${_post_request}" + # _CERTPASSWORD_ is unset because Let's Encrypt certificates don't have a passwort. But if they ever do, here's the place to use it! + _CERTPASSWORD_= + printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n${_CERTPASSWORD_}\r\n" >> "${_post_request}" + printf -- "--${_post_boundary}\r\n" >> "${_post_request}" + printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n" >> "${_post_request}" + printf "Content-Type: application/octet-stream\r\n\r\n" >> "${_post_request}" + cat "${_ckey}" >> "${_post_request}" + cat "${_cfullchain}" >> "${_post_request}" + printf "\r\n" >> "${_post_request}" + printf -- "--${_post_boundary}--" >> "${_post_request}" + + _info "Upload certificate to the FRITZ!Box" + wget -q -O - "${_fritzbox_url}/cgi-bin/firmwarecfg" --header="Content-type: multipart/form-data boundary=${_post_boundary}" --post-file "${_post_request}" | grep SSL + + _info "Upload successful" + rm "${_post_request}" + + return 0 +} From e6f81173a38c5768aae800acf058a2aea07f092e Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Tue, 29 Aug 2017 23:58:20 +0200 Subject: [PATCH 44/90] Delete auto-backup file --- deploy/fritzbox.sh~ | 94 --------------------------------------------- 1 file changed, 94 deletions(-) delete mode 100644 deploy/fritzbox.sh~ diff --git a/deploy/fritzbox.sh~ b/deploy/fritzbox.sh~ deleted file mode 100644 index c6a730c5..00000000 --- a/deploy/fritzbox.sh~ +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env sh - -#Here is a script to deploy cert to an AVM FRITZ!Box router. - -#returns 0 means success, otherwise error. - -#DEPLOY_FRITZBOX_USERNAME="username" -#DEPLOY_FRITZBOX_PASSWORD="password" -#DEPLOY_FRITZBOX_URL="https://fritz.box" - -######## Public functions ##################### - -#domain keyfile certfile cafile fullchain -fritzbox_deploy() { - _cdomain="$1" - _ckey="$2" - _ccert="$3" - _cca="$4" - _cfullchain="$5" - - _debug _cdomain "$_cdomain" - _debug _ckey "$_ckey" - _debug _ccert "$_ccert" - _debug _cca "$_cca" - _debug _cfullchain "$_cfullchain" - - if ! _exists wget; then - _err "wget not found" - return 1 - fi - if ! _exists iconv; then - _err "iconv not found" - return 1 - fi - - _fritzbox_username="${DEPLOY_FRITZBOX_USERNAME}" - _fritzbox_password="${DEPLOY_FRITZBOX_PASSWORD}" - _fritzbox_url="${DEPLOY_FRITZBOX_URL}" - - _debug _fritzbox_url "$_fritzbox_url" - _debug _fritzbox_usename "$_fritzbox_username" - _secure_debug _fritzbox_password "$_fritzbox_password" - if [ -z "$_fritzbox_username" ]; then - _err "FRITZ!Box username is not found, please define DEPLOY_FRITZBOX_USERNAME." - return 1 - fi - if [ -z "$_fritzbox_password" ]; then - _err "FRITZ!Box password is not found, please define DEPLOY_FRITZBOX_PASSWORD." - return 1 - fi - if [ -z "$_fritzbox_url" ]; then - _err "FRITZ!Box url is not found, please define DEPLOY_FRITZBOX_URL." - return 1 - fi - - _saveaccountconf DEPLOY_FRITZBOX_USERNAME "${_fritzbox_username}" - _saveaccountconf DEPLOY_FRITZBOX_PASSWORD "${_fritzbox_password}" - _saveaccountconf DEPLOY_FRITZBOX_URL "${_fritzbox_url}" - - _info "Log in to the FRITZ!Box" - _fritzbox_challenge="$(wget -q -O - ${_fritzbox_url}/login_sid.lua | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" - _fritzbox_hash="$(echo -n ${_fritzbox_challenge}-${_fritzbox_password} | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" - _fritzbox_sid="$(wget -q -O - ${_fritzbox_url}/login_sid.lua?sid=0000000000000000\&username=${_fritzbox_username}\&response=${_fritzbox_challenge}-${_fritzbox_hash} | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" - - if [ -z "${_fritzbox_sid}" -o "${_fritzbox_sid}" = "0000000000000000" ] ; then - _err "Logging in to the FRITZ!Box failed. Please check username, password and URL." - return 1 - fi - - _info "Generate form POST request" - _post_request="$(_mktemp)" - _post_boundary="---------------------------$(date +%Y%m%d%H%M%S)" - printf -- "--${_post_boundary}\r\n" >> "${_post_request}" - printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n${_fritzbox_sid}\r\n" >> "${_post_request}" - printf -- "--${_post_boundary}\r\n" >> "${_post_request}" - # _CERTPASSWORD_ is unset because Let's Encrypt certificates don't have a passwort. But if they ever do, here's the place to use it! - _CERTPASSWORD_= - printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n${_CERTPASSWORD_}\r\n" >> "${_post_request}" - printf -- "--${_post_boundary}\r\n" >> "${_post_request}" - printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n" >> "${_post_request}" - printf "Content-Type: application/octet-stream\r\n\r\n" >> "${_post_request}" - cat "${_ckey}" >> "${_post_request}" - cat "${_cfullchain}" >> "${_post_request}" - printf "\r\n" >> "${_post_request}" - printf -- "--${_post_boundary}--" >> "${_post_request}" - - _info "Upload certificate to the FRITZ!Box" - wget -q -O - "${_fritzbox_url}/cgi-bin/firmwarecfg" --header="Content-type: multipart/form-data boundary=${_post_boundary}" --post-file "${_post_request}" | grep SSL - - _info "Upload successful" - rm "${_post_request}" - - return 0 -} From 412e4e6cf9ecbf26c4d9b9330c3dfef1ddc92e42 Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Wed, 30 Aug 2017 00:24:31 +0200 Subject: [PATCH 45/90] Add acknowledgement note --- deploy/fritzbox.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index 16c310bc..804548c5 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -8,6 +8,9 @@ #DEPLOY_FRITZBOX_PASSWORD="password" #DEPLOY_FRITZBOX_URL="https://fritz.box" +# Kudos to wikrie at Github for his FRITZ!Box update script: +# https://gist.github.com/wikrie/f1d5747a714e0a34d0582981f7cb4cfb + ######## Public functions ##################### #domain keyfile certfile cafile fullchain From b6d48b7a144cefeebd3db92f8a3cabcad05139c6 Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Wed, 30 Aug 2017 00:45:03 +0200 Subject: [PATCH 46/90] Update README.md for the deploy hooks. --- deploy/README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/deploy/README.md b/deploy/README.md index e026cadf..d0f3d7f0 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -93,8 +93,18 @@ If you are login as root, please specify the username to deploy cert to: export DEPLOY_CPANEL_USER=username acme.sh --deploy -d example.com --deploy-hook cpanel_uapi ``` +## 8. Deploy the cert to your FRITZ!Box router +You must specify the credentials that have administrative privileges on the FRITZ!Box in order to deploy the certificate, plus the URL of your FRITZ!Box, through the following environment variables: +```sh +$ export DEPLOY_FRITZBOX_USERNAME=my_username +$ export DEPLOY_FRITZBOX_PASSWORD=the_password +$ export DEPLOY_FRITZBOX_URL=https://fritzbox.example.com +``` +After the first deployment, these values will be stored in your $HOME/.acme.sh/account.conf. You may now deploy the certificate like this: - +```sh +acme.sh --deploy -d fritz.box --deploy-hook fritzbox +``` From 103fa959cb7346d6bbade60d4009df84f1726a21 Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Wed, 30 Aug 2017 00:47:31 +0200 Subject: [PATCH 47/90] Typo --- deploy/fritzbox.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index 804548c5..cea84f59 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -41,7 +41,7 @@ fritzbox_deploy() { _fritzbox_url="${DEPLOY_FRITZBOX_URL}" _debug _fritzbox_url "$_fritzbox_url" - _debug _fritzbox_usename "$_fritzbox_username" + _debug _fritzbox_username "$_fritzbox_username" _secure_debug _fritzbox_password "$_fritzbox_password" if [ -z "$_fritzbox_username" ]; then _err "FRITZ!Box username is not found, please define DEPLOY_FRITZBOX_USERNAME." From a3a92ff1dfc283ffc80bfd2a3cb9527295a832e7 Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Thu, 31 Aug 2017 17:12:11 +0200 Subject: [PATCH 48/90] Fix formatting errors. --- deploy/fritzbox.sh | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index cea84f59..e2102eda 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -61,11 +61,11 @@ fritzbox_deploy() { _saveaccountconf DEPLOY_FRITZBOX_URL "${_fritzbox_url}" _info "Log in to the FRITZ!Box" - _fritzbox_challenge="$(wget --no-check-certificate -q -O - ${_fritzbox_url}/login_sid.lua | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" - _fritzbox_hash="$(echo -n ${_fritzbox_challenge}-${_fritzbox_password} | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" - _fritzbox_sid="$(wget --no-check-certificate -q -O - ${_fritzbox_url}/login_sid.lua?sid=0000000000000000\&username=${_fritzbox_username}\&response=${_fritzbox_challenge}-${_fritzbox_hash} | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" + _fritzbox_challenge="$(wget --no-check-certificate -q -O - "${_fritzbox_url}/login_sid.lua" | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" + _fritzbox_hash="$(echo -n "${_fritzbox_challenge}-${_fritzbox_password}" | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" + _fritzbox_sid="$(wget --no-check-certificate -q -O - "${_fritzbox_url}/login_sid.lua?sid=0000000000000000\&username=${_fritzbox_username}\&response=${_fritzbox_challenge}-${_fritzbox_hash}" | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" - if [ -z "${_fritzbox_sid}" -o "${_fritzbox_sid}" = "0000000000000000" ] ; then + if [ -z "${_fritzbox_sid}" ] || [ "${_fritzbox_sid}" = "0000000000000000" ]; then _err "Logging in to the FRITZ!Box failed. Please check username, password and URL." return 1 fi @@ -73,19 +73,24 @@ fritzbox_deploy() { _info "Generate form POST request" _post_request="$(_mktemp)" _post_boundary="---------------------------$(date +%Y%m%d%H%M%S)" - printf -- "--${_post_boundary}\r\n" >> "${_post_request}" - printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n${_fritzbox_sid}\r\n" >> "${_post_request}" - printf -- "--${_post_boundary}\r\n" >> "${_post_request}" + { + printf -- "--%s\r\n" "${_post_boundary}"; + printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n%s\r\n" "${_fritzbox_sid}"; + printf -- "--%s\r\n""${_post_boundary}"; + } >>"${_post_request}" # _CERTPASSWORD_ is unset because Let's Encrypt certificates don't have a passwort. But if they ever do, here's the place to use it! _CERTPASSWORD_= - printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n${_CERTPASSWORD_}\r\n" >> "${_post_request}" - printf -- "--${_post_boundary}\r\n" >> "${_post_request}" - printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n" >> "${_post_request}" - printf "Content-Type: application/octet-stream\r\n\r\n" >> "${_post_request}" - cat "${_ckey}" >> "${_post_request}" - cat "${_cfullchain}" >> "${_post_request}" - printf "\r\n" >> "${_post_request}" - printf -- "--${_post_boundary}--" >> "${_post_request}" + { + printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n%s\r\n" "${_CERTPASSWORD_}"; + printf -- "--%s\r\n" "${_post_boundary}"; + printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n"; + printf "Content-Type: application/octet-stream\r\n\r\n"; + } >>"${_post_request}" + cat "${_ckey}${_cfullchain}" >>"${_post_request}" + { + printf "\r\n"; + printf -- "--%s--" "${_post_boundary}"; + } >>"${_post_request}" _info "Upload certificate to the FRITZ!Box" wget --no-check-certificate -q -O - "${_fritzbox_url}/cgi-bin/firmwarecfg" --header="Content-type: multipart/form-data boundary=${_post_boundary}" --post-file "${_post_request}" | grep SSL From 6cb5377d73c2ad6a4c9e7adfc727b191f127910b Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Thu, 31 Aug 2017 17:25:08 +0200 Subject: [PATCH 49/90] Fix bugs and more/new formatting errors. --- deploy/fritzbox.sh | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index e2102eda..1fe28e89 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -63,7 +63,7 @@ fritzbox_deploy() { _info "Log in to the FRITZ!Box" _fritzbox_challenge="$(wget --no-check-certificate -q -O - "${_fritzbox_url}/login_sid.lua" | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" _fritzbox_hash="$(echo -n "${_fritzbox_challenge}-${_fritzbox_password}" | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" - _fritzbox_sid="$(wget --no-check-certificate -q -O - "${_fritzbox_url}/login_sid.lua?sid=0000000000000000\&username=${_fritzbox_username}\&response=${_fritzbox_challenge}-${_fritzbox_hash}" | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" + _fritzbox_sid="$(wget --no-check-certificate -q -O - "${_fritzbox_url}/login_sid.lua?sid=0000000000000000&username=${_fritzbox_username}&response=${_fritzbox_challenge}-${_fritzbox_hash}" | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" if [ -z "${_fritzbox_sid}" ] || [ "${_fritzbox_sid}" = "0000000000000000" ]; then _err "Logging in to the FRITZ!Box failed. Please check username, password and URL." @@ -74,22 +74,22 @@ fritzbox_deploy() { _post_request="$(_mktemp)" _post_boundary="---------------------------$(date +%Y%m%d%H%M%S)" { - printf -- "--%s\r\n" "${_post_boundary}"; - printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n%s\r\n" "${_fritzbox_sid}"; - printf -- "--%s\r\n""${_post_boundary}"; + printf -- "--%s\r\n" "${_post_boundary}" + printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n%s\r\n" "${_fritzbox_sid}" + printf -- "--%s\r\n" "${_post_boundary}" } >>"${_post_request}" # _CERTPASSWORD_ is unset because Let's Encrypt certificates don't have a passwort. But if they ever do, here's the place to use it! _CERTPASSWORD_= { - printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n%s\r\n" "${_CERTPASSWORD_}"; - printf -- "--%s\r\n" "${_post_boundary}"; - printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n"; - printf "Content-Type: application/octet-stream\r\n\r\n"; + printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n%s\r\n" "${_CERTPASSWORD_}" + printf -- "--%s\r\n" "${_post_boundary}" + printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n" + printf "Content-Type: application/octet-stream\r\n\r\n" } >>"${_post_request}" - cat "${_ckey}${_cfullchain}" >>"${_post_request}" + cat "${_ckey}" "${_cfullchain}" >>"${_post_request}" { - printf "\r\n"; - printf -- "--%s--" "${_post_boundary}"; + printf "\r\n" + printf -- "--%s--" "${_post_boundary}" } >>"${_post_request}" _info "Upload certificate to the FRITZ!Box" From 3794b5cb5846cc9713979027d68fc930211ec86e Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 1 Sep 2017 23:01:37 +0800 Subject: [PATCH 50/90] fix changes for :https://community.letsencrypt.org/t/acme-sh-standalone-fails-multiple-validation-requests-staging-multi-va/41249/8 use socat instead of nc. --- acme.sh | 79 +++++++++++++-------------------------------------------- 1 file changed, 17 insertions(+), 62 deletions(-) diff --git a/acme.sh b/acme.sh index cd2f981c..c7f8eddd 100755 --- a/acme.sh +++ b/acme.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -VER=2.7.3 +VER=2.7.4 PROJECT_NAME="acme.sh" @@ -164,11 +164,11 @@ _dlg_versions() { echo "nginx doesn't exists." fi - echo "nc:" - if _exists "nc"; then - nc -h 2>&1 + echo "socat:" + if _exists "socat"; then + socat -h 2>&1 else - _debug "nc doesn't exists." + _debug "socat doesn't exists." fi } @@ -1967,68 +1967,22 @@ _startserver() { _debug "ncaddr" "$ncaddr" _debug "startserver: $$" - nchelp="$(nc -h 2>&1)" _debug Le_HTTPPort "$Le_HTTPPort" _debug Le_Listen_V4 "$Le_Listen_V4" _debug Le_Listen_V6 "$Le_Listen_V6" - _NC="nc" + _NC="socat" if [ "$Le_Listen_V4" ]; then _NC="$_NC -4" elif [ "$Le_Listen_V6" ]; then _NC="$_NC -6" fi - if [ "$Le_Listen_V4$Le_Listen_V6$ncaddr" ]; then - if ! _contains "$nchelp" "-4"; then - _err "The nc doesn't support '-4', '-6' or local-address, please install 'netcat-openbsd' and try again." - _err "See $(__green $_PREPARE_LINK)" - return 1 - fi - fi - - if echo "$nchelp" | grep "\-q[ ,]" >/dev/null; then - _NC="$_NC -q 1 -l $ncaddr" - else - if echo "$nchelp" | grep "GNU netcat" >/dev/null && echo "$nchelp" | grep "\-c, \-\-close" >/dev/null; then - _NC="$_NC -c -l $ncaddr" - elif echo "$nchelp" | grep "\-N" | grep "Shutdown the network socket after EOF on stdin" >/dev/null; then - _NC="$_NC -N -l $ncaddr" - else - _NC="$_NC -l $ncaddr" - fi - fi - _debug "_NC" "$_NC" - - #for centos ncat - if _contains "$nchelp" "nmap.org"; then - _debug "Using ncat: nmap.org" - if ! _exec "printf \"%s\r\n\r\n%s\" \"HTTP/1.1 200 OK\" \"$content\" | $_NC \"$Le_HTTPPort\" >&2"; then - _exec_err - return 1 - fi - if [ "$DEBUG" ]; then - _exec_err - fi - return - fi - - # while true ; do - if ! _exec "printf \"%s\r\n\r\n%s\" \"HTTP/1.1 200 OK\" \"$content\" | $_NC -p \"$Le_HTTPPort\" >&2"; then - _exec "printf \"%s\r\n\r\n%s\" \"HTTP/1.1 200 OK\" \"$content\" | $_NC \"$Le_HTTPPort\" >&2" - fi - - if [ "$?" != "0" ]; then - _err "nc listen error." - _exec_err - exit 1 - fi - if [ "$DEBUG" ]; then - _exec_err - fi - # done + #todo listen address + socat TCP-LISTEN:$Le_HTTPPort,crlf,reuseaddr,fork SYSTEM:"echo HTTP/1.1 200 OK'; echo ; echo $content; echo;" & + serverproc="$!" } _stopserver() { @@ -2038,6 +1992,8 @@ _stopserver() { return fi + kill $pid + _debug2 "Le_HTTPPort" "$Le_HTTPPort" if [ "$Le_HTTPPort" ]; then if [ "$DEBUG" ] && [ "$DEBUG" -gt "3" ]; then @@ -2943,8 +2899,8 @@ _on_before_issue() { fi if _hasfield "$_chk_web_roots" "$NO_VALUE"; then - if ! _exists "nc"; then - _err "Please install netcat(nc) tools first." + if ! _exists "socat"; then + _err "Please install socat tools first." return 1 fi fi @@ -3665,13 +3621,12 @@ issue() { _info "Standalone mode server" _ncaddr="$(_getfield "$_local_addr" "$_ncIndex")" _ncIndex="$(_math $_ncIndex + 1)" - _startserver "$keyauthorization" "$_ncaddr" & + _startserver "$keyauthorization" "$_ncaddr" if [ "$?" != "0" ]; then _clearup _on_issue_err "$_post_hook" "$vlist" return 1 fi - serverproc="$!" sleep 1 _debug serverproc "$serverproc" elif [ "$_currentRoot" = "$MODE_STATELESS" ]; then @@ -4788,9 +4743,9 @@ _precheck() { return 1 fi - if ! _exists "nc"; then - _err "It is recommended to install nc first, try to install 'nc' or 'netcat'." - _err "We use nc for standalone server if you use standalone mode." + if ! _exists "socat"; then + _err "It is recommended to install socat first." + _err "We use socat for standalone server if you use standalone mode." _err "If you don't use standalone mode, just ignore this warning." fi From 443a5ca0c2d0af8e11f720f3acbb04ee628a001b Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 1 Sep 2017 23:44:52 +0800 Subject: [PATCH 51/90] socat tls mode --- acme.sh | 33 +++------------------------------ 1 file changed, 3 insertions(+), 30 deletions(-) diff --git a/acme.sh b/acme.sh index c7f8eddd..84ae7e93 100755 --- a/acme.sh +++ b/acme.sh @@ -1994,25 +1994,6 @@ _stopserver() { kill $pid - _debug2 "Le_HTTPPort" "$Le_HTTPPort" - if [ "$Le_HTTPPort" ]; then - if [ "$DEBUG" ] && [ "$DEBUG" -gt "3" ]; then - _get "http://localhost:$Le_HTTPPort" "" 1 - else - _get "http://localhost:$Le_HTTPPort" "" 1 >/dev/null 2>&1 - fi - fi - - _debug2 "Le_TLSPort" "$Le_TLSPort" - if [ "$Le_TLSPort" ]; then - if [ "$DEBUG" ] && [ "$DEBUG" -gt "3" ]; then - _get "https://localhost:$Le_TLSPort" "" 1 - _get "https://localhost:$Le_TLSPort" "" 1 - else - _get "https://localhost:$Le_TLSPort" "" 1 >/dev/null 2>&1 - _get "https://localhost:$Le_TLSPort" "" 1 >/dev/null 2>&1 - fi - fi } # sleep sec @@ -2067,12 +2048,7 @@ _starttlsserver() { return 1 fi - __S_OPENSSL="${ACME_OPENSSL_BIN:-openssl} s_server -cert $TLS_CERT -key $TLS_KEY " - if [ "$opaddr" ]; then - __S_OPENSSL="$__S_OPENSSL -accept $opaddr:$port" - else - __S_OPENSSL="$__S_OPENSSL -accept $port" - fi + __S_OPENSSL="socat" _debug Le_Listen_V4 "$Le_Listen_V4" _debug Le_Listen_V6 "$Le_Listen_V6" @@ -2083,12 +2059,9 @@ _starttlsserver() { fi _debug "$__S_OPENSSL" - if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then - (printf "%s\r\n\r\n%s" "HTTP/1.1 200 OK" "$content" | $__S_OPENSSL -tlsextdebug) & - else - (printf "%s\r\n\r\n%s" "HTTP/1.1 200 OK" "$content" | $__S_OPENSSL >/dev/null 2>&1) & - fi + #todo listen address + $__S_OPENSSL openssl-listen:$port,cert=$TLS_CERT,key=$TLS_KEY,verify=0,reuseaddr,fork SYSTEM:"echo HTTP/1.1 200 OK'; echo ; echo $content; echo;" & serverproc="$!" sleep 1 _debug serverproc "$serverproc" From 7b8ddfdd96d5edd6992335a1f289b845ab9403d2 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 2 Sep 2017 08:59:30 +0800 Subject: [PATCH 52/90] use socat --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 2ba02b9c..1378e947 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,6 +20,7 @@ install: - if [ "$TRAVIS_OS_NAME" = 'osx' ]; then brew update && brew install openssl; brew info openssl; + brew info socat; ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/Cellar/openssl/1.0.2j/bin/openssl /usr/local/openssl; @@ -30,6 +31,7 @@ install: openssl version 2>&1 || true; $ACME_OPENSSL_BIN version 2>&1 || true; export PATH="$_old_path"; + else sudo apt-get install socat; fi script: From cc6610edc2fe1c4d19aed233ac5449b2124de4ea Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 2 Sep 2017 17:32:40 +0800 Subject: [PATCH 53/90] add socat --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1378e947..b45cc464 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,9 +18,8 @@ addons: install: - if [ "$TRAVIS_OS_NAME" = 'osx' ]; then - brew update && brew install openssl; + brew update && brew install openssl socat; brew info openssl; - brew info socat; ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/Cellar/openssl/1.0.2j/bin/openssl /usr/local/openssl; From f9cdfd3e5baf89eb84f04a5a912223e2c57c01bb Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 2 Sep 2017 18:58:07 +0800 Subject: [PATCH 54/90] fix for behind proxy --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 84ae7e93..07617c40 100755 --- a/acme.sh +++ b/acme.sh @@ -1981,7 +1981,7 @@ _startserver() { _debug "_NC" "$_NC" #todo listen address - socat TCP-LISTEN:$Le_HTTPPort,crlf,reuseaddr,fork SYSTEM:"echo HTTP/1.1 200 OK'; echo ; echo $content; echo;" & + socat TCP-LISTEN:$Le_HTTPPort,crlf,reuseaddr,fork SYSTEM:"sleep 0.5; echo HTTP/1.1 200 OK'; echo ; echo $content; echo;" & serverproc="$!" } @@ -2061,7 +2061,7 @@ _starttlsserver() { _debug "$__S_OPENSSL" #todo listen address - $__S_OPENSSL openssl-listen:$port,cert=$TLS_CERT,key=$TLS_KEY,verify=0,reuseaddr,fork SYSTEM:"echo HTTP/1.1 200 OK'; echo ; echo $content; echo;" & + $__S_OPENSSL openssl-listen:$port,cert=$TLS_CERT,key=$TLS_KEY,verify=0,reuseaddr,fork SYSTEM:"sleep 0.5; echo HTTP/1.1 200 OK'; echo ; echo $content; echo;" & serverproc="$!" sleep 1 _debug serverproc "$serverproc" From 6104680caa1c1542b5c2291b8392f5b67b061717 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 2 Sep 2017 20:46:04 +0800 Subject: [PATCH 55/90] fix https://github.com/Neilpang/acme.sh/issues/999 --- acme.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 07617c40..45287eef 100755 --- a/acme.sh +++ b/acme.sh @@ -3934,7 +3934,10 @@ issue() { Le_NextRenewTime=$(_math "$Le_NextRenewTime" - 86400) _savedomainconf "Le_NextRenewTime" "$Le_NextRenewTime" - _on_issue_success "$_post_hook" "$_renew_hook" + if ! _on_issue_success "$_post_hook" "$_renew_hook"; then + _err "Call hook error." + return 1 + fi if [ "$_real_cert$_real_key$_real_ca$_reload_cmd$_real_fullchain" ]; then _savedomainconf "Le_RealCertPath" "$_real_cert" From 4356eefbb10d519cdbd6d44a52b757e3df348075 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 3 Sep 2017 08:42:44 +0800 Subject: [PATCH 56/90] fix https://github.com/Neilpang/acme.sh/issues/1005#event-1232471561 --- acme.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/acme.sh b/acme.sh index 45287eef..f6447f73 100755 --- a/acme.sh +++ b/acme.sh @@ -4821,9 +4821,11 @@ install() { _debug "Skip install cron job" fi - if ! _precheck "$_nocron"; then - _err "Pre-check failed, can not install." - return 1 + if [ "$IN_CRON" != "1" ]; then + if ! _precheck "$_nocron"; then + _err "Pre-check failed, can not install." + return 1 + fi fi if [ -z "$_c_home" ] && [ "$LE_CONFIG_HOME" != "$LE_WORKING_DIR" ]; then @@ -4876,7 +4878,9 @@ install() { _info "Installed to $LE_WORKING_DIR/$PROJECT_ENTRY" - _installalias "$_c_home" + if [ "$IN_CRON" != "1" ]; then + _installalias "$_c_home" + fi for subf in $_SUB_FOLDERS; do if [ -d "$subf" ]; then From c73fdd402243071d01a23eae7ae17088b5914d7d Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 3 Sep 2017 08:45:58 +0800 Subject: [PATCH 57/90] minor --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index f6447f73..e482b87b 100755 --- a/acme.sh +++ b/acme.sh @@ -4970,7 +4970,7 @@ _uninstallalias() { } cron() { - IN_CRON=1 + export IN_CRON=1 _initpath _info "$(__green "===Starting cron===")" if [ "$AUTO_UPGRADE" = "1" ]; then From e52304edb47b974c905e88bc41b7124705f514e6 Mon Sep 17 00:00:00 2001 From: Santeri Date: Sun, 3 Sep 2017 13:35:20 +0400 Subject: [PATCH 58/90] cpanel_uapi tried to make it a bit less confusing --- deploy/README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/deploy/README.md b/deploy/README.md index e026cadf..62a3fb6f 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -6,6 +6,8 @@ Here are the scripts to deploy the certs/key to the server/services. ## 1. Deploy the certs to your cpanel host. +If you want to deploy using cpanel UAPI see 7. + (cpanel deploy hook is not finished yet, this is just an example.) @@ -81,14 +83,13 @@ acme.sh --deploy -d ftp.example.com --deploy-hook exim4 acme.sh --deploy -d ftp.example.com --deploy-hook keychain ``` -## 7. Deploy to cpanel host. +## 7. Deploy to cpanel host using UAPI +This hook is using UAPI and works in cPanel & WHM version 56 or newer. ``` acme.sh --deploy -d example.com --deploy-hook cpanel_uapi ``` - -If you are login as root, please specify the username to deploy cert to: - +DEPLOY_CPANEL_USER is required only if you run the script as root and it should contain cpanel username. ```sh export DEPLOY_CPANEL_USER=username acme.sh --deploy -d example.com --deploy-hook cpanel_uapi From a098167bdbd145ff3d522b33c4d18f99e8ff09ec Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Mon, 4 Sep 2017 14:07:10 +0200 Subject: [PATCH 59/90] Fix more formatting errors --- deploy/fritzbox.sh | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index 1fe28e89..c86b44ad 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -62,7 +62,7 @@ fritzbox_deploy() { _info "Log in to the FRITZ!Box" _fritzbox_challenge="$(wget --no-check-certificate -q -O - "${_fritzbox_url}/login_sid.lua" | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" - _fritzbox_hash="$(echo -n "${_fritzbox_challenge}-${_fritzbox_password}" | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" + _fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" _fritzbox_sid="$(wget --no-check-certificate -q -O - "${_fritzbox_url}/login_sid.lua?sid=0000000000000000&username=${_fritzbox_username}&response=${_fritzbox_challenge}-${_fritzbox_hash}" | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" if [ -z "${_fritzbox_sid}" ] || [ "${_fritzbox_sid}" = "0000000000000000" ]; then @@ -73,14 +73,12 @@ fritzbox_deploy() { _info "Generate form POST request" _post_request="$(_mktemp)" _post_boundary="---------------------------$(date +%Y%m%d%H%M%S)" + # _CERTPASSWORD_ is unset because Let's Encrypt certificates don't have a password. But if they ever do, here's the place to use it! + _CERTPASSWORD_= { printf -- "--%s\r\n" "${_post_boundary}" printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n%s\r\n" "${_fritzbox_sid}" printf -- "--%s\r\n" "${_post_boundary}" - } >>"${_post_request}" - # _CERTPASSWORD_ is unset because Let's Encrypt certificates don't have a passwort. But if they ever do, here's the place to use it! - _CERTPASSWORD_= - { printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n%s\r\n" "${_CERTPASSWORD_}" printf -- "--%s\r\n" "${_post_boundary}" printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n" From bd8b1a2501a867a373772398b3687ac47341f0f5 Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Mon, 4 Sep 2017 14:27:22 +0200 Subject: [PATCH 60/90] Don't use wget directly, but instead use _get and _post. --- deploy/fritzbox.sh | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index c86b44ad..e7d01a8b 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -27,10 +27,6 @@ fritzbox_deploy() { _debug _cca "$_cca" _debug _cfullchain "$_cfullchain" - if ! _exists wget; then - _err "wget not found" - return 1 - fi if ! _exists iconv; then _err "iconv not found" return 1 @@ -60,10 +56,13 @@ fritzbox_deploy() { _saveaccountconf DEPLOY_FRITZBOX_PASSWORD "${_fritzbox_password}" _saveaccountconf DEPLOY_FRITZBOX_URL "${_fritzbox_url}" + # Do not check for a valid SSL certificate, because initially the cert is not valid, so it could not install the LE generated certificate + export HTTPS_INSECURE=1 + _info "Log in to the FRITZ!Box" - _fritzbox_challenge="$(wget --no-check-certificate -q -O - "${_fritzbox_url}/login_sid.lua" | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" + _fritzbox_challenge="$(_get "${_fritzbox_url}/login_sid.lua" | sed -e 's/^.*//' -e 's/<\/Challenge>.*$//')" _fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')" - _fritzbox_sid="$(wget --no-check-certificate -q -O - "${_fritzbox_url}/login_sid.lua?sid=0000000000000000&username=${_fritzbox_username}&response=${_fritzbox_challenge}-${_fritzbox_hash}" | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" + _fritzbox_sid="$(_get "${_fritzbox_url}/login_sid.lua?sid=0000000000000000&username=${_fritzbox_username}&response=${_fritzbox_challenge}-${_fritzbox_hash}" | sed -e 's/^.*//' -e 's/<\/SID>.*$//')" if [ -z "${_fritzbox_sid}" ] || [ "${_fritzbox_sid}" = "0000000000000000" ]; then _err "Logging in to the FRITZ!Box failed. Please check username, password and URL." @@ -91,10 +90,17 @@ fritzbox_deploy() { } >>"${_post_request}" _info "Upload certificate to the FRITZ!Box" - wget --no-check-certificate -q -O - "${_fritzbox_url}/cgi-bin/firmwarecfg" --header="Content-type: multipart/form-data boundary=${_post_boundary}" --post-file "${_post_request}" | grep SSL - _info "Upload successful" + export _H1="Content-type: multipart/form-data boundary=${_post_boundary}" + _post "$(cat ${_post_request})" "${_fritzbox_url}/cgi-bin/firmwarecfg" | grep SSL + + retval=$? + if [ $retval = 0 ] ; then + _info "Upload successful" + else + _err "Upload failed" + fi rm "${_post_request}" - return 0 + return $retval } From 8ee5ede834f2493b9d0e3af9a251ccfbaf4156ec Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Mon, 4 Sep 2017 14:30:40 +0200 Subject: [PATCH 61/90] Fix more formatting errors --- deploy/fritzbox.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index e7d01a8b..a6f6684c 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -92,10 +92,10 @@ fritzbox_deploy() { _info "Upload certificate to the FRITZ!Box" export _H1="Content-type: multipart/form-data boundary=${_post_boundary}" - _post "$(cat ${_post_request})" "${_fritzbox_url}/cgi-bin/firmwarecfg" | grep SSL + _post "$(cat "${_post_request}")" "${_fritzbox_url}/cgi-bin/firmwarecfg" | grep SSL retval=$? - if [ $retval = 0 ] ; then + if [ $retval = 0 ]; then _info "Upload successful" else _err "Upload failed" From 72e1eb88d969dfb26935b1c8070db7685105d6b1 Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Mon, 4 Sep 2017 14:40:28 +0200 Subject: [PATCH 62/90] Don't use individual redirects, but do it all in one block. --- deploy/fritzbox.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index a6f6684c..dbff3680 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -82,9 +82,7 @@ fritzbox_deploy() { printf -- "--%s\r\n" "${_post_boundary}" printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n" printf "Content-Type: application/octet-stream\r\n\r\n" - } >>"${_post_request}" - cat "${_ckey}" "${_cfullchain}" >>"${_post_request}" - { + cat "${_ckey}" "${_cfullchain}" printf "\r\n" printf -- "--%s--" "${_post_boundary}" } >>"${_post_request}" From 1e30718df63555700444226ef056f132f8620a1c Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Mon, 4 Sep 2017 14:48:27 +0200 Subject: [PATCH 63/90] Try and work around shellcheck error SC2039: In POSIX sh, printf -%s-- is undefined. --- deploy/fritzbox.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/deploy/fritzbox.sh b/deploy/fritzbox.sh index dbff3680..943b198d 100644 --- a/deploy/fritzbox.sh +++ b/deploy/fritzbox.sh @@ -75,16 +75,20 @@ fritzbox_deploy() { # _CERTPASSWORD_ is unset because Let's Encrypt certificates don't have a password. But if they ever do, here's the place to use it! _CERTPASSWORD_= { - printf -- "--%s\r\n" "${_post_boundary}" + printf -- "--" + printf -- "%s\r\n" "${_post_boundary}" printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n%s\r\n" "${_fritzbox_sid}" - printf -- "--%s\r\n" "${_post_boundary}" + printf -- "--" + printf -- "%s\r\n" "${_post_boundary}" printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n%s\r\n" "${_CERTPASSWORD_}" - printf -- "--%s\r\n" "${_post_boundary}" + printf -- "--" + printf -- "%s\r\n" "${_post_boundary}" printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n" printf "Content-Type: application/octet-stream\r\n\r\n" cat "${_ckey}" "${_cfullchain}" printf "\r\n" - printf -- "--%s--" "${_post_boundary}" + printf -- "--" + printf -- "%s--" "${_post_boundary}" } >>"${_post_request}" _info "Upload certificate to the FRITZ!Box" From 8148bfeacf43a311551c00473f39c514e5f50d52 Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 5 Sep 2017 20:32:14 +0800 Subject: [PATCH 64/90] fix https://github.com/Neilpang/acme.sh/issues/998 --- acme.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index e482b87b..d9855651 100755 --- a/acme.sh +++ b/acme.sh @@ -1814,7 +1814,12 @@ _send_signed_request() { _CACHED_NONCE="$(echo "$responseHeaders" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)" - if _contains "$response" "JWS has invalid anti-replay nonce"; then + _body="$response" + if [ "$needbase64" ]; then + _body="$(echo "$_body" | _dbase64)" + fi + _debug3 _body "$_body" + if _contains "$_body" "JWS has invalid anti-replay nonce"; then _info "It seems the CA server is busy now, let's wait and retry." _request_retry_times=$(_math "$_request_retry_times" + 1) _sleep 5 From f81d4033fa0e85f4a4cb789e250bb52d3a282e5f Mon Sep 17 00:00:00 2001 From: Santeri Kannisto Date: Tue, 5 Sep 2017 17:37:48 +0400 Subject: [PATCH 65/90] One cert per domain Deploy works only for the first domain --- deploy/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/deploy/README.md b/deploy/README.md index 62a3fb6f..48caea6f 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -94,6 +94,7 @@ DEPLOY_CPANEL_USER is required only if you run the script as root and it should export DEPLOY_CPANEL_USER=username acme.sh --deploy -d example.com --deploy-hook cpanel_uapi ``` +Please note, that the cpanel_uapi hook will deploy only the first domain when your certificate will automatically renew. Therefore you should issue only one certificate per domain. From a9726fde1948c7404e8873e9b6264785081b025a Mon Sep 17 00:00:00 2001 From: Santeri Kannisto Date: Tue, 5 Sep 2017 17:42:17 +0400 Subject: [PATCH 66/90] 1 cert per domain for cpanel_uapi --- deploy/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/README.md b/deploy/README.md index 48caea6f..c80a567e 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -94,7 +94,7 @@ DEPLOY_CPANEL_USER is required only if you run the script as root and it should export DEPLOY_CPANEL_USER=username acme.sh --deploy -d example.com --deploy-hook cpanel_uapi ``` -Please note, that the cpanel_uapi hook will deploy only the first domain when your certificate will automatically renew. Therefore you should issue only one certificate per domain. +Please note, that the cpanel_uapi hook will deploy only the first domain when your certificate will automatically renew. Therefore you should issue a separete certificate for each domain. From 3eeb090578a371eb5e5ce507adb27a6cf1676ac8 Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 6 Sep 2017 20:50:31 +0800 Subject: [PATCH 67/90] fix tls mode back to use openssl --- acme.sh | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index d9855651..83c06fa5 100755 --- a/acme.sh +++ b/acme.sh @@ -2053,7 +2053,12 @@ _starttlsserver() { return 1 fi - __S_OPENSSL="socat" + __S_OPENSSL="${ACME_OPENSSL_BIN:-openssl} s_server -www -cert $TLS_CERT -key $TLS_KEY " + if [ "$opaddr" ]; then + __S_OPENSSL="$__S_OPENSSL -accept $opaddr:$port" + else + __S_OPENSSL="$__S_OPENSSL -accept $port" + fi _debug Le_Listen_V4 "$Le_Listen_V4" _debug Le_Listen_V6 "$Le_Listen_V6" @@ -2064,9 +2069,12 @@ _starttlsserver() { fi _debug "$__S_OPENSSL" + if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then + $__S_OPENSSL -tlsextdebug & + else + $__S_OPENSSL >/dev/null 2>&1 & + fi - #todo listen address - $__S_OPENSSL openssl-listen:$port,cert=$TLS_CERT,key=$TLS_KEY,verify=0,reuseaddr,fork SYSTEM:"sleep 0.5; echo HTTP/1.1 200 OK'; echo ; echo $content; echo;" & serverproc="$!" sleep 1 _debug serverproc "$serverproc" From 53273a15bf54d2b3c48e8351c592f42ee1e49dab Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 6 Sep 2017 21:18:02 +0800 Subject: [PATCH 68/90] use socat for tls mode --- acme.sh | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/acme.sh b/acme.sh index 83c06fa5..d9855651 100755 --- a/acme.sh +++ b/acme.sh @@ -2053,12 +2053,7 @@ _starttlsserver() { return 1 fi - __S_OPENSSL="${ACME_OPENSSL_BIN:-openssl} s_server -www -cert $TLS_CERT -key $TLS_KEY " - if [ "$opaddr" ]; then - __S_OPENSSL="$__S_OPENSSL -accept $opaddr:$port" - else - __S_OPENSSL="$__S_OPENSSL -accept $port" - fi + __S_OPENSSL="socat" _debug Le_Listen_V4 "$Le_Listen_V4" _debug Le_Listen_V6 "$Le_Listen_V6" @@ -2069,12 +2064,9 @@ _starttlsserver() { fi _debug "$__S_OPENSSL" - if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then - $__S_OPENSSL -tlsextdebug & - else - $__S_OPENSSL >/dev/null 2>&1 & - fi + #todo listen address + $__S_OPENSSL openssl-listen:$port,cert=$TLS_CERT,key=$TLS_KEY,verify=0,reuseaddr,fork SYSTEM:"sleep 0.5; echo HTTP/1.1 200 OK'; echo ; echo $content; echo;" & serverproc="$!" sleep 1 _debug serverproc "$serverproc" From 856811bd2e23279fcc44efed041c65e011253eb7 Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Wed, 6 Sep 2017 17:04:40 +0000 Subject: [PATCH 69/90] Use stable gandi API url The gandi api has changed its url for a more stable one. Although https://dns.beta.gandi.net will continue to work for the foreseable future, this commits updates the url to new official one. --- dnsapi/dns_gandi_livedns.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_gandi_livedns.sh b/dnsapi/dns_gandi_livedns.sh index 82ed599c..7a21aba6 100755 --- a/dnsapi/dns_gandi_livedns.sh +++ b/dnsapi/dns_gandi_livedns.sh @@ -11,7 +11,7 @@ # ######## Public functions ##################### -GANDI_LIVEDNS_API="https://dns.beta.gandi.net/api/v5" +GANDI_LIVEDNS_API="https://dns.api.gandi.net/api/v5" #Usage: dns_gandi_livedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_gandi_livedns_add() { From a6b399286e4dcd387c5193589358d066174d51eb Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 9 Sep 2017 14:15:11 +0800 Subject: [PATCH 70/90] add socat --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 7ca042ea..e85098e0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ RUN apk update -f \ && apk --no-cache add -f \ openssl \ curl \ - netcat-openbsd \ + socat \ && rm -rf /var/cache/apk/* ENV LE_CONFIG_HOME /acme.sh From 36309e6dbc5b074b108c268bb2a652689aae379d Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 11 Sep 2017 21:28:37 +0800 Subject: [PATCH 71/90] minor, fix debug info --- acme.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index d9855651..b1a7f68a 100755 --- a/acme.sh +++ b/acme.sh @@ -1817,8 +1817,9 @@ _send_signed_request() { _body="$response" if [ "$needbase64" ]; then _body="$(echo "$_body" | _dbase64)" + _debug2 _body "$_body" fi - _debug3 _body "$_body" + if _contains "$_body" "JWS has invalid anti-replay nonce"; then _info "It seems the CA server is busy now, let's wait and retry." _request_retry_times=$(_math "$_request_retry_times" + 1) From 95949b6519b4b7e8de5f8dc83ef900d558caa331 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 11 Sep 2017 21:40:56 +0800 Subject: [PATCH 72/90] minor --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index b1a7f68a..e7746931 100755 --- a/acme.sh +++ b/acme.sh @@ -1987,7 +1987,7 @@ _startserver() { _debug "_NC" "$_NC" #todo listen address - socat TCP-LISTEN:$Le_HTTPPort,crlf,reuseaddr,fork SYSTEM:"sleep 0.5; echo HTTP/1.1 200 OK'; echo ; echo $content; echo;" & + $_NC TCP-LISTEN:$Le_HTTPPort,crlf,reuseaddr,fork SYSTEM:"sleep 0.5; echo HTTP/1.1 200 OK'; echo ; echo $content; echo;" & serverproc="$!" } From 2fc0225bc98da5e0a7221c12ea13b20c9cf26ec2 Mon Sep 17 00:00:00 2001 From: Manuel Friedli Date: Tue, 12 Sep 2017 11:35:21 +0200 Subject: [PATCH 73/90] Make command line example consistent with env variable example. --- deploy/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/README.md b/deploy/README.md index f76c667a..af6fc5f3 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -108,6 +108,6 @@ $ export DEPLOY_FRITZBOX_URL=https://fritzbox.example.com After the first deployment, these values will be stored in your $HOME/.acme.sh/account.conf. You may now deploy the certificate like this: ```sh -acme.sh --deploy -d fritz.box --deploy-hook fritzbox +acme.sh --deploy -d fritzbox.example.com --deploy-hook fritzbox ``` From 270ce87582e8749b629033c2448bccf313aeb365 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 23 Sep 2017 22:12:17 +0800 Subject: [PATCH 74/90] add debug info --- acme.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/acme.sh b/acme.sh index e7746931..0f2a436d 100755 --- a/acme.sh +++ b/acme.sh @@ -2241,6 +2241,7 @@ _initpath() { fi fi + _debug2 ACME_DIRECTORY "$ACME_DIRECTORY" _ACME_SERVER_HOST="$(echo "$ACME_DIRECTORY" | cut -d : -f 2 | tr -s / | cut -d / -f 2)" _debug2 "_ACME_SERVER_HOST" "$_ACME_SERVER_HOST" From acf117584bb92c3c5e06774ef1c5b5fd7c4582cc Mon Sep 17 00:00:00 2001 From: Santeri Kannisto Date: Tue, 26 Sep 2017 07:04:30 +0400 Subject: [PATCH 75/90] #1042 Apparently UAPI does not return any error code, just JSON output that has a string "status: 0" whenever the command fails. --- deploy/cpanel_uapi.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/cpanel_uapi.sh b/deploy/cpanel_uapi.sh index 2ba112c4..4563b9c4 100644 --- a/deploy/cpanel_uapi.sh +++ b/deploy/cpanel_uapi.sh @@ -51,8 +51,8 @@ cpanel_uapi_deploy() { else _response=$(uapi SSL install_ssl domain="$_cdomain" cert="$_cert" key="$_key") fi - - if [ $? -ne 0 ]; then + error_response="status: 0" + if test "${_response#*$error_response}" != "$_response"; then _err "Error in deploying certificate:" _err "$_response" return 1 From 5261162fdfbc4cfe458267e822a9f89a4bea7f16 Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 26 Sep 2017 19:43:06 +0400 Subject: [PATCH 76/90] Remove stray single-quote Get rid of a single stray erroneous single-quote that is breaking socat when using standalone mode. --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 0f2a436d..3e63282d 100755 --- a/acme.sh +++ b/acme.sh @@ -1987,7 +1987,7 @@ _startserver() { _debug "_NC" "$_NC" #todo listen address - $_NC TCP-LISTEN:$Le_HTTPPort,crlf,reuseaddr,fork SYSTEM:"sleep 0.5; echo HTTP/1.1 200 OK'; echo ; echo $content; echo;" & + $_NC TCP-LISTEN:$Le_HTTPPort,crlf,reuseaddr,fork SYSTEM:"sleep 0.5; echo HTTP/1.1 200 OK; echo ; echo $content; echo;" & serverproc="$!" } From 754a4a7c8bef3fcaa384be159e1744cdae0399bc Mon Sep 17 00:00:00 2001 From: sahsanu Date: Sat, 30 Sep 2017 20:12:53 +0200 Subject: [PATCH 77/90] Update dns_cloudns.sh Added code to save CLOUDNS_AUTH_ID and CLOUDNS_AUTH_PASSWORD on account.conf file so the id and password for cloudns can be reused. --- dnsapi/dns_cloudns.sh | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_cloudns.sh b/dnsapi/dns_cloudns.sh index f48a8052..14403a7d 100755 --- a/dnsapi/dns_cloudns.sh +++ b/dnsapi/dns_cloudns.sh @@ -96,6 +96,16 @@ _dns_cloudns_init_check() { return 0 fi + CLOUDNS_AUTH_ID="${CLOUDNS_AUTH_ID:-$(_readaccountconf_mutable CLOUDNS_AUTH_ID)}" + CLOUDNS_AUTH_PASSWORD="${CLOUDNS_AUTH_PASSWORD:-$(_readaccountconf_mutable CLOUDNS_AUTH_PASSWORD)}" + if [ -z "$CLOUDNS_AUTH_ID" ] || [ -z "$CLOUDNS_AUTH_PASSWORD" ]; then + CLOUDNS_AUTH_ID="" + CLOUDNS_AUTH_PASSWORD="" + _err "You don't specify cloudns api id and password yet." + _err "Please create you id and password and try again." + return 1 + fi + if [ -z "$CLOUDNS_AUTH_ID" ]; then _err "CLOUDNS_AUTH_ID is not configured" return 1 @@ -113,8 +123,12 @@ _dns_cloudns_init_check() { return 1 fi + #save the api id and password to the account conf file. + _saveaccountconf_mutable CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID" + _saveaccountconf_mutable CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD" + CLOUDNS_INIT_CHECK_COMPLETED=1 - + return 0 } From 6c7da215e7d364fb9d9af3274397c947269b966e Mon Sep 17 00:00:00 2001 From: sahsanu Date: Sun, 1 Oct 2017 10:06:38 +0200 Subject: [PATCH 78/90] Update dns_cloudns.sh --- dnsapi/dns_cloudns.sh | 272 ++++++++++++++++++++---------------------- 1 file changed, 129 insertions(+), 143 deletions(-) diff --git a/dnsapi/dns_cloudns.sh b/dnsapi/dns_cloudns.sh index 14403a7d..2ad77ca0 100755 --- a/dnsapi/dns_cloudns.sh +++ b/dnsapi/dns_cloudns.sh @@ -11,174 +11,160 @@ CLOUDNS_API="https://api.cloudns.net" #Usage: dns_cloudns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_cloudns_add() { - _info "Using cloudns" - - if ! _dns_cloudns_init_check; then - return 1 - fi - - zone="$(_dns_cloudns_get_zone_name "$1")" - if [ -z "$zone" ]; then - _err "Missing DNS zone at ClouDNS. Please log into your control panel and create the required DNS zone for the initial setup." - return 1 - fi - - host="$(echo "$1" | sed "s/\.$zone\$//")" - record=$2 - record_id=$(_dns_cloudns_get_record_id "$zone" "$host") - - _debug zone "$zone" - _debug host "$host" - _debug record "$record" - _debug record_id "$record_id" - - if [ -z "$record_id" ]; then - _info "Adding the TXT record for $1" - _dns_cloudns_http_api_call "dns/add-record.json" "domain-name=$zone&record-type=TXT&host=$host&record=$record&ttl=60" - if ! _contains "$response" "\"status\":\"Success\""; then - _err "Record cannot be added." - return 1 - fi - _info "Added." - else - _info "Updating the TXT record for $1" - _dns_cloudns_http_api_call "dns/mod-record.json" "domain-name=$zone&record-id=$record_id&record-type=TXT&host=$host&record=$record&ttl=60" - if ! _contains "$response" "\"status\":\"Success\""; then - _err "The TXT record for $1 cannot be updated." - return 1 - fi - _info "Updated." - fi - - return 0 + _info "Using cloudns" + + if ! _dns_cloudns_init_check; then + return 1 + fi + + zone="$(_dns_cloudns_get_zone_name "$1")" + if [ -z "$zone" ]; then + _err "Missing DNS zone at ClouDNS. Please log into your control panel and create the required DNS zone for the initial setup." + return 1 + fi + + host="$(echo "$1" | sed "s/\.$zone\$//")" + record=$2 + record_id=$(_dns_cloudns_get_record_id "$zone" "$host") + + _debug zone "$zone" + _debug host "$host" + _debug record "$record" + _debug record_id "$record_id" + + if [ -z "$record_id" ]; then + _info "Adding the TXT record for $1" + _dns_cloudns_http_api_call "dns/add-record.json" "domain-name=$zone&record-type=TXT&host=$host&record=$record&ttl=60" + if ! _contains "$response" "\"status\":\"Success\""; then + _err "Record cannot be added." + return 1 + fi + _info "Added." + else + _info "Updating the TXT record for $1" + _dns_cloudns_http_api_call "dns/mod-record.json" "domain-name=$zone&record-id=$record_id&record-type=TXT&host=$host&record=$record&ttl=60" + if ! _contains "$response" "\"status\":\"Success\""; then + _err "The TXT record for $1 cannot be updated." + return 1 + fi + _info "Updated." + fi + + return 0 } #Usage: dns_cloudns_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_cloudns_rm() { - _info "Using cloudns" - - if ! _dns_cloudns_init_check; then - return 1 - fi - - if [ -z "$zone" ]; then - zone="$(_dns_cloudns_get_zone_name "$1")" - if [ -z "$zone" ]; then - _err "Missing DNS zone at ClouDNS. Please log into your control panel and create the required DNS zone for the initial setup." - return 1 - fi - fi - - host="$(echo "$1" | sed "s/\.$zone\$//")" - record=$2 - record_id=$(_dns_cloudns_get_record_id "$zone" "$host") - - _debug zone "$zone" - _debug host "$host" - _debug record "$record" - _debug record_id "$record_id" - - if [ ! -z "$record_id" ]; then - _info "Deleting the TXT record for $1" - _dns_cloudns_http_api_call "dns/delete-record.json" "domain-name=$zone&record-id=$record_id" - if ! _contains "$response" "\"status\":\"Success\""; then - _err "The TXT record for $1 cannot be deleted." - return 1 - fi - _info "Deleted." - fi - return 0 + _info "Using cloudns" + + if ! _dns_cloudns_init_check; then + return 1 + fi + + if [ -z "$zone" ]; then + zone="$(_dns_cloudns_get_zone_name "$1")" + if [ -z "$zone" ]; then + _err "Missing DNS zone at ClouDNS. Please log into your control panel and create the required DNS zone for the initial setup." + return 1 + fi + fi + + host="$(echo "$1" | sed "s/\.$zone\$//")" + record=$2 + record_id=$(_dns_cloudns_get_record_id "$zone" "$host") + + _debug zone "$zone" + _debug host "$host" + _debug record "$record" + _debug record_id "$record_id" + + if [ ! -z "$record_id" ]; then + _info "Deleting the TXT record for $1" + _dns_cloudns_http_api_call "dns/delete-record.json" "domain-name=$zone&record-id=$record_id" + if ! _contains "$response" "\"status\":\"Success\""; then + _err "The TXT record for $1 cannot be deleted." + return 1 + fi + _info "Deleted." + fi + return 0 } #################### Private functions below ################################## _dns_cloudns_init_check() { - if [ ! -z "$CLOUDNS_INIT_CHECK_COMPLETED" ]; then - return 0 - fi - - CLOUDNS_AUTH_ID="${CLOUDNS_AUTH_ID:-$(_readaccountconf_mutable CLOUDNS_AUTH_ID)}" - CLOUDNS_AUTH_PASSWORD="${CLOUDNS_AUTH_PASSWORD:-$(_readaccountconf_mutable CLOUDNS_AUTH_PASSWORD)}" - if [ -z "$CLOUDNS_AUTH_ID" ] || [ -z "$CLOUDNS_AUTH_PASSWORD" ]; then - CLOUDNS_AUTH_ID="" - CLOUDNS_AUTH_PASSWORD="" - _err "You don't specify cloudns api id and password yet." - _err "Please create you id and password and try again." - return 1 - fi - - if [ -z "$CLOUDNS_AUTH_ID" ]; then - _err "CLOUDNS_AUTH_ID is not configured" - return 1 - fi - - if [ -z "$CLOUDNS_AUTH_PASSWORD" ]; then - _err "CLOUDNS_AUTH_PASSWORD is not configured" - return 1 - fi - - _dns_cloudns_http_api_call "dns/login.json" "" - - if ! _contains "$response" "\"status\":\"Success\""; then - _err "Invalid CLOUDNS_AUTH_ID or CLOUDNS_AUTH_PASSWORD. Please check your login credentials." - return 1 - fi - - #save the api id and password to the account conf file. - _saveaccountconf_mutable CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID" - _saveaccountconf_mutable CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD" - - CLOUDNS_INIT_CHECK_COMPLETED=1 - - return 0 + if [ ! -z "$CLOUDNS_INIT_CHECK_COMPLETED" ]; then + return 0 + fi + + if [ -z "$CLOUDNS_AUTH_ID" ]; then + _err "CLOUDNS_AUTH_ID is not configured" + return 1 + fi + + if [ -z "$CLOUDNS_AUTH_PASSWORD" ]; then + _err "CLOUDNS_AUTH_PASSWORD is not configured" + return 1 + fi + + _dns_cloudns_http_api_call "dns/login.json" "" + + if ! _contains "$response" "\"status\":\"Success\""; then + _err "Invalid CLOUDNS_AUTH_ID or CLOUDNS_AUTH_PASSWORD. Please check your login credentials." + return 1 + fi + + CLOUDNS_INIT_CHECK_COMPLETED=1 + + return 0 } _dns_cloudns_get_zone_name() { - i=2 - while true; do - zoneForCheck=$(printf "%s" "$1" | cut -d . -f $i-100) + i=2 + while true; do + zoneForCheck=$(printf "%s" "$1" | cut -d . -f $i-100) - if [ -z "$zoneForCheck" ]; then - return 1 - fi + if [ -z "$zoneForCheck" ]; then + return 1 + fi - _debug zoneForCheck "$zoneForCheck" + _debug zoneForCheck "$zoneForCheck" - _dns_cloudns_http_api_call "dns/get-zone-info.json" "domain-name=$zoneForCheck" + _dns_cloudns_http_api_call "dns/get-zone-info.json" "domain-name=$zoneForCheck" - if ! _contains "$response" "\"status\":\"Failed\""; then - echo "$zoneForCheck" - return 0 - fi + if ! _contains "$response" "\"status\":\"Failed\""; then + echo "$zoneForCheck" + return 0 + fi - i=$(_math "$i" + 1) - done - return 1 + i=$(_math "$i" + 1) + done + return 1 } _dns_cloudns_get_record_id() { - _dns_cloudns_http_api_call "dns/records.json" "domain-name=$1&host=$2&type=TXT" - if _contains "$response" "\"id\":"; then - echo "$response" | cut -d '"' -f 2 - return 0 - fi - return 1 + _dns_cloudns_http_api_call "dns/records.json" "domain-name=$1&host=$2&type=TXT" + if _contains "$response" "\"id\":"; then + echo "$response" | cut -d '"' -f 2 + return 0 + fi + return 1 } _dns_cloudns_http_api_call() { - method=$1 + method=$1 - _debug CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID" - _debug CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD" + _debug CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID" + _debug CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD" - if [ -z "$2" ]; then - data="auth-id=$CLOUDNS_AUTH_ID&auth-password=$CLOUDNS_AUTH_PASSWORD" - else - data="auth-id=$CLOUDNS_AUTH_ID&auth-password=$CLOUDNS_AUTH_PASSWORD&$2" - fi + if [ -z "$2" ]; then + data="auth-id=$CLOUDNS_AUTH_ID&auth-password=$CLOUDNS_AUTH_PASSWORD" + else + data="auth-id=$CLOUDNS_AUTH_ID&auth-password=$CLOUDNS_AUTH_PASSWORD&$2" + fi - response="$(_get "$CLOUDNS_API/$method?$data")" + response="$(_get "$CLOUDNS_API/$method?$data")" - _debug2 response "$response" + _debug2 response "$response" - return 0 + return 0 } From c73c33f94c4d5731ef1d9bee92a33ab71dea1f92 Mon Sep 17 00:00:00 2001 From: sahsanu Date: Sun, 1 Oct 2017 10:31:38 +0200 Subject: [PATCH 79/90] Update dns_cloudns.sh --- dnsapi/dns_cloudns.sh | 272 ++++++++++++++++++++++-------------------- 1 file changed, 143 insertions(+), 129 deletions(-) diff --git a/dnsapi/dns_cloudns.sh b/dnsapi/dns_cloudns.sh index 2ad77ca0..b1861b24 100755 --- a/dnsapi/dns_cloudns.sh +++ b/dnsapi/dns_cloudns.sh @@ -11,160 +11,174 @@ CLOUDNS_API="https://api.cloudns.net" #Usage: dns_cloudns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_cloudns_add() { - _info "Using cloudns" - - if ! _dns_cloudns_init_check; then - return 1 - fi - - zone="$(_dns_cloudns_get_zone_name "$1")" - if [ -z "$zone" ]; then - _err "Missing DNS zone at ClouDNS. Please log into your control panel and create the required DNS zone for the initial setup." - return 1 - fi - - host="$(echo "$1" | sed "s/\.$zone\$//")" - record=$2 - record_id=$(_dns_cloudns_get_record_id "$zone" "$host") - - _debug zone "$zone" - _debug host "$host" - _debug record "$record" - _debug record_id "$record_id" - - if [ -z "$record_id" ]; then - _info "Adding the TXT record for $1" - _dns_cloudns_http_api_call "dns/add-record.json" "domain-name=$zone&record-type=TXT&host=$host&record=$record&ttl=60" - if ! _contains "$response" "\"status\":\"Success\""; then - _err "Record cannot be added." - return 1 - fi - _info "Added." - else - _info "Updating the TXT record for $1" - _dns_cloudns_http_api_call "dns/mod-record.json" "domain-name=$zone&record-id=$record_id&record-type=TXT&host=$host&record=$record&ttl=60" - if ! _contains "$response" "\"status\":\"Success\""; then - _err "The TXT record for $1 cannot be updated." - return 1 - fi - _info "Updated." - fi - - return 0 + _info "Using cloudns" + + if ! _dns_cloudns_init_check; then + return 1 + fi + + zone="$(_dns_cloudns_get_zone_name "$1")" + if [ -z "$zone" ]; then + _err "Missing DNS zone at ClouDNS. Please log into your control panel and create the required DNS zone for the initial setup." + return 1 + fi + + host="$(echo "$1" | sed "s/\.$zone\$//")" + record=$2 + record_id=$(_dns_cloudns_get_record_id "$zone" "$host") + + _debug zone "$zone" + _debug host "$host" + _debug record "$record" + _debug record_id "$record_id" + + if [ -z "$record_id" ]; then + _info "Adding the TXT record for $1" + _dns_cloudns_http_api_call "dns/add-record.json" "domain-name=$zone&record-type=TXT&host=$host&record=$record&ttl=60" + if ! _contains "$response" "\"status\":\"Success\""; then + _err "Record cannot be added." + return 1 + fi + _info "Added." + else + _info "Updating the TXT record for $1" + _dns_cloudns_http_api_call "dns/mod-record.json" "domain-name=$zone&record-id=$record_id&record-type=TXT&host=$host&record=$record&ttl=60" + if ! _contains "$response" "\"status\":\"Success\""; then + _err "The TXT record for $1 cannot be updated." + return 1 + fi + _info "Updated." + fi + + return 0 } #Usage: dns_cloudns_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_cloudns_rm() { - _info "Using cloudns" - - if ! _dns_cloudns_init_check; then - return 1 - fi - - if [ -z "$zone" ]; then - zone="$(_dns_cloudns_get_zone_name "$1")" - if [ -z "$zone" ]; then - _err "Missing DNS zone at ClouDNS. Please log into your control panel and create the required DNS zone for the initial setup." - return 1 - fi - fi - - host="$(echo "$1" | sed "s/\.$zone\$//")" - record=$2 - record_id=$(_dns_cloudns_get_record_id "$zone" "$host") - - _debug zone "$zone" - _debug host "$host" - _debug record "$record" - _debug record_id "$record_id" - - if [ ! -z "$record_id" ]; then - _info "Deleting the TXT record for $1" - _dns_cloudns_http_api_call "dns/delete-record.json" "domain-name=$zone&record-id=$record_id" - if ! _contains "$response" "\"status\":\"Success\""; then - _err "The TXT record for $1 cannot be deleted." - return 1 - fi - _info "Deleted." - fi - return 0 + _info "Using cloudns" + + if ! _dns_cloudns_init_check; then + return 1 + fi + + if [ -z "$zone" ]; then + zone="$(_dns_cloudns_get_zone_name "$1")" + if [ -z "$zone" ]; then + _err "Missing DNS zone at ClouDNS. Please log into your control panel and create the required DNS zone for the initial setup." + return 1 + fi + fi + + host="$(echo "$1" | sed "s/\.$zone\$//")" + record=$2 + record_id=$(_dns_cloudns_get_record_id "$zone" "$host") + + _debug zone "$zone" + _debug host "$host" + _debug record "$record" + _debug record_id "$record_id" + + if [ ! -z "$record_id" ]; then + _info "Deleting the TXT record for $1" + _dns_cloudns_http_api_call "dns/delete-record.json" "domain-name=$zone&record-id=$record_id" + if ! _contains "$response" "\"status\":\"Success\""; then + _err "The TXT record for $1 cannot be deleted." + return 1 + fi + _info "Deleted." + fi + return 0 } #################### Private functions below ################################## _dns_cloudns_init_check() { - if [ ! -z "$CLOUDNS_INIT_CHECK_COMPLETED" ]; then - return 0 - fi - - if [ -z "$CLOUDNS_AUTH_ID" ]; then - _err "CLOUDNS_AUTH_ID is not configured" - return 1 - fi - - if [ -z "$CLOUDNS_AUTH_PASSWORD" ]; then - _err "CLOUDNS_AUTH_PASSWORD is not configured" - return 1 - fi - - _dns_cloudns_http_api_call "dns/login.json" "" - - if ! _contains "$response" "\"status\":\"Success\""; then - _err "Invalid CLOUDNS_AUTH_ID or CLOUDNS_AUTH_PASSWORD. Please check your login credentials." - return 1 - fi - - CLOUDNS_INIT_CHECK_COMPLETED=1 - - return 0 + if [ ! -z "$CLOUDNS_INIT_CHECK_COMPLETED" ]; then + return 0 + fi + + CLOUDNS_AUTH_ID="${CLOUDNS_AUTH_ID:-$(_readaccountconf_mutable CLOUDNS_AUTH_ID)}" + CLOUDNS_AUTH_PASSWORD="${CLOUDNS_AUTH_PASSWORD:-$(_readaccountconf_mutable CLOUDNS_AUTH_PASSWORD)}" + if [ -z "$CLOUDNS_AUTH_ID" ] || [ -z "$CLOUDNS_AUTH_PASSWORD" ]; then + CLOUDNS_AUTH_ID="" + CLOUDNS_AUTH_PASSWORD="" + _err "You don't specify cloudns api id and password yet." + _err "Please create you id and password and try again." + return 1 + fi + + if [ -z "$CLOUDNS_AUTH_ID" ]; then + _err "CLOUDNS_AUTH_ID is not configured" + return 1 + fi + + if [ -z "$CLOUDNS_AUTH_PASSWORD" ]; then + _err "CLOUDNS_AUTH_PASSWORD is not configured" + return 1 + fi + + _dns_cloudns_http_api_call "dns/login.json" "" + + if ! _contains "$response" "\"status\":\"Success\""; then + _err "Invalid CLOUDNS_AUTH_ID or CLOUDNS_AUTH_PASSWORD. Please check your login credentials." + return 1 + fi + + #save the api id and password to the account conf file. + _saveaccountconf_mutable CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID" + _saveaccountconf_mutable CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD" + + CLOUDNS_INIT_CHECK_COMPLETED=1 + + return 0 } _dns_cloudns_get_zone_name() { - i=2 - while true; do - zoneForCheck=$(printf "%s" "$1" | cut -d . -f $i-100) + i=2 + while true; do + zoneForCheck=$(printf "%s" "$1" | cut -d . -f $i-100) - if [ -z "$zoneForCheck" ]; then - return 1 - fi + if [ -z "$zoneForCheck" ]; then + return 1 + fi - _debug zoneForCheck "$zoneForCheck" + _debug zoneForCheck "$zoneForCheck" - _dns_cloudns_http_api_call "dns/get-zone-info.json" "domain-name=$zoneForCheck" + _dns_cloudns_http_api_call "dns/get-zone-info.json" "domain-name=$zoneForCheck" - if ! _contains "$response" "\"status\":\"Failed\""; then - echo "$zoneForCheck" - return 0 - fi + if ! _contains "$response" "\"status\":\"Failed\""; then + echo "$zoneForCheck" + return 0 + fi - i=$(_math "$i" + 1) - done - return 1 + i=$(_math "$i" + 1) + done + return 1 } _dns_cloudns_get_record_id() { - _dns_cloudns_http_api_call "dns/records.json" "domain-name=$1&host=$2&type=TXT" - if _contains "$response" "\"id\":"; then - echo "$response" | cut -d '"' -f 2 - return 0 - fi - return 1 + _dns_cloudns_http_api_call "dns/records.json" "domain-name=$1&host=$2&type=TXT" + if _contains "$response" "\"id\":"; then + echo "$response" | cut -d '"' -f 2 + return 0 + fi + return 1 } _dns_cloudns_http_api_call() { - method=$1 + method=$1 - _debug CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID" - _debug CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD" + _debug CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID" + _debug CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD" - if [ -z "$2" ]; then - data="auth-id=$CLOUDNS_AUTH_ID&auth-password=$CLOUDNS_AUTH_PASSWORD" - else - data="auth-id=$CLOUDNS_AUTH_ID&auth-password=$CLOUDNS_AUTH_PASSWORD&$2" - fi + if [ -z "$2" ]; then + data="auth-id=$CLOUDNS_AUTH_ID&auth-password=$CLOUDNS_AUTH_PASSWORD" + else + data="auth-id=$CLOUDNS_AUTH_ID&auth-password=$CLOUDNS_AUTH_PASSWORD&$2" + fi - response="$(_get "$CLOUDNS_API/$method?$data")" + response="$(_get "$CLOUDNS_API/$method?$data")" - _debug2 response "$response" + _debug2 response "$response" - return 0 + return 0 } From 641a2895a6282472fe3c8d52e5289165bf8a3d7d Mon Sep 17 00:00:00 2001 From: hiska Date: Mon, 2 Oct 2017 08:32:36 +0900 Subject: [PATCH 80/90] Create strongswan.sh --- deploy/strongswan.sh | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 deploy/strongswan.sh diff --git a/deploy/strongswan.sh b/deploy/strongswan.sh new file mode 100644 index 00000000..73232785 --- /dev/null +++ b/deploy/strongswan.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env sh + +#Here is a sample custom api script. +#This file name is "myapi.sh" +#So, here must be a method myapi_deploy() +#Which will be called by acme.sh to deploy the cert +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +strongswan_deploy() { + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + + cat "$_ckey" >"/etc/ipsec.d/private/$(basename "$_ckey")" + cat "$_ccert" >"/etc/ipsec.d/certs/$(basename "$_ccert")" + cat "$_cca" >"/etc/ipsec.d/cacerts/$(basename "$_cca")" + cat "$_cfullchain" >"/etc/ipsec.d/cacerts/$(basename "$_cfullchain")" + + ipsec reload + + return 0 + +} From afe3283c53930c66017aadbb8e35d5f01b3c714e Mon Sep 17 00:00:00 2001 From: hiska Date: Mon, 2 Oct 2017 08:34:32 +0900 Subject: [PATCH 81/90] Update README.md --- deploy/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/deploy/README.md b/deploy/README.md index c80a567e..31053579 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -97,6 +97,10 @@ acme.sh --deploy -d example.com --deploy-hook cpanel_uapi Please note, that the cpanel_uapi hook will deploy only the first domain when your certificate will automatically renew. Therefore you should issue a separete certificate for each domain. +## 8. Deploy the cert to strongswan +```sh +acme.sh --deploy -d ftp.example.com --deploy-hook strongswan +``` From 372f691fd69a191cb2d718ace2d6f6a16568514e Mon Sep 17 00:00:00 2001 From: hebbet Date: Mon, 2 Oct 2017 15:04:02 +0200 Subject: [PATCH 82/90] unify headlines unify headlines in deploy readme --- deploy/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/deploy/README.md b/deploy/README.md index af6fc5f3..4e4a7261 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -4,7 +4,7 @@ Before you can deploy your cert, you must [issue the cert first](https://github. Here are the scripts to deploy the certs/key to the server/services. -## 1. Deploy the certs to your cpanel host. +## 1. Deploy the certs to your cpanel host If you want to deploy using cpanel UAPI see 7. @@ -20,7 +20,7 @@ export DEPLOY_CPANEL_PASSWORD=PASSWORD acme.sh --deploy -d example.com --deploy-hook cpanel ``` -## 2. Deploy ssl cert on kong proxy engine based on api. +## 2. Deploy ssl cert on kong proxy engine based on api Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert). Currently supports Kong-v0.10.x. @@ -29,11 +29,11 @@ Currently supports Kong-v0.10.x. acme.sh --deploy -d ftp.example.com --deploy-hook kong ``` -## 3. Deploy the cert to remote server through SSH access. +## 3. Deploy the cert to remote server through SSH access (TODO) -## 4. Deploy the cert to local vsftpd server. +## 4. Deploy the cert to local vsftpd server ```sh acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd @@ -55,7 +55,7 @@ export DEPLOY_VSFTPD_RELOAD="/etc/init.d/vsftpd restart" acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd ``` -## 5. Deploy the cert to local exim4 server. +## 5. Deploy the cert to local exim4 server ```sh acme.sh --deploy -d ftp.example.com --deploy-hook exim4 From c924e7c537249a33713e8dc6691ae3311e0b7a23 Mon Sep 17 00:00:00 2001 From: hiska Date: Wed, 4 Oct 2017 06:44:02 +0900 Subject: [PATCH 83/90] remove "return 0" --- deploy/strongswan.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/deploy/strongswan.sh b/deploy/strongswan.sh index 73232785..2de18f88 100644 --- a/deploy/strongswan.sh +++ b/deploy/strongswan.sh @@ -29,6 +29,4 @@ strongswan_deploy() { ipsec reload - return 0 - } From ee56b9cd4e50da0ff36af392676074d3914f12d7 Mon Sep 17 00:00:00 2001 From: sahsanu Date: Sat, 7 Oct 2017 21:31:24 +0200 Subject: [PATCH 84/90] Update ClouDNS.net API doc Update ClouDNS.net API doc to show that CLOUDNS_AUTH_ID and CLOUDNS_AUTH_PASSWORD will be saved in ~/.acme.sh/account.conf --- dnsapi/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/dnsapi/README.md b/dnsapi/README.md index 34b38678..ce8bbfb9 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -420,6 +420,7 @@ Ok, let's issue a cert now: ``` acme.sh --issue --dns dns_cloudns -d example.com -d www.example.com ``` +The `CLOUDNS_AUTH_ID` and `CLOUDNS_AUTH_PASSWORD` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. ## 22. Use Infoblox API From 5f6e3da766ef6ffcefca8d5ced3df4b2fcdd7a62 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 8 Oct 2017 19:45:50 +0800 Subject: [PATCH 85/90] fix https://github.com/Neilpang/acme.sh/issues/1062 change back to use openssl for tls mode. --- acme.sh | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index 3e63282d..9b917f7b 100755 --- a/acme.sh +++ b/acme.sh @@ -2054,7 +2054,12 @@ _starttlsserver() { return 1 fi - __S_OPENSSL="socat" + __S_OPENSSL="${ACME_OPENSSL_BIN:-openssl} s_server -www -cert $TLS_CERT -key $TLS_KEY " + if [ "$opaddr" ]; then + __S_OPENSSL="$__S_OPENSSL -accept $opaddr:$port" + else + __S_OPENSSL="$__S_OPENSSL -accept $port" + fi _debug Le_Listen_V4 "$Le_Listen_V4" _debug Le_Listen_V6 "$Le_Listen_V6" @@ -2065,9 +2070,12 @@ _starttlsserver() { fi _debug "$__S_OPENSSL" + if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then + $__S_OPENSSL -tlsextdebug & + else + $__S_OPENSSL >/dev/null 2>&1 & + fi - #todo listen address - $__S_OPENSSL openssl-listen:$port,cert=$TLS_CERT,key=$TLS_KEY,verify=0,reuseaddr,fork SYSTEM:"sleep 0.5; echo HTTP/1.1 200 OK'; echo ; echo $content; echo;" & serverproc="$!" sleep 1 _debug serverproc "$serverproc" From 872bfe4757a9593e1a3a6f8e9969ad465ef66beb Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 11 Oct 2017 20:34:56 +0800 Subject: [PATCH 86/90] fix for PR https://github.com/Neilpang/acme.sh/pull/1069 --- dnsapi/dns_aws.sh | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/dnsapi/dns_aws.sh b/dnsapi/dns_aws.sh index 40782573..5a716514 100755 --- a/dnsapi/dns_aws.sh +++ b/dnsapi/dns_aws.sh @@ -87,6 +87,7 @@ _get_root() { _debug "response" "$response" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug2 "Checking domain: $h" if [ -z "$h" ]; then if _contains "$response" "true" && _contains "$response" ""; then _debug "IsTruncated" @@ -102,23 +103,23 @@ _get_root() { fi fi #not valid + _err "Invalid domain" return 1 fi if _contains "$response" "$h."; then hostedzone="$(echo "$response" | sed 's//#&/g' | tr '#' '\n' | _egrep_o "[^<]*<.Id>$h.<.Name>.*false<.PrivateZone>.*<.HostedZone>")" _debug hostedzone "$hostedzone" - if [ -z "$hostedzone" ]; then - _err "Error, can not get hostedzone." + if [ "$hostedzone" ]; then + _domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o ".*<.Id>" | head -n 1 | _egrep_o ">.*<" | tr -d "<>") + if [ "$_domain_id" ]; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain=$h + return 0 + fi + _err "Can not find domain id: $h" return 1 fi - _domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o ".*<.Id>" | head -n 1 | _egrep_o ">.*<" | tr -d "<>") - if [ "$_domain_id" ]; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) - _domain=$h - return 0 - fi - return 1 fi p=$i i=$(_math "$i" + 1) From 352dd907ac0d90ed5cecf4a9553a59d25ca4ac3d Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 18 Oct 2017 20:27:09 +0800 Subject: [PATCH 87/90] fix https://github.com/Neilpang/acme.sh/issues/1074 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 9b917f7b..d988eb06 100755 --- a/acme.sh +++ b/acme.sh @@ -3135,7 +3135,7 @@ _regAccount() { fi if [ "$code" = '202' ]; then _info "Update account tos info success." - + echo "$response" >"$ACCOUNT_JSON_PATH" CA_KEY_HASH="$(__calcAccountKeyHash)" _debug "Calc CA_KEY_HASH" "$CA_KEY_HASH" _savecaconf CA_KEY_HASH "$CA_KEY_HASH" From 7902d10a3aaeff25bd2225e5c2ffd1af1f8e834b Mon Sep 17 00:00:00 2001 From: max2711 <32955673+max2711@users.noreply.github.com> Date: Fri, 20 Oct 2017 14:22:20 +0200 Subject: [PATCH 88/90] remove unused crontab jobs --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index e85098e0..97626ba0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ ADD ./ /install_acme.sh/ RUN cd /install_acme.sh && ([ -f /install_acme.sh/acme.sh ] && /install_acme.sh/acme.sh --install || curl https://get.acme.sh | sh) && rm -rf /install_acme.sh/ -RUN ln -s /root/.acme.sh/acme.sh /usr/local/bin/acme.sh && crontab -l | sed 's#> /dev/null##' | crontab - +RUN ln -s /root/.acme.sh/acme.sh /usr/local/bin/acme.sh && crontab -l | grep acme.sh | sed 's#> /dev/null##' | crontab - RUN for verb in help \ version \ From 4c99c0127b849a8db29151a10b78acb66f78ebdd Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 1 Nov 2017 10:14:44 +0800 Subject: [PATCH 89/90] add dev guide --- dnsapi/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/dnsapi/README.md b/dnsapi/README.md index ce8bbfb9..cff59c79 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -618,6 +618,7 @@ acme.sh --issue --dns dns_myapi -d example.com -d www.example.com For more details, please check our sample script: [dns_myapi.sh](dns_myapi.sh) +See: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide # Use lexicon DNS API From 6e93ff8bcac9744ff451181b6feeb7269d2ce1a8 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 10 Nov 2017 23:01:29 +0800 Subject: [PATCH 90/90] fix https://github.com/Neilpang/acme.sh/issues/1106 --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index d988eb06..9c8d6d4e 100755 --- a/acme.sh +++ b/acme.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -VER=2.7.4 +VER=2.7.5 PROJECT_NAME="acme.sh" @@ -3474,7 +3474,7 @@ issue() { token="$(printf "%s\n" "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')" _debug token "$token" - uri="$(printf "%s\n" "$entry" | _egrep_o '"uri":"[^"]*' | cut -d : -f 2,3 | tr -d '"')" + uri="$(printf "%s\n" "$entry" | _egrep_o '"uri":"[^"]*' | cut -d '"' -f 4)" _debug uri "$uri" keyauthorization="$token.$thumbprint"