Hello community,

here is the log from the commit of package dehydrated for openSUSE:Factory 
checked in at 2018-01-16 09:43:17
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/dehydrated (Old)
 and      /work/SRC/openSUSE:Factory/.dehydrated.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "dehydrated"

Tue Jan 16 09:43:17 2018 rev:6 rq:565804 version:0.5.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/dehydrated/dehydrated.changes    2017-10-29 
20:24:21.535360514 +0100
+++ /work/SRC/openSUSE:Factory/.dehydrated.new/dehydrated.changes       
2018-01-16 09:43:17.839086345 +0100
@@ -1,0 +2,38 @@
+Mon Jan 15 12:15:07 UTC 2018 - [email protected]
+
+- Remove redundant noarch entries. They cause an error in RPM 4.14.
+
+-------------------------------------------------------------------
+Mon Jan 15 11:29:11 UTC 2018 - [email protected]
+
+- Updated dehydrated to 0.5.0
+
+  This removes the following patches and files, which are now part of the
+  upstream package:
+  * 0001-Add-optional-user-and-group-configuration.patch
+  * 0002-use-nullglob-disable-warning-on-empty-CONFIG_D-direc.patch
+  * dehydrated.1: the man page has been adopted by upstream
+
+  Starting with this version, upstream introduced signed releases, which
+  is now being used for source validation.
+
+  Upstream changes:
+
+  Changed
+
+  * Certificate chain is now cached (CHAINCACHE)
+  * OpenSSL binary path is now configurable (OPENSSL)
+  * Cleanup now also moves revoked certificates
+
+  Added
+
+  * New feature for updating contact information (--account)
+  * Allow automatic cleanup on exit (AUTO_CLEANUP)
+  * Initial support for fetching OCSP status to be used for OCSP stapling
+    (OCSP_FETCH)
+  * Certificates can now have aliases to create multiple certificates with
+    identical set of domains (see --alias and domains.txt documentation)
+  * Allow dehydrated to run as specified user (/group). This was already
+    available previously as a patch to this package.
+
+-------------------------------------------------------------------

Old:
----
  0001-Add-optional-user-and-group-configuration.patch
  0002-use-nullglob-disable-warning-on-empty-CONFIG_D-direc.patch
  dehydrated-0.4.0.tar.gz
  dehydrated.1

New:
----
  dehydrated-0.5.0.tar.gz
  dehydrated-0.5.0.tar.gz.asc
  dehydrated.keyring

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ dehydrated.spec ++++++
--- /var/tmp/diff_new_pack.039Syd/_old  2018-01-16 09:43:18.735044407 +0100
+++ /var/tmp/diff_new_pack.039Syd/_new  2018-01-16 09:43:18.735044407 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package dehydrated
 #
-# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -46,7 +46,7 @@
 %endif
 
 Name:           dehydrated
-Version:        0.4.0
+Version:        0.5.0
 Release:        0
 Summary:        A client for signing certificates with an ACME server
 License:        MIT
@@ -60,14 +60,11 @@
 Source5:        dehydrated.tmpfiles.d
 Source6:        dehydrated.service.in
 Source7:        dehydrated.timer
-Source8:        dehydrated.1
 Source9:        README.SUSE
 Source10:       README.Fedora
 Source11:       README.hooks
-# Patch submitted to  upstream
-Patch1:         0001-Add-optional-user-and-group-configuration.patch
-# Patch from upstream
-Patch2:         0002-use-nullglob-disable-warning-on-empty-CONFIG_D-direc.patch
+Source12:       %{name}-%{version}.tar.gz.asc
+Source13:       %{name}.keyring
 BuildRequires:  %{_apache}
 Requires:       coreutils
 Requires:       curl
@@ -78,7 +75,6 @@
 Requires(pre):  %{_sbindir}/useradd
 Obsoletes:      letsencrypt.sh < %{version}
 Provides:       letsencrypt.sh = %{version}
-BuildArch:      noarch
 %if %{with lighttpd}
 BuildRequires:  lighttpd
 %endif
@@ -135,7 +131,6 @@
 %if ! 0%{?suse_version}
 Requires:       mod_ssl
 %endif
-BuildArch:      noarch
 
 %description %{_apache}
 This adds a configuration file for dehydrated's acme-challenge to Apache.
@@ -148,7 +143,6 @@
 Requires:       nginx
 Obsoletes:      letsencrypt.sh-nginx < %{version}
 Provides:       letsencrypt.sh-nginx = %{version}
-BuildArch:      noarch
 
 %description nginx
 This adds a configuration file for dehydrated's acme-challenge to nginx.
@@ -160,7 +154,6 @@
 Group:          Productivity/Networking/Security
 Requires:       %{name}
 Requires:       lighttpd
-BuildArch:      noarch
 
 %description lighttpd
 This adds a configuration file for dehydrated's acme-challenge to lighttpd.
@@ -189,8 +182,6 @@
 
 %prep
 %setup -q
-%patch1 -p1
-%patch2 -p1
 cp %{SOURCE9} .
 cp %{SOURCE10} .
 
@@ -198,13 +189,13 @@
 
 %install
 # sensitive keys
-mkdir -p %{buildroot}%{_home}/{accounts,certs}
+mkdir -p %{buildroot}%{_home}/{accounts,certs,chains}
 mkdir -p %{buildroot}%{_sbindir}
 mkdir -p %{buildroot}%{_mandir}/man1
 mkdir -p %{buildroot}%{_home}/config.d
 mkdir -p %{buildroot}%{_postrunhooks}
 
-cat %{SOURCE8} | gzip > %{buildroot}%{_mandir}/man1/dehydrated.1.gz
+cat dehydrated.1 | gzip > %{buildroot}%{_mandir}/man1/dehydrated.1.gz
 
 # Silence E: env-script-interpreter
 find \( -name \*.sh -o -name dehydrated \) -exec sed -i "s,#!/usr/bin/env 
bash,#!$(command -v bash),g" {} \;
@@ -262,6 +253,7 @@
 %attr(750,root,%{_user}) %dir %{_sysconfdir}/dehydrated
 %attr(700,%{_user},%{_user}) %dir %{_sysconfdir}/dehydrated/accounts
 %attr(700,%{_user},%{_user}) %dir %{_sysconfdir}/dehydrated/certs
+%attr(700,%{_user},%{_user}) %dir %{_sysconfdir}/dehydrated/chains
 %config(noreplace) %attr(640,root,%{_user}) %{_sysconfdir}/dehydrated/config
 %config(noreplace) %attr(750,root,%{_user}) %{_sysconfdir}/dehydrated/config.d
 %config(noreplace) %attr(640,root,%{_user}) 
%{_sysconfdir}/dehydrated/domains.txt

++++++ README.SUSE ++++++
--- /var/tmp/diff_new_pack.039Syd/_old  2018-01-16 09:43:18.783042160 +0100
+++ /var/tmp/diff_new_pack.039Syd/_new  2018-01-16 09:43:18.787041973 +0100
@@ -110,7 +110,7 @@
 Aqcuisition through DNS (dns-01)
 ================================
 
-Tnis is mostly useful under these conditions
+This is mostly useful under these conditions
 
 1. Your hosts are not directly exposed to the internet
 2. Your host names are part of a public DNS zone visible on the internet.

