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: If it is a bug report:
- make sure you are able to repro it on the latest released version. - 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` ...@@ -8,13 +10,11 @@ You can install the latest version by: `acme.sh --upgrade`
- Refer to the [WIKI](https://wiki.acme.sh). - Refer to the [WIKI](https://wiki.acme.sh).
- Debug info [Debug](https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh). - Debug info [Debug](https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh).
--> -->
Steps to reproduce Steps to reproduce
------------------ ------------------
Debug log Debug log
----------------- -----------------
......
...@@ -26,14 +26,13 @@ install: ...@@ -26,14 +26,13 @@ install:
_old_path="$PATH"; _old_path="$PATH";
echo "PATH=$PATH"; echo "PATH=$PATH";
export PATH=""; export PATH="";
export OPENSSL_BIN="/usr/local/openssl"; export ACME_OPENSSL_BIN="/usr/local/openssl";
openssl version 2>&1 || true; openssl version 2>&1 || true;
$OPENSSL_BIN version 2>&1 || true; $ACME_OPENSSL_BIN version 2>&1 || true;
export PATH="$_old_path"; export PATH="$_old_path";
fi fi
script: script:
- echo "TEST_LOCAL=$TEST_LOCAL"
- echo "NGROK_TOKEN=$(echo "$NGROK_TOKEN" | wc -c)" - echo "NGROK_TOKEN=$(echo "$NGROK_TOKEN" | wc -c)"
- command -V openssl && openssl version - command -V openssl && openssl version
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then curl -sSL $SHFMT_URL -o ~/shfmt ; fi - if [ "$TRAVIS_OS_NAME" = "linux" ]; then curl -sSL $SHFMT_URL -o ~/shfmt ; fi
...@@ -44,8 +43,8 @@ script: ...@@ -44,8 +43,8 @@ script:
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck **/*.sh && echo "shellcheck OK" ; fi - if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck **/*.sh && echo "shellcheck OK" ; fi
- cd .. - cd ..
- git clone https://github.com/Neilpang/acmetest.git && cp -r acme.sh acmetest/ && cd acmetest - 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" = "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 NGROK_TOKEN="$NGROK_TOKEN" OPENSSL_BIN="$OPENSSL_BIN" ./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: matrix:
......
...@@ -54,7 +54,9 @@ https://github.com/Neilpang/acmetest ...@@ -54,7 +54,9 @@ https://github.com/Neilpang/acmetest
- Webroot mode - Webroot mode
- Standalone mode - Standalone mode
- Apache mode - Apache mode
- Nginx mode ( Beta )
- DNS mode - DNS mode
- [Stateless mode](https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode)
# 1. How to install # 1. How to install
...@@ -146,7 +148,7 @@ You **MUST** use this command to copy the certs to the target files, **DO NOT** ...@@ -146,7 +148,7 @@ You **MUST** use this command to copy the certs to the target files, **DO NOT**
**Apache** example: **Apache** example:
```bash ```bash
acme.sh --installcert -d example.com \ acme.sh --install-cert -d example.com \
--certpath /path/to/certfile/in/apache/cert.pem \ --certpath /path/to/certfile/in/apache/cert.pem \
--keypath /path/to/keyfile/in/apache/key.pem \ --keypath /path/to/keyfile/in/apache/key.pem \
--fullchainpath /path/to/fullchain/certfile/apache/fullchain.pem \ --fullchainpath /path/to/fullchain/certfile/apache/fullchain.pem \
...@@ -155,7 +157,7 @@ acme.sh --installcert -d example.com \ ...@@ -155,7 +157,7 @@ acme.sh --installcert -d example.com \
**Nginx** example: **Nginx** example:
```bash ```bash
acme.sh --installcert -d example.com \ acme.sh --install-cert -d example.com \
--keypath /path/to/keyfile/in/nginx/key.pem \ --keypath /path/to/keyfile/in/nginx/key.pem \
--fullchainpath /path/to/fullchain/nginx/cert.pem \ --fullchainpath /path/to/fullchain/nginx/cert.pem \
--reloadcmd "service nginx force-reload" --reloadcmd "service nginx force-reload"
...@@ -214,8 +216,27 @@ acme.sh --issue --apache -d example.com -d www.example.com -d cp.example.com ...@@ -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 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. Support the `dns-01` challenge.
...@@ -246,7 +267,7 @@ acme.sh --renew -d example.com ...@@ -246,7 +267,7 @@ acme.sh --renew -d example.com
Ok, it's finished. 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. 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! ...@@ -271,6 +292,9 @@ You don't have to do anything manually!
1. Alwaysdata.com API 1. Alwaysdata.com API
1. Linode.com API 1. Linode.com API
1. FreeDNS (https://freedns.afraid.org/) 1. FreeDNS (https://freedns.afraid.org/)
1. cyon.ch
1. Domain-Offensive/Resellerinterface/Domainrobot API
1. Gandi LiveDNS API
**More APIs coming soon...** **More APIs coming soon...**
...@@ -279,7 +303,7 @@ If your DNS provider is not on the supported list above, you can write your own ...@@ -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) 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. `Let's Encrypt` can now issue **ECDSA** certificates.
...@@ -310,7 +334,7 @@ Valid values are: ...@@ -310,7 +334,7 @@ Valid values are:
3. **ec-521 (secp521r1, "ECDSA P-521", which is not supported by Let's Encrypt yet.)** 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. 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 ...@@ -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. 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 ...@@ -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 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". Speak ACME language using shell, directly to "Let's Encrypt".
TODO: TODO:
# Acknowledgments # 15. Acknowledgments
1. Acme-tiny: https://github.com/diafygi/acme-tiny 1. Acme-tiny: https://github.com/diafygi/acme-tiny
2. ACME protocol: https://github.com/ietf-wg-acme/acme 2. ACME protocol: https://github.com/ietf-wg-acme/acme
3. Certbot: https://github.com/certbot/certbot 3. Certbot: https://github.com/certbot/certbot
# License & Others # 16. License & Others
License is GPLv3 License is GPLv3
...@@ -380,8 +404,9 @@ Please Star and Fork me. ...@@ -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. [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) [Donate List](https://github.com/Neilpang/acme.sh/wiki/Donate-list)
#!/usr/bin/env sh #!/usr/bin/env sh
VER=2.6.6 VER=2.6.7
PROJECT_NAME="acme.sh" PROJECT_NAME="acme.sh"
...@@ -41,8 +41,14 @@ NO_VALUE="no" ...@@ -41,8 +41,14 @@ NO_VALUE="no"
W_TLS="tls" W_TLS="tls"
MODE_STATELESS="stateless"
STATE_VERIFIED="verified_ok" STATE_VERIFIED="verified_ok"
NGINX="nginx:"
NGINX_START="#ACME_NGINX_START"
NGINX_END="#ACME_NGINX_END"
BEGIN_CSR="-----BEGIN CERTIFICATE REQUEST-----" BEGIN_CSR="-----BEGIN CERTIFICATE REQUEST-----"
END_CSR="-----END CERTIFICATE REQUEST-----" END_CSR="-----END CERTIFICATE REQUEST-----"
...@@ -59,8 +65,39 @@ LOG_LEVEL_2=2 ...@@ -59,8 +65,39 @@ LOG_LEVEL_2=2
LOG_LEVEL_3=3 LOG_LEVEL_3=3
DEFAULT_LOG_LEVEL="$LOG_LEVEL_1" 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" _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="" __INTERACTIVE=""
if [ -t 1 ]; then if [ -t 1 ]; then
__INTERACTIVE="1" __INTERACTIVE="1"
...@@ -100,11 +137,11 @@ _printargs() { ...@@ -100,11 +137,11 @@ _printargs() {
_dlg_versions() { _dlg_versions() {
echo "Diagnosis versions: " echo "Diagnosis versions: "
echo "openssl:$OPENSSL_BIN" echo "openssl:$ACME_OPENSSL_BIN"
if _exists "$OPENSSL_BIN"; then if _exists "$ACME_OPENSSL_BIN"; then
$OPENSSL_BIN version 2>&1 $ACME_OPENSSL_BIN version 2>&1
else else
echo "$OPENSSL_BIN doesn't exists." echo "$ACME_OPENSSL_BIN doesn't exists."
fi fi
echo "apache:" echo "apache:"
...@@ -122,6 +159,16 @@ _dlg_versions() { ...@@ -122,6 +159,16 @@ _dlg_versions() {
fi 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() { _log() {
[ -z "$LOG_FILE" ] && return [ -z "$LOG_FILE" ] && return
_printargs "$@" >>"$LOG_FILE" _printargs "$@" >>"$LOG_FILE"
...@@ -129,10 +176,14 @@ _log() { ...@@ -129,10 +176,14 @@ _log() {
_info() { _info() {
_log "$@" _log "$@"
if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_INFO" ]; then
_syslog "$SYSLOG_INFO" "$@"
fi
_printargs "$@" _printargs "$@"
} }
_err() { _err() {
_syslog "$SYSLOG_ERROR" "$@"
_log "$@" _log "$@"
if [ -z "$NO_TIMESTAMP" ] || [ "$NO_TIMESTAMP" = "0" ]; then if [ -z "$NO_TIMESTAMP" ] || [ "$NO_TIMESTAMP" = "0" ]; then
printf -- "%s" "[$(date)] " >&2 printf -- "%s" "[$(date)] " >&2
...@@ -152,30 +203,99 @@ _usage() { ...@@ -152,30 +203,99 @@ _usage() {
} }
_debug() { _debug() {
if [ -z "$LOG_LEVEL" ] || [ "$LOG_LEVEL" -ge "$LOG_LEVEL_1" ]; then if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_1" ]; then
_log "$@" _log "$@"
fi fi
if [ -z "$DEBUG" ]; then if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG" ]; then
return _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 fi
_printargs "$@" >&2
} }
_debug2() { _debug2() {
if [ "$LOG_LEVEL" ] && [ "$LOG_LEVEL" -ge "$LOG_LEVEL_2" ]; then if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_2" ]; then
_log "$@" _log "$@"
fi fi
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG_2" ]; then
_debug "$@" _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 fi
} }
_debug3() { _debug3() {
if [ "$LOG_LEVEL" ] && [ "$LOG_LEVEL" -ge "$LOG_LEVEL_3" ]; then if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_3" ]; then
_log "$@" _log "$@"
fi fi
if [ "$DEBUG" ] && [ "$DEBUG" -ge "3" ]; then if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG_3" ]; then
_debug "$@" _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 fi
} }
...@@ -358,8 +478,16 @@ _ascii_hex() { ...@@ -358,8 +478,16 @@ _ascii_hex() {
#input:"abc" #input:"abc"
#output: " 61 62 63" #output: " 61 62 63"
_hex_dump() { _hex_dump() {
#in wired some system, the od command is missing. if _exists od; then
if ! od -A n -v -t x1 | tr -d "\r\t" | tr -s " " | sed "s/ $//" | tr -d "\n" 2>/dev/null; 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) str=$(cat)
_ascii_hex "$str" _ascii_hex "$str"
fi fi
...@@ -652,19 +780,19 @@ _base64() { ...@@ -652,19 +780,19 @@ _base64() {
[ "" ] #urgly [ "" ] #urgly
if [ "$1" ]; then if [ "$1" ]; then
_debug3 "base64 multiline:'$1'" _debug3 "base64 multiline:'$1'"
$OPENSSL_BIN base64 -e $ACME_OPENSSL_BIN base64 -e
else else
_debug3 "base64 single line." _debug3 "base64 single line."
$OPENSSL_BIN base64 -e | tr -d '\r\n' $ACME_OPENSSL_BIN base64 -e | tr -d '\r\n'
fi fi
} }
#Usage: multiline #Usage: multiline
_dbase64() { _dbase64() {
if [ "$1" ]; then if [ "$1" ]; then
$OPENSSL_BIN base64 -d -A $ACME_OPENSSL_BIN base64 -d -A
else else
$OPENSSL_BIN base64 -d $ACME_OPENSSL_BIN base64 -d
fi fi
} }
...@@ -681,9 +809,9 @@ _digest() { ...@@ -681,9 +809,9 @@ _digest() {
if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ] || [ "$alg" = "md5" ]; then if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ] || [ "$alg" = "md5" ]; then
if [ "$outputhex" ]; 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 else
$OPENSSL_BIN dgst -"$alg" -binary | _base64 $ACME_OPENSSL_BIN dgst -"$alg" -binary | _base64
fi fi
else else
_err "$alg is not supported yet" _err "$alg is not supported yet"
...@@ -706,9 +834,9 @@ _hmac() { ...@@ -706,9 +834,9 @@ _hmac() {
if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ]; then if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ]; then
if [ "$outputhex" ]; 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 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 fi
else else
_err "$alg is not supported yet" _err "$alg is not supported yet"
...@@ -727,7 +855,7 @@ _sign() { ...@@ -727,7 +855,7 @@ _sign() {
return 1 return 1
fi fi
_sign_openssl="$OPENSSL_BIN dgst -sign $keyfile " _sign_openssl="$ACME_OPENSSL_BIN dgst -sign $keyfile "
if [ "$alg" = "sha256" ]; then if [ "$alg" = "sha256" ]; then
_sign_openssl="$_sign_openssl -$alg" _sign_openssl="$_sign_openssl -$alg"
else else
...@@ -738,7 +866,7 @@ _sign() { ...@@ -738,7 +866,7 @@ _sign() {
if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
$_sign_openssl | _base64 $_sign_openssl | _base64
elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then 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 "Sign failed: $_sign_openssl"
_err "Key file: $keyfile" _err "Key file: $keyfile"
_err "Key content:$(wc -l <"$keyfile") lises" _err "Key content:$(wc -l <"$keyfile") lises"
...@@ -799,12 +927,21 @@ _createkey() { ...@@ -799,12 +927,21 @@ _createkey() {
_debug "Use length $length" _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 if _isEccKey "$length"; then
_debug "Using ec name: $eccname" _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 else
_debug "Using RSA: $length" _debug "Using RSA: $length"
$OPENSSL_BIN genrsa "$length" 2>/dev/null >"$f" $ACME_OPENSSL_BIN genrsa "$length" 2>/dev/null >"$f"
fi fi
if [ "$?" != "0" ]; then if [ "$?" != "0" ]; then
...@@ -890,7 +1027,11 @@ _createcsr() { ...@@ -890,7 +1027,11 @@ _createcsr() {
_csr_cn="$(_idn "$domain")" _csr_cn="$(_idn "$domain")"
_debug2 _csr_cn "$_csr_cn" _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 #_signcsr key csr conf cert
...@@ -901,7 +1042,7 @@ _signcsr() { ...@@ -901,7 +1042,7 @@ _signcsr() {
cert="$4" cert="$4"
_debug "_signcsr" _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="$?" _ret="$?"
_debug "$_msg" _debug "$_msg"
return $_ret return $_ret
...@@ -914,7 +1055,7 @@ _readSubjectFromCSR() { ...@@ -914,7 +1055,7 @@ _readSubjectFromCSR() {
_usage "_readSubjectFromCSR mycsr.csr" _usage "_readSubjectFromCSR mycsr.csr"
return 1 return 1
fi 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 #_csrfile
...@@ -929,7 +1070,7 @@ _readSubjectAltNamesFromCSR() { ...@@ -929,7 +1070,7 @@ _readSubjectAltNamesFromCSR() {
_csrsubj="$(_readSubjectFromCSR "$_csrfile")" _csrsubj="$(_readSubjectFromCSR "$_csrfile")"
_debug _csrsubj "$_csrsubj" _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" _debug _dnsAltnames "$_dnsAltnames"
if _contains "$_dnsAltnames," "DNS:$_csrsubj,"; then if _contains "$_dnsAltnames," "DNS:$_csrsubj,"; then
...@@ -950,13 +1091,13 @@ _readKeyLengthFromCSR() { ...@@ -950,13 +1091,13 @@ _readKeyLengthFromCSR() {
return 1 return 1
fi 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 if _contains "$_outcsr" "Public Key Algorithm: id-ecPublicKey"; then
_debug "ECC CSR" _debug "ECC CSR"
echo "$_outcsr" | _egrep_o "^ *ASN1 OID:.*" | cut -d ':' -f 2 | tr -d ' ' echo "$_outcsr" | _egrep_o "^ *ASN1 OID:.*" | cut -d ':' -f 2 | tr -d ' '
else else
_debug "RSA CSR" _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 fi
} }
...@@ -1004,9 +1145,9 @@ toPkcs() { ...@@ -1004,9 +1145,9 @@ toPkcs() {
_initpath "$domain" "$_isEcc" _initpath "$domain" "$_isEcc"
if [ "$pfxPassword" ]; then 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 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 fi
if [ "$?" = "0" ]; then if [ "$?" = "0" ]; then
...@@ -1015,6 +1156,27 @@ toPkcs() { ...@@ -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] #[2048]
createAccountKey() { createAccountKey() {
_info "Creating account key" _info "Creating account key"
...@@ -1168,7 +1330,7 @@ _calcjwk() { ...@@ -1168,7 +1330,7 @@ _calcjwk() {
if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
_debug "RSA key" _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 if [ "${#pub_exp}" = "5" ]; then
pub_exp=0$pub_exp pub_exp=0$pub_exp
fi fi
...@@ -1177,7 +1339,7 @@ _calcjwk() { ...@@ -1177,7 +1339,7 @@ _calcjwk() {
e=$(echo "$pub_exp" | _h2b | _base64) e=$(echo "$pub_exp" | _h2b | _base64)
_debug3 e "$e" _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" _debug3 modulus "$modulus"
n="$(printf "%s" "$modulus" | _h2b | _base64 | _url_replace)" n="$(printf "%s" "$modulus" | _h2b | _base64 | _url_replace)"
_debug3 n "$n" _debug3 n "$n"
...@@ -1190,12 +1352,12 @@ _calcjwk() { ...@@ -1190,12 +1352,12 @@ _calcjwk() {
JWK_HEADERPLACE_PART2='", "alg": "RS256", "jwk": '$jwk'}' JWK_HEADERPLACE_PART2='", "alg": "RS256", "jwk": '$jwk'}'
elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
_debug "EC key" _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" _debug3 crv "$crv"
if [ -z "$crv" ]; then if [ -z "$crv" ]; then
_debug "Let's try ASN1 OID" _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" _debug3 crv_oid "$crv_oid"
case "${crv_oid}" in case "${crv_oid}" in
"prime256v1") "prime256v1")
...@@ -1215,15 +1377,15 @@ _calcjwk() { ...@@ -1215,15 +1377,15 @@ _calcjwk() {
_debug3 crv "$crv" _debug3 crv "$crv"
fi 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) pubi=$(_math "$pubi" + 1)
_debug3 pubi "$pubi" _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) pubj=$(_math "$pubj" - 1)
_debug3 pubj "$pubj" _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" _debug3 pubtext "$pubtext"
xlen="$(printf "%s" "$pubtext" | tr -d ':' | wc -c)" xlen="$(printf "%s" "$pubtext" | tr -d ':' | wc -c)"
...@@ -1263,6 +1425,10 @@ _time() { ...@@ -1263,6 +1425,10 @@ _time() {
date -u "+%s" date -u "+%s"
} }
_utc_date() {
date -u "+%Y-%m-%d %H:%M:%S"
}
_mktemp() { _mktemp() {
if _exists mktemp; then if _exists mktemp; then
if mktemp 2>/dev/null; then if mktemp 2>/dev/null; then
...@@ -1319,6 +1485,11 @@ _inithttp() { ...@@ -1319,6 +1485,11 @@ _inithttp() {
fi fi
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 __HTTP_INITIALIZED=1
} }
...@@ -1339,7 +1510,7 @@ _post() { ...@@ -1339,7 +1510,7 @@ _post() {
_inithttp _inithttp
if [ "$_ACME_CURL" ]; then if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then
_CURL="$_ACME_CURL" _CURL="$_ACME_CURL"
if [ "$HTTPS_INSECURE" ]; then if [ "$HTTPS_INSECURE" ]; then
_CURL="$_CURL --insecure " _CURL="$_CURL --insecure "
...@@ -1380,7 +1551,7 @@ _post() { ...@@ -1380,7 +1551,7 @@ _post() {
_ret="$?" _ret="$?"
if [ "$_ret" = "8" ]; then if [ "$_ret" = "8" ]; then
_ret=0 _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 fi
if [ "$_ret" != "0" ]; then if [ "$_ret" != "0" ]; then
_err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $_ret" _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() { ...@@ -1406,7 +1577,7 @@ _get() {
_inithttp _inithttp
if [ "$_ACME_CURL" ]; then if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then
_CURL="$_ACME_CURL" _CURL="$_ACME_CURL"
if [ "$HTTPS_INSECURE" ]; then if [ "$HTTPS_INSECURE" ]; then
_CURL="$_CURL --insecure " _CURL="$_CURL --insecure "
...@@ -1443,9 +1614,9 @@ _get() { ...@@ -1443,9 +1614,9 @@ _get() {
$_WGET --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" -O - "$url" $_WGET --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" -O - "$url"
fi fi
ret=$? ret=$?
if [ "$_ret" = "8" ]; then if [ "$ret" = "8" ]; then
_ret=0 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 fi
if [ "$ret" != "0" ]; then if [ "$ret" != "0" ]; then
_err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $ret" _err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $ret"
...@@ -1488,62 +1659,75 @@ _send_signed_request() { ...@@ -1488,62 +1659,75 @@ _send_signed_request() {
payload64=$(printf "%s" "$payload" | _base64 | _url_replace) payload64=$(printf "%s" "$payload" | _base64 | _url_replace)
_debug3 payload64 "$payload64" _debug3 payload64 "$payload64"
if [ -z "$_CACHED_NONCE" ]; then MAX_REQUEST_RETRY_TIMES=5
_debug2 "Get nonce." _request_retry_times=0
nonceurl="$API/directory" while [ "${_request_retry_times}" -lt "$MAX_REQUEST_RETRY_TIMES" ]; do
_headers="$(_get "$nonceurl" "onlyheader")" _debug3 _request_retry_times "$_request_retry_times"
if [ -z "$_CACHED_NONCE" ]; then
_debug2 "Get nonce."
nonceurl="$API/directory"
_headers="$(_get "$nonceurl" "onlyheader")"
if [ "$?" != "0" ]; then if [ "$?" != "0" ]; then
_err "Can not connect to $nonceurl to get nonce." _err "Can not connect to $nonceurl to get nonce."
return 1 return 1
fi fi
_debug2 _headers "$_headers" _debug2 _headers "$_headers"
_CACHED_NONCE="$(echo "$_headers" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)" _CACHED_NONCE="$(echo "$_headers" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)"
_debug2 _CACHED_NONCE "$_CACHED_NONCE" _debug2 _CACHED_NONCE "$_CACHED_NONCE"
else else
_debug2 "Use _CACHED_NONCE" "$_CACHED_NONCE" _debug2 "Use _CACHED_NONCE" "$_CACHED_NONCE"
fi fi
nonce="$_CACHED_NONCE" nonce="$_CACHED_NONCE"
_debug2 nonce "$nonce" _debug2 nonce "$nonce"
protected="$JWK_HEADERPLACE_PART1$nonce$JWK_HEADERPLACE_PART2" protected="$JWK_HEADERPLACE_PART1$nonce$JWK_HEADERPLACE_PART2"
_debug3 protected "$protected" _debug3 protected "$protected"
protected64="$(printf "%s" "$protected" | _base64 | _url_replace)" protected64="$(printf "%s" "$protected" | _base64 | _url_replace)"
_debug3 protected64 "$protected64" _debug3 protected64 "$protected64"
if ! _sig_t="$(printf "%s" "$protected64.$payload64" | _sign "$keyfile" "sha256")"; then if ! _sig_t="$(printf "%s" "$protected64.$payload64" | _sign "$keyfile" "sha256")"; then
_err "Sign request failed." _err "Sign request failed."
return 1 return 1
fi fi
_debug3 _sig_t "$_sig_t" _debug3 _sig_t "$_sig_t"
sig="$(printf "%s" "$_sig_t" | _url_replace)" sig="$(printf "%s" "$_sig_t" | _url_replace)"
_debug3 sig "$sig" _debug3 sig "$sig"
body="{\"header\": $JWK_HEADER, \"protected\": \"$protected64\", \"payload\": \"$payload64\", \"signature\": \"$sig\"}" body="{\"header\": $JWK_HEADER, \"protected\": \"$protected64\", \"payload\": \"$payload64\", \"signature\": \"$sig\"}"
_debug3 body "$body" _debug3 body "$body"
response="$(_post "$body" "$url" "$needbase64")" response="$(_post "$body" "$url" "$needbase64")"
_CACHED_NONCE="" _CACHED_NONCE=""
if [ "$?" != "0" ]; then
_err "Can not post to $url"
return 1
fi
_debug2 original "$response"
response="$(echo "$response" | _normalizeJson)" if [ "$?" != "0" ]; then
_err "Can not post to $url"
return 1
fi
_debug2 original "$response"
response="$(echo "$response" | _normalizeJson)"
responseHeaders="$(cat "$HTTP_HEADER")" responseHeaders="$(cat "$HTTP_HEADER")"
_debug2 responseHeaders "$responseHeaders" _debug2 responseHeaders "$responseHeaders"
_debug2 response "$response" _debug2 response "$response"
code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\r\n")" code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\r\n")"
_debug code "$code" _debug code "$code"
_CACHED_NONCE="$(echo "$responseHeaders" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)" _CACHED_NONCE="$(echo "$responseHeaders" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)"
if _contains "$response" "JWS has invalid anti-replay nonce"; then
_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
} }
...@@ -1568,20 +1752,20 @@ _setopt() { ...@@ -1568,20 +1752,20 @@ _setopt() {
__val="$(echo "$__val" | sed 's/&/\\&/g')" __val="$(echo "$__val" | sed 's/&/\\&/g')"
fi fi
text="$(cat "$__conf")" 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 elif grep -n "^#$__opt$__sep" "$__conf" >/dev/null; then
if _contains "$__val" "&"; then if _contains "$__val" "&"; then
__val="$(echo "$__val" | sed 's/&/\\&/g')" __val="$(echo "$__val" | sed 's/&/\\&/g')"
fi fi
text="$(cat "$__conf")" 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 else
_debug3 APP _debug3 APP
echo "$__opt$__sep$__val$__end" >>"$__conf" echo "$__opt$__sep$__val$__end" >>"$__conf"
fi fi
_debug2 "$(grep -n "^$__opt$__sep" "$__conf")" _debug3 "$(grep -n "^$__opt$__sep" "$__conf")"
} }
#_save_conf file key value #_save_conf file key value
...@@ -1684,6 +1868,14 @@ _startserver() { ...@@ -1684,6 +1868,14 @@ _startserver() {
_NC="$_NC -6" _NC="$_NC -6"
fi fi
if [ "$Le_Listen_V4$Le_Listen_V6$ncaddr" ]; then
if ! _contains "$nchelp" "-4"; then
_err "The nc doesn't support '-4', '-6' or local-address, please install 'netcat-openbsd' and try again."
_err "See $(__green $_PREPARE_LINK)"
return 1
fi
fi
if echo "$nchelp" | grep "\-q[ ,]" >/dev/null; then if echo "$nchelp" | grep "\-q[ ,]" >/dev/null; then
_NC="$_NC -q 1 -l $ncaddr" _NC="$_NC -q 1 -l $ncaddr"
else else
...@@ -1807,7 +1999,7 @@ _starttlsserver() { ...@@ -1807,7 +1999,7 @@ _starttlsserver() {
return 1 return 1
fi 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 if [ "$opaddr" ]; then
__S_OPENSSL="$__S_OPENSSL -accept $opaddr:$port" __S_OPENSSL="$__S_OPENSSL -accept $opaddr:$port"
else else
...@@ -1986,8 +2178,8 @@ _initpath() { ...@@ -1986,8 +2178,8 @@ _initpath() {
CERT_HOME="$_DEFAULT_CERT_HOME" CERT_HOME="$_DEFAULT_CERT_HOME"
fi fi
if [ -z "$OPENSSL_BIN" ]; then if [ -z "$ACME_OPENSSL_BIN" ] || [ ! -f "$ACME_OPENSSL_BIN" ] || [ ! -x "$ACME_OPENSSL_BIN" ]; then
OPENSSL_BIN="$DEFAULT_OPENSSL_BIN" ACME_OPENSSL_BIN="$DEFAULT_OPENSSL_BIN"
fi fi
if [ -z "$1" ]; then if [ -z "$1" ]; then
...@@ -2013,6 +2205,10 @@ _initpath() { ...@@ -2013,6 +2205,10 @@ _initpath() {
_debug DOMAIN_PATH "$DOMAIN_PATH" _debug DOMAIN_PATH "$DOMAIN_PATH"
fi fi
if [ -z "$DOMAIN_BACKUP_PATH" ]; then
DOMAIN_BACKUP_PATH="$DOMAIN_PATH/backup"
fi
if [ -z "$DOMAIN_CONF" ]; then if [ -z "$DOMAIN_CONF" ]; then
DOMAIN_CONF="$DOMAIN_PATH/$domain.conf" DOMAIN_CONF="$DOMAIN_PATH/$domain.conf"
fi fi
...@@ -2039,6 +2235,9 @@ _initpath() { ...@@ -2039,6 +2235,9 @@ _initpath() {
if [ -z "$CERT_PFX_PATH" ]; then if [ -z "$CERT_PFX_PATH" ]; then
CERT_PFX_PATH="$DOMAIN_PATH/$domain.pfx" CERT_PFX_PATH="$DOMAIN_PATH/$domain.pfx"
fi fi
if [ -z "$CERT_PKCS8_PATH" ]; then
CERT_PKCS8_PATH="$DOMAIN_PATH/$domain.pkcs8"
fi
if [ -z "$TLS_CONF" ]; then if [ -z "$TLS_CONF" ]; then
TLS_CONF="$DOMAIN_PATH/tls.valdation.conf" TLS_CONF="$DOMAIN_PATH/tls.valdation.conf"
...@@ -2227,10 +2426,228 @@ Allow from all ...@@ -2227,10 +2426,228 @@ Allow from all
return 0 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() { _clearup() {
_stopserver "$serverproc" _stopserver "$serverproc"
serverproc="" serverproc=""
_restoreApache _restoreApache
_restoreNginx
_clearupdns _clearupdns
if [ -z "$DEBUG" ]; then if [ -z "$DEBUG" ]; then
rm -f "$TLS_CONF" rm -f "$TLS_CONF"
...@@ -2256,7 +2673,7 @@ _clearupdns() { ...@@ -2256,7 +2673,7 @@ _clearupdns() {
txt="$(printf "%s" "$keyauthorization" | _digest "sha256" | _url_replace)" txt="$(printf "%s" "$keyauthorization" | _digest "sha256" | _url_replace)"
_debug txt "$txt" _debug txt "$txt"
if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then
_info "$d is already verified, skip $vtype." _debug "$d is already verified, skip $vtype."
continue continue
fi fi
...@@ -2328,34 +2745,39 @@ _clearupwebbroot() { ...@@ -2328,34 +2745,39 @@ _clearupwebbroot() {
} }
_on_before_issue() { _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 _debug _on_before_issue
#run pre hook #run pre hook
if [ "$Le_PreHook" ]; then if [ "$_chk_pre_hook" ]; then
_info "Run pre hook:'$Le_PreHook'" _info "Run pre hook:'$_chk_pre_hook'"
if ! ( if ! (
cd "$DOMAIN_PATH" && eval "$Le_PreHook" cd "$DOMAIN_PATH" && eval "$_chk_pre_hook"
); then ); then
_err "Error when run pre hook." _err "Error when run pre hook."
return 1 return 1
fi fi
fi fi
if _hasfield "$Le_Webroot" "$NO_VALUE"; then if _hasfield "$_chk_web_roots" "$NO_VALUE"; then
if ! _exists "nc"; then if ! _exists "nc"; then
_err "Please install netcat(nc) tools first." _err "Please install netcat(nc) tools first."
return 1 return 1
fi fi
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 _index=1
_currentRoot="" _currentRoot=""
_addrIndex=1 _addrIndex=1
for d in $alldomains; do for d in $alldomains; do
_debug "Check for domain" "$d" _debug "Check for domain" "$d"
_currentRoot="$(_getfield "$Le_Webroot" $_index)" _currentRoot="$(_getfield "$_chk_web_roots" $_index)"
_debug "_currentRoot" "$_currentRoot" _debug "_currentRoot" "$_currentRoot"
_index=$(_math $_index + 1) _index=$(_math $_index + 1)
_checkport="" _checkport=""
...@@ -2379,7 +2801,7 @@ _on_before_issue() { ...@@ -2379,7 +2801,7 @@ _on_before_issue() {
if [ "$_checkport" ]; then if [ "$_checkport" ]; then
_debug _checkport "$_checkport" _debug _checkport "$_checkport"
_checkaddr="$(_getfield "$Le_LocalAddress" $_addrIndex)" _checkaddr="$(_getfield "$_chk_local_addr" $_addrIndex)"
_debug _checkaddr "$_checkaddr" _debug _checkaddr "$_checkaddr"
_addrIndex="$(_math $_addrIndex + 1)" _addrIndex="$(_math $_addrIndex + 1)"
...@@ -2398,7 +2820,7 @@ _on_before_issue() { ...@@ -2398,7 +2820,7 @@ _on_before_issue() {
fi fi
done done
if _hasfield "$Le_Webroot" "apache"; then if _hasfield "$_chk_web_roots" "apache"; then
if ! _setApache; then if ! _setApache; then
_err "set up apache error. Report error to me." _err "set up apache error. Report error to me."
return 1 return 1
...@@ -2410,6 +2832,8 @@ _on_before_issue() { ...@@ -2410,6 +2832,8 @@ _on_before_issue() {
} }
_on_issue_err() { _on_issue_err() {
_chk_post_hook="$1"
_chk_vlist="$2"
_debug _on_issue_err _debug _on_issue_err
if [ "$LOG_FILE" ]; then if [ "$LOG_FILE" ]; then
_err "Please check log file for more details: $LOG_FILE" _err "Please check log file for more details: $LOG_FILE"
...@@ -2418,29 +2842,49 @@ _on_issue_err() { ...@@ -2418,29 +2842,49 @@ _on_issue_err() {
_err "See: $_DEBUG_WIKI" _err "See: $_DEBUG_WIKI"
fi fi
if [ "$DEBUG" ] && [ "$DEBUG" -gt "0" ]; then
_debug "$(_dlg_versions)"
fi
#run the post hook #run the post hook
if [ "$Le_PostHook" ]; then if [ "$_chk_post_hook" ]; then
_info "Run post hook:'$Le_PostHook'" _info "Run post hook:'$_chk_post_hook'"
if ! ( if ! (
cd "$DOMAIN_PATH" && eval "$Le_PostHook" cd "$DOMAIN_PATH" && eval "$_chk_post_hook"
); then ); then
_err "Error when run post hook." _err "Error when run post hook."
return 1 return 1
fi fi
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() { _on_issue_success() {
_chk_post_hook="$1"
_chk_renew_hook="$2"
_debug _on_issue_success _debug _on_issue_success
#run the post hook #run the post hook
if [ "$Le_PostHook" ]; then if [ "$_chk_post_hook" ]; then
_info "Run post hook:'$Le_PostHook'" _info "Run post hook:'$_chk_post_hook'"
if ! ( if ! (
cd "$DOMAIN_PATH" && eval "$Le_PostHook" cd "$DOMAIN_PATH" && eval "$_chk_post_hook"
); then ); then
_err "Error when run post hook." _err "Error when run post hook."
return 1 return 1
...@@ -2448,10 +2892,10 @@ _on_issue_success() { ...@@ -2448,10 +2892,10 @@ _on_issue_success() {
fi fi
#run renew hook #run renew hook
if [ "$IS_RENEW" ] && [ "$Le_RenewHook" ]; then if [ "$IS_RENEW" ] && [ "$_chk_renew_hook" ]; then
_info "Run renew hook:'$Le_RenewHook'" _info "Run renew hook:'$_chk_renew_hook'"
if ! ( if ! (
cd "$DOMAIN_PATH" && eval "$Le_RenewHook" cd "$DOMAIN_PATH" && eval "$_chk_renew_hook"
); then ); then
_err "Error when run renew hook." _err "Error when run renew hook."
return 1 return 1
...@@ -2475,6 +2919,10 @@ __calcAccountKeyHash() { ...@@ -2475,6 +2919,10 @@ __calcAccountKeyHash() {
[ -f "$ACCOUNT_KEY_PATH" ] && _digest sha256 <"$ACCOUNT_KEY_PATH" [ -f "$ACCOUNT_KEY_PATH" ] && _digest sha256 <"$ACCOUNT_KEY_PATH"
} }
__calc_account_thumbprint() {
printf "%s" "$jwk" | tr -d ' ' | _digest "sha256" | _url_replace
}
#keylength #keylength
_regAccount() { _regAccount() {
_initpath _initpath
...@@ -2565,6 +3013,8 @@ _regAccount() { ...@@ -2565,6 +3013,8 @@ _regAccount() {
return 1 return 1
fi fi
fi fi
ACCOUNT_THUMBPRINT="$(__calc_account_thumbprint)"
_info "ACCOUNT_THUMBPRINT" "$ACCOUNT_THUMBPRINT"
return 0 return 0
done done
...@@ -2636,44 +3086,54 @@ __get_domain_new_authz() { ...@@ -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 #webroot, domain domainlist keylength
issue() { issue() {
if [ -z "$2" ]; then if [ -z "$2" ]; then
_usage "Usage: $PROJECT_ENTRY --issue -d a.com -w /path/to/webroot/a.com/ " _usage "Usage: $PROJECT_ENTRY --issue -d a.com -w /path/to/webroot/a.com/ "
return 1 return 1
fi fi
Le_Webroot="$1" _web_roots="$1"
Le_Domain="$2" _main_domain="$2"
Le_Alt="$3" _alt_domains="$3"
if _contains "$Le_Domain" ","; then if _contains "$_main_domain" ","; then
Le_Domain=$(echo "$2,$3" | cut -d , -f 1) _main_domain=$(echo "$2,$3" | cut -d , -f 1)
Le_Alt=$(echo "$2,$3" | cut -d , -f 2- | sed "s/,${NO_VALUE}$//") _alt_domains=$(echo "$2,$3" | cut -d , -f 2- | sed "s/,${NO_VALUE}$//")
fi fi
Le_Keylength="$4" _key_length="$4"
Le_RealCertPath="$5" _real_cert="$5"
Le_RealKeyPath="$6" _real_key="$6"
Le_RealCACertPath="$7" _real_ca="$7"
Le_ReloadCmd="$8" _reload_cmd="$8"
Le_RealFullChainPath="$9" _real_fullchain="$9"
Le_PreHook="${10}" _pre_hook="${10}"
Le_PostHook="${11}" _post_hook="${11}"
Le_RenewHook="${12}" _renew_hook="${12}"
Le_LocalAddress="${13}" _local_addr="${13}"
#remove these later. #remove these later.
if [ "$Le_Webroot" = "dns-cf" ]; then if [ "$_web_roots" = "dns-cf" ]; then
Le_Webroot="dns_cf" _web_roots="dns_cf"
fi fi
if [ "$Le_Webroot" = "dns-dp" ]; then if [ "$_web_roots" = "dns-dp" ]; then
Le_Webroot="dns_dp" _web_roots="dns_dp"
fi fi
if [ "$Le_Webroot" = "dns-cx" ]; then if [ "$_web_roots" = "dns-cx" ]; then
Le_Webroot="dns_cx" _web_roots="dns_cx"
fi fi
_debug "Using api: $API" _debug "Using api: $API"
if [ ! "$IS_RENEW" ]; then if [ ! "$IS_RENEW" ]; then
_initpath "$Le_Domain" "$Le_Keylength" _initpath "$_main_domain" "$_key_length"
mkdir -p "$DOMAIN_PATH" mkdir -p "$DOMAIN_PATH"
fi fi
...@@ -2685,7 +3145,7 @@ issue() { ...@@ -2685,7 +3145,7 @@ issue() {
_debug _saved_domain "$_saved_domain" _debug _saved_domain "$_saved_domain"
_saved_alt=$(_readdomainconf Le_Alt) _saved_alt=$(_readdomainconf Le_Alt)
_debug _saved_alt "$_saved_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 "Domains not changed."
_info "Skip, Next renewal time is: $(__green "$(_readdomainconf Le_NextRenewTimeStr)")" _info "Skip, Next renewal time is: $(__green "$(_readdomainconf Le_NextRenewTimeStr)")"
_info "Add '$(__red '--force')' to force to renew." _info "Add '$(__red '--force')' to force to renew."
...@@ -2696,16 +3156,16 @@ issue() { ...@@ -2696,16 +3156,16 @@ issue() {
fi fi
fi fi
_savedomainconf "Le_Domain" "$Le_Domain" _savedomainconf "Le_Domain" "$_main_domain"
_savedomainconf "Le_Alt" "$Le_Alt" _savedomainconf "Le_Alt" "$_alt_domains"
_savedomainconf "Le_Webroot" "$Le_Webroot" _savedomainconf "Le_Webroot" "$_web_roots"
_savedomainconf "Le_PreHook" "$Le_PreHook" _savedomainconf "Le_PreHook" "$_pre_hook"
_savedomainconf "Le_PostHook" "$Le_PostHook" _savedomainconf "Le_PostHook" "$_post_hook"
_savedomainconf "Le_RenewHook" "$Le_RenewHook" _savedomainconf "Le_RenewHook" "$_renew_hook"
if [ "$Le_LocalAddress" ]; then if [ "$_local_addr" ]; then
_savedomainconf "Le_LocalAddress" "$Le_LocalAddress" _savedomainconf "Le_LocalAddress" "$_local_addr"
else else
_cleardomainconf "Le_LocalAddress" _cleardomainconf "Le_LocalAddress"
fi fi
...@@ -2713,15 +3173,15 @@ issue() { ...@@ -2713,15 +3173,15 @@ issue() {
Le_API="$API" Le_API="$API"
_savedomainconf "Le_API" "$Le_API" _savedomainconf "Le_API" "$Le_API"
if [ "$Le_Alt" = "$NO_VALUE" ]; then if [ "$_alt_domains" = "$NO_VALUE" ]; then
Le_Alt="" _alt_domains=""
fi fi
if [ "$Le_Keylength" = "$NO_VALUE" ]; then if [ "$_key_length" = "$NO_VALUE" ]; then
Le_Keylength="" _key_length=""
fi 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." _err "_on_before_issue."
return 1 return 1
fi fi
...@@ -2731,7 +3191,7 @@ issue() { ...@@ -2731,7 +3191,7 @@ issue() {
if [ -z "$_saved_account_key_hash" ] || [ "$_saved_account_key_hash" != "$(__calcAccountKeyHash)" ]; then if [ -z "$_saved_account_key_hash" ] || [ "$_saved_account_key_hash" != "$(__calcAccountKeyHash)" ]; then
if ! _regAccount "$_accountkeylength"; then if ! _regAccount "$_accountkeylength"; then
_on_issue_err _on_issue_err "$_post_hook"
return 1 return 1
fi fi
else else
...@@ -2743,37 +3203,38 @@ issue() { ...@@ -2743,37 +3203,38 @@ issue() {
else else
_key=$(_readdomainconf Le_Keylength) _key=$(_readdomainconf Le_Keylength)
_debug "Read key length:$_key" _debug "Read key length:$_key"
if [ ! -f "$CERT_KEY_PATH" ] || [ "$Le_Keylength" != "$_key" ]; then if [ ! -f "$CERT_KEY_PATH" ] || [ "$_key_length" != "$_key" ]; then
if ! createDomainKey "$Le_Domain" "$Le_Keylength"; then if ! createDomainKey "$_main_domain" "$_key_length"; then
_err "Create domain key error." _err "Create domain key error."
_clearup _clearup
_on_issue_err _on_issue_err "$_post_hook"
return 1 return 1
fi fi
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." _err "Create CSR error."
_clearup _clearup
_on_issue_err _on_issue_err "$_post_hook"
return 1 return 1
fi fi
fi fi
_savedomainconf "Le_Keylength" "$Le_Keylength" _savedomainconf "Le_Keylength" "$_key_length"
vlist="$Le_Vlist" vlist="$Le_Vlist"
_info "Getting domain auth token for each domain" _info "Getting domain auth token for each domain"
sep='#' sep='#'
dvsep=','
if [ -z "$vlist" ]; then if [ -z "$vlist" ]; then
alldomains=$(echo "$Le_Domain,$Le_Alt" | tr ',' ' ') alldomains=$(echo "$_main_domain,$_alt_domains" | tr ',' ' ')
_index=1 _index=1
_currentRoot="" _currentRoot=""
for d in $alldomains; do for d in $alldomains; do
_info "Getting webroot for domain" "$d" _info "Getting webroot for domain" "$d"
_w="$(echo $Le_Webroot | cut -d , -f $_index)" _w="$(echo $_web_roots | cut -d , -f $_index)"
_info _w "$_w" _debug _w "$_w"
if [ "$_w" ]; then if [ "$_w" ]; then
_currentRoot="$_w" _currentRoot="$_w"
fi fi
...@@ -2791,13 +3252,12 @@ issue() { ...@@ -2791,13 +3252,12 @@ issue() {
if ! __get_domain_new_authz "$d"; then if ! __get_domain_new_authz "$d"; then
_clearup _clearup
_on_issue_err _on_issue_err "$_post_hook"
return 1 return 1
fi fi
if [ -z "$thumbprint" ]; then if [ -z "$thumbprint" ]; then
accountkey_json=$(printf "%s" "$jwk" | tr -d ' ') thumbprint="$(__calc_account_thumbprint)"
thumbprint=$(printf "%s" "$accountkey_json" | _digest "sha256" | _url_replace)
fi fi
entry="$(printf "%s\n" "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')" entry="$(printf "%s\n" "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"
...@@ -2805,7 +3265,7 @@ issue() { ...@@ -2805,7 +3265,7 @@ issue() {
if [ -z "$entry" ]; then if [ -z "$entry" ]; then
_err "Error, can not get domain token $d" _err "Error, can not get domain token $d"
_clearup _clearup
_on_issue_err _on_issue_err "$_post_hook"
return 1 return 1
fi fi
token="$(printf "%s\n" "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')" token="$(printf "%s\n" "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')"
...@@ -2818,7 +3278,7 @@ issue() { ...@@ -2818,7 +3278,7 @@ issue() {
_debug keyauthorization "$keyauthorization" _debug keyauthorization "$keyauthorization"
if printf "%s" "$response" | grep '"status":"valid"' >/dev/null 2>&1; then 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" keyauthorization="$STATE_VERIFIED"
_debug keyauthorization "$keyauthorization" _debug keyauthorization "$keyauthorization"
fi fi
...@@ -2826,13 +3286,13 @@ issue() { ...@@ -2826,13 +3286,13 @@ issue() {
dvlist="$d$sep$keyauthorization$sep$uri$sep$vtype$sep$_currentRoot" dvlist="$d$sep$keyauthorization$sep$uri$sep$vtype$sep$_currentRoot"
_debug dvlist "$dvlist" _debug dvlist "$dvlist"
vlist="$vlist$dvlist," vlist="$vlist$dvlist$dvsep"
done done
_debug vlist "$vlist"
#add entry #add entry
dnsadded="" dnsadded=""
ventries=$(echo "$vlist" | tr ',' ' ') ventries=$(echo "$vlist" | tr "$dvsep" ' ')
for ventry in $ventries; do for ventry in $ventries; do
d=$(echo "$ventry" | cut -d "$sep" -f 1) d=$(echo "$ventry" | cut -d "$sep" -f 1)
keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2) keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2)
...@@ -2840,7 +3300,7 @@ issue() { ...@@ -2840,7 +3300,7 @@ issue() {
_currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5) _currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5)
if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then
_info "$d is already verified, skip $vtype." _debug "$d is already verified, skip $vtype."
continue continue
fi fi
...@@ -2886,7 +3346,7 @@ issue() { ...@@ -2886,7 +3346,7 @@ issue() {
if [ "$?" != "0" ]; then if [ "$?" != "0" ]; then
_clearup _clearup
_on_issue_err _on_issue_err "$_post_hook"
return 1 return 1
fi fi
dnsadded='1' dnsadded='1'
...@@ -2898,7 +3358,7 @@ issue() { ...@@ -2898,7 +3358,7 @@ issue() {
_debug "Dns record not added yet, so, save to $DOMAIN_CONF and exit." _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." _err "Please add the TXT records to the domains, and retry again."
_clearup _clearup
_on_issue_err _on_issue_err "$_post_hook"
return 1 return 1
fi fi
...@@ -2915,10 +3375,11 @@ issue() { ...@@ -2915,10 +3375,11 @@ issue() {
_sleep "$Le_DNSSleep" _sleep "$Le_DNSSleep"
fi fi
NGINX_RESTORE_VLIST=""
_debug "ok, let's start to verify" _debug "ok, let's start to verify"
_ncIndex=1 _ncIndex=1
ventries=$(echo "$vlist" | tr ',' ' ') ventries=$(echo "$vlist" | tr "$dvsep" ' ')
for ventry in $ventries; do for ventry in $ventries; do
d=$(echo "$ventry" | cut -d "$sep" -f 1) d=$(echo "$ventry" | cut -d "$sep" -f 1)
keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2) keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2)
...@@ -2943,18 +3404,38 @@ issue() { ...@@ -2943,18 +3404,38 @@ issue() {
if [ "$vtype" = "$VTYPE_HTTP" ]; then if [ "$vtype" = "$VTYPE_HTTP" ]; then
if [ "$_currentRoot" = "$NO_VALUE" ]; then if [ "$_currentRoot" = "$NO_VALUE" ]; then
_info "Standalone mode server" _info "Standalone mode server"
_ncaddr="$(_getfield "$Le_LocalAddress" "$_ncIndex")" _ncaddr="$(_getfield "$_local_addr" "$_ncIndex")"
_ncIndex="$(_math $_ncIndex + 1)" _ncIndex="$(_math $_ncIndex + 1)"
_startserver "$keyauthorization" "$_ncaddr" & _startserver "$keyauthorization" "$_ncaddr" &
if [ "$?" != "0" ]; then if [ "$?" != "0" ]; then
_clearup _clearup
_on_issue_err _on_issue_err "$_post_hook" "$vlist"
return 1 return 1
fi fi
serverproc="$!" serverproc="$!"
sleep 1 sleep 1
_debug serverproc "$serverproc" _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 else
if [ "$_currentRoot" = "apache" ]; then if [ "$_currentRoot" = "apache" ]; then
wellknown_path="$ACME_DIR" wellknown_path="$ACME_DIR"
...@@ -2979,7 +3460,7 @@ issue() { ...@@ -2979,7 +3460,7 @@ issue() {
_err "$d:Can not write token to file : $wellknown_path/$token" _err "$d:Can not write token to file : $wellknown_path/$token"
_clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup _clearup
_on_issue_err _on_issue_err "$_post_hook" "$vlist"
return 1 return 1
fi fi
...@@ -3018,22 +3499,22 @@ issue() { ...@@ -3018,22 +3499,22 @@ issue() {
_SAN_B="$_x.$_y.acme.invalid" _SAN_B="$_x.$_y.acme.invalid"
_debug2 _SAN_B "$_SAN_B" _debug2 _SAN_B "$_SAN_B"
_ncaddr="$(_getfield "$Le_LocalAddress" "$_ncIndex")" _ncaddr="$(_getfield "$_local_addr" "$_ncIndex")"
_ncIndex="$(_math "$_ncIndex" + 1)" _ncIndex="$(_math "$_ncIndex" + 1)"
if ! _starttlsserver "$_SAN_B" "$_SAN_A" "$Le_TLSPort" "$keyauthorization" "$_ncaddr"; then if ! _starttlsserver "$_SAN_B" "$_SAN_A" "$Le_TLSPort" "$keyauthorization" "$_ncaddr"; then
_err "Start tls server error." _err "Start tls server error."
_clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup _clearup
_on_issue_err _on_issue_err "$_post_hook" "$vlist"
return 1 return 1
fi fi
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" _err "$d:Can not get challenge: $response"
_clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup _clearup
_on_issue_err _on_issue_err "$_post_hook" "$vlist"
return 1 return 1
fi fi
...@@ -3041,7 +3522,7 @@ issue() { ...@@ -3041,7 +3522,7 @@ issue() {
_err "$d:Challenge error: $response" _err "$d:Challenge error: $response"
_clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup _clearup
_on_issue_err _on_issue_err "$_post_hook" "$vlist"
return 1 return 1
fi fi
...@@ -3056,7 +3537,7 @@ issue() { ...@@ -3056,7 +3537,7 @@ issue() {
_err "$d:Timeout" _err "$d:Timeout"
_clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup _clearup
_on_issue_err _on_issue_err "$_post_hook" "$vlist"
return 1 return 1
fi fi
...@@ -3068,7 +3549,7 @@ issue() { ...@@ -3068,7 +3549,7 @@ issue() {
_err "$d:Verify error:$response" _err "$d:Verify error:$response"
_clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup _clearup
_on_issue_err _on_issue_err "$_post_hook" "$vlist"
return 1 return 1
fi fi
_debug2 original "$response" _debug2 original "$response"
...@@ -3103,7 +3584,7 @@ issue() { ...@@ -3103,7 +3584,7 @@ issue() {
fi fi
_clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup _clearup
_on_issue_err _on_issue_err "$_post_hook" "$vlist"
return 1 return 1
fi fi
...@@ -3113,7 +3594,7 @@ issue() { ...@@ -3113,7 +3594,7 @@ issue() {
_err "$d:Verify error:$response" _err "$d:Verify error:$response"
_clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup _clearup
_on_issue_err _on_issue_err "$_post_hook" "$vlist"
return 1 return 1
fi fi
...@@ -3127,7 +3608,7 @@ issue() { ...@@ -3127,7 +3608,7 @@ issue() {
if ! _send_signed_request "$API/acme/new-cert" "{\"resource\": \"new-cert\", \"csr\": \"$der\"}" "needbase64"; then if ! _send_signed_request "$API/acme/new-cert" "{\"resource\": \"new-cert\", \"csr\": \"$der\"}" "needbase64"; then
_err "Sign failed." _err "Sign failed."
_on_issue_err _on_issue_err "$_post_hook"
return 1 return 1
fi fi
...@@ -3169,7 +3650,7 @@ issue() { ...@@ -3169,7 +3650,7 @@ issue() {
if [ -z "$Le_LinkCert" ]; then if [ -z "$Le_LinkCert" ]; then
response="$(echo "$response" | _dbase64 "multiline" | _normalizeJson)" response="$(echo "$response" | _dbase64 "multiline" | _normalizeJson)"
_err "Sign failed: $(echo "$response" | _egrep_o '"detail":"[^"]*"')" _err "Sign failed: $(echo "$response" | _egrep_o '"detail":"[^"]*"')"
_on_issue_err _on_issue_err "$_post_hook"
return 1 return 1
fi fi
...@@ -3231,10 +3712,15 @@ issue() { ...@@ -3231,10 +3712,15 @@ issue() {
Le_NextRenewTime=$(_math "$Le_NextRenewTime" - 86400) Le_NextRenewTime=$(_math "$Le_NextRenewTime" - 86400)
_savedomainconf "Le_NextRenewTime" "$Le_NextRenewTime" _savedomainconf "Le_NextRenewTime" "$Le_NextRenewTime"
_on_issue_success _on_issue_success "$_post_hook" "$_renew_hook"
if [ "$Le_RealCertPath$Le_RealKeyPath$Le_RealCACertPath$Le_ReloadCmd$Le_RealFullChainPath" ]; then if [ "$_real_cert$_real_key$_real_ca$_reload_cmd$_real_fullchain" ]; then
_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"
fi fi
} }
...@@ -3287,7 +3773,7 @@ renew() { ...@@ -3287,7 +3773,7 @@ renew() {
fi fi
if [ "$Le_DeployHook" ]; then if [ "$Le_DeployHook" ]; then
deploy "$Le_Domain" "$Le_DeployHook" "$Le_Keylength" _deploy "$Le_Domain" "$Le_DeployHook"
res="$?" res="$?"
fi fi
...@@ -3459,151 +3945,169 @@ list() { ...@@ -3459,151 +3945,169 @@ list() {
} }
_deploy() {
_d="$1"
_hooks="$2"
for _d_api in $(echo "$_hooks" | tr ',' " "); do
_deployApi="$(_findHook "$_d" deploy "$_d_api")"
if [ -z "$_deployApi" ]; then
_err "The deploy hook $_d_api is not found."
return 1
fi
_debug _deployApi "$_deployApi"
if ! (
if ! . "$_deployApi"; then
_err "Load file $_deployApi error. Please check your api file and try again."
return 1
fi
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 "$_d" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$CERT_FULLCHAIN_PATH"; then
_err "Error deploy for domain:$_d"
return 1
fi
); then
_err "Deploy error."
return 1
else
_info "$(__green Success)"
fi
done
}
#domain hooks
deploy() { deploy() {
Le_Domain="$1" _d="$1"
Le_DeployHook="$2" _hooks="$2"
_isEcc="$3" _isEcc="$3"
if [ -z "$Le_DeployHook" ]; then if [ -z "$_hooks" ]; then
_usage "Usage: $PROJECT_ENTRY --deploy -d domain.com --deploy-hook cpanel [--ecc] " _usage "Usage: $PROJECT_ENTRY --deploy -d domain.com --deploy-hook cpanel [--ecc] "
return 1 return 1
fi fi
_initpath "$Le_Domain" "$_isEcc" _initpath "$_d" "$_isEcc"
if [ ! -d "$DOMAIN_PATH" ]; then if [ ! -d "$DOMAIN_PATH" ]; then
_err "Domain is not valid:'$Le_Domain'" _err "Domain is not valid:'$_d'"
return 1 return 1
fi fi
_deployApi="$(_findHook "$Le_Domain" deploy "$Le_DeployHook")" . "$DOMAIN_CONF"
if [ -z "$_deployApi" ]; then
_err "The deploy hook $Le_DeployHook 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" _savedomainconf Le_DeployHook "$_hooks"
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
return 1
fi
); then
_err "Deploy error."
return 1
else
_info "$(__green Success)"
fi
_deploy "$_d" "$_hooks"
} }
installcert() { installcert() {
Le_Domain="$1" _main_domain="$1"
if [ -z "$Le_Domain" ]; then 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]" _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 return 1
fi fi
Le_RealCertPath="$2" _real_cert="$2"
Le_RealKeyPath="$3" _real_key="$3"
Le_RealCACertPath="$4" _real_ca="$4"
Le_ReloadCmd="$5" _reload_cmd="$5"
Le_RealFullChainPath="$6" _real_fullchain="$6"
_isEcc="$7" _isEcc="$7"
_initpath "$Le_Domain" "$_isEcc" _initpath "$_main_domain" "$_isEcc"
if [ ! -d "$DOMAIN_PATH" ]; then if [ ! -d "$DOMAIN_PATH" ]; then
_err "Domain is not valid:'$Le_Domain'" _err "Domain is not valid:'$_main_domain'"
return 1 return 1
fi 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() { _installcert() {
_savedomainconf "Le_RealCertPath" "$Le_RealCertPath" _main_domain="$1"
_savedomainconf "Le_RealCACertPath" "$Le_RealCACertPath" _real_cert="$2"
_savedomainconf "Le_RealKeyPath" "$Le_RealKeyPath" _real_key="$3"
_savedomainconf "Le_ReloadCmd" "$Le_ReloadCmd" _real_ca="$4"
_savedomainconf "Le_RealFullChainPath" "$Le_RealFullChainPath" _real_fullchain="$5"
_reload_cmd="$6"
_backup_prefix="$7"
if [ "$Le_RealCertPath" = "$NO_VALUE" ]; then if [ "$_real_cert" = "$NO_VALUE" ]; then
Le_RealCertPath="" _real_cert=""
fi fi
if [ "$Le_RealKeyPath" = "$NO_VALUE" ]; then if [ "$_real_key" = "$NO_VALUE" ]; then
Le_RealKeyPath="" _real_key=""
fi fi
if [ "$Le_RealCACertPath" = "$NO_VALUE" ]; then if [ "$_real_ca" = "$NO_VALUE" ]; then
Le_RealCACertPath="" _real_ca=""
fi fi
if [ "$Le_ReloadCmd" = "$NO_VALUE" ]; then if [ "$_reload_cmd" = "$NO_VALUE" ]; then
Le_ReloadCmd="" _reload_cmd=""
fi fi
if [ "$Le_RealFullChainPath" = "$NO_VALUE" ]; then if [ "$_real_fullchain" = "$NO_VALUE" ]; then
Le_RealFullChainPath="" _real_fullchain=""
fi fi
if [ "$Le_RealCertPath" ]; then _backup_path="$DOMAIN_BACKUP_PATH/$_backup_prefix"
mkdir -p "$_backup_path"
_info "Installing cert to:$Le_RealCertPath" if [ "$_real_cert" ]; then
if [ -f "$Le_RealCertPath" ] && [ ! "$IS_RENEW" ]; then _info "Installing cert to:$_real_cert"
cp "$Le_RealCertPath" "$Le_RealCertPath".bak if [ -f "$_real_cert" ] && [ ! "$IS_RENEW" ]; then
cp "$_real_cert" "$_backup_path/cert.bak"
fi fi
cat "$CERT_PATH" >"$Le_RealCertPath" cat "$CERT_PATH" >"$_real_cert"
fi fi
if [ "$Le_RealCACertPath" ]; then if [ "$_real_ca" ]; then
_info "Installing CA to:$_real_ca"
_info "Installing CA to:$Le_RealCACertPath" if [ "$_real_ca" = "$_real_cert" ]; then
if [ "$Le_RealCACertPath" = "$Le_RealCertPath" ]; then echo "" >>"$_real_ca"
echo "" >>"$Le_RealCACertPath" cat "$CA_CERT_PATH" >>"$_real_ca"
cat "$CA_CERT_PATH" >>"$Le_RealCACertPath"
else else
if [ -f "$Le_RealCACertPath" ] && [ ! "$IS_RENEW" ]; then if [ -f "$_real_ca" ] && [ ! "$IS_RENEW" ]; then
cp "$Le_RealCACertPath" "$Le_RealCACertPath".bak cp "$_real_ca" "$_backup_path/ca.bak"
fi fi
cat "$CA_CERT_PATH" >"$Le_RealCACertPath" cat "$CA_CERT_PATH" >"$_real_ca"
fi fi
fi fi
if [ "$Le_RealKeyPath" ]; then if [ "$_real_key" ]; then
_info "Installing key to:$_real_key"
_info "Installing key to:$Le_RealKeyPath" if [ -f "$_real_key" ] && [ ! "$IS_RENEW" ]; then
if [ -f "$Le_RealKeyPath" ] && [ ! "$IS_RENEW" ]; then cp "$_real_key" "$_backup_path/key.bak"
cp "$Le_RealKeyPath" "$Le_RealKeyPath".bak
fi fi
cat "$CERT_KEY_PATH" >"$Le_RealKeyPath" cat "$CERT_KEY_PATH" >"$_real_key"
fi fi
if [ "$Le_RealFullChainPath" ]; then if [ "$_real_fullchain" ]; then
_info "Installing full chain to:$_real_fullchain"
_info "Installing full chain to:$Le_RealFullChainPath" if [ -f "$_real_fullchain" ] && [ ! "$IS_RENEW" ]; then
if [ -f "$Le_RealFullChainPath" ] && [ ! "$IS_RENEW" ]; then cp "$_real_fullchain" "$_backup_path/fullchain.bak"
cp "$Le_RealFullChainPath" "$Le_RealFullChainPath".bak
fi fi
cat "$CERT_FULLCHAIN_PATH" >"$Le_RealFullChainPath" cat "$CERT_FULLCHAIN_PATH" >"$_real_fullchain"
fi fi
if [ "$Le_ReloadCmd" ]; then if [ "$_reload_cmd" ]; then
_info "Run Le_ReloadCmd: $Le_ReloadCmd" _info "Run reload cmd: $_reload_cmd"
if ( if (
export CERT_PATH export CERT_PATH
export CERT_KEY_PATH export CERT_KEY_PATH
export CA_CERT_PATH export CA_CERT_PATH
export CERT_FULLCHAIN_PATH export CERT_FULLCHAIN_PATH
cd "$DOMAIN_PATH" && eval "$Le_ReloadCmd" cd "$DOMAIN_PATH" && eval "$_reload_cmd"
); then ); then
_info "$(__green "Reload success")" _info "$(__green "Reload success")"
else else
...@@ -3896,12 +4400,7 @@ _detect_profile() { ...@@ -3896,12 +4400,7 @@ _detect_profile() {
_initconf() { _initconf() {
_initpath _initpath
if [ ! -f "$ACCOUNT_CONF_PATH" ]; then if [ ! -f "$ACCOUNT_CONF_PATH" ]; then
echo "#ACCOUNT_CONF_PATH=xxxx echo "
#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\"
#LOG_FILE=\"$DEFAULT_LOG_FILE\" #LOG_FILE=\"$DEFAULT_LOG_FILE\"
#LOG_LEVEL=1 #LOG_LEVEL=1
...@@ -3909,12 +4408,6 @@ _initconf() { ...@@ -3909,12 +4408,6 @@ _initconf() {
#AUTO_UPGRADE=\"1\" #AUTO_UPGRADE=\"1\"
#NO_TIMESTAMP=1 #NO_TIMESTAMP=1
#OPENSSL_BIN=openssl
#USER_AGENT=\"$USER_AGENT\"
#USER_PATH=
" >"$ACCOUNT_CONF_PATH" " >"$ACCOUNT_CONF_PATH"
fi fi
...@@ -3942,8 +4435,8 @@ _precheck() { ...@@ -3942,8 +4435,8 @@ _precheck() {
fi fi
fi fi
if ! _exists "$OPENSSL_BIN"; then if ! _exists "$ACME_OPENSSL_BIN"; then
_err "Please install openssl first." _err "Please install openssl first. ACME_OPENSSL_BIN=$ACME_OPENSSL_BIN"
_err "We need openssl to generate keys." _err "We need openssl to generate keys."
return 1 return 1
fi fi
...@@ -4220,7 +4713,7 @@ Commands: ...@@ -4220,7 +4713,7 @@ Commands:
--version, -v Show version info. --version, -v Show version info.
--install Install $PROJECT_NAME to your system. --install Install $PROJECT_NAME to your system.
--uninstall Uninstall $PROJECT_NAME, and uninstall the cron job. --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. --issue Issue a cert.
--signcsr Issue a cert from an existing csr. --signcsr Issue a cert from an existing csr.
--deploy Deploy the cert to your server. --deploy Deploy the cert to your server.
...@@ -4235,10 +4728,11 @@ Commands: ...@@ -4235,10 +4728,11 @@ Commands:
--uninstall-cronjob Uninstall the cron job. The 'uninstall' command can do this automatically. --uninstall-cronjob Uninstall the cron job. The 'uninstall' command can do this automatically.
--cron Run cron job to renew all the certs. --cron Run cron job to renew all the certs.
--toPkcs Export the certificate and key to a pfx file. --toPkcs Export the certificate and key to a pfx file.
--toPkcs8 Convert to pkcs8 format.
--update-account Update account info. --update-account Update account info.
--register-account Register account key. --register-account Register account key.
--createAccountKey, -cak Create an account private key, professional use. --create-account-key Create an account private key, professional use.
--createDomainKey, -cdk Create an domain private key, professional use. --create-domain-key Create an domain private key, professional use.
--createCSR, -ccsr Create CSR , professional use. --createCSR, -ccsr Create CSR , professional use.
--deactivate Deactivate the domain authz, professional use. --deactivate Deactivate the domain authz, professional use.
...@@ -4247,9 +4741,10 @@ Parameters: ...@@ -4247,9 +4741,10 @@ Parameters:
--force, -f Used to force to install or force to renew a cert immediately. --force, -f Used to force to install or force to renew a cert immediately.
--staging, --test Use staging server, just for test. --staging, --test Use staging server, just for test.
--debug Output debug info. --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. --webroot, -w /path/to/webroot Specifies the web root folder for web root mode.
--standalone Use standalone mode. --standalone Use standalone mode.
--stateless Use stateless mode, see: $_STATELESS_WIKI
--tls Use standalone tls mode. --tls Use standalone tls mode.
--apache Use apache mode. --apache Use apache mode.
--dns [dns_cf|dns_dp|dns_cx|/path/to/api/file] Use dns mode or dns api. --dns [dns_cf|dns_dp|dns_cx|/path/to/api/file] Use dns mode or dns api.
...@@ -4259,6 +4754,7 @@ Parameters: ...@@ -4259,6 +4754,7 @@ Parameters:
--accountkeylength, -ak [2048] Specifies the account key length. --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 [/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. --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: These parameters are to install the cert to nginx/apache or anyother server after issue/renew a cert:
...@@ -4296,6 +4792,7 @@ Parameters: ...@@ -4296,6 +4792,7 @@ Parameters:
--listen-v4 Force standalone/tls server to listen at ipv4. --listen-v4 Force standalone/tls server to listen at ipv4.
--listen-v6 Force standalone/tls server to listen at ipv6. --listen-v6 Force standalone/tls server to listen at ipv6.
--openssl-bin Specifies a custom openssl bin location. --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() { ...@@ -4363,9 +4860,9 @@ _processAccountConf() {
fi fi
if [ "$_openssl_bin" ]; then if [ "$_openssl_bin" ]; then
_saveaccountconf "OPENSSL_BIN" "$_openssl_bin" _saveaccountconf "ACME_OPENSSL_BIN" "$_openssl_bin"
elif [ "$OPENSSL_BIN" ] && [ "$OPENSSL_BIN" != "$DEFAULT_OPENSSL_BIN" ]; then elif [ "$ACME_OPENSSL_BIN" ] && [ "$ACME_OPENSSL_BIN" != "$DEFAULT_OPENSSL_BIN" ]; then
_saveaccountconf "OPENSSL_BIN" "$OPENSSL_BIN" _saveaccountconf "ACME_OPENSSL_BIN" "$ACME_OPENSSL_BIN"
fi fi
if [ "$_auto_upgrade" ]; then if [ "$_auto_upgrade" ]; then
...@@ -4374,6 +4871,12 @@ _processAccountConf() { ...@@ -4374,6 +4871,12 @@ _processAccountConf() {
_saveaccountconf "AUTO_UPGRADE" "$AUTO_UPGRADE" _saveaccountconf "AUTO_UPGRADE" "$AUTO_UPGRADE"
fi 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() { _process() {
...@@ -4417,6 +4920,8 @@ _process() { ...@@ -4417,6 +4920,8 @@ _process() {
_listen_v4="" _listen_v4=""
_listen_v6="" _listen_v6=""
_openssl_bin="" _openssl_bin=""
_syslog=""
_use_wget=""
while [ ${#} -gt 0 ]; do while [ ${#} -gt 0 ]; do
case "${1}" in case "${1}" in
...@@ -4479,10 +4984,13 @@ _process() { ...@@ -4479,10 +4984,13 @@ _process() {
--toPkcs) --toPkcs)
_CMD="toPkcs" _CMD="toPkcs"
;; ;;
--createAccountKey | --createaccountkey | -cak) --toPkcs8)
_CMD="toPkcs8"
;;
--createAccountKey | --createaccountkey | -cak | --create-account-key)
_CMD="createAccountKey" _CMD="createAccountKey"
;; ;;
--createDomainKey | --createdomainkey | -cdk) --createDomainKey | --createdomainkey | -cdk | --create-domain-key)
_CMD="createDomainKey" _CMD="createDomainKey"
;; ;;
--createCSR | --createcsr | -ccr) --createCSR | --createcsr | -ccr)
...@@ -4532,12 +5040,15 @@ _process() { ...@@ -4532,12 +5040,15 @@ _process() {
;; ;;
--debug) --debug)
if [ -z "$2" ] || _startswith "$2" "-"; then if [ -z "$2" ] || _startswith "$2" "-"; then
DEBUG="1" DEBUG="$DEBUG_LEVEL_DEFAULT"
else else
DEBUG="$2" DEBUG="$2"
shift shift
fi fi
;; ;;
--output-insecure)
export OUTPUT_INSECURE=1
;;
--webroot | -w) --webroot | -w)
wvalue="$2" wvalue="$2"
if [ -z "$_webroot" ]; then if [ -z "$_webroot" ]; then
...@@ -4555,6 +5066,14 @@ _process() { ...@@ -4555,6 +5066,14 @@ _process() {
_webroot="$_webroot,$wvalue" _webroot="$_webroot,$wvalue"
fi fi
;; ;;
--stateless)
wvalue="$MODE_STATELESS"
if [ -z "$_webroot" ]; then
_webroot="$wvalue"
else
_webroot="$_webroot,$wvalue"
fi
;;
--local-address) --local-address)
lvalue="$2" lvalue="$2"
_local_address="$_local_address$lvalue," _local_address="$_local_address$lvalue,"
...@@ -4568,6 +5087,14 @@ _process() { ...@@ -4568,6 +5087,14 @@ _process() {
_webroot="$_webroot,$wvalue" _webroot="$_webroot,$wvalue"
fi fi
;; ;;
--nginx)
wvalue="$NGINX"
if [ -z "$_webroot" ]; then
_webroot="$wvalue"
else
_webroot="$_webroot,$wvalue"
fi
;;
--tls) --tls)
wvalue="$W_TLS" wvalue="$W_TLS"
if [ -z "$_webroot" ]; then if [ -z "$_webroot" ]; then
...@@ -4715,7 +5242,11 @@ _process() { ...@@ -4715,7 +5242,11 @@ _process() {
shift shift
;; ;;
--deploy-hook) --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 shift
;; ;;
--ocsp-must-staple | --ocsp) --ocsp-must-staple | --ocsp)
...@@ -4739,6 +5270,15 @@ _process() { ...@@ -4739,6 +5270,15 @@ _process() {
LOG_LEVEL="$_log_level" LOG_LEVEL="$_log_level"
shift shift
;; ;;
--syslog)
if ! _startswith "$2" '-'; then
_syslog="$2"
shift
fi
if [ -z "$_syslog" ]; then
_syslog="$SYSLOG_LEVEL_DEFAULT"
fi
;;
--auto-upgrade) --auto-upgrade)
_auto_upgrade="$2" _auto_upgrade="$2"
if [ -z "$_auto_upgrade" ] || _startswith "$_auto_upgrade" '-'; then if [ -z "$_auto_upgrade" ] || _startswith "$_auto_upgrade" '-'; then
...@@ -4758,7 +5298,12 @@ _process() { ...@@ -4758,7 +5298,12 @@ _process() {
;; ;;
--openssl-bin) --openssl-bin)
_openssl_bin="$2" _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" _err "Unknown parameter : $1"
...@@ -4786,6 +5331,21 @@ _process() { ...@@ -4786,6 +5331,21 @@ _process() {
LOG_LEVEL="$_log_level" LOG_LEVEL="$_log_level"
fi 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 _processAccountConf
fi fi
...@@ -4844,6 +5404,9 @@ _process() { ...@@ -4844,6 +5404,9 @@ _process() {
toPkcs) toPkcs)
toPkcs "$_domain" "$_password" "$_ecc" toPkcs "$_domain" "$_password" "$_ecc"
;; ;;
toPkcs8)
toPkcs8 "$_domain" "$_ecc"
;;
createAccountKey) createAccountKey)
createAccountKey "$_accountkeylength" createAccountKey "$_accountkeylength"
;; ;;
...@@ -4878,6 +5441,21 @@ _process() { ...@@ -4878,6 +5441,21 @@ _process() {
if [ "$_log_level" ]; then if [ "$_log_level" ]; then
_saveaccountconf "LOG_LEVEL" "$_log_level" _saveaccountconf "LOG_LEVEL" "$_log_level"
fi 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 _processAccountConf
fi 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 ...@@ -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 you create under a FreeDNS public domain. You must own the top level domain in order to automaitcally
validate with acme.sh at FreeDNS. 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 # Use custom API
If your API is not supported yet, you can write your own DNS 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