Unverified Commit ce38ecb9 authored by Philippe Kueck's avatar Philippe Kueck
Browse files

merge with upstream

parents 13ffa170 1e2d5598
<!--
If it is a bug report:
- make sure you are able to repro it on the latest released version.
You can install the latest version by: `acme.sh --upgrade`
- Search the existing issues.
- Refer to the [WIKI](https://wiki.acme.sh).
- Debug info [Debug](https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh).
-->
Steps to reproduce
------------------
Debug log
-----------------
```
acme.sh --issue ..... --debug 2
```
language: shell
env:
global:
- SHFMT_URL=https://github.com/mvdan/sh/releases/download/v0.4.0/shfmt_v0.4.0_linux_amd64
addons:
apt:
sources:
- debian-sid # Grab shellcheck from the Debian repo (o_O)
packages:
- shellcheck
script:
- curl -sSL $SHFMT_URL -o ~/shfmt
- chmod +x ~/shfmt
- shellcheck -V
- shellcheck -e SC2021,SC2126,SC2034 **/*.sh && echo "shellcheck OK"
- ~/shfmt -l -w -i 2 . && echo "shfmt OK" || git diff --exit-code || (echo "Run shfmt to fix the formatting issues" && false)
matrix:
fast_finish: true
# An ACME Shell script: acme.sh # An ACME Shell script: acme.sh [![Build Status](https://travis-ci.org/Neilpang/acme.sh.svg?branch=master)](https://travis-ci.org/Neilpang/acme.sh)
- An ACME protocol client written purely in Shell (Unix shell) language. - An ACME protocol client written purely in Shell (Unix shell) language.
- Fully ACME protocol implementation. - Fully ACME protocol implementation.
- Simple, powerful and very easy to use. You only need 3 minutes to learn. - Simple, powerful and very easy to use. You only need 3 minutes to learn.
...@@ -36,6 +36,7 @@ Wiki: https://github.com/Neilpang/acme.sh/wiki ...@@ -36,6 +36,7 @@ Wiki: https://github.com/Neilpang/acme.sh/wiki
|16|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/mageia.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Mageia |16|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/mageia.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Mageia
|17|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/Neilpang/acme.sh/wiki/How-to-run-on-OpenWRT) |17|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/Neilpang/acme.sh/wiki/How-to-run-on-OpenWRT)
|18|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/solaris.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|SunOS/Solaris |18|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/solaris.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|SunOS/Solaris
|19|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/gentoo-stage3-amd64.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Gentoo Linux
For all build statuses, check our [daily build project](https://github.com/Neilpang/acmetest): For all build statuses, check our [daily build project](https://github.com/Neilpang/acmetest):
...@@ -137,15 +138,24 @@ More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert ...@@ -137,15 +138,24 @@ More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
# 3. Install the issued cert to apache/nginx etc. # 3. Install the issued cert to apache/nginx etc.
After you issue a cert, you probably want to install/copy the cert to your nginx/apache or other servers you may be using. After you issue a cert, you probably want to install/copy the cert to your nginx/apache or other servers.
You **MUST** use this command to copy the certs to the target files, **Do NOT** use the certs files in **.acme.sh/** folder, they are for internal use only, the folder structure may change in future.
**nginx** example
```bash ```bash
acme.sh --installcert -d example.com \ acme.sh --installcert -d example.com \
--certpath /path/to/certfile/in/apache/nginx \ --keypath /path/to/keyfile/in/nginx/key.pem \
--keypath /path/to/keyfile/in/apache/nginx \ --fullchainpath path/to/fullchain/nginx/cert.pem \
--capath /path/to/ca/certfile/apache/nginx \ --reloadcmd "service nginx restart"
--fullchainpath path/to/fullchain/certfile/apache/nginx \ ```
--reloadcmd "service apache2|nginx reload"
**apache** example
```bash
acme.sh --installcert -d example.com \
--certpath /path/to/certfile/in/apache/cert.pem \
--keypath /path/to/keyfile/in/apache/key.pem \
--fullchainpath path/to/fullchain/certfile/apache/fullchain.pem \
--reloadcmd "service apache2 restart"
``` ```
Only the domain is required, all the other parameters are optional. Only the domain is required, all the other parameters are optional.
...@@ -244,7 +254,9 @@ You don't have do anything manually! ...@@ -244,7 +254,9 @@ You don't have do anything manually!
7. PowerDNS API 7. PowerDNS API
8. lexicon dns api: https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api 8. lexicon dns api: https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api
(DigitalOcean, DNSimple, DnsMadeEasy, DNSPark, EasyDNS, Namesilo, NS1, PointHQ, Rage4 and Vultr etc.) (DigitalOcean, DNSimple, DnsMadeEasy, DNSPark, EasyDNS, Namesilo, NS1, PointHQ, Rage4 and Vultr etc.)
9. nsupdate 9. LuaDNS.com API
10. DNSMadeEasy.com API
11. nsupdate
##### More APIs are coming soon... ##### More APIs are coming soon...
......
#!/usr/bin/env sh #!/usr/bin/env sh
VER=2.6.2 VER=2.6.5
PROJECT_NAME="acme.sh" PROJECT_NAME="acme.sh"
...@@ -16,15 +16,18 @@ _SUB_FOLDERS="dnsapi deploy" ...@@ -16,15 +16,18 @@ _SUB_FOLDERS="dnsapi deploy"
DEFAULT_CA="https://acme-v01.api.letsencrypt.org" DEFAULT_CA="https://acme-v01.api.letsencrypt.org"
DEFAULT_AGREEMENT="https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf" DEFAULT_AGREEMENT="https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf"
DEFAULT_USER_AGENT="$PROJECT_ENTRY client v$VER : $PROJECT" DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)"
DEFAULT_ACCOUNT_EMAIL="" DEFAULT_ACCOUNT_EMAIL=""
DEFAULT_ACCOUNT_KEY_LENGTH=2048
DEFAULT_DOMAIN_KEY_LENGTH=2048
STAGE_CA="https://acme-staging.api.letsencrypt.org" STAGE_CA="https://acme-staging.api.letsencrypt.org"
VTYPE_HTTP="http-01" VTYPE_HTTP="http-01"
VTYPE_DNS="dns-01" VTYPE_DNS="dns-01"
VTYPE_TLS="tls-sni-01" VTYPE_TLS="tls-sni-01"
VTYPE_TLS2="tls-sni-02" #VTYPE_TLS2="tls-sni-02"
LOCAL_ANY_ADDRESS="0.0.0.0" LOCAL_ANY_ADDRESS="0.0.0.0"
...@@ -57,33 +60,32 @@ DEFAULT_LOG_LEVEL="$LOG_LEVEL_1" ...@@ -57,33 +60,32 @@ DEFAULT_LOG_LEVEL="$LOG_LEVEL_1"
_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"
__INTERACTIVE="" __INTERACTIVE=""
if [ -t 1 ] ; then if [ -t 1 ]; then
__INTERACTIVE="1" __INTERACTIVE="1"
fi fi
__green() { __green() {
if [ "$__INTERACTIVE" ] ; then if [ "$__INTERACTIVE" ]; then
printf '\033[1;31;32m' printf '\033[1;31;32m'
fi fi
printf -- "$1" printf -- "$1"
if [ "$__INTERACTIVE" ] ; then if [ "$__INTERACTIVE" ]; then
printf '\033[0m' printf '\033[0m'
fi fi
} }
__red() { __red() {
if [ "$__INTERACTIVE" ] ; then if [ "$__INTERACTIVE" ]; then
printf '\033[1;31;40m' printf '\033[1;31;40m'
fi fi
printf -- "$1" printf -- "$1"
if [ "$__INTERACTIVE" ] ; then if [ "$__INTERACTIVE" ]; then
printf '\033[0m' printf '\033[0m'
fi fi
} }
_printargs() { _printargs() {
if [ -z "$2" ] ; then if [ -z "$2" ]; then
printf -- "[$(date)] $1" printf -- "[$(date)] $1"
else else
printf -- "[$(date)] $1='$2'" printf -- "[$(date)] $1='$2'"
...@@ -91,10 +93,33 @@ _printargs() { ...@@ -91,10 +93,33 @@ _printargs() {
printf "\n" printf "\n"
} }
_dlg_versions() {
echo "Diagnosis versions: "
echo "openssl:"
if _exists openssl; then
openssl version 2>&1
else
echo "openssl doesn't exists."
fi
echo "apache:"
if [ "$_APACHECTL" ] && _exists "$_APACHECTL"; then
_APACHECTL -V 2>&1
else
echo "apache doesn't exists."
fi
echo "nc:"
if _exists "nc"; then
nc -h 2>&1
else
_debug "nc doesn't exists."
fi
}
_log() { _log() {
[ -z "$LOG_FILE" ] && return [ -z "$LOG_FILE" ] && return
_printargs "$@" >> $LOG_FILE _printargs "$@" >>"$LOG_FILE"
} }
_info() { _info() {
...@@ -102,11 +127,10 @@ _info() { ...@@ -102,11 +127,10 @@ _info() {
_printargs "$@" _printargs "$@"
} }
_err() { _err() {
_log "$@" _log "$@"
printf -- "[$(date)] " >&2 printf -- "[$(date)] " >&2
if [ -z "$2" ] ; then if [ -z "$2" ]; then
__red "$1" >&2 __red "$1" >&2
else else
__red "$1='$2'" >&2 __red "$1='$2'" >&2
...@@ -116,52 +140,51 @@ _err() { ...@@ -116,52 +140,51 @@ _err() {
} }
_usage() { _usage() {
__red "$@" >&2 __red "$@" >&2
printf "\n" >&2 printf "\n" >&2
} }
_debug() { _debug() {
if [ -z "$LOG_LEVEL" ] || [ "$LOG_LEVEL" -ge "$LOG_LEVEL_1" ] ; then if [ -z "$LOG_LEVEL" ] || [ "$LOG_LEVEL" -ge "$LOG_LEVEL_1" ]; then
_log "$@" _log "$@"
fi fi
if [ -z "$DEBUG" ] ; then if [ -z "$DEBUG" ]; then
return return
fi fi
_printargs "$@" >&2 _printargs "$@" >&2
} }
_debug2() { _debug2() {
if [ "$LOG_LEVEL" ] && [ "$LOG_LEVEL" -ge "$LOG_LEVEL_2" ] ; then if [ "$LOG_LEVEL" ] && [ "$LOG_LEVEL" -ge "$LOG_LEVEL_2" ]; then
_log "$@" _log "$@"
fi fi
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ] ; then if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
_debug "$@" _debug "$@"
fi fi
} }
_debug3() { _debug3() {
if [ "$LOG_LEVEL" ] && [ "$LOG_LEVEL" -ge "$LOG_LEVEL_3" ] ; then if [ "$LOG_LEVEL" ] && [ "$LOG_LEVEL" -ge "$LOG_LEVEL_3" ]; then
_log "$@" _log "$@"
fi fi
if [ "$DEBUG" ] && [ "$DEBUG" -ge "3" ] ; then if [ "$DEBUG" ] && [ "$DEBUG" -ge "3" ]; then
_debug "$@" _debug "$@"
fi fi
} }
_startswith(){ _startswith() {
_str="$1" _str="$1"
_sub="$2" _sub="$2"
echo "$_str" | grep "^$_sub" >/dev/null 2>&1 echo "$_str" | grep "^$_sub" >/dev/null 2>&1
} }
_endswith(){ _endswith() {
_str="$1" _str="$1"
_sub="$2" _sub="$2"
echo "$_str" | grep -- "$_sub\$" >/dev/null 2>&1 echo "$_str" | grep -- "$_sub\$" >/dev/null 2>&1
} }
_contains(){ _contains() {
_str="$1" _str="$1"
_sub="$2" _sub="$2"
echo "$_str" | grep -- "$_sub" >/dev/null 2>&1 echo "$_str" | grep -- "$_sub" >/dev/null 2>&1
...@@ -171,17 +194,17 @@ _hasfield() { ...@@ -171,17 +194,17 @@ _hasfield() {
_str="$1" _str="$1"
_field="$2" _field="$2"
_sep="$3" _sep="$3"
if [ -z "$_field" ] ; then if [ -z "$_field" ]; then
_usage "Usage: str field [sep]" _usage "Usage: str field [sep]"
return 1 return 1
fi fi
if [ -z "$_sep" ] ; then if [ -z "$_sep" ]; then
_sep="," _sep=","
fi fi
for f in $(echo "$_str" | tr ',' ' ') ; do for f in $(echo "$_str" | tr ',' ' '); do
if [ "$f" = "$_field" ] ; then if [ "$f" = "$_field" ]; then
_debug2 "'$_str' contains '$_field'" _debug2 "'$_str' contains '$_field'"
return 0 #contains ok return 0 #contains ok
fi fi
...@@ -190,45 +213,44 @@ _hasfield() { ...@@ -190,45 +213,44 @@ _hasfield() {
return 1 #not contains return 1 #not contains
} }
_getfield(){ _getfield() {
_str="$1" _str="$1"
_findex="$2" _findex="$2"
_sep="$3" _sep="$3"
if [ -z "$_findex" ] ; then if [ -z "$_findex" ]; then
_usage "Usage: str field [sep]" _usage "Usage: str field [sep]"
return 1 return 1
fi fi
if [ -z "$_sep" ] ; then if [ -z "$_sep" ]; then
_sep="," _sep=","
fi fi
_ffi=$_findex _ffi="$_findex"
while [ "$_ffi" -gt "0" ] while [ "$_ffi" -gt "0" ]; do
do _fv="$(echo "$_str" | cut -d "$_sep" -f "$_ffi")"
_fv="$(echo "$_str" | cut -d $_sep -f $_ffi)" if [ "$_fv" ]; then
if [ "$_fv" ] ; then
printf -- "%s" "$_fv" printf -- "%s" "$_fv"
return 0 return 0
fi fi
_ffi="$(_math $_ffi - 1)" _ffi="$(_math "$_ffi" - 1)"
done done
printf -- "%s" "$_str" printf -- "%s" "$_str"
} }
_exists(){ _exists() {
cmd="$1" cmd="$1"
if [ -z "$cmd" ] ; then if [ -z "$cmd" ]; then
_usage "Usage: _exists cmd" _usage "Usage: _exists cmd"
return 1 return 1
fi fi
if type command >/dev/null 2>&1 ; then if command >/dev/null 2>&1; then
command -v "$cmd" >/dev/null 2>&1 command -v "$cmd" >/dev/null 2>&1
else elif which >/dev/null 2>&1; then
type "$cmd" >/dev/null 2>&1 which "$cmd" >/dev/null 2>&1
fi fi
ret="$?" ret="$?"
_debug3 "$cmd exists=$ret" _debug3 "$cmd exists=$ret"
...@@ -236,41 +258,41 @@ _exists(){ ...@@ -236,41 +258,41 @@ _exists(){
} }
#a + b #a + b
_math(){ _math() {
expr "$@" _m_opts="$@"
printf "%s" "$(($_m_opts))"
} }
_h_char_2_dec() { _h_char_2_dec() {
_ch=$1 _ch=$1
case "${_ch}" in case "${_ch}" in
a|A) a | A)
printf "10" printf "10"
;; ;;
b|B) b | B)
printf "11" printf "11"
;; ;;
c|C) c | C)
printf "12" printf "12"
;; ;;
d|D) d | D)
printf "13" printf "13"
;; ;;
e|E) e | E)
printf "14" printf "14"
;; ;;
f|F) f | F)
printf "15" printf "15"
;; ;;
*) *)
printf "%s" "$_ch" printf "%s" "$_ch"
;; ;;
esac esac
} }
_URGLY_PRINTF="" _URGLY_PRINTF=""
if [ "$(printf '\x41')" != 'A' ] ; then if [ "$(printf '\x41')" != 'A' ]; then
_URGLY_PRINTF=1 _URGLY_PRINTF=1
fi fi
...@@ -278,35 +300,29 @@ _h2b() { ...@@ -278,35 +300,29 @@ _h2b() {
hex=$(cat) hex=$(cat)
i=1 i=1
j=2 j=2
if _exists let ; then
uselet="1"
fi
_debug3 uselet "$uselet"
_debug3 _URGLY_PRINTF "$_URGLY_PRINTF" _debug3 _URGLY_PRINTF "$_URGLY_PRINTF"
while true ; do while true; do
if [ -z "$_URGLY_PRINTF" ] ; then if [ -z "$_URGLY_PRINTF" ]; then
h="$(printf $hex | cut -c $i-$j)" h="$(printf "%s" "$hex" | cut -c $i-$j)"
if [ -z "$h" ] ; then if [ -z "$h" ]; then
break; break
fi fi
printf "\x$h" printf "\x$h%s"
else else
ic="$(printf $hex | cut -c $i)" ic="$(printf "%s" "$hex" | cut -c $i)"
jc="$(printf $hex | cut -c $j)" jc="$(printf "%s" "$hex" | cut -c $j)"
if [ -z "$ic$jc" ] ; then if [ -z "$ic$jc" ]; then
break; break
fi fi
ic="$(_h_char_2_dec "$ic")" ic="$(_h_char_2_dec "$ic")"
jc="$(_h_char_2_dec "$jc")" jc="$(_h_char_2_dec "$jc")"
printf '\'"$(printf %o "$(_math $ic \* 16 + $jc)")" printf '\'"$(printf "%o" "$(_math "$ic" \* 16 + $jc)")""%s"
fi fi
if [ "$uselet" ] ; then
let "i+=2" >/dev/null i="$(_math "$i" + 2)"
let "j+=2" >/dev/null j="$(_math "$j" + 2)"
else
i="$(_math $i + 2)"
j="$(_math $j + 2)"
fi
done done
} }
...@@ -314,7 +330,7 @@ _h2b() { ...@@ -314,7 +330,7 @@ _h2b() {
_sed_i() { _sed_i() {
options="$1" options="$1"
filename="$2" filename="$2"
if [ -z "$filename" ] ; then if [ -z "$filename" ]; then
_usage "Usage:_sed_i options filename" _usage "Usage:_sed_i options filename"
return 1 return 1
fi fi
...@@ -325,12 +341,12 @@ _sed_i() { ...@@ -325,12 +341,12 @@ _sed_i() {
else else
_debug "No -i support in sed" _debug "No -i support in sed"
text="$(cat "$filename")" text="$(cat "$filename")"
echo "$text" | sed "$options" > "$filename" echo "$text" | sed "$options" >"$filename"
fi fi
} }
_egrep_o() { _egrep_o() {
if _contains "$(egrep -o 2>&1)" "egrep: illegal option -- o" ; then if _contains "$(egrep -o 2>&1)" "egrep: illegal option -- o"; then
sed -n 's/.*\('"$1"'\).*/\1/p' sed -n 's/.*\('"$1"'\).*/\1/p'
else else
egrep -o "$1" egrep -o "$1"
...@@ -342,34 +358,34 @@ _getfile() { ...@@ -342,34 +358,34 @@ _getfile() {
filename="$1" filename="$1"
startline="$2" startline="$2"
endline="$3" endline="$3"
if [ -z "$endline" ] ; then if [ -z "$endline" ]; then
_usage "Usage: file startline endline" _usage "Usage: file startline endline"
return 1 return 1
fi fi
i="$(grep -n -- "$startline" "$filename" | cut -d : -f 1)" i="$(grep -n -- "$startline" "$filename" | cut -d : -f 1)"
if [ -z "$i" ] ; then if [ -z "$i" ]; then
_err "Can not find start line: $startline" _err "Can not find start line: $startline"
return 1 return 1
fi fi
i="$(_math "$i" + 1)" i="$(_math "$i" + 1)"
_debug i "$i" _debug i "$i"
j="$(grep -n -- "$endline" "$filename" | cut -d : -f 1)" j="$(grep -n -- "$endline" "$filename" | cut -d : -f 1)"
if [ -z "$j" ] ; then if [ -z "$j" ]; then
_err "Can not find end line: $endline" _err "Can not find end line: $endline"
return 1 return 1
fi fi
j="$(_math "$j" - 1)" j="$(_math "$j" - 1)"
_debug j "$j" _debug j "$j"
sed -n "$i,${j}p" "$filename" sed -n "$i,${j}p" "$filename"
} }
#Usage: multiline #Usage: multiline
_base64() { _base64() {
if [ "$1" ] ; then if [ "$1" ]; then
openssl base64 -e openssl base64 -e
else else
openssl base64 -e | tr -d '\r\n' openssl base64 -e | tr -d '\r\n'
...@@ -378,7 +394,7 @@ _base64() { ...@@ -378,7 +394,7 @@ _base64() {
#Usage: multiline #Usage: multiline
_dbase64() { _dbase64() {
if [ "$1" ] ; then if [ "$1" ]; then
openssl base64 -d -A openssl base64 -d -A
else else
openssl base64 -d openssl base64 -d
...@@ -389,18 +405,43 @@ _dbase64() { ...@@ -389,18 +405,43 @@ _dbase64() {
#Output Base64-encoded digest #Output Base64-encoded digest
_digest() { _digest() {
alg="$1" alg="$1"
if [ -z "$alg" ] ; then if [ -z "$alg" ]; then
_usage "Usage: _digest hashalg" _usage "Usage: _digest hashalg"
return 1 return 1
fi fi
outputhex="$2" outputhex="$2"
if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ] || [ "$alg" = "md5" ]; then
if [ "$outputhex" ]; then
openssl dgst -"$alg" -hex | cut -d = -f 2 | tr -d ' '
else
openssl dgst -"$alg" -binary | _base64
fi
else
_err "$alg is not supported yet"
return 1
fi
}
#Usage: hashalg secret [outputhex]
#Output Base64-encoded hmac
_hmac() {
alg="$1"
hmac_sec="$2"
outputhex="$3"
if [ -z "$hmac_sec" ]; then
_usage "Usage: _hmac hashalg secret [outputhex]"
return 1
fi
if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ]; then if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ]; then
if [ "$outputhex" ] ; then if [ "$outputhex" ]; then
openssl dgst -$alg -hex | cut -d = -f 2 | tr -d ' ' openssl dgst -"$alg" -hmac "$hmac_sec" | cut -d = -f 2 | tr -d ' '
else else
openssl dgst -$alg -binary | _base64 openssl dgst -"$alg" -hmac "$hmac_sec" -binary | _base64
fi fi
else else
_err "$alg is not supported yet" _err "$alg is not supported yet"
...@@ -414,33 +455,54 @@ _digest() { ...@@ -414,33 +455,54 @@ _digest() {
_sign() { _sign() {
keyfile="$1" keyfile="$1"
alg="$2" alg="$2"
if [ -z "$alg" ] ; then if [ -z "$alg" ]; then
_usage "Usage: _sign keyfile hashalg" _usage "Usage: _sign keyfile hashalg"
return 1 return 1
fi fi
if [ "$alg" = "sha256" ] ; then _sign_openssl="openssl dgst -sign $keyfile "
openssl dgst -sha256 -sign "$keyfile" | _base64 if [ "$alg" = "sha256" ]; then
_sign_openssl="$_sign_openssl -$alg"
else else
_err "$alg is not supported yet" _err "$alg is not supported yet"
return 1 return 1
fi fi
if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
$_sign_openssl | _base64
elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
if ! _signedECText="$($_sign_openssl | openssl asn1parse -inform DER)"; then
_err "Sign failed: $_sign_openssl"
_err "Key file: $keyfile"
_err "Key content:$(wc -l <"$keyfile") lises"
return 1
fi
_debug3 "_signedECText" "$_signedECText"
_ec_r="$(echo "$_signedECText" | _head_n 2 | _tail_n 1 | cut -d : -f 4 | tr -d "\r\n")"
_debug3 "_ec_r" "$_ec_r"
_ec_s="$(echo "$_signedECText" | _head_n 3 | _tail_n 1 | cut -d : -f 4 | tr -d "\r\n")"
_debug3 "_ec_s" "$_ec_s"
printf "%s" "$_ec_r$_ec_s" | _h2b | _base64
else
_err "Unknown key file format."
return 1
fi
} }
#keylength #keylength
_isEccKey() { _isEccKey() {
_length="$1" _length="$1"
if [ -z "$_length" ] ;then if [ -z "$_length" ]; then
return 1 return 1
fi fi
[ "$_length" != "1024" ] \ [ "$_length" != "1024" ] \
&& [ "$_length" != "2048" ] \ && [ "$_length" != "2048" ] \
&& [ "$_length" != "3072" ] \ && [ "$_length" != "3072" ] \
&& [ "$_length" != "4096" ] \ && [ "$_length" != "4096" ] \
&& [ "$_length" != "8192" ] && [ "$_length" != "8192" ]
} }
# _createkey 2048|ec-256 file # _createkey 2048|ec-256 file
...@@ -448,47 +510,46 @@ _createkey() { ...@@ -448,47 +510,46 @@ _createkey() {
length="$1" length="$1"
f="$2" f="$2"
eccname="$length" eccname="$length"
if _startswith "$length" "ec-" ; then if _startswith "$length" "ec-"; then
length=$(printf $length | cut -d '-' -f 2-100) length=$(printf "%s" "$length" | cut -d '-' -f 2-100)
if [ "$length" = "256" ] ; then if [ "$length" = "256" ]; then
eccname="prime256v1" eccname="prime256v1"
fi fi
if [ "$length" = "384" ] ; then if [ "$length" = "384" ]; then
eccname="secp384r1" eccname="secp384r1"
fi fi
if [ "$length" = "521" ] ; then if [ "$length" = "521" ]; then
eccname="secp521r1" eccname="secp521r1"
fi fi
fi fi
if [ -z "$length" ] ; then if [ -z "$length" ]; then
length=2048 length=2048
fi fi
_debug "Use length $length" _debug "Use length $length"
if _isEccKey "$length" ; then if _isEccKey "$length"; then
_debug "Using ec name: $eccname" _debug "Using ec name: $eccname"
openssl ecparam -name $eccname -genkey 2>/dev/null > "$f" openssl ecparam -name "$eccname" -genkey 2>/dev/null >"$f"
else else
_debug "Using RSA: $length" _debug "Using RSA: $length"
openssl genrsa $length 2>/dev/null > "$f" openssl genrsa "$length" 2>/dev/null >"$f"
fi fi
if [ "$?" != "0" ] ; then if [ "$?" != "0" ]; then
_err "Create key error." _err "Create key error."
return 1 return 1
fi fi
} }
#domain #domain
_is_idn() { _is_idn() {
_is_idn_d="$1" _is_idn_d="$1"
_debug2 _is_idn_d "$_is_idn_d" _debug2 _is_idn_d "$_is_idn_d"
_idn_temp=$(printf "%s" "$_is_idn_d" | tr -d "[0-9a-zA-Z.,-]") _idn_temp=$(printf "%s" "$_is_idn_d" | tr -d '[0-9]' | tr -d '[a-z]' | tr -d '[A-Z]' | tr -d '.,-')
_debug2 _idn_temp "$_idn_temp" _debug2 _idn_temp "$_idn_temp"
[ "$_idn_temp" ] [ "$_idn_temp" ]
} }
...@@ -497,22 +558,22 @@ _is_idn() { ...@@ -497,22 +558,22 @@ _is_idn() {
#aa.com,bb.com,cc.com #aa.com,bb.com,cc.com
_idn() { _idn() {
__idn_d="$1" __idn_d="$1"
if ! _is_idn "$__idn_d" ; then if ! _is_idn "$__idn_d"; then
printf "%s" "$__idn_d" printf "%s" "$__idn_d"
return 0 return 0
fi fi
if _exists idn ; then if _exists idn; then
if _contains "$__idn_d" ',' ; then if _contains "$__idn_d" ','; then
_i_first="1" _i_first="1"
for f in $(echo "$__idn_d" | tr ',' ' ') ; do for f in $(echo "$__idn_d" | tr ',' ' '); do
[ -z "$f" ] && continue [ -z "$f" ] && continue
if [ -z "$_i_first" ] ; then if [ -z "$_i_first" ]; then
printf "%s" "," printf "%s" ","
else else
_i_first="" _i_first=""
fi fi
idn "$f" | tr -d "\r\n" idn --quiet "$f" | tr -d "\r\n"
done done
else else
idn "$__idn_d" | tr -d "\r\n" idn "$__idn_d" | tr -d "\r\n"
...@@ -535,29 +596,29 @@ _createcsr() { ...@@ -535,29 +596,29 @@ _createcsr() {
_debug2 csrkey "$csrkey" _debug2 csrkey "$csrkey"
_debug2 csr "$csr" _debug2 csr "$csr"
_debug2 csrconf "$csrconf" _debug2 csrconf "$csrconf"
printf "[ req_distinguished_name ]\n[ req ]\ndistinguished_name = req_distinguished_name\nreq_extensions = v3_req\n[ v3_req ]\n\nkeyUsage = nonRepudiation, digitalSignature, keyEncipherment" > "$csrconf" printf "[ req_distinguished_name ]\n[ req ]\ndistinguished_name = req_distinguished_name\nreq_extensions = v3_req\n[ v3_req ]\n\nkeyUsage = nonRepudiation, digitalSignature, keyEncipherment" >"$csrconf"
if [ -z "$domainlist" ] || [ "$domainlist" = "$NO_VALUE" ]; then if [ -z "$domainlist" ] || [ "$domainlist" = "$NO_VALUE" ]; then
#single domain #single domain
_info "Single domain" "$domain" _info "Single domain" "$domain"
else else
domainlist="$(_idn $domainlist)" domainlist="$(_idn "$domainlist")"
_debug2 domainlist "$domainlist" _debug2 domainlist "$domainlist"
if _contains "$domainlist" "," ; then if _contains "$domainlist" ","; then
alt="DNS:$(echo $domainlist | sed "s/,/,DNS:/g")" alt="DNS:$(echo "$domainlist" | sed "s/,/,DNS:/g")"
else else
alt="DNS:$domainlist" alt="DNS:$domainlist"
fi fi
#multi #multi
_info "Multi domain" "$alt" _info "Multi domain" "$alt"
printf -- "\nsubjectAltName=$alt" >> "$csrconf" printf -- "\nsubjectAltName=$alt" >>"$csrconf"
fi fi
if [ "$Le_OCSP_Stable" ] ; then if [ "$Le_OCSP_Stable" ]; then
_savedomainconf Le_OCSP_Stable "$Le_OCSP_Stable" _savedomainconf Le_OCSP_Stable "$Le_OCSP_Stable"
printf -- "\nbasicConstraints = CA:FALSE\n1.3.6.1.5.5.7.1.24=DER:30:03:02:01:05" >> "$csrconf" printf -- "\nbasicConstraints = CA:FALSE\n1.3.6.1.5.5.7.1.24=DER:30:03:02:01:05" >>"$csrconf"
fi fi
_csr_cn="$(_idn "$domain")" _csr_cn="$(_idn "$domain")"
_debug2 _csr_cn "$_csr_cn" _debug2 _csr_cn "$_csr_cn"
openssl req -new -sha256 -key "$csrkey" -subj "/CN=$_csr_cn" -config "$csrconf" -out "$csr" openssl req -new -sha256 -key "$csrkey" -subj "/CN=$_csr_cn" -config "$csrconf" -out "$csr"
...@@ -570,8 +631,8 @@ _signcsr() { ...@@ -570,8 +631,8 @@ _signcsr() {
conf="$3" conf="$3"
cert="$4" cert="$4"
_debug "_signcsr" _debug "_signcsr"
_msg="$(openssl x509 -req -days 365 -in "$csr" -signkey "$key" -extensions v3_req -extfile "$conf" -out "$cert" 2>&1)" _msg="$(openssl 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
...@@ -580,48 +641,48 @@ _signcsr() { ...@@ -580,48 +641,48 @@ _signcsr() {
#_csrfile #_csrfile
_readSubjectFromCSR() { _readSubjectFromCSR() {
_csrfile="$1" _csrfile="$1"
if [ -z "$_csrfile" ] ; then if [ -z "$_csrfile" ]; then
_usage "_readSubjectFromCSR mycsr.csr" _usage "_readSubjectFromCSR mycsr.csr"
return 1 return 1
fi fi
openssl req -noout -in "$_csrfile" -subject | _egrep_o "CN=.*" | cut -d = -f 2 | cut -d / -f 1 | tr -d '\n' openssl req -noout -in "$_csrfile" -subject | _egrep_o "CN=.*" | cut -d = -f 2 | cut -d / -f 1 | tr -d '\n'
} }
#_csrfile #_csrfile
#echo comma separated domain list #echo comma separated domain list
_readSubjectAltNamesFromCSR() { _readSubjectAltNamesFromCSR() {
_csrfile="$1" _csrfile="$1"
if [ -z "$_csrfile" ] ; then if [ -z "$_csrfile" ]; then
_usage "_readSubjectAltNamesFromCSR mycsr.csr" _usage "_readSubjectAltNamesFromCSR mycsr.csr"
return 1 return 1
fi fi
_csrsubj="$(_readSubjectFromCSR "$_csrfile")" _csrsubj="$(_readSubjectFromCSR "$_csrfile")"
_debug _csrsubj "$_csrsubj" _debug _csrsubj "$_csrsubj"
_dnsAltnames="$(openssl req -noout -text -in "$_csrfile" | grep "^ *DNS:.*" | tr -d ' \n')" _dnsAltnames="$(openssl 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
_debug "AltNames contains subject" _debug "AltNames contains subject"
_dnsAltnames="$(printf "%s" "$_dnsAltnames," | sed "s/DNS:$_csrsubj,//g")" _dnsAltnames="$(printf "%s" "$_dnsAltnames," | sed "s/DNS:$_csrsubj,//g")"
else else
_debug "AltNames doesn't contain subject" _debug "AltNames doesn't contain subject"
fi fi
printf "%s" "$_dnsAltnames" | sed "s/DNS://g" printf "%s" "$_dnsAltnames" | sed "s/DNS://g"
} }
#_csrfile #_csrfile
_readKeyLengthFromCSR() { _readKeyLengthFromCSR() {
_csrfile="$1" _csrfile="$1"
if [ -z "$_csrfile" ] ; then if [ -z "$_csrfile" ]; then
_usage "_readKeyLengthFromCSR mycsr.csr" _usage "_readKeyLengthFromCSR mycsr.csr"
return 1 return 1
fi fi
_outcsr="$(openssl req -noout -text -in "$_csrfile")" _outcsr="$(openssl 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
...@@ -630,25 +691,24 @@ _readKeyLengthFromCSR() { ...@@ -630,25 +691,24 @@ _readKeyLengthFromCSR() {
fi fi
} }
_ss() { _ss() {
_port="$1" _port="$1"
if _exists "ss" ; then if _exists "ss"; then
_debug "Using: ss" _debug "Using: ss"
ss -ntpl | grep ":$_port " ss -ntpl | grep ":$_port "
return 0 return 0
fi fi
if _exists "netstat" ; then if _exists "netstat"; then
_debug "Using: netstat" _debug "Using: netstat"
if netstat -h 2>&1 | grep "\-p proto" >/dev/null ; then if netstat -h 2>&1 | grep "\-p proto" >/dev/null; then
#for windows version netstat tool #for windows version netstat tool
netstat -an -p tcp | grep "LISTENING" | grep ":$_port " netstat -an -p tcp | grep "LISTENING" | grep ":$_port "
else else
if netstat -help 2>&1 | grep "\-p protocol" >/dev/null ; then if netstat -help 2>&1 | grep "\-p protocol" >/dev/null; then
netstat -an -p tcp | grep LISTEN | grep ":$_port " netstat -an -p tcp | grep LISTEN | grep ":$_port "
elif netstat -help 2>&1 | grep -- '-P protocol' >/dev/null ; then elif netstat -help 2>&1 | grep -- '-P protocol' >/dev/null; then
#for solaris #for solaris
netstat -an -P tcp | grep "\.$_port " | grep "LISTEN" netstat -an -P tcp | grep "\.$_port " | grep "LISTEN"
else else
...@@ -665,22 +725,22 @@ _ss() { ...@@ -665,22 +725,22 @@ _ss() {
toPkcs() { toPkcs() {
domain="$1" domain="$1"
pfxPassword="$2" pfxPassword="$2"
if [ -z "$domain" ] ; then if [ -z "$domain" ]; then
_usage "Usage: $PROJECT_ENTRY --toPkcs -d domain [--password pfx-password]" _usage "Usage: $PROJECT_ENTRY --toPkcs -d domain [--password pfx-password]"
return 1 return 1
fi fi
_isEcc="$3" _isEcc="$3"
_initpath "$domain" "$_isEcc" _initpath "$domain" "$_isEcc"
if [ "$pfxPassword" ] ; then if [ "$pfxPassword" ]; then
openssl pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH" -password "pass:$pfxPassword" openssl pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH" -password "pass:$pfxPassword"
else else
openssl pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH" openssl 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
_info "Success, Pfx is exported to: $CERT_PFX_PATH" _info "Success, Pfx is exported to: $CERT_PFX_PATH"
fi fi
...@@ -689,24 +749,30 @@ toPkcs() { ...@@ -689,24 +749,30 @@ toPkcs() {
#[2048] #[2048]
createAccountKey() { createAccountKey() {
_info "Creating account key" _info "Creating account key"
if [ -z "$1" ] ; then if [ -z "$1" ]; then
_usage "Usage: $PROJECT_ENTRY --createAccountKey --accountkeylength 2048" _usage "Usage: $PROJECT_ENTRY --createAccountKey --accountkeylength 2048"
return return
fi fi
length=$1 length=$1
if _isEccKey "$length" ; then _create_account_key "$length"
length=2048
fi }
if [ -z "$length" ] || [ "$length" = "$NO_VALUE" ] ; then _create_account_key() {
_debug "Use default length 2048"
length=2048 length=$1
if [ -z "$length" ] || [ "$length" = "$NO_VALUE" ]; then
_debug "Use default length $DEFAULT_ACCOUNT_KEY_LENGTH"
length="$DEFAULT_ACCOUNT_KEY_LENGTH"
fi fi
_debug length "$length" _debug length "$length"
_initpath _initpath
if [ -f "$ACCOUNT_KEY_PATH" ] ; then mkdir -p "$CA_DIR"
if [ -f "$ACCOUNT_KEY_PATH" ]; then
_info "Account key exists, skip" _info "Account key exists, skip"
return return
else else
...@@ -719,20 +785,25 @@ createAccountKey() { ...@@ -719,20 +785,25 @@ createAccountKey() {
#domain [length] #domain [length]
createDomainKey() { createDomainKey() {
_info "Creating domain key" _info "Creating domain key"
if [ -z "$1" ] ; then if [ -z "$1" ]; then
_usage "Usage: $PROJECT_ENTRY --createDomainKey -d domain.com [ --keylength 2048 ]" _usage "Usage: $PROJECT_ENTRY --createDomainKey -d domain.com [ --keylength 2048 ]"
return return
fi fi
domain=$1 domain=$1
length=$2 length=$2
_initpath $domain "$length"
if [ ! -f "$CERT_KEY_PATH" ] || ( [ "$FORCE" ] && ! [ "$IS_RENEW" ] ); then if [ -z "$length" ]; then
_debug "Use DEFAULT_DOMAIN_KEY_LENGTH=$DEFAULT_DOMAIN_KEY_LENGTH"
length="$DEFAULT_DOMAIN_KEY_LENGTH"
fi
_initpath "$domain" "$length"
if [ ! -f "$CERT_KEY_PATH" ] || ([ "$FORCE" ] && ! [ "$IS_RENEW" ]); then
_createkey "$length" "$CERT_KEY_PATH" _createkey "$length" "$CERT_KEY_PATH"
else else
if [ "$IS_RENEW" ] ; then if [ "$IS_RENEW" ]; then
_info "Domain key exists, skip" _info "Domain key exists, skip"
return 0 return 0
else else
...@@ -747,52 +818,52 @@ createDomainKey() { ...@@ -747,52 +818,52 @@ createDomainKey() {
# domain domainlist isEcc # domain domainlist isEcc
createCSR() { createCSR() {
_info "Creating csr" _info "Creating csr"
if [ -z "$1" ] ; then if [ -z "$1" ]; then
_usage "Usage: $PROJECT_ENTRY --createCSR -d domain1.com [-d domain2.com -d domain3.com ... ]" _usage "Usage: $PROJECT_ENTRY --createCSR -d domain1.com [-d domain2.com -d domain3.com ... ]"
return return
fi fi
domain="$1" domain="$1"
domainlist="$2" domainlist="$2"
_isEcc="$3" _isEcc="$3"
_initpath "$domain" "$_isEcc" _initpath "$domain" "$_isEcc"
if [ -f "$CSR_PATH" ] && [ "$IS_RENEW" ] && [ -z "$FORCE" ]; then if [ -f "$CSR_PATH" ] && [ "$IS_RENEW" ] && [ -z "$FORCE" ]; then
_info "CSR exists, skip" _info "CSR exists, skip"
return return
fi fi
if [ ! -f "$CERT_KEY_PATH" ] ; then if [ ! -f "$CERT_KEY_PATH" ]; then
_err "The key file is not found: $CERT_KEY_PATH" _err "The key file is not found: $CERT_KEY_PATH"
_err "Please create the key file first." _err "Please create the key file first."
return 1 return 1
fi fi
_createcsr "$domain" "$domainlist" "$CERT_KEY_PATH" "$CSR_PATH" "$DOMAIN_SSL_CONF" _createcsr "$domain" "$domainlist" "$CERT_KEY_PATH" "$CSR_PATH" "$DOMAIN_SSL_CONF"
} }
_urlencode() { _urlencode() {
__n=$(cat) tr '/+' '_-' | tr -d '= '
echo $__n | tr '/+' '_-' | tr -d '= '
} }
_time2str() { _time2str() {
#BSD #BSD
if date -u -d@$1 2>/dev/null ; then if date -u -d@"$1" 2>/dev/null; then
return return
fi fi
#Linux #Linux
if date -u -r $1 2>/dev/null ; then if date -u -r "$1" 2>/dev/null; then
return return
fi fi
#Soaris #Soaris
if _exists adb ; then if _exists adb; then
echo $(echo "0t${1}=Y" | adb) _t_s_a=$(echo "0t${1}=Y" | adb)
echo "$_t_s_a"
fi fi
} }
_normalizeJson() { _normalizeJson() {
...@@ -801,93 +872,120 @@ _normalizeJson() { ...@@ -801,93 +872,120 @@ _normalizeJson() {
_stat() { _stat() {
#Linux #Linux
if stat -c '%U:%G' "$1" 2>/dev/null ; then if stat -c '%U:%G' "$1" 2>/dev/null; then
return return
fi fi
#BSD #BSD
if stat -f '%Su:%Sg' "$1" 2>/dev/null ; then if stat -f '%Su:%Sg' "$1" 2>/dev/null; then
return return
fi fi
return 1; #error, 'stat' not found return 1 #error, 'stat' not found
} }
#keyfile #keyfile
_calcjwk() { _calcjwk() {
keyfile="$1" keyfile="$1"
if [ -z "$keyfile" ] ; then if [ -z "$keyfile" ]; then
_usage "Usage: _calcjwk keyfile" _usage "Usage: _calcjwk keyfile"
return 1 return 1
fi fi
EC_SIGN=""
if grep "BEGIN RSA PRIVATE KEY" "$keyfile" > /dev/null 2>&1 ; then if [ "$JWK_HEADER" ] && [ "$__CACHED_JWK_KEY_FILE" = "$keyfile" ]; then
_debug2 "Use cached jwk for file: $__CACHED_JWK_KEY_FILE"
return 0
fi
if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
_debug "RSA key" _debug "RSA key"
pub_exp=$(openssl rsa -in $keyfile -noout -text | grep "^publicExponent:"| cut -d '(' -f 2 | cut -d 'x' -f 2 | cut -d ')' -f 1) pub_exp=$(openssl 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
_debug3 pub_exp "$pub_exp" _debug3 pub_exp "$pub_exp"
e=$(echo $pub_exp | _h2b | _base64) e=$(echo "$pub_exp" | _h2b | _base64)
_debug3 e "$e" _debug3 e "$e"
modulus=$(openssl rsa -in $keyfile -modulus -noout | cut -d '=' -f 2 ) modulus=$(openssl rsa -in "$keyfile" -modulus -noout | cut -d '=' -f 2)
_debug3 modulus "$modulus" _debug3 modulus "$modulus"
n="$(printf "%s" "$modulus"| _h2b | _base64 | _urlencode )" n="$(printf "%s" "$modulus" | _h2b | _base64 | _urlencode)"
jwk='{"e": "'$e'", "kty": "RSA", "n": "'$n'"}' jwk='{"e": "'$e'", "kty": "RSA", "n": "'$n'"}'
_debug3 jwk "$jwk" _debug3 jwk "$jwk"
HEADER='{"alg": "RS256", "jwk": '$jwk'}' JWK_HEADER='{"alg": "RS256", "jwk": '$jwk'}'
HEADERPLACE_PART1='{"nonce": "' JWK_HEADERPLACE_PART1='{"nonce": "'
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"
EC_SIGN="1" crv="$(openssl ec -in "$keyfile" -noout -text 2>/dev/null | grep "^NIST CURVE:" | cut -d ":" -f 2 | tr -d " \r\n")"
crv="$(openssl 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"
pubi="$(openssl ec -in $keyfile -noout -text 2>/dev/null | grep -n pub: | cut -d : -f 1)" if [ -z "$crv" ]; then
pubi=$(_math $pubi + 1) _debug "Let's try ASN1 OID"
crv_oid="$(openssl ec -in "$keyfile" -noout -text 2>/dev/null | grep "^ASN1 OID:" | cut -d ":" -f 2 | tr -d " \r\n")"
_debug3 crv_oid "$crv_oid"
case "${crv_oid}" in
"prime256v1")
crv="P-256"
;;
"secp384r1")
crv="P-384"
;;
"secp521r1")
crv="P-521"
;;
*)
_err "ECC oid : $crv_oid"
return 1
;;
esac
_debug3 crv "$crv"
fi
pubi="$(openssl ec -in "$keyfile" -noout -text 2>/dev/null | grep -n pub: | cut -d : -f 1)"
pubi=$(_math "$pubi" + 1)
_debug3 pubi "$pubi" _debug3 pubi "$pubi"
pubj="$(openssl ec -in $keyfile -noout -text 2>/dev/null | grep -n "ASN1 OID:" | cut -d : -f 1)" pubj="$(openssl 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 ec -in $keyfile -noout -text 2>/dev/null | sed -n "$pubi,${pubj}p" | tr -d " \n\r")" pubtext="$(openssl 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 "$pubtext" | tr -d ':' | wc -c)" xlen="$(printf "%s" "$pubtext" | tr -d ':' | wc -c)"
xlen=$(_math $xlen / 4) xlen=$(_math "$xlen" / 4)
_debug3 xlen "$xlen" _debug3 xlen "$xlen"
xend=$(_math "$xend" + 1) xend=$(_math "$xlen" + 1)
x="$(printf $pubtext | cut -d : -f 2-$xend)" x="$(printf "%s" "$pubtext" | cut -d : -f 2-"$xend")"
_debug3 x "$x" _debug3 x "$x"
x64="$(printf $x | tr -d : | _h2b | _base64 | _urlencode)" x64="$(printf "%s" "$x" | tr -d : | _h2b | _base64 | _urlencode)"
_debug3 x64 "$x64" _debug3 x64 "$x64"
xend=$(_math "$xend" + 1) xend=$(_math "$xend" + 1)
y="$(printf $pubtext | cut -d : -f $xend-10000)" y="$(printf "%s" "$pubtext" | cut -d : -f "$xend"-10000)"
_debug3 y "$y" _debug3 y "$y"
y64="$(printf $y | tr -d : | _h2b | _base64 | _urlencode)" y64="$(printf "%s" "$y" | tr -d : | _h2b | _base64 | _urlencode)"
_debug3 y64 "$y64" _debug3 y64 "$y64"
jwk='{"kty": "EC", "crv": "'$crv'", "x": "'$x64'", "y": "'$y64'"}' jwk='{"crv": "'$crv'", "kty": "EC", "x": "'$x64'", "y": "'$y64'"}'
_debug3 jwk "$jwk" _debug3 jwk "$jwk"
HEADER='{"alg": "ES256", "jwk": '$jwk'}' JWK_HEADER='{"alg": "ES256", "jwk": '$jwk'}'
HEADERPLACE_PART1='{"nonce": "' JWK_HEADERPLACE_PART1='{"nonce": "'
HEADERPLACE_PART2='", "alg": "ES256", "jwk": '$jwk'}' JWK_HEADERPLACE_PART2='", "alg": "ES256", "jwk": '$jwk'}'
else else
_err "Only RSA or EC key is supported." _err "Only RSA or EC key is supported."
return 1 return 1
fi fi
_debug3 HEADER "$HEADER" _debug3 JWK_HEADER "$JWK_HEADER"
__CACHED_JWK_KEY_FILE="$keyfile"
} }
_time() { _time() {
...@@ -895,59 +993,70 @@ _time() { ...@@ -895,59 +993,70 @@ _time() {
} }
_mktemp() { _mktemp() {
if _exists mktemp ; then if _exists mktemp; then
if mktemp 2>/dev/null ; then if mktemp 2>/dev/null; then
return return 0
elif _contains "$(mktemp 2>&1)" "-t prefix" && mktemp -t "$PROJECT_NAME" 2>/dev/null ; then elif _contains "$(mktemp 2>&1)" "-t prefix" && mktemp -t "$PROJECT_NAME" 2>/dev/null; then
#for Mac osx #for Mac osx
return return 0
fi fi
fi fi
if [ -d "/tmp" ] ; then if [ -d "/tmp" ]; then
echo "/tmp/${PROJECT_NAME}wefADf24sf.$(_time).tmp" echo "/tmp/${PROJECT_NAME}wefADf24sf.$(_time).tmp"
return 0 return 0
elif [ "$LE_TEMP_DIR" ] && mkdir -p "$LE_TEMP_DIR"; then
echo "/$LE_TEMP_DIR/wefADf24sf.$(_time).tmp"
return 0
fi fi
_err "Can not create temp file." _err "Can not create temp file."
} }
_inithttp() { _inithttp() {
if [ -z "$HTTP_HEADER" ] || ! touch "$HTTP_HEADER" ; then if [ -z "$HTTP_HEADER" ] || ! touch "$HTTP_HEADER"; then
HTTP_HEADER="$(_mktemp)" HTTP_HEADER="$(_mktemp)"
_debug2 HTTP_HEADER "$HTTP_HEADER" _debug2 HTTP_HEADER "$HTTP_HEADER"
fi fi
if [ -z "$CURL" ] ; then if [ "$__HTTP_INITIALIZED" ]; then
CURL="curl -L --silent --dump-header $HTTP_HEADER " if [ "$_ACME_CURL$_ACME_WGET" ]; then
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ] ; then _debug2 "Http already initialized."
return 0
fi
fi
if [ -z "$_ACME_CURL" ] && _exists "curl"; then
_ACME_CURL="curl -L --silent --dump-header $HTTP_HEADER "
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
_CURL_DUMP="$(_mktemp)" _CURL_DUMP="$(_mktemp)"
CURL="$CURL --trace-ascii $_CURL_DUMP " _ACME_CURL="$_ACME_CURL --trace-ascii $_CURL_DUMP "
fi fi
if [ "$CA_BUNDLE" ] ; then if [ "$CA_BUNDLE" ]; then
CURL="$CURL --cacert $CA_BUNDLE " _ACME_CURL="$_ACME_CURL --cacert $CA_BUNDLE "
fi fi
if [ "$HTTPS_INSECURE" ] ; then if [ "$HTTPS_INSECURE" ]; then
CURL="$CURL --insecure " _ACME_CURL="$_ACME_CURL --insecure "
fi fi
fi fi
if [ -z "$WGET" ] ; then if [ -z "$_ACME_WGET" ] && _exists "wget"; then
WGET="wget -q" _ACME_WGET="wget -q"
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ] ; then if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
WGET="$WGET -d " _ACME_WGET="$_ACME_WGET -d "
fi fi
if [ "$CA_BUNDLE" ] ; then if [ "$CA_BUNDLE" ]; then
WGET="$WGET --ca-certificate $CA_BUNDLE " _ACME_WGET="$_ACME_WGET --ca-certificate $CA_BUNDLE "
fi fi
if [ "$HTTPS_INSECURE" ] ; then if [ "$HTTPS_INSECURE" ]; then
WGET="$WGET --no-check-certificate " _ACME_WGET="$_ACME_WGET --no-check-certificate "
fi fi
fi fi
} __HTTP_INITIALIZED=1
}
# body url [needbase64] [POST|PUT] # body url [needbase64] [POST|PUT]
_post() { _post() {
...@@ -956,53 +1065,53 @@ _post() { ...@@ -956,53 +1065,53 @@ _post() {
needbase64="$3" needbase64="$3"
httpmethod="$4" httpmethod="$4"
if [ -z "$httpmethod" ] ; then if [ -z "$httpmethod" ]; then
httpmethod="POST" httpmethod="POST"
fi fi
_debug $httpmethod _debug $httpmethod
_debug "url" "$url" _debug "url" "$url"
_debug2 "body" "$body" _debug2 "body" "$body"
_inithttp _inithttp
if _exists "curl" ; then if [ "$_ACME_CURL" ]; then
_CURL="$CURL" _CURL="$_ACME_CURL"
_debug "_CURL" "$_CURL" _debug "_CURL" "$_CURL"
if [ "$needbase64" ] ; then if [ "$needbase64" ]; then
response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$url" | _base64)" response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$url" | _base64)"
else else
response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$url" )" response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$url")"
fi fi
_ret="$?" _ret="$?"
if [ "$_ret" != "0" ] ; then if [ "$_ret" != "0" ]; then
_err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $_ret" _err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $_ret"
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ] ; then if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
_err "Here is the curl dump log:" _err "Here is the curl dump log:"
_err "$(cat "$_CURL_DUMP")" _err "$(cat "$_CURL_DUMP")"
fi fi
fi fi
elif _exists "wget" ; then elif [ "$_ACME_WGET" ]; then
_debug "WGET" "$WGET" _debug "_ACME_WGET" "$_ACME_WGET"
if [ "$needbase64" ] ; then if [ "$needbase64" ]; then
if [ "$httpmethod" = "POST" ] ; then if [ "$httpmethod" = "POST" ]; then
response="$($WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-data="$body" "$url" 2>"$HTTP_HEADER" | _base64)" response="$($_ACME_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-data="$body" "$url" 2>"$HTTP_HEADER" | _base64)"
else else
response="$($WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --method $httpmethod --body-data="$body" "$url" 2>"$HTTP_HEADER" | _base64)" response="$($_ACME_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --method $httpmethod --body-data="$body" "$url" 2>"$HTTP_HEADER" | _base64)"
fi fi
else else
if [ "$httpmethod" = "POST" ] ; then if [ "$httpmethod" = "POST" ]; then
response="$($WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-data="$body" "$url" 2>"$HTTP_HEADER")" response="$($_ACME_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-data="$body" "$url" 2>"$HTTP_HEADER")"
else else
response="$($WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --method $httpmethod --body-data="$body" "$url" 2>"$HTTP_HEADER")" response="$($_ACME_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --method $httpmethod --body-data="$body" "$url" 2>"$HTTP_HEADER")"
fi fi
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' respons, 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"
fi fi
_sed_i "s/^ *//g" "$HTTP_HEADER" _sed_i "s/^ *//g" "$HTTP_HEADER"
else else
...@@ -1014,55 +1123,54 @@ _post() { ...@@ -1014,55 +1123,54 @@ _post() {
return $_ret return $_ret
} }
# url getheader timeout # url getheader timeout
_get() { _get() {
_debug GET _debug GET
url="$1" url="$1"
onlyheader="$2" onlyheader="$2"
t="$3" t="$3"
_debug url $url _debug url "$url"
_debug "timeout" "$t" _debug "timeout" "$t"
_inithttp _inithttp
if _exists "curl" ; then if [ "$_ACME_CURL" ]; then
_CURL="$CURL" _CURL="$_ACME_CURL"
if [ "$t" ] ; then if [ "$t" ]; then
_CURL="$_CURL --connect-timeout $t" _CURL="$_CURL --connect-timeout $t"
fi fi
_debug "_CURL" "$_CURL" _debug "_CURL" "$_CURL"
if [ "$onlyheader" ] ; then if [ "$onlyheader" ]; then
$_CURL -I --user-agent "$USER_AGENT" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" $url $_CURL -I --user-agent "$USER_AGENT" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$url"
else else
$_CURL --user-agent "$USER_AGENT" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" $url $_CURL --user-agent "$USER_AGENT" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$url"
fi fi
ret=$? ret=$?
if [ "$ret" != "0" ] ; then if [ "$ret" != "0" ]; then
_err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $ret" _err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $ret"
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ] ; then if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
_err "Here is the curl dump log:" _err "Here is the curl dump log:"
_err "$(cat "$_CURL_DUMP")" _err "$(cat "$_CURL_DUMP")"
fi fi
fi fi
elif _exists "wget" ; then elif [ "$_ACME_WGET" ]; then
_WGET="$WGET" _WGET="$_ACME_WGET"
if [ "$t" ] ; then if [ "$t" ]; then
_WGET="$_WGET --timeout=$t" _WGET="$_WGET --timeout=$t"
fi fi
_debug "_WGET" "$_WGET" _debug "_WGET" "$_WGET"
if [ "$onlyheader" ] ; then if [ "$onlyheader" ]; then
$_WGET --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" -S -O /dev/null $url 2>&1 | sed 's/^[ ]*//g' $_WGET --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" -S -O /dev/null "$url" 2>&1 | sed 's/^[ ]*//g'
else else
$_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' respons, 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"
fi fi
else else
ret=$? ret=$?
...@@ -1073,13 +1181,13 @@ _get() { ...@@ -1073,13 +1181,13 @@ _get() {
} }
_head_n() { _head_n() {
head -n $1 head -n "$1"
} }
_tail_n() { _tail_n() {
if ! tail -n $1 2>/dev/null ; then if ! tail -n "$1" 2>/dev/null; then
#fix for solaris #fix for solaris
tail -$1 tail -"$1"
fi fi
} }
...@@ -1089,64 +1197,77 @@ _send_signed_request() { ...@@ -1089,64 +1197,77 @@ _send_signed_request() {
payload=$2 payload=$2
needbase64=$3 needbase64=$3
keyfile=$4 keyfile=$4
if [ -z "$keyfile" ] ; then if [ -z "$keyfile" ]; then
keyfile="$ACCOUNT_KEY_PATH" keyfile="$ACCOUNT_KEY_PATH"
fi fi
_debug url $url _debug url "$url"
_debug payload "$payload" _debug payload "$payload"
if ! _calcjwk "$keyfile" ; then if ! _calcjwk "$keyfile"; then
return 1 return 1
fi fi
payload64=$(printf "%s" "$payload" | _base64 | _urlencode) payload64=$(printf "%s" "$payload" | _base64 | _urlencode)
_debug3 payload64 $payload64 _debug3 payload64 "$payload64"
nonceurl="$API/directory" if [ -z "$_CACHED_NONCE" ]; then
_headers="$(_get $nonceurl "onlyheader")" _debug2 "Get nonce."
nonceurl="$API/directory"
if [ "$?" != "0" ] ; then _headers="$(_get "$nonceurl" "onlyheader")"
_err "Can not connect to $nonceurl to get nonce."
return 1 if [ "$?" != "0" ]; then
_err "Can not connect to $nonceurl to get nonce."
return 1
fi
_debug2 _headers "$_headers"
_CACHED_NONCE="$(echo "$_headers" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)"
_debug2 _CACHED_NONCE "$_CACHED_NONCE"
else
_debug2 "Use _CACHED_NONCE" "$_CACHED_NONCE"
fi fi
nonce="$_CACHED_NONCE"
_debug3 _headers "$_headers" _debug2 nonce "$nonce"
nonce="$( echo "$_headers" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)"
_debug3 nonce "$nonce" protected="$JWK_HEADERPLACE_PART1$nonce$JWK_HEADERPLACE_PART2"
protected="$HEADERPLACE_PART1$nonce$HEADERPLACE_PART2"
_debug3 protected "$protected" _debug3 protected "$protected"
protected64="$(printf "$protected" | _base64 | _urlencode)" protected64="$(printf "%s" "$protected" | _base64 | _urlencode)"
_debug3 protected64 "$protected64" _debug3 protected64 "$protected64"
sig=$(printf "%s" "$protected64.$payload64" | _sign "$keyfile" "sha256" | _urlencode) if ! _sig_t="$(printf "%s" "$protected64.$payload64" | _sign "$keyfile" "sha256")"; then
_err "Sign request failed."
return 1
fi
_debug3 _sig_t "$_sig_t"
sig="$(printf "%s" "$_sig_t" | _urlencode)"
_debug3 sig "$sig" _debug3 sig "$sig"
body="{\"header\": $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")"
if [ "$?" != "0" ] ; then _CACHED_NONCE=""
if [ "$?" != "0" ]; then
_err "Can not post to $url" _err "Can not post to $url"
return 1 return 1
fi fi
_debug2 original "$response" _debug2 original "$response"
response="$( echo "$response" | _normalizeJson )"
responseHeaders="$(cat $HTTP_HEADER)" response="$(echo "$response" | _normalizeJson)"
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)"
}
#setopt "file" "opt" "=" "value" [";"] #setopt "file" "opt" "=" "value" [";"]
_setopt() { _setopt() {
...@@ -1155,90 +1276,114 @@ _setopt() { ...@@ -1155,90 +1276,114 @@ _setopt() {
__sep="$3" __sep="$3"
__val="$4" __val="$4"
__end="$5" __end="$5"
if [ -z "$__opt" ] ; then if [ -z "$__opt" ]; then
_usage usage: _setopt '"file" "opt" "=" "value" [";"]' _usage usage: _setopt '"file" "opt" "=" "value" [";"]'
return return
fi fi
if [ ! -f "$__conf" ] ; then if [ ! -f "$__conf" ]; then
touch "$__conf" touch "$__conf"
fi fi
if grep -n "^$__opt$__sep" "$__conf" > /dev/null ; then if grep -n "^$__opt$__sep" "$__conf" >/dev/null; then
_debug3 OK _debug3 OK
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" echo "$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" echo "$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
_debug2 "$(grep -n "^$__opt$__sep" "$__conf")"
}
#_save_conf file key value
#save to conf
_save_conf() {
_s_c_f="$1"
_sdkey="$2"
_sdvalue="$3"
if [ "$_s_c_f" ]; then
_setopt "$_s_c_f" "$_sdkey" "=" "'$_sdvalue'"
else
_err "config file is empty, can not save $_sdkey=$_sdvalue"
fi
}
#_clear_conf file key
_clear_conf() {
_c_c_f="$1"
_sdkey="$2"
if [ "$_c_c_f" ]; then
_conf_data="$(cat "$_c_c_f")"
echo "$_conf_data" | sed "s/^$_sdkey *=.*$//" > "$_c_c_f"
else
_err "config file is empty, can not clear"
fi
}
#_read_conf file key
_read_conf() {
_r_c_f="$1"
_sdkey="$2"
if [ -f "$_r_c_f" ]; then
(
eval "$(grep "^$_sdkey *=" "$_r_c_f")"
eval "printf \"%s\" \"\$$_sdkey\""
)
else
_debug "config file is empty, can not read $_sdkey"
fi fi
_debug2 "$(grep -n "^$__opt$__sep" $__conf)"
} }
#_savedomainconf key value #_savedomainconf key value
#save to domain.conf #save to domain.conf
_savedomainconf() { _savedomainconf() {
_sdkey="$1" _save_conf "$DOMAIN_CONF" "$1" "$2"
_sdvalue="$2"
if [ "$DOMAIN_CONF" ] ; then
_setopt "$DOMAIN_CONF" "$_sdkey" "=" "\"$_sdvalue\""
else
_err "DOMAIN_CONF is empty, can not save $_sdkey=$_sdvalue"
fi
} }
#_cleardomainconf key #_cleardomainconf key
_cleardomainconf() { _cleardomainconf() {
_sdkey="$1" _clear_conf "$DOMAIN_CONF" "$1"
if [ "$DOMAIN_CONF" ] ; then
_sed_i "s/^$_sdkey.*$//" "$DOMAIN_CONF"
else
_err "DOMAIN_CONF is empty, can not save $_sdkey=$value"
fi
} }
#_readdomainconf key #_readdomainconf key
_readdomainconf() { _readdomainconf() {
_sdkey="$1" _read_conf "$DOMAIN_CONF" "$1"
if [ "$DOMAIN_CONF" ] ; then
(
eval $(grep "^$_sdkey *=" "$DOMAIN_CONF")
eval "printf \"%s\" \"\$$_sdkey\""
)
else
_err "DOMAIN_CONF is empty, can not read $_sdkey"
fi
} }
#_saveaccountconf key value #_saveaccountconf key value
_saveaccountconf() { _saveaccountconf() {
_sckey="$1" _save_conf "$ACCOUNT_CONF_PATH" "$1" "$2"
_scvalue="$2"
if [ "$ACCOUNT_CONF_PATH" ] ; then
_setopt "$ACCOUNT_CONF_PATH" "$_sckey" "=" "'$_scvalue'"
else
_err "ACCOUNT_CONF_PATH is empty, can not save $_sckey=$_scvalue"
fi
} }
#_clearaccountconf key #_clearaccountconf key
_clearaccountconf() { _clearaccountconf() {
_scvalue="$1" _clear_conf "$ACCOUNT_CONF_PATH" "$1"
if [ "$ACCOUNT_CONF_PATH" ] ; then }
_sed_i "s/^$_scvalue.*$//" "$ACCOUNT_CONF_PATH"
else #_savecaconf key value
_err "ACCOUNT_CONF_PATH is empty, can not clear $_scvalue" _savecaconf() {
fi _save_conf "$CA_CONF" "$1" "$2"
}
#_readcaconf key
_readcaconf() {
_read_conf "$CA_CONF" "$1"
}
#_clearaccountconf key
_clearcaconf() {
_clear_conf "$CA_CONF" "$1"
} }
# content localaddress # content localaddress
...@@ -1249,84 +1394,83 @@ _startserver() { ...@@ -1249,84 +1394,83 @@ _startserver() {
_debug "startserver: $$" _debug "startserver: $$"
nchelp="$(nc -h 2>&1)" nchelp="$(nc -h 2>&1)"
_debug Le_HTTPPort "$Le_HTTPPort" _debug Le_HTTPPort "$Le_HTTPPort"
_debug Le_Listen_V4 "$Le_Listen_V4" _debug Le_Listen_V4 "$Le_Listen_V4"
_debug Le_Listen_V6 "$Le_Listen_V6" _debug Le_Listen_V6 "$Le_Listen_V6"
_NC="nc" _NC="nc"
if [ "$Le_Listen_V4" ] ; then if [ "$Le_Listen_V4" ]; then
_NC="$_NC -4" _NC="$_NC -4"
elif [ "$Le_Listen_V6" ] ; then elif [ "$Le_Listen_V6" ]; then
_NC="$_NC -6" _NC="$_NC -6"
fi fi
if 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
if echo "$nchelp" | grep "GNU netcat" >/dev/null && echo "$nchelp" | grep "\-c, \-\-close" >/dev/null ; then if echo "$nchelp" | grep "GNU netcat" >/dev/null && echo "$nchelp" | grep "\-c, \-\-close" >/dev/null; then
_NC="$_NC -c -l $ncaddr" _NC="$_NC -c -l $ncaddr"
elif echo "$nchelp" | grep "\-N" |grep "Shutdown the network socket after EOF on stdin" >/dev/null ; then elif echo "$nchelp" | grep "\-N" | grep "Shutdown the network socket after EOF on stdin" >/dev/null; then
_NC="$_NC -N -l $ncaddr" _NC="$_NC -N -l $ncaddr"
else else
_NC="$_NC -l $ncaddr" _NC="$_NC -l $ncaddr"
fi fi
fi fi
_debug "_NC" "$_NC" _debug "_NC" "$_NC"
#for centos ncat #for centos ncat
if _contains "$nchelp" "nmap.org" ; then if _contains "$nchelp" "nmap.org"; then
_debug "Using ncat: nmap.org" _debug "Using ncat: nmap.org"
if [ "$DEBUG" ] ; then if [ "$DEBUG" ]; then
if printf "HTTP/1.1 200 OK\r\n\r\n$content" | $_NC $Le_HTTPPort ; then if printf "%s\r\n\r\n%s" "HTTP/1.1 200 OK" "$content" | $_NC "$Le_HTTPPort"; then
return return
fi fi
else else
if printf "HTTP/1.1 200 OK\r\n\r\n$content" | $_NC $Le_HTTPPort > /dev/null 2>&1; then if printf "%s\r\n\r\n%s" "HTTP/1.1 200 OK" "$content" | $_NC "$Le_HTTPPort" >/dev/null 2>&1; then
return return
fi fi
fi fi
_err "ncat listen error." _err "ncat listen error."
fi fi
# while true ; do # while true ; do
if [ "$DEBUG" ] ; then if [ "$DEBUG" ]; then
if ! printf "HTTP/1.1 200 OK\r\n\r\n$content" | $_NC -p $Le_HTTPPort ; then if ! printf "%s\r\n\r\n%s" "HTTP/1.1 200 OK" "$content" | $_NC -p "$Le_HTTPPort"; then
printf "HTTP/1.1 200 OK\r\n\r\n$content" | $_NC $Le_HTTPPort ; printf "%s\r\n\r\n%s" "HTTP/1.1 200 OK" "$content" | $_NC "$Le_HTTPPort"
fi
else
if ! printf "HTTP/1.1 200 OK\r\n\r\n$content" | $_NC -p $Le_HTTPPort > /dev/null 2>&1; then
printf "HTTP/1.1 200 OK\r\n\r\n$content" | $_NC $Le_HTTPPort > /dev/null 2>&1
fi
fi fi
if [ "$?" != "0" ] ; then else
_err "nc listen error." if ! printf "%s\r\n\r\n%s" "HTTP/1.1 200 OK" "$content" | $_NC -p "$Le_HTTPPort" >/dev/null 2>&1; then
exit 1 printf "%s\r\n\r\n%s" "HTTP/1.1 200 OK" "$content" | $_NC "$Le_HTTPPort" >/dev/null 2>&1
fi fi
# done fi
if [ "$?" != "0" ]; then
_err "nc listen error."
exit 1
fi
# done
} }
_stopserver(){ _stopserver() {
pid="$1" pid="$1"
_debug "pid" "$pid" _debug "pid" "$pid"
if [ -z "$pid" ] ; then if [ -z "$pid" ]; then
return return
fi fi
_debug2 "Le_HTTPPort" "$Le_HTTPPort" _debug2 "Le_HTTPPort" "$Le_HTTPPort"
if [ "$Le_HTTPPort" ] ; then if [ "$Le_HTTPPort" ]; then
if [ "$DEBUG" ] && [ "$DEBUG" -gt "3" ] ; then if [ "$DEBUG" ] && [ "$DEBUG" -gt "3" ]; then
_get "http://localhost:$Le_HTTPPort" "" 1 _get "http://localhost:$Le_HTTPPort" "" 1
else else
_get "http://localhost:$Le_HTTPPort" "" 1 >/dev/null 2>&1 _get "http://localhost:$Le_HTTPPort" "" 1 >/dev/null 2>&1
fi fi
fi fi
_debug2 "Le_TLSPort" "$Le_TLSPort" _debug2 "Le_TLSPort" "$Le_TLSPort"
if [ "$Le_TLSPort" ] ; then if [ "$Le_TLSPort" ]; then
if [ "$DEBUG" ] && [ "$DEBUG" -gt "3" ] ; then if [ "$DEBUG" ] && [ "$DEBUG" -gt "3" ]; then
_get "https://localhost:$Le_TLSPort" "" 1 _get "https://localhost:$Le_TLSPort" "" 1
_get "https://localhost:$Le_TLSPort" "" 1 _get "https://localhost:$Le_TLSPort" "" 1
else else
...@@ -1339,13 +1483,12 @@ _stopserver(){ ...@@ -1339,13 +1483,12 @@ _stopserver(){
# sleep sec # sleep sec
_sleep() { _sleep() {
_sleep_sec="$1" _sleep_sec="$1"
if [ "$__INTERACTIVE" ] ; then if [ "$__INTERACTIVE" ]; then
_sleep_c="$_sleep_sec" _sleep_c="$_sleep_sec"
while [ "$_sleep_c" -ge "0" ] ; while [ "$_sleep_c" -ge "0" ]; do
do
printf "\r \r" printf "\r \r"
__green "$_sleep_c" __green "$_sleep_c"
_sleep_c="$(_math $_sleep_c - 1)" _sleep_c="$(_math "$_sleep_c" - 1)"
sleep 1 sleep 1
done done
printf "\r" printf "\r"
...@@ -1362,35 +1505,35 @@ _starttlsserver() { ...@@ -1362,35 +1505,35 @@ _starttlsserver() {
port="$3" port="$3"
content="$4" content="$4"
opaddr="$5" opaddr="$5"
_debug san_a "$san_a" _debug san_a "$san_a"
_debug san_b "$san_b" _debug san_b "$san_b"
_debug port "$port" _debug port "$port"
#create key TLS_KEY #create key TLS_KEY
if ! _createkey "2048" "$TLS_KEY" ; then if ! _createkey "2048" "$TLS_KEY"; then
_err "Create tls validation key error." _err "Create tls validation key error."
return 1 return 1
fi fi
#create csr #create csr
alt="$san_a" alt="$san_a"
if [ "$san_b" ] ; then if [ "$san_b" ]; then
alt="$alt,$san_b" alt="$alt,$san_b"
fi fi
if ! _createcsr "tls.acme.sh" "$alt" "$TLS_KEY" "$TLS_CSR" "$TLS_CONF" ; then if ! _createcsr "tls.acme.sh" "$alt" "$TLS_KEY" "$TLS_CSR" "$TLS_CONF"; then
_err "Create tls validation csr error." _err "Create tls validation csr error."
return 1 return 1
fi fi
#self signed #self signed
if ! _signcsr "$TLS_KEY" "$TLS_CSR" "$TLS_CONF" "$TLS_CERT" ; then if ! _signcsr "$TLS_KEY" "$TLS_CSR" "$TLS_CONF" "$TLS_CERT"; then
_err "Create tls validation cert error." _err "Create tls validation cert error."
return 1 return 1
fi fi
__S_OPENSSL="openssl s_server -cert $TLS_CERT -key $TLS_KEY " __S_OPENSSL="openssl 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
__S_OPENSSL="$__S_OPENSSL -accept $port" __S_OPENSSL="$__S_OPENSSL -accept $port"
...@@ -1398,47 +1541,47 @@ _starttlsserver() { ...@@ -1398,47 +1541,47 @@ _starttlsserver() {
_debug Le_Listen_V4 "$Le_Listen_V4" _debug Le_Listen_V4 "$Le_Listen_V4"
_debug Le_Listen_V6 "$Le_Listen_V6" _debug Le_Listen_V6 "$Le_Listen_V6"
if [ "$Le_Listen_V4" ] ; then if [ "$Le_Listen_V4" ]; then
__S_OPENSSL="$__S_OPENSSL -4" __S_OPENSSL="$__S_OPENSSL -4"
elif [ "$Le_Listen_V6" ] ; then elif [ "$Le_Listen_V6" ]; then
__S_OPENSSL="$__S_OPENSSL -6" __S_OPENSSL="$__S_OPENSSL -6"
fi fi
#start openssl #start openssl
_debug "$__S_OPENSSL" _debug "$__S_OPENSSL"
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ] ; then if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
(printf "HTTP/1.1 200 OK\r\n\r\n$content" | $__S_OPENSSL -tlsextdebug ) & (printf "%s\r\n\r\n%s" "HTTP/1.1 200 OK" "$content" | $__S_OPENSSL -tlsextdebug) &
else else
(printf "HTTP/1.1 200 OK\r\n\r\n$content" | $__S_OPENSSL >/dev/null 2>&1) & (printf "%s\r\n\r\n%s" "HTTP/1.1 200 OK" "$content" | $__S_OPENSSL >/dev/null 2>&1) &
fi fi
serverproc="$!" serverproc="$!"
sleep 2 sleep 1
_debug serverproc $serverproc _debug serverproc "$serverproc"
} }
#file #file
_readlink() { _readlink() {
_rf="$1" _rf="$1"
if ! readlink -f "$_rf" 2>/dev/null; then if ! readlink -f "$_rf" 2>/dev/null; then
if _startswith "$_rf" "\./$PROJECT_ENTRY" ; then if _startswith "$_rf" "\./$PROJECT_ENTRY"; then
printf -- "%s" "$(pwd)/$PROJECT_ENTRY" printf -- "%s" "$(pwd)/$PROJECT_ENTRY"
return 0 return 0
fi fi
readlink "$_rf" readlink "$_rf"
fi fi
} }
__initHome() { __initHome() {
if [ -z "$_SCRIPT_HOME" ] ; then if [ -z "$_SCRIPT_HOME" ]; then
if _exists readlink && _exists dirname ; then if _exists readlink && _exists dirname; then
_debug "Lets find script dir." _debug "Lets find script dir."
_debug "_SCRIPT_" "$_SCRIPT_" _debug "_SCRIPT_" "$_SCRIPT_"
_script="$(_readlink "$_SCRIPT_")" _script="$(_readlink "$_SCRIPT_")"
_debug "_script" "$_script" _debug "_script" "$_script"
_script_home="$(dirname "$_script")" _script_home="$(dirname "$_script")"
_debug "_script_home" "$_script_home" _debug "_script_home" "$_script_home"
if [ -d "$_script_home" ] ; then if [ -d "$_script_home" ]; then
_SCRIPT_HOME="$_script_home" _SCRIPT_HOME="$_script_home"
else else
_err "It seems the script home is not correct:$_script_home" _err "It seems the script home is not correct:$_script_home"
...@@ -1446,17 +1589,16 @@ __initHome() { ...@@ -1446,17 +1589,16 @@ __initHome() {
fi fi
fi fi
if [ -z "$LE_WORKING_DIR" ]; then
if [ -z "$LE_WORKING_DIR" ] ; then if [ -f "$DEFAULT_INSTALL_HOME/account.conf" ]; then
if [ -f "$DEFAULT_INSTALL_HOME/account.conf" ] ; then
_debug "It seems that $PROJECT_NAME is already installed in $DEFAULT_INSTALL_HOME" _debug "It seems that $PROJECT_NAME is already installed in $DEFAULT_INSTALL_HOME"
LE_WORKING_DIR="$DEFAULT_INSTALL_HOME" LE_WORKING_DIR="$DEFAULT_INSTALL_HOME"
else else
LE_WORKING_DIR="$_SCRIPT_HOME" LE_WORKING_DIR="$_SCRIPT_HOME"
fi fi
fi fi
if [ -z "$LE_WORKING_DIR" ] ; then if [ -z "$LE_WORKING_DIR" ]; then
_debug "Using default home:$DEFAULT_INSTALL_HOME" _debug "Using default home:$DEFAULT_INSTALL_HOME"
LE_WORKING_DIR="$DEFAULT_INSTALL_HOME" LE_WORKING_DIR="$DEFAULT_INSTALL_HOME"
fi fi
...@@ -1464,19 +1606,23 @@ __initHome() { ...@@ -1464,19 +1606,23 @@ __initHome() {
_DEFAULT_ACCOUNT_CONF_PATH="$LE_WORKING_DIR/account.conf" _DEFAULT_ACCOUNT_CONF_PATH="$LE_WORKING_DIR/account.conf"
if [ -z "$ACCOUNT_CONF_PATH" ] ; then if [ -z "$ACCOUNT_CONF_PATH" ]; then
if [ -f "$_DEFAULT_ACCOUNT_CONF_PATH" ] ; then if [ -f "$_DEFAULT_ACCOUNT_CONF_PATH" ]; then
. "$_DEFAULT_ACCOUNT_CONF_PATH" . "$_DEFAULT_ACCOUNT_CONF_PATH"
fi fi
fi fi
if [ -z "$ACCOUNT_CONF_PATH" ] ; then if [ -z "$ACCOUNT_CONF_PATH" ]; then
ACCOUNT_CONF_PATH="$_DEFAULT_ACCOUNT_CONF_PATH" ACCOUNT_CONF_PATH="$_DEFAULT_ACCOUNT_CONF_PATH"
fi fi
DEFAULT_LOG_FILE="$LE_WORKING_DIR/$PROJECT_NAME.log" DEFAULT_LOG_FILE="$LE_WORKING_DIR/$PROJECT_NAME.log"
DEFAULT_CA_HOME="$LE_WORKING_DIR/ca" DEFAULT_CA_HOME="$LE_WORKING_DIR/ca"
if [ -z "$LE_TEMP_DIR" ]; then
LE_TEMP_DIR="$LE_WORKING_DIR/tmp"
fi
} }
#[domain] [keylength] #[domain] [keylength]
...@@ -1484,178 +1630,210 @@ _initpath() { ...@@ -1484,178 +1630,210 @@ _initpath() {
__initHome __initHome
if [ -f "$ACCOUNT_CONF_PATH" ] ; then if [ -f "$ACCOUNT_CONF_PATH" ]; then
. "$ACCOUNT_CONF_PATH" . "$ACCOUNT_CONF_PATH"
fi fi
if [ "$IN_CRON" ] ; then if [ "$IN_CRON" ]; then
if [ ! "$_USER_PATH_EXPORTED" ] ; then if [ ! "$_USER_PATH_EXPORTED" ]; then
_USER_PATH_EXPORTED=1 _USER_PATH_EXPORTED=1
export PATH="$USER_PATH:$PATH" export PATH="$USER_PATH:$PATH"
fi fi
fi fi
if [ -z "$CA_HOME" ] ; then if [ -z "$CA_HOME" ]; then
CA_HOME="$DEFAULT_CA_HOME" CA_HOME="$DEFAULT_CA_HOME"
fi fi
if [ -z "$API" ] ; then if [ -z "$API" ]; then
if [ -z "$STAGE" ] ; then if [ -z "$STAGE" ]; then
API="$DEFAULT_CA" API="$DEFAULT_CA"
else else
API="$STAGE_CA" API="$STAGE_CA"
_info "Using stage api:$API" _info "Using stage api:$API"
fi fi
fi fi
_API_HOST="$(echo "$API" | cut -d : -f 2 | tr -d '/')" _API_HOST="$(echo "$API" | cut -d : -f 2 | tr -d '/')"
CA_DIR="$CA_HOME/$_API_HOST" CA_DIR="$CA_HOME/$_API_HOST"
_DEFAULT_CA_CONF="$CA_DIR/ca.conf" _DEFAULT_CA_CONF="$CA_DIR/ca.conf"
if [ -z "$CA_CONF" ] ; then if [ -z "$CA_CONF" ]; then
CA_CONF="$_DEFAULT_CA_CONF" CA_CONF="$_DEFAULT_CA_CONF"
fi fi
if [ -f "$CA_CONF" ] ; then if [ -f "$CA_CONF" ]; then
. "$CA_CONF" . "$CA_CONF"
fi fi
if [ -z "$ACME_DIR" ] ; then if [ -z "$ACME_DIR" ]; then
ACME_DIR="/home/.acme" ACME_DIR="/home/.acme"
fi fi
if [ -z "$APACHE_CONF_BACKUP_DIR" ] ; then if [ -z "$APACHE_CONF_BACKUP_DIR" ]; then
APACHE_CONF_BACKUP_DIR="$LE_WORKING_DIR" APACHE_CONF_BACKUP_DIR="$LE_WORKING_DIR"
fi fi
if [ -z "$USER_AGENT" ] ; then if [ -z "$USER_AGENT" ]; then
USER_AGENT="$DEFAULT_USER_AGENT" USER_AGENT="$DEFAULT_USER_AGENT"
fi fi
if [ -z "$HTTP_HEADER" ] ; then if [ -z "$HTTP_HEADER" ]; then
HTTP_HEADER="$LE_WORKING_DIR/http.header" HTTP_HEADER="$LE_WORKING_DIR/http.header"
fi fi
_OLD_ACCOUNT_KEY="$LE_WORKING_DIR/account.key" _OLD_ACCOUNT_KEY="$LE_WORKING_DIR/account.key"
_OLD_ACCOUNT_JSON="$LE_WORKING_DIR/account.json" _OLD_ACCOUNT_JSON="$LE_WORKING_DIR/account.json"
_DEFAULT_ACCOUNT_KEY_PATH="$CA_DIR/account.key" _DEFAULT_ACCOUNT_KEY_PATH="$CA_DIR/account.key"
_DEFAULT_ACCOUNT_JSON_PATH="$CA_DIR/account.json" _DEFAULT_ACCOUNT_JSON_PATH="$CA_DIR/account.json"
if [ -z "$ACCOUNT_KEY_PATH" ] ; then if [ -z "$ACCOUNT_KEY_PATH" ]; then
ACCOUNT_KEY_PATH="$_DEFAULT_ACCOUNT_KEY_PATH" ACCOUNT_KEY_PATH="$_DEFAULT_ACCOUNT_KEY_PATH"
fi fi
if [ -z "$ACCOUNT_JSON_PATH" ] ; then if [ -z "$ACCOUNT_JSON_PATH" ]; then
ACCOUNT_JSON_PATH="$_DEFAULT_ACCOUNT_JSON_PATH" ACCOUNT_JSON_PATH="$_DEFAULT_ACCOUNT_JSON_PATH"
fi fi
_DEFAULT_CERT_HOME="$LE_WORKING_DIR" _DEFAULT_CERT_HOME="$LE_WORKING_DIR"
if [ -z "$CERT_HOME" ] ; then if [ -z "$CERT_HOME" ]; then
CERT_HOME="$_DEFAULT_CERT_HOME" CERT_HOME="$_DEFAULT_CERT_HOME"
fi fi
if [ -z "$1" ] ; then if [ -z "$1" ]; then
return 0 return 0
fi fi
mkdir -p "$CA_DIR" mkdir -p "$CA_DIR"
domain="$1" domain="$1"
_ilength="$2" _ilength="$2"
if [ -z "$DOMAIN_PATH" ] ; then if [ -z "$DOMAIN_PATH" ]; then
domainhome="$CERT_HOME/$domain" domainhome="$CERT_HOME/$domain"
domainhomeecc="$CERT_HOME/$domain$ECC_SUFFIX" domainhomeecc="$CERT_HOME/$domain$ECC_SUFFIX"
DOMAIN_PATH="$domainhome" DOMAIN_PATH="$domainhome"
if _isEccKey "$_ilength" ; then if _isEccKey "$_ilength"; then
DOMAIN_PATH="$domainhomeecc" DOMAIN_PATH="$domainhomeecc"
else else
if [ ! -d "$domainhome" ] && [ -d "$domainhomeecc" ] ; then if [ ! -d "$domainhome" ] && [ -d "$domainhomeecc" ]; then
_info "The domain '$domain' seems to have a ECC cert already, please add '$(__red "--ecc")' parameter if you want to use that cert." _info "The domain '$domain' seems to have a ECC cert already, please add '$(__red "--ecc")' parameter if you want to use that cert."
fi fi
fi fi
_debug DOMAIN_PATH "$DOMAIN_PATH" _debug DOMAIN_PATH "$DOMAIN_PATH"
fi fi
if [ ! -d "$DOMAIN_PATH" ] ; then if [ ! -d "$DOMAIN_PATH" ]; then
if ! mkdir -p "$DOMAIN_PATH" ; then if ! mkdir -p "$DOMAIN_PATH"; then
_err "Can not create domain path: $DOMAIN_PATH" _err "Can not create domain path: $DOMAIN_PATH"
return 1 return 1
fi fi
fi 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
if [ -z "$DOMAIN_SSL_CONF" ] ; then if [ -z "$DOMAIN_SSL_CONF" ]; then
DOMAIN_SSL_CONF="$DOMAIN_PATH/$domain.csr.conf" DOMAIN_SSL_CONF="$DOMAIN_PATH/$domain.csr.conf"
fi fi
if [ -z "$CSR_PATH" ] ; then if [ -z "$CSR_PATH" ]; then
CSR_PATH="$DOMAIN_PATH/$domain.csr" CSR_PATH="$DOMAIN_PATH/$domain.csr"
fi fi
if [ -z "$CERT_KEY_PATH" ] ; then if [ -z "$CERT_KEY_PATH" ]; then
CERT_KEY_PATH="$DOMAIN_PATH/$domain.key" CERT_KEY_PATH="$DOMAIN_PATH/$domain.key"
fi fi
if [ -z "$CERT_PATH" ] ; then if [ -z "$CERT_PATH" ]; then
CERT_PATH="$DOMAIN_PATH/$domain.cer" CERT_PATH="$DOMAIN_PATH/$domain.cer"
fi fi
if [ -z "$CA_CERT_PATH" ] ; then if [ -z "$CA_CERT_PATH" ]; then
CA_CERT_PATH="$DOMAIN_PATH/ca.cer" CA_CERT_PATH="$DOMAIN_PATH/ca.cer"
fi fi
if [ -z "$CERT_FULLCHAIN_PATH" ] ; then if [ -z "$CERT_FULLCHAIN_PATH" ]; then
CERT_FULLCHAIN_PATH="$DOMAIN_PATH/fullchain.cer" CERT_FULLCHAIN_PATH="$DOMAIN_PATH/fullchain.cer"
fi fi
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 "$TLS_CONF" ] ; then if [ -z "$TLS_CONF" ]; then
TLS_CONF="$DOMAIN_PATH/tls.valdation.conf" TLS_CONF="$DOMAIN_PATH/tls.valdation.conf"
fi fi
if [ -z "$TLS_CERT" ] ; then if [ -z "$TLS_CERT" ]; then
TLS_CERT="$DOMAIN_PATH/tls.valdation.cert" TLS_CERT="$DOMAIN_PATH/tls.valdation.cert"
fi fi
if [ -z "$TLS_KEY" ] ; then if [ -z "$TLS_KEY" ]; then
TLS_KEY="$DOMAIN_PATH/tls.valdation.key" TLS_KEY="$DOMAIN_PATH/tls.valdation.key"
fi fi
if [ -z "$TLS_CSR" ] ; then if [ -z "$TLS_CSR" ]; then
TLS_CSR="$DOMAIN_PATH/tls.valdation.csr" TLS_CSR="$DOMAIN_PATH/tls.valdation.csr"
fi fi
} }
_exec() {
if [ -z "$_EXEC_TEMP_ERR" ]; then
_EXEC_TEMP_ERR="$(_mktemp)"
fi
if [ "$_EXEC_TEMP_ERR" ]; then
"$@" 2>"$_EXEC_TEMP_ERR"
else
"$@"
fi
}
_exec_err() {
[ "$_EXEC_TEMP_ERR" ] && _err "$(cat "$_EXEC_TEMP_ERR")"
}
_apachePath() { _apachePath() {
_APACHECTL="apachectl" _APACHECTL="apachectl"
if ! _exists apachectl ; then if ! _exists apachectl; then
if _exists apache2ctl ; then if _exists apache2ctl; then
_APACHECTL="apache2ctl" _APACHECTL="apache2ctl"
else else
_err "'apachectl not found. It seems that apache is not installed, or you are not root user.'" _err "'apachectl not found. It seems that apache is not installed, or you are not root user.'"
_err "Please use webroot mode to try again." _err "Please use webroot mode to try again."
return 1 return 1
fi fi
fi fi
httpdconfname="$($_APACHECTL -V | grep SERVER_CONFIG_FILE= | cut -d = -f 2 | tr -d '"' )"
_debug httpdconfname "$httpdconfname" if ! _exec $_APACHECTL -V >/dev/null; then
if _startswith "$httpdconfname" '/' ; then _exec_err
httpdconf="$httpdconfname" return 1
httpdconfname="$(basename $httpdconfname)" fi
if [ "$APACHE_HTTPD_CONF" ]; then
_saveaccountconf APACHE_HTTPD_CONF "$APACHE_HTTPD_CONF"
httpdconf="$APACHE_HTTPD_CONF"
httpdconfname="$(basename "$httpdconfname")"
else else
httpdroot="$($_APACHECTL -V | grep HTTPD_ROOT= | cut -d = -f 2 | tr -d '"' )" httpdconfname="$($_APACHECTL -V | grep SERVER_CONFIG_FILE= | cut -d = -f 2 | tr -d '"')"
_debug httpdroot "$httpdroot" _debug httpdconfname "$httpdconfname"
httpdconf="$httpdroot/$httpdconfname"
httpdconfname="$(basename $httpdconfname)" if [ -z "$httpdconfname" ]; then
_err "Can not read apache config file."
return 1
fi
if _startswith "$httpdconfname" '/'; then
httpdconf="$httpdconfname"
httpdconfname="$(basename "$httpdconfname")"
else
httpdroot="$($_APACHECTL -V | grep HTTPD_ROOT= | cut -d = -f 2 | tr -d '"')"
_debug httpdroot "$httpdroot"
httpdconf="$httpdroot/$httpdconfname"
httpdconfname="$(basename "$httpdconfname")"
fi
fi fi
_debug httpdconf "$httpdconf" _debug httpdconf "$httpdconf"
_debug httpdconfname "$httpdconfname" _debug httpdconfname "$httpdconfname"
if [ ! -f "$httpdconf" ] ; then if [ ! -f "$httpdconf" ]; then
_err "Apache Config file not found" "$httpdconf" _err "Apache Config file not found" "$httpdconf"
return 1 return 1
fi fi
...@@ -1663,51 +1841,52 @@ _apachePath() { ...@@ -1663,51 +1841,52 @@ _apachePath() {
} }
_restoreApache() { _restoreApache() {
if [ -z "$usingApache" ] ; then if [ -z "$usingApache" ]; then
return 0 return 0
fi fi
_initpath _initpath
if ! _apachePath ; then if ! _apachePath; then
return 1 return 1
fi fi
if [ ! -f "$APACHE_CONF_BACKUP_DIR/$httpdconfname" ] ; then if [ ! -f "$APACHE_CONF_BACKUP_DIR/$httpdconfname" ]; then
_debug "No config file to restore." _debug "No config file to restore."
return 0 return 0
fi fi
cat "$APACHE_CONF_BACKUP_DIR/$httpdconfname" > "$httpdconf" cat "$APACHE_CONF_BACKUP_DIR/$httpdconfname" >"$httpdconf"
_debug "Restored: $httpdconf." _debug "Restored: $httpdconf."
if ! $_APACHECTL -t >/dev/null 2>&1 ; then if ! _exec $_APACHECTL -t; then
_exec_err
_err "Sorry, restore apache config error, please contact me." _err "Sorry, restore apache config error, please contact me."
return 1; return 1
fi fi
_debug "Restored successfully." _debug "Restored successfully."
rm -f "$APACHE_CONF_BACKUP_DIR/$httpdconfname" rm -f "$APACHE_CONF_BACKUP_DIR/$httpdconfname"
return 0 return 0
} }
_setApache() { _setApache() {
_initpath _initpath
if ! _apachePath ; then if ! _apachePath; then
return 1 return 1
fi fi
#test the conf first #test the conf first
_info "Checking if there is an error in the apache config file before starting." _info "Checking if there is an error in the apache config file before starting."
_msg="$($_APACHECTL -t 2>&1 )"
if [ "$?" != "0" ] ; then if ! _exec "$_APACHECTL" -t >/dev/null; then
_err "Sorry, apache config file has error, please fix it first, then try again." _exec_err
_err "The apache config file has error, please fix it first, then try again."
_err "Don't worry, there is nothing changed to your system." _err "Don't worry, there is nothing changed to your system."
_err "$_msg" return 1
return 1;
else else
_info "OK" _info "OK"
fi fi
#backup the conf #backup the conf
_debug "Backup apache config file" "$httpdconf" _debug "Backup apache config file" "$httpdconf"
if ! cp "$httpdconf" "$APACHE_CONF_BACKUP_DIR/" ; then if ! cp "$httpdconf" "$APACHE_CONF_BACKUP_DIR/"; then
_err "Can not backup apache config file, so abort. Don't worry, the apache config is not changed." _err "Can not backup apache config file, so abort. Don't worry, the apache config is not changed."
_err "This might be a bug of $PROJECT_NAME , pleae report issue: $PROJECT" _err "This might be a bug of $PROJECT_NAME , pleae report issue: $PROJECT"
return 1 return 1
...@@ -1715,22 +1894,22 @@ _setApache() { ...@@ -1715,22 +1894,22 @@ _setApache() {
_info "JFYI, Config file $httpdconf is backuped to $APACHE_CONF_BACKUP_DIR/$httpdconfname" _info "JFYI, Config file $httpdconf is backuped to $APACHE_CONF_BACKUP_DIR/$httpdconfname"
_info "In case there is an error that can not be restored automatically, you may try restore it yourself." _info "In case there is an error that can not be restored automatically, you may try restore it yourself."
_info "The backup file will be deleted on sucess, just forget it." _info "The backup file will be deleted on sucess, just forget it."
#add alias #add alias
apacheVer="$($_APACHECTL -V | grep "Server version:" | cut -d : -f 2 | cut -d " " -f 2 | cut -d '/' -f 2 )" apacheVer="$($_APACHECTL -V | grep "Server version:" | cut -d : -f 2 | cut -d " " -f 2 | cut -d '/' -f 2)"
_debug "apacheVer" "$apacheVer" _debug "apacheVer" "$apacheVer"
apacheMajer="$(echo "$apacheVer" | cut -d . -f 1)" apacheMajer="$(echo "$apacheVer" | cut -d . -f 1)"
apacheMinor="$(echo "$apacheVer" | cut -d . -f 2)" apacheMinor="$(echo "$apacheVer" | cut -d . -f 2)"
if [ "$apacheVer" ] && [ "$apacheMajer$apacheMinor" -ge "24" ] ; then if [ "$apacheVer" ] && [ "$apacheMajer$apacheMinor" -ge "24" ]; then
echo " echo "
Alias /.well-known/acme-challenge $ACME_DIR Alias /.well-known/acme-challenge $ACME_DIR
<Directory $ACME_DIR > <Directory $ACME_DIR >
Require all granted Require all granted
</Directory> </Directory>
" >> "$httpdconf" " >>"$httpdconf"
else else
echo " echo "
Alias /.well-known/acme-challenge $ACME_DIR Alias /.well-known/acme-challenge $ACME_DIR
...@@ -1739,40 +1918,41 @@ Alias /.well-known/acme-challenge $ACME_DIR ...@@ -1739,40 +1918,41 @@ Alias /.well-known/acme-challenge $ACME_DIR
Order allow,deny Order allow,deny
Allow from all Allow from all
</Directory> </Directory>
" >> "$httpdconf" " >>"$httpdconf"
fi fi
_msg="$($_APACHECTL -t 2>&1 )" _msg="$($_APACHECTL -t 2>&1)"
if [ "$?" != "0" ] ; then if [ "$?" != "0" ]; then
_err "Sorry, apache config error" _err "Sorry, apache config error"
if _restoreApache ; then if _restoreApache; then
_err "The apache config file is restored." _err "The apache config file is restored."
else else
_err "Sorry, The apache config file can not be restored, please report bug." _err "Sorry, The apache config file can not be restored, please report bug."
fi fi
return 1; return 1
fi fi
if [ ! -d "$ACME_DIR" ] ; then if [ ! -d "$ACME_DIR" ]; then
mkdir -p "$ACME_DIR" mkdir -p "$ACME_DIR"
chmod 755 "$ACME_DIR" chmod 755 "$ACME_DIR"
fi fi
if ! $_APACHECTL graceful ; then if ! _exec "$_APACHECTL" graceful; then
_err "Sorry, $_APACHECTL graceful error, please contact me." _exec_err
_err "$_APACHECTL graceful error, please contact me."
_restoreApache _restoreApache
return 1; return 1
fi fi
usingApache="1" usingApache="1"
return 0 return 0
} }
_clearup() { _clearup() {
_stopserver $serverproc _stopserver "$serverproc"
serverproc="" serverproc=""
_restoreApache _restoreApache
_clearupdns _clearupdns
if [ -z "$DEBUG" ] ; then if [ -z "$DEBUG" ]; then
rm -f "$TLS_CONF" rm -f "$TLS_CONF"
rm -f "$TLS_CERT" rm -f "$TLS_CERT"
rm -f "$TLS_KEY" rm -f "$TLS_KEY"
...@@ -1782,157 +1962,152 @@ _clearup() { ...@@ -1782,157 +1962,152 @@ _clearup() {
_clearupdns() { _clearupdns() {
_debug "_clearupdns" _debug "_clearupdns"
if [ "$dnsadded" != 1 ] || [ -z "$vlist" ] ; then if [ "$dnsadded" != 1 ] || [ -z "$vlist" ]; then
_info "Dns not added, skip." _debug "Dns not added, skip."
return return
fi fi
ventries=$(echo "$vlist" | tr ',' ' ' ) ventries=$(echo "$vlist" | tr ',' ' ')
for ventry in $ventries for ventry in $ventries; do
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) vtype=$(echo "$ventry" | cut -d "$sep" -f 4)
vtype=$(echo $ventry | cut -d $sep -f 4) _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." _info "$d is already verified, skip $vtype."
continue continue
fi fi
if [ "$vtype" != "$VTYPE_DNS" ] ; then if [ "$vtype" != "$VTYPE_DNS" ]; then
_info "Skip $d for $vtype" _info "Skip $d for $vtype"
continue continue
fi fi
d_api="$(_findHook $d dnsapi $_currentRoot)" d_api="$(_findHook "$d" dnsapi "$_currentRoot")"
_debug d_api "$d_api" _debug d_api "$d_api"
if [ -z "$d_api" ] ; then if [ -z "$d_api" ]; then
_info "Not Found domain api file: $d_api" _info "Not Found domain api file: $d_api"
continue continue
fi fi
( (
if ! . $d_api ; then if ! . "$d_api"; then
_err "Load file $d_api error. Please check your api file and try again." _err "Load file $d_api error. Please check your api file and try again."
return 1 return 1
fi fi
rmcommand="${_currentRoot}_rm" rmcommand="${_currentRoot}_rm"
if ! _exists $rmcommand ; then if ! _exists "$rmcommand"; then
_err "It seems that your api file doesn't define $rmcommand" _err "It seems that your api file doesn't define $rmcommand"
return 1 return 1
fi fi
txtdomain="_acme-challenge.$d" txtdomain="_acme-challenge.$d"
if ! $rmcommand $txtdomain ; then if ! $rmcommand "$txtdomain"; then
_err "Error removing txt for domain:$txtdomain" _err "Error removing txt for domain:$txtdomain"
return 1 return 1
fi fi
) )
done done
} }
# webroot removelevel tokenfile # webroot removelevel tokenfile
_clearupwebbroot() { _clearupwebbroot() {
__webroot="$1" __webroot="$1"
if [ -z "$__webroot" ] ; then if [ -z "$__webroot" ]; then
_debug "no webroot specified, skip" _debug "no webroot specified, skip"
return 0 return 0
fi fi
_rmpath="" _rmpath=""
if [ "$2" = '1' ] ; then if [ "$2" = '1' ]; then
_rmpath="$__webroot/.well-known" _rmpath="$__webroot/.well-known"
elif [ "$2" = '2' ] ; then elif [ "$2" = '2' ]; then
_rmpath="$__webroot/.well-known/acme-challenge" _rmpath="$__webroot/.well-known/acme-challenge"
elif [ "$2" = '3' ] ; then elif [ "$2" = '3' ]; then
_rmpath="$__webroot/.well-known/acme-challenge/$3" _rmpath="$__webroot/.well-known/acme-challenge/$3"
else else
_debug "Skip for removelevel:$2" _debug "Skip for removelevel:$2"
fi fi
if [ "$_rmpath" ] ; then if [ "$_rmpath" ]; then
if [ "$DEBUG" ] ; then if [ "$DEBUG" ]; then
_debug "Debugging, skip removing: $_rmpath" _debug "Debugging, skip removing: $_rmpath"
else else
rm -rf "$_rmpath" rm -rf "$_rmpath"
fi fi
fi fi
return 0 return 0
} }
_on_before_issue() { _on_before_issue() {
_debug _on_before_issue _debug _on_before_issue
if _hasfield "$Le_Webroot" "$NO_VALUE" ; then if _hasfield "$Le_Webroot" "$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
elif ! _hasfield "$Le_Webroot" "$W_TLS" ; then
#no need to check anymore
return 0
fi fi
_debug Le_LocalAddress "$Le_LocalAddress" _debug Le_LocalAddress "$Le_LocalAddress"
alldomains=$(echo "$Le_Domain,$Le_Alt" | tr ',' ' ' ) alldomains=$(echo "$Le_Domain,$Le_Alt" | tr ',' ' ')
_index=1 _index=1
_currentRoot="" _currentRoot=""
_addrIndex=1 _addrIndex=1
for d in $alldomains for d in $alldomains; do
do _debug "Check for domain" "$d"
_debug "Check for domain" $d
_currentRoot="$(_getfield "$Le_Webroot" $_index)" _currentRoot="$(_getfield "$Le_Webroot" $_index)"
_debug "_currentRoot" "$_currentRoot" _debug "_currentRoot" "$_currentRoot"
_index=$(_math $_index + 1) _index=$(_math $_index + 1)
_checkport="" _checkport=""
if [ "$_currentRoot" = "$NO_VALUE" ] ; then if [ "$_currentRoot" = "$NO_VALUE" ]; then
_info "Standalone mode." _info "Standalone mode."
if [ -z "$Le_HTTPPort" ] ; then if [ -z "$Le_HTTPPort" ]; then
Le_HTTPPort=80 Le_HTTPPort=80
else else
_savedomainconf "Le_HTTPPort" "$Le_HTTPPort" _savedomainconf "Le_HTTPPort" "$Le_HTTPPort"
fi fi
_checkport="$Le_HTTPPort" _checkport="$Le_HTTPPort"
elif [ "$_currentRoot" = "$W_TLS" ] ; then elif [ "$_currentRoot" = "$W_TLS" ]; then
_info "Standalone tls mode." _info "Standalone tls mode."
if [ -z "$Le_TLSPort" ] ; then if [ -z "$Le_TLSPort" ]; then
Le_TLSPort=443 Le_TLSPort=443
else else
_savedomainconf "Le_TLSPort" "$Le_TLSPort" _savedomainconf "Le_TLSPort" "$Le_TLSPort"
fi fi
_checkport="$Le_TLSPort" _checkport="$Le_TLSPort"
fi fi
if [ "$_checkport" ] ; then if [ "$_checkport" ]; then
_debug _checkport "$_checkport" _debug _checkport "$_checkport"
_checkaddr="$(_getfield "$Le_LocalAddress" $_addrIndex)" _checkaddr="$(_getfield "$Le_LocalAddress" $_addrIndex)"
_debug _checkaddr "$_checkaddr" _debug _checkaddr "$_checkaddr"
_addrIndex="$(_math $_addrIndex + 1)" _addrIndex="$(_math $_addrIndex + 1)"
_netprc="$(_ss "$_checkport" | grep "$_checkport")" _netprc="$(_ss "$_checkport" | grep "$_checkport")"
netprc="$(echo "$_netprc" | grep "$_checkaddr")" netprc="$(echo "$_netprc" | grep "$_checkaddr")"
if [ -z "$netprc" ] ; then if [ -z "$netprc" ]; then
netprc="$(echo "$_netprc" | grep "$LOCAL_ANY_ADDRESS")" netprc="$(echo "$_netprc" | grep "$LOCAL_ANY_ADDRESS")"
fi fi
if [ "$netprc" ] ; then if [ "$netprc" ]; then
_err "$netprc" _err "$netprc"
_err "tcp port $_checkport is already used by $(echo "$netprc" | cut -d : -f 4)" _err "tcp port $_checkport is already used by $(echo "$netprc" | cut -d : -f 4)"
_err "Please stop it first" _err "Please stop it first"
return 1 return 1
fi fi
fi fi
done done
if _hasfield "$Le_Webroot" "apache" ; then if _hasfield "$Le_Webroot" "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
fi fi
...@@ -1941,11 +2116,11 @@ _on_before_issue() { ...@@ -1941,11 +2116,11 @@ _on_before_issue() {
fi fi
#run pre hook #run pre hook
if [ "$Le_PreHook" ] ; then if [ "$Le_PreHook" ]; then
_info "Run pre hook:'$Le_PreHook'" _info "Run pre hook:'$Le_PreHook'"
if ! ( if ! (
cd "$DOMAIN_PATH" && eval "$Le_PreHook" cd "$DOMAIN_PATH" && eval "$Le_PreHook"
) ; then ); then
_err "Error when run pre hook." _err "Error when run pre hook."
return 1 return 1
fi fi
...@@ -1954,19 +2129,23 @@ _on_before_issue() { ...@@ -1954,19 +2129,23 @@ _on_before_issue() {
_on_issue_err() { _on_issue_err() {
_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"
else else
_err "Please use add '--debug' or '--log' to check more details." _err "Please use add '--debug' or '--log' to check more details."
_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 [ "$Le_PostHook" ]; then
_info "Run post hook:'$Le_PostHook'" _info "Run post hook:'$Le_PostHook'"
if ! ( if ! (
cd "$DOMAIN_PATH" && eval "$Le_PostHook" cd "$DOMAIN_PATH" && eval "$Le_PostHook"
) ; then ); then
_err "Error when run post hook." _err "Error when run post hook."
return 1 return 1
fi fi
...@@ -1976,27 +2155,27 @@ _on_issue_err() { ...@@ -1976,27 +2155,27 @@ _on_issue_err() {
_on_issue_success() { _on_issue_success() {
_debug _on_issue_success _debug _on_issue_success
#run the post hook #run the post hook
if [ "$Le_PostHook" ] ; then if [ "$Le_PostHook" ]; then
_info "Run post hook:'$Le_PostHook'" _info "Run post hook:'$Le_PostHook'"
if ! ( if ! (
cd "$DOMAIN_PATH" && eval "$Le_PostHook" cd "$DOMAIN_PATH" && eval "$Le_PostHook"
) ; then ); then
_err "Error when run post hook." _err "Error when run post hook."
return 1 return 1
fi fi
fi fi
#run renew hook #run renew hook
if [ "$IS_RENEW" ] && [ "$Le_RenewHook" ] ; then if [ "$IS_RENEW" ] && [ "$Le_RenewHook" ]; then
_info "Run renew hook:'$Le_RenewHook'" _info "Run renew hook:'$Le_RenewHook'"
if ! ( if ! (
cd "$DOMAIN_PATH" && eval "$Le_RenewHook" cd "$DOMAIN_PATH" && eval "$Le_RenewHook"
) ; then ); then
_err "Error when run renew hook." _err "Error when run renew hook."
return 1 return 1
fi fi
fi fi
} }
updateaccount() { updateaccount() {
...@@ -2005,76 +2184,76 @@ updateaccount() { ...@@ -2005,76 +2184,76 @@ updateaccount() {
} }
registeraccount() { registeraccount() {
_reg_length="$1"
_initpath _initpath
_regAccount _regAccount "$_reg_length"
} }
__calcAccountKeyHash() {
[ -f "$ACCOUNT_KEY_PATH" ] && _digest sha256 <"$ACCOUNT_KEY_PATH"
}
#keylength
_regAccount() { _regAccount() {
_initpath _initpath
_reg_length="$1"
if [ ! -f "$ACCOUNT_KEY_PATH" ] && [ -f "$_OLD_ACCOUNT_KEY" ]; then if [ ! -f "$ACCOUNT_KEY_PATH" ] && [ -f "$_OLD_ACCOUNT_KEY" ]; then
_info "mv $_OLD_ACCOUNT_KEY to $ACCOUNT_KEY_PATH" _info "mv $_OLD_ACCOUNT_KEY to $ACCOUNT_KEY_PATH"
mv "$_OLD_ACCOUNT_KEY" "$ACCOUNT_KEY_PATH" mv "$_OLD_ACCOUNT_KEY" "$ACCOUNT_KEY_PATH"
fi fi
if [ ! -f "$ACCOUNT_JSON_PATH" ] && [ -f "$_OLD_ACCOUNT_JSON" ]; then if [ ! -f "$ACCOUNT_JSON_PATH" ] && [ -f "$_OLD_ACCOUNT_JSON" ]; then
_info "mv $_OLD_ACCOUNT_JSON to $ACCOUNT_JSON_PATH" _info "mv $_OLD_ACCOUNT_JSON to $ACCOUNT_JSON_PATH"
mv "$_OLD_ACCOUNT_JSON" "$ACCOUNT_JSON_PATH" mv "$_OLD_ACCOUNT_JSON" "$ACCOUNT_JSON_PATH"
fi fi
if [ ! -f "$ACCOUNT_KEY_PATH" ] ; then if [ ! -f "$ACCOUNT_KEY_PATH" ]; then
_acck="no" if ! _create_account_key "$_reg_length"; then
if [ "$Le_Keylength" ] ; then
_acck="$Le_Keylength"
fi
if ! createAccountKey "$_acck" ; then
_err "Create account key error." _err "Create account key error."
return 1 return 1
fi fi
fi fi
if ! _calcjwk "$ACCOUNT_KEY_PATH" ; then if ! _calcjwk "$ACCOUNT_KEY_PATH"; then
return 1 return 1
fi fi
_updateTos="" _updateTos=""
_reg_res="new-reg" _reg_res="new-reg"
while true ; while true; do
do
_debug AGREEMENT "$AGREEMENT" _debug AGREEMENT "$AGREEMENT"
accountkey_json=$(printf "%s" "$jwk" | tr -d ' ' )
thumbprint=$(printf "%s" "$accountkey_json" | _digest "sha256" | _urlencode)
regjson='{"resource": "'$_reg_res'", "agreement": "'$AGREEMENT'"}' regjson='{"resource": "'$_reg_res'", "agreement": "'$AGREEMENT'"}'
if [ "$ACCOUNT_EMAIL" ] ; then if [ "$ACCOUNT_EMAIL" ]; then
regjson='{"resource": "'$_reg_res'", "contact": ["mailto: '$ACCOUNT_EMAIL'"], "agreement": "'$AGREEMENT'"}' regjson='{"resource": "'$_reg_res'", "contact": ["mailto: '$ACCOUNT_EMAIL'"], "agreement": "'$AGREEMENT'"}'
fi fi
if [ -z "$_updateTos" ] ; then if [ -z "$_updateTos" ]; then
_info "Registering account" _info "Registering account"
if ! _send_signed_request "$API/acme/new-reg" "$regjson" ; then if ! _send_signed_request "$API/acme/new-reg" "$regjson"; then
_err "Register account Error: $response" _err "Register account Error: $response"
return 1 return 1
fi fi
if [ "$code" = "" ] || [ "$code" = '201' ] ; then if [ "$code" = "" ] || [ "$code" = '201' ]; then
echo "$response" > $ACCOUNT_JSON_PATH echo "$response" >"$ACCOUNT_JSON_PATH"
_info "Registered" _info "Registered"
elif [ "$code" = '409' ] ; then elif [ "$code" = '409' ]; then
_info "Already registered" _info "Already registered"
else else
_err "Register account Error: $response" _err "Register account Error: $response"
return 1 return 1
fi fi
_accUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ' ' -f 2| tr -d "\r\n")" _accUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ' ' -f 2 | tr -d "\r\n")"
_debug "_accUri" "$_accUri" _debug "_accUri" "$_accUri"
_tos="$(echo "$responseHeaders" | grep "^Link:.*rel=\"terms-of-service\"" | _head_n 1 | _egrep_o "<.*>" | tr -d '<>')" _tos="$(echo "$responseHeaders" | grep "^Link:.*rel=\"terms-of-service\"" | _head_n 1 | _egrep_o "<.*>" | tr -d '<>')"
_debug "_tos" "$_tos" _debug "_tos" "$_tos"
if [ -z "$_tos" ] ; then if [ -z "$_tos" ]; then
_debug "Use default tos: $DEFAULT_AGREEMENT" _debug "Use default tos: $DEFAULT_AGREEMENT"
_tos="$DEFAULT_AGREEMENT" _tos="$DEFAULT_AGREEMENT"
fi fi
...@@ -2084,15 +2263,19 @@ _regAccount() { ...@@ -2084,15 +2263,19 @@ _regAccount() {
_reg_res="reg" _reg_res="reg"
continue continue
fi fi
else else
_debug "Update tos: $_tos" _debug "Update tos: $_tos"
if ! _send_signed_request "$_accUri" "$regjson" ; then if ! _send_signed_request "$_accUri" "$regjson"; then
_err "Update tos error." _err "Update tos error."
return 1 return 1
fi fi
if [ "$code" = '202' ] ; then if [ "$code" = '202' ]; then
_info "Update success." _info "Update success."
CA_KEY_HASH="$(__calcAccountKeyHash)"
_debug "Calc CA_KEY_HASH" "$CA_KEY_HASH"
_savecaconf CA_KEY_HASH "$CA_KEY_HASH"
else else
_err "Update account error." _err "Update account error."
return 1 return 1
...@@ -2103,33 +2286,69 @@ _regAccount() { ...@@ -2103,33 +2286,69 @@ _regAccount() {
} }
# domain folder file # domain folder file
_findHook() { _findHook() {
_hookdomain="$1" _hookdomain="$1"
_hookcat="$2" _hookcat="$2"
_hookname="$3" _hookname="$3"
if [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname" ] ; then if [ -f "$_SCRIPT_HOME/$_hookcat/$_hookname" ]; then
d_api="$_SCRIPT_HOME/$_hookcat/$_hookname"
elif [ -f "$_SCRIPT_HOME/$_hookcat/$_hookname.sh" ]; then
d_api="$_SCRIPT_HOME/$_hookcat/$_hookname.sh"
elif [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname" ]; then
d_api="$LE_WORKING_DIR/$_hookdomain/$_hookname" d_api="$LE_WORKING_DIR/$_hookdomain/$_hookname"
elif [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname.sh" ] ; then elif [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname.sh" ]; then
d_api="$LE_WORKING_DIR/$_hookdomain/$_hookname.sh" d_api="$LE_WORKING_DIR/$_hookdomain/$_hookname.sh"
elif [ -f "$LE_WORKING_DIR/$_hookname" ] ; then elif [ -f "$LE_WORKING_DIR/$_hookname" ]; then
d_api="$LE_WORKING_DIR/$_hookname" d_api="$LE_WORKING_DIR/$_hookname"
elif [ -f "$LE_WORKING_DIR/$_hookname.sh" ] ; then elif [ -f "$LE_WORKING_DIR/$_hookname.sh" ]; then
d_api="$LE_WORKING_DIR/$_hookname.sh" d_api="$LE_WORKING_DIR/$_hookname.sh"
elif [ -f "$LE_WORKING_DIR/$_hookcat/$_hookname" ] ; then elif [ -f "$LE_WORKING_DIR/$_hookcat/$_hookname" ]; then
d_api="$LE_WORKING_DIR/$_hookcat/$_hookname" d_api="$LE_WORKING_DIR/$_hookcat/$_hookname"
elif [ -f "$LE_WORKING_DIR/$_hookcat/$_hookname.sh" ] ; then elif [ -f "$LE_WORKING_DIR/$_hookcat/$_hookname.sh" ]; then
d_api="$LE_WORKING_DIR/$_hookcat/$_hookname.sh" d_api="$LE_WORKING_DIR/$_hookcat/$_hookname.sh"
fi fi
printf "%s" "$d_api" printf "%s" "$d_api"
} }
#domain
__get_domain_new_authz() {
_gdnd="$1"
_info "Getting new-authz for domain" "$_gdnd"
_Max_new_authz_retry_times=5
_authz_i=0
while [ "$_authz_i" -lt "$_Max_new_authz_retry_times" ]; do
_debug "Try new-authz for the $_authz_i time."
if ! _send_signed_request "$API/acme/new-authz" "{\"resource\": \"new-authz\", \"identifier\": {\"type\": \"dns\", \"value\": \"$(_idn "$_gdnd")\"}}"; then
_err "Can not get domain new authz."
return 1
fi
if ! _contains "$response" "An error occurred while processing your request"; then
_info "The new-authz request is ok."
break
fi
_authz_i="$(_math "$_authz_i" + 1)"
_info "The server is busy, Sleep $_authz_i to retry."
_sleep "$_authz_i"
done
if [ "$_authz_i" = "$_Max_new_authz_retry_times" ]; then
_err "new-authz retry reach the max $_Max_new_authz_retry_times times."
fi
if [ ! -z "$code" ] && [ ! "$code" = '201' ]; then
_err "new-authz error: $response"
return 1
fi
}
#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
...@@ -2146,36 +2365,36 @@ issue() { ...@@ -2146,36 +2365,36 @@ issue() {
Le_PostHook="${11}" Le_PostHook="${11}"
Le_RenewHook="${12}" Le_RenewHook="${12}"
Le_LocalAddress="${13}" Le_LocalAddress="${13}"
#remove these later. #remove these later.
if [ "$Le_Webroot" = "dns-cf" ] ; then if [ "$Le_Webroot" = "dns-cf" ]; then
Le_Webroot="dns_cf" Le_Webroot="dns_cf"
fi fi
if [ "$Le_Webroot" = "dns-dp" ] ; then if [ "$Le_Webroot" = "dns-dp" ]; then
Le_Webroot="dns_dp" Le_Webroot="dns_dp"
fi fi
if [ "$Le_Webroot" = "dns-cx" ] ; then if [ "$Le_Webroot" = "dns-cx" ]; then
Le_Webroot="dns_cx" Le_Webroot="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 "$Le_Domain" "$Le_Keylength"
mkdir -p "$DOMAIN_PATH" mkdir -p "$DOMAIN_PATH"
fi fi
if [ -f "$DOMAIN_CONF" ] ; then if [ -f "$DOMAIN_CONF" ]; then
Le_NextRenewTime=$(_readdomainconf Le_NextRenewTime) Le_NextRenewTime=$(_readdomainconf Le_NextRenewTime)
_debug Le_NextRenewTime "$Le_NextRenewTime" _debug Le_NextRenewTime "$Le_NextRenewTime"
if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ $(_time) -lt $Le_NextRenewTime ] ; then if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(_time)" -lt "$Le_NextRenewTime" ]; then
_saved_domain=$(_readdomainconf Le_Domain) _saved_domain=$(_readdomainconf Le_Domain)
_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" = "$Le_Domain,$Le_Alt" ]; 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."
return $RENEW_SKIP return $RENEW_SKIP
else else
_info "Domains have changed." _info "Domains have changed."
...@@ -2183,45 +2402,55 @@ issue() { ...@@ -2183,45 +2402,55 @@ issue() {
fi fi
fi fi
_savedomainconf "Le_Domain" "$Le_Domain" _savedomainconf "Le_Domain" "$Le_Domain"
_savedomainconf "Le_Alt" "$Le_Alt" _savedomainconf "Le_Alt" "$Le_Alt"
_savedomainconf "Le_Webroot" "$Le_Webroot" _savedomainconf "Le_Webroot" "$Le_Webroot"
_savedomainconf "Le_PreHook" "$Le_PreHook" _savedomainconf "Le_PreHook" "$Le_PreHook"
_savedomainconf "Le_PostHook" "$Le_PostHook" _savedomainconf "Le_PostHook" "$Le_PostHook"
_savedomainconf "Le_RenewHook" "$Le_RenewHook" _savedomainconf "Le_RenewHook" "$Le_RenewHook"
_savedomainconf "Le_LocalAddress" "$Le_LocalAddress"
if [ "$Le_LocalAddress" ]; then
_savedomainconf "Le_LocalAddress" "$Le_LocalAddress"
else
_cleardomainconf "Le_LocalAddress"
fi
Le_API="$API" Le_API="$API"
_savedomainconf "Le_API" "$Le_API" _savedomainconf "Le_API" "$Le_API"
if [ "$Le_Alt" = "$NO_VALUE" ] ; then if [ "$Le_Alt" = "$NO_VALUE" ]; then
Le_Alt="" Le_Alt=""
fi fi
if [ "$Le_Keylength" = "$NO_VALUE" ] ; then if [ "$Le_Keylength" = "$NO_VALUE" ]; then
Le_Keylength="" Le_Keylength=""
fi fi
if ! _on_before_issue ; then if ! _on_before_issue; then
_err "_on_before_issue." _err "_on_before_issue."
return 1 return 1
fi fi
if ! _regAccount ; then _saved_account_key_hash="$(_readcaconf "CA_KEY_HASH")"
_on_issue_err _debug2 _saved_account_key_hash "$_saved_account_key_hash"
return 1
if [ -z "$_saved_account_key_hash" ] || [ "$_saved_account_key_hash" != "$(__calcAccountKeyHash)" ]; then
if ! _regAccount "$_accountkeylength"; then
_on_issue_err
return 1
fi
else
_debug "_saved_account_key_hash is not changed, skip register account."
fi fi
if [ -f "$CSR_PATH" ] && [ ! -f "$CERT_KEY_PATH" ] ; then if [ -f "$CSR_PATH" ] && [ ! -f "$CERT_KEY_PATH" ]; then
_info "Signing from existing CSR." _info "Signing from existing CSR."
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" ] || [ "$Le_Keylength" != "$_key" ]; then
if ! createDomainKey $Le_Domain $Le_Keylength ; then if ! createDomainKey "$Le_Domain" "$Le_Keylength"; then
_err "Create domain key error." _err "Create domain key error."
_clearup _clearup
_on_issue_err _on_issue_err
...@@ -2229,7 +2458,7 @@ issue() { ...@@ -2229,7 +2458,7 @@ issue() {
fi fi
fi fi
if ! _createcsr "$Le_Domain" "$Le_Alt" "$CERT_KEY_PATH" "$CSR_PATH" "$DOMAIN_SSL_CONF" ; then if ! _createcsr "$Le_Domain" "$Le_Alt" "$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
...@@ -2237,140 +2466,131 @@ issue() { ...@@ -2237,140 +2466,131 @@ issue() {
fi fi
fi fi
_savedomainconf "Le_Keylength" "$Le_Keylength" _savedomainconf "Le_Keylength" "$Le_Keylength"
vlist="$Le_Vlist" vlist="$Le_Vlist"
# verify each domain
_info "Verify each domain" _info "Getting domain auth token for each domain"
sep='#' sep='#'
if [ -z "$vlist" ] ; then if [ -z "$vlist" ]; then
alldomains=$(echo "$Le_Domain,$Le_Alt" | tr ',' ' ' ) alldomains=$(echo "$Le_Domain,$Le_Alt" | tr ',' ' ')
_index=1 _index=1
_currentRoot="" _currentRoot=""
for d in $alldomains for d in $alldomains; do
do _info "Getting webroot for domain" "$d"
_info "Getting webroot for domain" $d
_w="$(echo $Le_Webroot | cut -d , -f $_index)" _w="$(echo $Le_Webroot | cut -d , -f $_index)"
_info _w "$_w" _info _w "$_w"
if [ "$_w" ] ; then if [ "$_w" ]; then
_currentRoot="$_w" _currentRoot="$_w"
fi fi
_debug "_currentRoot" "$_currentRoot" _debug "_currentRoot" "$_currentRoot"
_index=$(_math $_index + 1) _index=$(_math $_index + 1)
vtype="$VTYPE_HTTP" vtype="$VTYPE_HTTP"
if _startswith "$_currentRoot" "dns" ; then if _startswith "$_currentRoot" "dns"; then
vtype="$VTYPE_DNS" vtype="$VTYPE_DNS"
fi fi
if [ "$_currentRoot" = "$W_TLS" ] ; then if [ "$_currentRoot" = "$W_TLS" ]; then
vtype="$VTYPE_TLS" vtype="$VTYPE_TLS"
fi fi
_info "Getting new-authz for domain" $d
if ! _send_signed_request "$API/acme/new-authz" "{\"resource\": \"new-authz\", \"identifier\": {\"type\": \"dns\", \"value\": \"$(_idn "$d")\"}}" ; then if ! __get_domain_new_authz "$d"; then
_err "Can not get domain token."
_clearup _clearup
_on_issue_err _on_issue_err
return 1 return 1
fi fi
if [ ! -z "$code" ] && [ ! "$code" = '201' ] ; then if [ -z "$thumbprint" ]; then
_err "new-authz error: $response" accountkey_json=$(printf "%s" "$jwk" | tr -d ' ')
_clearup thumbprint=$(printf "%s" "$accountkey_json" | _digest "sha256" | _urlencode)
_on_issue_err
return 1
fi fi
entry="$(printf "%s\n" "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')" entry="$(printf "%s\n" "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"
_debug entry "$entry" _debug entry "$entry"
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
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 '"')"
_debug token $token _debug token "$token"
uri="$(printf "%s\n" "$entry" | _egrep_o '"uri":"[^"]*'| cut -d : -f 2,3 | tr -d '"' )" uri="$(printf "%s\n" "$entry" | _egrep_o '"uri":"[^"]*' | cut -d : -f 2,3 | tr -d '"')"
_debug uri $uri _debug uri "$uri"
keyauthorization="$token.$thumbprint" keyauthorization="$token.$thumbprint"
_debug keyauthorization "$keyauthorization" _debug keyauthorization "$keyauthorization"
if printf "%s" "$response" | grep '"status":"valid"' >/dev/null 2>&1; then
if printf "$response" | grep '"status":"valid"' >/dev/null 2>&1 ; then
_info "$d is already verified, skip." _info "$d is already verified, skip."
keyauthorization=$STATE_VERIFIED keyauthorization="$STATE_VERIFIED"
_debug keyauthorization "$keyauthorization" _debug keyauthorization "$keyauthorization"
fi fi
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,"
done done
#add entry #add entry
dnsadded="" dnsadded=""
ventries=$(echo "$vlist" | tr ',' ' ' ) ventries=$(echo "$vlist" | tr ',' ' ')
for ventry in $ventries for ventry in $ventries; do
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) vtype=$(echo "$ventry" | cut -d "$sep" -f 4)
vtype=$(echo $ventry | cut -d $sep -f 4) _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." _info "$d is already verified, skip $vtype."
continue continue
fi fi
if [ "$vtype" = "$VTYPE_DNS" ] ; then if [ "$vtype" = "$VTYPE_DNS" ]; then
dnsadded='0' dnsadded='0'
txtdomain="_acme-challenge.$d" txtdomain="_acme-challenge.$d"
_debug txtdomain "$txtdomain" _debug txtdomain "$txtdomain"
txt="$(printf "%s" "$keyauthorization" | _digest "sha256" | _urlencode)" txt="$(printf "%s" "$keyauthorization" | _digest "sha256" | _urlencode)"
_debug txt "$txt" _debug txt "$txt"
d_api="$(_findHook $d dnsapi $_currentRoot)" d_api="$(_findHook "$d" dnsapi "$_currentRoot")"
_debug d_api "$d_api" _debug d_api "$d_api"
if [ "$d_api" ] ; then if [ "$d_api" ]; then
_info "Found domain api file: $d_api" _info "Found domain api file: $d_api"
else else
_err "Add the following TXT record:" _err "Add the following TXT record:"
_err "Domain: '$(__green $txtdomain)'" _err "Domain: '$(__green "$txtdomain")'"
_err "TXT value: '$(__green $txt)'" _err "TXT value: '$(__green "$txt")'"
_err "Please be aware that you prepend _acme-challenge. before your domain" _err "Please be aware that you prepend _acme-challenge. before your domain"
_err "so the resulting subdomain will be: $txtdomain" _err "so the resulting subdomain will be: $txtdomain"
continue continue
fi fi
( (
if ! . $d_api ; then if ! . "$d_api"; then
_err "Load file $d_api error. Please check your api file and try again." _err "Load file $d_api error. Please check your api file and try again."
return 1 return 1
fi fi
addcommand="${_currentRoot}_add" addcommand="${_currentRoot}_add"
if ! _exists $addcommand ; then if ! _exists "$addcommand"; then
_err "It seems that your api file is not correct, it must have a function named: $addcommand" _err "It seems that your api file is not correct, it must have a function named: $addcommand"
return 1 return 1
fi fi
if ! $addcommand $txtdomain $txt ; then if ! $addcommand "$txtdomain" "$txt"; then
_err "Error add txt for domain:$txtdomain" _err "Error add txt for domain:$txtdomain"
return 1 return 1
fi fi
) )
if [ "$?" != "0" ] ; then if [ "$?" != "0" ]; then
_clearup _clearup
_on_issue_err _on_issue_err
return 1 return 1
...@@ -2379,41 +2599,40 @@ issue() { ...@@ -2379,41 +2599,40 @@ issue() {
fi fi
done done
if [ "$dnsadded" = '0' ] ; then if [ "$dnsadded" = '0' ]; then
_savedomainconf "Le_Vlist" "$vlist" _savedomainconf "Le_Vlist" "$vlist"
_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
return 1 return 1
fi fi
fi fi
if [ "$dnsadded" = '1' ] ; then if [ "$dnsadded" = '1' ]; then
if [ -z "$Le_DNSSleep" ] ; then if [ -z "$Le_DNSSleep" ]; then
Le_DNSSleep=$DEFAULT_DNS_SLEEP Le_DNSSleep="$DEFAULT_DNS_SLEEP"
else else
_savedomainconf "Le_DNSSleep" "$Le_DNSSleep" _savedomainconf "Le_DNSSleep" "$Le_DNSSleep"
fi fi
_info "Sleep $(__green $Le_DNSSleep) seconds for the txt records to take effect" _info "Sleep $(__green $Le_DNSSleep) seconds for the txt records to take effect"
_sleep $Le_DNSSleep _sleep "$Le_DNSSleep"
fi fi
_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 ',' ' ')
for ventry in $ventries for ventry in $ventries; do
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) uri=$(echo "$ventry" | cut -d "$sep" -f 3)
uri=$(echo $ventry | cut -d $sep -f 3) vtype=$(echo "$ventry" | cut -d "$sep" -f 4)
vtype=$(echo $ventry | cut -d $sep -f 4) _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." _info "$d is already verified, skip $vtype."
continue continue
fi fi
...@@ -2427,30 +2646,29 @@ issue() { ...@@ -2427,30 +2646,29 @@ issue() {
_debug "_currentRoot" "$_currentRoot" _debug "_currentRoot" "$_currentRoot"
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 "$Le_LocalAddress" "$_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
return 1 return 1
fi fi
serverproc="$!" serverproc="$!"
sleep 2 sleep 1
_debug serverproc $serverproc _debug serverproc "$serverproc"
else else
if [ "$_currentRoot" = "apache" ] ; then if [ "$_currentRoot" = "apache" ]; then
wellknown_path="$ACME_DIR" wellknown_path="$ACME_DIR"
else else
wellknown_path="$_currentRoot/.well-known/acme-challenge" wellknown_path="$_currentRoot/.well-known/acme-challenge"
if [ ! -d "$_currentRoot/.well-known" ] ; then if [ ! -d "$_currentRoot/.well-known" ]; then
removelevel='1' removelevel='1'
elif [ ! -d "$_currentRoot/.well-known/acme-challenge" ] ; then elif [ ! -d "$_currentRoot/.well-known/acme-challenge" ]; then
removelevel='2' removelevel='2'
else else
removelevel='3' removelevel='3'
...@@ -2462,19 +2680,27 @@ issue() { ...@@ -2462,19 +2680,27 @@ issue() {
_debug "writing token:$token to $wellknown_path/$token" _debug "writing token:$token to $wellknown_path/$token"
mkdir -p "$wellknown_path" mkdir -p "$wellknown_path"
printf "%s" "$keyauthorization" > "$wellknown_path/$token"
if [ ! "$usingApache" ] ; then if ! printf "%s" "$keyauthorization" >"$wellknown_path/$token"; then
if webroot_owner=$(_stat $_currentRoot) ; then _err "$d:Can not write token to file : $wellknown_path/$token"
_clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup
_on_issue_err
return 1
fi
if [ ! "$usingApache" ]; then
if webroot_owner=$(_stat "$_currentRoot"); then
_debug "Changing owner/group of .well-known to $webroot_owner" _debug "Changing owner/group of .well-known to $webroot_owner"
chown -R $webroot_owner "$_currentRoot/.well-known" chown -R "$webroot_owner" "$_currentRoot/.well-known"
else else
_debug "not chaning owner/group of webroot"; _debug "not chaning owner/group of webroot"
fi fi
fi fi
fi fi
elif [ "$vtype" = "$VTYPE_TLS" ] ; then elif [ "$vtype" = "$VTYPE_TLS" ]; then
#create A #create A
#_hash_A="$(printf "%s" $token | _digest "sha256" "hex" )" #_hash_A="$(printf "%s" $token | _digest "sha256" "hex" )"
#_debug2 _hash_A "$_hash_A" #_debug2 _hash_A "$_hash_A"
...@@ -2484,22 +2710,22 @@ issue() { ...@@ -2484,22 +2710,22 @@ issue() {
#_debug2 _y "$_y" #_debug2 _y "$_y"
#_SAN_A="$_x.$_y.token.acme.invalid" #_SAN_A="$_x.$_y.token.acme.invalid"
#_debug2 _SAN_A "$_SAN_A" #_debug2 _SAN_A "$_SAN_A"
#create B #create B
_hash_B="$(printf "%s" $keyauthorization | _digest "sha256" "hex" )" _hash_B="$(printf "%s" "$keyauthorization" | _digest "sha256" "hex")"
_debug2 _hash_B "$_hash_B" _debug2 _hash_B "$_hash_B"
_x="$(echo $_hash_B | cut -c 1-32)" _x="$(echo "$_hash_B" | cut -c 1-32)"
_debug2 _x "$_x" _debug2 _x "$_x"
_y="$(echo $_hash_B | cut -c 33-64)" _y="$(echo "$_hash_B" | cut -c 33-64)"
_debug2 _y "$_y" _debug2 _y "$_y"
#_SAN_B="$_x.$_y.ka.acme.invalid" #_SAN_B="$_x.$_y.ka.acme.invalid"
_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 "$Le_LocalAddress" "$_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"
...@@ -2508,43 +2734,43 @@ issue() { ...@@ -2508,43 +2734,43 @@ issue() {
return 1 return 1
fi fi
fi fi
if ! _send_signed_request $uri "{\"resource\": \"challenge\", \"keyAuthorization\": \"$keyauthorization\"}" ; then if ! _send_signed_request "$uri" "{\"resource\": \"challenge\", \"keyAuthorization\": \"$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
return 1 return 1
fi fi
if [ ! -z "$code" ] && [ ! "$code" = '202' ] ; then if [ ! -z "$code" ] && [ ! "$code" = '202' ]; then
_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
return 1 return 1
fi fi
waittimes=0 waittimes=0
if [ -z "$MAX_RETRY_TIMES" ] ; then if [ -z "$MAX_RETRY_TIMES" ]; then
MAX_RETRY_TIMES=30 MAX_RETRY_TIMES=30
fi fi
while true ; do while true; do
waittimes=$(_math $waittimes + 1) waittimes=$(_math "$waittimes" + 1)
if [ "$waittimes" -ge "$MAX_RETRY_TIMES" ] ; then if [ "$waittimes" -ge "$MAX_RETRY_TIMES" ]; then
_err "$d:Timeout" _err "$d:Timeout"
_clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup _clearup
_on_issue_err _on_issue_err
return 1 return 1
fi fi
_debug "sleep 5 secs to verify" _debug "sleep 2 secs to verify"
sleep 5 sleep 2
_debug "checking" _debug "checking"
response="$(_get $uri)" response="$(_get "$uri")"
if [ "$?" != "0" ] ; then if [ "$?" != "0" ]; then
_err "$d:Verify error:$response" _err "$d:Verify error:$response"
_clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup _clearup
...@@ -2552,166 +2778,168 @@ issue() { ...@@ -2552,166 +2778,168 @@ issue() {
return 1 return 1
fi fi
_debug2 original "$response" _debug2 original "$response"
response="$(echo "$response" | _normalizeJson )" response="$(echo "$response" | _normalizeJson)"
_debug2 response "$response" _debug2 response "$response"
status=$(echo "$response" | _egrep_o '"status":"[^"]*' | cut -d : -f 2 | tr -d '"') status=$(echo "$response" | _egrep_o '"status":"[^"]*' | cut -d : -f 2 | tr -d '"')
if [ "$status" = "valid" ] ; then if [ "$status" = "valid" ]; then
_info "Success" _info "Success"
_stopserver $serverproc _stopserver "$serverproc"
serverproc="" serverproc=""
_clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
break; break
fi fi
if [ "$status" = "invalid" ] ; then if [ "$status" = "invalid" ]; then
error="$(echo "$response" | tr -d "\r\n" | _egrep_o '"error":\{[^\}]*')" error="$(echo "$response" | tr -d "\r\n" | _egrep_o '"error":\{[^\}]*')"
_debug2 error "$error" _debug2 error "$error"
errordetail="$(echo "$error" | _egrep_o '"detail": *"[^"]*' | cut -d '"' -f 4)" errordetail="$(echo "$error" | _egrep_o '"detail": *"[^"]*' | cut -d '"' -f 4)"
_debug2 errordetail "$errordetail" _debug2 errordetail "$errordetail"
if [ "$errordetail" ] ; then if [ "$errordetail" ]; then
_err "$d:Verify error:$errordetail" _err "$d:Verify error:$errordetail"
else else
_err "$d:Verify error:$error" _err "$d:Verify error:$error"
fi fi
if [ "$DEBUG" ] ; then if [ "$DEBUG" ]; then
if [ "$vtype" = "$VTYPE_HTTP" ] ; then if [ "$vtype" = "$VTYPE_HTTP" ]; then
_debug "Debug: get token url." _debug "Debug: get token url."
_get "http://$d/.well-known/acme-challenge/$token" "" 1 _get "http://$d/.well-known/acme-challenge/$token" "" 1
fi fi
fi fi
_clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup _clearup
_on_issue_err _on_issue_err
return 1; return 1
fi fi
if [ "$status" = "pending" ] ; then if [ "$status" = "pending" ]; then
_info "Pending" _info "Pending"
else else
_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
return 1 return 1
fi fi
done done
done done
_clearup _clearup
_info "Verify finished, start to sign." _info "Verify finished, start to sign."
der="$(_getfile "${CSR_PATH}" "${BEGIN_CSR}" "${END_CSR}" | tr -d "\r\n" | _urlencode)" der="$(_getfile "${CSR_PATH}" "${BEGIN_CSR}" "${END_CSR}" | tr -d "\r\n" | _urlencode)"
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
return 1 return 1
fi fi
_rcert="$response" _rcert="$response"
Le_LinkCert="$(grep -i '^Location.*$' $HTTP_HEADER | _head_n 1 | tr -d "\r\n" | cut -d " " -f 2)" Le_LinkCert="$(grep -i '^Location.*$' "$HTTP_HEADER" | _head_n 1 | tr -d "\r\n" | cut -d " " -f 2)"
_savedomainconf "Le_LinkCert" "$Le_LinkCert" _savedomainconf "Le_LinkCert" "$Le_LinkCert"
if [ "$Le_LinkCert" ] ; then if [ "$Le_LinkCert" ]; then
echo "$BEGIN_CERT" > "$CERT_PATH" echo "$BEGIN_CERT" >"$CERT_PATH"
if ! _get "$Le_LinkCert" | _base64 "multiline" >> "$CERT_PATH" ; then #if ! _get "$Le_LinkCert" | _base64 "multiline" >> "$CERT_PATH" ; then
_debug "Get cert failed. Let's try last response." # _debug "Get cert failed. Let's try last response."
printf -- "%s" "$_rcert" | _dbase64 "multiline" | _base64 "multiline" >> "$CERT_PATH" # printf -- "%s" "$_rcert" | _dbase64 "multiline" | _base64 "multiline" >> "$CERT_PATH"
#fi
if ! printf -- "%s" "$_rcert" | _dbase64 "multiline" | _base64 "multiline" >>"$CERT_PATH"; then
_debug "Try cert link."
_get "$Le_LinkCert" | _base64 "multiline" >>"$CERT_PATH"
fi fi
echo "$END_CERT" >> "$CERT_PATH" echo "$END_CERT" >>"$CERT_PATH"
_info "$(__green "Cert success.")" _info "$(__green "Cert success.")"
cat "$CERT_PATH" cat "$CERT_PATH"
_info "Your cert is in $( __green " $CERT_PATH ")"
if [ -f "$CERT_KEY_PATH" ] ; then _info "Your cert is in $(__green " $CERT_PATH ")"
_info "Your cert key is in $( __green " $CERT_KEY_PATH ")"
if [ -f "$CERT_KEY_PATH" ]; then
_info "Your cert key is in $(__green " $CERT_KEY_PATH ")"
fi fi
cp "$CERT_PATH" "$CERT_FULLCHAIN_PATH" cp "$CERT_PATH" "$CERT_FULLCHAIN_PATH"
if [ ! "$USER_PATH" ] || [ ! "$IN_CRON" ] ; then if [ ! "$USER_PATH" ] || [ ! "$IN_CRON" ]; then
USER_PATH="$PATH" USER_PATH="$PATH"
_saveaccountconf "USER_PATH" "$USER_PATH" _saveaccountconf "USER_PATH" "$USER_PATH"
fi fi
fi fi
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
return 1 return 1
fi fi
_cleardomainconf "Le_Vlist" _cleardomainconf "Le_Vlist"
Le_LinkIssuer=$(grep -i '^Link' $HTTP_HEADER | _head_n 1 | cut -d " " -f 2| cut -d ';' -f 1 | tr -d '<>' ) Le_LinkIssuer=$(grep -i '^Link' "$HTTP_HEADER" | _head_n 1 | cut -d " " -f 2 | cut -d ';' -f 1 | tr -d '<>')
if ! _contains "$Le_LinkIssuer" ":" ; then if ! _contains "$Le_LinkIssuer" ":"; then
Le_LinkIssuer="$API$Le_LinkIssuer" Le_LinkIssuer="$API$Le_LinkIssuer"
fi fi
_savedomainconf "Le_LinkIssuer" "$Le_LinkIssuer" _savedomainconf "Le_LinkIssuer" "$Le_LinkIssuer"
if [ "$Le_LinkIssuer" ] ; then if [ "$Le_LinkIssuer" ]; then
echo "$BEGIN_CERT" > "$CA_CERT_PATH" echo "$BEGIN_CERT" >"$CA_CERT_PATH"
_get "$Le_LinkIssuer" | _base64 "multiline" >> "$CA_CERT_PATH" _get "$Le_LinkIssuer" | _base64 "multiline" >>"$CA_CERT_PATH"
echo "$END_CERT" >> "$CA_CERT_PATH" echo "$END_CERT" >>"$CA_CERT_PATH"
_info "The intermediate CA cert is in $( __green " $CA_CERT_PATH ")" _info "The intermediate CA cert is in $(__green " $CA_CERT_PATH ")"
cat "$CA_CERT_PATH" >> "$CERT_FULLCHAIN_PATH" cat "$CA_CERT_PATH" >>"$CERT_FULLCHAIN_PATH"
_info "And the full chain certs is there: $( __green " $CERT_FULLCHAIN_PATH ")" _info "And the full chain certs is there: $(__green " $CERT_FULLCHAIN_PATH ")"
fi fi
Le_CertCreateTime=$(_time) Le_CertCreateTime=$(_time)
_savedomainconf "Le_CertCreateTime" "$Le_CertCreateTime" _savedomainconf "Le_CertCreateTime" "$Le_CertCreateTime"
Le_CertCreateTimeStr=$(date -u ) Le_CertCreateTimeStr=$(date -u)
_savedomainconf "Le_CertCreateTimeStr" "$Le_CertCreateTimeStr" _savedomainconf "Le_CertCreateTimeStr" "$Le_CertCreateTimeStr"
if [ -z "$Le_RenewalDays" ] || [ "$Le_RenewalDays" -lt "0" ] || [ "$Le_RenewalDays" -gt "$MAX_RENEW" ] ; then if [ -z "$Le_RenewalDays" ] || [ "$Le_RenewalDays" -lt "0" ] || [ "$Le_RenewalDays" -gt "$MAX_RENEW" ]; then
Le_RenewalDays=$MAX_RENEW Le_RenewalDays="$MAX_RENEW"
else else
_savedomainconf "Le_RenewalDays" "$Le_RenewalDays" _savedomainconf "Le_RenewalDays" "$Le_RenewalDays"
fi fi
if [ "$CA_BUNDLE" ] ; then if [ "$CA_BUNDLE" ]; then
_saveaccountconf CA_BUNDLE "$CA_BUNDLE" _saveaccountconf CA_BUNDLE "$CA_BUNDLE"
else else
_clearaccountconf "CA_BUNDLE" _clearaccountconf "CA_BUNDLE"
fi fi
if [ "$HTTPS_INSECURE" ] ; then if [ "$HTTPS_INSECURE" ]; then
_saveaccountconf HTTPS_INSECURE "$HTTPS_INSECURE" _saveaccountconf HTTPS_INSECURE "$HTTPS_INSECURE"
else else
_clearaccountconf "HTTPS_INSECURE" _clearaccountconf "HTTPS_INSECURE"
fi fi
if [ "$Le_Listen_V4" ] ; then if [ "$Le_Listen_V4" ]; then
_savedomainconf "Le_Listen_V4" "$Le_Listen_V4" _savedomainconf "Le_Listen_V4" "$Le_Listen_V4"
_cleardomainconf Le_Listen_V6 _cleardomainconf Le_Listen_V6
elif [ "$Le_Listen_V6" ] ; then elif [ "$Le_Listen_V6" ]; then
_savedomainconf "Le_Listen_V6" "$Le_Listen_V6" _savedomainconf "Le_Listen_V6" "$Le_Listen_V6"
_cleardomainconf Le_Listen_V4 _cleardomainconf Le_Listen_V4
fi fi
Le_NextRenewTime=$(_math $Le_CertCreateTime + $Le_RenewalDays \* 24 \* 60 \* 60)
Le_NextRenewTimeStr=$( _time2str $Le_NextRenewTime )
_savedomainconf "Le_NextRenewTimeStr" "$Le_NextRenewTimeStr"
Le_NextRenewTime=$(_math $Le_NextRenewTime - 86400)
_savedomainconf "Le_NextRenewTime" "$Le_NextRenewTime"
Le_NextRenewTime=$(_math "$Le_CertCreateTime" + "$Le_RenewalDays" \* 24 \* 60 \* 60)
Le_NextRenewTimeStr=$(_time2str "$Le_NextRenewTime")
_savedomainconf "Le_NextRenewTimeStr" "$Le_NextRenewTimeStr"
Le_NextRenewTime=$(_math "$Le_NextRenewTime" - 86400)
_savedomainconf "Le_NextRenewTime" "$Le_NextRenewTime"
_on_issue_success _on_issue_success
if [ "$Le_RealCertPath$Le_RealKeyPath$Le_RealCACertPath$Le_ReloadCmd$Le_RealFullChainPath" ] ; then if [ "$Le_RealCertPath$Le_RealKeyPath$Le_RealCACertPath$Le_ReloadCmd$Le_RealFullChainPath" ]; then
_installcert _installcert
fi fi
...@@ -2720,52 +2948,52 @@ issue() { ...@@ -2720,52 +2948,52 @@ issue() {
#domain [isEcc] #domain [isEcc]
renew() { renew() {
Le_Domain="$1" Le_Domain="$1"
if [ -z "$Le_Domain" ] ; then if [ -z "$Le_Domain" ]; then
_usage "Usage: $PROJECT_ENTRY --renew -d domain.com [--ecc]" _usage "Usage: $PROJECT_ENTRY --renew -d domain.com [--ecc]"
return 1 return 1
fi fi
_isEcc="$2" _isEcc="$2"
_initpath $Le_Domain "$_isEcc" _initpath "$Le_Domain" "$_isEcc"
_info "$(__green "Renew: '$Le_Domain'")" _info "$(__green "Renew: '$Le_Domain'")"
if [ ! -f "$DOMAIN_CONF" ] ; then if [ ! -f "$DOMAIN_CONF" ]; then
_info "'$Le_Domain' is not a issued domain, skip." _info "'$Le_Domain' is not a issued domain, skip."
return 0; return 0
fi fi
if [ "$Le_RenewalDays" ] ; then if [ "$Le_RenewalDays" ]; then
_savedomainconf Le_RenewalDays "$Le_RenewalDays" _savedomainconf Le_RenewalDays "$Le_RenewalDays"
fi fi
. "$DOMAIN_CONF" . "$DOMAIN_CONF"
if [ "$Le_API" ] ; then if [ "$Le_API" ]; then
API="$Le_API" API="$Le_API"
fi fi
if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(_time)" -lt "$Le_NextRenewTime" ] ; then if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(_time)" -lt "$Le_NextRenewTime" ]; then
_info "Skip, Next renewal time is: $(__green "$Le_NextRenewTimeStr")" _info "Skip, Next renewal time is: $(__green "$Le_NextRenewTimeStr")"
_info "Add '$(__red '--force')' to force to renew." _info "Add '$(__red '--force')' to force to renew."
return $RENEW_SKIP return "$RENEW_SKIP"
fi fi
IS_RENEW="1" IS_RENEW="1"
issue "$Le_Webroot" "$Le_Domain" "$Le_Alt" "$Le_Keylength" "$Le_RealCertPath" "$Le_RealKeyPath" "$Le_RealCACertPath" "$Le_ReloadCmd" "$Le_RealFullChainPath" "$Le_PreHook" "$Le_PostHook" "$Le_RenewHook" "$Le_LocalAddress" issue "$Le_Webroot" "$Le_Domain" "$Le_Alt" "$Le_Keylength" "$Le_RealCertPath" "$Le_RealKeyPath" "$Le_RealCACertPath" "$Le_ReloadCmd" "$Le_RealFullChainPath" "$Le_PreHook" "$Le_PostHook" "$Le_RenewHook" "$Le_LocalAddress"
res=$? res="$?"
if [ "$res" != "0" ] ; then if [ "$res" != "0" ]; then
return $res return "$res"
fi fi
if [ "$Le_DeployHook" ] ; then if [ "$Le_DeployHook" ]; then
deploy $Le_Domain "$Le_DeployHook" "$Le_Keylength" deploy "$Le_Domain" "$Le_DeployHook" "$Le_Keylength"
res=$? res="$?"
fi fi
IS_RENEW="" IS_RENEW=""
return $res return "$res"
} }
#renewAll [stopRenewOnError] #renewAll [stopRenewOnError]
...@@ -2775,35 +3003,36 @@ renewAll() { ...@@ -2775,35 +3003,36 @@ renewAll() {
_debug "_stopRenewOnError" "$_stopRenewOnError" _debug "_stopRenewOnError" "$_stopRenewOnError"
_ret="0" _ret="0"
for d in $(ls -F ${CERT_HOME}/ | grep [^.].*[.].*/$ ) ; do for di in "${CERT_HOME}"/*.*/; do
d=$(echo $d | cut -d '/' -f 1) _debug di "$di"
d=$(basename "$di")
_debug d "$d"
( (
if _endswith $d "$ECC_SUFFIX" ; then if _endswith "$d" "$ECC_SUFFIX"; then
_isEcc=$(echo $d | cut -d "$ECC_SEP" -f 2) _isEcc=$(echo "$d" | cut -d "$ECC_SEP" -f 2)
d=$(echo $d | cut -d "$ECC_SEP" -f 1) d=$(echo "$d" | cut -d "$ECC_SEP" -f 1)
fi fi
renew "$d" "$_isEcc" renew "$d" "$_isEcc"
) )
rc="$?" rc="$?"
_debug "Return code: $rc" _debug "Return code: $rc"
if [ "$rc" != "0" ] ; then if [ "$rc" != "0" ]; then
if [ "$rc" = "$RENEW_SKIP" ] ; then if [ "$rc" = "$RENEW_SKIP" ]; then
_info "Skipped $d" _info "Skipped $d"
elif [ "$_stopRenewOnError" ] ; then elif [ "$_stopRenewOnError" ]; then
_err "Error renew $d, stop now." _err "Error renew $d, stop now."
return $rc return "$rc"
else else
_ret="$rc" _ret="$rc"
_err "Error renew $d, Go ahead to next one." _err "Error renew $d, Go ahead to next one."
fi fi
fi fi
done done
return $_ret return "$_ret"
} }
#csr webroot #csr webroot
signcsr(){ signcsr() {
_csrfile="$1" _csrfile="$1"
_csrW="$2" _csrW="$2"
if [ -z "$_csrfile" ] || [ -z "$_csrW" ]; then if [ -z "$_csrfile" ] || [ -z "$_csrW" ]; then
...@@ -2814,50 +3043,49 @@ signcsr(){ ...@@ -2814,50 +3043,49 @@ signcsr(){
_initpath _initpath
_csrsubj=$(_readSubjectFromCSR "$_csrfile") _csrsubj=$(_readSubjectFromCSR "$_csrfile")
if [ "$?" != "0" ] ; then if [ "$?" != "0" ]; then
_err "Can not read subject from csr: $_csrfile" _err "Can not read subject from csr: $_csrfile"
return 1 return 1
fi fi
_debug _csrsubj "$_csrsubj" _debug _csrsubj "$_csrsubj"
_csrdomainlist=$(_readSubjectAltNamesFromCSR "$_csrfile") _csrdomainlist=$(_readSubjectAltNamesFromCSR "$_csrfile")
if [ "$?" != "0" ] ; then if [ "$?" != "0" ]; then
_err "Can not read domain list from csr: $_csrfile" _err "Can not read domain list from csr: $_csrfile"
return 1 return 1
fi fi
_debug "_csrdomainlist" "$_csrdomainlist" _debug "_csrdomainlist" "$_csrdomainlist"
if [ -z "$_csrsubj" ]; then
if [ -z "$_csrsubj" ] ; then
_csrsubj="$(_getfield "$_csrdomainlist" 1)" _csrsubj="$(_getfield "$_csrdomainlist" 1)"
_debug _csrsubj "$_csrsubj" _debug _csrsubj "$_csrsubj"
_csrdomainlist="$(echo "$_csrdomainlist" | cut -d , -f 2-)" _csrdomainlist="$(echo "$_csrdomainlist" | cut -d , -f 2-)"
_debug "_csrdomainlist" "$_csrdomainlist" _debug "_csrdomainlist" "$_csrdomainlist"
fi fi
if [ -z "$_csrsubj" ] ; then if [ -z "$_csrsubj" ]; then
_err "Can not read subject from csr: $_csrfile" _err "Can not read subject from csr: $_csrfile"
return 1 return 1
fi fi
_csrkeylength=$(_readKeyLengthFromCSR "$_csrfile") _csrkeylength=$(_readKeyLengthFromCSR "$_csrfile")
if [ "$?" != "0" ] || [ -z "$_csrkeylength" ] ; then if [ "$?" != "0" ] || [ -z "$_csrkeylength" ]; then
_err "Can not read key length from csr: $_csrfile" _err "Can not read key length from csr: $_csrfile"
return 1 return 1
fi fi
_initpath "$_csrsubj" "$_csrkeylength" _initpath "$_csrsubj" "$_csrkeylength"
mkdir -p "$DOMAIN_PATH" mkdir -p "$DOMAIN_PATH"
_info "Copy csr to: $CSR_PATH" _info "Copy csr to: $CSR_PATH"
cp "$_csrfile" "$CSR_PATH" cp "$_csrfile" "$CSR_PATH"
issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength" issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength"
} }
showcsr() { showcsr() {
_csrfile="$1" _csrfile="$1"
_csrd="$2" _csrd="$2"
if [ -z "$_csrfile" ] && [ -z "$_csrd" ]; then if [ -z "$_csrfile" ] && [ -z "$_csrd" ]; then
_usage "Usage: $PROJECT_ENTRY --showcsr --csr mycsr.csr" _usage "Usage: $PROJECT_ENTRY --showcsr --csr mycsr.csr"
...@@ -2865,17 +3093,17 @@ showcsr() { ...@@ -2865,17 +3093,17 @@ showcsr() {
fi fi
_initpath _initpath
_csrsubj=$(_readSubjectFromCSR "$_csrfile") _csrsubj=$(_readSubjectFromCSR "$_csrfile")
if [ "$?" != "0" ] || [ -z "$_csrsubj" ] ; then if [ "$?" != "0" ] || [ -z "$_csrsubj" ]; then
_err "Can not read subject from csr: $_csrfile" _err "Can not read subject from csr: $_csrfile"
return 1 return 1
fi fi
_info "Subject=$_csrsubj" _info "Subject=$_csrsubj"
_csrdomainlist=$(_readSubjectAltNamesFromCSR "$_csrfile") _csrdomainlist=$(_readSubjectAltNamesFromCSR "$_csrfile")
if [ "$?" != "0" ] ; then if [ "$?" != "0" ]; then
_err "Can not read domain list from csr: $_csrfile" _err "Can not read domain list from csr: $_csrfile"
return 1 return 1
fi fi
...@@ -2883,9 +3111,8 @@ showcsr() { ...@@ -2883,9 +3111,8 @@ showcsr() {
_info "SubjectAltNames=$_csrdomainlist" _info "SubjectAltNames=$_csrdomainlist"
_csrkeylength=$(_readKeyLengthFromCSR "$_csrfile") _csrkeylength=$(_readKeyLengthFromCSR "$_csrfile")
if [ "$?" != "0" ] || [ -z "$_csrkeylength" ] ; then if [ "$?" != "0" ] || [ -z "$_csrkeylength" ]; then
_err "Can not read key length from csr: $_csrfile" _err "Can not read key length from csr: $_csrfile"
return 1 return 1
fi fi
...@@ -2895,88 +3122,88 @@ showcsr() { ...@@ -2895,88 +3122,88 @@ showcsr() {
list() { list() {
_raw="$1" _raw="$1"
_initpath _initpath
_sep="|" _sep="|"
if [ "$_raw" ] ; then if [ "$_raw" ]; then
printf "Main_Domain${_sep}KeyLength${_sep}SAN_Domains${_sep}Created${_sep}Renew\n" printf "%s\n" "Main_Domain${_sep}KeyLength${_sep}SAN_Domains${_sep}Created${_sep}Renew"
for d in $(ls -F ${CERT_HOME}/ | grep [^.].*[.].*/$ ) ; do for di in "${CERT_HOME}"/*.*/; do
d=$(echo $d | cut -d '/' -f 1) d=$(basename "$di")
_debug d "$d"
( (
if _endswith $d "$ECC_SUFFIX" ; then if _endswith "$d" "$ECC_SUFFIX"; then
_isEcc=$(echo $d | cut -d "$ECC_SEP" -f 2) _isEcc=$(echo "$d" | cut -d "$ECC_SEP" -f 2)
d=$(echo $d | cut -d "$ECC_SEP" -f 1) d=$(echo "$d" | cut -d "$ECC_SEP" -f 1)
fi fi
_initpath $d "$_isEcc" _initpath "$d" "$_isEcc"
if [ -f "$DOMAIN_CONF" ] ; then if [ -f "$DOMAIN_CONF" ]; then
. "$DOMAIN_CONF" . "$DOMAIN_CONF"
printf "$Le_Domain${_sep}\"$Le_Keylength\"${_sep}$Le_Alt${_sep}$Le_CertCreateTimeStr${_sep}$Le_NextRenewTimeStr\n" printf "%s\n" "$Le_Domain${_sep}\"$Le_Keylength\"${_sep}$Le_Alt${_sep}$Le_CertCreateTimeStr${_sep}$Le_NextRenewTimeStr"
fi fi
) )
done done
else else
if _exists column ; then if _exists column; then
list "raw" | column -t -s "$_sep" list "raw" | column -t -s "$_sep"
else else
list "raw" | tr "$_sep" '\t' list "raw" | tr "$_sep" '\t'
fi fi
fi fi
} }
deploy() { deploy() {
Le_Domain="$1" Le_Domain="$1"
Le_DeployHook="$2" Le_DeployHook="$2"
_isEcc="$3" _isEcc="$3"
if [ -z "$Le_DeployHook" ] ; then if [ -z "$Le_DeployHook" ]; 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 "$Le_Domain" "$_isEcc"
if [ ! -d "$DOMAIN_PATH" ] ; then if [ ! -d "$DOMAIN_PATH" ]; then
_err "Domain is not valid:'$Le_Domain'" _err "Domain is not valid:'$Le_Domain'"
return 1 return 1
fi fi
_deployApi="$(_findHook $Le_Domain deploy $Le_DeployHook)" _deployApi="$(_findHook "$Le_Domain" deploy "$Le_DeployHook")"
if [ -z "$_deployApi" ] ; then if [ -z "$_deployApi" ]; then
_err "The deploy hook $Le_DeployHook is not found." _err "The deploy hook $Le_DeployHook is not found."
return 1 return 1
fi fi
_debug _deployApi "$_deployApi" _debug _deployApi "$_deployApi"
_savedomainconf Le_DeployHook "$Le_DeployHook" _savedomainconf Le_DeployHook "$Le_DeployHook"
if ! ( if ! (
if ! . $_deployApi ; then if ! . "$_deployApi"; then
_err "Load file $_deployApi error. Please check your api file and try again." _err "Load file $_deployApi error. Please check your api file and try again."
return 1 return 1
fi fi
d_command="${Le_DeployHook}_deploy" d_command="${Le_DeployHook}_deploy"
if ! _exists $d_command ; then if ! _exists "$d_command"; then
_err "It seems that your api file is not correct, it must have a function named: $d_command" _err "It seems that your api file is not correct, it must have a function named: $d_command"
return 1 return 1
fi fi
if ! $d_command $Le_Domain "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$CERT_FULLCHAIN_PATH" ; then if ! $d_command "$Le_Domain" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$CERT_FULLCHAIN_PATH"; then
_err "Error deploy for domain:$Le_Domain" _err "Error deploy for domain:$Le_Domain"
_on_issue_err _on_issue_err
return 1 return 1
fi fi
) ; then ); then
_err "Deploy error." _err "Deploy error."
return 1 return 1
else else
_info "$(__green Success)" _info "$(__green Success)"
fi fi
} }
installcert() { installcert() {
Le_Domain="$1" Le_Domain="$1"
if [ -z "$Le_Domain" ] ; then if [ -z "$Le_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
...@@ -2988,8 +3215,8 @@ installcert() { ...@@ -2988,8 +3215,8 @@ installcert() {
Le_RealFullChainPath="$6" Le_RealFullChainPath="$6"
_isEcc="$7" _isEcc="$7"
_initpath $Le_Domain "$_isEcc" _initpath "$Le_Domain" "$_isEcc"
if [ ! -d "$DOMAIN_PATH" ] ; then if [ ! -d "$DOMAIN_PATH" ]; then
_err "Domain is not valid:'$Le_Domain'" _err "Domain is not valid:'$Le_Domain'"
return 1 return 1
fi fi
...@@ -2997,90 +3224,85 @@ installcert() { ...@@ -2997,90 +3224,85 @@ installcert() {
_installcert _installcert
} }
_installcert() { _installcert() {
_savedomainconf "Le_RealCertPath" "$Le_RealCertPath"
_savedomainconf "Le_RealCACertPath" "$Le_RealCACertPath"
_savedomainconf "Le_RealKeyPath" "$Le_RealKeyPath"
_savedomainconf "Le_ReloadCmd" "$Le_ReloadCmd"
_savedomainconf "Le_RealFullChainPath" "$Le_RealFullChainPath"
_savedomainconf "Le_RealCertPath" "$Le_RealCertPath" if [ "$Le_RealCertPath" = "$NO_VALUE" ]; then
_savedomainconf "Le_RealCACertPath" "$Le_RealCACertPath"
_savedomainconf "Le_RealKeyPath" "$Le_RealKeyPath"
_savedomainconf "Le_ReloadCmd" "$Le_ReloadCmd"
_savedomainconf "Le_RealFullChainPath" "$Le_RealFullChainPath"
if [ "$Le_RealCertPath" = "$NO_VALUE" ] ; then
Le_RealCertPath="" Le_RealCertPath=""
fi fi
if [ "$Le_RealKeyPath" = "$NO_VALUE" ] ; then if [ "$Le_RealKeyPath" = "$NO_VALUE" ]; then
Le_RealKeyPath="" Le_RealKeyPath=""
fi fi
if [ "$Le_RealCACertPath" = "$NO_VALUE" ] ; then if [ "$Le_RealCACertPath" = "$NO_VALUE" ]; then
Le_RealCACertPath="" Le_RealCACertPath=""
fi fi
if [ "$Le_ReloadCmd" = "$NO_VALUE" ] ; then if [ "$Le_ReloadCmd" = "$NO_VALUE" ]; then
Le_ReloadCmd="" Le_ReloadCmd=""
fi fi
if [ "$Le_RealFullChainPath" = "$NO_VALUE" ] ; then if [ "$Le_RealFullChainPath" = "$NO_VALUE" ]; then
Le_RealFullChainPath="" Le_RealFullChainPath=""
fi fi
_installed="0" if [ "$Le_RealCertPath" ]; then
if [ "$Le_RealCertPath" ] ; then
_installed=1
_info "Installing cert to:$Le_RealCertPath" _info "Installing cert to:$Le_RealCertPath"
if [ -f "$Le_RealCertPath" ] && [ ! "$IS_RENEW" ] ; then if [ -f "$Le_RealCertPath" ] && [ ! "$IS_RENEW" ]; then
cp "$Le_RealCertPath" "$Le_RealCertPath".bak cp "$Le_RealCertPath" "$Le_RealCertPath".bak
fi fi
cat "$CERT_PATH" > "$Le_RealCertPath" cat "$CERT_PATH" >"$Le_RealCertPath"
fi fi
if [ "$Le_RealCACertPath" ] ; then if [ "$Le_RealCACertPath" ]; then
_installed=1
_info "Installing CA to:$Le_RealCACertPath" _info "Installing CA to:$Le_RealCACertPath"
if [ "$Le_RealCACertPath" = "$Le_RealCertPath" ] ; then if [ "$Le_RealCACertPath" = "$Le_RealCertPath" ]; then
echo "" >> "$Le_RealCACertPath" echo "" >>"$Le_RealCACertPath"
cat "$CA_CERT_PATH" >> "$Le_RealCACertPath" cat "$CA_CERT_PATH" >>"$Le_RealCACertPath"
else else
if [ -f "$Le_RealCACertPath" ] && [ ! "$IS_RENEW" ] ; then if [ -f "$Le_RealCACertPath" ] && [ ! "$IS_RENEW" ]; then
cp "$Le_RealCACertPath" "$Le_RealCACertPath".bak cp "$Le_RealCACertPath" "$Le_RealCACertPath".bak
fi fi
cat "$CA_CERT_PATH" > "$Le_RealCACertPath" cat "$CA_CERT_PATH" >"$Le_RealCACertPath"
fi fi
fi fi
if [ "$Le_RealKeyPath" ]; then
if [ "$Le_RealKeyPath" ] ; then
_installed=1
_info "Installing key to:$Le_RealKeyPath" _info "Installing key to:$Le_RealKeyPath"
if [ -f "$Le_RealKeyPath" ] && [ ! "$IS_RENEW" ] ; then if [ -f "$Le_RealKeyPath" ] && [ ! "$IS_RENEW" ]; then
cp "$Le_RealKeyPath" "$Le_RealKeyPath".bak cp "$Le_RealKeyPath" "$Le_RealKeyPath".bak
fi fi
cat "$CERT_KEY_PATH" > "$Le_RealKeyPath" cat "$CERT_KEY_PATH" >"$Le_RealKeyPath"
fi fi
if [ "$Le_RealFullChainPath" ] ; then if [ "$Le_RealFullChainPath" ]; then
_installed=1
_info "Installing full chain to:$Le_RealFullChainPath" _info "Installing full chain to:$Le_RealFullChainPath"
if [ -f "$Le_RealFullChainPath" ] && [ ! "$IS_RENEW" ] ; then if [ -f "$Le_RealFullChainPath" ] && [ ! "$IS_RENEW" ]; then
cp "$Le_RealFullChainPath" "$Le_RealFullChainPath".bak cp "$Le_RealFullChainPath" "$Le_RealFullChainPath".bak
fi fi
cat "$CERT_FULLCHAIN_PATH" > "$Le_RealFullChainPath" cat "$CERT_FULLCHAIN_PATH" >"$Le_RealFullChainPath"
fi fi
if [ "$Le_ReloadCmd" ]; then
if [ "$Le_ReloadCmd" ] ; then
_installed=1
_info "Run Le_ReloadCmd: $Le_ReloadCmd" _info "Run Le_ReloadCmd: $Le_ReloadCmd"
if (cd "$DOMAIN_PATH" && eval "$Le_ReloadCmd") ; then if (cd "$DOMAIN_PATH" && eval "$Le_ReloadCmd"); then
_info "$(__green "Reload success")" _info "$(__green "Reload success")"
else else
_err "Reload error for :$Le_Domain" _err "Reload error for :$Le_Domain"
fi fi
fi fi
} }
installcronjob() { installcronjob() {
_initpath _initpath
if ! _exists "crontab" ; then if ! _exists "crontab"; then
_err "crontab doesn't exist, so, we can not install cron jobs." _err "crontab doesn't exist, so, we can not install cron jobs."
_err "All your certs will not be renewed automatically." _err "All your certs will not be renewed automatically."
_err "You must add your own cron job to call '$PROJECT_ENTRY --cron' everyday." _err "You must add your own cron job to call '$PROJECT_ENTRY --cron' everyday."
...@@ -3088,20 +3310,26 @@ installcronjob() { ...@@ -3088,20 +3310,26 @@ installcronjob() {
fi fi
_info "Installing cron job" _info "Installing cron job"
if ! crontab -l | grep "$PROJECT_ENTRY --cron" ; then if ! crontab -l | grep "$PROJECT_ENTRY --cron"; then
if [ -f "$LE_WORKING_DIR/$PROJECT_ENTRY" ] ; then if [ -f "$LE_WORKING_DIR/$PROJECT_ENTRY" ]; then
lesh="\"$LE_WORKING_DIR\"/$PROJECT_ENTRY" lesh="\"$LE_WORKING_DIR\"/$PROJECT_ENTRY"
else else
_err "Can not install cronjob, $PROJECT_ENTRY not found." _err "Can not install cronjob, $PROJECT_ENTRY not found."
return 1 return 1
fi fi
if _exists uname && uname -a | grep solaris >/dev/null ; then if _exists uname && uname -a | grep solaris >/dev/null; then
crontab -l | { cat; echo "0 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" > /dev/null"; } | crontab -- crontab -l | {
cat
echo "0 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" > /dev/null"
} | crontab --
else else
crontab -l | { cat; echo "0 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" > /dev/null"; } | crontab - crontab -l | {
cat
echo "0 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" > /dev/null"
} | crontab -
fi fi
fi fi
if [ "$?" != "0" ] ; then if [ "$?" != "0" ]; then
_err "Install cron job failed. You need to manually renew your certs." _err "Install cron job failed. You need to manually renew your certs."
_err "Or you can add cronjob by yourself:" _err "Or you can add cronjob by yourself:"
_err "$lesh --cron --home \"$LE_WORKING_DIR\" > /dev/null" _err "$lesh --cron --home \"$LE_WORKING_DIR\" > /dev/null"
...@@ -3110,74 +3338,78 @@ installcronjob() { ...@@ -3110,74 +3338,78 @@ installcronjob() {
} }
uninstallcronjob() { uninstallcronjob() {
if ! _exists "crontab" ; then if ! _exists "crontab"; then
return return
fi fi
_info "Removing cron job" _info "Removing cron job"
cr="$(crontab -l | grep "$PROJECT_ENTRY --cron")" cr="$(crontab -l | grep "$PROJECT_ENTRY --cron")"
if [ "$cr" ] ; then if [ "$cr" ]; then
if _exists uname && uname -a | grep solaris >/dev/null ; then if _exists uname && uname -a | grep solaris >/dev/null; then
crontab -l | sed "/$PROJECT_ENTRY --cron/d" | crontab -- crontab -l | sed "/$PROJECT_ENTRY --cron/d" | crontab --
else else
crontab -l | sed "/$PROJECT_ENTRY --cron/d" | crontab - crontab -l | sed "/$PROJECT_ENTRY --cron/d" | crontab -
fi fi
LE_WORKING_DIR="$(echo "$cr" | cut -d ' ' -f 9 | tr -d '"')" LE_WORKING_DIR="$(echo "$cr" | cut -d ' ' -f 9 | tr -d '"')"
_info LE_WORKING_DIR "$LE_WORKING_DIR" _info LE_WORKING_DIR "$LE_WORKING_DIR"
fi fi
_initpath _initpath
} }
revoke() { revoke() {
Le_Domain="$1" Le_Domain="$1"
if [ -z "$Le_Domain" ] ; then if [ -z "$Le_Domain" ]; then
_usage "Usage: $PROJECT_ENTRY --revoke -d domain.com" _usage "Usage: $PROJECT_ENTRY --revoke -d domain.com"
return 1 return 1
fi fi
_isEcc="$2" _isEcc="$2"
_initpath $Le_Domain "$_isEcc" _initpath "$Le_Domain" "$_isEcc"
if [ ! -f "$DOMAIN_CONF" ] ; then if [ ! -f "$DOMAIN_CONF" ]; then
_err "$Le_Domain is not a issued domain, skip." _err "$Le_Domain is not a issued domain, skip."
return 1; return 1
fi fi
if [ ! -f "$CERT_PATH" ] ; then if [ ! -f "$CERT_PATH" ]; then
_err "Cert for $Le_Domain $CERT_PATH is not found, skip." _err "Cert for $Le_Domain $CERT_PATH is not found, skip."
return 1 return 1
fi fi
cert="$(_getfile "${CERT_PATH}" "${BEGIN_CERT}" "${END_CERT}"| tr -d "\r\n" | _urlencode)"
if [ -z "$cert" ] ; then cert="$(_getfile "${CERT_PATH}" "${BEGIN_CERT}" "${END_CERT}" | tr -d "\r\n" | _urlencode)"
if [ -z "$cert" ]; then
_err "Cert for $Le_Domain is empty found, skip." _err "Cert for $Le_Domain is empty found, skip."
return 1 return 1
fi fi
data="{\"resource\": \"revoke-cert\", \"certificate\": \"$cert\"}" data="{\"resource\": \"revoke-cert\", \"certificate\": \"$cert\"}"
uri="$API/acme/revoke-cert" uri="$API/acme/revoke-cert"
_info "Try domain key first." if [ -f "$CERT_KEY_PATH" ]; then
if _send_signed_request $uri "$data" "" "$CERT_KEY_PATH"; then _info "Try domain key first."
if [ -z "$response" ] ; then if _send_signed_request "$uri" "$data" "" "$CERT_KEY_PATH"; then
_info "Revoke success." if [ -z "$response" ]; then
rm -f $CERT_PATH _info "Revoke success."
return 0 rm -f "$CERT_PATH"
else return 0
_err "Revoke error by domain key." else
_err "$response" _err "Revoke error by domain key."
_err "$response"
fi
fi fi
else
_info "Domain key file doesn't exists."
fi fi
_info "Then try account key."
if _send_signed_request $uri "$data" "" "$ACCOUNT_KEY_PATH" ; then _info "Try account key."
if [ -z "$response" ] ; then
if _send_signed_request "$uri" "$data" "" "$ACCOUNT_KEY_PATH"; then
if [ -z "$response" ]; then
_info "Revoke success." _info "Revoke success."
rm -f $CERT_PATH rm -f "$CERT_PATH"
return 0 return 0
else else
_err "Revoke error." _err "Revoke error."
_debug "$response" _debug "$response"
fi fi
...@@ -3185,65 +3417,63 @@ revoke() { ...@@ -3185,65 +3417,63 @@ revoke() {
return 1 return 1
} }
#domain vtype #domain vtype
_deactivate() { _deactivate() {
_d_domain="$1" _d_domain="$1"
_d_type="$2" _d_type="$2"
_initpath _initpath
_d_i=0 _d_i=0
_d_max_retry=9 _d_max_retry=9
while [ "$_d_i" -lt "$_d_max_retry" ] ; while [ "$_d_i" -lt "$_d_max_retry" ]; do
do
_info "Deactivate: $_d_domain" _info "Deactivate: $_d_domain"
_d_i="$(_math $_d_i + 1)" _d_i="$(_math $_d_i + 1)"
if ! _send_signed_request "$API/acme/new-authz" "{\"resource\": \"new-authz\", \"identifier\": {\"type\": \"dns\", \"value\": \"$(_idn "$_d_domain")\"}}" ; then
_err "Can not get domain token." if ! __get_domain_new_authz "$_d_domain"; then
_err "Can not get domain new authz token."
return 1 return 1
fi fi
authzUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ' ' -f 2 | tr -d "\r\n")" authzUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ' ' -f 2 | tr -d "\r\n")"
_debug "authzUri" "$authzUri" _debug "authzUri" "$authzUri"
if [ ! -z "$code" ] && [ ! "$code" = '201' ] ; then if [ ! -z "$code" ] && [ ! "$code" = '201' ]; then
_err "new-authz error: $response" _err "new-authz error: $response"
return 1 return 1
fi fi
entry="$(printf "%s\n" "$response" | _egrep_o '[^\{]*"status":"valid","uri"[^\}]*')" entry="$(printf "%s\n" "$response" | _egrep_o '[^\{]*"status":"valid","uri"[^\}]*')"
_debug entry "$entry" _debug entry "$entry"
if [ -z "$entry" ] ; then if [ -z "$entry" ]; then
_info "No more valid entry found." _info "No more valid entry found."
break break
fi fi
_vtype="$(printf "%s\n" "$entry" | _egrep_o '"type": *"[^"]*"' | cut -d : -f 2 | tr -d '"')" _vtype="$(printf "%s\n" "$entry" | _egrep_o '"type": *"[^"]*"' | cut -d : -f 2 | tr -d '"')"
_debug _vtype $_vtype _debug _vtype "$_vtype"
_info "Found $_vtype" _info "Found $_vtype"
uri="$(printf "%s\n" "$entry" | _egrep_o '"uri":"[^"]*' | cut -d : -f 2,3 | tr -d '"')"
uri="$(printf "%s\n" "$entry" | _egrep_o '"uri":"[^"]*'| cut -d : -f 2,3 | tr -d '"' )" _debug uri "$uri"
_debug uri $uri
if [ "$_d_type" ] && [ "$_d_type" != "$_vtype" ]; then
if [ "$_d_type" ] && [ "$_d_type" != "$_vtype" ] ; then
_info "Skip $_vtype" _info "Skip $_vtype"
continue continue
fi fi
_info "Deactivate: $_vtype" _info "Deactivate: $_vtype"
if ! _send_signed_request "$authzUri" "{\"resource\": \"authz\", \"status\":\"deactivated\"}" ; then if ! _send_signed_request "$authzUri" "{\"resource\": \"authz\", \"status\":\"deactivated\"}"; then
_err "Can not deactivate $_vtype." _err "Can not deactivate $_vtype."
return 1 return 1
fi fi
_info "Deactivate: $_vtype success." _info "Deactivate: $_vtype success."
done done
_debug "$_d_i" _debug "$_d_i"
if [ "$_d_i" -lt "$_d_max_retry" ] ; then if [ "$_d_i" -lt "$_d_max_retry" ]; then
_info "Deactivated success!" _info "Deactivated success!"
else else
_err "Deactivate failed." _err "Deactivate failed."
...@@ -3256,16 +3486,15 @@ deactivate() { ...@@ -3256,16 +3486,15 @@ deactivate() {
_d_type="$2" _d_type="$2"
_initpath _initpath
_debug _d_domain_list "$_d_domain_list" _debug _d_domain_list "$_d_domain_list"
if [ -z "$(echo $_d_domain_list | cut -d , -f 1 )" ] ; then if [ -z "$(echo $_d_domain_list | cut -d , -f 1)" ]; then
_usage "Usage: $PROJECT_ENTRY --deactivate -d domain.com [-d domain.com]" _usage "Usage: $PROJECT_ENTRY --deactivate -d domain.com [-d domain.com]"
return 1 return 1
fi fi
for _d_dm in $(echo "$_d_domain_list" | tr ',' ' ' ) ; for _d_dm in $(echo "$_d_domain_list" | tr ',' ' '); do
do if [ -z "$_d_dm" ] || [ "$_d_dm" = "$NO_VALUE" ]; then
if [ -z "$_d_dm" ] || [ "$_d_dm" = "$NO_VALUE" ] ; then
continue continue
fi fi
if ! _deactivate "$_d_dm" $_d_type ; then if ! _deactivate "$_d_dm" "$_d_type"; then
return 1 return 1
fi fi
done done
...@@ -3273,7 +3502,7 @@ deactivate() { ...@@ -3273,7 +3502,7 @@ deactivate() {
# Detect profile file if not specified as environment variable # Detect profile file if not specified as environment variable
_detect_profile() { _detect_profile() {
if [ -n "$PROFILE" -a -f "$PROFILE" ] ; then if [ -n "$PROFILE" -a -f "$PROFILE" ]; then
echo "$PROFILE" echo "$PROFILE"
return return
fi fi
...@@ -3281,36 +3510,36 @@ _detect_profile() { ...@@ -3281,36 +3510,36 @@ _detect_profile() {
DETECTED_PROFILE='' DETECTED_PROFILE=''
SHELLTYPE="$(basename "/$SHELL")" SHELLTYPE="$(basename "/$SHELL")"
if [ "$SHELLTYPE" = "bash" ] ; then if [ "$SHELLTYPE" = "bash" ]; then
if [ -f "$HOME/.bashrc" ] ; then if [ -f "$HOME/.bashrc" ]; then
DETECTED_PROFILE="$HOME/.bashrc" DETECTED_PROFILE="$HOME/.bashrc"
elif [ -f "$HOME/.bash_profile" ] ; then elif [ -f "$HOME/.bash_profile" ]; then
DETECTED_PROFILE="$HOME/.bash_profile" DETECTED_PROFILE="$HOME/.bash_profile"
fi fi
elif [ "$SHELLTYPE" = "zsh" ] ; then elif [ "$SHELLTYPE" = "zsh" ]; then
DETECTED_PROFILE="$HOME/.zshrc" DETECTED_PROFILE="$HOME/.zshrc"
fi fi
if [ -z "$DETECTED_PROFILE" ] ; then if [ -z "$DETECTED_PROFILE" ]; then
if [ -f "$HOME/.profile" ] ; then if [ -f "$HOME/.profile" ]; then
DETECTED_PROFILE="$HOME/.profile" DETECTED_PROFILE="$HOME/.profile"
elif [ -f "$HOME/.bashrc" ] ; then elif [ -f "$HOME/.bashrc" ]; then
DETECTED_PROFILE="$HOME/.bashrc" DETECTED_PROFILE="$HOME/.bashrc"
elif [ -f "$HOME/.bash_profile" ] ; then elif [ -f "$HOME/.bash_profile" ]; then
DETECTED_PROFILE="$HOME/.bash_profile" DETECTED_PROFILE="$HOME/.bash_profile"
elif [ -f "$HOME/.zshrc" ] ; then elif [ -f "$HOME/.zshrc" ]; then
DETECTED_PROFILE="$HOME/.zshrc" DETECTED_PROFILE="$HOME/.zshrc"
fi fi
fi fi
if [ ! -z "$DETECTED_PROFILE" ] ; then if [ ! -z "$DETECTED_PROFILE" ]; then
echo "$DETECTED_PROFILE" echo "$DETECTED_PROFILE"
fi fi
} }
_initconf() { _initconf() {
_initpath _initpath
if [ ! -f "$ACCOUNT_CONF_PATH" ] ; then if [ ! -f "$ACCOUNT_CONF_PATH" ]; then
echo "#ACCOUNT_CONF_PATH=xxxx echo "#ACCOUNT_CONF_PATH=xxxx
#Account configurations: #Account configurations:
...@@ -3334,7 +3563,7 @@ _initconf() { ...@@ -3334,7 +3563,7 @@ _initconf() {
#USER_AGENT=\"$USER_AGENT\" #USER_AGENT=\"$USER_AGENT\"
#USER_PATH="" #USER_PATH=
#dns api #dns api
####################### #######################
...@@ -3375,75 +3604,75 @@ _initconf() { ...@@ -3375,75 +3604,75 @@ _initconf() {
#PDNS_Token=\"0123456789ABCDEF\" #PDNS_Token=\"0123456789ABCDEF\"
#PDNS_Ttl=60 #PDNS_Ttl=60
" > $ACCOUNT_CONF_PATH " >"$ACCOUNT_CONF_PATH"
fi fi
} }
# nocron # nocron
_precheck() { _precheck() {
_nocron="$1" _nocron="$1"
if ! _exists "curl" && ! _exists "wget"; then if ! _exists "curl" && ! _exists "wget"; then
_err "Please install curl or wget first, we need to access http resources." _err "Please install curl or wget first, we need to access http resources."
return 1 return 1
fi fi
if [ -z "$_nocron" ] ; then if [ -z "$_nocron" ]; then
if ! _exists "crontab" ; then if ! _exists "crontab"; then
_err "It is recommended to install crontab first. try to install 'cron, crontab, crontabs or vixie-cron'." _err "It is recommended to install crontab first. try to install 'cron, crontab, crontabs or vixie-cron'."
_err "We need to set cron job to renew the certs automatically." _err "We need to set cron job to renew the certs automatically."
_err "Otherwise, your certs will not be able to be renewed automatically." _err "Otherwise, your certs will not be able to be renewed automatically."
if [ -z "$FORCE" ] ; then if [ -z "$FORCE" ]; then
_err "Please add '--force' and try install again to go without crontab." _err "Please add '--force' and try install again to go without crontab."
_err "./$PROJECT_ENTRY --install --force" _err "./$PROJECT_ENTRY --install --force"
return 1 return 1
fi fi
fi fi
fi fi
if ! _exists "openssl" ; then if ! _exists "openssl"; then
_err "Please install openssl first." _err "Please install openssl first."
_err "We need openssl to generate keys." _err "We need openssl to generate keys."
return 1 return 1
fi fi
if ! _exists "nc" ; then if ! _exists "nc"; then
_err "It is recommended to install nc first, try to install 'nc' or 'netcat'." _err "It is recommended to install nc first, try to install 'nc' or 'netcat'."
_err "We use nc for standalone server if you use standalone mode." _err "We use nc for standalone server if you use standalone mode."
_err "If you don't use standalone mode, just ignore this warning." _err "If you don't use standalone mode, just ignore this warning."
fi fi
return 0 return 0
} }
_setShebang() { _setShebang() {
_file="$1" _file="$1"
_shebang="$2" _shebang="$2"
if [ -z "$_shebang" ] ; then if [ -z "$_shebang" ]; then
_usage "Usage: file shebang" _usage "Usage: file shebang"
return 1 return 1
fi fi
cp "$_file" "$_file.tmp" cp "$_file" "$_file.tmp"
echo "$_shebang" > "$_file" echo "$_shebang" >"$_file"
sed -n 2,99999p "$_file.tmp" >> "$_file" sed -n 2,99999p "$_file.tmp" >>"$_file"
rm -f "$_file.tmp" rm -f "$_file.tmp"
} }
_installalias() { _installalias() {
_initpath _initpath
_envfile="$LE_WORKING_DIR/$PROJECT_ENTRY.env" _envfile="$LE_WORKING_DIR/$PROJECT_ENTRY.env"
if [ "$_upgrading" ] && [ "$_upgrading" = "1" ] ; then if [ "$_upgrading" ] && [ "$_upgrading" = "1" ]; then
echo "$(cat $_envfile)" | sed "s|^LE_WORKING_DIR.*$||" > "$_envfile" echo "$(cat "$_envfile")" | sed "s|^LE_WORKING_DIR.*$||" >"$_envfile"
echo "$(cat $_envfile)" | sed "s|^alias le.*$||" > "$_envfile" echo "$(cat "$_envfile")" | sed "s|^alias le.*$||" >"$_envfile"
echo "$(cat $_envfile)" | sed "s|^alias le.sh.*$||" > "$_envfile" echo "$(cat "$_envfile")" | sed "s|^alias le.sh.*$||" >"$_envfile"
fi fi
_setopt "$_envfile" "export LE_WORKING_DIR" "=" "\"$LE_WORKING_DIR\"" _setopt "$_envfile" "export LE_WORKING_DIR" "=" "\"$LE_WORKING_DIR\""
_setopt "$_envfile" "alias $PROJECT_ENTRY" "=" "\"$LE_WORKING_DIR/$PROJECT_ENTRY\"" _setopt "$_envfile" "alias $PROJECT_ENTRY" "=" "\"$LE_WORKING_DIR/$PROJECT_ENTRY\""
_profile="$(_detect_profile)" _profile="$(_detect_profile)"
if [ "$_profile" ] ; then if [ "$_profile" ]; then
_debug "Found profile: $_profile" _debug "Found profile: $_profile"
_info "Installing alias to '$_profile'" _info "Installing alias to '$_profile'"
_setopt "$_profile" ". \"$_envfile\"" _setopt "$_profile" ". \"$_envfile\""
...@@ -3451,25 +3680,24 @@ _installalias() { ...@@ -3451,25 +3680,24 @@ _installalias() {
else else
_info "No profile is found, you will need to go into $LE_WORKING_DIR to use $PROJECT_NAME" _info "No profile is found, you will need to go into $LE_WORKING_DIR to use $PROJECT_NAME"
fi fi
#for csh #for csh
_cshfile="$LE_WORKING_DIR/$PROJECT_ENTRY.csh" _cshfile="$LE_WORKING_DIR/$PROJECT_ENTRY.csh"
_csh_profile="$HOME/.cshrc" _csh_profile="$HOME/.cshrc"
if [ -f "$_csh_profile" ] ; then if [ -f "$_csh_profile" ]; then
_info "Installing alias to '$_csh_profile'" _info "Installing alias to '$_csh_profile'"
_setopt "$_cshfile" "setenv LE_WORKING_DIR" " " "\"$LE_WORKING_DIR\"" _setopt "$_cshfile" "setenv LE_WORKING_DIR" " " "\"$LE_WORKING_DIR\""
_setopt "$_cshfile" "alias $PROJECT_ENTRY" " " "\"$LE_WORKING_DIR/$PROJECT_ENTRY\"" _setopt "$_cshfile" "alias $PROJECT_ENTRY" " " "\"$LE_WORKING_DIR/$PROJECT_ENTRY\""
_setopt "$_csh_profile" "source \"$_cshfile\"" _setopt "$_csh_profile" "source \"$_cshfile\""
fi fi
#for tcsh #for tcsh
_tcsh_profile="$HOME/.tcshrc" _tcsh_profile="$HOME/.tcshrc"
if [ -f "$_tcsh_profile" ] ; then if [ -f "$_tcsh_profile" ]; then
_info "Installing alias to '$_tcsh_profile'" _info "Installing alias to '$_tcsh_profile'"
_setopt "$_cshfile" "setenv LE_WORKING_DIR" " " "\"$LE_WORKING_DIR\"" _setopt "$_cshfile" "setenv LE_WORKING_DIR" " " "\"$LE_WORKING_DIR\""
_setopt "$_cshfile" "alias $PROJECT_ENTRY" " " "\"$LE_WORKING_DIR/$PROJECT_ENTRY\"" _setopt "$_cshfile" "alias $PROJECT_ENTRY" " " "\"$LE_WORKING_DIR/$PROJECT_ENTRY\""
_setopt "$_tcsh_profile" "source \"$_cshfile\"" _setopt "$_tcsh_profile" "source \"$_cshfile\""
fi fi
} }
...@@ -3477,36 +3705,35 @@ _installalias() { ...@@ -3477,36 +3705,35 @@ _installalias() {
# nocron # nocron
install() { install() {
if [ -z "$LE_WORKING_DIR" ] ; then if [ -z "$LE_WORKING_DIR" ]; then
LE_WORKING_DIR="$DEFAULT_INSTALL_HOME" LE_WORKING_DIR="$DEFAULT_INSTALL_HOME"
fi fi
_nocron="$1" _nocron="$1"
if ! _initpath ; then if ! _initpath; then
_err "Install failed." _err "Install failed."
return 1 return 1
fi fi
if [ "$_nocron" ] ; then if [ "$_nocron" ]; then
_debug "Skip install cron job" _debug "Skip install cron job"
fi fi
if ! _precheck "$_nocron" ; then if ! _precheck "$_nocron"; then
_err "Pre-check failed, can not install." _err "Pre-check failed, can not install."
return 1 return 1
fi fi
#convert from le #convert from le
if [ -d "$HOME/.le" ] ; then if [ -d "$HOME/.le" ]; then
for envfile in "le.env" "le.sh.env" for envfile in "le.env" "le.sh.env"; do
do if [ -f "$HOME/.le/$envfile" ]; then
if [ -f "$HOME/.le/$envfile" ] ; then if grep "le.sh" "$HOME/.le/$envfile" >/dev/null; then
if grep "le.sh" "$HOME/.le/$envfile" >/dev/null ; then _upgrading="1"
_upgrading="1" _info "You are upgrading from le.sh"
_info "You are upgrading from le.sh" _info "Renaming \"$HOME/.le\" to $LE_WORKING_DIR"
_info "Renaming \"$HOME/.le\" to $LE_WORKING_DIR" mv "$HOME/.le" "$LE_WORKING_DIR"
mv "$HOME/.le" "$LE_WORKING_DIR" mv "$LE_WORKING_DIR/$envfile" "$LE_WORKING_DIR/$PROJECT_ENTRY.env"
mv "$LE_WORKING_DIR/$envfile" "$LE_WORKING_DIR/$PROJECT_ENTRY.env" break
break;
fi fi
fi fi
done done
...@@ -3514,16 +3741,16 @@ install() { ...@@ -3514,16 +3741,16 @@ install() {
_info "Installing to $LE_WORKING_DIR" _info "Installing to $LE_WORKING_DIR"
if ! mkdir -p "$LE_WORKING_DIR" ; then if ! mkdir -p "$LE_WORKING_DIR"; then
_err "Can not create working dir: $LE_WORKING_DIR" _err "Can not create working dir: $LE_WORKING_DIR"
return 1 return 1
fi fi
chmod 700 "$LE_WORKING_DIR" chmod 700 "$LE_WORKING_DIR"
cp $PROJECT_ENTRY "$LE_WORKING_DIR/" && chmod +x "$LE_WORKING_DIR/$PROJECT_ENTRY" cp "$PROJECT_ENTRY" "$LE_WORKING_DIR/" && chmod +x "$LE_WORKING_DIR/$PROJECT_ENTRY"
if [ "$?" != "0" ] ; then if [ "$?" != "0" ]; then
_err "Install failed, can not copy $PROJECT_ENTRY" _err "Install failed, can not copy $PROJECT_ENTRY"
return 1 return 1
fi fi
...@@ -3532,43 +3759,42 @@ install() { ...@@ -3532,43 +3759,42 @@ install() {
_installalias _installalias
for subf in $_SUB_FOLDERS ; do for subf in $_SUB_FOLDERS; do
if [ -d "$subf" ] ; then if [ -d "$subf" ]; then
mkdir -p $LE_WORKING_DIR/$subf mkdir -p "$LE_WORKING_DIR/$subf"
cp $subf/* $LE_WORKING_DIR/$subf/ cp "$subf"/* "$LE_WORKING_DIR"/"$subf"/
fi fi
done done
if [ ! -f "$ACCOUNT_CONF_PATH" ]; then
if [ ! -f "$ACCOUNT_CONF_PATH" ] ; then
_initconf _initconf
fi fi
if [ "$_DEFAULT_ACCOUNT_CONF_PATH" != "$ACCOUNT_CONF_PATH" ] ; then if [ "$_DEFAULT_ACCOUNT_CONF_PATH" != "$ACCOUNT_CONF_PATH" ]; then
_setopt "$_DEFAULT_ACCOUNT_CONF_PATH" "ACCOUNT_CONF_PATH" "=" "\"$ACCOUNT_CONF_PATH\"" _setopt "$_DEFAULT_ACCOUNT_CONF_PATH" "ACCOUNT_CONF_PATH" "=" "\"$ACCOUNT_CONF_PATH\""
fi fi
if [ "$_DEFAULT_CERT_HOME" != "$CERT_HOME" ] ; then if [ "$_DEFAULT_CERT_HOME" != "$CERT_HOME" ]; then
_saveaccountconf "CERT_HOME" "$CERT_HOME" _saveaccountconf "CERT_HOME" "$CERT_HOME"
fi fi
if [ "$_DEFAULT_ACCOUNT_KEY_PATH" != "$ACCOUNT_KEY_PATH" ] ; then if [ "$_DEFAULT_ACCOUNT_KEY_PATH" != "$ACCOUNT_KEY_PATH" ]; then
_saveaccountconf "ACCOUNT_KEY_PATH" "$ACCOUNT_KEY_PATH" _saveaccountconf "ACCOUNT_KEY_PATH" "$ACCOUNT_KEY_PATH"
fi fi
if [ -z "$_nocron" ] ; then if [ -z "$_nocron" ]; then
installcronjob installcronjob
fi fi
if [ -z "$NO_DETECT_SH" ] ; then if [ -z "$NO_DETECT_SH" ]; then
#Modify shebang #Modify shebang
if _exists bash ; then if _exists bash; then
_info "Good, bash is found, so change the shebang to use bash as prefered." _info "Good, bash is found, so change the shebang to use bash as prefered."
_shebang='#!/usr/bin/env bash' _shebang='#!/usr/bin/env bash'
_setShebang "$LE_WORKING_DIR/$PROJECT_ENTRY" "$_shebang" _setShebang "$LE_WORKING_DIR/$PROJECT_ENTRY" "$_shebang"
for subf in $_SUB_FOLDERS ; do for subf in $_SUB_FOLDERS; do
if [ -d "$LE_WORKING_DIR/$subf" ] ; then if [ -d "$LE_WORKING_DIR/$subf" ]; then
for _apifile in "$LE_WORKING_DIR/$subf/"*.sh ; do for _apifile in "$LE_WORKING_DIR/$subf/"*.sh; do
_setShebang "$_apifile" "$_shebang" _setShebang "$_apifile" "$_shebang"
done done
fi fi
...@@ -3582,14 +3808,14 @@ install() { ...@@ -3582,14 +3808,14 @@ install() {
# nocron # nocron
uninstall() { uninstall() {
_nocron="$1" _nocron="$1"
if [ -z "$_nocron" ] ; then if [ -z "$_nocron" ]; then
uninstallcronjob uninstallcronjob
fi fi
_initpath _initpath
_uninstallalias _uninstallalias
rm -f $LE_WORKING_DIR/$PROJECT_ENTRY rm -f "$LE_WORKING_DIR/$PROJECT_ENTRY"
_info "The keys and certs are in $LE_WORKING_DIR, you can remove them by yourself." _info "The keys and certs are in $LE_WORKING_DIR, you can remove them by yourself."
} }
...@@ -3598,24 +3824,24 @@ _uninstallalias() { ...@@ -3598,24 +3824,24 @@ _uninstallalias() {
_initpath _initpath
_profile="$(_detect_profile)" _profile="$(_detect_profile)"
if [ "$_profile" ] ; then if [ "$_profile" ]; then
_info "Uninstalling alias from: '$_profile'" _info "Uninstalling alias from: '$_profile'"
text="$(cat $_profile)" text="$(cat "$_profile")"
echo "$text" | sed "s|^.*\"$LE_WORKING_DIR/$PROJECT_NAME.env\"$||" > "$_profile" echo "$text" | sed "s|^.*\"$LE_WORKING_DIR/$PROJECT_NAME.env\"$||" >"$_profile"
fi fi
_csh_profile="$HOME/.cshrc" _csh_profile="$HOME/.cshrc"
if [ -f "$_csh_profile" ] ; then if [ -f "$_csh_profile" ]; then
_info "Uninstalling alias from: '$_csh_profile'" _info "Uninstalling alias from: '$_csh_profile'"
text="$(cat $_csh_profile)" text="$(cat "$_csh_profile")"
echo "$text" | sed "s|^.*\"$LE_WORKING_DIR/$PROJECT_NAME.csh\"$||" > "$_csh_profile" echo "$text" | sed "s|^.*\"$LE_WORKING_DIR/$PROJECT_NAME.csh\"$||" >"$_csh_profile"
fi fi
_tcsh_profile="$HOME/.tcshrc" _tcsh_profile="$HOME/.tcshrc"
if [ -f "$_tcsh_profile" ] ; then if [ -f "$_tcsh_profile" ]; then
_info "Uninstalling alias from: '$_csh_profile'" _info "Uninstalling alias from: '$_csh_profile'"
text="$(cat $_tcsh_profile)" text="$(cat "$_tcsh_profile")"
echo "$text" | sed "s|^.*\"$LE_WORKING_DIR/$PROJECT_NAME.csh\"$||" > "$_tcsh_profile" echo "$text" | sed "s|^.*\"$LE_WORKING_DIR/$PROJECT_NAME.csh\"$||" >"$_tcsh_profile"
fi fi
} }
...@@ -3623,20 +3849,20 @@ _uninstallalias() { ...@@ -3623,20 +3849,20 @@ _uninstallalias() {
cron() { cron() {
IN_CRON=1 IN_CRON=1
_initpath _initpath
if [ "$AUTO_UPGRADE" = "1" ] ; then if [ "$AUTO_UPGRADE" = "1" ]; then
export LE_WORKING_DIR export LE_WORKING_DIR
( (
if ! upgrade ; then if ! upgrade; then
_err "Cron:Upgrade failed!" _err "Cron:Upgrade failed!"
return 1 return 1
fi fi
) )
. $LE_WORKING_DIR/$PROJECT_ENTRY >/dev/null . "$LE_WORKING_DIR/$PROJECT_ENTRY" >/dev/null
if [ -t 1 ] ; then if [ -t 1 ]; then
__INTERACTIVE="1" __INTERACTIVE="1"
fi fi
_info "Auto upgraded to: $VER" _info "Auto upgraded to: $VER"
fi fi
renewAll renewAll
...@@ -3739,31 +3965,31 @@ Parameters: ...@@ -3739,31 +3965,31 @@ Parameters:
_installOnline() { _installOnline() {
_info "Installing from online archive." _info "Installing from online archive."
_nocron="$1" _nocron="$1"
if [ ! "$BRANCH" ] ; then if [ ! "$BRANCH" ]; then
BRANCH="master" BRANCH="master"
fi fi
target="$PROJECT/archive/$BRANCH.tar.gz" target="$PROJECT/archive/$BRANCH.tar.gz"
_info "Downloading $target" _info "Downloading $target"
localname="$BRANCH.tar.gz" localname="$BRANCH.tar.gz"
if ! _get "$target" > $localname ; then if ! _get "$target" >$localname; then
_err "Download error." _err "Download error."
return 1 return 1
fi fi
( (
_info "Extracting $localname" _info "Extracting $localname"
tar xzf $localname tar xzf $localname
cd "$PROJECT_NAME-$BRANCH" cd "$PROJECT_NAME-$BRANCH"
chmod +x $PROJECT_ENTRY chmod +x $PROJECT_ENTRY
if ./$PROJECT_ENTRY install "$_nocron" ; then if ./$PROJECT_ENTRY install "$_nocron"; then
_info "Install success!" _info "Install success!"
fi fi
cd .. cd ..
rm -rf "$PROJECT_NAME-$BRANCH" rm -rf "$PROJECT_NAME-$BRANCH"
rm -f "$localname" rm -f "$localname"
) )
} }
...@@ -3773,7 +3999,7 @@ upgrade() { ...@@ -3773,7 +3999,7 @@ upgrade() {
export LE_WORKING_DIR export LE_WORKING_DIR
cd "$LE_WORKING_DIR" cd "$LE_WORKING_DIR"
_installOnline "nocron" _installOnline "nocron"
) ; then ); then
_info "Upgrade success!" _info "Upgrade success!"
exit 0 exit 0
else else
...@@ -3783,24 +4009,24 @@ upgrade() { ...@@ -3783,24 +4009,24 @@ upgrade() {
} }
_processAccountConf() { _processAccountConf() {
if [ "$_useragent" ] ; then if [ "$_useragent" ]; then
_saveaccountconf "USER_AGENT" "$_useragent" _saveaccountconf "USER_AGENT" "$_useragent"
elif [ "$USER_AGENT" ] && [ "$USER_AGENT" != "$DEFAULT_USER_AGENT" ] ; then elif [ "$USER_AGENT" ] && [ "$USER_AGENT" != "$DEFAULT_USER_AGENT" ]; then
_saveaccountconf "USER_AGENT" "$USER_AGENT" _saveaccountconf "USER_AGENT" "$USER_AGENT"
fi fi
if [ "$_accountemail" ] ; then if [ "$_accountemail" ]; then
_saveaccountconf "ACCOUNT_EMAIL" "$_accountemail" _saveaccountconf "ACCOUNT_EMAIL" "$_accountemail"
elif [ "$ACCOUNT_EMAIL" ] && [ "$ACCOUNT_EMAIL" != "$DEFAULT_ACCOUNT_EMAIL" ] ; then elif [ "$ACCOUNT_EMAIL" ] && [ "$ACCOUNT_EMAIL" != "$DEFAULT_ACCOUNT_EMAIL" ]; then
_saveaccountconf "ACCOUNT_EMAIL" "$ACCOUNT_EMAIL" _saveaccountconf "ACCOUNT_EMAIL" "$ACCOUNT_EMAIL"
fi fi
if [ "$_auto_upgrade" ] ; then if [ "$_auto_upgrade" ]; then
_saveaccountconf "AUTO_UPGRADE" "$_auto_upgrade" _saveaccountconf "AUTO_UPGRADE" "$_auto_upgrade"
elif [ "$AUTO_UPGRADE" ] ; then elif [ "$AUTO_UPGRADE" ]; then
_saveaccountconf "AUTO_UPGRADE" "$AUTO_UPGRADE" _saveaccountconf "AUTO_UPGRADE" "$AUTO_UPGRADE"
fi fi
} }
_process() { _process() {
...@@ -3826,7 +4052,7 @@ _process() { ...@@ -3826,7 +4052,7 @@ _process() {
_dnssleep="" _dnssleep=""
_listraw="" _listraw=""
_stopRenewOnError="" _stopRenewOnError=""
_insecure="" #_insecure=""
_ca_bundle="" _ca_bundle=""
_nocron="" _nocron=""
_ecc="" _ecc=""
...@@ -3842,342 +4068,339 @@ _process() { ...@@ -3842,342 +4068,339 @@ _process() {
_auto_upgrade="" _auto_upgrade=""
_listen_v4="" _listen_v4=""
_listen_v6="" _listen_v6=""
while [ ${#} -gt 0 ] ; do while [ ${#} -gt 0 ]; do
case "${1}" in case "${1}" in
--help|-h) --help | -h)
showhelp showhelp
return return
;; ;;
--version|-v) --version | -v)
version version
return return
;; ;;
--install) --install)
_CMD="install" _CMD="install"
;; ;;
--uninstall) --uninstall)
_CMD="uninstall" _CMD="uninstall"
;; ;;
--upgrade) --upgrade)
_CMD="upgrade" _CMD="upgrade"
;; ;;
--issue) --issue)
_CMD="issue" _CMD="issue"
;; ;;
--deploy) --deploy)
_CMD="deploy" _CMD="deploy"
;; ;;
--signcsr) --signcsr)
_CMD="signcsr" _CMD="signcsr"
;; ;;
--showcsr) --showcsr)
_CMD="showcsr" _CMD="showcsr"
;; ;;
--installcert|-i) --installcert | -i)
_CMD="installcert" _CMD="installcert"
;; ;;
--renew|-r) --renew | -r)
_CMD="renew" _CMD="renew"
;; ;;
--renewAll|--renewall) --renewAll | --renewall)
_CMD="renewAll" _CMD="renewAll"
;; ;;
--revoke) --revoke)
_CMD="revoke" _CMD="revoke"
;; ;;
--list) --list)
_CMD="list" _CMD="list"
;; ;;
--installcronjob) --installcronjob)
_CMD="installcronjob" _CMD="installcronjob"
;; ;;
--uninstallcronjob) --uninstallcronjob)
_CMD="uninstallcronjob" _CMD="uninstallcronjob"
;; ;;
--cron) --cron)
_CMD="cron" _CMD="cron"
;; ;;
--toPkcs) --toPkcs)
_CMD="toPkcs" _CMD="toPkcs"
;; ;;
--createAccountKey|--createaccountkey|-cak) --createAccountKey | --createaccountkey | -cak)
_CMD="createAccountKey" _CMD="createAccountKey"
;; ;;
--createDomainKey|--createdomainkey|-cdk) --createDomainKey | --createdomainkey | -cdk)
_CMD="createDomainKey" _CMD="createDomainKey"
;; ;;
--createCSR|--createcsr|-ccr) --createCSR | --createcsr | -ccr)
_CMD="createCSR" _CMD="createCSR"
;; ;;
--deactivate) --deactivate)
_CMD="deactivate" _CMD="deactivate"
;; ;;
--updateaccount) --updateaccount)
_CMD="updateaccount" _CMD="updateaccount"
;; ;;
--registeraccount) --registeraccount)
_CMD="registeraccount" _CMD="registeraccount"
;; ;;
--domain|-d) --domain | -d)
_dvalue="$2" _dvalue="$2"
if [ "$_dvalue" ] ; then if [ "$_dvalue" ]; then
if _startswith "$_dvalue" "-" ; then if _startswith "$_dvalue" "-"; then
_err "'$_dvalue' is not a valid domain for parameter '$1'" _err "'$_dvalue' is not a valid domain for parameter '$1'"
return 1 return 1
fi fi
if _is_idn "$_dvalue" && ! _exists idn ; then if _is_idn "$_dvalue" && ! _exists idn; then
_err "It seems that $_dvalue is an IDN( Internationalized Domain Names), please install 'idn' command first." _err "It seems that $_dvalue is an IDN( Internationalized Domain Names), please install 'idn' command first."
return 1 return 1
fi fi
if [ -z "$_domain" ] ; then if [ -z "$_domain" ]; then
_domain="$_dvalue" _domain="$_dvalue"
else else
if [ "$_altdomains" = "$NO_VALUE" ] ; then if [ "$_altdomains" = "$NO_VALUE" ]; then
_altdomains="$_dvalue" _altdomains="$_dvalue"
else else
_altdomains="$_altdomains,$_dvalue" _altdomains="$_altdomains,$_dvalue"
fi fi
fi fi
fi fi
shift shift
;; ;;
--force|-f) --force | -f)
FORCE="1" FORCE="1"
;; ;;
--staging|--test) --staging | --test)
STAGE="1" STAGE="1"
;; ;;
--debug) --debug)
if [ -z "$2" ] || _startswith "$2" "-" ; then if [ -z "$2" ] || _startswith "$2" "-"; then
DEBUG="1" DEBUG="1"
else else
DEBUG="$2" DEBUG="$2"
shift shift
fi fi
;; ;;
--webroot|-w) --webroot | -w)
wvalue="$2" wvalue="$2"
if [ -z "$_webroot" ] ; then if [ -z "$_webroot" ]; then
_webroot="$wvalue" _webroot="$wvalue"
else else
_webroot="$_webroot,$wvalue" _webroot="$_webroot,$wvalue"
fi fi
shift shift
;; ;;
--standalone) --standalone)
wvalue="$NO_VALUE" wvalue="$NO_VALUE"
if [ -z "$_webroot" ] ; then if [ -z "$_webroot" ]; then
_webroot="$wvalue" _webroot="$wvalue"
else else
_webroot="$_webroot,$wvalue" _webroot="$_webroot,$wvalue"
fi fi
;; ;;
--local-address) --local-address)
lvalue="$2" lvalue="$2"
_local_address="$_local_address$lvalue," _local_address="$_local_address$lvalue,"
shift shift
;; ;;
--apache) --apache)
wvalue="apache" wvalue="apache"
if [ -z "$_webroot" ] ; then if [ -z "$_webroot" ]; then
_webroot="$wvalue" _webroot="$wvalue"
else else
_webroot="$_webroot,$wvalue" _webroot="$_webroot,$wvalue"
fi fi
;; ;;
--tls) --tls)
wvalue="$W_TLS" wvalue="$W_TLS"
if [ -z "$_webroot" ] ; then if [ -z "$_webroot" ]; then
_webroot="$wvalue" _webroot="$wvalue"
else else
_webroot="$_webroot,$wvalue" _webroot="$_webroot,$wvalue"
fi fi
;; ;;
--dns) --dns)
wvalue="dns" wvalue="dns"
if ! _startswith "$2" "-" ; then if ! _startswith "$2" "-"; then
wvalue="$2" wvalue="$2"
shift shift
fi fi
if [ -z "$_webroot" ] ; then if [ -z "$_webroot" ]; then
_webroot="$wvalue" _webroot="$wvalue"
else else
_webroot="$_webroot,$wvalue" _webroot="$_webroot,$wvalue"
fi fi
;; ;;
--dnssleep) --dnssleep)
_dnssleep="$2" _dnssleep="$2"
Le_DNSSleep="$_dnssleep" Le_DNSSleep="$_dnssleep"
shift shift
;; ;;
--keylength|-k) --keylength | -k)
_keylength="$2" _keylength="$2"
if [ "$_accountkeylength" = "$NO_VALUE" ] ; then
_accountkeylength="$2"
fi
shift shift
;; ;;
--accountkeylength|-ak) --accountkeylength | -ak)
_accountkeylength="$2" _accountkeylength="$2"
shift shift
;; ;;
--certpath) --certpath)
_certpath="$2" _certpath="$2"
shift shift
;; ;;
--keypath) --keypath)
_keypath="$2" _keypath="$2"
shift shift
;; ;;
--capath) --capath)
_capath="$2" _capath="$2"
shift shift
;; ;;
--fullchainpath) --fullchainpath)
_fullchainpath="$2" _fullchainpath="$2"
shift shift
;; ;;
--reloadcmd|--reloadCmd) --reloadcmd | --reloadCmd)
_reloadcmd="$2" _reloadcmd="$2"
shift shift
;; ;;
--password) --password)
_password="$2" _password="$2"
shift shift
;; ;;
--accountconf) --accountconf)
_accountconf="$2" _accountconf="$2"
ACCOUNT_CONF_PATH="$_accountconf" ACCOUNT_CONF_PATH="$_accountconf"
shift shift
;; ;;
--home) --home)
LE_WORKING_DIR="$2" LE_WORKING_DIR="$2"
shift shift
;; ;;
--certhome) --certhome)
_certhome="$2" _certhome="$2"
CERT_HOME="$_certhome" CERT_HOME="$_certhome"
shift shift
;; ;;
--useragent) --useragent)
_useragent="$2" _useragent="$2"
USER_AGENT="$_useragent" USER_AGENT="$_useragent"
shift shift
;; ;;
--accountemail ) --accountemail)
_accountemail="$2" _accountemail="$2"
ACCOUNT_EMAIL="$_accountemail" ACCOUNT_EMAIL="$_accountemail"
shift shift
;; ;;
--accountkey ) --accountkey)
_accountkey="$2" _accountkey="$2"
ACCOUNT_KEY_PATH="$_accountkey" ACCOUNT_KEY_PATH="$_accountkey"
shift shift
;; ;;
--days ) --days)
_days="$2" _days="$2"
Le_RenewalDays="$_days" Le_RenewalDays="$_days"
shift shift
;; ;;
--httpport ) --httpport)
_httpport="$2" _httpport="$2"
Le_HTTPPort="$_httpport" Le_HTTPPort="$_httpport"
shift shift
;; ;;
--tlsport ) --tlsport)
_tlsport="$2" _tlsport="$2"
Le_TLSPort="$_tlsport" Le_TLSPort="$_tlsport"
shift shift
;; ;;
--listraw ) --listraw)
_listraw="raw" _listraw="raw"
;; ;;
--stopRenewOnError|--stoprenewonerror|-se ) --stopRenewOnError | --stoprenewonerror | -se)
_stopRenewOnError="1" _stopRenewOnError="1"
;; ;;
--insecure) --insecure)
_insecure="1" #_insecure="1"
HTTPS_INSECURE="1" HTTPS_INSECURE="1"
;; ;;
--ca-bundle) --ca-bundle)
_ca_bundle="$(readlink -f $2)" _ca_bundle="$(readlink -f "$2")"
CA_BUNDLE="$_ca_bundle" CA_BUNDLE="$_ca_bundle"
shift shift
;; ;;
--nocron) --nocron)
_nocron="1" _nocron="1"
;; ;;
--ecc) --ecc)
_ecc="isEcc" _ecc="isEcc"
;; ;;
--csr) --csr)
_csr="$2" _csr="$2"
shift shift
;; ;;
--pre-hook) --pre-hook)
_pre_hook="$2" _pre_hook="$2"
shift shift
;; ;;
--post-hook) --post-hook)
_post_hook="$2" _post_hook="$2"
shift shift
;; ;;
--renew-hook) --renew-hook)
_renew_hook="$2" _renew_hook="$2"
shift shift
;; ;;
--deploy-hook) --deploy-hook)
_deploy_hook="$2" _deploy_hook="$2"
shift shift
;; ;;
--ocsp-must-staple|--ocsp) --ocsp-must-staple | --ocsp)
Le_OCSP_Stable="1" Le_OCSP_Stable="1"
;; ;;
--log|--logfile) --log | --logfile)
_log="1" _log="1"
_logfile="$2" _logfile="$2"
if _startswith "$_logfile" '-' ; then if _startswith "$_logfile" '-'; then
_logfile="" _logfile=""
else else
shift shift
fi fi
LOG_FILE="$_logfile" LOG_FILE="$_logfile"
if [ -z "$LOG_LEVEL" ] ; then if [ -z "$LOG_LEVEL" ]; then
LOG_LEVEL="$DEFAULT_LOG_LEVEL" LOG_LEVEL="$DEFAULT_LOG_LEVEL"
fi fi
;; ;;
--log-level) --log-level)
_log_level="$2" _log_level="$2"
LOG_LEVEL="$_log_level" LOG_LEVEL="$_log_level"
shift shift
;; ;;
--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
_auto_upgrade="1" _auto_upgrade="1"
else else
shift shift
fi fi
AUTO_UPGRADE="$_auto_upgrade" AUTO_UPGRADE="$_auto_upgrade"
;; ;;
--listen-v4) --listen-v4)
_listen_v4="1" _listen_v4="1"
Le_Listen_V4="$_listen_v4" Le_Listen_V4="$_listen_v4"
;; ;;
--listen-v6) --listen-v6)
_listen_v6="1" _listen_v6="1"
Le_Listen_V6="$_listen_v6" Le_Listen_V6="$_listen_v6"
;; ;;
*) *)
_err "Unknown parameter : $1" _err "Unknown parameter : $1"
return 1 return 1
;; ;;
...@@ -4186,27 +4409,29 @@ _process() { ...@@ -4186,27 +4409,29 @@ _process() {
shift 1 shift 1
done done
if [ "${_CMD}" != "install" ] ; then if [ "${_CMD}" != "install" ]; then
__initHome __initHome
if [ "$_log" ]; then if [ "$_log" ]; then
if [ -z "$_logfile" ] ; then if [ -z "$_logfile" ]; then
_logfile="$DEFAULT_LOG_FILE" _logfile="$DEFAULT_LOG_FILE"
fi fi
fi fi
if [ "$_logfile" ] ; then if [ "$_logfile" ]; then
_saveaccountconf "LOG_FILE" "$_logfile" _saveaccountconf "LOG_FILE" "$_logfile"
LOG_FILE="$_logfile" LOG_FILE="$_logfile"
fi fi
if [ "$_log_level" ] ; then if [ "$_log_level" ]; then
_saveaccountconf "LOG_LEVEL" "$_log_level" _saveaccountconf "LOG_LEVEL" "$_log_level"
LOG_LEVEL="$_log_level" LOG_LEVEL="$_log_level"
fi fi
_processAccountConf _processAccountConf
fi fi
if [ "$DEBUG" ] ; then _debug2 LE_WORKING_DIR "$LE_WORKING_DIR"
if [ "$DEBUG" ]; then
version version
fi fi
...@@ -4215,7 +4440,7 @@ _process() { ...@@ -4215,7 +4440,7 @@ _process() {
uninstall) uninstall "$_nocron" ;; uninstall) uninstall "$_nocron" ;;
upgrade) upgrade ;; upgrade) upgrade ;;
issue) issue)
issue "$_webroot" "$_domain" "$_altdomains" "$_keylength" "$_certpath" "$_keypath" "$_capath" "$_reloadcmd" "$_fullchainpath" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" issue "$_webroot" "$_domain" "$_altdomains" "$_keylength" "$_certpath" "$_keypath" "$_capath" "$_reloadcmd" "$_fullchainpath" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address"
;; ;;
deploy) deploy)
deploy "$_domain" "$_deploy_hook" "$_ecc" deploy "$_domain" "$_deploy_hook" "$_ecc"
...@@ -4229,63 +4454,63 @@ _process() { ...@@ -4229,63 +4454,63 @@ _process() {
installcert) installcert)
installcert "$_domain" "$_certpath" "$_keypath" "$_capath" "$_reloadcmd" "$_fullchainpath" "$_ecc" installcert "$_domain" "$_certpath" "$_keypath" "$_capath" "$_reloadcmd" "$_fullchainpath" "$_ecc"
;; ;;
renew) renew)
renew "$_domain" "$_ecc" renew "$_domain" "$_ecc"
;; ;;
renewAll) renewAll)
renewAll "$_stopRenewOnError" renewAll "$_stopRenewOnError"
;; ;;
revoke) revoke)
revoke "$_domain" "$_ecc" revoke "$_domain" "$_ecc"
;; ;;
deactivate) deactivate)
deactivate "$_domain,$_altdomains" deactivate "$_domain,$_altdomains"
;; ;;
registeraccount) registeraccount)
registeraccount registeraccount "$_accountkeylength"
;; ;;
updateaccount) updateaccount)
updateaccount updateaccount
;; ;;
list) list)
list "$_listraw" list "$_listraw"
;; ;;
installcronjob) installcronjob ;; installcronjob) installcronjob ;;
uninstallcronjob) uninstallcronjob ;; uninstallcronjob) uninstallcronjob ;;
cron) cron ;; cron) cron ;;
toPkcs) toPkcs)
toPkcs "$_domain" "$_password" "$_ecc" toPkcs "$_domain" "$_password" "$_ecc"
;; ;;
createAccountKey) createAccountKey)
createAccountKey "$_accountkeylength" createAccountKey "$_accountkeylength"
;; ;;
createDomainKey) createDomainKey)
createDomainKey "$_domain" "$_keylength" createDomainKey "$_domain" "$_keylength"
;; ;;
createCSR) createCSR)
createCSR "$_domain" "$_altdomains" "$_ecc" createCSR "$_domain" "$_altdomains" "$_ecc"
;; ;;
*) *)
_err "Invalid command: $_CMD" _err "Invalid command: $_CMD"
showhelp; showhelp
return 1 return 1
;; ;;
esac esac
_ret="$?" _ret="$?"
if [ "$_ret" != "0" ] ; then if [ "$_ret" != "0" ]; then
return $_ret return $_ret
fi fi
if [ "${_CMD}" = "install" ] ; then if [ "${_CMD}" = "install" ]; then
if [ "$_log" ] ; then if [ "$_log" ]; then
if [ -z "$LOG_FILE" ] ; then if [ -z "$LOG_FILE" ]; then
LOG_FILE="$DEFAULT_LOG_FILE" LOG_FILE="$DEFAULT_LOG_FILE"
fi fi
_saveaccountconf "LOG_FILE" "$LOG_FILE" _saveaccountconf "LOG_FILE" "$LOG_FILE"
fi fi
if [ "$_log_level" ] ; then if [ "$_log_level" ]; then
_saveaccountconf "LOG_LEVEL" "$_log_level" _saveaccountconf "LOG_LEVEL" "$_log_level"
fi fi
_processAccountConf _processAccountConf
...@@ -4293,24 +4518,15 @@ _process() { ...@@ -4293,24 +4518,15 @@ _process() {
} }
if [ "$INSTALLONLINE" ]; then
if [ "$INSTALLONLINE" ] ; then
INSTALLONLINE="" INSTALLONLINE=""
_installOnline $BRANCH _installOnline $BRANCH
exit exit
fi fi
main() { main() {
[ -z "$1" ] && showhelp && return [ -z "$1" ] && showhelp && return
if _startswith "$1" '-' ; then _process "$@"; else "$@";fi if _startswith "$1" '-'; then _process "$@"; else "$@"; fi
} }
main "$@" main "$@"
...@@ -6,8 +6,6 @@ ...@@ -6,8 +6,6 @@
#Which will be called by acme.sh to deploy the cert #Which will be called by acme.sh to deploy the cert
#returns 0 means success, otherwise error. #returns 0 means success, otherwise error.
######## Public functions ##################### ######## Public functions #####################
#domain keyfile certfile cafile fullchain #domain keyfile certfile cafile fullchain
...@@ -17,17 +15,14 @@ myapi_deploy() { ...@@ -17,17 +15,14 @@ myapi_deploy() {
_ccert="$3" _ccert="$3"
_cca="$4" _cca="$4"
_cfullchain="$5" _cfullchain="$5"
_debug _cdomain "$_cdomain" _debug _cdomain "$_cdomain"
_debug _ckey "$_ckey" _debug _ckey "$_ckey"
_debug _ccert "$_ccert" _debug _ccert "$_ccert"
_debug _cca "$_cca" _debug _cca "$_cca"
_debug _cfullchain "$_cfullchain" _debug _cfullchain "$_cfullchain"
_err "Not implemented yet" _err "Not implemented yet"
return 1 return 1
} }
...@@ -186,4 +186,41 @@ For more details, please check our sample script: [dns_myapi.sh](dns_myapi.sh) ...@@ -186,4 +186,41 @@ For more details, please check our sample script: [dns_myapi.sh](dns_myapi.sh)
https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api
## Use LuaDNS domain API
Get your API token at https://api.luadns.com/settings
```
export LUA_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
export LUA_Email="xxxx@sss.com"
```
To issue a cert:
```
acme.sh --issue --dns dns_lua --dnssleep 3 -d example.com -d www.example.com
```
The `LUA_Key` and `LUA_Email` will be saved in `~/.acme.sh/account.conf`, and will be reused when needed.
## Use DNSMadeEasy domain API
Get your API credentials at https://cp.dnsmadeeasy.com/account/info
```
export ME_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
export ME_Secret="qdfqsdfkjdskfj"
```
To issue a cert:
```
acme.sh --issue --dns dns_me --dnssleep 3 -d example.com -d www.example.com
```
The `ME_Key` and `ME_Secret` will be saved in `~/.acme.sh/account.conf`, and will be reused when needed.
#!/usr/bin/env sh #!/usr/bin/env sh
# #
#CF_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" #CF_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
# #
#CF_Email="xxxx@sss.com" #CF_Email="xxxx@sss.com"
CF_Api="https://api.cloudflare.com/client/v4" CF_Api="https://api.cloudflare.com/client/v4"
######## Public functions ##################### ######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_cf_add(){ dns_cf_add() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
if [ -z "$CF_Key" ] || [ -z "$CF_Email" ] ; then if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then
CF_Key=""
CF_Email=""
_err "You don't specify cloudflare api key and email yet." _err "You don't specify cloudflare api key and email yet."
_err "Please create you key and try again." _err "Please create you key and try again."
return 1 return 1
fi fi
#save the api key and email to the account conf file. #save the api key and email to the account conf file.
_saveaccountconf CF_Key "$CF_Key" _saveaccountconf CF_Key "$CF_Key"
_saveaccountconf CF_Email "$CF_Email" _saveaccountconf CF_Email "$CF_Email"
_debug "First detect the root zone" _debug "First detect the root zone"
if ! _get_root $fulldomain ; then if ! _get_root "$fulldomain"; then
_err "invalid domain" _err "invalid domain"
return 1 return 1
fi fi
_debug _domain_id "$_domain_id" _debug _domain_id "$_domain_id"
_debug _sub_domain "$_sub_domain" _debug _sub_domain "$_sub_domain"
_debug _domain "$_domain" _debug _domain "$_domain"
_debug "Getting txt records" _debug "Getting txt records"
_cf_rest GET "zones/${_domain_id}/dns_records?type=TXT&name=$fulldomain" _cf_rest GET "zones/${_domain_id}/dns_records?type=TXT&name=$fulldomain"
if ! printf "$response" | grep \"success\":true > /dev/null ; then if ! printf "%s" "$response" | grep \"success\":true >/dev/null; then
_err "Error" _err "Error"
return 1 return 1
fi fi
count=$(printf "%s\n" "$response" | _egrep_o \"count\":[^,]* | cut -d : -f 2) count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2)
_debug count "$count" _debug count "$count"
if [ "$count" = "0" ] ; then if [ "$count" = "0" ]; then
_info "Adding record" _info "Adding record"
if _cf_rest POST "zones/$_domain_id/dns_records" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then if _cf_rest POST "zones/$_domain_id/dns_records" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
if printf -- "%s" "$response" | grep $fulldomain > /dev/null ; then if printf -- "%s" "$response" | grep "$fulldomain" >/dev/null; then
_info "Added, sleeping 10 seconds" _info "Added, sleeping 10 seconds"
sleep 10 sleep 10
#todo: check if the record takes effect #todo: check if the record takes effect
...@@ -61,22 +61,21 @@ dns_cf_add(){ ...@@ -61,22 +61,21 @@ dns_cf_add(){
_err "Add txt record error." _err "Add txt record error."
else else
_info "Updating record" _info "Updating record"
record_id=$(printf "%s\n" "$response" | _egrep_o \"id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \"| head -n 1) record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1)
_debug "record_id" $record_id _debug "record_id" "$record_id"
_cf_rest PUT "zones/$_domain_id/dns_records/$record_id" "{\"id\":\"$record_id\",\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"zone_id\":\"$_domain_id\",\"zone_name\":\"$_domain\"}" _cf_rest PUT "zones/$_domain_id/dns_records/$record_id" "{\"id\":\"$record_id\",\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"zone_id\":\"$_domain_id\",\"zone_name\":\"$_domain\"}"
if [ "$?" = "0" ]; then if [ "$?" = "0" ]; then
_info "Updated, sleeping 10 seconds" _info "Updated, sleeping 10 seconds"
sleep 10 sleep 10
#todo: check if the record takes effect #todo: check if the record takes effect
return 0; return 0
fi fi
_err "Update error" _err "Update error"
return 1 return 1
fi fi
}
}
#fulldomain #fulldomain
dns_cf_rm() { dns_cf_rm() {
...@@ -84,7 +83,6 @@ dns_cf_rm() { ...@@ -84,7 +83,6 @@ dns_cf_rm() {
} }
#################### Private functions bellow ################################## #################### Private functions bellow ##################################
#_acme-challenge.www.domain.com #_acme-challenge.www.domain.com
#returns #returns
...@@ -95,28 +93,28 @@ _get_root() { ...@@ -95,28 +93,28 @@ _get_root() {
domain=$1 domain=$1
i=2 i=2
p=1 p=1
while [ '1' ] ; do while true; do
h=$(printf $domain | cut -d . -f $i-100) h=$(printf "%s" "$domain" | cut -d . -f $i-100)
if [ -z "$h" ] ; then if [ -z "$h" ]; then
#not valid #not valid
return 1; return 1
fi fi
if ! _cf_rest GET "zones?name=$h" ; then if ! _cf_rest GET "zones?name=$h"; then
return 1 return 1
fi fi
if printf $response | grep \"name\":\"$h\" >/dev/null ; then if printf "%s" "$response" | grep "\"name\":\"$h\"" >/dev/null; then
_domain_id=$(printf "%s\n" "$response" | _egrep_o \"id\":\"[^\"]*\" | head -n 1 | cut -d : -f 2 | tr -d \") _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | head -n 1 | cut -d : -f 2 | tr -d \")
if [ "$_domain_id" ] ; then if [ "$_domain_id" ]; then
_sub_domain=$(printf $domain | cut -d . -f 1-$p) _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain=$h _domain=$h
return 0 return 0
fi fi
return 1 return 1
fi fi
p=$i p=$i
i=$(expr $i + 1) i=$(_math "$i" + 1)
done done
return 1 return 1
} }
...@@ -125,25 +123,23 @@ _cf_rest() { ...@@ -125,25 +123,23 @@ _cf_rest() {
m=$1 m=$1
ep="$2" ep="$2"
data="$3" data="$3"
_debug $ep _debug "$ep"
_H1="X-Auth-Email: $CF_Email" _H1="X-Auth-Email: $CF_Email"
_H2="X-Auth-Key: $CF_Key" _H2="X-Auth-Key: $CF_Key"
_H3="Content-Type: application/json" _H3="Content-Type: application/json"
if [ "$data" ] ; then if [ "$data" ]; then
_debug data "$data" _debug data "$data"
response="$(_post "$data" "$CF_Api/$ep" "" $m)" response="$(_post "$data" "$CF_Api/$ep" "" "$m")"
else else
response="$(_get "$CF_Api/$ep")" response="$(_get "$CF_Api/$ep")"
fi fi
if [ "$?" != "0" ] ; then if [ "$?" != "0" ]; then
_err "error $ep" _err "error $ep"
return 1 return 1
fi fi
_debug2 response "$response" _debug2 response "$response"
return 0 return 0
} }
...@@ -6,10 +6,8 @@ ...@@ -6,10 +6,8 @@
# #
#CX_Secret="sADDsdasdgdsf" #CX_Secret="sADDsdasdgdsf"
CX_Api="https://www.cloudxns.net/api2" CX_Api="https://www.cloudxns.net/api2"
#REST_API #REST_API
######## Public functions ##################### ######## Public functions #####################
...@@ -17,54 +15,52 @@ CX_Api="https://www.cloudxns.net/api2" ...@@ -17,54 +15,52 @@ CX_Api="https://www.cloudxns.net/api2"
dns_cx_add() { dns_cx_add() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
if [ -z "$CX_Key" ] || [ -z "$CX_Secret" ] ; then if [ -z "$CX_Key" ] || [ -z "$CX_Secret" ]; then
CX_Key=""
CX_Secret=""
_err "You don't specify cloudxns.com api key or secret yet." _err "You don't specify cloudxns.com api key or secret yet."
_err "Please create you key and try again." _err "Please create you key and try again."
return 1 return 1
fi fi
REST_API=$CX_Api REST_API="$CX_Api"
#save the api key and email to the account conf file. #save the api key and email to the account conf file.
_saveaccountconf CX_Key "$CX_Key" _saveaccountconf CX_Key "$CX_Key"
_saveaccountconf CX_Secret "$CX_Secret" _saveaccountconf CX_Secret "$CX_Secret"
_debug "First detect the root zone" _debug "First detect the root zone"
if ! _get_root $fulldomain ; then if ! _get_root "$fulldomain"; then
_err "invalid domain" _err "invalid domain"
return 1 return 1
fi fi
existing_records $_domain $_sub_domain existing_records "$_domain" "$_sub_domain"
_debug count "$count" _debug count "$count"
if [ "$?" != "0" ] ; then if [ "$?" != "0" ]; then
_err "Error get existing records." _err "Error get existing records."
return 1 return 1
fi fi
if [ "$count" = "0" ] ; then if [ "$count" = "0" ]; then
add_record $_domain $_sub_domain $txtvalue add_record "$_domain" "$_sub_domain" "$txtvalue"
else else
update_record $_domain $_sub_domain $txtvalue update_record "$_domain" "$_sub_domain" "$txtvalue"
fi fi
if [ "$?" = "0" ] ; then if [ "$?" = "0" ]; then
return 0 return 0
fi fi
return 1 return 1
} }
#fulldomain #fulldomain
dns_cx_rm() { dns_cx_rm() {
fulldomain=$1 fulldomain=$1
} }
#usage: root sub #usage: root sub
#return if the sub record already exists. #return if the sub record already exists.
#echos the existing records count. #echos the existing records count.
...@@ -73,24 +69,24 @@ existing_records() { ...@@ -73,24 +69,24 @@ existing_records() {
_debug "Getting txt records" _debug "Getting txt records"
root=$1 root=$1
sub=$2 sub=$2
if ! _rest GET "record/$_domain_id?:domain_id?host_id=0&offset=0&row_num=100" ; then if ! _rest GET "record/$_domain_id?:domain_id?host_id=0&offset=0&row_num=100"; then
return 1 return 1
fi fi
count=0 count=0
seg=$(printf "%s\n" "$response" | _egrep_o "{[^\{]*host\":\"$_sub_domain\"[^\}]*\}") seg=$(printf "%s\n" "$response" | _egrep_o "{[^\{]*host\":\"$_sub_domain\"[^\}]*\}")
_debug seg "$seg" _debug seg "$seg"
if [ -z "$seg" ] ; then if [ -z "$seg" ]; then
return 0 return 0
fi fi
if printf "$response" | grep '"type":"TXT"' > /dev/null ; then if printf "%s" "$response" | grep '"type":"TXT"' >/dev/null; then
count=1 count=1
record_id=$(printf "%s\n" "$seg" | _egrep_o \"record_id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \") record_id=$(printf "%s\n" "$seg" | _egrep_o "\"record_id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")
_debug record_id "$record_id" _debug record_id "$record_id"
return 0 return 0
fi fi
} }
#add the txt record. #add the txt record.
...@@ -99,14 +95,14 @@ add_record() { ...@@ -99,14 +95,14 @@ add_record() {
root=$1 root=$1
sub=$2 sub=$2
txtvalue=$3 txtvalue=$3
fulldomain=$sub.$root fulldomain="$sub.$root"
_info "Adding record" _info "Adding record"
if ! _rest POST "record" "{\"domain_id\": $_domain_id, \"host\":\"$_sub_domain\", \"value\":\"$txtvalue\", \"type\":\"TXT\",\"ttl\":600, \"line_id\":1}"; then if ! _rest POST "record" "{\"domain_id\": $_domain_id, \"host\":\"$_sub_domain\", \"value\":\"$txtvalue\", \"type\":\"TXT\",\"ttl\":600, \"line_id\":1}"; then
return 1 return 1
fi fi
return 0 return 0
} }
...@@ -116,20 +112,17 @@ update_record() { ...@@ -116,20 +112,17 @@ update_record() {
root=$1 root=$1
sub=$2 sub=$2
txtvalue=$3 txtvalue=$3
fulldomain=$sub.$root fulldomain="$sub.$root"
_info "Updating record" _info "Updating record"
if _rest PUT "record/$record_id" "{\"domain_id\": $_domain_id, \"host\":\"$_sub_domain\", \"value\":\"$txtvalue\", \"type\":\"TXT\",\"ttl\":600, \"line_id\":1}" ; then if _rest PUT "record/$record_id" "{\"domain_id\": $_domain_id, \"host\":\"$_sub_domain\", \"value\":\"$txtvalue\", \"type\":\"TXT\",\"ttl\":600, \"line_id\":1}"; then
return 0 return 0
fi fi
return 1 return 1
} }
#################### Private functions bellow ################################## #################### Private functions bellow ##################################
#_acme-challenge.www.domain.com #_acme-challenge.www.domain.com
#returns #returns
...@@ -140,79 +133,76 @@ _get_root() { ...@@ -140,79 +133,76 @@ _get_root() {
domain=$1 domain=$1
i=2 i=2
p=1 p=1
if ! _rest GET "domain" ; then if ! _rest GET "domain"; then
return 1 return 1
fi fi
while [ '1' ] ; do while true; do
h=$(printf $domain | cut -d . -f $i-100) h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug h "$h" _debug h "$h"
if [ -z "$h" ] ; then if [ -z "$h" ]; then
#not valid #not valid
return 1; return 1
fi fi
if printf "$response" | grep "$h." >/dev/null ; then if _contains "$response" "$h."; then
seg=$(printf "%s" "$response" | _egrep_o "\{[^\{]*\"$h\.\"[^\}]*\}" ) seg=$(printf "%s" "$response" | _egrep_o "\{[^\{]*\"$h\.\"[^\}]*\}")
_debug seg "$seg" _debug seg "$seg"
_domain_id=$(printf "%s" "$seg" | _egrep_o \"id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \") _domain_id=$(printf "%s" "$seg" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")
_debug _domain_id "$_domain_id" _debug _domain_id "$_domain_id"
if [ "$_domain_id" ] ; then if [ "$_domain_id" ]; then
_sub_domain=$(printf $domain | cut -d . -f 1-$p) _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_debug _sub_domain $_sub_domain _debug _sub_domain "$_sub_domain"
_domain=$h _domain="$h"
_debug _domain $_domain _debug _domain "$_domain"
return 0 return 0
fi fi
return 1 return 1
fi fi
p=$i p="$i"
i=$(expr $i + 1) i=$(_math "$i" + 1)
done done
return 1 return 1
} }
#Usage: method URI data #Usage: method URI data
_rest() { _rest() {
m=$1 m=$1
ep="$2" ep="$2"
_debug $ep _debug "$ep"
url="$REST_API/$ep" url="$REST_API/$ep"
_debug url "$url" _debug url "$url"
cdate=$(date -u "+%Y-%m-%d %H:%M:%S UTC") cdate=$(date -u "+%Y-%m-%d %H:%M:%S UTC")
_debug cdate "$cdate" _debug cdate "$cdate"
data="$3" data="$3"
_debug data "$data" _debug data "$data"
sec="$CX_Key$url$data$cdate$CX_Secret" sec="$CX_Key$url$data$cdate$CX_Secret"
_debug sec "$sec" _debug sec "$sec"
hmac=$(printf "$sec"| openssl md5 |cut -d " " -f 2) hmac=$(printf "%s" "$sec" | _digest md5 hex)
_debug hmac "$hmac" _debug hmac "$hmac"
_H1="API-KEY: $CX_Key" _H1="API-KEY: $CX_Key"
_H2="API-REQUEST-DATE: $cdate" _H2="API-REQUEST-DATE: $cdate"
_H3="API-HMAC: $hmac" _H3="API-HMAC: $hmac"
_H4="Content-Type: application/json" _H4="Content-Type: application/json"
if [ "$data" ] ; then if [ "$data" ]; then
response="$(_post "$data" "$url" "" $m)" response="$(_post "$data" "$url" "" "$m")"
else else
response="$(_get "$url")" response="$(_get "$url")"
fi fi
if [ "$?" != "0" ] ; then if [ "$?" != "0" ]; then
_err "error $ep" _err "error $ep"
return 1 return 1
fi fi
_debug2 response "$response" _debug2 response "$response"
if ! printf "$response" | grep '"message":"success"' > /dev/null ; then if ! _contains "$response" '"message":"success"'; then
return 1 return 1
fi fi
return 0 return 0
} }
...@@ -6,10 +6,8 @@ ...@@ -6,10 +6,8 @@
# #
#DP_Key="sADDsdasdgdsf" #DP_Key="sADDsdasdgdsf"
DP_Api="https://dnsapi.cn" DP_Api="https://dnsapi.cn"
#REST_API #REST_API
######## Public functions ##################### ######## Public functions #####################
...@@ -17,49 +15,47 @@ DP_Api="https://dnsapi.cn" ...@@ -17,49 +15,47 @@ DP_Api="https://dnsapi.cn"
dns_dp_add() { dns_dp_add() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
if [ -z "$DP_Id" ] || [ -z "$DP_Key" ] ; then if [ -z "$DP_Id" ] || [ -z "$DP_Key" ]; then
DP_Id=""
DP_Key=""
_err "You don't specify dnspod api key and key id yet." _err "You don't specify dnspod api key and key id yet."
_err "Please create you key and try again." _err "Please create you key and try again."
return 1 return 1
fi fi
REST_API=$DP_Api REST_API="$DP_Api"
#save the api key and email to the account conf file. #save the api key and email to the account conf file.
_saveaccountconf DP_Id "$DP_Id" _saveaccountconf DP_Id "$DP_Id"
_saveaccountconf DP_Key "$DP_Key" _saveaccountconf DP_Key "$DP_Key"
_debug "First detect the root zone" _debug "First detect the root zone"
if ! _get_root $fulldomain ; then if ! _get_root "$fulldomain"; then
_err "invalid domain" _err "invalid domain"
return 1 return 1
fi fi
existing_records $_domain $_sub_domain existing_records "$_domain" "$_sub_domain"
_debug count "$count" _debug count "$count"
if [ "$?" != "0" ] ; then if [ "$?" != "0" ]; then
_err "Error get existing records." _err "Error get existing records."
return 1 return 1
fi fi
if [ "$count" = "0" ] ; then if [ "$count" = "0" ]; then
add_record $_domain $_sub_domain $txtvalue add_record "$_domain" "$_sub_domain" "$txtvalue"
else else
update_record $_domain $_sub_domain $txtvalue update_record "$_domain" "$_sub_domain" "$txtvalue"
fi fi
} }
#fulldomain #fulldomain
dns_dp_rm() { dns_dp_rm() {
fulldomain=$1 fulldomain=$1
} }
#usage: root sub #usage: root sub
#return if the sub record already exists. #return if the sub record already exists.
#echos the existing records count. #echos the existing records count.
...@@ -68,26 +64,25 @@ existing_records() { ...@@ -68,26 +64,25 @@ existing_records() {
_debug "Getting txt records" _debug "Getting txt records"
root=$1 root=$1
sub=$2 sub=$2
if ! _rest POST "Record.List" "login_token=$DP_Id,$DP_Key&domain_id=$_domain_id&sub_domain=$_sub_domain"; then if ! _rest POST "Record.List" "login_token=$DP_Id,$DP_Key&domain_id=$_domain_id&sub_domain=$_sub_domain"; then
return 1 return 1
fi fi
if printf "$response" | grep 'No records' ; then if _contains "$response" 'No records'; then
count=0; count=0
return 0 return 0
fi fi
if printf "$response" | grep "Action completed successful" >/dev/null ; then if _contains "$response" "Action completed successful"; then
count=$(printf "$response" | grep '<type>TXT</type>' | wc -l) count=$(printf "%s" "$response" | grep '<type>TXT</type>' | wc -l)
record_id=$(printf "$response" | grep '^<id>' | tail -1 | cut -d '>' -f 2 | cut -d '<' -f 1) record_id=$(printf "%s" "$response" | grep '^<id>' | tail -1 | cut -d '>' -f 2 | cut -d '<' -f 1)
return 0 return 0
else else
_err "get existing records error." _err "get existing records error."
return 1 return 1
fi fi
count=0 count=0
} }
...@@ -97,20 +92,19 @@ add_record() { ...@@ -97,20 +92,19 @@ add_record() {
root=$1 root=$1
sub=$2 sub=$2
txtvalue=$3 txtvalue=$3
fulldomain=$sub.$root fulldomain="$sub.$root"
_info "Adding record" _info "Adding record"
if ! _rest POST "Record.Create" "login_token=$DP_Id,$DP_Key&format=json&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=默认"; then if ! _rest POST "Record.Create" "login_token=$DP_Id,$DP_Key&format=json&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=默认"; then
return 1 return 1
fi fi
if printf "$response" | grep "Action completed successful" ; then if _contains "$response" "Action completed successful"; then
return 0 return 0
fi fi
return 1 #error return 1 #error
} }
...@@ -120,25 +114,22 @@ update_record() { ...@@ -120,25 +114,22 @@ update_record() {
root=$1 root=$1
sub=$2 sub=$2
txtvalue=$3 txtvalue=$3
fulldomain=$sub.$root fulldomain="$sub.$root"
_info "Updating record" _info "Updating record"
if ! _rest POST "Record.Modify" "login_token=$DP_Id,$DP_Key&format=json&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=默认&record_id=$record_id"; then if ! _rest POST "Record.Modify" "login_token=$DP_Id,$DP_Key&format=json&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=默认&record_id=$record_id"; then
return 1 return 1
fi fi
if printf "$response" | grep "Action completed successful" ; then if _contains "$response" "Action completed successful"; then
return 0 return 0
fi fi
return 1 #error return 1 #error
} }
#################### Private functions bellow ################################## #################### Private functions bellow ##################################
#_acme-challenge.www.domain.com #_acme-challenge.www.domain.com
#returns #returns
...@@ -149,59 +140,56 @@ _get_root() { ...@@ -149,59 +140,56 @@ _get_root() {
domain=$1 domain=$1
i=2 i=2
p=1 p=1
while [ '1' ] ; do while true; do
h=$(printf $domain | cut -d . -f $i-100) h=$(printf "%s" "$domain" | cut -d . -f $i-100)
if [ -z "$h" ] ; then if [ -z "$h" ]; then
#not valid #not valid
return 1; return 1
fi fi
if ! _rest POST "Domain.Info" "login_token=$DP_Id,$DP_Key&format=json&domain=$h"; then if ! _rest POST "Domain.Info" "login_token=$DP_Id,$DP_Key&format=json&domain=$h"; then
return 1 return 1
fi fi
if printf "$response" | grep "Action completed successful" >/dev/null ; then if _contains "$response" "Action completed successful"; then
_domain_id=$(printf "%s\n" "$response" | _egrep_o \"id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \") _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")
_debug _domain_id "$_domain_id" _debug _domain_id "$_domain_id"
if [ "$_domain_id" ] ; then if [ "$_domain_id" ]; then
_sub_domain=$(printf $domain | cut -d . -f 1-$p) _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_debug _sub_domain $_sub_domain _debug _sub_domain "$_sub_domain"
_domain=$h _domain="$h"
_debug _domain $_domain _debug _domain "$_domain"
return 0 return 0
fi fi
return 1 return 1
fi fi
p=$i p="$i"
i=$(expr $i + 1) i=$(_math "$i" + 1)
done done
return 1 return 1
} }
#Usage: method URI data #Usage: method URI data
_rest() { _rest() {
m=$1 m=$1
ep="$2" ep="$2"
data="$3" data="$3"
_debug $ep _debug "$ep"
url="$REST_API/$ep" url="$REST_API/$ep"
_debug url "$url" _debug url "$url"
if [ "$data" ] ; then if [ "$data" ]; then
_debug2 data "$data" _debug2 data "$data"
response="$(_post $data "$url")" response="$(_post "$data" "$url")"
else else
response="$(_get "$url")" response="$(_get "$url")"
fi fi
if [ "$?" != "0" ] ; then if [ "$?" != "0" ]; then
_err "error $ep" _err "error $ep"
return 1 return 1
fi fi
_debug2 response "$response" _debug2 response "$response"
return 0 return 0
} }
...@@ -6,39 +6,39 @@ ...@@ -6,39 +6,39 @@
# #
#GD_Secret="asdfsdfsfsdfsdfdfsdf" #GD_Secret="asdfsdfsfsdfsdfdfsdf"
GD_Api="https://api.godaddy.com/v1" GD_Api="https://api.godaddy.com/v1"
######## Public functions ##################### ######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_gd_add(){ dns_gd_add() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
if [ -z "$GD_Key" ] || [ -z "$GD_Secret" ] ; then if [ -z "$GD_Key" ] || [ -z "$GD_Secret" ]; then
GD_Key=""
GD_Secret=""
_err "You don't specify godaddy api key and secret yet." _err "You don't specify godaddy api key and secret yet."
_err "Please create you key and try again." _err "Please create you key and try again."
return 1 return 1
fi fi
#save the api key and email to the account conf file. #save the api key and email to the account conf file.
_saveaccountconf GD_Key "$GD_Key" _saveaccountconf GD_Key "$GD_Key"
_saveaccountconf GD_Secret "$GD_Secret" _saveaccountconf GD_Secret "$GD_Secret"
_debug "First detect the root zone" _debug "First detect the root zone"
if ! _get_root $fulldomain ; then if ! _get_root "$fulldomain"; then
_err "invalid domain" _err "invalid domain"
return 1 return 1
fi fi
_debug _domain_id "$_domain_id"
_debug _sub_domain "$_sub_domain" _debug _sub_domain "$_sub_domain"
_debug _domain "$_domain" _debug _domain "$_domain"
_info "Adding record" _info "Adding record"
if _gd_rest PUT "domains/$_domain/records/TXT/$_sub_domain" "[{\"data\":\"$txtvalue\"}]"; then if _gd_rest PUT "domains/$_domain/records/TXT/$_sub_domain" "[{\"data\":\"$txtvalue\"}]"; then
if [ "$response" = "{}" ] ; then if [ "$response" = "{}" ]; then
_info "Added, sleeping 10 seconds" _info "Added, sleeping 10 seconds"
sleep 10 sleep 10
#todo: check if the record takes effect #todo: check if the record takes effect
...@@ -50,10 +50,8 @@ dns_gd_add(){ ...@@ -50,10 +50,8 @@ dns_gd_add(){
fi fi
fi fi
_err "Add txt record error." _err "Add txt record error."
}
}
#fulldomain #fulldomain
dns_gd_rm() { dns_gd_rm() {
...@@ -61,39 +59,35 @@ dns_gd_rm() { ...@@ -61,39 +59,35 @@ dns_gd_rm() {
} }
#################### Private functions bellow ################################## #################### Private functions bellow ##################################
#_acme-challenge.www.domain.com #_acme-challenge.www.domain.com
#returns #returns
# _sub_domain=_acme-challenge.www # _sub_domain=_acme-challenge.www
# _domain=domain.com # _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root() { _get_root() {
domain=$1 domain=$1
i=2 i=2
p=1 p=1
while [ '1' ] ; do while true; do
h=$(printf $domain | cut -d . -f $i-100) h=$(printf "%s" "$domain" | cut -d . -f $i-100)
if [ -z "$h" ] ; then if [ -z "$h" ]; then
#not valid #not valid
return 1; return 1
fi fi
if ! _gd_rest GET "domains/$h" ; then if ! _gd_rest GET "domains/$h"; then
return 1 return 1
fi fi
if printf "$response" | grep '"code":"NOT_FOUND"' >/dev/null ; then if _contains "$response" '"code":"NOT_FOUND"'; then
_debug "$h not found" _debug "$h not found"
else else
_sub_domain=$(printf $domain | cut -d . -f 1-$p) _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain=$h _domain="$h"
return 0 return 0
fi fi
p=$i p="$i"
i=$(expr $i + 1) i=$(_math "$i" + 1)
done done
return 1 return 1
} }
...@@ -102,24 +96,22 @@ _gd_rest() { ...@@ -102,24 +96,22 @@ _gd_rest() {
m=$1 m=$1
ep="$2" ep="$2"
data="$3" data="$3"
_debug $ep _debug "$ep"
_H1="Authorization: sso-key $GD_Key:$GD_Secret" _H1="Authorization: sso-key $GD_Key:$GD_Secret"
_H2="Content-Type: application/json" _H2="Content-Type: application/json"
if [ "$data" ] ; then if [ "$data" ]; then
_debug data "$data" _debug data "$data"
response="$(_post "$data" "$GD_Api/$ep" "" $m)" response="$(_post "$data" "$GD_Api/$ep" "" "$m")"
else else
response="$(_get "$GD_Api/$ep")" response="$(_get "$GD_Api/$ep")"
fi fi
if [ "$?" != "0" ] ; then if [ "$?" != "0" ]; then
_err "error $ep" _err "error $ep"
return 1 return 1
fi fi
_debug2 response "$response" _debug2 response "$response"
return 0 return 0
} }
...@@ -13,15 +13,16 @@ wiki="https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api" ...@@ -13,15 +13,16 @@ wiki="https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api"
dns_lexicon_add() { dns_lexicon_add() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
domain=$(printf "$fulldomain" | cut -d . -f 2-999) domain=$(printf "%s" "$fulldomain" | cut -d . -f 2-999)
if ! _exists $lexicon_cmd ; then if ! _exists "$lexicon_cmd"; then
_err "Please install $lexicon_cmd first: $wiki" _err "Please install $lexicon_cmd first: $wiki"
return 1 return 1
fi fi
if [ -z "$PROVIDER" ] ; then if [ -z "$PROVIDER" ]; then
PROVIDER=""
_err "Please define env PROVIDER first: $wiki" _err "Please define env PROVIDER first: $wiki"
return 1 return 1
fi fi
...@@ -29,50 +30,44 @@ dns_lexicon_add() { ...@@ -29,50 +30,44 @@ dns_lexicon_add() {
_savedomainconf PROVIDER "$PROVIDER" _savedomainconf PROVIDER "$PROVIDER"
export PROVIDER export PROVIDER
Lx_name=$(echo LEXICON_${PROVIDER}_USERNAME | tr [a-z] [A-Z]) Lx_name=$(echo LEXICON_"${PROVIDER}"_USERNAME | tr '[a-z]' '[A-Z]')
eval Lx_name_v="\$$Lx_name" Lx_name_v=$(eval echo \$"$Lx_name")
_debug "$Lx_name" "$Lx_name_v" _debug "$Lx_name" "$Lx_name_v"
if [ "$Lx_name_v" ] ; then if [ "$Lx_name_v" ]; then
_saveaccountconf $Lx_name "$Lx_name_v" _saveaccountconf "$Lx_name" "$Lx_name_v"
export "$Lx_name" eval export "$Lx_name"
fi fi
Lx_token=$(echo LEXICON_${PROVIDER}_TOKEN | tr [a-z] [A-Z]) Lx_token=$(echo LEXICON_"${PROVIDER}"_TOKEN | tr '[a-z]' '[A-Z]')
eval Lx_token_v="\$$Lx_token" Lx_token_v=$(eval echo \$"$Lx_token")
_debug "$Lx_token" "$Lx_token_v" _debug "$Lx_token" "$Lx_token_v"
if [ "$Lx_token_v" ] ; then if [ "$Lx_token_v" ]; then
_saveaccountconf $Lx_token "$Lx_token_v" _saveaccountconf "$Lx_token" "$Lx_token_v"
export "$Lx_token" eval export "$Lx_token"
fi fi
Lx_password=$(echo LEXICON_${PROVIDER}_PASSWORD | tr [a-z] [A-Z]) Lx_password=$(echo LEXICON_"${PROVIDER}"_PASSWORD | tr '[a-z]' '[A-Z]')
eval Lx_password_v="\$$Lx_password" Lx_password_v=$(eval echo \$"$Lx_password")
_debug "$Lx_password" "$Lx_password_v" _debug "$Lx_password" "$Lx_password_v"
if [ "$Lx_password_v" ] ; then if [ "$Lx_password_v" ]; then
_saveaccountconf $Lx_password "$Lx_password_v" _saveaccountconf "$Lx_password" "$Lx_password_v"
export "$Lx_password" eval export "$Lx_password"
fi fi
Lx_domaintoken=$(echo LEXICON_${PROVIDER}_DOMAINTOKEN | tr [a-z] [A-Z]) Lx_domaintoken=$(echo LEXICON_"${PROVIDER}"_DOMAINTOKEN | tr '[a-z]' '[A-Z]')
eval Lx_domaintoken_v="\$$Lx_domaintoken" Lx_domaintoken_v=$(eval echo \$"$Lx_domaintoken")
_debug "$Lx_domaintoken" "$Lx_domaintoken_v" _debug "$Lx_domaintoken" "$Lx_domaintoken_v"
if [ "$Lx_domaintoken_v" ] ; then if [ "$Lx_domaintoken_v" ]; then
export "$Lx_domaintoken" eval export "$Lx_domaintoken"
_saveaccountconf $Lx_domaintoken "$Lx_domaintoken_v" _saveaccountconf "$Lx_domaintoken" "$Lx_domaintoken_v"
fi fi
$lexicon_cmd "$PROVIDER" create ${domain} TXT --name="_acme-challenge.${domain}." --content="${txtvalue}" $lexicon_cmd "$PROVIDER" create "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}"
} }
#fulldomain #fulldomain
dns_lexicon_rm() { dns_lexicon_rm() {
fulldomain=$1 fulldomain=$1
} }
#!/usr/bin/env sh
# bug reports to dev@1e.ca
#
#LUA_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
#
#LUA_Email="user@luadns.net"
LUA_Api="https://api.luadns.com/v1"
LUA_auth=$(printf "%s" "$LUA_Email:$LUA_Key" | _base64)
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_lua_add() {
fulldomain=$1
txtvalue=$2
if [ -z "$LUA_Key" ] || [ -z "$LUA_Email" ]; then
LUA_Key=""
LUA_Email=""
_err "You don't specify luadns api key and email yet."
_err "Please create you key and try again."
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf LUA_Key "$LUA_Key"
_saveaccountconf LUA_Email "$LUA_Email"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _domain_id "$_domain_id"
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_debug "Getting txt records"
_LUA_rest GET "zones/${_domain_id}/records"
if ! _contains "$response" "\"id\":"; then
_err "Error"
return 1
fi
count=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"$fulldomain\"" | wc -l)
_debug count "$count"
if [ "$count" = "0" ]; then
_info "Adding record"
if _LUA_rest POST "zones/$_domain_id/records" "{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
if printf -- "%s" "$response" | grep "$fulldomain" >/dev/null; then
_info "Added"
#todo: check if the record takes effect
return 0
else
_err "Add txt record error."
return 1
fi
fi
_err "Add txt record error."
else
_info "Updating record"
record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*,\"name\":\"$fulldomain.\",\"type\":\"TXT\"" | cut -d: -f2 | cut -d, -f1)
_debug "record_id" "$record_id"
_LUA_rest PUT "zones/$_domain_id/records/$record_id" "{\"id\":\"$record_id\",\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"content\":\"$txtvalue\",\"zone_id\":\"$_domain_id\",\"ttl\":120}"
if [ "$?" = "0" ]; then
_info "Updated!"
#todo: check if the record takes effect
return 0
fi
_err "Update error"
return 1
fi
}
#fulldomain
dns_lua_rm() {
fulldomain=$1
}
#################### Private functions bellow ##################################
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root() {
domain=$1
i=2
p=1
if ! _LUA_rest GET "zones"; then
return 1
fi
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
if [ -z "$h" ]; then
#not valid
return 1
fi
if _contains "$response" "\"name\":\"$h\""; then
_domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*,\"name\":\"$h\"" | cut -d : -f 2 | cut -d , -f 1)
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain="$h"
return 0
fi
return 1
fi
p=$i
i=$(_math "$i" + 1)
done
return 1
}
_LUA_rest() {
m=$1
ep="$2"
data="$3"
_debug "$ep"
_H1="Accept: application/json"
_H2="Authorization: Basic $LUA_auth"
if [ "$data" ]; then
_debug data "$data"
response="$(_post "$data" "$LUA_Api/$ep" "" "$m")"
else
response="$(_get "$LUA_Api/$ep")"
fi
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}
#!/usr/bin/env sh
# bug reports to dev@1e.ca
# ME_Key=qmlkdjflmkqdjf
# ME_Secret=qmsdlkqmlksdvnnpae
ME_Api=https://api.dnsmadeeasy.com/V2.0/dns/managed
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_me_add() {
fulldomain=$1
txtvalue=$2
if [ -z "$ME_Key" ] || [ -z "$ME_Secret" ]; then
ME_Key=""
ME_Secret=""
_err "You didn't specify DNSMadeEasy api key and secret yet."
_err "Please create you key and try again."
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf ME_Key "$ME_Key"
_saveaccountconf ME_Secret "$ME_Secret"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _domain_id "$_domain_id"
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_debug "Getting txt records"
_me_rest GET "${_domain_id}/records?recordName=$_sub_domain&type=TXT"
if ! _contains "$response" "\"totalRecords\":"; then
_err "Error"
return 1
fi
count=$(printf "%s\n" "$response" | _egrep_o "\"totalRecords\":[^,]*" | cut -d : -f 2)
_debug count "$count"
if [ "$count" = "0" ]; then
_info "Adding record"
if _me_rest POST "$_domain_id/records/" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":\"$txtvalue\",\"gtdLocation\":\"DEFAULT\",\"ttl\":120}"; then
if printf -- "%s" "$response" | grep \"id\": >/dev/null; then
_info "Added"
#todo: check if the record takes effect
return 0
else
_err "Add txt record error."
return 1
fi
fi
_err "Add txt record error."
else
_info "Updating record"
record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*" | cut -d : -f 2 | head -n 1)
_debug "record_id" "$record_id"
_me_rest PUT "$_domain_id/records/$record_id/" "{\"id\":\"$record_id\",\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":\"$txtvalue\",\"gtdLocation\":\"DEFAULT\",\"ttl\":120}"
if [ "$?" = "0" ]; then
_info "Updated"
#todo: check if the record takes effect
return 0
fi
_err "Update error"
return 1
fi
}
#fulldomain
dns_me_rm() {
fulldomain=$1
}
#################### Private functions bellow ##################################
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root() {
domain=$1
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
if [ -z "$h" ]; then
#not valid
return 1
fi
if ! _me_rest GET "name?domainname=$h"; then
return 1
fi
if _contains "$response" "\"name\":\"$h\""; then
_domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*" | head -n 1 | cut -d : -f 2)
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain="$h"
return 0
fi
return 1
fi
p=$i
i=$(_math "$i" + 1)
done
return 1
}
_me_rest() {
m=$1
ep="$2"
data="$3"
_debug "$ep"
cdate=$(date -u +"%a, %d %b %Y %T %Z")
hmac=$(printf "%s" "$cdate" | _hmac sha1 "$ME_Secret" 1)
_H1="x-dnsme-apiKey: $ME_Key"
_H2="x-dnsme-requestDate: $cdate"
_H3="x-dnsme-hmac: $hmac"
if [ "$data" ]; then
_debug data "$data"
response="$(_post "$data" "$ME_Api/$ep" "" "$m")"
else
response="$(_get "$ME_Api/$ep")"
fi
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}
...@@ -6,8 +6,6 @@ ...@@ -6,8 +6,6 @@
#Which will be called by acme.sh to add the txt record to your api system. #Which will be called by acme.sh to add the txt record to your api system.
#returns 0 means success, otherwise error. #returns 0 means success, otherwise error.
######## Public functions ##################### ######## Public functions #####################
#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" #Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
...@@ -15,21 +13,18 @@ dns_myapi_add() { ...@@ -15,21 +13,18 @@ dns_myapi_add() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
_err "Not implemented!" _err "Not implemented!"
return 1; return 1
} }
#fulldomain #fulldomain
dns_myapi_rm() { dns_myapi_rm() {
fulldomain=$1 fulldomain=$1
} }
#################### Private functions bellow ################################## #################### Private functions bellow ##################################
_info() { _info() {
if [ -z "$2" ] ; then if [ -z "$2" ]; then
echo "[$(date)] $1" echo "[$(date)] $1"
else else
echo "[$(date)] $1='$2'" echo "[$(date)] $1='$2'"
...@@ -42,7 +37,7 @@ _err() { ...@@ -42,7 +37,7 @@ _err() {
} }
_debug() { _debug() {
if [ -z "$DEBUG" ] ; then if [ -z "$DEBUG" ]; then
return return
fi fi
_err "$@" _err "$@"
...@@ -50,8 +45,8 @@ _debug() { ...@@ -50,8 +45,8 @@ _debug() {
} }
_debug2() { _debug2() {
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ] ; then if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
_debug "$@" _debug "$@"
fi fi
return return
} }
\ No newline at end of file
#!/usr/bin/env sh #!/usr/bin/env sh
#Applcation Key #Applcation Key
#OVH_AK="sdfsdfsdfljlbjkljlkjsdfoiwje" #OVH_AK="sdfsdfsdfljlbjkljlkjsdfoiwje"
# #
...@@ -10,10 +9,8 @@ ...@@ -10,10 +9,8 @@
#Consumer Key #Consumer Key
#OVH_CK="sdfsdfsdfsdfsdfdsf" #OVH_CK="sdfsdfsdfsdfsdfdsf"
#OVH_END_POINT=ovh-eu #OVH_END_POINT=ovh-eu
#'ovh-eu' #'ovh-eu'
OVH_EU='https://eu.api.ovh.com/1.0' OVH_EU='https://eu.api.ovh.com/1.0'
...@@ -35,121 +32,118 @@ SYS_CA='https://ca.api.soyoustart.com/1.0' ...@@ -35,121 +32,118 @@ SYS_CA='https://ca.api.soyoustart.com/1.0'
#'runabove-ca' #'runabove-ca'
RAV_CA='https://api.runabove.com/1.0' RAV_CA='https://api.runabove.com/1.0'
wiki="https://github.com/Neilpang/acme.sh/wiki/How-to-use-OVH-domain-api" wiki="https://github.com/Neilpang/acme.sh/wiki/How-to-use-OVH-domain-api"
ovh_success="https://github.com/Neilpang/acme.sh/wiki/OVH-Success" ovh_success="https://github.com/Neilpang/acme.sh/wiki/OVH-Success"
_ovh_get_api() { _ovh_get_api() {
_ogaep="$1" _ogaep="$1"
case "${_ogaep}" in case "${_ogaep}" in
ovh-eu|ovheu) ovh-eu | ovheu)
printf "%s" $OVH_EU printf "%s" $OVH_EU
return return
;; ;;
ovh-ca|ovhca) ovh-ca | ovhca)
printf "%s" $OVH_CA printf "%s" $OVH_CA
return return
;; ;;
kimsufi-eu|kimsufieu) kimsufi-eu | kimsufieu)
printf "%s" $KSF_EU printf "%s" $KSF_EU
return return
;; ;;
kimsufi-ca|kimsufica) kimsufi-ca | kimsufica)
printf "%s" $KSF_CA printf "%s" $KSF_CA
return return
;; ;;
soyoustart-eu|soyoustarteu) soyoustart-eu | soyoustarteu)
printf "%s" $SYS_EU printf "%s" $SYS_EU
return return
;; ;;
soyoustart-ca|soyoustartca) soyoustart-ca | soyoustartca)
printf "%s" $SYS_CA printf "%s" $SYS_CA
return return
;; ;;
runabove-ca|runaboveca) runabove-ca | runaboveca)
printf "%s" $RAV_CA printf "%s" $RAV_CA
return return
;; ;;
*) *)
_err "Unknown parameter : $1"
return 1 _err "Unknown parameter : $1"
;; return 1
esac ;;
esac
} }
######## Public functions ##################### ######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_ovh_add(){ dns_ovh_add() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
if [ -z "$OVH_AK" ] || [ -z "$OVH_AS" ] ; then if [ -z "$OVH_AK" ] || [ -z "$OVH_AS" ]; then
OVH_AK=""
OVH_AS=""
_err "You don't specify OVH application key and application secret yet." _err "You don't specify OVH application key and application secret yet."
_err "Please create you key and try again." _err "Please create you key and try again."
return 1 return 1
fi fi
#save the api key and email to the account conf file. #save the api key and email to the account conf file.
_saveaccountconf OVH_AK "$OVH_AK" _saveaccountconf OVH_AK "$OVH_AK"
_saveaccountconf OVH_AS "$OVH_AS" _saveaccountconf OVH_AS "$OVH_AS"
if [ -z "$OVH_END_POINT" ]; then
if [ -z "$OVH_END_POINT" ] ; then
OVH_END_POINT="ovh-eu" OVH_END_POINT="ovh-eu"
fi fi
_info "Using OVH endpoint: $OVH_END_POINT" _info "Using OVH endpoint: $OVH_END_POINT"
if [ "$OVH_END_POINT" != "ovh-eu" ] ; then if [ "$OVH_END_POINT" != "ovh-eu" ]; then
_saveaccountconf OVH_END_POINT "$OVH_END_POINT" _saveaccountconf OVH_END_POINT "$OVH_END_POINT"
fi fi
OVH_API="$(_ovh_get_api $OVH_END_POINT )" OVH_API="$(_ovh_get_api $OVH_END_POINT)"
_debug OVH_API "$OVH_API" _debug OVH_API "$OVH_API"
if [ -z "$OVH_CK" ] ; then if [ -z "$OVH_CK" ]; then
_info "OVH consumer key is empty, Let's get one:" _info "OVH consumer key is empty, Let's get one:"
if ! _ovh_authentication ; then if ! _ovh_authentication; then
_err "Can not get consumer key." _err "Can not get consumer key."
fi fi
#return and wait for retry. #return and wait for retry.
return 1; return 1
fi fi
_info "Checking authentication" _info "Checking authentication"
response="$(_ovh_rest GET "domain/")" response="$(_ovh_rest GET "domain/")"
if _contains "$response" "INVALID_CREDENTIAL" ; then if _contains "$response" "INVALID_CREDENTIAL"; then
_err "The consumer key is invalid: $OVH_CK" _err "The consumer key is invalid: $OVH_CK"
_err "Please retry to create a new one." _err "Please retry to create a new one."
_clearaccountconf OVH_CK _clearaccountconf OVH_CK
return 1 return 1
fi fi
_info "Consumer key is ok." _info "Consumer key is ok."
_debug "First detect the root zone" _debug "First detect the root zone"
if ! _get_root $fulldomain ; then if ! _get_root "$fulldomain"; then
_err "invalid domain" _err "invalid domain"
return 1 return 1
fi fi
_debug _domain_id "$_domain_id"
_debug _sub_domain "$_sub_domain" _debug _sub_domain "$_sub_domain"
_debug _domain "$_domain" _debug _domain "$_domain"
_debug "Getting txt records" _debug "Getting txt records"
_ovh_rest GET "domain/zone/$_domain/record?fieldType=TXT&subDomain=$_sub_domain" _ovh_rest GET "domain/zone/$_domain/record?fieldType=TXT&subDomain=$_sub_domain"
if _contains "$response" '\[\]' || _contains "$response" "This service does not exist" ; then if _contains "$response" '\[\]' || _contains "$response" "This service does not exist"; then
_info "Adding record" _info "Adding record"
if _ovh_rest POST "domain/zone/$_domain/record" "{\"fieldType\":\"TXT\",\"subDomain\":\"$_sub_domain\",\"target\":\"$txtvalue\",\"ttl\":60}"; then if _ovh_rest POST "domain/zone/$_domain/record" "{\"fieldType\":\"TXT\",\"subDomain\":\"$_sub_domain\",\"target\":\"$txtvalue\",\"ttl\":60}"; then
if _contains "$response" "$txtvalue" ; then if _contains "$response" "$txtvalue"; then
_ovh_rest POST "domain/zone/$_domain/refresh" _ovh_rest POST "domain/zone/$_domain/refresh"
_debug "Refresh:$response" _debug "Refresh:$response"
_info "Added, sleeping 10 seconds" _info "Added, sleeping 10 seconds"
...@@ -161,27 +155,26 @@ dns_ovh_add(){ ...@@ -161,27 +155,26 @@ dns_ovh_add(){
else else
_info "Updating record" _info "Updating record"
record_id=$(printf "%s" "$response" | tr -d "[]" | cut -d , -f 1) record_id=$(printf "%s" "$response" | tr -d "[]" | cut -d , -f 1)
if [ -z "$record_id" ] ; then if [ -z "$record_id" ]; then
_err "Can not get record id." _err "Can not get record id."
return 1 return 1
fi fi
_debug "record_id" $record_id _debug "record_id" "$record_id"
if _ovh_rest PUT "domain/zone/$_domain/record/$record_id" "{\"target\":\"$txtvalue\",\"subDomain\":\"$_sub_domain\",\"ttl\":60}" ; then if _ovh_rest PUT "domain/zone/$_domain/record/$record_id" "{\"target\":\"$txtvalue\",\"subDomain\":\"$_sub_domain\",\"ttl\":60}"; then
if _contains "$response" "null" ; then if _contains "$response" "null"; then
_ovh_rest POST "domain/zone/$_domain/refresh" _ovh_rest POST "domain/zone/$_domain/refresh"
_debug "Refresh:$response" _debug "Refresh:$response"
_info "Updated, sleeping 10 seconds" _info "Updated, sleeping 10 seconds"
sleep 10 sleep 10
return 0; return 0
fi fi
fi fi
_err "Update error" _err "Update error"
return 1 return 1
fi fi
}
}
#fulldomain #fulldomain
dns_ovh_rm() { dns_ovh_rm() {
...@@ -189,72 +182,69 @@ dns_ovh_rm() { ...@@ -189,72 +182,69 @@ dns_ovh_rm() {
} }
#################### Private functions bellow ################################## #################### Private functions bellow ##################################
_ovh_authentication() { _ovh_authentication() {
_H1="X-Ovh-Application: $OVH_AK" _H1="X-Ovh-Application: $OVH_AK"
_H2="Content-type: application/json" _H2="Content-type: application/json"
_H3="" _H3=""
_H4="" _H4=""
_ovhdata='{"accessRules": [{"method": "GET","path": "/*"},{"method": "POST","path": "/*"},{"method": "PUT","path": "/*"},{"method": "DELETE","path": "/*"}],"redirection":"'$ovh_success'"}' _ovhdata='{"accessRules": [{"method": "GET","path": "/*"},{"method": "POST","path": "/*"},{"method": "PUT","path": "/*"},{"method": "DELETE","path": "/*"}],"redirection":"'$ovh_success'"}'
response="$(_post "$_ovhdata" "$OVH_API/auth/credential")" response="$(_post "$_ovhdata" "$OVH_API/auth/credential")"
_debug3 response "$response" _debug3 response "$response"
validationUrl="$(echo "$response" | _egrep_o "validationUrl\":\"[^\"]*\"" | _egrep_o "http.*\"" | tr -d '"')" validationUrl="$(echo "$response" | _egrep_o "validationUrl\":\"[^\"]*\"" | _egrep_o "http.*\"" | tr -d '"')"
if [ -z "$validationUrl" ] ; then if [ -z "$validationUrl" ]; then
_err "Unable to get validationUrl" _err "Unable to get validationUrl"
return 1 return 1
fi fi
_debug validationUrl "$validationUrl" _debug validationUrl "$validationUrl"
consumerKey="$(echo "$response" | _egrep_o "consumerKey\":\"[^\"]*\"" | cut -d : -f 2 | tr -d '"')" consumerKey="$(echo "$response" | _egrep_o "consumerKey\":\"[^\"]*\"" | cut -d : -f 2 | tr -d '"')"
if [ -z "$consumerKey" ] ; then if [ -z "$consumerKey" ]; then
_err "Unable to get consumerKey" _err "Unable to get consumerKey"
return 1 return 1
fi fi
_debug consumerKey "$consumerKey" _debug consumerKey "$consumerKey"
OVH_CK="$consumerKey" OVH_CK="$consumerKey"
_saveaccountconf OVH_CK "$OVH_CK" _saveaccountconf OVH_CK "$OVH_CK"
_info "Please open this link to do authentication: $(__green "$validationUrl" )"
_info "Here is a guide for you: $(__green "$wiki" )" _info "Please open this link to do authentication: $(__green "$validationUrl")"
_info "Here is a guide for you: $(__green "$wiki")"
_info "Please retry after the authentication is done." _info "Please retry after the authentication is done."
} }
#_acme-challenge.www.domain.com #_acme-challenge.www.domain.com
#returns #returns
# _sub_domain=_acme-challenge.www # _sub_domain=_acme-challenge.www
# _domain=domain.com # _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root() { _get_root() {
domain=$1 domain=$1
i=2 i=2
p=1 p=1
while [ '1' ] ; do while true; do
h=$(printf $domain | cut -d . -f $i-100) h=$(printf "%s" "$domain" | cut -d . -f $i-100)
if [ -z "$h" ] ; then if [ -z "$h" ]; then
#not valid #not valid
return 1; return 1
fi fi
if ! _ovh_rest GET "domain/zone/$h" ; then if ! _ovh_rest GET "domain/zone/$h"; then
return 1 return 1
fi fi
if ! _contains "$response" "This service does not exist" >/dev/null ; then if ! _contains "$response" "This service does not exist" >/dev/null; then
_sub_domain=$(printf $domain | cut -d . -f 1-$p) _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain=$h _domain="$h"
return 0 return 0
fi fi
p=$i p=$i
i=$(expr $i + 1) i=$(_math "$i" + 1)
done done
return 1 return 1
} }
...@@ -272,9 +262,8 @@ _ovh_rest() { ...@@ -272,9 +262,8 @@ _ovh_rest() {
m=$1 m=$1
ep="$2" ep="$2"
data="$3" data="$3"
_debug $ep _debug "$ep"
_ovh_url="$OVH_API/$ep" _ovh_url="$OVH_API/$ep"
_debug2 _ovh_url "$_ovh_url" _debug2 _ovh_url "$_ovh_url"
_ovh_t="$(_ovh_timestamp)" _ovh_t="$(_ovh_timestamp)"
...@@ -283,7 +272,6 @@ _ovh_rest() { ...@@ -283,7 +272,6 @@ _ovh_rest() {
_debug _ovh_p "$_ovh_p" _debug _ovh_p "$_ovh_p"
_ovh_hex="$(printf "%s" "$_ovh_p" | _digest sha1 hex)" _ovh_hex="$(printf "%s" "$_ovh_p" | _digest sha1 hex)"
_debug2 _ovh_hex "$_ovh_hex" _debug2 _ovh_hex "$_ovh_hex"
_H1="X-Ovh-Application: $OVH_AK" _H1="X-Ovh-Application: $OVH_AK"
_H2="X-Ovh-Signature: \$1\$$_ovh_hex" _H2="X-Ovh-Signature: \$1\$$_ovh_hex"
...@@ -291,19 +279,17 @@ _ovh_rest() { ...@@ -291,19 +279,17 @@ _ovh_rest() {
_H3="X-Ovh-Timestamp: $_ovh_t" _H3="X-Ovh-Timestamp: $_ovh_t"
_H4="X-Ovh-Consumer: $OVH_CK" _H4="X-Ovh-Consumer: $OVH_CK"
_H5="Content-Type: application/json;charset=utf-8" _H5="Content-Type: application/json;charset=utf-8"
if [ "$data" ] || [ "$m" = "POST" ] || [ "$m" = "PUT" ] ; then if [ "$data" ] || [ "$m" = "POST" ] || [ "$m" = "PUT" ]; then
_debug data "$data" _debug data "$data"
response="$(_post "$data" "$_ovh_url" "" $m)" response="$(_post "$data" "$_ovh_url" "" "$m")"
else else
response="$(_get "$_ovh_url")" response="$(_get "$_ovh_url")"
fi fi
if [ "$?" != "0" ] ; then if [ "$?" != "0" ]; then
_err "error $ep" _err "error $ep"
return 1 return 1
fi fi
_debug2 response "$response" _debug2 response "$response"
return 0 return 0
} }
...@@ -16,70 +16,71 @@ dns_pdns_add() { ...@@ -16,70 +16,71 @@ dns_pdns_add() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
if [ -z "$PDNS_Url" ] ; then if [ -z "$PDNS_Url" ]; then
PDNS_Url=""
_err "You don't specify PowerDNS address." _err "You don't specify PowerDNS address."
_err "Please set PDNS_Url and try again." _err "Please set PDNS_Url and try again."
return 1 return 1
fi fi
if [ -z "$PDNS_ServerId" ] ; then if [ -z "$PDNS_ServerId" ]; then
PDNS_ServerId=""
_err "You don't specify PowerDNS server id." _err "You don't specify PowerDNS server id."
_err "Please set you PDNS_ServerId and try again." _err "Please set you PDNS_ServerId and try again."
return 1 return 1
fi fi
if [ -z "$PDNS_Token" ] ; then if [ -z "$PDNS_Token" ]; then
PDNS_Token=""
_err "You don't specify PowerDNS token." _err "You don't specify PowerDNS token."
_err "Please create you PDNS_Token and try again." _err "Please create you PDNS_Token and try again."
return 1 return 1
fi fi
if [ -z "$PDNS_Ttl" ] ; then if [ -z "$PDNS_Ttl" ]; then
PDNS_Ttl=$DEFAULT_PDNS_TTL PDNS_Ttl="$DEFAULT_PDNS_TTL"
fi fi
#save the api addr and key to the account conf file. #save the api addr and key to the account conf file.
_saveaccountconf PDNS_Url "$PDNS_Url" _saveaccountconf PDNS_Url "$PDNS_Url"
_saveaccountconf PDNS_ServerId "$PDNS_ServerId" _saveaccountconf PDNS_ServerId "$PDNS_ServerId"
_saveaccountconf PDNS_Token "$PDNS_Token" _saveaccountconf PDNS_Token "$PDNS_Token"
if [ "$PDNS_Ttl" != "$DEFAULT_PDNS_TTL" ] ; then if [ "$PDNS_Ttl" != "$DEFAULT_PDNS_TTL" ]; then
_saveaccountconf PDNS_Ttl "$PDNS_Ttl" _saveaccountconf PDNS_Ttl "$PDNS_Ttl"
fi fi
_debug "First detect the root zone" _debug "First detect the root zone"
if ! _get_root $fulldomain ; then if ! _get_root "$fulldomain"; then
_err "invalid domain" _err "invalid domain"
return 1 return 1
fi fi
_debug _domain "$_domain" _debug _domain "$_domain"
if ! set_record "$_domain" "$fulldomain" "$txtvalue" ; then if ! set_record "$_domain" "$fulldomain" "$txtvalue"; then
return 1 return 1
fi fi
return 0 return 0
} }
#fulldomain #fulldomain
dns_pdns_rm() { dns_pdns_rm() {
fulldomain=$1 fulldomain=$1
} }
set_record() { set_record() {
_info "Adding record" _info "Adding record"
root=$1 root=$1
full=$2 full=$2
txtvalue=$3 txtvalue=$3
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root." "{\"rrsets\": [{\"name\": \"$full.\", \"changetype\": \"REPLACE\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [{\"name\": \"$full.\", \"type\": \"TXT\", \"content\": \"\\\"$txtvalue\\\"\", \"disabled\": false, \"ttl\": $PDNS_Ttl}]}]}" ; then if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root." "{\"rrsets\": [{\"name\": \"$full.\", \"changetype\": \"REPLACE\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [{\"name\": \"$full.\", \"type\": \"TXT\", \"content\": \"\\\"$txtvalue\\\"\", \"disabled\": false, \"ttl\": $PDNS_Ttl}]}]}"; then
_err "Set txt record error." _err "Set txt record error."
return 1 return 1
fi fi
if ! _pdns_rest "PUT" "/api/v1/servers/$PDNS_ServerId/zones/$root./notify" ; then if ! _pdns_rest "PUT" "/api/v1/servers/$PDNS_ServerId/zones/$root./notify"; then
_err "Notify servers error." _err "Notify servers error."
return 1 return 1
fi fi
...@@ -93,25 +94,23 @@ set_record() { ...@@ -93,25 +94,23 @@ set_record() {
_get_root() { _get_root() {
domain=$1 domain=$1
i=1 i=1
p=1
if _pdns_rest "GET" "/api/v1/servers/$PDNS_ServerId/zones" ; then if _pdns_rest "GET" "/api/v1/servers/$PDNS_ServerId/zones"; then
_zones_response=$response _zones_response="$response"
fi fi
while [ '1' ] ; do while true; do
h=$(printf $domain | cut -d . -f $i-100) h=$(printf "%s" "$domain" | cut -d . -f $i-100)
if [ -z "$h" ] ; then if [ -z "$h" ]; then
return 1 return 1
fi fi
if printf "$_zones_response" | grep "\"name\": \"$h.\"" >/dev/null ; then if _contains "$_zones_response" "\"name\": \"$h.\""; then
_domain=$h _domain="$h"
return 0 return 0
fi fi
p=$i i=$(_math $i + 1)
i=$(expr $i + 1)
done done
_debug "$domain not found" _debug "$domain not found"
return 1 return 1
...@@ -124,18 +123,18 @@ _pdns_rest() { ...@@ -124,18 +123,18 @@ _pdns_rest() {
_H1="X-API-Key: $PDNS_Token" _H1="X-API-Key: $PDNS_Token"
if [ ! "$method" = "GET" ] ; then if [ ! "$method" = "GET" ]; then
_debug data "$data" _debug data "$data"
response="$(_post "$data" "$PDNS_Url$ep" "" "$method")" response="$(_post "$data" "$PDNS_Url$ep" "" "$method")"
else else
response="$(_get "$PDNS_Url$ep")" response="$(_get "$PDNS_Url$ep")"
fi fi
if [ "$?" != "0" ] ; then if [ "$?" != "0" ]; then
_err "error $ep" _err "error $ep"
return 1 return 1
fi fi
_debug2 response "$response" _debug2 response "$response"
return 0 return 0
} }
\ No newline at end of file
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