++++++ dehydrated-0.4.0.tar.gz -> dehydrated-0.5.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dehydrated-0.4.0/.gitignore 
new/dehydrated-0.5.0/.gitignore
--- old/dehydrated-0.4.0/.gitignore     2017-02-05 15:33:17.000000000 +0100
+++ new/dehydrated-0.5.0/.gitignore     2018-01-13 20:08:12.000000000 +0100
@@ -6,3 +6,4 @@
 certs/*
 archive/*
 accounts/*
+chains/*
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dehydrated-0.4.0/CHANGELOG 
new/dehydrated-0.5.0/CHANGELOG
--- old/dehydrated-0.4.0/CHANGELOG      2017-02-05 15:33:17.000000000 +0100
+++ new/dehydrated-0.5.0/CHANGELOG      2018-01-13 20:08:12.000000000 +0100
@@ -1,9 +1,18 @@
 # Change Log
 This file contains a log of major changes in dehydrated
 
-## [x.x.x] - xxxx-xx-xx
+## [0.5.0] - 2018-01-13
 ## Changed
-- ...
+- Certificate chain is now cached (CHAINCACHE)
+- OpenSSL binary path is now configurable (OPENSSL)
+- Cleanup now also moves revoked certificates
+
+## Added
+- New feature for updating contact information (--account)
+- Allow automatic cleanup on exit (AUTO_CLEANUP)
+- Initial support for fetching OCSP status to be used for OCSP stapling 
(OCSP_FETCH)
+- Certificates can now have aliases to create multiple certificates with 
identical set of domains (see --alias and domains.txt documentation)
+- Allow dehydrated to run as specified user (/group)
 
 ## [0.4.0] - 2017-02-05
 ## Changed
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dehydrated-0.4.0/README.md 
new/dehydrated-0.5.0/README.md
--- old/dehydrated-0.4.0/README.md      2017-02-05 15:33:17.000000000 +0100
+++ new/dehydrated-0.5.0/README.md      2018-01-13 20:08:12.000000000 +0100
@@ -1,4 +1,4 @@
-# dehydrated [![Build 
Status](https://travis-ci.org/lukas2511/dehydrated.svg?branch=master)](https://travis-ci.org/lukas2511/dehydrated)
+# dehydrated
 
 ![](docs/logo.jpg)
 
@@ -33,7 +33,7 @@
 - `/etc/dehydrated/config`
 - `/usr/local/etc/dehydrated/config`
 - The current working directory of your shell
-- The directory from which dehydrated was ran
+- The directory from which dehydrated was run
 
 Have a look at [docs/examples/config](docs/examples/config) to get started, 
copy it to e.g. `/etc/dehydrated/config`
 and edit it to fit your needs.
@@ -46,8 +46,10 @@
 Default command: help
 
 Commands:
+ --version (-v)                   Print version information
  --register                       Register account key
- --cron (-c)                      Sign/renew non-existant/changed/expiring 
certificates.
+ --account                        Update account contact information
+ --cron (-c)                      Sign/renew non-existent/changed/expiring 
certificates.
  --signcsr (-s) path/to/csr.pem   Sign a given CSR, output CRT on stdout 
(advanced usage)
  --revoke (-r) path/to/cert.pem   Revoke specified certificate
  --cleanup (-gc)                  Move unused certificate files to archive 
directory
@@ -60,6 +62,7 @@
  --ipv4 (-4)                      Resolve names to IPv4 addresses only
  --ipv6 (-6)                      Resolve names to IPv6 addresses only
  --domain (-d) domain.tld         Use specified domain name(s) instead of 
domains.txt entry (one certificate!)
+ --alias certalias                Use specified name for certificate directory 
(and per-certificate config) instead of the primary domain (only used if 
--domain is specified)
  --keep-going (-g)                Keep going after encountering an error while 
creating/renewing multiple certificates in cron mode
  --force (-x)                     Force renew of certificate even if it is 
longer valid than value in RENEW_DAYS
  --no-lock (-n)                   Don't use lockfile (potentially dangerous!)
@@ -72,3 +75,34 @@
  --challenge (-t) http-01|dns-01  Which challenge should be used? Currently 
http-01 and dns-01 are supported
  --algo (-a) rsa|prime256v1|secp384r1 Which public key algorithm should be 
used? Supported: rsa, prime256v1 and secp384r1
 ```
+
+## Donate
+
+I'm having fun developing dehydrated, but it takes time, and time is money, at 
least that's what I've been told.
+
+I will definitively continue developing dehydrated for free, but if you want 
to support me you can do so using the following ways:
+
+### PayPal
+
+[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=23P9DSJBTY7C8)
+
+### BitCoin
+
+Send bitcoins to 12487bHxcrREffTGwUDnoxF1uYxCA7ztKK
+
+### Server
+
+I'm still planning on building a bigger testing-suite for dehydrated, it would 
be really cool to have a big(ish) server running
+in a datacenter somewhere without having to pay for it... If you are a server 
provider and can offer me a (dedicated!) machine,
+please contact me at `[email protected]`.
+
+### Other ways
+
+I always like to play around with modern(ish) network and computer gear, 10G 
switches and stuff, modern ARM boards
+(but please not that Raspberry Pi rubbish), tiny PCs for routing, etc.
+
+If you have something that seems of value and that you don't need anymore feel 
free to contact me at
+`[email protected]`.
+
+Also here is my [Amazon 
Wishlist](http://www.amazon.de/registry/wishlist/1TUCFJK35IO4Q) :)
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dehydrated-0.4.0/dehydrated 
new/dehydrated-0.5.0/dehydrated
--- old/dehydrated-0.4.0/dehydrated     2017-02-05 15:33:17.000000000 +0100
+++ new/dehydrated-0.5.0/dehydrated     2018-01-13 20:08:12.000000000 +0100
@@ -1,16 +1,20 @@
 #!/usr/bin/env bash
 
 # dehydrated by lukas2511
-# Source: https://github.com/lukas2511/dehydrated
+# Source: https://dehydrated.de
 #
 # This script is licensed under The MIT License (see LICENSE for more 
information).
 
 set -e
 set -u
 set -o pipefail
-[[ -n "${ZSH_VERSION:-}" ]] && set -o SH_WORD_SPLIT && set +o FUNCTION_ARGZERO
+[[ -n "${ZSH_VERSION:-}" ]] && set -o SH_WORD_SPLIT && set +o FUNCTION_ARGZERO 
&& set -o NULL_GLOB
+[[ -z "${ZSH_VERSION:-}" ]] && shopt -s nullglob
+
 umask 077 # paranoid umask, we're creating private keys
 
+VERSION="0.5.0"
+
 # Find directory in which this script is stored by traversing all symbolic 
links
 SOURCE="${0}"
 while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a 
symlink
@@ -21,6 +25,7 @@
 SCRIPTDIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
 
 BASEDIR="${SCRIPTDIR}"
+ORIGARGS="$@"
 
 # Create (identifiable) temporary files
 _mktemp() {
@@ -31,7 +36,7 @@
 # Check for script dependencies
 check_dependencies() {
   # just execute some dummy and/or version commands to see if required tools 
exist and are actually usable
-  openssl version > /dev/null 2>&1 || _exiterr "This script requires an 
openssl binary."
+  "${OPENSSL}" version > /dev/null 2>&1 || _exiterr "This script requires an 
openssl binary."
   _sed "" < /dev/null > /dev/null 2>&1 || _exiterr "This script requires sed 
with support for extended (modern) regular expressions."
   command -v grep > /dev/null 2>&1 || _exiterr "This script requires grep."
   command -v mktemp > /dev/null 2>&1 || _exiterr "This script requires mktemp."
@@ -77,16 +82,16 @@
 
 # verify configuration values
 verify_config() {
-  [[ "${CHALLENGETYPE}" =~ (http-01|dns-01) ]] || _exiterr "Unknown challenge 
type ${CHALLENGETYPE}... can not continue."
+  [[ "${CHALLENGETYPE}" == "http-01" || "${CHALLENGETYPE}" == "dns-01" ]] || 
_exiterr "Unknown challenge type ${CHALLENGETYPE}... cannot continue."
   if [[ "${CHALLENGETYPE}" = "dns-01" ]] && [[ -z "${HOOK}" ]]; then
-    _exiterr "Challenge type dns-01 needs a hook script for deployment... can 
not continue."
+    _exiterr "Challenge type dns-01 needs a hook script for deployment... 
cannot continue."
   fi
   if [[ "${CHALLENGETYPE}" = "http-01" && ! -d "${WELLKNOWN}" && ! 
"${COMMAND:-}" = "register" ]]; then
     _exiterr "WELLKNOWN directory doesn't exist, please create ${WELLKNOWN} 
and set appropriate permissions."
   fi
-  [[ "${KEY_ALGO}" =~ ^(rsa|prime256v1|secp384r1)$ ]] || _exiterr "Unknown 
public key algorithm ${KEY_ALGO}... can not continue."
+  [[ "${KEY_ALGO}" == "rsa" || "${KEY_ALGO}" == "prime256v1" || "${KEY_ALGO}" 
== "secp384r1" ]] || _exiterr "Unknown public key algorithm ${KEY_ALGO}... 
cannot continue."
   if [[ -n "${IP_VERSION}" ]]; then
-    [[ "${IP_VERSION}" = "4" || "${IP_VERSION}" = "6" ]] || _exiterr "Unknown 
IP version ${IP_VERSION}... can not continue."
+    [[ "${IP_VERSION}" = "4" || "${IP_VERSION}" = "6" ]] || _exiterr "Unknown 
IP version ${IP_VERSION}... cannot continue."
   fi
 }
 
@@ -111,6 +116,7 @@
   ACCOUNTDIR=
   CHALLENGETYPE="http-01"
   CONFIG_D=
+  CURL_OPTS=
   DOMAINS_D=
   DOMAINS_TXT=
   HOOK=
@@ -121,11 +127,17 @@
   PRIVATE_KEY_RENEW="yes"
   PRIVATE_KEY_ROLLOVER="no"
   KEY_ALGO=rsa
-  OPENSSL_CNF="$(openssl version -d | cut -d\" -f2)/openssl.cnf"
+  OPENSSL=openssl
+  OPENSSL_CNF=
   CONTACT_EMAIL=
   LOCKFILE=
   OCSP_MUST_STAPLE="no"
+  OCSP_FETCH="no"
   IP_VERSION=
+  CHAINCACHE=
+  AUTO_CLEANUP="no"
+  DEHYDRATED_USER=
+  DEHYDRATED_GROUP=
 
   if [[ -z "${CONFIG:-}" ]]; then
     echo "#" >&2
@@ -142,25 +154,51 @@
 
   if [[ -n "${CONFIG_D}" ]]; then
     if [[ ! -d "${CONFIG_D}" ]]; then
-      _exiterr "The path ${CONFIG_D} specified for CONFIG_D does not point to 
a directory." >&2
+      _exiterr "The path ${CONFIG_D} specified for CONFIG_D does not point to 
a directory."
     fi
 
     for check_config_d in "${CONFIG_D}"/*.sh; do
-      if [[ ! -e "${check_config_d}" ]]; then
-        echo "# !! WARNING !! Extra configuration directory ${CONFIG_D} 
exists, but no configuration found in it." >&2
-        break
-      elif [[ -f "${check_config_d}" ]] && [[ -r "${check_config_d}" ]]; then
+      if [[ -f "${check_config_d}" ]] && [[ -r "${check_config_d}" ]]; then
         echo "# INFO: Using additional config file ${check_config_d}"
         # shellcheck disable=SC1090
         . "${check_config_d}"
       else
-        _exiterr "Specified additional config ${check_config_d} is not 
readable or not a file at all." >&2
+        _exiterr "Specified additional config ${check_config_d} is not 
readable or not a file at all."
       fi
    done
   fi
 
+  # Check if we are running & are allowed to run as root
+  if [[ -n "$DEHYDRATED_USER" ]]; then
+    command -v sudo > /dev/null 2>&1 || _exiterr "DEHYDRATED_USER set but sudo 
not available. Please install sudo."
+    command -v getent > /dev/null 2>&1 || _exiterr "DEHYDRATED_USER set but 
getent not available. Please install getent."
+
+    TARGET_UID="$(getent passwd "${DEHYDRATED_USER}" | cut -d':' -f3)"
+    if [[ -z "${DEHYDRATED_GROUP}" ]]; then
+      if [[ "${EUID}" != "${TARGET_UID}" ]]; then
+        echo "# INFO: Running $0 as ${DEHYDRATED_USER}"
+        exec sudo -u "${DEHYDRATED_USER}" "${0}" ${ORIGARGS}
+      fi
+    else
+      TARGET_GID="$(getent group "${DEHYDRATED_GROUP}" | cut -d':' -f3)"
+      if [[ -z "${EGID:-}" ]]; then
+        command -v id > /dev/null 2>&1 || _exiterr "DEHYDRATED_GROUP set, 
don't know current gid and 'id' not available... Please provide 'id' binary."
+        EGID="$(id -g)"
+      fi
+      if [[ "${EUID}" != "${TARGET_UID}" ]] || [[ "${EGID}" != "${TARGET_GID}" 
]]; then
+        echo "# INFO: Running $0 as ${DEHYDRATED_USER}/${DEHYDRATED_GROUP}"
+        exec sudo -u "${DEHYDRATED_USER}" -g "${DEHYDRATED_GROUP}" "${0}" 
${ORIGARGS}
+      fi
+    fi
+  elif [[ -n "${DEHYDRATED_GROUP}" ]]; then
+    _exiterr "DEHYDRATED_GROUP can only be used in combination with 
DEHYDRATED_USER."
+  fi
+
+  # Check for missing dependencies
+  check_dependencies
+
   # Remove slash from end of BASEDIR. Mostly for cleaner outputs, doesn't 
change functionality.
-  BASEDIR="${BASEDIR%%/}"
+  [[ "$BASEDIR" != "/" ]] && BASEDIR="${BASEDIR%%/}"
 
   # Check BASEDIR and set default variables
   [[ -d "${BASEDIR}" ]] || _exiterr "BASEDIR does not exist: ${BASEDIR}"
@@ -182,9 +220,11 @@
   fi
 
   [[ -z "${CERTDIR}" ]] && CERTDIR="${BASEDIR}/certs"
+  [[ -z "${CHAINCACHE}" ]] && CHAINCACHE="${BASEDIR}/chains"
   [[ -z "${DOMAINS_TXT}" ]] && DOMAINS_TXT="${BASEDIR}/domains.txt"
   [[ -z "${WELLKNOWN}" ]] && WELLKNOWN="/var/www/dehydrated"
   [[ -z "${LOCKFILE}" ]] && LOCKFILE="${BASEDIR}/lock"
+  [[ -z "${OPENSSL_CNF}" ]] && OPENSSL_CNF="$("${OPENSSL}" version -d | cut 
-d\" -f2)/openssl.cnf"
   [[ -n "${PARAM_LOCKFILE_SUFFIX:-}" ]] && 
LOCKFILE="${LOCKFILE}-${PARAM_LOCKFILE_SUFFIX}"
   [[ -n "${PARAM_NO_LOCK:-}" ]] && LOCKFILE=""
 
@@ -195,7 +235,9 @@
   [[ -n "${PARAM_OCSP_MUST_STAPLE:-}" ]] && 
OCSP_MUST_STAPLE="${PARAM_OCSP_MUST_STAPLE}"
   [[ -n "${PARAM_IP_VERSION:-}" ]] && IP_VERSION="${PARAM_IP_VERSION}"
 
-  verify_config
+  if [ ! "${1:-}" = "noverify" ]; then
+    verify_config
+  fi
   store_configvars
 }
 
@@ -220,6 +262,8 @@
   # shellcheck disable=SC2015
   CA_REVOKE_CERT="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value 
revoke-cert)" ||
   _exiterr "Problem retrieving ACME/CA-URLs, check if your configured CA 
points to the directory entrypoint."
+  # Since reg URI is missing from directory we will assume it is the same as 
CA_NEW_REG without the new part
+  CA_REG=${CA_NEW_REG/new-reg/reg}
 
   # Export some environment variables to be used in hook script
   export WELLKNOWN BASEDIR CERTDIR CONFIG COMMAND
@@ -236,18 +280,18 @@
     if [[ ! -e "${ACCOUNT_KEY}" ]]; then
       REAL_LICENSE="$(http_request head "${CA_TERMS}" | (grep Location: || 
true) | awk -F ': ' '{print $2}' | tr -d '\n\r')"
       if [[ -z "${REAL_LICENSE}" ]]; then
-        printf '\n'
-        printf 'Error retrieving terms of service from certificate 
authority.\n'
-        printf 'Please set LICENSE in config manually.\n'
+        printf '\n' >&2
+        printf 'Error retrieving terms of service from certificate 
authority.\n' >&2
+        printf 'Please set LICENSE in config manually.\n' >&2
         exit 1
       fi
       if [[ ! "${LICENSE}" = "${REAL_LICENSE}" ]]; then
         if [[ "${PARAM_ACCEPT_TERMS:-}" = "yes" ]]; then
           LICENSE="${REAL_LICENSE}"
         else
-          printf '\n'
-          printf 'To use dehydrated with this certificate authority you have 
to agree to their terms of service which you can find here: %s\n\n' 
"${REAL_LICENSE}"
-          printf 'To accept these terms of service run `%s --register 
--accept-terms`.\n' "${0}"
+          printf '\n' >&2
+          printf 'To use dehydrated with this certificate authority you have 
to agree to their terms of service which you can find here: %s\n\n' 
"${REAL_LICENSE}" >&2
+          printf 'To accept these terms of service run `%s --register 
--accept-terms`.\n' "${0}" >&2
           exit 1
         fi
       fi
@@ -257,13 +301,13 @@
       register_new_key="yes"
     fi
   fi
-  openssl rsa -in "${ACCOUNT_KEY}" -check 2>/dev/null > /dev/null || _exiterr 
"Account key is not valid, can not continue."
+  "${OPENSSL}" rsa -in "${ACCOUNT_KEY}" -check 2>/dev/null > /dev/null || 
_exiterr "Account key is not valid, cannot continue."
 
   # Get public components from private key and calculate thumbprint
-  pubExponent64="$(printf '%x' "$(openssl rsa -in "${ACCOUNT_KEY}" -noout 
-text | awk '/publicExponent/ {print $2}')" | hex2bin | urlbase64)"
-  pubMod64="$(openssl rsa -in "${ACCOUNT_KEY}" -noout -modulus | cut -d'=' -f2 
| hex2bin | urlbase64)"
+  pubExponent64="$(printf '%x' "$("${OPENSSL}" rsa -in "${ACCOUNT_KEY}" -noout 
-text | awk '/publicExponent/ {print $2}')" | hex2bin | urlbase64)"
+  pubMod64="$("${OPENSSL}" rsa -in "${ACCOUNT_KEY}" -noout -modulus | cut 
-d'=' -f2 | hex2bin | urlbase64)"
 
-  thumbprint="$(printf '{"e":"%s","kty":"RSA","n":"%s"}' "${pubExponent64}" 
"${pubMod64}" | openssl dgst -sha256 -binary | urlbase64)"
+  thumbprint="$(printf '{"e":"%s","kty":"RSA","n":"%s"}' "${pubExponent64}" 
"${pubMod64}" | "${OPENSSL}" dgst -sha256 -binary | urlbase64)"
 
   # If we generated a new private key in the step above we have to register it 
with the acme-server
   if [[ "${register_new_key}" = "yes" ]]; then
@@ -285,9 +329,9 @@
     fi
 
     if [[ "${FAILED}" = "true" ]]; then
-      echo
-      echo
-      echo "Error registering account key. See message above for more 
information."
+      echo >&2
+      echo >&2
+      echo "Error registering account key. See message above for more 
information." >&2
       rm "${ACCOUNT_KEY}" "${ACCOUNT_KEY_JSON}"
       exit 1
     fi
@@ -299,7 +343,7 @@
 
 # Different sed version for different os types...
 _sed() {
-  if [[ "${OSTYPE}" = "Linux" ]]; then
+  if [[ "${OSTYPE}" = "Linux" || "${OSTYPE:0:5}" = "MINGW" ]]; then
     sed -r "${@}"
   else
     sed -E "${@}"
@@ -320,7 +364,7 @@
 # Encode data as url-safe formatted base64
 urlbase64() {
   # urlbase64: base64 encoded string with '+' replaced with '-' and '/' 
replaced with '_'
-  openssl base64 -e | tr -d '\n\r' | _sed -e 's:=*$::g' -e 'y:+/:-_:'
+  "${OPENSSL}" base64 -e | tr -d '\n\r' | _sed -e 's:=*$::g' -e 'y:+/:-_:'
 }
 
 # Convert hex string to binary data
@@ -336,6 +380,13 @@
   sed -n "${filter}"
 }
 
+# Get integer value from json
+get_json_int_value() {
+  local filter
+  filter=$(printf 's/.*"%s": *\([0-9]*\).*/\\1/p' "$1")
+  sed -n "${filter}"
+}
+
 rm_json_arrays() {
   local filter
   filter='s/\[[^][]*\]/null/g'
@@ -347,7 +398,7 @@
 # display the output if the exit code was != 0 to simplify debugging.
 _openssl() {
   set +e
-  out="$(openssl "${@}" 2>&1)"
+  out="$("${OPENSSL}" "${@}" 2>&1)"
   res=$?
   set -e
   if [[ ${res} -ne 0 ]]; then
@@ -370,13 +421,13 @@
 
   set +e
   if [[ "${1}" = "head" ]]; then
-    statuscode="$(curl ${ip_version:-} -s -w "%{http_code}" -o "${tempcont}" 
"${2}" -I)"
+    statuscode="$(curl ${ip_version:-} ${CURL_OPTS} -s -w "%{http_code}" -o 
"${tempcont}" "${2}" -I)"
     curlret="${?}"
   elif [[ "${1}" = "get" ]]; then
-    statuscode="$(curl ${ip_version:-} -s -w "%{http_code}" -o "${tempcont}" 
"${2}")"
+    statuscode="$(curl ${ip_version:-} ${CURL_OPTS} -s -w "%{http_code}" -o 
"${tempcont}" "${2}")"
     curlret="${?}"
   elif [[ "${1}" = "post" ]]; then
-    statuscode="$(curl ${ip_version:-} -s -w "%{http_code}" -o "${tempcont}" 
"${2}" -d "${3}")"
+    statuscode="$(curl ${ip_version:-} ${CURL_OPTS} -s -w "%{http_code}" -o 
"${tempcont}" "${2}" -d "${3}")"
     curlret="${?}"
   else
     set -e
@@ -389,7 +440,12 @@
   fi
 
   if [[ ! "${statuscode:0:1}" = "2" ]]; then
-    if [[ ! "${2}" = "${CA_TERMS}" ]] || [[ ! "${statuscode:0:1}" = "3" ]]; 
then
+    if [[ -n "${CA_REVOKE_CERT:-}" ]] && [[ "${2}" = "${CA_REVOKE_CERT:-}" ]] 
&& [[ "${statuscode}" = "409" ]]; then
+      grep -q "Certificate already revoked" "${tempcont}" && return
+    elif [[ -n "${CA_TERMS:-}" ]] && [[ "${2}" = "${CA_TERMS:-}" ]] && [[ 
"${statuscode:0:1}" = "3" ]]; then
+      # do nothing
+      :
+    else
       echo "  + ERROR: An error occurred while sending ${1}-request to ${2} 
(Status ${statuscode})" >&2
       echo >&2
       echo "Details:" >&2
@@ -399,7 +455,7 @@
 
       # An exclusive hook for the {1}-request error might be useful (e.g., for 
sending an e-mail to admins)
       if [[ -n "${HOOK}" ]] && [[ "${HOOK_CHAIN}" != "yes" ]]; then
-        errtxt=`cat ${tempcont}`
+        errtxt="$(cat ${tempcont})"
         "${HOOK}" "request_failure" "${statuscode}" "${errtxt}" "${1}"
       fi
 
@@ -436,7 +492,7 @@
   protected64="$(printf '%s' "${protected}" | urlbase64)"
 
   # Sign header with nonce and our payload with our private key and encode 
signature as urlbase64
-  signed64="$(printf '%s' "${protected64}.${payload64}" | openssl dgst -sha256 
-sign "${ACCOUNT_KEY}" | urlbase64)"
+  signed64="$(printf '%s' "${protected64}.${payload64}" | "${OPENSSL}" dgst 
-sha256 -sign "${ACCOUNT_KEY}" | urlbase64)"
 
   # Send header + extended header + payload + signature to the acme-server
   data='{"header": '"${header}"', "protected": "'"${protected64}"'", 
"payload": "'"${payload64}"'", "signature": "'"${signed64}"'"}'
@@ -449,11 +505,11 @@
 extract_altnames() {
   csr="${1}" # the CSR itself (not a file)
 
-  if ! <<<"${csr}" openssl req -verify -noout 2>/dev/null; then
+  if ! <<<"${csr}" "${OPENSSL}" req -verify -noout 2>/dev/null; then
     _exiterr "Certificate signing request isn't valid"
   fi
 
-  reqtext="$( <<<"${csr}" openssl req -noout -text )"
+  reqtext="$( <<<"${csr}" "${OPENSSL}" req -noout -text )"
   if <<<"${reqtext}" grep -q '^[[:space:]]*X509v3 Subject Alternative 
Name:[[:space:]]*$'; then
     # SANs used, extract these
     altnames="$( <<<"${reqtext}" awk '/X509v3 Subject Alternative 
Name:/{print;getline;print;}' | tail -n1 )"
@@ -461,16 +517,16 @@
     # shellcheck disable=SC1003
     altnames="$( <<<"${altnames}" _sed -e 's/^[[:space:]]*//; s/, /\'$'\n''/g' 
)"
     # we can only get DNS: ones signed
-    if grep -qv '^DNS:' <<<"${altnames}"; then
+    if grep -qEv '^(DNS|othername):' <<<"${altnames}"; then
       _exiterr "Certificate signing request contains non-DNS Subject 
Alternative Names"
     fi
     # strip away the DNS: prefix
-    altnames="$( <<<"${altnames}" _sed -e 's/^DNS://' )"
+    altnames="$( <<<"${altnames}" _sed -e 
's/^(DNS:|othername:<unsupported>)//' )"
     echo "${altnames}"
 
   else
     # No SANs, extract CN
-    altnames="$( <<<"${reqtext}" grep '^[[:space:]]*Subject:' | _sed -e 's/.* 
CN=([^ /,]*).*/\1/' )"
+    altnames="$( <<<"${reqtext}" grep '^[[:space:]]*Subject:' | _sed -e 's/.* 
CN ?= ?([^ /,]*).*/\1/' )"
     echo "${altnames}"
   fi
 }
@@ -490,6 +546,7 @@
   if [ -z "${altnames}" ]; then
     altnames="$( extract_altnames "${csr}" )"
   fi
+  export altnames
 
   if [[ -z "${CA_NEW_AUTHZ}" ]] || [[ -z "${CA_NEW_CERT}" ]]; then
     _exiterr "Certificate authority doesn't allow certificate signing"
@@ -509,7 +566,7 @@
     response="$(signed_request "${CA_NEW_AUTHZ}" '{"resource": "new-authz", 
"identifier": {"type": "dns", "value": "'"${altname}"'"}}' | clean_json)"
 
     challenge_status="$(printf '%s' "${response}" | rm_json_arrays | 
get_json_string_value status)"
-    if [ "${challenge_status}" = "valid" ]; then
+    if [ "${challenge_status}" = "valid" ] && [ ! "${PARAM_FORCE:-no}" = "yes" 
]; then
        echo " + Already validated!"
        continue
     fi
@@ -536,7 +593,7 @@
         ;;
       "dns-01")
         # Generate DNS entry content for dns-01 validation
-        keyauth_hook="$(printf '%s' "${keyauth}" | openssl dgst -sha256 
-binary | urlbase64)"
+        keyauth_hook="$(printf '%s' "${keyauth}" | "${OPENSSL}" dgst -sha256 
-binary | urlbase64)"
         ;;
     esac
 
@@ -593,6 +650,7 @@
         echo " + Challenge is valid!"
       else
         [[ -n "${HOOK}" ]] && [[ "${HOOK_CHAIN}" != "yes" ]] && "${HOOK}" 
"invalid_challenge" "${altname}" "${result}"
+        break
       fi
     done
   fi
@@ -617,8 +675,8 @@
 
   # Finally request certificate from the acme-server and store it in 
cert-${timestamp}.pem and link from cert.pem
   echo " + Requesting certificate..."
-  csr64="$( <<<"${csr}" openssl req -outform DER | urlbase64)"
-  crt64="$(signed_request "${CA_NEW_CERT}" '{"resource": "new-cert", "csr": 
"'"${csr64}"'"}' | openssl base64 -e)"
+  csr64="$( <<<"${csr}" "${OPENSSL}" req -config "${OPENSSL_CNF}" -outform DER 
| urlbase64)"
+  crt64="$(signed_request "${CA_NEW_CERT}" '{"resource": "new-cert", "csr": 
"'"${csr64}"'"}' | "${OPENSSL}" base64 -e)"
   crt="$( printf -- '-----BEGIN CERTIFICATE-----\n%s\n-----END 
CERTIFICATE-----\n' "${crt64}" )"
 
   # Try to load the certificate to detect corruption
@@ -634,7 +692,17 @@
 # grep issuer cert uri from certificate
 get_issuer_cert_uri() {
   certificate="${1}"
-  openssl x509 -in "${certificate}" -noout -text | (grep 'CA Issuers - URI:' | 
cut -d':' -f2-) || true
+  "${OPENSSL}" x509 -in "${certificate}" -noout -text | (grep 'CA Issuers - 
URI:' | cut -d':' -f2-) || true
+}
+
+get_issuer_hash() {
+  certificate="${1}"
+  "${OPENSSL}" x509 -in "${certificate}" -noout -issuer_hash
+}
+
+get_ocsp_url() {
+  certificate="${1}"
+  "${OPENSSL}" x509 -in "${certificate}" -noout -ocsp_uri
 }
 
 # walk certificate chain, retrieving all intermediate certificates
@@ -658,9 +726,9 @@
     # PEM
     if grep -q "BEGIN CERTIFICATE" "${tmpcert_raw}"; then mv "${tmpcert_raw}" 
"${tmpcert}"
     # DER
-    elif openssl x509 -in "${tmpcert_raw}" -inform DER -out "${tmpcert}" 
-outform PEM 2> /dev/null > /dev/null; then :
+    elif "${OPENSSL}" x509 -in "${tmpcert_raw}" -inform DER -out "${tmpcert}" 
-outform PEM 2> /dev/null > /dev/null; then :
     # PKCS7
-    elif openssl pkcs7 -in "${tmpcert_raw}" -inform DER -out "${tmpcert}" 
-outform PEM -print_certs 2> /dev/null > /dev/null; then :
+    elif "${OPENSSL}" pkcs7 -in "${tmpcert_raw}" -inform DER -out "${tmpcert}" 
-outform PEM -print_certs 2> /dev/null > /dev/null; then :
     # Unknown certificate type
     else _exiterr "Unknown certificate type in chain"
     fi
@@ -678,57 +746,65 @@
 
 # Create certificate for domain(s)
 sign_domain() {
+  local certdir="${1}"
+  shift
   domain="${1}"
   altnames="${*}"
   timestamp="$(date +%s)"
 
+  export altnames
+
   echo " + Signing domains..."
   if [[ -z "${CA_NEW_AUTHZ}" ]] || [[ -z "${CA_NEW_CERT}" ]]; then
     _exiterr "Certificate authority doesn't allow certificate signing"
   fi
 
   # If there is no existing certificate directory => make it
-  if [[ ! -e "${CERTDIR}/${domain}" ]]; then
-    echo " + Creating new directory ${CERTDIR}/${domain} ..."
-    mkdir -p "${CERTDIR}/${domain}" || _exiterr "Unable to create directory 
${CERTDIR}/${domain}"
+  if [[ ! -e "${certdir}" ]]; then
+    echo " + Creating new directory ${certdir} ..."
+    mkdir -p "${certdir}" || _exiterr "Unable to create directory ${certdir}"
+  fi
+  if [ ! -d "${CHAINCACHE}" ]; then
+    echo " + Creating chain cache directory ${CHAINCACHE}"
+    mkdir "${CHAINCACHE}"
   fi
 
   privkey="privkey.pem"
   # generate a new private key if we need or want one
-  if [[ ! -r "${CERTDIR}/${domain}/privkey.pem" ]] || [[ 
"${PRIVATE_KEY_RENEW}" = "yes" ]]; then
+  if [[ ! -r "${certdir}/privkey.pem" ]] || [[ "${PRIVATE_KEY_RENEW}" = "yes" 
]]; then
     echo " + Generating private key..."
     privkey="privkey-${timestamp}.pem"
     case "${KEY_ALGO}" in
-      rsa) _openssl genrsa -out 
"${CERTDIR}/${domain}/privkey-${timestamp}.pem" "${KEYSIZE}";;
-      prime256v1|secp384r1) _openssl ecparam -genkey -name "${KEY_ALGO}" -out 
"${CERTDIR}/${domain}/privkey-${timestamp}.pem";;
+      rsa) _openssl genrsa -out "${certdir}/privkey-${timestamp}.pem" 
"${KEYSIZE}";;
+      prime256v1|secp384r1) _openssl ecparam -genkey -name "${KEY_ALGO}" -out 
"${certdir}/privkey-${timestamp}.pem";;
     esac
   fi
   # move rolloverkey into position (if any)
-  if [[ -r "${CERTDIR}/${domain}/privkey.pem" && -r 
"${CERTDIR}/${domain}/privkey.roll.pem" && "${PRIVATE_KEY_RENEW}" = "yes" && 
"${PRIVATE_KEY_ROLLOVER}" = "yes" ]]; then
+  if [[ -r "${certdir}/privkey.pem" && -r "${certdir}/privkey.roll.pem" && 
"${PRIVATE_KEY_RENEW}" = "yes" && "${PRIVATE_KEY_ROLLOVER}" = "yes" ]]; then
     echo " + Moving Rolloverkey into position....  "
-    mv "${CERTDIR}/${domain}/privkey.roll.pem" 
"${CERTDIR}/${domain}/privkey-tmp.pem"
-    mv "${CERTDIR}/${domain}/privkey-${timestamp}.pem" 
"${CERTDIR}/${domain}/privkey.roll.pem"
-    mv "${CERTDIR}/${domain}/privkey-tmp.pem" 
"${CERTDIR}/${domain}/privkey-${timestamp}.pem"
+    mv "${certdir}/privkey.roll.pem" "${certdir}/privkey-tmp.pem"
+    mv "${certdir}/privkey-${timestamp}.pem" "${certdir}/privkey.roll.pem"
+    mv "${certdir}/privkey-tmp.pem" "${certdir}/privkey-${timestamp}.pem"
   fi
   # generate a new private rollover key if we need or want one
-  if [[ ! -r "${CERTDIR}/${domain}/privkey.roll.pem" && 
"${PRIVATE_KEY_ROLLOVER}" = "yes" && "${PRIVATE_KEY_RENEW}" = "yes" ]]; then
+  if [[ ! -r "${certdir}/privkey.roll.pem" && "${PRIVATE_KEY_ROLLOVER}" = 
"yes" && "${PRIVATE_KEY_RENEW}" = "yes" ]]; then
     echo " + Generating private rollover key..."
     case "${KEY_ALGO}" in
-      rsa) _openssl genrsa -out "${CERTDIR}/${domain}/privkey.roll.pem" 
"${KEYSIZE}";;
-      prime256v1|secp384r1) _openssl ecparam -genkey -name "${KEY_ALGO}" -out 
"${CERTDIR}/${domain}/privkey.roll.pem";;
+      rsa) _openssl genrsa -out "${certdir}/privkey.roll.pem" "${KEYSIZE}";;
+      prime256v1|secp384r1) _openssl ecparam -genkey -name "${KEY_ALGO}" -out 
"${certdir}/privkey.roll.pem";;
     esac
   fi
   # delete rolloverkeys if disabled
-  if [[ -r "${CERTDIR}/${domain}/privkey.roll.pem" && ! 
"${PRIVATE_KEY_ROLLOVER}" = "yes" ]]; then
+  if [[ -r "${certdir}/privkey.roll.pem" && ! "${PRIVATE_KEY_ROLLOVER}" = 
"yes" ]]; then
     echo " + Removing Rolloverkey (feature disabled)..."
-    rm -f "${CERTDIR}/${domain}/privkey.roll.pem"
+    rm -f "${certdir}/privkey.roll.pem"
   fi
 
   # Generate signing request config and the actual signing request
   echo " + Generating signing request..."
   SAN=""
   for altname in ${altnames}; do
-    SAN+="DNS:${altname}, "
+    SAN="${SAN}DNS:${altname}, "
   done
   SAN="${SAN%%, }"
   local tmp_openssl_cnf
@@ -738,34 +814,86 @@
   if [ "${OCSP_MUST_STAPLE}" = "yes" ]; then
     printf "\n1.3.6.1.5.5.7.1.24=DER:30:03:02:01:05" >> "${tmp_openssl_cnf}"
   fi
-  openssl req -new -sha256 -key "${CERTDIR}/${domain}/${privkey}" -out 
"${CERTDIR}/${domain}/cert-${timestamp}.csr" -subj "/CN=${domain}/" -reqexts 
SAN -config "${tmp_openssl_cnf}"
+  SUBJ="/CN=${domain}/"
+  if [[ "${OSTYPE:0:5}" = "MINGW" ]]; then
+    # The subject starts with a /, so MSYS will assume it's a path and convert
+    # it unless we escape it with another one:
+    SUBJ="/${SUBJ}"
+  fi
+  "${OPENSSL}" req -new -sha256 -key "${certdir}/${privkey}" -out 
"${certdir}/cert-${timestamp}.csr" -subj "${SUBJ}" -reqexts SAN -config 
"${tmp_openssl_cnf}"
   rm -f "${tmp_openssl_cnf}"
 
