Commit 4ab67861 authored by nytral's avatar nytral
Browse files

Merge remote-tracking branch 'upstream/master'

parents e82ea94b eaad34a6
<!--
请确保已经更新到最新的代码, 然后贴上来 `--debug 2` 的调试输出. 没有调试输出,我帮不了你.
如何调试 https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh
If it is a bug report:
- make sure you are able to repro it on the latest released version.
......@@ -8,13 +10,11 @@ You can install the latest version by: `acme.sh --upgrade`
- Refer to the [WIKI](https://wiki.acme.sh).
- Debug info [Debug](https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh).
-->
Steps to reproduce
------------------
Debug log
-----------------
......
......@@ -26,14 +26,13 @@ install:
_old_path="$PATH";
echo "PATH=$PATH";
export PATH="";
export OPENSSL_BIN="/usr/local/openssl";
export ACME_OPENSSL_BIN="/usr/local/openssl";
openssl version 2>&1 || true;
$OPENSSL_BIN version 2>&1 || true;
$ACME_OPENSSL_BIN version 2>&1 || true;
export PATH="$_old_path";
fi
script:
- echo "TEST_LOCAL=$TEST_LOCAL"
- echo "NGROK_TOKEN=$(echo "$NGROK_TOKEN" | wc -c)"
- command -V openssl && openssl version
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then curl -sSL $SHFMT_URL -o ~/shfmt ; fi
......@@ -44,8 +43,8 @@ script:
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck **/*.sh && echo "shellcheck OK" ; fi
- cd ..
- git clone https://github.com/Neilpang/acmetest.git && cp -r acme.sh acmetest/ && cd acmetest
- if [ "$TRAVIS_OS_NAME" = "linux" -a "$NGROK_TOKEN" ]; then sudo NGROK_TOKEN="$NGROK_TOKEN" ./letest.sh ; fi
- if [ "$TRAVIS_OS_NAME" = "osx" -a "$NGROK_TOKEN" ]; then sudo NGROK_TOKEN="$NGROK_TOKEN" OPENSSL_BIN="$OPENSSL_BIN" ./letest.sh ; fi
- if [ "$TRAVIS_OS_NAME" = "linux" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ./letest.sh ; fi
- if [ "$TRAVIS_OS_NAME" = "osx" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ACME_OPENSSL_BIN="$ACME_OPENSSL_BIN" ./letest.sh ; fi
matrix:
......
......@@ -54,7 +54,9 @@ https://github.com/Neilpang/acmetest
- Webroot mode
- Standalone mode
- Apache mode
- Nginx mode ( Beta )
- DNS mode
- [Stateless mode](https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode)
# 1. How to install
......@@ -146,7 +148,7 @@ You **MUST** use this command to copy the certs to the target files, **DO NOT**
**Apache** example:
```bash
acme.sh --installcert -d example.com \
acme.sh --install-cert -d example.com \
--certpath /path/to/certfile/in/apache/cert.pem \
--keypath /path/to/keyfile/in/apache/key.pem \
--fullchainpath /path/to/fullchain/certfile/apache/fullchain.pem \
......@@ -155,7 +157,7 @@ acme.sh --installcert -d example.com \
**Nginx** example:
```bash
acme.sh --installcert -d example.com \
acme.sh --install-cert -d example.com \
--keypath /path/to/keyfile/in/nginx/key.pem \
--fullchainpath /path/to/fullchain/nginx/cert.pem \
--reloadcmd "service nginx force-reload"
......@@ -214,8 +216,27 @@ acme.sh --issue --apache -d example.com -d www.example.com -d cp.example.com
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
# 7. Use Nginx mode
# 7. Use DNS mode:
**(requires you to be root/sudoer, since it is required to interact with Nginx server)**
If you are running a web server, Apache or Nginx, it is recommended to use the `Webroot mode`.
Particularly, if you are running an nginx server, you can use nginx mode instead. This mode doesn't write any files to your web root folder.
Just set string "nginx" as the second argument.
It will configure nginx server automatically to verify the domain and then restore the nginx config to the original version.
So, the config is not changed.
```
acme.sh --issue --nginx -d example.com -d www.example.com -d cp.example.com
```
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
# 8. Use DNS mode:
Support the `dns-01` challenge.
......@@ -246,7 +267,7 @@ acme.sh --renew -d example.com
Ok, it's finished.
# 8. Automatic DNS API integration
# 9. Automatic DNS API integration
If your DNS provider supports API access, we can use that API to automatically issue the certs.
......@@ -271,6 +292,9 @@ You don't have to do anything manually!
1. Alwaysdata.com API
1. Linode.com API
1. FreeDNS (https://freedns.afraid.org/)
1. cyon.ch
1. Domain-Offensive/Resellerinterface/Domainrobot API
1. Gandi LiveDNS API
**More APIs coming soon...**
......@@ -279,7 +303,7 @@ If your DNS provider is not on the supported list above, you can write your own
For more details: [How to use DNS API](dnsapi)
# 9. Issue ECC certificates
# 10. Issue ECC certificates
`Let's Encrypt` can now issue **ECDSA** certificates.
......@@ -310,7 +334,7 @@ Valid values are:
3. **ec-521 (secp521r1, "ECDSA P-521", which is not supported by Let's Encrypt yet.)**
# 10. How to renew the issued certs
# 11. How to renew the issued certs
No, you don't need to renew the certs manually. All the certs will be renewed automatically every **60** days.
......@@ -327,7 +351,7 @@ acme.sh --renew -d example.com --force --ecc
```
# 11. How to upgrade `acme.sh`
# 12. How to upgrade `acme.sh`
acme.sh is in constant development, so it's strongly recommended to use the latest code.
......@@ -352,26 +376,26 @@ acme.sh --upgrade --auto-upgrade 0
```
# 12. Issue a cert from an existing CSR
# 13. Issue a cert from an existing CSR
https://github.com/Neilpang/acme.sh/wiki/Issue-a-cert-from-existing-CSR
# Under the Hood
# 14. Under the Hood
Speak ACME language using shell, directly to "Let's Encrypt".
TODO:
# Acknowledgments
# 15. Acknowledgments
1. Acme-tiny: https://github.com/diafygi/acme-tiny
2. ACME protocol: https://github.com/ietf-wg-acme/acme
3. Certbot: https://github.com/certbot/certbot
# License & Others
# 16. License & Others
License is GPLv3
......@@ -380,8 +404,9 @@ Please Star and Fork me.
[Issues](https://github.com/Neilpang/acme.sh/issues) and [pull requests](https://github.com/Neilpang/acme.sh/pulls) are welcome.
# Donate
# 17. Donate
Your donation makes **acme.sh** better:
1. PayPal: donate@acme.sh
1. PayPal/Alipay(支付宝)/Wechat(微信): [https://donate.acme.sh/](https://donate.acme.sh/)
[Donate List](https://github.com/Neilpang/acme.sh/wiki/Donate-list)
#!/usr/bin/env sh
VER=2.6.6
VER=2.6.7
PROJECT_NAME="acme.sh"
......@@ -41,8 +41,14 @@ NO_VALUE="no"
W_TLS="tls"
MODE_STATELESS="stateless"
STATE_VERIFIED="verified_ok"
NGINX="nginx:"
NGINX_START="#ACME_NGINX_START"
NGINX_END="#ACME_NGINX_END"
BEGIN_CSR="-----BEGIN CERTIFICATE REQUEST-----"
END_CSR="-----END CERTIFICATE REQUEST-----"
......@@ -59,8 +65,39 @@ LOG_LEVEL_2=2
LOG_LEVEL_3=3
DEFAULT_LOG_LEVEL="$LOG_LEVEL_1"
DEBUG_LEVEL_1=1
DEBUG_LEVEL_2=2
DEBUG_LEVEL_3=3
DEBUG_LEVEL_DEFAULT=$DEBUG_LEVEL_1
DEBUG_LEVEL_NONE=0
HIDDEN_VALUE="[hidden](please add '--output-insecure' to see this value)"
SYSLOG_ERROR="user.error"
SYSLOG_INFO="user.info"
SYSLOG_DEBUG="user.debug"
#error
SYSLOG_LEVEL_ERROR=3
#info
SYSLOG_LEVEL_INFO=6
#debug
SYSLOG_LEVEL_DEBUG=7
#debug2
SYSLOG_LEVEL_DEBUG_2=8
#debug3
SYSLOG_LEVEL_DEBUG_3=9
SYSLOG_LEVEL_DEFAULT=$SYSLOG_LEVEL_ERROR
#none
SYSLOG_LEVEL_NONE=0
_DEBUG_WIKI="https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh"
_PREPARE_LINK="https://github.com/Neilpang/acme.sh/wiki/Install-preparations"
_STATELESS_WIKI="https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode"
__INTERACTIVE=""
if [ -t 1 ]; then
__INTERACTIVE="1"
......@@ -100,11 +137,11 @@ _printargs() {
_dlg_versions() {
echo "Diagnosis versions: "
echo "openssl:$OPENSSL_BIN"
if _exists "$OPENSSL_BIN"; then
$OPENSSL_BIN version 2>&1
echo "openssl:$ACME_OPENSSL_BIN"
if _exists "$ACME_OPENSSL_BIN"; then
$ACME_OPENSSL_BIN version 2>&1
else
echo "$OPENSSL_BIN doesn't exists."
echo "$ACME_OPENSSL_BIN doesn't exists."
fi
echo "apache:"
......@@ -122,6 +159,16 @@ _dlg_versions() {
fi
}
#class
_syslog() {
if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" = "$SYSLOG_LEVEL_NONE" ]; then
return
fi
_logclass="$1"
shift
logger -i -t "$PROJECT_NAME" -p "$_logclass" "$(_printargs "$@")" >/dev/null 2>&1
}
_log() {
[ -z "$LOG_FILE" ] && return
_printargs "$@" >>"$LOG_FILE"
......@@ -129,10 +176,14 @@ _log() {
_info() {
_log "$@"
if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_INFO" ]; then
_syslog "$SYSLOG_INFO" "$@"
fi
_printargs "$@"
}
_err() {
_syslog "$SYSLOG_ERROR" "$@"
_log "$@"
if [ -z "$NO_TIMESTAMP" ] || [ "$NO_TIMESTAMP" = "0" ]; then
printf -- "%s" "[$(date)] " >&2
......@@ -152,30 +203,99 @@ _usage() {
}
_debug() {
if [ -z "$LOG_LEVEL" ] || [ "$LOG_LEVEL" -ge "$LOG_LEVEL_1" ]; then
if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_1" ]; then
_log "$@"
fi
if [ -z "$DEBUG" ]; then
return
if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG" ]; then
_syslog "$SYSLOG_DEBUG" "$@"
fi
if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_1" ]; then
_printargs "$@" >&2
fi
}
#output the sensitive messages
_secure_debug() {
if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_1" ]; then
if [ "$OUTPUT_INSECURE" = "1" ]; then
_log "$@"
else
_log "$1" "$HIDDEN_VALUE"
fi
fi
if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG" ]; then
_syslog "$SYSLOG_DEBUG" "$1" "$HIDDEN_VALUE"
fi
if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_1" ]; then
if [ "$OUTPUT_INSECURE" = "1" ]; then
_printargs "$@" >&2
else
_printargs "$1" "$HIDDEN_VALUE" >&2
fi
fi
}
_debug2() {
if [ "$LOG_LEVEL" ] && [ "$LOG_LEVEL" -ge "$LOG_LEVEL_2" ]; then
if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_2" ]; then
_log "$@"
fi
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
_debug "$@"
if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG_2" ]; then
_syslog "$SYSLOG_DEBUG" "$@"
fi
if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then
_printargs "$@" >&2
fi
}
_secure_debug2() {
if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_2" ]; then
if [ "$OUTPUT_INSECURE" = "1" ]; then
_log "$@"
else
_log "$1" "$HIDDEN_VALUE"
fi
fi
if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG_2" ]; then
_syslog "$SYSLOG_DEBUG" "$1" "$HIDDEN_VALUE"
fi
if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then
if [ "$OUTPUT_INSECURE" = "1" ]; then
_printargs "$@" >&2
else
_printargs "$1" "$HIDDEN_VALUE" >&2
fi
fi
}
_debug3() {
if [ "$LOG_LEVEL" ] && [ "$LOG_LEVEL" -ge "$LOG_LEVEL_3" ]; then
if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_3" ]; then
_log "$@"
fi
if [ "$DEBUG" ] && [ "$DEBUG" -ge "3" ]; then
_debug "$@"
if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG_3" ]; then
_syslog "$SYSLOG_DEBUG" "$@"
fi
if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_3" ]; then
_printargs "$@" >&2
fi
}
_secure_debug3() {
if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_3" ]; then
if [ "$OUTPUT_INSECURE" = "1" ]; then
_log "$@"
else
_log "$1" "$HIDDEN_VALUE"
fi
fi
if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG_3" ]; then
_syslog "$SYSLOG_DEBUG" "$1" "$HIDDEN_VALUE"
fi
if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_3" ]; then
if [ "$OUTPUT_INSECURE" = "1" ]; then
_printargs "$@" >&2
else
_printargs "$1" "$HIDDEN_VALUE" >&2
fi
fi
}
......@@ -358,8 +478,16 @@ _ascii_hex() {
#input:"abc"
#output: " 61 62 63"
_hex_dump() {
#in wired some system, the od command is missing.
if ! od -A n -v -t x1 | tr -d "\r\t" | tr -s " " | sed "s/ $//" | tr -d "\n" 2>/dev/null; then
if _exists od; then
od -A n -v -t x1 | tr -s " " | sed 's/ $//' | tr -d "\r\t\n"
elif _exists hexdump; then
_debug3 "using hexdump"
hexdump -v -e '/1 ""' -e '/1 " %02x" ""'
elif _exists xxd; then
_debug3 "using xxd"
xxd -ps -c 20 -i | sed "s/ 0x/ /g" | tr -d ",\n" | tr -s " "
else
_debug3 "using _ascii_hex"
str=$(cat)
_ascii_hex "$str"
fi
......@@ -652,19 +780,19 @@ _base64() {
[ "" ] #urgly
if [ "$1" ]; then
_debug3 "base64 multiline:'$1'"
$OPENSSL_BIN base64 -e
$ACME_OPENSSL_BIN base64 -e
else
_debug3 "base64 single line."
$OPENSSL_BIN base64 -e | tr -d '\r\n'
$ACME_OPENSSL_BIN base64 -e | tr -d '\r\n'
fi
}
#Usage: multiline
_dbase64() {
if [ "$1" ]; then
$OPENSSL_BIN base64 -d -A
$ACME_OPENSSL_BIN base64 -d -A
else
$OPENSSL_BIN base64 -d
$ACME_OPENSSL_BIN base64 -d
fi
}
......@@ -681,9 +809,9 @@ _digest() {
if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ] || [ "$alg" = "md5" ]; then
if [ "$outputhex" ]; then
$OPENSSL_BIN dgst -"$alg" -hex | cut -d = -f 2 | tr -d ' '
$ACME_OPENSSL_BIN dgst -"$alg" -hex | cut -d = -f 2 | tr -d ' '
else
$OPENSSL_BIN dgst -"$alg" -binary | _base64
$ACME_OPENSSL_BIN dgst -"$alg" -binary | _base64
fi
else
_err "$alg is not supported yet"
......@@ -706,9 +834,9 @@ _hmac() {
if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ]; then
if [ "$outputhex" ]; then
$OPENSSL_BIN dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" | cut -d = -f 2 | tr -d ' '
($ACME_OPENSSL_BIN dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" 2>/dev/null || $ACME_OPENSSL_BIN dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)") | cut -d = -f 2 | tr -d ' '
else
$OPENSSL_BIN dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" -binary
$ACME_OPENSSL_BIN dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" -binary 2>/dev/null || $ACME_OPENSSL_BIN dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)" -binary
fi
else
_err "$alg is not supported yet"
......@@ -727,7 +855,7 @@ _sign() {
return 1
fi
_sign_openssl="$OPENSSL_BIN dgst -sign $keyfile "
_sign_openssl="$ACME_OPENSSL_BIN dgst -sign $keyfile "
if [ "$alg" = "sha256" ]; then
_sign_openssl="$_sign_openssl -$alg"
else
......@@ -738,7 +866,7 @@ _sign() {
if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
$_sign_openssl | _base64
elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
if ! _signedECText="$($_sign_openssl | $OPENSSL_BIN asn1parse -inform DER)"; then
if ! _signedECText="$($_sign_openssl | $ACME_OPENSSL_BIN asn1parse -inform DER)"; then
_err "Sign failed: $_sign_openssl"
_err "Key file: $keyfile"
_err "Key content:$(wc -l <"$keyfile") lises"
......@@ -799,12 +927,21 @@ _createkey() {
_debug "Use length $length"
if ! touch "$f" >/dev/null 2>&1; then
_f_path="$(dirname "$f")"
_debug _f_path "$_f_path"
if ! mkdir -p "$_f_path"; then
_err "Can not create path: $_f_path"
return 1
fi
fi
if _isEccKey "$length"; then
_debug "Using ec name: $eccname"
$OPENSSL_BIN ecparam -name "$eccname" -genkey 2>/dev/null >"$f"
$ACME_OPENSSL_BIN ecparam -name "$eccname" -genkey 2>/dev/null >"$f"
else
_debug "Using RSA: $length"
$OPENSSL_BIN genrsa "$length" 2>/dev/null >"$f"
$ACME_OPENSSL_BIN genrsa "$length" 2>/dev/null >"$f"
fi
if [ "$?" != "0" ]; then
......@@ -890,7 +1027,11 @@ _createcsr() {
_csr_cn="$(_idn "$domain")"
_debug2 _csr_cn "$_csr_cn"
$OPENSSL_BIN req -new -sha256 -key "$csrkey" -subj "/CN=$_csr_cn" -config "$csrconf" -out "$csr"
if _contains "$(uname -a)" "MINGW"; then
$ACME_OPENSSL_BIN req -new -sha256 -key "$csrkey" -subj "//CN=$_csr_cn" -config "$csrconf" -out "$csr"
else
$ACME_OPENSSL_BIN req -new -sha256 -key "$csrkey" -subj "/CN=$_csr_cn" -config "$csrconf" -out "$csr"
fi
}
#_signcsr key csr conf cert
......@@ -901,7 +1042,7 @@ _signcsr() {
cert="$4"
_debug "_signcsr"
_msg="$($OPENSSL_BIN x509 -req -days 365 -in "$csr" -signkey "$key" -extensions v3_req -extfile "$conf" -out "$cert" 2>&1)"
_msg="$($ACME_OPENSSL_BIN x509 -req -days 365 -in "$csr" -signkey "$key" -extensions v3_req -extfile "$conf" -out "$cert" 2>&1)"
_ret="$?"
_debug "$_msg"
return $_ret
......@@ -914,7 +1055,7 @@ _readSubjectFromCSR() {
_usage "_readSubjectFromCSR mycsr.csr"
return 1
fi
$OPENSSL_BIN req -noout -in "$_csrfile" -subject | _egrep_o "CN=.*" | cut -d = -f 2 | cut -d / -f 1 | tr -d '\n'
$ACME_OPENSSL_BIN req -noout -in "$_csrfile" -subject | _egrep_o "CN *=.*" | cut -d = -f 2 | cut -d / -f 1 | tr -d '\n'
}
#_csrfile
......@@ -929,7 +1070,7 @@ _readSubjectAltNamesFromCSR() {
_csrsubj="$(_readSubjectFromCSR "$_csrfile")"
_debug _csrsubj "$_csrsubj"
_dnsAltnames="$($OPENSSL_BIN req -noout -text -in "$_csrfile" | grep "^ *DNS:.*" | tr -d ' \n')"
_dnsAltnames="$($ACME_OPENSSL_BIN req -noout -text -in "$_csrfile" | grep "^ *DNS:.*" | tr -d ' \n')"
_debug _dnsAltnames "$_dnsAltnames"
if _contains "$_dnsAltnames," "DNS:$_csrsubj,"; then
......@@ -950,13 +1091,13 @@ _readKeyLengthFromCSR() {
return 1
fi
_outcsr="$($OPENSSL_BIN req -noout -text -in "$_csrfile")"
_outcsr="$($ACME_OPENSSL_BIN req -noout -text -in "$_csrfile")"
if _contains "$_outcsr" "Public Key Algorithm: id-ecPublicKey"; then
_debug "ECC CSR"
echo "$_outcsr" | _egrep_o "^ *ASN1 OID:.*" | cut -d ':' -f 2 | tr -d ' '
else
_debug "RSA CSR"
echo "$_outcsr" | _egrep_o "^ *Public-Key:.*" | cut -d '(' -f 2 | cut -d ' ' -f 1
echo "$_outcsr" | _egrep_o "(^ *|^RSA )Public.Key:.*" | cut -d '(' -f 2 | cut -d ' ' -f 1
fi
}
......@@ -1004,9 +1145,9 @@ toPkcs() {
_initpath "$domain" "$_isEcc"
if [ "$pfxPassword" ]; then
$OPENSSL_BIN pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH" -password "pass:$pfxPassword"
$ACME_OPENSSL_BIN pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH" -password "pass:$pfxPassword"
else
$OPENSSL_BIN pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH"
$ACME_OPENSSL_BIN pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH"
fi
if [ "$?" = "0" ]; then
......@@ -1015,6 +1156,27 @@ toPkcs() {
}
#domain [isEcc]
toPkcs8() {
domain="$1"
if [ -z "$domain" ]; then
_usage "Usage: $PROJECT_ENTRY --toPkcs8 -d domain [--ecc]"
return 1
fi
_isEcc="$2"
_initpath "$domain" "$_isEcc"
$ACME_OPENSSL_BIN pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in "$CERT_KEY_PATH" -out "$CERT_PKCS8_PATH"
if [ "$?" = "0" ]; then
_info "Success, $CERT_PKCS8_PATH"
fi
}
#[2048]
createAccountKey() {
_info "Creating account key"
......@@ -1168,7 +1330,7 @@ _calcjwk() {
if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
_debug "RSA key"
pub_exp=$($OPENSSL_BIN rsa -in "$keyfile" -noout -text | grep "^publicExponent:" | cut -d '(' -f 2 | cut -d 'x' -f 2 | cut -d ')' -f 1)
pub_exp=$($ACME_OPENSSL_BIN rsa -in "$keyfile" -noout -text | grep "^publicExponent:" | cut -d '(' -f 2 | cut -d 'x' -f 2 | cut -d ')' -f 1)
if [ "${#pub_exp}" = "5" ]; then
pub_exp=0$pub_exp
fi
......@@ -1177,7 +1339,7 @@ _calcjwk() {
e=$(echo "$pub_exp" | _h2b | _base64)
_debug3 e "$e"
modulus=$($OPENSSL_BIN rsa -in "$keyfile" -modulus -noout | cut -d '=' -f 2)
modulus=$($ACME_OPENSSL_BIN rsa -in "$keyfile" -modulus -noout | cut -d '=' -f 2)
_debug3 modulus "$modulus"
n="$(printf "%s" "$modulus" | _h2b | _base64 | _url_replace)"
_debug3 n "$n"
......@@ -1190,12 +1352,12 @@ _calcjwk() {
JWK_HEADERPLACE_PART2='", "alg": "RS256", "jwk": '$jwk'}'
elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
_debug "EC key"
crv="$($OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep "^NIST CURVE:" | cut -d ":" -f 2 | tr -d " \r\n")"
crv="$($ACME_OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep "^NIST CURVE:" | cut -d ":" -f 2 | tr -d " \r\n")"
_debug3 crv "$crv"
if [ -z "$crv" ]; then
_debug "Let's try ASN1 OID"
crv_oid="$($OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep "^ASN1 OID:" | cut -d ":" -f 2 | tr -d " \r\n")"
crv_oid="$($ACME_OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep "^ASN1 OID:" | cut -d ":" -f 2 | tr -d " \r\n")"
_debug3 crv_oid "$crv_oid"
case "${crv_oid}" in
"prime256v1")
......@@ -1215,15 +1377,15 @@ _calcjwk() {
_debug3 crv "$crv"
fi
pubi="$($OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep -n pub: | cut -d : -f 1)"
pubi="$($ACME_OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep -n pub: | cut -d : -f 1)"
pubi=$(_math "$pubi" + 1)
_debug3 pubi "$pubi"
pubj="$($OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep -n "ASN1 OID:" | cut -d : -f 1)"
pubj="$($ACME_OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | grep -n "ASN1 OID:" | cut -d : -f 1)"
pubj=$(_math "$pubj" - 1)
_debug3 pubj "$pubj"
pubtext="$($OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | sed -n "$pubi,${pubj}p" | tr -d " \n\r")"
pubtext="$($ACME_OPENSSL_BIN ec -in "$keyfile" -noout -text 2>/dev/null | sed -n "$pubi,${pubj}p" | tr -d " \n\r")"
_debug3 pubtext "$pubtext"
xlen="$(printf "%s" "$pubtext" | tr -d ':' | wc -c)"
......@@ -1263,6 +1425,10 @@ _time() {
date -u "+%s"
}
_utc_date() {
date -u "+%Y-%m-%d %H:%M:%S"
}
_mktemp() {
if _exists mktemp; then
if mktemp 2>/dev/null; then
......@@ -1319,6 +1485,11 @@ _inithttp() {
fi
fi
#from wget 1.14: do not skip body on 404 error
if [ "$_ACME_WGET" ] && _contains "$($_ACME_WGET --help 2>&1)" "--content-on-error"; then
_ACME_WGET="$_ACME_WGET --content-on-error "
fi
__HTTP_INITIALIZED=1
}
......@@ -1339,7 +1510,7 @@ _post() {
_inithttp
if [ "$_ACME_CURL" ]; then
if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then
_CURL="$_ACME_CURL"
if [ "$HTTPS_INSECURE" ]; then
_CURL="$_CURL --insecure "
......@@ -1380,7 +1551,7 @@ _post() {
_ret="$?"
if [ "$_ret" = "8" ]; then
_ret=0
_debug "wget returns 8, the server returns a 'Bad request' respons, lets process the response later."
_debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later."
fi
if [ "$_ret" != "0" ]; then
_err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $_ret"
......@@ -1406,7 +1577,7 @@ _get() {
_inithttp
if [ "$_ACME_CURL" ]; then
if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then
_CURL="$_ACME_CURL"
if [ "$HTTPS_INSECURE" ]; then
_CURL="$_CURL --insecure "
......@@ -1443,9 +1614,9 @@ _get() {
$_WGET --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" -O - "$url"
fi
ret=$?
if [ "$_ret" = "8" ]; then
_ret=0
_debug "wget returns 8, the server returns a 'Bad request' respons, lets process the response later."
if [ "$ret" = "8" ]; then
ret=0
_debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later."
fi
if [ "$ret" != "0" ]; then
_err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $ret"
......@@ -1488,6 +1659,10 @@ _send_signed_request() {
payload64=$(printf "%s" "$payload" | _base64 | _url_replace)
_debug3 payload64 "$payload64"
MAX_REQUEST_RETRY_TIMES=5
_request_retry_times=0
while [ "${_request_retry_times}" -lt "$MAX_REQUEST_RETRY_TIMES" ]; do
_debug3 _request_retry_times "$_request_retry_times"
if [ -z "$_CACHED_NONCE" ]; then
_debug2 "Get nonce."
nonceurl="$API/directory"
......@@ -1528,12 +1703,12 @@ _send_signed_request() {
response="$(_post "$body" "$url" "$needbase64")"
_CACHED_NONCE=""
if [ "$?" != "0" ]; then
_err "Can not post to $url"
return 1
fi
_debug2 original "$response"
response="$(echo "$response" | _normalizeJson)"
responseHeaders="$(cat "$HTTP_HEADER")"
......@@ -1545,6 +1720,15 @@ _send_signed_request() {
_CACHED_NONCE="$(echo "$responseHeaders" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)"
if _contains "$response" "JWS has invalid anti-replay nonce"; then
_info "It seems the CA server is busy now, let's wait and retry."
_request_retry_times=$(_math "$_request_retry_times" + 1)
_sleep 5
continue
fi
break
done
}
#setopt "file" "opt" "=" "value" [";"]
......@@ -1568,20 +1752,20 @@ _setopt() {
__val="$(echo "$__val" | sed 's/&/\\&/g')"
fi
text="$(cat "$__conf")"
echo "$text" | sed "s|^$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf"
printf -- "%s\n" "$text" | sed "s|^$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf"
elif grep -n "^#$__opt$__sep" "$__conf" >/dev/null; then
if _contains "$__val" "&"; then
__val="$(echo "$__val" | sed 's/&/\\&/g')"
fi
text="$(cat "$__conf")"
echo "$text" | sed "s|^#$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf"
printf -- "%s\n" "$text" | sed "s|^#$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf"
else
_debug3 APP
echo "$__opt$__sep$__val$__end" >>"$__conf"
fi
_debug2 "$(grep -n "^$__opt$__sep" "$__conf")"
_debug3 "$(grep -n "^$__opt$__sep" "$__conf")"
}
#_save_conf file key value
......@@ -1684,6 +1868,14 @@ _startserver() {
_NC="$_NC -6"
fi
if [ "$Le_Listen_V4$Le_Listen_V6$ncaddr" ]; then
if ! _contains "$nchelp" "-4"; then
_err "The nc doesn't support '-4', '-6' or local-address, please install 'netcat-openbsd' and try again."
_err "See $(__green $_PREPARE_LINK)"
return 1
fi
fi
if echo "$nchelp" | grep "\-q[ ,]" >/dev/null; then
_NC="$_NC -q 1 -l $ncaddr"
else
......@@ -1807,7 +1999,7 @@ _starttlsserver() {
return 1
fi
__S_OPENSSL="$OPENSSL_BIN s_server -cert $TLS_CERT -key $TLS_KEY "
__S_OPENSSL="$ACME_OPENSSL_BIN s_server -cert $TLS_CERT -key $TLS_KEY "
if [ "$opaddr" ]; then
__S_OPENSSL="$__S_OPENSSL -accept $opaddr:$port"
else
......@@ -1986,8 +2178,8 @@ _initpath() {
CERT_HOME="$_DEFAULT_CERT_HOME"
fi
if [ -z "$OPENSSL_BIN" ]; then
OPENSSL_BIN="$DEFAULT_OPENSSL_BIN"
if [ -z "$ACME_OPENSSL_BIN" ] || [ ! -f "$ACME_OPENSSL_BIN" ] || [ ! -x "$ACME_OPENSSL_BIN" ]; then
ACME_OPENSSL_BIN="$DEFAULT_OPENSSL_BIN"
fi
if [ -z "$1" ]; then
......@@ -2013,6 +2205,10 @@ _initpath() {
_debug DOMAIN_PATH "$DOMAIN_PATH"
fi
if [ -z "$DOMAIN_BACKUP_PATH" ]; then
DOMAIN_BACKUP_PATH="$DOMAIN_PATH/backup"
fi
if [ -z "$DOMAIN_CONF" ]; then
DOMAIN_CONF="$DOMAIN_PATH/$domain.conf"
fi
......@@ -2039,6 +2235,9 @@ _initpath() {
if [ -z "$CERT_PFX_PATH" ]; then
CERT_PFX_PATH="$DOMAIN_PATH/$domain.pfx"
fi
if [ -z "$CERT_PKCS8_PATH" ]; then
CERT_PKCS8_PATH="$DOMAIN_PATH/$domain.pkcs8"
fi
if [ -z "$TLS_CONF" ]; then
TLS_CONF="$DOMAIN_PATH/tls.valdation.conf"
......@@ -2227,10 +2426,228 @@ Allow from all
return 0
}
#find the real nginx conf file
#backup
#set the nginx conf
#returns the real nginx conf file
_setNginx() {
_d="$1"
_croot="$2"
_thumbpt="$3"
if ! _exists "nginx"; then
_err "nginx command is not found."
return 1
fi
FOUND_REAL_NGINX_CONF=""
FOUND_REAL_NGINX_CONF_LN=""
BACKUP_NGINX_CONF=""
_debug _croot "$_croot"
_start_f="$(echo "$_croot" | cut -d : -f 2)"
_debug _start_f "$_start_f"
if [ -z "$_start_f" ]; then
_debug "find start conf from nginx command"
if [ -z "$NGINX_CONF" ]; then
NGINX_CONF="$(nginx -V 2>&1 | _egrep_o "--conf-path=[^ ]* " | tr -d " ")"
_debug NGINX_CONF "$NGINX_CONF"
NGINX_CONF="$(echo "$NGINX_CONF" | cut -d = -f 2)"
_debug NGINX_CONF "$NGINX_CONF"
if [ ! -f "$NGINX_CONF" ]; then
_err "'$NGINX_CONF' doesn't exist."
NGINX_CONF=""
return 1
fi
_debug "Found nginx conf file:$NGINX_CONF"
fi
_start_f="$NGINX_CONF"
fi
_debug "Start detect nginx conf for $_d from:$_start_f"
if ! _checkConf "$_d" "$_start_f"; then
"Can not find conf file for domain $d"
return 1
fi
_info "Found conf file: $FOUND_REAL_NGINX_CONF"
_ln=$FOUND_REAL_NGINX_CONF_LN
_debug "_ln" "$_ln"
_lnn=$(_math $_ln + 1)
_debug _lnn "$_lnn"
_start_tag="$(sed -n "$_lnn,${_lnn}p" "$FOUND_REAL_NGINX_CONF")"
_debug "_start_tag" "$_start_tag"
if [ "$_start_tag" = "$NGINX_START" ]; then
_info "The domain $_d is already configured, skip"
FOUND_REAL_NGINX_CONF=""
return 0
fi
mkdir -p "$DOMAIN_BACKUP_PATH"
_backup_conf="$DOMAIN_BACKUP_PATH/$_d.nginx.conf"
_debug _backup_conf "$_backup_conf"
BACKUP_NGINX_CONF="$_backup_conf"
_info "Backup $FOUND_REAL_NGINX_CONF to $_backup_conf"
if ! cp "$FOUND_REAL_NGINX_CONF" "$_backup_conf"; then
_err "backup error."
FOUND_REAL_NGINX_CONF=""
return 1
fi
_info "Check the nginx conf before setting up."
if ! _exec "nginx -t" >/dev/null; then
_exec_err
return 1
fi
_info "OK, Set up nginx config file"
if ! sed -n "1,${_ln}p" "$_backup_conf" >"$FOUND_REAL_NGINX_CONF"; then
cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF"
_err "write nginx conf error, but don't worry, the file is restored to the original version."
return 1
fi
echo "$NGINX_START
location ~ \"^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)\$\" {
default_type text/plain;
return 200 \"\$1.$_thumbpt\";
}
#NGINX_START
" >>"$FOUND_REAL_NGINX_CONF"
if ! sed -n "${_lnn},99999p" "$_backup_conf" >>"$FOUND_REAL_NGINX_CONF"; then
cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF"
_err "write nginx conf error, but don't worry, the file is restored."
return 1
fi
_info "nginx conf is done, let's check it again."
if ! _exec "nginx -t" >/dev/null; then
_exec_err
_err "It seems that nginx conf was broken, let's restore."
cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF"
return 1
fi
_info "Reload nginx"
if ! _exec "nginx -s reload" >/dev/null; then
_exec_err
_err "It seems that nginx reload error, let's restore."
cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF"
return 1
fi
return 0
}
#d , conf
_checkConf() {
_d="$1"
_c_file="$2"
_debug "Start _checkConf from:$_c_file"
if [ ! -f "$2" ] && ! echo "$2" | grep '*$' >/dev/null && echo "$2" | grep '*' >/dev/null; then
_debug "wildcard"
for _w_f in $2; do
if _checkConf "$1" "$_w_f"; then
return 0
fi
done
#not found
return 1
elif [ -f "$2" ]; then
_debug "single"
if _isRealNginxConf "$1" "$2"; then
_debug "$2 is found."
FOUND_REAL_NGINX_CONF="$2"
return 0
fi
if grep "^ *include *.*;" "$2" >/dev/null; then
_debug "Try include files"
for included in $(grep "^ *include *.*;" "$2" | sed "s/include //" | tr -d " ;"); do
_debug "check included $included"
if _checkConf "$1" "$included"; then
return 0
fi
done
fi
return 1
else
_debug "$2 not found."
return 1
fi
return 1
}
#d , conf
_isRealNginxConf() {
_debug "_isRealNginxConf $1 $2"
if [ -f "$2" ]; then
for _fln in $(grep -n "^ *server_name.* $1" "$2" | cut -d : -f 1); do
_debug _fln "$_fln"
if [ "$_fln" ]; then
_start=$(cat "$2" | _head_n "$_fln" | grep -n "^ *server *{" | _tail_n 1)
_debug "_start" "$_start"
_start_n=$(echo "$_start" | cut -d : -f 1)
_start_nn=$(_math $_start_n + 1)
_debug "_start_n" "$_start_n"
_debug "_start_nn" "$_start_nn"
_left="$(sed -n "${_start_nn},99999p" "$2")"
_debug2 _left "$_left"
if echo "$_left" | grep -n "^ *server *{" >/dev/null; then
_end=$(echo "$_left" | grep -n "^ *server *{" | _head_n 1)
_debug "_end" "$_end"
_end_n=$(echo "$_end" | cut -d : -f 1)
_debug "_end_n" "$_end_n"
_seg_n=$(echo "$_left" | sed -n "1,${_end_n}p")
else
_seg_n="$_left"
fi
_debug "_seg_n" "$_seg_n"
if [ "$(echo "$_seg_n" | _egrep_o "^ *ssl *on *;")" ]; then
_debug "ssl on, skip"
return 1
fi
FOUND_REAL_NGINX_CONF_LN=$_fln
return 0
fi
done
fi
return 1
}
#restore all the nginx conf
_restoreNginx() {
if [ -z "$NGINX_RESTORE_VLIST" ]; then
_debug "No need to restore nginx, skip."
return
fi
_debug "_restoreNginx"
_debug "NGINX_RESTORE_VLIST" "$NGINX_RESTORE_VLIST"
for ng_entry in $(echo "$NGINX_RESTORE_VLIST" | tr "$dvsep" ' '); do
_debug "ng_entry" "$ng_entry"
_nd=$(echo "$ng_entry" | cut -d "$sep" -f 1)
_ngconf=$(echo "$ng_entry" | cut -d "$sep" -f 2)
_ngbackupconf=$(echo "$ng_entry" | cut -d "$sep" -f 3)
_info "Restoring from $_ngbackupconf to $_ngconf"
cat "$_ngbackupconf" >"$_ngconf"
done
_info "Reload nginx"
if ! _exec "nginx -s reload" >/dev/null; then
_exec_err
_err "It seems that nginx reload error, please report bug."
return 1
fi
return 0
}
_clearup() {
_stopserver "$serverproc"
serverproc=""
_restoreApache
_restoreNginx
_clearupdns
if [ -z "$DEBUG" ]; then
rm -f "$TLS_CONF"
......@@ -2256,7 +2673,7 @@ _clearupdns() {
txt="$(printf "%s" "$keyauthorization" | _digest "sha256" | _url_replace)"
_debug txt "$txt"
if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then
_info "$d is already verified, skip $vtype."
_debug "$d is already verified, skip $vtype."
continue
fi
......@@ -2328,34 +2745,39 @@ _clearupwebbroot() {
}
_on_before_issue() {
_chk_web_roots="$1"
_chk_main_domain="$2"
_chk_alt_domains="$3"
_chk_pre_hook="$4"
_chk_local_addr="$5"
_debug _on_before_issue
#run pre hook
if [ "$Le_PreHook" ]; then
_info "Run pre hook:'$Le_PreHook'"
if [ "$_chk_pre_hook" ]; then
_info "Run pre hook:'$_chk_pre_hook'"
if ! (
cd "$DOMAIN_PATH" && eval "$Le_PreHook"
cd "$DOMAIN_PATH" && eval "$_chk_pre_hook"
); then
_err "Error when run pre hook."
return 1
fi
fi
if _hasfield "$Le_Webroot" "$NO_VALUE"; then
if _hasfield "$_chk_web_roots" "$NO_VALUE"; then
if ! _exists "nc"; then
_err "Please install netcat(nc) tools first."
return 1
fi
fi
_debug Le_LocalAddress "$Le_LocalAddress"
_debug Le_LocalAddress "$_chk_local_addr"
alldomains=$(echo "$Le_Domain,$Le_Alt" | tr ',' ' ')
alldomains=$(echo "$_chk_main_domain,$_chk_alt_domains" | tr ',' ' ')
_index=1
_currentRoot=""
_addrIndex=1
for d in $alldomains; do
_debug "Check for domain" "$d"
_currentRoot="$(_getfield "$Le_Webroot" $_index)"
_currentRoot="$(_getfield "$_chk_web_roots" $_index)"
_debug "_currentRoot" "$_currentRoot"
_index=$(_math $_index + 1)
_checkport=""
......@@ -2379,7 +2801,7 @@ _on_before_issue() {
if [ "$_checkport" ]; then
_debug _checkport "$_checkport"
_checkaddr="$(_getfield "$Le_LocalAddress" $_addrIndex)"
_checkaddr="$(_getfield "$_chk_local_addr" $_addrIndex)"
_debug _checkaddr "$_checkaddr"
_addrIndex="$(_math $_addrIndex + 1)"
......@@ -2398,7 +2820,7 @@ _on_before_issue() {
fi
done
if _hasfield "$Le_Webroot" "apache"; then
if _hasfield "$_chk_web_roots" "apache"; then
if ! _setApache; then
_err "set up apache error. Report error to me."
return 1
......@@ -2410,6 +2832,8 @@ _on_before_issue() {
}
_on_issue_err() {
_chk_post_hook="$1"
_chk_vlist="$2"
_debug _on_issue_err
if [ "$LOG_FILE" ]; then
_err "Please check log file for more details: $LOG_FILE"
......@@ -2418,29 +2842,49 @@ _on_issue_err() {
_err "See: $_DEBUG_WIKI"
fi
if [ "$DEBUG" ] && [ "$DEBUG" -gt "0" ]; then
_debug "$(_dlg_versions)"
fi
#run the post hook
if [ "$Le_PostHook" ]; then
_info "Run post hook:'$Le_PostHook'"
if [ "$_chk_post_hook" ]; then
_info "Run post hook:'$_chk_post_hook'"
if ! (
cd "$DOMAIN_PATH" && eval "$Le_PostHook"
cd "$DOMAIN_PATH" && eval "$_chk_post_hook"
); then
_err "Error when run post hook."
return 1
fi
fi
#trigger the validation to flush the pending authz
if [ "$_chk_vlist" ]; then
(
_debug2 "_chk_vlist" "$_chk_vlist"
_debug2 "start to deactivate authz"
ventries=$(echo "$_chk_vlist" | tr "$dvsep" ' ')
for ventry in $ventries; do
d=$(echo "$ventry" | cut -d "$sep" -f 1)
keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2)
uri=$(echo "$ventry" | cut -d "$sep" -f 3)
vtype=$(echo "$ventry" | cut -d "$sep" -f 4)
_currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5)
__trigger_validaton "$uri" "$keyauthorization"
done
)
fi
if [ "$DEBUG" ] && [ "$DEBUG" -gt "0" ]; then
_debug "$(_dlg_versions)"
fi
}
_on_issue_success() {
_chk_post_hook="$1"
_chk_renew_hook="$2"
_debug _on_issue_success
#run the post hook
if [ "$Le_PostHook" ]; then
_info "Run post hook:'$Le_PostHook'"
if [ "$_chk_post_hook" ]; then
_info "Run post hook:'$_chk_post_hook'"
if ! (
cd "$DOMAIN_PATH" && eval "$Le_PostHook"
cd "$DOMAIN_PATH" && eval "$_chk_post_hook"
); then
_err "Error when run post hook."
return 1
......@@ -2448,10 +2892,10 @@ _on_issue_success() {
fi
#run renew hook
if [ "$IS_RENEW" ] && [ "$Le_RenewHook" ]; then
_info "Run renew hook:'$Le_RenewHook'"
if [ "$IS_RENEW" ] && [ "$_chk_renew_hook" ]; then
_info "Run renew hook:'$_chk_renew_hook'"
if ! (
cd "$DOMAIN_PATH" && eval "$Le_RenewHook"
cd "$DOMAIN_PATH" && eval "$_chk_renew_hook"
); then
_err "Error when run renew hook."
return 1
......@@ -2475,6 +2919,10 @@ __calcAccountKeyHash() {
[ -f "$ACCOUNT_KEY_PATH" ] && _digest sha256 <"$ACCOUNT_KEY_PATH"
}
__calc_account_thumbprint() {
printf "%s" "$jwk" | tr -d ' ' | _digest "sha256" | _url_replace
}
#keylength
_regAccount() {
_initpath
......@@ -2565,6 +3013,8 @@ _regAccount() {
return 1
fi
fi
ACCOUNT_THUMBPRINT="$(__calc_account_thumbprint)"
_info "ACCOUNT_THUMBPRINT" "$ACCOUNT_THUMBPRINT"
return 0
done
......@@ -2636,44 +3086,54 @@ __get_domain_new_authz() {
}
#uri keyAuthorization
__trigger_validaton() {
_debug2 "tigger domain validation."
_t_url="$1"
_debug2 _t_url "$_t_url"
_t_key_authz="$2"
_debug2 _t_key_authz "$_t_key_authz"
_send_signed_request "$_t_url" "{\"resource\": \"challenge\", \"keyAuthorization\": \"$_t_key_authz\"}"
}
#webroot, domain domainlist keylength
issue() {
if [ -z "$2" ]; then
_usage "Usage: $PROJECT_ENTRY --issue -d a.com -w /path/to/webroot/a.com/ "
return 1
fi
Le_Webroot="$1"
Le_Domain="$2"
Le_Alt="$3"
if _contains "$Le_Domain" ","; then
Le_Domain=$(echo "$2,$3" | cut -d , -f 1)
Le_Alt=$(echo "$2,$3" | cut -d , -f 2- | sed "s/,${NO_VALUE}$//")
fi
Le_Keylength="$4"
Le_RealCertPath="$5"
Le_RealKeyPath="$6"
Le_RealCACertPath="$7"
Le_ReloadCmd="$8"
Le_RealFullChainPath="$9"
Le_PreHook="${10}"
Le_PostHook="${11}"
Le_RenewHook="${12}"
Le_LocalAddress="${13}"
_web_roots="$1"
_main_domain="$2"
_alt_domains="$3"
if _contains "$_main_domain" ","; then
_main_domain=$(echo "$2,$3" | cut -d , -f 1)
_alt_domains=$(echo "$2,$3" | cut -d , -f 2- | sed "s/,${NO_VALUE}$//")
fi
_key_length="$4"
_real_cert="$5"
_real_key="$6"
_real_ca="$7"
_reload_cmd="$8"
_real_fullchain="$9"
_pre_hook="${10}"
_post_hook="${11}"
_renew_hook="${12}"
_local_addr="${13}"
#remove these later.
if [ "$Le_Webroot" = "dns-cf" ]; then
Le_Webroot="dns_cf"
if [ "$_web_roots" = "dns-cf" ]; then
_web_roots="dns_cf"
fi
if [ "$Le_Webroot" = "dns-dp" ]; then
Le_Webroot="dns_dp"
if [ "$_web_roots" = "dns-dp" ]; then
_web_roots="dns_dp"
fi
if [ "$Le_Webroot" = "dns-cx" ]; then
Le_Webroot="dns_cx"
if [ "$_web_roots" = "dns-cx" ]; then
_web_roots="dns_cx"
fi
_debug "Using api: $API"
if [ ! "$IS_RENEW" ]; then
_initpath "$Le_Domain" "$Le_Keylength"
_initpath "$_main_domain" "$_key_length"
mkdir -p "$DOMAIN_PATH"
fi
......@@ -2685,7 +3145,7 @@ issue() {
_debug _saved_domain "$_saved_domain"
_saved_alt=$(_readdomainconf Le_Alt)
_debug _saved_alt "$_saved_alt"
if [ "$_saved_domain,$_saved_alt" = "$Le_Domain,$Le_Alt" ]; then
if [ "$_saved_domain,$_saved_alt" = "$_main_domain,$_alt_domains" ]; then
_info "Domains not changed."
_info "Skip, Next renewal time is: $(__green "$(_readdomainconf Le_NextRenewTimeStr)")"
_info "Add '$(__red '--force')' to force to renew."
......@@ -2696,16 +3156,16 @@ issue() {
fi
fi
_savedomainconf "Le_Domain" "$Le_Domain"
_savedomainconf "Le_Alt" "$Le_Alt"
_savedomainconf "Le_Webroot" "$Le_Webroot"
_savedomainconf "Le_Domain" "$_main_domain"
_savedomainconf "Le_Alt" "$_alt_domains"
_savedomainconf "Le_Webroot" "$_web_roots"
_savedomainconf "Le_PreHook" "$Le_PreHook"
_savedomainconf "Le_PostHook" "$Le_PostHook"
_savedomainconf "Le_RenewHook" "$Le_RenewHook"
_savedomainconf "Le_PreHook" "$_pre_hook"
_savedomainconf "Le_PostHook" "$_post_hook"
_savedomainconf "Le_RenewHook" "$_renew_hook"
if [ "$Le_LocalAddress" ]; then
_savedomainconf "Le_LocalAddress" "$Le_LocalAddress"
if [ "$_local_addr" ]; then
_savedomainconf "Le_LocalAddress" "$_local_addr"
else
_cleardomainconf "Le_LocalAddress"
fi
......@@ -2713,15 +3173,15 @@ issue() {
Le_API="$API"
_savedomainconf "Le_API" "$Le_API"
if [ "$Le_Alt" = "$NO_VALUE" ]; then
Le_Alt=""
if [ "$_alt_domains" = "$NO_VALUE" ]; then
_alt_domains=""
fi
if [ "$Le_Keylength" = "$NO_VALUE" ]; then
Le_Keylength=""
if [ "$_key_length" = "$NO_VALUE" ]; then
_key_length=""
fi
if ! _on_before_issue; then
if ! _on_before_issue "$_web_roots" "$_main_domain" "$_alt_domains" "$_pre_hook" "$_local_addr"; then
_err "_on_before_issue."
return 1
fi
......@@ -2731,7 +3191,7 @@ issue() {
if [ -z "$_saved_account_key_hash" ] || [ "$_saved_account_key_hash" != "$(__calcAccountKeyHash)" ]; then
if ! _regAccount "$_accountkeylength"; then
_on_issue_err
_on_issue_err "$_post_hook"
return 1
fi
else
......@@ -2743,37 +3203,38 @@ issue() {
else
_key=$(_readdomainconf Le_Keylength)
_debug "Read key length:$_key"
if [ ! -f "$CERT_KEY_PATH" ] || [ "$Le_Keylength" != "$_key" ]; then
if ! createDomainKey "$Le_Domain" "$Le_Keylength"; then
if [ ! -f "$CERT_KEY_PATH" ] || [ "$_key_length" != "$_key" ]; then
if ! createDomainKey "$_main_domain" "$_key_length"; then
_err "Create domain key error."
_clearup
_on_issue_err
_on_issue_err "$_post_hook"
return 1
fi
fi
if ! _createcsr "$Le_Domain" "$Le_Alt" "$CERT_KEY_PATH" "$CSR_PATH" "$DOMAIN_SSL_CONF"; then
if ! _createcsr "$_main_domain" "$_alt_domains" "$CERT_KEY_PATH" "$CSR_PATH" "$DOMAIN_SSL_CONF"; then
_err "Create CSR error."
_clearup
_on_issue_err
_on_issue_err "$_post_hook"
return 1
fi
fi
_savedomainconf "Le_Keylength" "$Le_Keylength"
_savedomainconf "Le_Keylength" "$_key_length"
vlist="$Le_Vlist"
_info "Getting domain auth token for each domain"
sep='#'
dvsep=','
if [ -z "$vlist" ]; then
alldomains=$(echo "$Le_Domain,$Le_Alt" | tr ',' ' ')
alldomains=$(echo "$_main_domain,$_alt_domains" | tr ',' ' ')
_index=1
_currentRoot=""
for d in $alldomains; do
_info "Getting webroot for domain" "$d"
_w="$(echo $Le_Webroot | cut -d , -f $_index)"
_info _w "$_w"
_w="$(echo $_web_roots | cut -d , -f $_index)"
_debug _w "$_w"
if [ "$_w" ]; then
_currentRoot="$_w"
fi
......@@ -2791,13 +3252,12 @@ issue() {
if ! __get_domain_new_authz "$d"; then
_clearup
_on_issue_err
_on_issue_err "$_post_hook"
return 1
fi
if [ -z "$thumbprint" ]; then
accountkey_json=$(printf "%s" "$jwk" | tr -d ' ')
thumbprint=$(printf "%s" "$accountkey_json" | _digest "sha256" | _url_replace)
thumbprint="$(__calc_account_thumbprint)"
fi
entry="$(printf "%s\n" "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"
......@@ -2805,7 +3265,7 @@ issue() {
if [ -z "$entry" ]; then
_err "Error, can not get domain token $d"
_clearup
_on_issue_err
_on_issue_err "$_post_hook"
return 1
fi
token="$(printf "%s\n" "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')"
......@@ -2818,7 +3278,7 @@ issue() {
_debug keyauthorization "$keyauthorization"
if printf "%s" "$response" | grep '"status":"valid"' >/dev/null 2>&1; then
_info "$d is already verified, skip."
_debug "$d is already verified, skip."
keyauthorization="$STATE_VERIFIED"
_debug keyauthorization "$keyauthorization"
fi
......@@ -2826,13 +3286,13 @@ issue() {
dvlist="$d$sep$keyauthorization$sep$uri$sep$vtype$sep$_currentRoot"
_debug dvlist "$dvlist"
vlist="$vlist$dvlist,"
vlist="$vlist$dvlist$dvsep"
done
_debug vlist "$vlist"
#add entry
dnsadded=""
ventries=$(echo "$vlist" | tr ',' ' ')
ventries=$(echo "$vlist" | tr "$dvsep" ' ')
for ventry in $ventries; do
d=$(echo "$ventry" | cut -d "$sep" -f 1)
keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2)
......@@ -2840,7 +3300,7 @@ issue() {
_currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5)
if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then
_info "$d is already verified, skip $vtype."
_debug "$d is already verified, skip $vtype."
continue
fi
......@@ -2886,7 +3346,7 @@ issue() {
if [ "$?" != "0" ]; then
_clearup
_on_issue_err
_on_issue_err "$_post_hook"
return 1
fi
dnsadded='1'
......@@ -2898,7 +3358,7 @@ issue() {
_debug "Dns record not added yet, so, save to $DOMAIN_CONF and exit."
_err "Please add the TXT records to the domains, and retry again."
_clearup
_on_issue_err
_on_issue_err "$_post_hook"
return 1
fi
......@@ -2915,10 +3375,11 @@ issue() {
_sleep "$Le_DNSSleep"
fi
NGINX_RESTORE_VLIST=""
_debug "ok, let's start to verify"
_ncIndex=1
ventries=$(echo "$vlist" | tr ',' ' ')
ventries=$(echo "$vlist" | tr "$dvsep" ' ')
for ventry in $ventries; do
d=$(echo "$ventry" | cut -d "$sep" -f 1)
keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2)
......@@ -2943,18 +3404,38 @@ issue() {
if [ "$vtype" = "$VTYPE_HTTP" ]; then
if [ "$_currentRoot" = "$NO_VALUE" ]; then
_info "Standalone mode server"
_ncaddr="$(_getfield "$Le_LocalAddress" "$_ncIndex")"
_ncaddr="$(_getfield "$_local_addr" "$_ncIndex")"
_ncIndex="$(_math $_ncIndex + 1)"
_startserver "$keyauthorization" "$_ncaddr" &
if [ "$?" != "0" ]; then
_clearup
_on_issue_err
_on_issue_err "$_post_hook" "$vlist"
return 1
fi
serverproc="$!"
sleep 1
_debug serverproc "$serverproc"
elif [ "$_currentRoot" = "$MODE_STATELESS" ]; then
_info "Stateless mode for domain:$d"
_sleep 1
elif _startswith "$_currentRoot" "$NGINX"; then
_info "Nginx mode for domain:$d"
#set up nginx server
FOUND_REAL_NGINX_CONF=""
BACKUP_NGINX_CONF=""
if ! _setNginx "$d" "$_currentRoot" "$thumbprint"; then
_clearup
_on_issue_err "$_post_hook" "$vlist"
return 1
fi
if [ "$FOUND_REAL_NGINX_CONF" ]; then
_realConf="$FOUND_REAL_NGINX_CONF"
_backup="$BACKUP_NGINX_CONF"
_debug _realConf "$_realConf"
NGINX_RESTORE_VLIST="$d$sep$_realConf$sep$_backup$dvsep$NGINX_RESTORE_VLIST"
fi
_sleep 1
else
if [ "$_currentRoot" = "apache" ]; then
wellknown_path="$ACME_DIR"
......@@ -2979,7 +3460,7 @@ issue() {
_err "$d:Can not write token to file : $wellknown_path/$token"
_clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup
_on_issue_err
_on_issue_err "$_post_hook" "$vlist"
return 1
fi
......@@ -3018,22 +3499,22 @@ issue() {
_SAN_B="$_x.$_y.acme.invalid"
_debug2 _SAN_B "$_SAN_B"
_ncaddr="$(_getfield "$Le_LocalAddress" "$_ncIndex")"
_ncaddr="$(_getfield "$_local_addr" "$_ncIndex")"
_ncIndex="$(_math "$_ncIndex" + 1)"
if ! _starttlsserver "$_SAN_B" "$_SAN_A" "$Le_TLSPort" "$keyauthorization" "$_ncaddr"; then
_err "Start tls server error."
_clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup
_on_issue_err
_on_issue_err "$_post_hook" "$vlist"
return 1
fi
fi
if ! _send_signed_request "$uri" "{\"resource\": \"challenge\", \"keyAuthorization\": \"$keyauthorization\"}"; then
if ! __trigger_validaton "$uri" "$keyauthorization"; then
_err "$d:Can not get challenge: $response"
_clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup
_on_issue_err
_on_issue_err "$_post_hook" "$vlist"
return 1
fi
......@@ -3041,7 +3522,7 @@ issue() {
_err "$d:Challenge error: $response"
_clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup
_on_issue_err
_on_issue_err "$_post_hook" "$vlist"
return 1
fi
......@@ -3056,7 +3537,7 @@ issue() {
_err "$d:Timeout"
_clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup
_on_issue_err
_on_issue_err "$_post_hook" "$vlist"
return 1
fi
......@@ -3068,7 +3549,7 @@ issue() {
_err "$d:Verify error:$response"
_clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup
_on_issue_err
_on_issue_err "$_post_hook" "$vlist"
return 1
fi
_debug2 original "$response"
......@@ -3103,7 +3584,7 @@ issue() {
fi
_clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup
_on_issue_err
_on_issue_err "$_post_hook" "$vlist"
return 1
fi
......@@ -3113,7 +3594,7 @@ issue() {
_err "$d:Verify error:$response"
_clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup
_on_issue_err
_on_issue_err "$_post_hook" "$vlist"
return 1
fi
......@@ -3127,7 +3608,7 @@ issue() {
if ! _send_signed_request "$API/acme/new-cert" "{\"resource\": \"new-cert\", \"csr\": \"$der\"}" "needbase64"; then
_err "Sign failed."
_on_issue_err
_on_issue_err "$_post_hook"
return 1
fi
......@@ -3169,7 +3650,7 @@ issue() {
if [ -z "$Le_LinkCert" ]; then
response="$(echo "$response" | _dbase64 "multiline" | _normalizeJson)"
_err "Sign failed: $(echo "$response" | _egrep_o '"detail":"[^"]*"')"
_on_issue_err
_on_issue_err "$_post_hook"
return 1
fi
......@@ -3231,10 +3712,15 @@ issue() {
Le_NextRenewTime=$(_math "$Le_NextRenewTime" - 86400)
_savedomainconf "Le_NextRenewTime" "$Le_NextRenewTime"
_on_issue_success
_on_issue_success "$_post_hook" "$_renew_hook"
if [ "$Le_RealCertPath$Le_RealKeyPath$Le_RealCACertPath$Le_ReloadCmd$Le_RealFullChainPath" ]; then
_installcert
if [ "$_real_cert$_real_key$_real_ca$_reload_cmd$_real_fullchain" ]; then
_savedomainconf "Le_RealCertPath" "$_real_cert"
_savedomainconf "Le_RealCACertPath" "$_real_ca"
_savedomainconf "Le_RealKeyPath" "$_real_key"
_savedomainconf "Le_ReloadCmd" "$_reload_cmd"
_savedomainconf "Le_RealFullChainPath" "$_real_fullchain"
_installcert "$_main_domain" "$_real_cert" "$_real_key" "$_real_ca" "$_real_fullchain" "$_reload_cmd"
fi
}
......@@ -3287,7 +3773,7 @@ renew() {
fi
if [ "$Le_DeployHook" ]; then
deploy "$Le_Domain" "$Le_DeployHook" "$Le_Keylength"
_deploy "$Le_Domain" "$Le_DeployHook"
res="$?"
fi
......@@ -3459,45 +3945,32 @@ list() {
}
deploy() {
Le_Domain="$1"
Le_DeployHook="$2"
_isEcc="$3"
if [ -z "$Le_DeployHook" ]; then
_usage "Usage: $PROJECT_ENTRY --deploy -d domain.com --deploy-hook cpanel [--ecc] "
return 1
fi
_initpath "$Le_Domain" "$_isEcc"
if [ ! -d "$DOMAIN_PATH" ]; then
_err "Domain is not valid:'$Le_Domain'"
return 1
fi
_deploy() {
_d="$1"
_hooks="$2"
_deployApi="$(_findHook "$Le_Domain" deploy "$Le_DeployHook")"
for _d_api in $(echo "$_hooks" | tr ',' " "); do
_deployApi="$(_findHook "$_d" deploy "$_d_api")"
if [ -z "$_deployApi" ]; then
_err "The deploy hook $Le_DeployHook is not found."
_err "The deploy hook $_d_api is not found."
return 1
fi
_debug _deployApi "$_deployApi"
_savedomainconf Le_DeployHook "$Le_DeployHook"
if ! (
if ! . "$_deployApi"; then
_err "Load file $_deployApi error. Please check your api file and try again."
return 1
fi
d_command="${Le_DeployHook}_deploy"
d_command="${_d_api}_deploy"
if ! _exists "$d_command"; then
_err "It seems that your api file is not correct, it must have a function named: $d_command"
return 1
fi
if ! $d_command "$Le_Domain" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$CERT_FULLCHAIN_PATH"; then
_err "Error deploy for domain:$Le_Domain"
_on_issue_err
if ! $d_command "$_d" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$CERT_FULLCHAIN_PATH"; then
_err "Error deploy for domain:$_d"
return 1
fi
); then
......@@ -3506,104 +3979,135 @@ deploy() {
else
_info "$(__green Success)"
fi
done
}
#domain hooks
deploy() {
_d="$1"
_hooks="$2"
_isEcc="$3"
if [ -z "$_hooks" ]; then
_usage "Usage: $PROJECT_ENTRY --deploy -d domain.com --deploy-hook cpanel [--ecc] "
return 1
fi
_initpath "$_d" "$_isEcc"
if [ ! -d "$DOMAIN_PATH" ]; then
_err "Domain is not valid:'$_d'"
return 1
fi
. "$DOMAIN_CONF"
_savedomainconf Le_DeployHook "$_hooks"
_deploy "$_d" "$_hooks"
}
installcert() {
Le_Domain="$1"
if [ -z "$Le_Domain" ]; then
_main_domain="$1"
if [ -z "$_main_domain" ]; then
_usage "Usage: $PROJECT_ENTRY --installcert -d domain.com [--ecc] [--certpath cert-file-path] [--keypath key-file-path] [--capath ca-cert-file-path] [ --reloadCmd reloadCmd] [--fullchainpath fullchain-path]"
return 1
fi
Le_RealCertPath="$2"
Le_RealKeyPath="$3"
Le_RealCACertPath="$4"
Le_ReloadCmd="$5"
Le_RealFullChainPath="$6"
_real_cert="$2"
_real_key="$3"
_real_ca="$4"
_reload_cmd="$5"
_real_fullchain="$6"
_isEcc="$7"
_initpath "$Le_Domain" "$_isEcc"
_initpath "$_main_domain" "$_isEcc"
if [ ! -d "$DOMAIN_PATH" ]; then
_err "Domain is not valid:'$Le_Domain'"
_err "Domain is not valid:'$_main_domain'"
return 1
fi
_installcert
_savedomainconf "Le_RealCertPath" "$_real_cert"
_savedomainconf "Le_RealCACertPath" "$_real_ca"
_savedomainconf "Le_RealKeyPath" "$_real_key"
_savedomainconf "Le_ReloadCmd" "$_reload_cmd"
_savedomainconf "Le_RealFullChainPath" "$_real_fullchain"
_installcert "$_main_domain" "$_real_cert" "$_real_key" "$_real_ca" "$_real_fullchain" "$_reload_cmd"
}
#domain cert key ca fullchain reloadcmd backup-prefix
_installcert() {
_savedomainconf "Le_RealCertPath" "$Le_RealCertPath"
_savedomainconf "Le_RealCACertPath" "$Le_RealCACertPath"
_savedomainconf "Le_RealKeyPath" "$Le_RealKeyPath"
_savedomainconf "Le_ReloadCmd" "$Le_ReloadCmd"
_savedomainconf "Le_RealFullChainPath" "$Le_RealFullChainPath"
_main_domain="$1"
_real_cert="$2"
_real_key="$3"
_real_ca="$4"
_real_fullchain="$5"
_reload_cmd="$6"
_backup_prefix="$7"
if [ "$Le_RealCertPath" = "$NO_VALUE" ]; then
Le_RealCertPath=""
if [ "$_real_cert" = "$NO_VALUE" ]; then
_real_cert=""
fi
if [ "$Le_RealKeyPath" = "$NO_VALUE" ]; then
Le_RealKeyPath=""
if [ "$_real_key" = "$NO_VALUE" ]; then
_real_key=""
fi
if [ "$Le_RealCACertPath" = "$NO_VALUE" ]; then
Le_RealCACertPath=""
if [ "$_real_ca" = "$NO_VALUE" ]; then
_real_ca=""
fi
if [ "$Le_ReloadCmd" = "$NO_VALUE" ]; then
Le_ReloadCmd=""
if [ "$_reload_cmd" = "$NO_VALUE" ]; then
_reload_cmd=""
fi
if [ "$Le_RealFullChainPath" = "$NO_VALUE" ]; then
Le_RealFullChainPath=""
if [ "$_real_fullchain" = "$NO_VALUE" ]; then
_real_fullchain=""
fi
if [ "$Le_RealCertPath" ]; then
_backup_path="$DOMAIN_BACKUP_PATH/$_backup_prefix"
mkdir -p "$_backup_path"
_info "Installing cert to:$Le_RealCertPath"
if [ -f "$Le_RealCertPath" ] && [ ! "$IS_RENEW" ]; then
cp "$Le_RealCertPath" "$Le_RealCertPath".bak
if [ "$_real_cert" ]; then
_info "Installing cert to:$_real_cert"
if [ -f "$_real_cert" ] && [ ! "$IS_RENEW" ]; then
cp "$_real_cert" "$_backup_path/cert.bak"
fi
cat "$CERT_PATH" >"$Le_RealCertPath"
cat "$CERT_PATH" >"$_real_cert"
fi
if [ "$Le_RealCACertPath" ]; then
_info "Installing CA to:$Le_RealCACertPath"
if [ "$Le_RealCACertPath" = "$Le_RealCertPath" ]; then
echo "" >>"$Le_RealCACertPath"
cat "$CA_CERT_PATH" >>"$Le_RealCACertPath"
if [ "$_real_ca" ]; then
_info "Installing CA to:$_real_ca"
if [ "$_real_ca" = "$_real_cert" ]; then
echo "" >>"$_real_ca"
cat "$CA_CERT_PATH" >>"$_real_ca"
else
if [ -f "$Le_RealCACertPath" ] && [ ! "$IS_RENEW" ]; then
cp "$Le_RealCACertPath" "$Le_RealCACertPath".bak
if [ -f "$_real_ca" ] && [ ! "$IS_RENEW" ]; then
cp "$_real_ca" "$_backup_path/ca.bak"
fi
cat "$CA_CERT_PATH" >"$Le_RealCACertPath"
cat "$CA_CERT_PATH" >"$_real_ca"
fi
fi
if [ "$Le_RealKeyPath" ]; then
_info "Installing key to:$Le_RealKeyPath"
if [ -f "$Le_RealKeyPath" ] && [ ! "$IS_RENEW" ]; then
cp "$Le_RealKeyPath" "$Le_RealKeyPath".bak
if [ "$_real_key" ]; then
_info "Installing key to:$_real_key"
if [ -f "$_real_key" ] && [ ! "$IS_RENEW" ]; then
cp "$_real_key" "$_backup_path/key.bak"
fi
cat "$CERT_KEY_PATH" >"$Le_RealKeyPath"
cat "$CERT_KEY_PATH" >"$_real_key"
fi
if [ "$Le_RealFullChainPath" ]; then
_info "Installing full chain to:$Le_RealFullChainPath"
if [ -f "$Le_RealFullChainPath" ] && [ ! "$IS_RENEW" ]; then
cp "$Le_RealFullChainPath" "$Le_RealFullChainPath".bak
if [ "$_real_fullchain" ]; then
_info "Installing full chain to:$_real_fullchain"
if [ -f "$_real_fullchain" ] && [ ! "$IS_RENEW" ]; then
cp "$_real_fullchain" "$_backup_path/fullchain.bak"
fi
cat "$CERT_FULLCHAIN_PATH" >"$Le_RealFullChainPath"
cat "$CERT_FULLCHAIN_PATH" >"$_real_fullchain"
fi
if [ "$Le_ReloadCmd" ]; then
_info "Run Le_ReloadCmd: $Le_ReloadCmd"
if [ "$_reload_cmd" ]; then
_info "Run reload cmd: $_reload_cmd"
if (
export CERT_PATH
export CERT_KEY_PATH
export CA_CERT_PATH
export CERT_FULLCHAIN_PATH
cd "$DOMAIN_PATH" && eval "$Le_ReloadCmd"
cd "$DOMAIN_PATH" && eval "$_reload_cmd"
); then
_info "$(__green "Reload success")"
else
......@@ -3896,12 +4400,7 @@ _detect_profile() {
_initconf() {
_initpath
if [ ! -f "$ACCOUNT_CONF_PATH" ]; then
echo "#ACCOUNT_CONF_PATH=xxxx
#ACCOUNT_EMAIL=aaa@example.com # the account email used to register account.
#ACCOUNT_KEY_PATH=\"/path/to/account.key\"
#CERT_HOME=\"/path/to/cert/home\"
echo "
#LOG_FILE=\"$DEFAULT_LOG_FILE\"
#LOG_LEVEL=1
......@@ -3909,12 +4408,6 @@ _initconf() {
#AUTO_UPGRADE=\"1\"
#NO_TIMESTAMP=1
#OPENSSL_BIN=openssl
#USER_AGENT=\"$USER_AGENT\"
#USER_PATH=
" >"$ACCOUNT_CONF_PATH"
fi
......@@ -3942,8 +4435,8 @@ _precheck() {
fi
fi
if ! _exists "$OPENSSL_BIN"; then
_err "Please install openssl first."
if ! _exists "$ACME_OPENSSL_BIN"; then
_err "Please install openssl first. ACME_OPENSSL_BIN=$ACME_OPENSSL_BIN"
_err "We need openssl to generate keys."
return 1
fi
......@@ -4220,7 +4713,7 @@ Commands:
--version, -v Show version info.
--install Install $PROJECT_NAME to your system.
--uninstall Uninstall $PROJECT_NAME, and uninstall the cron job.
--upgrade Upgrade $PROJECT_NAME to the latest code from $PROJECT .
--upgrade Upgrade $PROJECT_NAME to the latest code from $PROJECT.
--issue Issue a cert.
--signcsr Issue a cert from an existing csr.
--deploy Deploy the cert to your server.
......@@ -4235,10 +4728,11 @@ Commands:
--uninstall-cronjob Uninstall the cron job. The 'uninstall' command can do this automatically.
--cron Run cron job to renew all the certs.
--toPkcs Export the certificate and key to a pfx file.
--toPkcs8 Convert to pkcs8 format.
--update-account Update account info.
--register-account Register account key.
--createAccountKey, -cak Create an account private key, professional use.
--createDomainKey, -cdk Create an domain private key, professional use.
--create-account-key Create an account private key, professional use.
--create-domain-key Create an domain private key, professional use.
--createCSR, -ccsr Create CSR , professional use.
--deactivate Deactivate the domain authz, professional use.
......@@ -4247,9 +4741,10 @@ Parameters:
--force, -f Used to force to install or force to renew a cert immediately.
--staging, --test Use staging server, just for test.
--debug Output debug info.
--output-insecure Output all the sensitive messages. By default all the credentials/sensitive messages are hidden from the output/debug/log for secure.
--webroot, -w /path/to/webroot Specifies the web root folder for web root mode.
--standalone Use standalone mode.
--stateless Use stateless mode, see: $_STATELESS_WIKI
--tls Use standalone tls mode.
--apache Use apache mode.
--dns [dns_cf|dns_dp|dns_cx|/path/to/api/file] Use dns mode or dns api.
......@@ -4259,6 +4754,7 @@ Parameters:
--accountkeylength, -ak [2048] Specifies the account key length.
--log [/path/to/logfile] Specifies the log file. The default is: \"$DEFAULT_LOG_FILE\" if you don't give a file path here.
--log-level 1|2 Specifies the log level, default is 1.
--syslog [0|3|6|7] Syslog level, 0: disable syslog, 3: error, 6: info, 7: debug.
These parameters are to install the cert to nginx/apache or anyother server after issue/renew a cert:
......@@ -4296,6 +4792,7 @@ Parameters:
--listen-v4 Force standalone/tls server to listen at ipv4.
--listen-v6 Force standalone/tls server to listen at ipv6.
--openssl-bin Specifies a custom openssl bin location.
--use-wget Force to use wget, if you have both curl and wget installed.
"
}
......@@ -4363,9 +4860,9 @@ _processAccountConf() {
fi
if [ "$_openssl_bin" ]; then
_saveaccountconf "OPENSSL_BIN" "$_openssl_bin"
elif [ "$OPENSSL_BIN" ] && [ "$OPENSSL_BIN" != "$DEFAULT_OPENSSL_BIN" ]; then
_saveaccountconf "OPENSSL_BIN" "$OPENSSL_BIN"
_saveaccountconf "ACME_OPENSSL_BIN" "$_openssl_bin"
elif [ "$ACME_OPENSSL_BIN" ] && [ "$ACME_OPENSSL_BIN" != "$DEFAULT_OPENSSL_BIN" ]; then
_saveaccountconf "ACME_OPENSSL_BIN" "$ACME_OPENSSL_BIN"
fi
if [ "$_auto_upgrade" ]; then
......@@ -4374,6 +4871,12 @@ _processAccountConf() {
_saveaccountconf "AUTO_UPGRADE" "$AUTO_UPGRADE"
fi
if [ "$_use_wget" ]; then
_saveaccountconf "ACME_USE_WGET" "$_use_wget"
elif [ "$ACME_USE_WGET" ]; then
_saveaccountconf "ACME_USE_WGET" "$ACME_USE_WGET"
fi
}
_process() {
......@@ -4417,6 +4920,8 @@ _process() {
_listen_v4=""
_listen_v6=""
_openssl_bin=""
_syslog=""
_use_wget=""
while [ ${#} -gt 0 ]; do
case "${1}" in
......@@ -4479,10 +4984,13 @@ _process() {
--toPkcs)
_CMD="toPkcs"
;;
--createAccountKey | --createaccountkey | -cak)
--toPkcs8)
_CMD="toPkcs8"
;;
--createAccountKey | --createaccountkey | -cak | --create-account-key)
_CMD="createAccountKey"
;;
--createDomainKey | --createdomainkey | -cdk)
--createDomainKey | --createdomainkey | -cdk | --create-domain-key)
_CMD="createDomainKey"
;;
--createCSR | --createcsr | -ccr)
......@@ -4532,12 +5040,15 @@ _process() {
;;
--debug)
if [ -z "$2" ] || _startswith "$2" "-"; then
DEBUG="1"
DEBUG="$DEBUG_LEVEL_DEFAULT"
else
DEBUG="$2"
shift
fi
;;
--output-insecure)
export OUTPUT_INSECURE=1
;;
--webroot | -w)
wvalue="$2"
if [ -z "$_webroot" ]; then
......@@ -4555,6 +5066,14 @@ _process() {
_webroot="$_webroot,$wvalue"
fi
;;
--stateless)
wvalue="$MODE_STATELESS"
if [ -z "$_webroot" ]; then
_webroot="$wvalue"
else
_webroot="$_webroot,$wvalue"
fi
;;
--local-address)
lvalue="$2"
_local_address="$_local_address$lvalue,"
......@@ -4568,6 +5087,14 @@ _process() {
_webroot="$_webroot,$wvalue"
fi
;;
--nginx)
wvalue="$NGINX"
if [ -z "$_webroot" ]; then
_webroot="$wvalue"
else
_webroot="$_webroot,$wvalue"
fi
;;
--tls)
wvalue="$W_TLS"
if [ -z "$_webroot" ]; then
......@@ -4715,7 +5242,11 @@ _process() {
shift
;;
--deploy-hook)
_deploy_hook="$2"
if [ -z "$2" ] || _startswith "$2" "-"; then
_usage "Please specify a value for '--deploy-hook'"
return 1
fi
_deploy_hook="$_deploy_hook$2,"
shift
;;
--ocsp-must-staple | --ocsp)
......@@ -4739,6 +5270,15 @@ _process() {
LOG_LEVEL="$_log_level"
shift
;;
--syslog)
if ! _startswith "$2" '-'; then
_syslog="$2"
shift
fi
if [ -z "$_syslog" ]; then
_syslog="$SYSLOG_LEVEL_DEFAULT"
fi
;;
--auto-upgrade)
_auto_upgrade="$2"
if [ -z "$_auto_upgrade" ] || _startswith "$_auto_upgrade" '-'; then
......@@ -4758,7 +5298,12 @@ _process() {
;;
--openssl-bin)
_openssl_bin="$2"
OPENSSL_BIN="$_openssl_bin"
ACME_OPENSSL_BIN="$_openssl_bin"
shift
;;
--use-wget)
_use_wget="1"
ACME_USE_WGET="1"
;;
*)
_err "Unknown parameter : $1"
......@@ -4786,6 +5331,21 @@ _process() {
LOG_LEVEL="$_log_level"
fi
if [ "$_syslog" ]; then
if _exists logger; then
if [ "$_syslog" = "0" ]; then
_clearaccountconf "SYS_LOG"
else
_saveaccountconf "SYS_LOG" "$_syslog"
fi
SYS_LOG="$_syslog"
else
_err "The 'logger' command is not found, can not enable syslog."
_clearaccountconf "SYS_LOG"
SYS_LOG=""
fi
fi
_processAccountConf
fi
......@@ -4844,6 +5404,9 @@ _process() {
toPkcs)
toPkcs "$_domain" "$_password" "$_ecc"
;;
toPkcs8)
toPkcs8 "$_domain" "$_ecc"
;;
createAccountKey)
createAccountKey "$_accountkeylength"
;;
......@@ -4878,6 +5441,21 @@ _process() {
if [ "$_log_level" ]; then
_saveaccountconf "LOG_LEVEL" "$_log_level"
fi
if [ "$_syslog" ]; then
if _exists logger; then
if [ "$_syslog" = "0" ]; then
_clearaccountconf "SYS_LOG"
else
_saveaccountconf "SYS_LOG" "$_syslog"
fi
else
_err "The 'logger' command is not found, can not enable syslog."
_clearaccountconf "SYS_LOG"
SYS_LOG=""
fi
fi
_processAccountConf
fi
......
#Using deploy api
# Using deploy api
Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert).
Here are the scripts to deploy the certs/key to the server/services.
## 1. Deploy the certs to your cpanel host.
(cpanel deploy hook is not finished yet, this is just an example.)
Then you can deploy now:
```sh
export DEPLOY_CPANEL_USER=myusername
export DEPLOY_CPANEL_PASSWORD=PASSWORD
acme.sh --deploy -d example.com --deploy-hook cpanel
```
## 2. Deploy ssl cert on kong proxy engine based on api.
Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert).
(TODO)
## 3. Deploy the cert to remote server through SSH access.
(TODO)
## 4. Deploy the cert to local vsftpd server.
```sh
acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd
```
The default vsftpd conf file is `/etc/vsftpd.conf`, if your vsftpd conf is not in the default location, you can specify one:
```sh
export DEPLOY_VSFTPD_CONF="/etc/vsftpd.conf"
acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd
```
The default command to restart vsftpd server is `service vsftpd restart`, if it doesn't work, you can specify one:
```sh
export DEPLOY_VSFTPD_RELOAD="/etc/init.d/vsftpd restart"
acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd
```
## 5. Deploy the cert to local exim4 server.
```sh
acme.sh --deploy -d ftp.example.com --deploy-hook exim4
```
The default exim4 conf file is `/etc/exim/exim.conf`, if your exim4 conf is not in the default location, you can specify one:
```sh
export DEPLOY_EXIM4_CONF="/etc/exim4/exim4.conf.template"
acme.sh --deploy -d ftp.example.com --deploy-hook exim4
```
The default command to restart exim4 server is `service exim4 restart`, if it doesn't work, you can specify one:
```sh
export DEPLOY_EXIM4_RELOAD="/etc/init.d/exim4 restart"
acme.sh --deploy -d ftp.example.com --deploy-hook exim4
```
#!/usr/bin/env sh
#Here is a script to deploy cert to dovecot server.
#returns 0 means success, otherwise error.
######## Public functions #####################
#domain keyfile certfile cafile fullchain
apache_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"
_debug _cdomain "$_cdomain"
_debug _ckey "$_ckey"
_debug _ccert "$_ccert"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
_err "Deploy cert to apache server, Not implemented yet"
return 1
}
#!/usr/bin/env sh
#Here is 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
}
#!/usr/bin/env sh
#Here is a script to deploy cert to dovecot server.
#returns 0 means success, otherwise error.
######## Public functions #####################
#domain keyfile certfile cafile fullchain
dovecot_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"
_debug _cdomain "$_cdomain"
_debug _ckey "$_ckey"
_debug _ccert "$_ccert"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
_err "Not implemented yet"
return 1
}
#!/usr/bin/env sh
#Here is a script to deploy cert to exim4 server.
#returns 0 means success, otherwise error.
#DEPLOY_EXIM4_CONF="/etc/exim/exim.conf"
#DEPLOY_EXIM4_RELOAD="service exim4 restart"
######## Public functions #####################
#domain keyfile certfile cafile fullchain
exim4_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"
_debug _cdomain "$_cdomain"
_debug _ckey "$_ckey"
_debug _ccert "$_ccert"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
_ssl_path="/etc/acme.sh/exim4"
if ! mkdir -p "$_ssl_path"; then
_err "Can not create folder:$_ssl_path"
return 1
fi
_info "Copying key and cert"
_real_key="$_ssl_path/exim4.key"
if ! cat "$_ckey" >"$_real_key"; then
_err "Error: write key file to: $_real_key"
return 1
fi
_real_fullchain="$_ssl_path/exim4.pem"
if ! cat "$_cfullchain" >"$_real_fullchain"; then
_err "Error: write key file to: $_real_fullchain"
return 1
fi
DEFAULT_EXIM4_RELOAD="service exim4 restart"
_reload="${DEPLOY_EXIM4_RELOAD:-$DEFAULT_EXIM4_RELOAD}"
if [ -z "$IS_RENEW" ]; then
DEFAULT_EXIM4_CONF="/etc/exim/exim.conf"
if [ ! -f "$DEFAULT_EXIM4_CONF" ]; then
DEFAULT_EXIM4_CONF="/etc/exim4/exim4.conf.template"
fi
_exim4_conf="${DEPLOY_EXIM4_CONF:-$DEFAULT_EXIM4_CONF}"
_debug _exim4_conf "$_exim4_conf"
if [ ! -f "$_exim4_conf" ]; then
if [ -z "$DEPLOY_EXIM4_CONF" ]; then
_err "exim4 conf is not found, please define DEPLOY_EXIM4_CONF"
return 1
else
_err "It seems that the specified exim4 conf is not valid, please check."
return 1
fi
fi
if [ ! -w "$_exim4_conf" ]; then
_err "The file $_exim4_conf is not writable, please change the permission."
return 1
fi
_backup_conf="$DOMAIN_BACKUP_PATH/exim4.conf.bak"
_info "Backup $_exim4_conf to $_backup_conf"
cp "$_exim4_conf" "$_backup_conf"
_info "Modify exim4 conf: $_exim4_conf"
if _setopt "$_exim4_conf" "tls_certificate" "=" "$_real_fullchain" \
&& _setopt "$_exim4_conf" "tls_privatekey" "=" "$_real_key"; then
_info "Set config success!"
else
_err "Config exim4 server error, please report bug to us."
_info "Restoring exim4 conf"
if cat "$_backup_conf" >"$_exim4_conf"; then
_info "Restore conf success"
eval "$_reload"
else
_err "Opps, error restore exim4 conf, please report bug to us."
fi
return 1
fi
fi
_info "Run reload: $_reload"
if eval "$_reload"; then
_info "Reload success!"
if [ "$DEPLOY_EXIM4_CONF" ]; then
_savedomainconf DEPLOY_EXIM4_CONF "$DEPLOY_EXIM4_CONF"
else
_cleardomainconf DEPLOY_EXIM4_CONF
fi
if [ "$DEPLOY_EXIM4_RELOAD" ]; then
_savedomainconf DEPLOY_EXIM4_RELOAD "$DEPLOY_EXIM4_RELOAD"
else
_cleardomainconf DEPLOY_EXIM4_RELOAD
fi
return 0
else
_err "Reload error, restoring"
if cat "$_backup_conf" >"$_exim4_conf"; then
_info "Restore conf success"
eval "$_reload"
else
_err "Opps, error restore exim4 conf, please report bug to us."
fi
return 1
fi
return 0
}
#!/usr/bin/env sh
#Here is a script to deploy cert to haproxy server.
#returns 0 means success, otherwise error.
######## Public functions #####################
#domain keyfile certfile cafile fullchain
haproxy_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"
_debug _cdomain "$_cdomain"
_debug _ckey "$_ckey"
_debug _ccert "$_ccert"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
_err "deploy cert to haproxy server, Not implemented yet"
return 1
}
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
#!/usr/bin/env sh
#Here is a script to deploy cert to mysqld server.
#returns 0 means success, otherwise error.
######## Public functions #####################
#domain keyfile certfile cafile fullchain
mysqld_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"
_debug _cdomain "$_cdomain"
_debug _ckey "$_ckey"
_debug _ccert "$_ccert"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
_err "deploy cert to mysqld server, Not implemented yet"
return 1
}
#!/usr/bin/env sh
#Here is a script to deploy cert to nginx server.
#returns 0 means success, otherwise error.
######## Public functions #####################
#domain keyfile certfile cafile fullchain
nginx_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"
_debug _cdomain "$_cdomain"
_debug _ckey "$_ckey"
_debug _ccert "$_ccert"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
_err "deploy cert to nginx server, Not implemented yet"
return 1
}
#!/usr/bin/env sh
#Here is a script to deploy cert to opensshd server.
#returns 0 means success, otherwise error.
######## Public functions #####################
#domain keyfile certfile cafile fullchain
opensshd_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"
_debug _cdomain "$_cdomain"
_debug _ckey "$_ckey"
_debug _ccert "$_ccert"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
_err "deploy cert to opensshd server, Not implemented yet"
return 1
}
#!/usr/bin/env sh
#Here is a script to deploy cert to pureftpd server.
#returns 0 means success, otherwise error.
######## Public functions #####################
#domain keyfile certfile cafile fullchain
pureftpd_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"
_debug _cdomain "$_cdomain"
_debug _ckey "$_ckey"
_debug _ccert "$_ccert"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
_err "deploy cert to pureftpd server, Not implemented yet"
return 1
}
#!/usr/bin/env sh
#Here is a script to deploy cert to vsftpd server.
#returns 0 means success, otherwise error.
#DEPLOY_VSFTPD_CONF="/etc/vsftpd.conf"
#DEPLOY_VSFTPD_RELOAD="service vsftpd restart"
######## Public functions #####################
#domain keyfile certfile cafile fullchain
vsftpd_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"
_debug _cdomain "$_cdomain"
_debug _ckey "$_ckey"
_debug _ccert "$_ccert"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
_ssl_path="/etc/acme.sh/vsftpd"
if ! mkdir -p "$_ssl_path"; then
_err "Can not create folder:$_ssl_path"
return 1
fi
_info "Copying key and cert"
_real_key="$_ssl_path/vsftpd.key"
if ! cat "$_ckey" >"$_real_key"; then
_err "Error: write key file to: $_real_key"
return 1
fi
_real_fullchain="$_ssl_path/vsftpd.chain.pem"
if ! cat "$_cfullchain" >"$_real_fullchain"; then
_err "Error: write key file to: $_real_fullchain"
return 1
fi
DEFAULT_VSFTPD_RELOAD="service vsftpd restart"
_reload="${DEPLOY_VSFTPD_RELOAD:-$DEFAULT_VSFTPD_RELOAD}"
if [ -z "$IS_RENEW" ]; then
DEFAULT_VSFTPD_CONF="/etc/vsftpd.conf"
_vsftpd_conf="${DEPLOY_VSFTPD_CONF:-$DEFAULT_VSFTPD_CONF}"
if [ ! -f "$_vsftpd_conf" ]; then
if [ -z "$DEPLOY_VSFTPD_CONF" ]; then
_err "vsftpd conf is not found, please define DEPLOY_VSFTPD_CONF"
return 1
else
_err "It seems that the specified vsftpd conf is not valid, please check."
return 1
fi
fi
if [ ! -w "$_vsftpd_conf" ]; then
_err "The file $_vsftpd_conf is not writable, please change the permission."
return 1
fi
_backup_conf="$DOMAIN_BACKUP_PATH/vsftpd.conf.bak"
_info "Backup $_vsftpd_conf to $_backup_conf"
cp "$_vsftpd_conf" "$_backup_conf"
_info "Modify vsftpd conf: $_vsftpd_conf"
if _setopt "$_vsftpd_conf" "rsa_cert_file" "=" "$_real_fullchain" \
&& _setopt "$_vsftpd_conf" "rsa_private_key_file" "=" "$_real_key" \
&& _setopt "$_vsftpd_conf" "ssl_enable" "=" "YES"; then
_info "Set config success!"
else
_err "Config vsftpd server error, please report bug to us."
_info "Restoring vsftpd conf"
if cat "$_backup_conf" >"$_vsftpd_conf"; then
_info "Restore conf success"
eval "$_reload"
else
_err "Opps, error restore vsftpd conf, please report bug to us."
fi
return 1
fi
fi
_info "Run reload: $_reload"
if eval "$_reload"; then
_info "Reload success!"
if [ "$DEPLOY_VSFTPD_CONF" ]; then
_savedomainconf DEPLOY_VSFTPD_CONF "$DEPLOY_VSFTPD_CONF"
else
_cleardomainconf DEPLOY_VSFTPD_CONF
fi
if [ "$DEPLOY_VSFTPD_RELOAD" ]; then
_savedomainconf DEPLOY_VSFTPD_RELOAD "$DEPLOY_VSFTPD_RELOAD"
else
_cleardomainconf DEPLOY_VSFTPD_RELOAD
fi
return 0
else
_err "Reload error, restoring"
if cat "$_backup_conf" >"$_vsftpd_conf"; then
_info "Restore conf success"
eval "$_reload"
else
_err "Opps, error restore vsftpd conf, please report bug to us."
fi
return 1
fi
return 0
}
......@@ -305,6 +305,50 @@ Note that you cannot use acme.sh automatic DNS validation for FreeDNS public dom
you create under a FreeDNS public domain. You must own the top level domain in order to automaitcally
validate with acme.sh at FreeDNS.
## 16. Use cyon.ch
You only need to set your cyon.ch login credentials.
If you also have 2 Factor Authentication (OTP) enabled, you need to set your secret token too and have `oathtool` installed.
```
export CY_Username="your_cyon_username"
export CY_Password="your_cyon_password"
export CY_OTP_Secret="your_otp_secret" # Only required if using 2FA
```
To issue a cert:
```
acme.sh --issue --dns dns_cyon -d example.com -d www.example.com
```
The `CY_Username`, `CY_Password` and `CY_OTP_Secret` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
## 17. Use Domain-Offensive/Resellerinterface/Domainrobot API
You will need your login credentials (Partner ID+Password) to the Resellerinterface, and export them before you run `acme.sh`:
```
export DO_PID="KD-1234567"
export DO_PW="cdfkjl3n2"
```
Ok, let's issue a cert now:
```
acme.sh --issue --dns dns_do -d example.com -d www.example.com
```
## 18. Use Gandi LiveDNS API
You must enable the new Gandi LiveDNS API first and the create your api key, See: http://doc.livedns.gandi.net/
```
export GANDI_LIVEDNS_KEY="fdmlfsdklmfdkmqsdfk"
```
Ok, let's issue a cert now:
```
acme.sh --issue --dns dns_gandi_livedns -d example.com -d www.example.com
```
# Use custom API
If your API is not supported yet, you can write your own DNS API.
......
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment