Browse Source

Merge branch 'master' of https://github.com/Neilpang/acme.sh into ssh-deploy

David Kerr 7 years ago
parent
commit
c809b33161
14 changed files with 414 additions and 177 deletions
  1. 2 1
      .travis.yml
  2. 2 2
      Dockerfile
  3. 78 103
      acme.sh
  4. 41 5
      deploy/README.md
  5. 0 29
      deploy/cpanel.sh
  6. 64 0
      deploy/cpanel_uapi.sh
  7. 108 0
      deploy/fritzbox.sh
  8. 32 0
      deploy/strongswan.sh
  9. 2 4
      dnsapi/README.md
  10. 10 9
      dnsapi/dns_aws.sh
  11. 14 0
      dnsapi/dns_cloudns.sh
  12. 58 21
      dnsapi/dns_duckdns.sh
  13. 1 1
      dnsapi/dns_gandi_livedns.sh
  14. 2 2
      dnsapi/dns_he.sh

+ 2 - 1
.travis.yml

@@ -18,7 +18,7 @@ addons:
 
 
 install:
 install:
   - if [ "$TRAVIS_OS_NAME" = 'osx' ]; then
   - if [ "$TRAVIS_OS_NAME" = 'osx' ]; then
-      brew update && brew install openssl;
+      brew update && brew install openssl socat;
       brew info openssl;
       brew info openssl;
       ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/;
       ln -s /usr/local/opt/openssl/lib/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/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/;
@@ -30,6 +30,7 @@ install:
       openssl version 2>&1 || true;
       openssl version 2>&1 || true;
       $ACME_OPENSSL_BIN version 2>&1 || true;
       $ACME_OPENSSL_BIN version 2>&1 || true;
       export PATH="$_old_path";
       export PATH="$_old_path";
+    else sudo apt-get install socat;
     fi
     fi
   
   
 script:
 script:

+ 2 - 2
Dockerfile

@@ -4,7 +4,7 @@ RUN apk update -f \
   && apk --no-cache add -f \
   && apk --no-cache add -f \
   openssl \
   openssl \
   curl \
   curl \
-  netcat-openbsd \
+  socat \
   && rm -rf /var/cache/apk/*
   && rm -rf /var/cache/apk/*
 
 
 ENV LE_CONFIG_HOME /acme.sh
 ENV LE_CONFIG_HOME /acme.sh
@@ -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 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 \ 
 RUN for verb in help \ 
   version \
   version \

+ 78 - 103
acme.sh

@@ -1,6 +1,6 @@
 #!/usr/bin/env sh
 #!/usr/bin/env sh
 
 
-VER=2.7.3
+VER=2.7.4
 
 
 PROJECT_NAME="acme.sh"
 PROJECT_NAME="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"
 _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=""
 __INTERACTIVE=""
 if [ -t 1 ]; then
 if [ -t 1 ]; then
   __INTERACTIVE="1"
   __INTERACTIVE="1"
@@ -160,11 +164,11 @@ _dlg_versions() {
     echo "nginx doesn't exists."
     echo "nginx doesn't exists."
   fi
   fi
 
 
-  echo "nc:"
-  if _exists "nc"; then
-    nc -h 2>&1
+  echo "socat:"
+  if _exists "socat"; then
+    socat -h 2>&1
   else
   else
-    _debug "nc doesn't exists."
+    _debug "socat doesn't exists."
   fi
   fi
 }
 }
 
 
@@ -1367,6 +1371,10 @@ _time2str() {
     echo "$_t_s_a"
     echo "$_t_s_a"
   fi
   fi
 
 
+  #Busybox
+  if echo "$1" | awk '{ print strftime("%c", $0); }' 2>/dev/null; then
+    return
+  fi
 }
 }
 
 
 _normalizeJson() {
 _normalizeJson() {
@@ -1806,7 +1814,13 @@ _send_signed_request() {
 
 
     _CACHED_NONCE="$(echo "$responseHeaders" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)"
     _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)"
+      _debug2 _body "$_body"
+    fi
+
+    if _contains "$_body" "JWS has invalid anti-replay nonce"; then
       _info "It seems the CA server is busy now, let's wait and retry."
       _info "It seems the CA server is busy now, let's wait and retry."
       _request_retry_times=$(_math "$_request_retry_times" + 1)
       _request_retry_times=$(_math "$_request_retry_times" + 1)
       _sleep 5
       _sleep 5
@@ -1959,68 +1973,22 @@ _startserver() {
   _debug "ncaddr" "$ncaddr"
   _debug "ncaddr" "$ncaddr"
 
 
   _debug "startserver: $$"
   _debug "startserver: $$"
-  nchelp="$(nc -h 2>&1)"
 
 
   _debug Le_HTTPPort "$Le_HTTPPort"
   _debug Le_HTTPPort "$Le_HTTPPort"
   _debug Le_Listen_V4 "$Le_Listen_V4"
   _debug Le_Listen_V4 "$Le_Listen_V4"
   _debug Le_Listen_V6 "$Le_Listen_V6"
   _debug Le_Listen_V6 "$Le_Listen_V6"
-  _NC="nc"
 
 
+  _NC="socat"
   if [ "$Le_Listen_V4" ]; then
   if [ "$Le_Listen_V4" ]; then
     _NC="$_NC -4"
     _NC="$_NC -4"
   elif [ "$Le_Listen_V6" ]; then
   elif [ "$Le_Listen_V6" ]; then
     _NC="$_NC -6"
     _NC="$_NC -6"
   fi
   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"
   _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
+  $_NC TCP-LISTEN:$Le_HTTPPort,crlf,reuseaddr,fork SYSTEM:"sleep 0.5; echo HTTP/1.1 200 OK; echo ; echo  $content; echo;" &
+  serverproc="$!"
 }
 }
 
 
 _stopserver() {
 _stopserver() {
@@ -2030,25 +1998,8 @@ _stopserver() {
     return
     return
   fi
   fi
 
 
-  _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
+  kill $pid
 
 
-  _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
 # sleep sec
@@ -2103,7 +2054,7 @@ _starttlsserver() {
     return 1
     return 1
   fi
   fi
 
 
-  __S_OPENSSL="${ACME_OPENSSL_BIN:-openssl} s_server -cert $TLS_CERT  -key $TLS_KEY "
+  __S_OPENSSL="${ACME_OPENSSL_BIN:-openssl} s_server -www -cert $TLS_CERT  -key $TLS_KEY "
   if [ "$opaddr" ]; then
   if [ "$opaddr" ]; then
     __S_OPENSSL="$__S_OPENSSL -accept $opaddr:$port"
     __S_OPENSSL="$__S_OPENSSL -accept $opaddr:$port"
   else
   else
@@ -2120,9 +2071,9 @@ _starttlsserver() {
 
 
   _debug "$__S_OPENSSL"
   _debug "$__S_OPENSSL"
   if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
   if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
-    (printf "%s\r\n\r\n%s" "HTTP/1.1 200 OK" "$content" | $__S_OPENSSL -tlsextdebug) &
+    $__S_OPENSSL -tlsextdebug &
   else
   else
-    (printf "%s\r\n\r\n%s" "HTTP/1.1 200 OK" "$content" | $__S_OPENSSL >/dev/null 2>&1) &
+    $__S_OPENSSL >/dev/null 2>&1 &
   fi
   fi
 
 
   serverproc="$!"
   serverproc="$!"
@@ -2298,6 +2249,7 @@ _initpath() {
     fi
     fi
   fi
   fi
 
 
+  _debug2 ACME_DIRECTORY "$ACME_DIRECTORY"
   _ACME_SERVER_HOST="$(echo "$ACME_DIRECTORY" | cut -d : -f 2 | tr -s / | cut -d / -f 2)"
   _ACME_SERVER_HOST="$(echo "$ACME_DIRECTORY" | cut -d : -f 2 | tr -s / | cut -d / -f 2)"
   _debug2 "_ACME_SERVER_HOST" "$_ACME_SERVER_HOST"
   _debug2 "_ACME_SERVER_HOST" "$_ACME_SERVER_HOST"
 
 
@@ -2935,8 +2887,8 @@ _on_before_issue() {
   fi
   fi
 
 
   if _hasfield "$_chk_web_roots" "$NO_VALUE"; then
   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
       return 1
     fi
     fi
   fi
   fi
@@ -3042,6 +2994,10 @@ _on_issue_err() {
     )
     )
   fi
   fi
 
 
+  if [ "$IS_RENEW" = "1" ] && _hasfield "$Le_Webroot" "dns"; then
+    _err "$_DNS_MANUAL_ERR"
+  fi
+
   if [ "$DEBUG" ] && [ "$DEBUG" -gt "0" ]; then
   if [ "$DEBUG" ] && [ "$DEBUG" -gt "0" ]; then
     _debug "$(_dlg_versions)"
     _debug "$(_dlg_versions)"
   fi
   fi
@@ -3074,6 +3030,10 @@ _on_issue_success() {
     fi
     fi
   fi
   fi
 
 
+  if _hasfield "$Le_Webroot" "dns"; then
+    _err "$_DNS_MANUAL_WARN"
+  fi
+
 }
 }
 
 
 updateaccount() {
 updateaccount() {
@@ -3175,7 +3135,7 @@ _regAccount() {
       fi
       fi
       if [ "$code" = '202' ]; then
       if [ "$code" = '202' ]; then
         _info "Update account tos info success."
         _info "Update account tos info success."
-
+        echo "$response" >"$ACCOUNT_JSON_PATH"
         CA_KEY_HASH="$(__calcAccountKeyHash)"
         CA_KEY_HASH="$(__calcAccountKeyHash)"
         _debug "Calc CA_KEY_HASH" "$CA_KEY_HASH"
         _debug "Calc CA_KEY_HASH" "$CA_KEY_HASH"
         _savecaconf CA_KEY_HASH "$CA_KEY_HASH"
         _savecaconf CA_KEY_HASH "$CA_KEY_HASH"
@@ -3649,13 +3609,12 @@ issue() {
         _info "Standalone mode server"
         _info "Standalone mode server"
         _ncaddr="$(_getfield "$_local_addr" "$_ncIndex")"
         _ncaddr="$(_getfield "$_local_addr" "$_ncIndex")"
         _ncIndex="$(_math $_ncIndex + 1)"
         _ncIndex="$(_math $_ncIndex + 1)"
-        _startserver "$keyauthorization" "$_ncaddr" &
+        _startserver "$keyauthorization" "$_ncaddr"
         if [ "$?" != "0" ]; then
         if [ "$?" != "0" ]; then
           _clearup
           _clearup
           _on_issue_err "$_post_hook" "$vlist"
           _on_issue_err "$_post_hook" "$vlist"
           return 1
           return 1
         fi
         fi
-        serverproc="$!"
         sleep 1
         sleep 1
         _debug serverproc "$serverproc"
         _debug serverproc "$serverproc"
       elif [ "$_currentRoot" = "$MODE_STATELESS" ]; then
       elif [ "$_currentRoot" = "$MODE_STATELESS" ]; then
@@ -3990,7 +3949,10 @@ issue() {
   Le_NextRenewTime=$(_math "$Le_NextRenewTime" - 86400)
   Le_NextRenewTime=$(_math "$Le_NextRenewTime" - 86400)
   _savedomainconf "Le_NextRenewTime" "$Le_NextRenewTime"
   _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
   if [ "$_real_cert$_real_key$_real_ca$_reload_cmd$_real_fullchain" ]; then
     _savedomainconf "Le_RealCertPath" "$_real_cert"
     _savedomainconf "Le_RealCertPath" "$_real_cert"
@@ -4417,15 +4379,19 @@ _installcert() {
 installcronjob() {
 installcronjob() {
   _c_home="$1"
   _c_home="$1"
   _initpath
   _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 "All your certs will not be renewed automatically."
     _err "You must add your own cron job to call '$PROJECT_ENTRY --cron' everyday."
     _err "You must add your own cron job to call '$PROJECT_ENTRY --cron' everyday."
     return 1
     return 1
   fi
   fi
 
 
   _info "Installing cron job"
   _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
     if [ -f "$LE_WORKING_DIR/$PROJECT_ENTRY" ]; then
       lesh="\"$LE_WORKING_DIR\"/$PROJECT_ENTRY"
       lesh="\"$LE_WORKING_DIR\"/$PROJECT_ENTRY"
     else
     else
@@ -4439,15 +4405,15 @@ installcronjob() {
     _t=$(_time)
     _t=$(_time)
     random_minute=$(_math $_t % 60)
     random_minute=$(_math $_t % 60)
     if _exists uname && uname -a | grep SunOS >/dev/null; then
     if _exists uname && uname -a | grep SunOS >/dev/null; then
-      crontab -l | {
+      $_CRONTAB -l | {
         cat
         cat
         echo "$random_minute 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" $_c_entry> /dev/null"
         echo "$random_minute 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" $_c_entry> /dev/null"
-      } | crontab --
+      } | $_CRONTAB --
     else
     else
-      crontab -l | {
+      $_CRONTAB -l | {
         cat
         cat
         echo "$random_minute 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" $_c_entry> /dev/null"
         echo "$random_minute 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" $_c_entry> /dev/null"
-      } | crontab -
+      } | $_CRONTAB -
     fi
     fi
   fi
   fi
   if [ "$?" != "0" ]; then
   if [ "$?" != "0" ]; then
@@ -4459,16 +4425,21 @@ installcronjob() {
 }
 }
 
 
 uninstallcronjob() {
 uninstallcronjob() {
-  if ! _exists "crontab"; then
+  _CRONTAB="crontab"
+  if ! _exists "$_CRONTAB" && _exists "fcrontab"; then
+    _CRONTAB="fcrontab"
+  fi
+
+  if ! _exists "$_CRONTAB"; then
     return
     return
   fi
   fi
   _info "Removing cron job"
   _info "Removing cron job"
-  cr="$(crontab -l | grep "$PROJECT_ENTRY --cron")"
+  cr="$($_CRONTAB -l | grep "$PROJECT_ENTRY --cron")"
   if [ "$cr" ]; then
   if [ "$cr" ]; then
     if _exists uname && uname -a | grep solaris >/dev/null; 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
     else
-      crontab -l | sed "/$PROJECT_ENTRY --cron/d" | crontab -
+      $_CRONTAB -l | sed "/$PROJECT_ENTRY --cron/d" | $_CRONTAB -
     fi
     fi
     LE_WORKING_DIR="$(echo "$cr" | cut -d ' ' -f 9 | tr -d '"')"
     LE_WORKING_DIR="$(echo "$cr" | cut -d ' ' -f 9 | tr -d '"')"
     _info LE_WORKING_DIR "$LE_WORKING_DIR"
     _info LE_WORKING_DIR "$LE_WORKING_DIR"
@@ -4745,7 +4716,7 @@ _precheck() {
   fi
   fi
 
 
   if [ -z "$_nocron" ]; then
   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 "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 "We need to set cron job to renew the certs automatically."
       _err "Otherwise, your certs will not be able to be renewed automatically."
       _err "Otherwise, your certs will not be able to be renewed automatically."
@@ -4763,9 +4734,9 @@ _precheck() {
     return 1
     return 1
   fi
   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."
     _err "If you don't use standalone mode, just ignore this warning."
   fi
   fi
 
 
@@ -4865,9 +4836,11 @@ install() {
     _debug "Skip install cron job"
     _debug "Skip install cron job"
   fi
   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
   fi
 
 
   if [ -z "$_c_home" ] && [ "$LE_CONFIG_HOME" != "$LE_WORKING_DIR" ]; then
   if [ -z "$_c_home" ] && [ "$LE_CONFIG_HOME" != "$LE_WORKING_DIR" ]; then
@@ -4920,7 +4893,9 @@ install() {
 
 
   _info "Installed to $LE_WORKING_DIR/$PROJECT_ENTRY"
   _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
   for subf in $_SUB_FOLDERS; do
     if [ -d "$subf" ]; then
     if [ -d "$subf" ]; then
@@ -5010,7 +4985,7 @@ _uninstallalias() {
 }
 }
 
 
 cron() {
 cron() {
-  IN_CRON=1
+  export IN_CRON=1
   _initpath
   _initpath
   _info "$(__green "===Starting cron===")"
   _info "$(__green "===Starting cron===")"
   if [ "$AUTO_UPGRADE" = "1" ]; then
   if [ "$AUTO_UPGRADE" = "1" ]; then

+ 41 - 5
deploy/README.md

@@ -4,7 +4,9 @@ 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.
 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.
 
 
 (cpanel deploy hook is not finished yet, this is just an example.)
 (cpanel deploy hook is not finished yet, this is just an example.)
 
 
@@ -18,7 +20,7 @@ export DEPLOY_CPANEL_PASSWORD=PASSWORD
 acme.sh --deploy -d example.com --deploy-hook cpanel
 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).
 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.
 Currently supports Kong-v0.10.x.
@@ -27,7 +29,7 @@ Currently supports Kong-v0.10.x.
 acme.sh --deploy -d ftp.example.com --deploy-hook kong
 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
 
 
 The ssh deploy plugin allows you to deploy certificates to a remote host
 The ssh deploy plugin allows you to deploy certificates to a remote host
 using SSH command to connect to the remote server.  The ssh plugin is invoked
 using SSH command to connect to the remote server.  The ssh plugin is invoked
@@ -170,7 +172,7 @@ export DEPLOY_SSH_BACKUP=no
 && service unifi restart
 && service unifi restart
 ```
 ```
 
 
-## 4. Deploy the cert to local vsftpd server.
+## 4. Deploy the cert to local vsftpd server
 
 
 ```sh
 ```sh
 acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd
 acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd
@@ -192,7 +194,7 @@ export DEPLOY_VSFTPD_RELOAD="/etc/init.d/vsftpd restart"
 acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd
 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
 ```sh
 acme.sh --deploy -d ftp.example.com --deploy-hook exim4
 acme.sh --deploy -d ftp.example.com --deploy-hook exim4
@@ -219,3 +221,37 @@ acme.sh --deploy -d ftp.example.com --deploy-hook exim4
 ```sh
 ```sh
 acme.sh --deploy -d ftp.example.com --deploy-hook keychain
 acme.sh --deploy -d ftp.example.com --deploy-hook keychain
 ```
 ```
+
+## 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
+```
+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
+```
+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 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 fritzbox.example.com --deploy-hook fritzbox
+```
+
+## 9. Deploy the cert to strongswan
+
+```sh
+acme.sh --deploy -d ftp.example.com --deploy-hook strongswan
+```

+ 0 - 29
deploy/cpanel.sh

@@ -1,29 +0,0 @@
-#!/usr/bin/env sh
-
-#Here is the script to deploy the cert to your cpanel account by the cpanel APIs.
-
-#returns 0 means success, otherwise error.
-
-#export DEPLOY_CPANEL_USER=myusername
-#export DEPLOY_CPANEL_PASSWORD=PASSWORD
-
-########  Public functions #####################
-
-#domain keyfile certfile cafile fullchain
-cpanel_deploy() {
-  _cdomain="$1"
-  _ckey="$2"
-  _ccert="$3"
-  _cca="$4"
-  _cfullchain="$5"
-
-  _debug _cdomain "$_cdomain"
-  _debug _ckey "$_ckey"
-  _debug _ccert "$_ccert"
-  _debug _cca "$_cca"
-  _debug _cfullchain "$_cfullchain"
-
-  _err "Not implemented yet"
-  return 1
-
-}

+ 64 - 0
deploy/cpanel_uapi.sh

@@ -0,0 +1,64 @@
+#!/usr/bin/env sh
+# Here is the script to deploy the cert to your cpanel using the cpanel API.
+# Uses command line uapi.  --user option is needed only if run as root.
+# Returns 0 when success.
+# Written by Santeri Kannisto <santeri.kannisto@2globalnomads.info>
+# Public domain, 2017
+
+#export DEPLOY_CPANEL_USER=myusername
+
+########  Public functions #####################
+
+#domain keyfile certfile cafile fullchain
+
+cpanel_uapi_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 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")
+  _cert=$(php -r "echo urlencode(\"$_certstr\");")
+  _key=$(php -r "echo urlencode(\"$_keystr\");")
+
+  _debug _cert "$_cert"
+  _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")
+  fi
+  error_response="status: 0"
+  if test "${_response#*$error_response}" != "$_response"; then
+    _err "Error in deploying certificate:"
+    _err "$_response"
+    return 1
+  fi
+
+  _debug response "$_response"
+  _info "Certificate successfully deployed"
+  return 0
+}

+ 108 - 0
deploy/fritzbox.sh

@@ -0,0 +1,108 @@
+#!/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"
+
+# Kudos to wikrie at Github for his FRITZ!Box update script:
+# https://gist.github.com/wikrie/f1d5747a714e0a34d0582981f7cb4cfb
+
+########  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 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_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."
+    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}"
+
+  # 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="$(_get "${_fritzbox_url}/login_sid.lua" | sed -e 's/^.*<Challenge>//' -e 's/<\/Challenge>.*$//')"
+  _fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')"
+  _fritzbox_sid="$(_get "${_fritzbox_url}/login_sid.lua?sid=0000000000000000&username=${_fritzbox_username}&response=${_fritzbox_challenge}-${_fritzbox_hash}" | sed -e 's/^.*<SID>//' -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."
+    return 1
+  fi
+
+  _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 -- "--"
+    printf -- "%s\r\n" "${_post_boundary}"
+    printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n%s\r\n" "${_fritzbox_sid}"
+    printf -- "--"
+    printf -- "%s\r\n" "${_post_boundary}"
+    printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n%s\r\n" "${_CERTPASSWORD_}"
+    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 -- "--"
+    printf -- "%s--" "${_post_boundary}"
+  } >>"${_post_request}"
+
+  _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
+
+  retval=$?
+  if [ $retval = 0 ]; then
+    _info "Upload successful"
+  else
+    _err "Upload failed"
+  fi
+  rm "${_post_request}"
+
+  return $retval
+}

+ 32 - 0
deploy/strongswan.sh

@@ -0,0 +1,32 @@
+#!/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
+
+}

+ 2 - 4
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
 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
 ## 22. Use Infoblox API
 
 
@@ -512,14 +513,11 @@ export DuckDNS_Token="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
 ```
 ```
 
 
 Please note that since DuckDNS uses StartSSL as their cert provider, thus 
 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
 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.
 For issues, please report to https://github.com/raidenii/acme.sh/issues.
 
 
 ## 28. Use Name.com API
 ## 28. Use Name.com API

+ 10 - 9
dnsapi/dns_aws.sh

@@ -87,6 +87,7 @@ _get_root() {
     _debug "response" "$response"
     _debug "response" "$response"
     while true; do
     while true; do
       h=$(printf "%s" "$domain" | cut -d . -f $i-100)
       h=$(printf "%s" "$domain" | cut -d . -f $i-100)
+      _debug2 "Checking domain: $h"
       if [ -z "$h" ]; then
       if [ -z "$h" ]; then
         if _contains "$response" "<IsTruncated>true</IsTruncated>" && _contains "$response" "<NextMarker>"; then
         if _contains "$response" "<IsTruncated>true</IsTruncated>" && _contains "$response" "<NextMarker>"; then
           _debug "IsTruncated"
           _debug "IsTruncated"
@@ -102,23 +103,23 @@ _get_root() {
           fi
           fi
         fi
         fi
         #not valid
         #not valid
+        _err "Invalid domain"
         return 1
         return 1
       fi
       fi
 
 
       if _contains "$response" "<Name>$h.</Name>"; then
       if _contains "$response" "<Name>$h.</Name>"; then
         hostedzone="$(echo "$response" | sed 's/<HostedZone>/#&/g' | tr '#' '\n' | _egrep_o "<HostedZone><Id>[^<]*<.Id><Name>$h.<.Name>.*<PrivateZone>false<.PrivateZone>.*<.HostedZone>")"
         hostedzone="$(echo "$response" | sed 's/<HostedZone>/#&/g' | tr '#' '\n' | _egrep_o "<HostedZone><Id>[^<]*<.Id><Name>$h.<.Name>.*<PrivateZone>false<.PrivateZone>.*<.HostedZone>")"
         _debug hostedzone "$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>.*<.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
           return 1
         fi
         fi
-        _domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "<Id>.*<.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
       fi
       p=$i
       p=$i
       i=$(_math "$i" + 1)
       i=$(_math "$i" + 1)

+ 14 - 0
dnsapi/dns_cloudns.sh

@@ -96,6 +96,16 @@ _dns_cloudns_init_check() {
     return 0
     return 0
   fi
   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
   if [ -z "$CLOUDNS_AUTH_ID" ]; then
     _err "CLOUDNS_AUTH_ID is not configured"
     _err "CLOUDNS_AUTH_ID is not configured"
     return 1
     return 1
@@ -113,6 +123,10 @@ _dns_cloudns_init_check() {
     return 1
     return 1
   fi
   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
   CLOUDNS_INIT_CHECK_COMPLETED=1
 
 
   return 0
   return 0

+ 58 - 21
dnsapi/dns_duckdns.sh

@@ -3,11 +3,14 @@
 #Created by RaidenII, to use DuckDNS's API to add/remove text records
 #Created by RaidenII, to use DuckDNS's API to add/remove text records
 #06/27/2017
 #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"
 DuckDNS_API="https://www.duckdns.org/update"
-API_Params="domains=$DuckDNS_Domain&token=$DuckDNS_Token"
 
 
 ########  Public functions #####################
 ########  Public functions #####################
 
 
@@ -16,35 +19,36 @@ dns_duckdns_add() {
   fulldomain=$1
   fulldomain=$1
   txtvalue=$2
   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
   if [ -z "$DuckDNS_Token" ]; then
-    DuckDNS_Token=""
+    _err "You must export variable: DuckDNS_Token"
     _err "The token for your DuckDNS account is necessary."
     _err "The token for your DuckDNS account is necessary."
     _err "You can look it up in your DuckDNS account."
     _err "You can look it up in your DuckDNS account."
     return 1
     return 1
   fi
   fi
 
 
   # Now save the credentials.
   # 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
   # Unfortunately, DuckDNS does not seems to support lookup domain through API
   # So I assume your credentials (which are your domain and token) are correct
   # 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 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
   # Now add the TXT record to DuckDNS
   _info "Trying to add TXT record"
   _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
   else
     _err "Errors happened during adding the TXT record."
     _err "Errors happened during adding the TXT record."
     return 1
     return 1
@@ -57,11 +61,28 @@ dns_duckdns_rm() {
   fulldomain=$1
   fulldomain=$1
   txtvalue=$2
   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
   # Now remove the TXT record from DuckDNS
   _info "Trying to remove TXT record"
   _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
   else
     _err "Errors happened during removing the TXT record."
     _err "Errors happened during removing the TXT record."
     return 1
     return 1
@@ -70,6 +91,22 @@ dns_duckdns_rm() {
 
 
 ####################  Private functions below ##################################
 ####################  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
 #Usage: method URI
 _duckdns_rest() {
 _duckdns_rest() {
   method=$1
   method=$1

+ 1 - 1
dnsapi/dns_gandi_livedns.sh

@@ -11,7 +11,7 @@
 #
 #
 ########  Public functions #####################
 ########  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"
 #Usage: dns_gandi_livedns_add   _acme-challenge.www.domain.com   "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
 dns_gandi_livedns_add() {
 dns_gandi_livedns_add() {

+ 2 - 2
dnsapi/dns_he.sh

@@ -47,7 +47,7 @@ dns_he_add() {
   response="$(_post "$body" "https://dns.he.net/")"
   response="$(_post "$body" "https://dns.he.net/")"
   exit_code="$?"
   exit_code="$?"
   if [ "$exit_code" -eq 0 ]; then
   if [ "$exit_code" -eq 0 ]; then
-    _info "TXT record added successfuly."
+    _info "TXT record added successfully."
   else
   else
     _err "Couldn't add the TXT record."
     _err "Couldn't add the TXT record."
   fi
   fi
@@ -96,7 +96,7 @@ dns_he_rm() {
       >/dev/null
       >/dev/null
   exit_code="$?"
   exit_code="$?"
   if [ "$exit_code" -eq 0 ]; then
   if [ "$exit_code" -eq 0 ]; then
-    _info "Record removed successfuly."
+    _info "Record removed successfully."
   else
   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."
     return "$exit_code"
     return "$exit_code"