-  crt_path="${CERTDIR}/${domain}/cert-${timestamp}.pem"
+  crt_path="${certdir}/cert-${timestamp}.pem"
   # shellcheck disable=SC2086
-  sign_csr "$(< "${CERTDIR}/${domain}/cert-${timestamp}.csr" )" ${altnames} 
3>"${crt_path}"
+  sign_csr "$(< "${certdir}/cert-${timestamp}.csr" )" ${altnames} 
3>"${crt_path}"
 
   # Create fullchain.pem
   echo " + Creating fullchain.pem..."
-  cat "${crt_path}" > "${CERTDIR}/${domain}/fullchain-${timestamp}.pem"
-  walk_chain "${crt_path}" > "${CERTDIR}/${domain}/chain-${timestamp}.pem"
-  cat "${CERTDIR}/${domain}/chain-${timestamp}.pem" >> 
"${CERTDIR}/${domain}/fullchain-${timestamp}.pem"
+  cat "${crt_path}" > "${certdir}/fullchain-${timestamp}.pem"
+  local issuer_hash
+  issuer_hash="$(get_issuer_hash "${crt_path}")"
+  if [ -e "${CHAINCACHE}/${issuer_hash}.chain" ]; then
+    echo " + Using cached chain!"
+    cat "${CHAINCACHE}/${issuer_hash}.chain" > 
"${certdir}/chain-${timestamp}.pem"
+  else
+    echo " + Walking chain..."
+    local issuer_cert_uri
+    issuer_cert_uri="$(get_issuer_cert_uri "${crt_path}" || echo "unknown")"
+    (walk_chain "${crt_path}" > "${certdir}/chain-${timestamp}.pem") || 
_exiterr "Walking chain has failed, your certificate has been created and can 
be found at ${crt_path}, the corresponding private key at ${privkey}. If you 
want you can manually continue on creating and linking all necessary files. If 
this error occurs again you should manually generate the certificate chain and 
place it under ${CHAINCACHE}/${issuer_hash}.chain (see ${issuer_cert_uri})"
+    cat "${certdir}/chain-${timestamp}.pem" > 
"${CHAINCACHE}/${issuer_hash}.chain"
+  fi
+  cat "${certdir}/chain-${timestamp}.pem" >> 
"${certdir}/fullchain-${timestamp}.pem"
 
   # Update symlinks
-  [[ "${privkey}" = "privkey.pem" ]] || ln -sf "privkey-${timestamp}.pem" 
"${CERTDIR}/${domain}/privkey.pem"
+  [[ "${privkey}" = "privkey.pem" ]] || ln -sf "privkey-${timestamp}.pem" 
"${certdir}/privkey.pem"
 
-  ln -sf "chain-${timestamp}.pem" "${CERTDIR}/${domain}/chain.pem"
-  ln -sf "fullchain-${timestamp}.pem" "${CERTDIR}/${domain}/fullchain.pem"
-  ln -sf "cert-${timestamp}.csr" "${CERTDIR}/${domain}/cert.csr"
-  ln -sf "cert-${timestamp}.pem" "${CERTDIR}/${domain}/cert.pem"
+  ln -sf "chain-${timestamp}.pem" "${certdir}/chain.pem"
+  ln -sf "fullchain-${timestamp}.pem" "${certdir}/fullchain.pem"
+  ln -sf "cert-${timestamp}.csr" "${certdir}/cert.csr"
+  ln -sf "cert-${timestamp}.pem" "${certdir}/cert.pem"
 
   # Wait for hook script to clean the challenge and to deploy cert if used
-  [[ -n "${HOOK}" ]] && "${HOOK}" "deploy_cert" "${domain}" 
"${CERTDIR}/${domain}/privkey.pem" "${CERTDIR}/${domain}/cert.pem" 
"${CERTDIR}/${domain}/fullchain.pem" "${CERTDIR}/${domain}/chain.pem" 
"${timestamp}"
+  [[ -n "${HOOK}" ]] && "${HOOK}" "deploy_cert" "${domain}" 
"${certdir}/privkey.pem" "${certdir}/cert.pem" "${certdir}/fullchain.pem" 
"${certdir}/chain.pem" "${timestamp}"
 
   unset challenge_token
   echo " + Done!"
 }
 
+# Usage: --version (-v)
+# Description: Print version information
+command_version() {
+  load_config noverify
+
+  echo "Dehydrated by Lukas Schauer"
+  echo "https://dehydrated.de";
+  echo ""
+  echo "Dehydrated version: ${VERSION}"
+  revision="$(cd "${SCRIPTDIR}"; git rev-parse HEAD 2>/dev/null || echo 
"unknown")"
+  echo "GIT-Revision: ${revision}"
+  echo ""
+  if [[ "${OSTYPE}" = "FreeBSD" ]]; then
+    echo "OS: $(uname -sr)"
+  else
+    echo "OS: $(cat /etc/issue | grep -v ^$ | head -n1 | _sed 's/\\(r|n|l) 
.*//g')"
+  fi
+  echo "Used software:"
+  [[ -n "${BASH_VERSION:-}" ]] && echo " bash: ${BASH_VERSION}"
+  [[ -n "${ZSH_VERSION:-}" ]] && echo " zsh: ${ZSH_VERSION}"
+  echo " curl: $(curl --version 2>&1 | head -n1 | cut -d" " -f1-2)"
+  if [[ "${OSTYPE}" = "FreeBSD" ]]; then
+    echo " awk, sed, mktemp: FreeBSD base system versions"
+  else
+    echo " awk: $(awk -W version 2>&1 | head -n1)"
+    echo " sed: $(sed --version 2>&1 | head -n1)"
+    echo " mktemp: $(mktemp --version 2>&1 | head -n1)"
+  fi
+  echo " grep: $(grep --version 2>&1 | head -n1)"
+  echo " diff: $(diff --version 2>&1 | head -n1)"
+  echo " openssl: $("${OPENSSL}" version 2>&1)"
+
+  exit 0
+}
+
 # Usage: --register
 # Description: Register account key
 command_register() {
@@ -774,14 +902,59 @@
   exit 0
 }
 
+# Usage: --account
+# Description: Update account contact information
+command_account() {
+  init_system
+  FAILED=false
+
+  NEW_ACCOUNT_KEY_JSON="$(_mktemp)"
+  REG_ID=$(cat "${ACCOUNT_KEY_JSON}" | get_json_int_value id)
+
+  # Check if we have the registration id
+  if [[ -z "${REG_ID}" ]]; then
+    _exiterr "Error retrieving registration id."
+  fi
+
+  echo "+ Updating registration id: ${REG_ID} contact information..."
+  # If an email for the contact has been provided then adding it to the 
registered account
+  if [[ -n "${CONTACT_EMAIL}" ]]; then
+    (signed_request "${CA_REG}"/"${REG_ID}" '{"resource": "reg", 
"contact":["mailto:'"${CONTACT_EMAIL}"'"]}' > "${NEW_ACCOUNT_KEY_JSON}") || 
FAILED=true
+  else
+    (signed_request "${CA_REG}"/"${REG_ID}" '{"resource": "reg", 
"contact":[]}' > "${NEW_ACCOUNT_KEY_JSON}") || FAILED=true
+  fi
+
+  if [[ "${FAILED}" = "true" ]]; then
+    rm "${NEW_ACCOUNT_KEY_JSON}"
+    _exiterr "Error updating account information. See message above for more 
information."
+  fi
+  if diff -q "${NEW_ACCOUNT_KEY_JSON}" "${ACCOUNT_KEY_JSON}" > /dev/null; then
+    echo "+ Account information was the same after the update"
+    rm "${NEW_ACCOUNT_KEY_JSON}"
+  else
+    ACCOUNT_KEY_JSON_BACKUP="${ACCOUNT_KEY_JSON%.*}-$(date +%s).json"
+    echo "+ Backup ${ACCOUNT_KEY_JSON} as ${ACCOUNT_KEY_JSON_BACKUP}"
+    cp -p "${ACCOUNT_KEY_JSON}" "${ACCOUNT_KEY_JSON_BACKUP}"
+    echo "+ Populate ${ACCOUNT_KEY_JSON}"
+    mv "${NEW_ACCOUNT_KEY_JSON}" "${ACCOUNT_KEY_JSON}"
+  fi
+  echo "+ Done!"
+  exit 0
+}
+
 # Usage: --cron (-c)
-# Description: Sign/renew non-existant/changed/expiring certificates.
+# Description: Sign/renew non-existent/changed/expiring certificates.
 command_sign_domains() {
   init_system
+  [[ -n "${HOOK}" ]] && "${HOOK}" "startup_hook"
 
   if [[ -n "${PARAM_DOMAIN:-}" ]]; then
     DOMAINS_TXT="$(_mktemp)"
-    printf -- "${PARAM_DOMAIN}" > "${DOMAINS_TXT}"
+    if [[ -n "${PARAM_ALIAS:-}" ]]; then
+      printf -- "${PARAM_DOMAIN} > ${PARAM_ALIAS}" > "${DOMAINS_TXT}"
+    else
+      printf -- "${PARAM_DOMAIN}" > "${DOMAINS_TXT}"
+    fi
   elif [[ -e "${DOMAINS_TXT}" ]]; then
     if [[ ! -r "${DOMAINS_TXT}" ]]; then
       _exiterr "domains.txt found but not readable"
@@ -793,12 +966,22 @@
   # Generate certificates for all domains found in domains.txt. Check if 
existing certificate are about to expire
   ORIGIFS="${IFS}"
   IFS=$'\n'
-  for line in $(<"${DOMAINS_TXT}" tr -d '\r' | awk '{print tolower($0)}' | 
_sed -e 's/^[[:space:]]*//g' -e 's/[[:space:]]*$//g' -e 's/[[:space:]]+/ /g' | 
(grep -vE '^(#|$)' || true)); do
+  for line in $(<"${DOMAINS_TXT}" tr -d '\r' | awk '{print tolower($0)}' | 
_sed -e 's/^[[:space:]]*//g' -e 's/[[:space:]]*$//g' -e 's/[[:space:]]+/ /g' -e 
's/([^ ])>/\1 >/g' -e 's/> />/g' | (grep -vE '^(#|$)' || true)); do
     reset_configvars
     IFS="${ORIGIFS}"
+    alias="$(grep -Eo '>[^ ]+' <<< "${line}" || true)"
+    line="$(_sed -e 's/>[^ ]+[ ]*//g' <<< "${line}")"
+    aliascount="$(grep -Eo '>' <<< "${alias}" | awk 'END {print NR}' || true )"
+    [ ${aliascount} -gt 1 ] && _exiterr "Only one alias per line is allowed in 
domains.txt!"
+
     domain="$(printf '%s\n' "${line}" | cut -d' ' -f1)"
     morenames="$(printf '%s\n' "${line}" | cut -s -d' ' -f2-)"
-    cert="${CERTDIR}/${domain}/cert.pem"
+    [ ${aliascount} -lt 1 ] && alias="${domain}" || alias="${alias#>}"
+    export alias
+
+    local certdir="${CERTDIR}/${alias}"
+    cert="${certdir}/cert.pem"
+    chain="${certdir}/chain.pem"
 
     force_renew="${PARAM_FORCE:-no}"
 
@@ -813,9 +996,9 @@
     # we could just source the config file but i decided to go this way to 
protect people from accidentally overriding
     # variables used internally by this script itself.
     if [[ -n "${DOMAINS_D}" ]]; then
-      certconfig="${DOMAINS_D}/${domain}"
+      certconfig="${DOMAINS_D}/${alias}"
     else
-      certconfig="${CERTDIR}/${domain}/config"
+      certconfig="${certdir}/config"
     fi
 
     if [ -f "${certconfig}" ]; then
@@ -841,7 +1024,7 @@
             declare -- "${config_var}=${config_value}"
             ;;
           _) ;;
-          *) echo "   ! Setting ${config_var} on a per-certificate base is not 
(yet) supported"
+          *) echo "   ! Setting ${config_var} on a per-certificate base is not 
(yet) supported" >&2
         esac
       done
       IFS="${ORIGIFS}"
@@ -849,10 +1032,12 @@
     verify_config
     export WELLKNOWN CHALLENGETYPE KEY_ALGO PRIVATE_KEY_ROLLOVER
 
+    skip="no"
+
     if [[ -e "${cert}" ]]; then
       printf " + Checking domain name(s) of existing cert..."
 
-      certnames="$(openssl x509 -in "${cert}" -text -noout | grep DNS: | _sed 
's/DNS://g' | tr -d ' ' | tr ',' '\n' | sort -u | tr '\n' ' ' | _sed 's/ $//')"
+      certnames="$("${OPENSSL}" x509 -in "${cert}" -text -noout | grep DNS: | 
_sed 's/DNS://g' | tr -d ' ' | tr ',' '\n' | sort -u | tr '\n' ' ' | _sed 's/ 
$//')"
       givennames="$(echo "${domain}" "${morenames}"| tr ' ' '\n' | sort -u | 
tr '\n' ' ' | _sed 's/ $//' | _sed 's/^ //')"
 
       if [[ "${certnames}" = "${givennames}" ]]; then
@@ -869,37 +1054,72 @@
 
     if [[ -e "${cert}" ]]; then
       echo " + Checking expire date of existing cert..."
-      valid="$(openssl x509 -enddate -noout -in "${cert}" | cut -d= -f2- )"
+      valid="$("${OPENSSL}" x509 -enddate -noout -in "${cert}" | cut -d= -f2- 
)"
 
       printf " + Valid till %s " "${valid}"
-      if openssl x509 -checkend $((RENEW_DAYS * 86400)) -noout -in "${cert}"; 
then
+      if "${OPENSSL}" x509 -checkend $((RENEW_DAYS * 86400)) -noout -in 
"${cert}"; then
         printf "(Longer than %d days). " "${RENEW_DAYS}"
         if [[ "${force_renew}" = "yes" ]]; then
           echo "Ignoring because renew was forced!"
         else
           # Certificate-Names unchanged and cert is still valid
           echo "Skipping renew!"
-          [[ -n "${HOOK}" ]] && "${HOOK}" "unchanged_cert" "${domain}" 
"${CERTDIR}/${domain}/privkey.pem" "${CERTDIR}/${domain}/cert.pem" 
"${CERTDIR}/${domain}/fullchain.pem" "${CERTDIR}/${domain}/chain.pem"
-          continue
+          [[ -n "${HOOK}" ]] && "${HOOK}" "unchanged_cert" "${domain}" 
"${certdir}/privkey.pem" "${certdir}/cert.pem" "${certdir}/fullchain.pem" 
"${certdir}/chain.pem"
+          skip="yes"
         fi
       else
         echo "(Less than ${RENEW_DAYS} days). Renewing!"
       fi
     fi
 
+    local update_ocsp
+    update_ocsp="no"
+
     # shellcheck disable=SC2086
-    if [[ "${PARAM_KEEP_GOING:-}" = "yes" ]]; then
-      sign_domain ${line} &
-      wait $! || true
-    else
-      sign_domain ${line}
+    if [[ ! "${skip}" = "yes" ]]; then
+      update_ocsp="yes"
+      if [[ "${PARAM_KEEP_GOING:-}" = "yes" ]]; then
+        sign_domain "${certdir}" ${domain} ${morenames} &
+        wait $! || true
+      else
+        sign_domain "${certdir}" ${domain} ${morenames}
+      fi
+    fi
+
+    if [[ "${OCSP_FETCH}" = "yes" ]]; then
+      local ocsp_url
+      ocsp_url="$(get_ocsp_url "${cert}")"
+
+      if [[ ! -e "${certdir}/ocsp.der" ]]; then
+        update_ocsp="yes"
+      elif ! ("${OPENSSL}" ocsp -no_nonce -issuer "${chain}" -verify_other 
"${chain}" -cert "${cert}" -respin "${certdir}/ocsp.der" -status_age 432000 
2>&1 | grep -q "${cert}: good"); then
+        update_ocsp="yes"
+      fi
+
+      if [[ "${update_ocsp}" = "yes" ]]; then
+        echo " + Updating OCSP stapling file"
+        ocsp_timestamp="$(date +%s)"
+        if grep -qE "^(0|(1\.0))\." <<< "$(${OPENSSL} version | awk '{print 
$2}')"; then
+          "${OPENSSL}" ocsp -no_nonce -issuer "${chain}" -verify_other 
"${chain}" -cert "${cert}" -respout "${certdir}/ocsp-${ocsp_timestamp}.der" 
-url "${ocsp_url}" -header "HOST" "$(echo "${ocsp_url}" | _sed -e 
's/^http(s?):\/\///' -e 's/\/.*$//g')" > /dev/null 2>&1
+        else
+          "${OPENSSL}" ocsp -no_nonce -issuer "${chain}" -verify_other 
"${chain}" -cert "${cert}" -respout "${certdir}/ocsp-${ocsp_timestamp}.der" 
-url "${ocsp_url}" > /dev/null 2>&1
+        fi
+        ln -sf "ocsp-${ocsp_timestamp}.der" "${certdir}/ocsp.der"
+      else
+        echo " + OSCP stapling file is still valid (skipping update)"
+      fi
     fi
   done
+  reset_configvars
 
   # remove temporary domains.txt file if used
   [[ -n "${PARAM_DOMAIN:-}" ]] && rm -f "${DOMAINS_TXT}"
 
   [[ -n "${HOOK}" ]] && "${HOOK}" "exit_hook"
+  if [[ "${AUTO_CLEANUP}" == "yes" ]]; then
+    echo "+ Running automatic cleanup"
+    command_cleanup noinit
+  fi
   exit 0
 }
 
@@ -931,11 +1151,11 @@
     # get and convert ca cert
     chainfile="$(_mktemp)"
     tmpchain="$(_mktemp)"
-    http_request get "$(openssl x509 -in "${certfile}" -noout -text | grep 'CA 
Issuers - URI:' | cut -d':' -f2-)" > "${tmpchain}"
+    http_request get "$("${OPENSSL}" x509 -in "${certfile}" -noout -text | 
grep 'CA Issuers - URI:' | cut -d':' -f2-)" > "${tmpchain}"
     if grep -q "BEGIN CERTIFICATE" "${tmpchain}"; then
       mv "${tmpchain}" "${chainfile}"
     else
-      openssl x509 -in "${tmpchain}" -inform DER -out "${chainfile}" -outform 
PEM
+      "${OPENSSL}" x509 -in "${tmpchain}" -inform DER -out "${chainfile}" 
-outform PEM
       rm "${tmpchain}"
     fi
 
@@ -973,7 +1193,7 @@
 
   echo "Revoking ${cert}"
 
-  cert64="$(openssl x509 -in "${cert}" -inform PEM -outform DER | urlbase64)"
+  cert64="$("${OPENSSL}" x509 -in "${cert}" -inform PEM -outform DER | 
urlbase64)"
   response="$(signed_request "${CA_REVOKE_CERT}" '{"resource": "revoke-cert", 
"certificate": "'"${cert64}"'"}' | clean_json)"
   # if there is a problem with our revoke request _request (via 
signed_request) will report this and "exit 1" out
   # so if we are here, it is safe to assume the request was successful
@@ -985,9 +1205,11 @@
 # Usage: --cleanup (-gc)
 # Description: Move unused certificate files to archive directory
 command_cleanup() {
-  load_config
+  if [ ! "${1:-}" = "noinit" ]; then
+    load_config
+  fi
 
-  # Create global archive directory if not existant
+  # Create global archive directory if not existent
   if [[ ! -e "${BASEDIR}/archive" ]]; then
     mkdir "${BASEDIR}/archive"
   fi
@@ -1000,14 +1222,14 @@
     # Get certificate name
     certname="$(basename "${certdir}")"
 
-    # Create certitifaces archive directory if not existant
+    # Create certificates archive directory if not existent
     archivedir="${BASEDIR}/archive/${certname}"
     if [[ ! -e "${archivedir}" ]]; then
       mkdir "${archivedir}"
     fi
 
     # Loop over file-types (certificates, keys, signing-requests, ...)
-    for filetype in cert.csr cert.pem chain.pem fullchain.pem privkey.pem; do
+    for filetype in cert.csr cert.pem chain.pem fullchain.pem privkey.pem 
ocsp.der; do
       # Skip if symlink is broken
       [[ -r "${certdir}/${filetype}" ]] || continue
 
@@ -1019,10 +1241,7 @@
       fileext="$(echo "${filetype}" | cut -d. -f2)"
 
       # Loop over all files of this type
-      for file in "${certdir}/${filebase}-"*".${fileext}"; do
-        # Handle case where no files match the wildcard
-        [[ -f "${file}" ]] || break
-
+      for file in "${certdir}/${filebase}-"*".${fileext}" 
"${certdir}/${filebase}-"*".${fileext}-revoked"; do
         # Check if current file is in use, if unused move to archive directory
         filename="$(basename "${file}")"
         if [[ ! "${filename}" = "${current}" ]]; then
@@ -1105,6 +1324,10 @@
         set_command register
         ;;
 
+      --account)
+        set_command account
+        ;;
+
       # PARAM_Usage: --accept-terms
       # PARAM_Description: Accept CAs terms of service
       --accept-terms)
@@ -1125,6 +1348,10 @@
         PARAM_REVOKECERT="${1}"
         ;;
 
+      --version|-v)
+        set_command version
+        ;;
+
       --cleanup|-gc)
         set_command cleanup
         ;;
@@ -1159,6 +1386,15 @@
          fi
         ;;
 
+      # PARAM_Usage: --alias certalias
+      # PARAM_Description: Use specified name for certificate directory (and 
per-certificate config) instead of the primary domain (only used if --domain is 
specified)
+      --alias)
+        shift 1
+        check_parameters "${1:-}"
+        [[ -n "${PARAM_ALIAS:-}" ]] && _exiterr "Alias can only be specified 
once!"
+        PARAM_ALIAS="${1}"
+        ;;
+
       # PARAM_Usage: --keep-going (-g)
       # PARAM_Description: Keep going after encountering an error while 
creating/renewing multiple certificates in cron mode
       --keep-going|-g)
@@ -1180,9 +1416,9 @@
       # PARAM_Usage: --lock-suffix example.com
       # PARAM_Description: Suffix lockfile name with a string (useful for with 
-d)
       --lock-suffix)
-       shift 1
+        shift 1
         check_parameters "${1:-}"
-       PARAM_LOCKFILE_SUFFIX="${1}"
+        PARAM_LOCKFILE_SUFFIX="${1}"
         ;;
 
       # PARAM_Usage: --ocsp
@@ -1254,9 +1490,11 @@
     env) command_env;;
     sign_domains) command_sign_domains;;
     register) command_register;;
+    account) command_account;;
     sign_csr) command_sign_csr "${PARAM_CSR}";;
     revoke) command_revoke "${PARAM_REVOKECERT}";;
     cleanup) command_cleanup;;
+    version) command_version;;
     *) command_help; exit 1;;
   esac
 }
@@ -1264,8 +1502,7 @@
 # Determine OS type
 OSTYPE="$(uname)"
 
-# Check for missing dependencies
-check_dependencies
-
-# Run script
-main "${@:-}"
+if [[ ! "${DEHYDRATED_NOOP:-}" = "NOOP" ]]; then
+  # Run script
+  main "${@:-}"
+fi
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dehydrated-0.4.0/dehydrated.1 
new/dehydrated-0.5.0/dehydrated.1
--- old/dehydrated-0.4.0/dehydrated.1   1970-01-01 01:00:00.000000000 +0100
+++ new/dehydrated-0.5.0/dehydrated.1   2018-01-13 20:08:12.000000000 +0100
@@ -0,0 +1,155 @@
+.TH DEHYDRATED 1 2017-09-20 "Dehydrated ACME Client"
+.SH NAME
+dehydrated \- ACME client implemented as a shell-script
+.SH SYNOPSIS
+.B dehydrated
+[\fBcommand\fR [\fBargument\fR]]
+[\fBargument\fR [\fBargument\fR]]
+.IR ...
+.SH DESCRIPTION
+A client for ACME-based Certificate Authorities, such as LetsEncrypt.  It
+allows to request and obtain TLS certificates from an ACME-based
+certificate authority.
+
+Before any certificates can be requested, Dehydrated needs
+to acquire an account with the Certificate Authorities. Optionally, an email
+address can be provided.  It will be used to e.g. notify about expiring
+certificates. You will usually need to accept the Terms of Service of the CA.
+Dehydrated will notify if no account is configured. Run with \fB--register
+--accept-terms\fR to create a new account.
+
+Next, all domain names must be provided in domains.txt. The format is line
+based: If the file contains two lines "example.com" and "example.net",
+Dehydrated will request two certificate, one for "example.com" and the other
+for "example.net". A single line while "example.com example.net" will request a
+single certificate valid for both "example.net" and "example.com" through the 
\fISubject
+Alternative Name\fR (SAN) field.
+
+For the next step, one way of verifying domain name ownership needs to be
+configured.  Dehydrated implements \fIhttp-01\fR and \fIdns-01\fR 
verification. 
+
+The \fIhttp-01\fR verification provides proof of ownership by providing a
+challenge token. In order to do that, the directory referenced in the
+\fIWELLKNOWN\fR config variable needs to be exposed at
+\fIhttp://{domain}/.well-known/acme-challenge/\fR, where {domain} is every
+domain name specified in \fIdomains.txt\fR.  Dehydrated does not provide its
+own challenge responder, but relies on an existing web server to provide the
+challenge response.  See \fIwellknown.md\fR for configuration examples of
+popular web servers.
+
+The \fIdns-01\fR verification works by providing a challenge token through DNS.
+This is especially interesting for hosts that cannot be exposed to the public
+Internet.  Because adding records to DNS zones is oftentimes highly specific to
+the software or the DNS provider at hand, there are many third party hooks
+available for dehydrated.  See \fIdns-verification.md\fR for hooks for popular
+DNS servers and DNS hosters.
+
+Finally, the certificates need to be requested and updated on a regular basis.
+This can happen through a cron job or a timer. Initially, you may enforce this
+by invoking \fIdehydrated -c\fR manually.
+
+After a successful run, certificates are stored in
+\fI/etc/dehydrated/certs/{domain}\fR, where {domain} is the domain name in the
+first column of \fIdomains.txt\fR.
+
+.SH OPTIONS
+
+.BR Commands
+.TP
+.BR \-\-version ", " \-v
+Print version information
+.TP
+.BR \-\-register
+Register account key
+.TP
+.BR \-\-account
+Update account contact information
+.TP
+.BR \-\-cron ", " \-c
+Sign/renew non\-existent/changed/expiring certificates.
+.TP
+.BR \-\-signcsr ", " \-s " " \fIpath/to/csr.pem\fR
+Sign a given CSR, output CRT on stdout (advanced usage)
+.TP
+.BR \-\-revoke ", " \-r " " \fIpath/to/cert.pem\fR
+Revoke specified certificate
+.TP
+.BR \-\-cleanup ", " \-gc
+Move unused certificate files to archive directory
+.TP
+.BR \-\-help ", " \-h
+Show help text
+.TP
+.BR \-\-env ", " \-e
+Output configuration variables for use in other scripts
+
+.PP
+.BR Parameters
+.TP
+.BR \-\-accept\-terms
+Accept CAs terms of service
+.TP
+.BR \-\-full\-chain ", " \-fc
+Print full chain when using \fB\-\-signcsr\fR
+.TP
+.BR \-\-ipv4 ", " \-4
+Resolve names to IPv4 addresses only
+.TP
+.BR \-\-ipv6 ", " \-6
+Resolve names to IPv6 addresses only
+.TP
+.BR \-\-domain ", " \-d " " \fIdomain.tld\fR
+Use specified domain name(s) instead of domains.txt entry (one certificate!)
+.TP
+.BR \-\-keep\-going ", " \-g
+Keep going after encountering an error while creating/renewing multiple
+certificates in cron mode
+.TP
+.BR \-\-force ", " \-x
+Force renew of certificate even if it is longer valid than value in RENEW_DAYS
+.TP
+.BR \-\-no\-lock ", " \-n
+Don't use lockfile (potentially dangerous!)
+.TP
+.BR \-\-lock\-suffix " " \fIexample.com\fR
+Suffix lockfile name with a string (useful for use with \-d)
+.TP
+.BR \-\-ocsp
+Sets option in CSR indicating OCSP stapling to be mandatory
+.TP
+.BR \-\-privkey ", " \-p " " \fIpath/to/key.pem\fR
+Use specified private key instead of account key (useful for revocation)
+.TP
+.BR \-\-config ", " \-f " " \fIpath/to/config\fR
+Use specified config file
+.TP
+.BR \-\-hook ", " \-k " " \fIpath/to/hook.sh\fR
+Use specified script for hooks
+.TP
+.BR \-\-out ", " \-o " " \fIcerts/directory\fR
+Output certificates into the specified directory
+.TP
+.BR \-\-challenge ", " \-t " " \fI[http\-01|dns\-01]\fR
+Which challenge should be used? Currently http\-01 and dns\-01 are supported
+.TP
+.BR \-\-algo ", " \-a " " \fI[rsa|prime256v1|secp384r1]\fR
+Which public key algorithm should be used? Supported: rsa, prime256v1 and
+secp384r1
+.SH DIAGNOSTICS
+The program exits 0 if everything was fine, 1 if an error occurred.
+.SH BUGS
+Please report any bugs that you may encounter at the project web site
+.UR https://github.com/lukas2511/dehydrated/issues
+.UE .
+.SH AUTHOR
+Dehydrated was written by Lukas Schauer. This man page was contributed by
+Daniel Molkentin.
+.SH COPYRIGHT
+Copyright 20015-2017 by Lukas Schauer and the respective contributors.
+Provided under the MIT License. See the LICENSE file that accompanies the
+distribution for licensing information.
+.SH SEE ALSO
+Full documentation along with configuration examples are provided in the 
\fIdocs\fR
+directory of the distribution, or at
+.UR https://github.com/lukas2511/dehydrated/tree/master/docs
+.UE .
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dehydrated-0.4.0/docs/dns-verification.md 
new/dehydrated-0.5.0/docs/dns-verification.md
--- old/dehydrated-0.4.0/docs/dns-verification.md       2017-02-05 
15:33:17.000000000 +0100
+++ new/dehydrated-0.5.0/docs/dns-verification.md       2018-01-13 
20:08:12.000000000 +0100
@@ -2,9 +2,18 @@
 
 This script also supports the new `dns-01`-type verification. This type of 
verification requires you to be able to create a specific `TXT` DNS record for 
each hostname included in the certificate.
 
-You need a hook script that deploys the challenge to your DNS server!
+You need a hook script that deploys the challenge to your DNS server.
 
-The hook script (indicated in the config file or the --hook/-k command line 
argument) gets four arguments: an operation name (clean_challenge, 
deploy_challenge, deploy_cert, invalid_challenge or request_failure) and some 
operands for that. For deploy_challenge $2 is the domain name for which the 
certificate is required, $3 is a "challenge token" (which is not needed for 
dns-01), and $4 is a token which needs to be inserted in a TXT record for the 
domain.
+The hook script (indicated in the config file or the `--hook/-k` command line 
argument) gets four arguments:
+
+$1 an operation name (`clean_challenge`, `deploy_challenge`, `deploy_cert`, 
`invalid_challenge` or `request_failure`) and some operands for that.
+For `deploy_challenge` 
+
+$2 is the domain name for which the certificate is required, 
+
+$3 is a "challenge token" (which is not needed for dns-01), and 
+
+$4 is a token which needs to be inserted in a TXT record for the domain.
 
 Typically, you will need to split the subdomain name in two, the subdomain 
name and the domain name separately. For example, for "my.example.com", you'll 
need "my" and "example.com" separately. You then have to prefix 
"_acme-challenge." before the subdomain name, as in "_acme-challenge.my" and 
set a TXT record for that on the domain (e.g. "example.com") which has the 
value supplied in $4
 
@@ -13,10 +22,10 @@
 _acme-challenge.my IN    TXT    $4
 ```
 
-That could be done manually (as most providers don't have a DNS API), by 
having your hook script echo $1, $2 and $4 and then wait (read -s -r -e < 
/dev/tty) - give it a little time to get into their DNS system. Usually 
providers give you a boxes to put "_acme-challenge.my" and the token value in, 
and a dropdown to choose the record type, TXT. 
+That could be done manually (as most providers don't have a DNS API), by 
having your hook script echo $1, $2 and $4 and then wait (`read -s -r -e < 
/dev/tty`) - give it a little time to get into their DNS system. Usually 
providers give you a boxes to put "_acme-challenge.my" and the token value in, 
and a dropdown to choose the record type, TXT. 
 
 Or when you do have a DNS API, pass the details accordingly to achieve the 
same thing.
 
-You can delete the TXT record when called with operation clean_challenge, when 
$2 is also the domain name.
+You can delete the TXT record when called with operation `clean_challenge`, 
when $2 is also the domain name.
 
 Here are some examples: [Examples for DNS-01 
hooks](https://github.com/lukas2511/dehydrated/wiki/Examples-for-DNS-01-hooks)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dehydrated-0.4.0/docs/domains_txt.md 
new/dehydrated-0.5.0/docs/domains_txt.md
--- old/dehydrated-0.4.0/docs/domains_txt.md    2017-02-05 15:33:17.000000000 
+0100
+++ new/dehydrated-0.5.0/docs/domains_txt.md    2018-01-13 20:08:12.000000000 
+0100
@@ -7,7 +7,13 @@
 ```text
 example.com www.example.com
 example.net www.example.net wiki.example.net
+example.net www.example.net wiki.example.net > certalias
 ```
 
 This states that there should be two certificates `example.com` and 
`example.net`,
 with the other domains in the corresponding line being their alternative names.
+
+You can define an alias for your certificate which will (instead of the 
primary domain) be
+used as directory name under your certdir and for a per-certificate lookup.
+This allows multiple certificates with identical sets of domains but different 
configuration
+to exist.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dehydrated-0.4.0/docs/examples/config 
new/dehydrated-0.5.0/docs/examples/config
--- old/dehydrated-0.4.0/docs/examples/config   2017-02-05 15:33:17.000000000 
+0100
+++ new/dehydrated-0.5.0/docs/examples/config   2018-01-13 20:08:12.000000000 
+0100
@@ -10,6 +10,12 @@
 # Default values of this config are in comments        #
 ########################################################
 
+# Which user should dehydrated run as? This will be implictly enforced when 
running as root
+#DEHYDRATED_USER=
+
+# Which group should dehydrated run as? This will be implictly enforced when 
running as root
+#DEHYDRATED_GROUP=
+
 # Resolve names to addresses of IP version only. (curl)
 # supported values: 4, 6
 # default: <unset>
@@ -54,6 +60,12 @@
 # Path to openssl config file (default: <unset> - tries to figure out system 
default)
 #OPENSSL_CNF=
 
+# Path to OpenSSL binary (default: "openssl")
+#OPENSSL="openssl"
+
+# Extra options passed to the curl binary (default: <unset>)
+#CURL_OPTS=
+
 # Program or function called in certain situations
 #
 # After generating the challenge-response, or after failed challenge (in this 
case altname is empty)
@@ -89,3 +101,12 @@
 
 # Option to add CSR-flag indicating OCSP stapling to be mandatory (default: no)
 #OCSP_MUST_STAPLE="no"
+
+# Fetch OCSP responses (default: no)
+#OCSP_FETCH="no"
+
+# Issuer chain cache directory (default: $BASEDIR/chains)
+#CHAINCACHE="${BASEDIR}/chains"
+
+# Automatic cleanup (default: no)
+#AUTO_CLEANUP="no"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dehydrated-0.4.0/docs/examples/hook.sh 
new/dehydrated-0.5.0/docs/examples/hook.sh
--- old/dehydrated-0.4.0/docs/examples/hook.sh  2017-02-05 15:33:17.000000000 
+0100
+++ new/dehydrated-0.5.0/docs/examples/hook.sh  2018-01-13 20:08:12.000000000 
+0100
@@ -91,7 +91,7 @@
 request_failure() {
     local STATUSCODE="${1}" REASON="${2}" REQTYPE="${3}"
 
-    # This hook is called when a HTTP request fails (e.g., when the ACME
+    # This hook is called when an HTTP request fails (e.g., when the ACME
     # server is busy, returns an error, etc). It will be called upon any
     # response code that does not start with '2'. Useful to alert admins
     # about problems with requests.
@@ -105,14 +105,21 @@
     #   The kind of request that was made (GET, POST...)
 }
 
+startup_hook() {
+  # This hook is called before the cron command to do some initial tasks
+  # (e.g. starting a webserver).
+
+  :
+}
+
 exit_hook() {
-  # This hook is called at the end of a dehydrated command and can be used
-  # to do some final (cleanup or other) tasks.
+  # This hook is called at the end of the cron command and can be used to
+  # do some final (cleanup or other) tasks.
 
   :
 }
 
 HANDLER="$1"; shift
-if [[ "${HANDLER}" =~ 
^(deploy_challenge|clean_challenge|deploy_cert|unchanged_cert|invalid_challenge|request_failure|exit_hook)$
 ]]; then
+if [[ "${HANDLER}" =~ 
^(deploy_challenge|clean_challenge|deploy_cert|unchanged_cert|invalid_challenge|request_failure|startup_hook|exit_hook)$
 ]]; then
   "$HANDLER" "$@"
 fi
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dehydrated-0.4.0/docs/per-certificate-config.md 
new/dehydrated-0.5.0/docs/per-certificate-config.md
--- old/dehydrated-0.4.0/docs/per-certificate-config.md 2017-02-05 
15:33:17.000000000 +0100
+++ new/dehydrated-0.5.0/docs/per-certificate-config.md 2018-01-13 
20:08:12.000000000 +0100
@@ -16,3 +16,10 @@
 - WELLKNOWN
 - OPENSSL_CNF
 - RENEW_DAYS
+
+## DOMAINS_D
+
+If `DOMAINS_D` is set, dehydrated will use it for your per-certificate 
configurations.
+Instead of `certs/example.org/config` it will look for a configuration under 
`DOMAINS_D/example.org`.
+
+If an alias is set, it will be used instead of the primary domain name.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dehydrated-0.4.0/docs/troubleshooting.md 
new/dehydrated-0.5.0/docs/troubleshooting.md
--- old/dehydrated-0.4.0/docs/troubleshooting.md        2017-02-05 
15:33:17.000000000 +0100
+++ new/dehydrated-0.5.0/docs/troubleshooting.md        2018-01-13 
20:08:12.000000000 +0100
@@ -31,8 +31,8 @@
 
 There are a few factors that could result in invalid challenges.
 
-If you are using http validation make sure that the path you have configured 
with WELLKNOWN is readable under your domain.
+If you are using HTTP validation make sure that the path you have configured 
with WELLKNOWN is readable under your domain.
 
-To test this create a file (e.g. `test.txt`) in that directory and try opening 
it with your browser: `http://example.org/.well-known/acme-challenge/test.txt`.
+To test this create a file (e.g. `test.txt`) in that directory and try opening 
it with your browser: `http://example.org/.well-known/acme-challenge/test.txt`. 
Note that if you have an IPv6 address, the challenge connection will be on 
IPv6. Be sure that you test HTTP connections on both IPv4 and IPv6. Checking 
the test file in your browser is often not sufficient because the browser just 
fails over to IPv4.
 
-If you get any error you'll have to fix your webserver configuration.
+If you get any error you'll have to fix your web server configuration.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dehydrated-0.4.0/docs/wellknown.md 
new/dehydrated-0.5.0/docs/wellknown.md
--- old/dehydrated-0.4.0/docs/wellknown.md      2017-02-05 15:33:17.000000000 
+0100
+++ new/dehydrated-0.5.0/docs/wellknown.md      2018-01-13 20:08:12.000000000 
+0100
@@ -65,3 +65,14 @@
  "/.well-known/acme-challenge/" => "/var/www/dehydrated/",
 )
 ```
+
+
+### Hiawatha example config
+
+With Hiawatha just add an alias to your config file for each VirtualHost and 
it should work:
+```hiawatha
+VirtualHost {
+    Hostname = example.tld subdomain.mywebsite.tld
+    Alias = /.well-known/acme-challenge:/var/www/dehydrated
+}
+```

++++++ dehydrated.keyring ++++++
pub   2048R/F438F333 2013-04-05
uid       [ unknown] Lukas Schauer <[email protected]>
uid       [ unknown] Lukas Schauer <[email protected]>
sub   2048R/57805524 2013-04-05

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2

mQENBFFfGhMBCADuxAL1vqC7J1AmxMrFGxobyPaY9tmUEueRF+JuUJlk48qSbcWg
zAMEprSgw3HY/15Galu/7g8KxXnlN4WO2vgA6eu1CYx3CoukJ8dc/m6hEMxqwsIW
H/1sI7P2hLGB/6YC3MqgpyZxrXzS3coe/JLLkeOtcnBgeT1VpGnodSEKsK4unkfV
cmheLuF+zMb0t1DFtd//Ka99XtoF7HXW6p/n8NjiAXKkEkTWf+0qsOIzar3Hl7QE
dnEMK1EjDbrqNufTe+TyvM9hVMyDTptvA0EDOj+5Jmt29pWpriOgUgm2D1JgZi9b
YmGnTo149q5bUzfLvsTDI0IS7ClxXIES/dfXABEBAAG0IEx1a2FzIFNjaGF1ZXIg
PGx1a2FzQHNjaGF1ZXIuc28+iQE5BBMBAgAjBQJSHiDfAhsDBwsJCAcDAgEGFQgC
CQoLBBYCAwECHgECF4AACgkQnE2+bPQ48zPRxgf/Y1pJ9H6uB6rmCa3VHoxhvLkV
ruUSpI+JXNUhwpUWUKNE1yk78jmjRhMMZf7UMYifyGkuK/0/cErktr5j8kqJ2r60
hOnmkC3jEq5H0hKfGzhosenUvzR9cENYzgnm/4BNWWz1I16jkWRcEGjeC8y033U3
Tjrtc6f0jLe7R6LzospUCWKzp8WUWgTgqpAyjJY6I44Y6QpTjmRF6t1Nz2yRxxf2
NAbOQWkSTueusgLVYyvqLZ51u3fsuDJxbQiBnNt0ZGYSDBKrs59Rvg0Xj1cBv1t7
SrzHuwyiiCQsEaLMvYCygk7qRmZBZ6PKA0gE8oYIr5f10Kx0Mjqnrs8wmpegiLQj
THVrYXMgU2NoYXVlciA8bHVrYXMyNTExQHh4cHJvLm5ldD6JATgEEwECACIFAlFf
GhMCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEJxNvmz0OPMzHXoH/jCy
wwo+W3hy7WAzaKqgnIjRfMQD63OFSwrPI8P7mU0WWrxURwET4C/i+eYHIZYPVaP0
HvdMMcpgSbBZ0sAW+gtv2qMtL+kB4s+FGVchV4lfh4q5w4EDRknuCEpD5bj7NsOT
ROvGu0gSvGbGG/EFLJuhrkct5s7ESH5sWonxstk6Ea9L5STR4PGH6swTq0WggbMq
VFQuWOkjw6KpQOeFTp9koQl3R6P6I0uqe6tVLKJD/nSTKbMYPMZX9Q+TvzqRSRlH
wL509ZIZV4IzdDFXGM28xvC7KIifbxEzWHVci2afdqbVNH2MBhgHt/SIaW8xBab2
wnd45rkdHuoK2wBPlPu5AQ0EUV8aEwEIAM1d0x6B/PUlXfUzkTlYtFmfm67OOPW2
EImld+53RgVc/HGY9RyYP0YwxNs1mjWalzJYV6/aQ9xke/Dz0pLYwIl2c1TCzwin
qgymkR17krDJ/+hj2GZBsiEHlMDbWskgwIc7WldhcmxsOvsvRrHSCcw7ZFD+iA9l
6XJoUrtP9QhJLaj6WoX0fU377t3me6hji5387pzYoDKiq8cfJu4q/K6oB42kmo+L
PVub+DvBBZPDakDnE46v0LfbgvPqjaVxM2KHjqllepk1CIOAbUbtyC9kVuavDgnI
OMe1couHsy0+7fXeQE0xMLPjGGZAXt6OVI8o/1IbgA2EbiVR225Tu2cAEQEAAYkB
HwQYAQIACQUCUV8aEwIbDAAKCRCcTb5s9DjzM09cCACGdENt71lx56EjzH6W5o/F
OYHHTm4ewcfgGSHWmdScq8gOI414kBkOg9ds9IMQt5hp60hXteSxG1l0qxEXbMX7
cO5FNnjer/ikcwPDS6eZ2a5Gni/h/UFRnVYcw2c+7UAAgouswhwqbkVUrRMDodG2
DT05fQIdgfbQLUBW5qFToS/CXNzvG47jqBEUS/mFMtZgF2+myU2buMlIXmarTi0K
EYMt0geGXhpS2DN9iQrQzQ8gjVz/EBgdHbEZOsHW4JMQaycYvouPFVqCIcZoN0s8
c9AilqEu9V8XLLWA0zRVC8Fp6m/ZpMX8t2kVQdBKMHb1NUz0b+uHynANCRQUGKIg
=2fWi
-----END PGP PUBLIC KEY BLOCK-----

Reply via email to