7 PROJECT_ENTRY
="acme.sh"
9 PROJECT
="https://github.com/Neilpang/$PROJECT_NAME"
11 DEFAULT_INSTALL_HOME
="$HOME/.$PROJECT_NAME"
14 _SUB_FOLDERS
="dnsapi deploy"
16 DEFAULT_CA
="https://acme-v01.api.letsencrypt.org"
17 DEFAULT_AGREEMENT
="https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf"
19 DEFAULT_USER_AGENT
="$PROJECT_NAME/$VER ($PROJECT)"
20 DEFAULT_ACCOUNT_EMAIL
=""
22 DEFAULT_ACCOUNT_KEY_LENGTH
=2048
23 DEFAULT_DOMAIN_KEY_LENGTH
=2048
25 STAGE_CA
="https://acme-staging.api.letsencrypt.org"
29 VTYPE_TLS
="tls-sni-01"
30 #VTYPE_TLS2="tls-sni-02"
32 LOCAL_ANY_ADDRESS
="0.0.0.0"
42 STATE_VERIFIED
="verified_ok"
44 BEGIN_CSR
="-----BEGIN CERTIFICATE REQUEST-----"
45 END_CSR
="-----END CERTIFICATE REQUEST-----"
47 BEGIN_CERT
="-----BEGIN CERTIFICATE-----"
48 END_CERT
="-----END CERTIFICATE-----"
53 ECC_SUFFIX
="${ECC_SEP}ecc"
58 DEFAULT_LOG_LEVEL
="$LOG_LEVEL_1"
60 _DEBUG_WIKI
="https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh"
68 if [ "$__INTERACTIVE" ]; then
69 printf '\033[1;31;32m'
72 if [ "$__INTERACTIVE" ]; then
78 if [ "$__INTERACTIVE" ]; then
79 printf '\033[1;31;40m'
82 if [ "$__INTERACTIVE" ]; then
89 printf -- "[$(date)] $1"
91 printf -- "[$(date)] $1='$2'"
97 echo "Diagnosis versions: "
99 if _exists openssl
; then
102 echo "openssl doesn't exists."
106 if [ "$_APACHECTL" ] && _exists
"$_APACHECTL"; then
109 echo "apache doesn't exists."
113 if _exists
"nc"; then
116 _debug
"nc doesn't exists."
121 [ -z "$LOG_FILE" ] && return
122 _printargs
"$@" >>"$LOG_FILE"
132 printf -- "[$(date)] " >&2
148 if [ -z "$LOG_LEVEL" ] ||
[ "$LOG_LEVEL" -ge "$LOG_LEVEL_1" ]; then
151 if [ -z "$DEBUG" ]; then
158 if [ "$LOG_LEVEL" ] && [ "$LOG_LEVEL" -ge "$LOG_LEVEL_2" ]; then
161 if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
167 if [ "$LOG_LEVEL" ] && [ "$LOG_LEVEL" -ge "$LOG_LEVEL_3" ]; then
170 if [ "$DEBUG" ] && [ "$DEBUG" -ge "3" ]; then
178 echo "$_str" |
grep "^$_sub" >/dev
/null
2>&1
184 echo "$_str" |
grep -- "$_sub\$" >/dev
/null
2>&1
190 echo "$_str" |
grep -- "$_sub" >/dev
/null
2>&1
197 if [ -z "$_field" ]; then
198 _usage
"Usage: str field [sep]"
202 if [ -z "$_sep" ]; then
206 for f
in $
(echo "$_str" |
tr ',' ' '); do
207 if [ "$f" = "$_field" ]; then
208 _debug2
"'$_str' contains '$_field'"
209 return 0 #contains ok
212 _debug2
"'$_str' does not contain '$_field'"
213 return 1 #not contains
221 if [ -z "$_findex" ]; then
222 _usage
"Usage: str field [sep]"
226 if [ -z "$_sep" ]; then
231 while [ "$_ffi" -gt "0" ]; do
232 _fv
="$(echo "$_str" | cut -d "$_sep" -f "$_ffi")"
234 printf -- "%s" "$_fv"
237 _ffi
="$(_math "$_ffi" - 1)"
240 printf -- "%s" "$_str"
246 if [ -z "$cmd" ]; then
247 _usage
"Usage: _exists cmd"
250 if command >/dev
/null
2>&1; then
251 command -v "$cmd" >/dev
/null
2>&1
252 elif which ls >/dev
/null
2>&1; then
253 which "$cmd" >/dev
/null
2>&1
256 _debug3
"$cmd exists=$ret"
263 printf "%s" "$(($_m_opts))"
295 if [ "$(printf '\x41')" != 'A' ]; then
304 _debug3 _URGLY_PRINTF
"$_URGLY_PRINTF"
306 if [ -z "$_URGLY_PRINTF" ]; then
307 h
="$(printf "%s
" "$hex" | cut -c $i-$j)"
313 ic
="$(printf "%s
" "$hex" | cut -c $i)"
314 jc
="$(printf "%s
" "$hex" | cut -c $j)"
315 if [ -z "$ic$jc" ]; then
318 ic
="$(_h_char_2_dec "$ic")"
319 jc
="$(_h_char_2_dec "$jc")"
320 printf '\'"$(printf "%o" "$(_math "$ic" \* 16 + $jc)")""%s"
323 i="$(_math "$i" + 2)"
324 j="$(_math "$j" + 2)"
333 if [ -z "$filename" ]; then
334 _usage "Usage:_sed_i options filename"
337 _debug2 options "$options"
338 if sed -h 2>&1 | grep "\-i\[SUFFIX]" >/dev/null 2>&1; then
339 _debug "Using sed -i"
340 sed -i "$options" "$filename"
342 _debug "No -i support in sed"
343 text="$(cat "$filename")"
344 echo "$text" | sed "$options" >"$filename"
349 if _contains "$(egrep -o 2>&1)" "egrep: illegal option -- o"; then
350 sed -n 's
/.
*\
('"$1"'\
).
*/\
1/p
'
356 #Usage: file startline endline
361 if [ -z "$endline" ]; then
362 _usage "Usage: file startline endline"
366 i="$(grep -n -- "$startline" "$filename" | cut -d : -f 1)"
368 _err "Can not find start line: $startline"
371 i="$(_math "$i" + 1)"
374 j="$(grep -n -- "$endline" "$filename" | cut -d : -f 1)"
376 _err "Can not find end line: $endline"
379 j="$(_math "$j" - 1)"
382 sed -n "$i,${j}p" "$filename"
391 openssl base64 -e | tr -d '\r\n'
404 #Usage: hashalg [outputhex]
405 #Output Base64-encoded digest
408 if [ -z "$alg" ]; then
409 _usage "Usage: _digest hashalg"
415 if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ] || [ "$alg" = "md5" ]; then
416 if [ "$outputhex" ]; then
417 openssl dgst -"$alg" -hex | cut -d = -f 2 | tr -d ' '
419 openssl dgst -"$alg" -binary | _base64
422 _err "$alg is not supported yet"
428 #Usage: hashalg secret [outputhex]
429 #Output Base64-encoded hmac
435 if [ -z "$hmac_sec" ]; then
436 _usage "Usage: _hmac hashalg secret [outputhex]"
440 if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ]; then
441 if [ "$outputhex" ]; then
442 openssl dgst -"$alg" -hmac "$hmac_sec" | cut -d = -f 2 | tr -d ' '
444 openssl dgst -"$alg" -hmac "$hmac_sec" -binary | _base64
447 _err "$alg is not supported yet"
453 #Usage: keyfile hashalg
454 #Output: Base64-encoded signature value
458 if [ -z "$alg" ]; then
459 _usage "Usage: _sign keyfile hashalg"
463 _sign_openssl="openssl dgst -sign $keyfile "
464 if [ "$alg" = "sha256" ]; then
465 _sign_openssl="$_sign_openssl -$alg"
467 _err "$alg is not supported yet"
471 if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
472 $_sign_openssl | _base64
473 elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
474 if ! _signedECText="$($_sign_openssl | openssl asn1parse -inform DER)"; then
475 _err "Sign failed: $_sign_openssl"
476 _err "Key file: $keyfile"
477 _err "Key content:$(wc -l <"$keyfile") lises"
480 _debug3 "_signedECText" "$_signedECText"
481 _ec_r="$(echo "$_signedECText" | _head_n 2 | _tail_n 1 | cut -d : -f 4 | tr -d "\r\n")"
482 _debug3 "_ec_r" "$_ec_r"
483 _ec_s="$(echo "$_signedECText" | _head_n 3 | _tail_n 1 | cut -d : -f 4 | tr -d "\r\n")"
484 _debug3 "_ec_s" "$_ec_s"
485 printf "%s" "$_ec_r$_ec_s" | _h2b | _base64
487 _err "Unknown key file format."
497 if [ -z "$_length" ]; then
501 [ "$_length" != "1024" ] \
502 && [ "$_length" != "2048" ] \
503 && [ "$_length" != "3072" ] \
504 && [ "$_length" != "4096" ] \
505 && [ "$_length" != "8192" ]
508 # _createkey 2048|ec-256 file
513 if _startswith "$length" "ec-"; then
514 length=$(printf "%s" "$length" | cut -d '-' -f 2-100)
516 if [ "$length" = "256" ]; then
519 if [ "$length" = "384" ]; then
522 if [ "$length" = "521" ]; then
528 if [ -z "$length" ]; then
532 _debug "Use length $length"
534 if _isEccKey "$length"; then
535 _debug "Using ec name: $eccname"
536 openssl ecparam -name "$eccname" -genkey 2>/dev/null >"$f"
538 _debug "Using RSA: $length"
539 openssl genrsa "$length" 2>/dev/null >"$f"
542 if [ "$?" != "0" ]; then
543 _err "Create key error."
551 _debug2 _is_idn_d "$_is_idn_d"
552 _idn_temp=$(printf "%s" "$_is_idn_d" | tr -d '[0-9]' | tr -d '[a-z
]' | tr -d '[A-Z
]' | tr -d '.
,-')
553 _debug2 _idn_temp "$_idn_temp"
558 #aa.com,bb.com,cc.com
561 if ! _is_idn "$__idn_d"; then
562 printf "%s" "$__idn_d"
567 if _contains "$__idn_d" ','; then
569 for f in $(echo "$__idn_d" | tr ',' ' '); do
570 [ -z "$f" ] && continue
571 if [ -z "$_i_first" ]; then
576 idn --quiet "$f" | tr -d "\r\n"
579 idn "$__idn_d" | tr -d "\r\n"
582 _err "Please install idn to process IDN names."
586 #_createcsr cn san_list keyfile csrfile conf
594 _debug2 domain "$domain"
595 _debug2 domainlist "$domainlist"
596 _debug2 csrkey "$csrkey"
598 _debug2 csrconf "$csrconf"
600 printf "[ req_distinguished_name ]\n[ req ]\ndistinguished_name = req_distinguished_name\nreq_extensions = v3_req\n[ v3_req ]\n\nkeyUsage = nonRepudiation, digitalSignature, keyEncipherment" >"$csrconf"
602 if [ -z "$domainlist" ] || [ "$domainlist" = "$NO_VALUE" ]; then
604 _info "Single domain" "$domain"
606 domainlist="$(_idn "$domainlist")"
607 _debug2 domainlist "$domainlist"
608 if _contains "$domainlist" ","; then
609 alt="DNS:$(echo "$domainlist" | sed "s/,/,DNS:/g")"
611 alt="DNS:$domainlist"
614 _info "Multi domain" "$alt"
615 printf -- "\nsubjectAltName=$alt" >>"$csrconf"
617 if [ "$Le_OCSP_Stable" ]; then
618 _savedomainconf Le_OCSP_Stable "$Le_OCSP_Stable"
619 printf -- "\nbasicConstraints = CA:FALSE\n1.3.6.1.5.5.7.1.24=DER:30:03:02:01:05" >>"$csrconf"
622 _csr_cn="$(_idn "$domain")"
623 _debug2 _csr_cn "$_csr_cn"
624 openssl req -new -sha256 -key "$csrkey" -subj "/CN=$_csr_cn" -config "$csrconf" -out "$csr"
627 #_signcsr key csr conf cert
635 _msg="$(openssl x509 -req -days 365 -in "$csr" -signkey "$key" -extensions v3_req -extfile "$conf" -out "$cert" 2>&1)"
642 _readSubjectFromCSR() {
644 if [ -z "$_csrfile" ]; then
645 _usage "_readSubjectFromCSR mycsr.csr"
648 openssl req -noout -in "$_csrfile" -subject | _egrep_o "CN=.*" | cut -d = -f 2 | cut -d / -f 1 | tr -d '\n'
652 #echo comma separated domain list
653 _readSubjectAltNamesFromCSR() {
655 if [ -z "$_csrfile" ]; then
656 _usage "_readSubjectAltNamesFromCSR mycsr.csr"
660 _csrsubj="$(_readSubjectFromCSR "$_csrfile")"
661 _debug _csrsubj "$_csrsubj"
663 _dnsAltnames="$(openssl req -noout -text -in "$_csrfile" | grep "^ *DNS:.*" | tr -d ' \n')"
664 _debug _dnsAltnames "$_dnsAltnames"
666 if _contains "$_dnsAltnames," "DNS:$_csrsubj,"; then
667 _debug "AltNames contains subject"
668 _dnsAltnames="$(printf "%s" "$_dnsAltnames," | sed "s/DNS:$_csrsubj,//g")"
670 _debug "AltNames doesn't contain subject
"
673 printf "%s
" "$_dnsAltnames" | sed "s
/DNS
://g
"
677 _readKeyLengthFromCSR() {
679 if [ -z "$_csrfile" ]; then
680 _usage "_readKeyLengthFromCSR mycsr.csr
"
684 _outcsr="$
(openssl req
-noout -text -in "$_csrfile")"
685 if _contains "$_outcsr" "Public Key Algorithm
: id-ecPublicKey
"; then
687 echo "$_outcsr" | _egrep_o "^
*ASN1 OID
:.
*" | cut -d ':' -f 2 | tr -d ' '
690 echo "$_outcsr" | _egrep_o "^
*Public-Key
:.
*" | cut -d '(' -f 2 | cut -d ' ' -f 1
697 if _exists "ss
"; then
699 ss -ntpl | grep ":$_port "
703 if _exists "netstat
"; then
704 _debug "Using
: netstat
"
705 if netstat -h 2>&1 | grep "\
-p proto
" >/dev/null; then
706 #for windows version netstat tool
707 netstat -an -p tcp | grep "LISTENING
" | grep ":$_port "
709 if netstat -help 2>&1 | grep "\
-p protocol
" >/dev/null; then
710 netstat -an -p tcp | grep LISTEN | grep ":$_port "
711 elif netstat -help 2>&1 | grep -- '-P protocol' >/dev/null; then
713 netstat -an -P tcp | grep "\.
$_port " | grep "LISTEN
"
715 netstat -ntpl | grep ":$_port "
724 #domain [password] [isEcc]
728 if [ -z "$domain" ]; then
729 _usage "Usage
: $PROJECT_ENTRY --toPkcs -d domain
[--password pfx-password
]"
735 _initpath "$domain" "$_isEcc"
737 if [ "$pfxPassword" ]; then
738 openssl pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH" -password "pass
:$pfxPassword"
740 openssl pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH"
743 if [ "$?
" = "0" ]; then
744 _info "Success
, Pfx is exported to
: $CERT_PFX_PATH"
751 _info "Creating account key
"
753 _usage "Usage
: $PROJECT_ENTRY --createAccountKey --accountkeylength 2048"
758 _create_account_key "$length"
762 _create_account_key() {
766 if [ -z "$length" ] || [ "$length" = "$NO_VALUE" ]; then
767 _debug "Use default length
$DEFAULT_ACCOUNT_KEY_LENGTH"
768 length="$DEFAULT_ACCOUNT_KEY_LENGTH"
771 _debug length "$length"
775 if [ -f "$ACCOUNT_KEY_PATH" ]; then
776 _info "Account key exists
, skip
"
779 #generate account key
780 _createkey "$length" "$ACCOUNT_KEY_PATH"
787 _info "Creating domain key
"
789 _usage "Usage
: $PROJECT_ENTRY --createDomainKey -d domain.com
[ --keylength 2048 ]"
796 if [ -z "$length" ]; then
797 _debug "Use DEFAULT_DOMAIN_KEY_LENGTH
=$DEFAULT_DOMAIN_KEY_LENGTH"
798 length="$DEFAULT_DOMAIN_KEY_LENGTH"
801 _initpath "$domain" "$length"
803 if [ ! -f "$CERT_KEY_PATH" ] || ([ "$FORCE" ] && ! [ "$IS_RENEW" ]); then
804 _createkey "$length" "$CERT_KEY_PATH"
806 if [ "$IS_RENEW" ]; then
807 _info "Domain key exists
, skip
"
810 _err "Domain key exists
, do you want to overwrite the key?
"
811 _err "Add
'--force', and try again.
"
818 # domain domainlist isEcc
822 _usage "Usage
: $PROJECT_ENTRY --createCSR -d domain1.com
[-d domain2.com
-d domain3.com ...
]"
830 _initpath "$domain" "$_isEcc"
832 if [ -f "$CSR_PATH" ] && [ "$IS_RENEW" ] && [ -z "$FORCE" ]; then
833 _info "CSR exists
, skip
"
837 if [ ! -f "$CERT_KEY_PATH" ]; then
838 _err "The key
file is not found
: $CERT_KEY_PATH"
839 _err "Please create the key
file first.
"
842 _createcsr "$domain" "$domainlist" "$CERT_KEY_PATH" "$CSR_PATH" "$DOMAIN_SSL_CONF"
847 tr '/+' '_-' | tr -d '= '
852 if date -u -d@"$1" 2>/dev/null; then
857 if date -u -r "$1" 2>/dev/null; then
863 _t_s_a=$(echo "0t
${1}=Y
" | adb)
870 sed "s
/\" *: *\
([\"{\
[]\
)/\":\
1/g
" | sed "s
/^
*\
([^
]\
)/\
1/" | tr -d "\r\n"
875 if stat -c '%U:%G' "$1" 2>/dev/null; then
880 if stat -f '%Su:%Sg' "$1" 2>/dev/null; then
884 return 1 #error, 'stat' not found
890 if [ -z "$keyfile" ]; then
891 _usage "Usage
: _calcjwk keyfile
"
895 if [ "$JWK_HEADER" ] && [ "$__CACHED_JWK_KEY_FILE" = "$keyfile" ]; then
896 _debug2 "Use cached jwk
for file: $__CACHED_JWK_KEY_FILE"
900 if grep "BEGIN RSA PRIVATE KEY
" "$keyfile" >/dev/null 2>&1; then
902 pub_exp=$(openssl rsa -in "$keyfile" -noout -text | grep "^publicExponent
:" | cut -d '(' -f 2 | cut -d 'x' -f 2 | cut -d ')' -f 1)
903 if [ "${#pub_exp}" = "5" ]; then
906 _debug3 pub_exp "$pub_exp"
908 e=$(echo "$pub_exp" | _h2b | _base64)
911 modulus=$(openssl rsa -in "$keyfile" -modulus -noout | cut -d '=' -f 2)
912 _debug3 modulus "$modulus"
913 n="$
(printf "%s" "$modulus" | _h2b | _base64 | _urlencode
)"
914 jwk='{"e
": "'$e'", "kty
": "RSA
", "n
": "'$n'"}'
917 JWK_HEADER='{"alg
": "RS256
", "jwk
": '$jwk'}'
918 JWK_HEADERPLACE_PART1='{"nonce
": "'
919 JWK_HEADERPLACE_PART2='", "alg
": "RS256
", "jwk
": '$jwk'}'
920 elif grep "BEGIN EC PRIVATE KEY
" "$keyfile" >/dev/null 2>&1; then
922 crv="$
(openssl ec
-in "$keyfile" -noout -text 2>/dev
/null |
grep "^NIST CURVE:" | cut
-d ":" -f 2 |
tr -d " \r\n")"
925 if [ -z "$crv" ]; then
926 _debug "Let
's try ASN1 OID"
927 crv_oid="$(openssl ec -in "$keyfile" -noout -text 2>/dev/null | grep "^ASN1 OID:" | cut -d ":" -f 2 | tr -d " \r\n")"
928 _debug3 crv_oid "$crv_oid"
940 _err "ECC oid : $crv_oid"
947 pubi="$(openssl ec -in "$keyfile" -noout -text 2>/dev/null | grep -n pub: | cut -d : -f 1)"
948 pubi=$(_math "$pubi" + 1)
951 pubj="$(openssl ec -in "$keyfile" -noout -text 2>/dev/null | grep -n "ASN1 OID:" | cut -d : -f 1)"
952 pubj=$(_math "$pubj" - 1)
955 pubtext="$(openssl ec -in "$keyfile" -noout -text 2>/dev/null | sed -n "$pubi,${pubj}p" | tr -d " \n\r")"
956 _debug3 pubtext "$pubtext"
958 xlen="$(printf "%s" "$pubtext" | tr -d ':' | wc -c)"
959 xlen=$(_math "$xlen" / 4)
962 xend=$(_math "$xlen" + 1)
963 x="$(printf "%s" "$pubtext" | cut -d : -f 2-"$xend")"
966 x64="$(printf "%s" "$x" | tr -d : | _h2b | _base64 | _urlencode)"
969 xend=$(_math "$xend" + 1)
970 y="$(printf "%s" "$pubtext" | cut -d : -f "$xend"-10000)"
973 y64="$(printf "%s" "$y" | tr -d : | _h2b | _base64 | _urlencode)"
976 jwk='{"crv": "'$crv'", "kty": "EC", "x": "'$x64'", "y": "'$y64'"}'
979 JWK_HEADER='{"alg": "ES256", "jwk": '$jwk'}'
980 JWK_HEADERPLACE_PART1='{"nonce": "'
981 JWK_HEADERPLACE_PART2='", "alg": "ES256", "jwk": '$jwk'}'
983 _err "Only RSA or EC key is supported."
987 _debug3 JWK_HEADER "$JWK_HEADER"
988 __CACHED_JWK_KEY_FILE="$keyfile"
996 if _exists mktemp; then
997 if mktemp 2>/dev/null; then
999 elif _contains "$(mktemp 2>&1)" "-t prefix" && mktemp -t "$PROJECT_NAME" 2>/dev/null; then
1004 if [ -d "/tmp" ]; then
1005 echo "/tmp/${PROJECT_NAME}wefADf24sf.$(_time).tmp"
1007 elif [ "$LE_TEMP_DIR" ] && mkdir -p "$LE_TEMP_DIR"; then
1008 echo "/$LE_TEMP_DIR/wefADf24sf.$(_time).tmp"
1011 _err "Can not create temp file."
1016 if [ -z "$HTTP_HEADER" ] || ! touch "$HTTP_HEADER"; then
1017 HTTP_HEADER="$(_mktemp)"
1018 _debug2 HTTP_HEADER "$HTTP_HEADER"
1021 if [ "$__HTTP_INITIALIZED" ]; then
1022 if [ "$_ACME_CURL$_ACME_WGET" ]; then
1023 _debug2 "Http already initialized."
1028 if [ -z "$_ACME_CURL" ] && _exists "curl"; then
1029 _ACME_CURL="curl -L --silent --dump-header $HTTP_HEADER "
1030 if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
1031 _CURL_DUMP="$(_mktemp)"
1032 _ACME_CURL="$_ACME_CURL --trace-ascii $_CURL_DUMP "
1035 if [ "$CA_BUNDLE" ]; then
1036 _ACME_CURL="$_ACME_CURL --cacert $CA_BUNDLE "
1039 if [ "$HTTPS_INSECURE" ]; then
1040 _ACME_CURL="$_ACME_CURL --insecure "
1044 if [ -z "$_ACME_WGET" ] && _exists "wget"; then
1045 _ACME_WGET="wget -q"
1046 if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
1047 _ACME_WGET="$_ACME_WGET -d "
1049 if [ "$CA_BUNDLE" ]; then
1050 _ACME_WGET="$_ACME_WGET --ca-certificate $CA_BUNDLE "
1052 if [ "$HTTPS_INSECURE" ]; then
1053 _ACME_WGET="$_ACME_WGET --no-check-certificate "
1057 __HTTP_INITIALIZED=1
1061 # body url [needbase64] [POST|PUT]
1068 if [ -z "$httpmethod" ]; then
1073 _debug2 "body" "$body"
1077 if [ "$_ACME_CURL" ]; then
1079 _debug "_CURL" "$_CURL"
1080 if [ "$needbase64" ]; then
1081 response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$url" | _base64)"
1083 response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$url")"
1086 if [ "$_ret" != "0" ]; then
1087 _err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $_ret"
1088 if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
1089 _err "Here is the curl dump log:"
1090 _err "$(cat "$_CURL_DUMP")"
1093 elif [ "$_ACME_WGET" ]; then
1094 _debug "_ACME_WGET" "$_ACME_WGET"
1095 if [ "$needbase64" ]; then
1096 if [ "$httpmethod" = "POST" ]; then
1097 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)"
1099 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)"
1102 if [ "$httpmethod" = "POST" ]; then
1103 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")"
1105 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")"
1109 if [ "$_ret" = "8" ]; then
1111 _debug "wget returns 8, the server returns a 'Bad request
' respons, lets process the response later."
1113 if [ "$_ret" != "0" ]; then
1114 _err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $_ret"
1116 _sed_i "s/^ *//g" "$HTTP_HEADER"
1119 _err "Neither curl nor wget is found, can not do $httpmethod."
1121 _debug "_ret" "$_ret"
1122 printf "%s" "$response"
1126 # url getheader timeout
1133 _debug "timeout" "$t"
1137 if [ "$_ACME_CURL" ]; then
1140 _CURL="$_CURL --connect-timeout $t"
1142 _debug "_CURL" "$_CURL"
1143 if [ "$onlyheader" ]; then
1144 $_CURL -I --user-agent "$USER_AGENT" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$url"
1146 $_CURL --user-agent "$USER_AGENT" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$url"
1149 if [ "$ret" != "0" ]; then
1150 _err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $ret"
1151 if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
1152 _err "Here is the curl dump log:"
1153 _err "$(cat "$_CURL_DUMP")"
1156 elif [ "$_ACME_WGET" ]; then
1159 _WGET="$_WGET --timeout=$t"
1161 _debug "_WGET" "$_WGET"
1162 if [ "$onlyheader" ]; then
1163 $_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
'
1165 $_WGET --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" -O - "$url"
1168 if [ "$_ret" = "8" ]; then
1170 _debug "wget returns 8, the server returns a 'Bad request
' respons, lets process the response later."
1172 if [ "$ret" != "0" ]; then
1173 _err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $ret"
1177 _err "Neither curl nor wget is found, can not do GET."
1188 if ! tail -n "$1" 2>/dev/null; then
1194 # url payload needbase64 keyfile
1195 _send_signed_request() {
1200 if [ -z "$keyfile" ]; then
1201 keyfile="$ACCOUNT_KEY_PATH"
1204 _debug payload "$payload"
1206 if ! _calcjwk "$keyfile"; then
1210 payload64=$(printf "%s" "$payload" | _base64 | _urlencode)
1211 _debug3 payload64 "$payload64"
1213 if [ -z "$_CACHED_NONCE" ]; then
1214 _debug2 "Get nonce."
1215 nonceurl="$API/directory"
1216 _headers="$(_get "$nonceurl" "onlyheader")"
1218 if [ "$?" != "0" ]; then
1219 _err "Can not connect to $nonceurl to get nonce."
1223 _debug2 _headers "$_headers"
1225 _CACHED_NONCE="$(echo "$_headers" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)"
1226 _debug2 _CACHED_NONCE "$_CACHED_NONCE"
1228 _debug2 "Use _CACHED_NONCE" "$_CACHED_NONCE"
1230 nonce="$_CACHED_NONCE"
1231 _debug2 nonce "$nonce"
1233 protected="$JWK_HEADERPLACE_PART1$nonce$JWK_HEADERPLACE_PART2"
1234 _debug3 protected "$protected"
1236 protected64="$(printf "%s" "$protected" | _base64 | _urlencode)"
1237 _debug3 protected64 "$protected64"
1239 if ! _sig_t="$(printf "%s" "$protected64.$payload64" | _sign "$keyfile" "sha256")"; then
1240 _err "Sign request failed."
1243 _debug3 _sig_t "$_sig_t"
1245 sig="$(printf "%s" "$_sig_t" | _urlencode)"
1248 body="{\"header\": $JWK_HEADER, \"protected\": \"$protected64\", \"payload\": \"$payload64\", \"signature\": \"$sig\"}"
1249 _debug3 body "$body"
1251 response="$(_post "$body" "$url" "$needbase64")"
1253 if [ "$?" != "0" ]; then
1254 _err "Can not post to $url"
1257 _debug2 original "$response"
1259 response="$(echo "$response" | _normalizeJson)"
1261 responseHeaders="$(cat "$HTTP_HEADER")"
1263 _debug2 responseHeaders "$responseHeaders"
1264 _debug2 response "$response"
1265 code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\r\n")"
1268 _CACHED_NONCE="$(echo "$responseHeaders" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)"
1272 #setopt "file" "opt" "=" "value" [";"]
1279 if [ -z "$__opt" ]; then
1280 _usage usage: _setopt '"file" "opt" "=" "value" [";"]'
1283 if [ ! -f "$__conf" ]; then
1287 if grep -n "^$__opt$__sep" "$__conf" >/dev/null; then
1289 if _contains "$__val" "&"; then
1290 __val="$(echo "$__val" | sed 's
/&/\\&/g
')"
1292 text="$(cat "$__conf")"
1293 echo "$text" | sed "s|^$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf"
1295 elif grep -n "^#$__opt$__sep" "$__conf" >/dev/null; then
1296 if _contains "$__val" "&"; then
1297 __val="$(echo "$__val" | sed 's
/&/\\&/g
')"
1299 text="$(cat "$__conf")"
1300 echo "$text" | sed "s|^#$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf"
1304 echo "$__opt$__sep$__val$__end" >>"$__conf"
1306 _debug2 "$(grep -n "^$__opt$__sep" "$__conf")"
1309 #_save_conf file key value
1315 if [ "$_s_c_f" ]; then
1316 _setopt "$_s_c_f" "$_sdkey" "=" "'$_sdvalue'"
1318 _err "config file is empty, can not save $_sdkey=$_sdvalue"
1322 #_clear_conf file key
1326 if [ "$_c_c_f" ]; then
1327 _conf_data="$(cat "$_c_c_f")"
1328 echo "$_conf_data" | sed "s/^$_sdkey *=.*$//" >"$_c_c_f"
1330 _err "config file is empty, can not clear"
1334 #_read_conf file key
1338 if [ -f "$_r_c_f" ]; then
1340 eval "$(grep "^$_sdkey *=" "$_r_c_f")"
1341 eval "printf \"%s\" \"\$$_sdkey\""
1344 _debug "config file is empty, can not read $_sdkey"
1348 #_savedomainconf key value
1349 #save to domain.conf
1351 _save_conf "$DOMAIN_CONF" "$1" "$2"
1354 #_cleardomainconf key
1355 _cleardomainconf() {
1356 _clear_conf "$DOMAIN_CONF" "$1"
1359 #_readdomainconf key
1361 _read_conf "$DOMAIN_CONF" "$1"
1364 #_saveaccountconf key value
1365 _saveaccountconf() {
1366 _save_conf "$ACCOUNT_CONF_PATH" "$1" "$2"
1369 #_clearaccountconf key
1370 _clearaccountconf() {
1371 _clear_conf "$ACCOUNT_CONF_PATH" "$1"
1374 #_savecaconf key value
1376 _save_conf "$CA_CONF" "$1" "$2"
1381 _read_conf "$CA_CONF" "$1"
1384 #_clearaccountconf key
1386 _clear_conf "$CA_CONF" "$1"
1389 # content localaddress
1393 _debug "ncaddr" "$ncaddr"
1395 _debug "startserver: $$"
1396 nchelp="$(nc -h 2>&1)"
1398 _debug Le_HTTPPort "$Le_HTTPPort"
1399 _debug Le_Listen_V4 "$Le_Listen_V4"
1400 _debug Le_Listen_V6 "$Le_Listen_V6"
1403 if [ "$Le_Listen_V4" ]; then
1405 elif [ "$Le_Listen_V6" ]; then
1409 if echo "$nchelp" | grep "\-q[ ,]" >/dev/null; then
1410 _NC="$_NC -q 1 -l $ncaddr"
1412 if echo "$nchelp" | grep "GNU netcat" >/dev/null && echo "$nchelp" | grep "\-c, \-\-close" >/dev/null; then
1413 _NC="$_NC -c -l $ncaddr"
1414 elif echo "$nchelp" | grep "\-N" | grep "Shutdown the network socket after EOF on stdin" >/dev/null; then
1415 _NC="$_NC -N -l $ncaddr"
1417 _NC="$_NC -l $ncaddr"
1424 if _contains "$nchelp" "nmap.org"; then
1425 _debug "Using ncat: nmap.org"
1426 if ! _exec "printf \"%s\r\n\r\n%s\" \"HTTP/1.1 200 OK\" \"$content\" | $_NC \"$Le_HTTPPort\" >&2"; then
1430 if [ "$DEBUG" ]; then
1437 if ! _exec "printf \"%s\r\n\r\n%s\" \"HTTP/1.1 200 OK\" \"$content\" | $_NC -p \"$Le_HTTPPort\" >&2"; then
1438 _exec "printf \"%s\r\n\r\n%s\" \"HTTP/1.1 200 OK\" \"$content\" | $_NC \"$Le_HTTPPort\" >&2"
1441 if [ "$?" != "0" ]; then
1442 _err "nc listen error."
1446 if [ "$DEBUG" ]; then
1455 if [ -z "$pid" ]; then
1459 _debug2 "Le_HTTPPort" "$Le_HTTPPort"
1460 if [ "$Le_HTTPPort" ]; then
1461 if [ "$DEBUG" ] && [ "$DEBUG" -gt "3" ]; then
1462 _get "http://localhost:$Le_HTTPPort" "" 1
1464 _get "http://localhost:$Le_HTTPPort" "" 1 >/dev/null 2>&1
1468 _debug2 "Le_TLSPort" "$Le_TLSPort"
1469 if [ "$Le_TLSPort" ]; then
1470 if [ "$DEBUG" ] && [ "$DEBUG" -gt "3" ]; then
1471 _get "https://localhost:$Le_TLSPort" "" 1
1472 _get "https://localhost:$Le_TLSPort" "" 1
1474 _get "https://localhost:$Le_TLSPort" "" 1 >/dev/null 2>&1
1475 _get "https://localhost:$Le_TLSPort" "" 1 >/dev/null 2>&1
1483 if [ "$__INTERACTIVE" ]; then
1484 _sleep_c="$_sleep_sec"
1485 while [ "$_sleep_c" -ge "0" ]; do
1488 _sleep_c="$(_math "$_sleep_c" - 1)"
1497 # _starttlsserver san_a san_b port content _ncaddr
1499 _info "Starting tls server."
1506 _debug san_a "$san_a"
1507 _debug san_b "$san_b"
1511 if ! _createkey "2048" "$TLS_KEY"; then
1512 _err "Create tls validation key error."
1518 if [ "$san_b" ]; then
1521 if ! _createcsr "tls.acme.sh" "$alt" "$TLS_KEY" "$TLS_CSR" "$TLS_CONF"; then
1522 _err "Create tls validation csr error."
1527 if ! _signcsr "$TLS_KEY" "$TLS_CSR" "$TLS_CONF" "$TLS_CERT"; then
1528 _err "Create tls validation cert error."
1532 __S_OPENSSL="openssl s_server -cert $TLS_CERT -key $TLS_KEY "
1533 if [ "$opaddr" ]; then
1534 __S_OPENSSL="$__S_OPENSSL -accept $opaddr:$port"
1536 __S_OPENSSL="$__S_OPENSSL -accept $port"
1539 _debug Le_Listen_V4 "$Le_Listen_V4"
1540 _debug Le_Listen_V6 "$Le_Listen_V6"
1541 if [ "$Le_Listen_V4" ]; then
1542 __S_OPENSSL="$__S_OPENSSL -4"
1543 elif [ "$Le_Listen_V6" ]; then
1544 __S_OPENSSL="$__S_OPENSSL -6"
1548 _debug "$__S_OPENSSL"
1549 if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
1550 (printf "%s\r\n\r\n%s" "HTTP/1.1 200 OK" "$content" | $__S_OPENSSL -tlsextdebug) &
1552 (printf "%s\r\n\r\n%s" "HTTP/1.1 200 OK" "$content" | $__S_OPENSSL >/dev/null 2>&1) &
1557 _debug serverproc "$serverproc"
1563 if ! readlink -f "$_rf" 2>/dev/null; then
1564 if _startswith "$_rf" "\./$PROJECT_ENTRY"; then
1565 printf -- "%s" "$(pwd)/$PROJECT_ENTRY"
1573 if [ -z "$_SCRIPT_HOME" ]; then
1574 if _exists readlink && _exists dirname; then
1575 _debug "Lets find script dir."
1576 _debug "_SCRIPT_" "$_SCRIPT_"
1577 _script="$(_readlink "$_SCRIPT_")"
1578 _debug "_script" "$_script"
1579 _script_home="$(dirname "$_script")"
1580 _debug "_script_home" "$_script_home"
1581 if [ -d "$_script_home" ]; then
1582 _SCRIPT_HOME="$_script_home"
1584 _err "It seems the script home is not correct:$_script_home"
1589 if [ -z "$LE_WORKING_DIR" ]; then
1590 if [ -f "$DEFAULT_INSTALL_HOME/account.conf" ]; then
1591 _debug "It seems that $PROJECT_NAME is already installed in $DEFAULT_INSTALL_HOME"
1592 LE_WORKING_DIR="$DEFAULT_INSTALL_HOME"
1594 LE_WORKING_DIR="$_SCRIPT_HOME"
1598 if [ -z "$LE_WORKING_DIR" ]; then
1599 _debug "Using default home:$DEFAULT_INSTALL_HOME"
1600 LE_WORKING_DIR="$DEFAULT_INSTALL_HOME"
1602 export LE_WORKING_DIR
1604 _DEFAULT_ACCOUNT_CONF_PATH="$LE_WORKING_DIR/account.conf"
1606 if [ -z "$ACCOUNT_CONF_PATH" ]; then
1607 if [ -f "$_DEFAULT_ACCOUNT_CONF_PATH" ]; then
1608 . "$_DEFAULT_ACCOUNT_CONF_PATH"
1612 if [ -z "$ACCOUNT_CONF_PATH" ]; then
1613 ACCOUNT_CONF_PATH="$_DEFAULT_ACCOUNT_CONF_PATH"
1616 DEFAULT_LOG_FILE="$LE_WORKING_DIR/$PROJECT_NAME.log"
1618 DEFAULT_CA_HOME="$LE_WORKING_DIR/ca"
1620 if [ -z "$LE_TEMP_DIR" ]; then
1621 LE_TEMP_DIR="$LE_WORKING_DIR/tmp"
1625 #[domain] [keylength]
1630 if [ -f "$ACCOUNT_CONF_PATH" ]; then
1631 . "$ACCOUNT_CONF_PATH"
1634 if [ "$IN_CRON" ]; then
1635 if [ ! "$_USER_PATH_EXPORTED" ]; then
1636 _USER_PATH_EXPORTED=1
1637 export PATH="$USER_PATH:$PATH"
1641 if [ -z "$CA_HOME" ]; then
1642 CA_HOME="$DEFAULT_CA_HOME"
1645 if [ -z "$API" ]; then
1646 if [ -z "$STAGE" ]; then
1650 _info "Using stage api:$API"
1654 _API_HOST="$(echo "$API" | cut -d : -f 2 | tr -d '/')"
1655 CA_DIR="$CA_HOME/$_API_HOST"
1657 _DEFAULT_CA_CONF="$CA_DIR/ca.conf"
1659 if [ -z "$CA_CONF" ]; then
1660 CA_CONF="$_DEFAULT_CA_CONF"
1663 if [ -f "$CA_CONF" ]; then
1667 if [ -z "$ACME_DIR" ]; then
1668 ACME_DIR="/home/.acme"
1671 if [ -z "$APACHE_CONF_BACKUP_DIR" ]; then
1672 APACHE_CONF_BACKUP_DIR="$LE_WORKING_DIR"
1675 if [ -z "$USER_AGENT" ]; then
1676 USER_AGENT="$DEFAULT_USER_AGENT"
1679 if [ -z "$HTTP_HEADER" ]; then
1680 HTTP_HEADER="$LE_WORKING_DIR/http.header"
1683 _OLD_ACCOUNT_KEY="$LE_WORKING_DIR/account.key"
1684 _OLD_ACCOUNT_JSON="$LE_WORKING_DIR/account.json"
1686 _DEFAULT_ACCOUNT_KEY_PATH="$CA_DIR/account.key"
1687 _DEFAULT_ACCOUNT_JSON_PATH="$CA_DIR/account.json"
1688 if [ -z "$ACCOUNT_KEY_PATH" ]; then
1689 ACCOUNT_KEY_PATH="$_DEFAULT_ACCOUNT_KEY_PATH"
1692 if [ -z "$ACCOUNT_JSON_PATH" ]; then
1693 ACCOUNT_JSON_PATH="$_DEFAULT_ACCOUNT_JSON_PATH"
1696 _DEFAULT_CERT_HOME="$LE_WORKING_DIR"
1697 if [ -z "$CERT_HOME" ]; then
1698 CERT_HOME="$_DEFAULT_CERT_HOME"
1701 if [ -z "$1" ]; then
1710 if [ -z "$DOMAIN_PATH" ]; then
1711 domainhome="$CERT_HOME/$domain"
1712 domainhomeecc="$CERT_HOME/$domain$ECC_SUFFIX"
1714 DOMAIN_PATH="$domainhome"
1716 if _isEccKey "$_ilength"; then
1717 DOMAIN_PATH="$domainhomeecc"
1719 if [ ! -d "$domainhome" ] && [ -d "$domainhomeecc" ]; then
1720 _info "The domain '$domain' seems to have a ECC cert already, please add '$
(__red
"--ecc")' parameter if you want to use that cert."
1723 _debug DOMAIN_PATH "$DOMAIN_PATH"
1726 if [ ! -d "$DOMAIN_PATH" ]; then
1727 if ! mkdir -p "$DOMAIN_PATH"; then
1728 _err "Can not create domain path: $DOMAIN_PATH"
1733 if [ -z "$DOMAIN_CONF" ]; then
1734 DOMAIN_CONF="$DOMAIN_PATH/$domain.conf"
1737 if [ -z "$DOMAIN_SSL_CONF" ]; then
1738 DOMAIN_SSL_CONF="$DOMAIN_PATH/$domain.csr.conf"
1741 if [ -z "$CSR_PATH" ]; then
1742 CSR_PATH="$DOMAIN_PATH/$domain.csr"
1744 if [ -z "$CERT_KEY_PATH" ]; then
1745 CERT_KEY_PATH="$DOMAIN_PATH/$domain.key"
1747 if [ -z "$CERT_PATH" ]; then
1748 CERT_PATH="$DOMAIN_PATH/$domain.cer"
1750 if [ -z "$CA_CERT_PATH" ]; then
1751 CA_CERT_PATH="$DOMAIN_PATH/ca.cer"
1753 if [ -z "$CERT_FULLCHAIN_PATH" ]; then
1754 CERT_FULLCHAIN_PATH="$DOMAIN_PATH/fullchain.cer"
1756 if [ -z "$CERT_PFX_PATH" ]; then
1757 CERT_PFX_PATH="$DOMAIN_PATH/$domain.pfx"
1760 if [ -z "$TLS_CONF" ]; then
1761 TLS_CONF="$DOMAIN_PATH/tls.valdation.conf"
1763 if [ -z "$TLS_CERT" ]; then
1764 TLS_CERT="$DOMAIN_PATH/tls.valdation.cert"
1766 if [ -z "$TLS_KEY" ]; then
1767 TLS_KEY="$DOMAIN_PATH/tls.valdation.key"
1769 if [ -z "$TLS_CSR" ]; then
1770 TLS_CSR="$DOMAIN_PATH/tls.valdation.csr"
1776 if [ -z "$_EXEC_TEMP_ERR" ]; then
1777 _EXEC_TEMP_ERR="$(_mktemp)"
1780 if [ "$_EXEC_TEMP_ERR" ]; then
1781 eval "$@ 2>>$_EXEC_TEMP_ERR"
1788 [ "$_EXEC_TEMP_ERR" ] && _err "$(cat "$_EXEC_TEMP_ERR")" && echo "" >"$_EXEC_TEMP_ERR"
1792 _APACHECTL="apachectl"
1793 if ! _exists apachectl; then
1794 if _exists apache2ctl; then
1795 _APACHECTL="apache2ctl"
1797 _err "'apachectl not found. It seems that apache is not installed
, or you are not root user.
'"
1798 _err "Please use webroot mode to try again."
1803 if ! _exec $_APACHECTL -V >/dev/null; then
1808 if [ "$APACHE_HTTPD_CONF" ]; then
1809 _saveaccountconf APACHE_HTTPD_CONF "$APACHE_HTTPD_CONF"
1810 httpdconf="$APACHE_HTTPD_CONF"
1811 httpdconfname="$(basename "$httpdconfname")"
1813 httpdconfname="$($_APACHECTL -V | grep SERVER_CONFIG_FILE= | cut -d = -f 2 | tr -d '"')"
1814 _debug httpdconfname
"$httpdconfname"
1816 if [ -z "$httpdconfname" ]; then
1817 _err
"Can not read apache config file."
1821 if _startswith
"$httpdconfname" '/'; then
1822 httpdconf
="$httpdconfname"
1823 httpdconfname
="$(basename "$httpdconfname")"
1825 httpdroot
="$($_APACHECTL -V | grep HTTPD_ROOT= | cut -d = -f 2 | tr -d '"')"
1826 _debug httpdroot "$httpdroot"
1827 httpdconf="$httpdroot/$httpdconfname"
1828 httpdconfname="$(basename "$httpdconfname")"
1831 _debug httpdconf "$httpdconf"
1832 _debug httpdconfname "$httpdconfname"
1833 if [ ! -f "$httpdconf" ]; then
1834 _err "Apache Config file not found" "$httpdconf"
1841 if [ -z "$usingApache" ]; then
1845 if ! _apachePath; then
1849 if [ ! -f "$APACHE_CONF_BACKUP_DIR/$httpdconfname" ]; then
1850 _debug "No config file to restore."
1854 cat "$APACHE_CONF_BACKUP_DIR/$httpdconfname" >"$httpdconf"
1855 _debug "Restored: $httpdconf."
1856 if ! _exec $_APACHECTL -t; then
1858 _err "Sorry, restore apache config error, please contact me."
1861 _debug "Restored successfully."
1862 rm -f "$APACHE_CONF_BACKUP_DIR/$httpdconfname"
1868 if ! _apachePath; then
1872 #test the conf first
1873 _info "Checking if there is an error in the apache config file before starting."
1875 if ! _exec "$_APACHECTL" -t >/dev/null; then
1877 _err "The apache config file has error, please fix it first, then try again."
1878 _err "Don't worry
, there is nothing changed to your system.
"
1885 _debug "Backup apache config
file" "$httpdconf"
1886 if ! cp "$httpdconf" "$APACHE_CONF_BACKUP_DIR/"; then
1887 _err "Can not backup apache config
file, so abort. Don
't worry, the apache config is not changed."
1888 _err "This might be a bug of $PROJECT_NAME , pleae report issue: $PROJECT"
1891 _info "JFYI, Config file $httpdconf is backuped to $APACHE_CONF_BACKUP_DIR/$httpdconfname"
1892 _info "In case there is an error that can not be restored automatically, you may try restore it yourself."
1893 _info "The backup file will be deleted on sucess, just forget it."
1897 apacheVer="$($_APACHECTL -V | grep "Server version:" | cut -d : -f 2 | cut -d " " -f 2 | cut -d '/' -f 2)"
1898 _debug "apacheVer" "$apacheVer"
1899 apacheMajer="$(echo "$apacheVer" | cut -d . -f 1)"
1900 apacheMinor="$(echo "$apacheVer" | cut -d . -f 2)"
1902 if [ "$apacheVer" ] && [ "$apacheMajer$apacheMinor" -ge "24" ]; then
1904 Alias /.well-known/acme-challenge $ACME_DIR
1906 <Directory $ACME_DIR >
1912 Alias /.well-known/acme-challenge $ACME_DIR
1914 <Directory $ACME_DIR >
1921 _msg="$($_APACHECTL -t 2>&1)"
1922 if [ "$?" != "0" ]; then
1923 _err "Sorry, apache config error"
1924 if _restoreApache; then
1925 _err "The apache config file is restored."
1927 _err "Sorry, The apache config file can not be restored, please report bug."
1932 if [ ! -d "$ACME_DIR" ]; then
1933 mkdir -p "$ACME_DIR"
1934 chmod 755 "$ACME_DIR"
1937 if ! _exec "$_APACHECTL" graceful; then
1939 _err "$_APACHECTL graceful error, please contact me."
1948 _stopserver "$serverproc"
1952 if [ -z "$DEBUG" ]; then
1961 _debug "_clearupdns"
1962 if [ "$dnsadded" != 1 ] || [ -z "$vlist" ]; then
1963 _debug "Dns not added, skip."
1967 ventries=$(echo "$vlist" | tr ',' ' ')
1968 for ventry in $ventries; do
1969 d=$(echo "$ventry" | cut -d "$sep" -f 1)
1970 keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2)
1971 vtype=$(echo "$ventry" | cut -d "$sep" -f 4)
1972 _currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5)
1974 if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then
1975 _info "$d is already verified, skip $vtype."
1979 if [ "$vtype" != "$VTYPE_DNS" ]; then
1980 _info "Skip $d for $vtype"
1984 d_api="$(_findHook "$d" dnsapi "$_currentRoot")"
1985 _debug d_api "$d_api"
1987 if [ -z "$d_api" ]; then
1988 _info "Not Found domain api file: $d_api"
1993 if ! . "$d_api"; then
1994 _err "Load file $d_api error. Please check your api file and try again."
1998 rmcommand="${_currentRoot}_rm"
1999 if ! _exists "$rmcommand"; then
2000 _err "It seems that your api file doesn't define
$rmcommand"
2004 txtdomain="_acme-challenge.
$d"
2006 if ! $rmcommand "$txtdomain"; then
2007 _err "Error removing txt
for domain
:$txtdomain"
2015 # webroot removelevel tokenfile
2016 _clearupwebbroot() {
2018 if [ -z "$__webroot" ]; then
2019 _debug "no webroot specified
, skip
"
2024 if [ "$2" = '1' ]; then
2025 _rmpath="$__webroot/.well-known
"
2026 elif [ "$2" = '2' ]; then
2027 _rmpath="$__webroot/.well-known
/acme-challenge
"
2028 elif [ "$2" = '3' ]; then
2029 _rmpath="$__webroot/.well-known
/acme-challenge
/$3"
2031 _debug "Skip
for removelevel
:$2"
2034 if [ "$_rmpath" ]; then
2035 if [ "$DEBUG" ]; then
2036 _debug "Debugging
, skip removing
: $_rmpath"
2046 _on_before_issue() {
2047 _debug _on_before_issue
2048 if _hasfield "$Le_Webroot" "$NO_VALUE"; then
2049 if ! _exists "nc
"; then
2050 _err "Please
install netcat
(nc
) tools first.
"
2055 _debug Le_LocalAddress "$Le_LocalAddress"
2057 alldomains=$(echo "$Le_Domain,$Le_Alt" | tr ',' ' ')
2061 for d in $alldomains; do
2062 _debug "Check
for domain
" "$d"
2063 _currentRoot="$
(_getfield
"$Le_Webroot" $_index)"
2064 _debug "_currentRoot
" "$_currentRoot"
2065 _index=$(_math $_index + 1)
2067 if [ "$_currentRoot" = "$NO_VALUE" ]; then
2068 _info "Standalone mode.
"
2069 if [ -z "$Le_HTTPPort" ]; then
2072 _savedomainconf "Le_HTTPPort
" "$Le_HTTPPort"
2074 _checkport="$Le_HTTPPort"
2075 elif [ "$_currentRoot" = "$W_TLS" ]; then
2076 _info "Standalone tls mode.
"
2077 if [ -z "$Le_TLSPort" ]; then
2080 _savedomainconf "Le_TLSPort
" "$Le_TLSPort"
2082 _checkport="$Le_TLSPort"
2085 if [ "$_checkport" ]; then
2086 _debug _checkport "$_checkport"
2087 _checkaddr="$
(_getfield
"$Le_LocalAddress" $_addrIndex)"
2088 _debug _checkaddr "$_checkaddr"
2090 _addrIndex="$
(_math
$_addrIndex + 1)"
2092 _netprc="$
(_ss
"$_checkport" |
grep "$_checkport")"
2093 netprc="$
(echo "$_netprc" |
grep "$_checkaddr")"
2094 if [ -z "$netprc" ]; then
2095 netprc="$
(echo "$_netprc" |
grep "$LOCAL_ANY_ADDRESS")"
2097 if [ "$netprc" ]; then
2099 _err "tcp port
$_checkport is already used by $
(echo "$netprc" | cut
-d : -f 4)"
2100 _err "Please stop it first
"
2106 if _hasfield "$Le_Webroot" "apache
"; then
2107 if ! _setApache; then
2108 _err "set up apache error. Report error to me.
"
2116 if [ "$Le_PreHook" ]; then
2117 _info "Run pre hook
:'$Le_PreHook'"
2119 cd "$DOMAIN_PATH" && eval "$Le_PreHook"
2121 _err "Error when run pre hook.
"
2128 _debug _on_issue_err
2129 if [ "$LOG_FILE" ]; then
2130 _err "Please check log
file for more details
: $LOG_FILE"
2132 _err "Please add
'--debug' or
'--log' to check
more details.
"
2133 _err "See
: $_DEBUG_WIKI"
2136 if [ "$DEBUG" ] && [ "$DEBUG" -gt "0" ]; then
2137 _debug "$
(_dlg_versions
)"
2141 if [ "$Le_PostHook" ]; then
2142 _info "Run post hook
:'$Le_PostHook'"
2144 cd "$DOMAIN_PATH" && eval "$Le_PostHook"
2146 _err "Error when run post hook.
"
2152 _on_issue_success() {
2153 _debug _on_issue_success
2155 if [ "$Le_PostHook" ]; then
2156 _info "Run post hook
:'$Le_PostHook'"
2158 cd "$DOMAIN_PATH" && eval "$Le_PostHook"
2160 _err "Error when run post hook.
"
2166 if [ "$IS_RENEW" ] && [ "$Le_RenewHook" ]; then
2167 _info "Run renew hook
:'$Le_RenewHook'"
2169 cd "$DOMAIN_PATH" && eval "$Le_RenewHook"
2171 _err "Error when run renew hook.
"
2186 _regAccount "$_reg_length"
2189 __calcAccountKeyHash() {
2190 [ -f "$ACCOUNT_KEY_PATH" ] && _digest sha256 <"$ACCOUNT_KEY_PATH"
2198 if [ ! -f "$ACCOUNT_KEY_PATH" ] && [ -f "$_OLD_ACCOUNT_KEY" ]; then
2199 _info "mv $_OLD_ACCOUNT_KEY to
$ACCOUNT_KEY_PATH"
2200 mv "$_OLD_ACCOUNT_KEY" "$ACCOUNT_KEY_PATH"
2203 if [ ! -f "$ACCOUNT_JSON_PATH" ] && [ -f "$_OLD_ACCOUNT_JSON" ]; then
2204 _info "mv $_OLD_ACCOUNT_JSON to
$ACCOUNT_JSON_PATH"
2205 mv "$_OLD_ACCOUNT_JSON" "$ACCOUNT_JSON_PATH"
2208 if [ ! -f "$ACCOUNT_KEY_PATH" ]; then
2209 if ! _create_account_key "$_reg_length"; then
2210 _err "Create account key error.
"
2215 if ! _calcjwk "$ACCOUNT_KEY_PATH"; then
2222 _debug AGREEMENT "$AGREEMENT"
2224 regjson='{"resource
": "'$_reg_res'", "agreement
": "'$AGREEMENT'"}'
2226 if [ "$ACCOUNT_EMAIL" ]; then
2227 regjson='{"resource
": "'$_reg_res'", "contact
": ["mailto
: '$ACCOUNT_EMAIL'"], "agreement
": "'$AGREEMENT'"}'
2230 if [ -z "$_updateTos" ]; then
2231 _info "Registering account
"
2233 if ! _send_signed_request "$API/acme
/new-reg
" "$regjson"; then
2234 _err "Register account Error
: $response"
2238 if [ "$code" = "" ] || [ "$code" = '201' ]; then
2239 echo "$response" >"$ACCOUNT_JSON_PATH"
2241 elif [ "$code" = '409' ]; then
2242 _info "Already registered
"
2244 _err "Register account Error
: $response"
2248 _accUri="$
(echo "$responseHeaders" |
grep "^Location:" | _head_n
1 | cut
-d ' ' -f 2 |
tr -d "\r\n")"
2249 _debug "_accUri
" "$_accUri"
2251 _tos="$
(echo "$responseHeaders" |
grep "^Link:.*rel=\"terms-of-service\"" | _head_n
1 | _egrep_o
"<.*>" |
tr -d '<>')"
2252 _debug "_tos
" "$_tos"
2253 if [ -z "$_tos" ]; then
2254 _debug "Use default tos
: $DEFAULT_AGREEMENT"
2255 _tos="$DEFAULT_AGREEMENT"
2257 if [ "$_tos" != "$AGREEMENT" ]; then
2265 _debug "Update tos
: $_tos"
2266 if ! _send_signed_request "$_accUri" "$regjson"; then
2267 _err "Update tos error.
"
2270 if [ "$code" = '202' ]; then
2271 _info "Update success.
"
2273 CA_KEY_HASH="$
(__calcAccountKeyHash
)"
2274 _debug "Calc CA_KEY_HASH
" "$CA_KEY_HASH"
2275 _savecaconf CA_KEY_HASH "$CA_KEY_HASH"
2277 _err "Update account error.
"
2286 # domain folder file
2292 if [ -f "$_SCRIPT_HOME/$_hookcat/$_hookname" ]; then
2293 d_api="$_SCRIPT_HOME/$_hookcat/$_hookname"
2294 elif [ -f "$_SCRIPT_HOME/$_hookcat/$_hookname.sh
" ]; then
2295 d_api="$_SCRIPT_HOME/$_hookcat/$_hookname.sh
"
2296 elif [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname" ]; then
2297 d_api="$LE_WORKING_DIR/$_hookdomain/$_hookname"
2298 elif [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname.sh
" ]; then
2299 d_api="$LE_WORKING_DIR/$_hookdomain/$_hookname.sh
"
2300 elif [ -f "$LE_WORKING_DIR/$_hookname" ]; then
2301 d_api="$LE_WORKING_DIR/$_hookname"
2302 elif [ -f "$LE_WORKING_DIR/$_hookname.sh
" ]; then
2303 d_api="$LE_WORKING_DIR/$_hookname.sh
"
2304 elif [ -f "$LE_WORKING_DIR/$_hookcat/$_hookname" ]; then
2305 d_api="$LE_WORKING_DIR/$_hookcat/$_hookname"
2306 elif [ -f "$LE_WORKING_DIR/$_hookcat/$_hookname.sh
" ]; then
2307 d_api="$LE_WORKING_DIR/$_hookcat/$_hookname.sh
"
2310 printf "%s
" "$d_api"
2314 __get_domain_new_authz() {
2316 _info "Getting new-authz
for domain
" "$_gdnd"
2318 _Max_new_authz_retry_times=5
2320 while [ "$_authz_i" -lt "$_Max_new_authz_retry_times" ]; do
2321 _debug "Try new-authz
for the
$_authz_i time.
"
2322 if ! _send_signed_request "$API/acme
/new-authz
" "{\"resource
\": \"new-authz
\", \"identifier
\": {\"type\": \"dns
\", \"value
\": \"$
(_idn
"$_gdnd")\"}}"; then
2323 _err "Can not get domain new authz.
"
2326 if ! _contains "$response" "An error occurred
while processing your request
"; then
2327 _info "The new-authz request is ok.
"
2330 _authz_i="$
(_math
"$_authz_i" + 1)"
2331 _info "The server is busy
, Sleep
$_authz_i to retry.
"
2335 if [ "$_authz_i" = "$_Max_new_authz_retry_times" ]; then
2336 _err "new-authz retry reach the max
$_Max_new_authz_retry_times times.
"
2339 if [ ! -z "$code" ] && [ ! "$code" = '201' ]; then
2340 _err "new-authz error
: $response"
2346 #webroot, domain domainlist keylength
2348 if [ -z "$2" ]; then
2349 _usage "Usage
: $PROJECT_ENTRY --issue -d a.com
-w /path
/to
/webroot
/a.com
/ "
2356 Le_RealCertPath="$5"
2358 Le_RealCACertPath="$7"
2360 Le_RealFullChainPath="$9"
2363 Le_RenewHook="${12}"
2364 Le_LocalAddress="${13}"
2366 #remove these later.
2367 if [ "$Le_Webroot" = "dns-cf
" ]; then
2370 if [ "$Le_Webroot" = "dns-dp
" ]; then
2373 if [ "$Le_Webroot" = "dns-cx
" ]; then
2376 _debug "Using api
: $API"
2378 if [ ! "$IS_RENEW" ]; then
2379 _initpath "$Le_Domain" "$Le_Keylength"
2380 mkdir -p "$DOMAIN_PATH"
2383 if [ -f "$DOMAIN_CONF" ]; then
2384 Le_NextRenewTime=$(_readdomainconf Le_NextRenewTime)
2385 _debug Le_NextRenewTime "$Le_NextRenewTime"
2386 if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$
(_time
)" -lt "$Le_NextRenewTime" ]; then
2387 _saved_domain=$(_readdomainconf Le_Domain)
2388 _debug _saved_domain "$_saved_domain"
2389 _saved_alt=$(_readdomainconf Le_Alt)
2390 _debug _saved_alt "$_saved_alt"
2391 if [ "$_saved_domain,$_saved_alt" = "$Le_Domain,$Le_Alt" ]; then
2392 _info "Domains not changed.
"
2393 _info "Skip
, Next renewal
time is
: $
(__green
"$(_readdomainconf Le_NextRenewTimeStr)")"
2394 _info "Add
'$(__red '--force')' to force to renew.
"
2397 _info "Domains have changed.
"
2402 _savedomainconf "Le_Domain
" "$Le_Domain"
2403 _savedomainconf "Le_Alt
" "$Le_Alt"
2404 _savedomainconf "Le_Webroot
" "$Le_Webroot"
2406 _savedomainconf "Le_PreHook
" "$Le_PreHook"
2407 _savedomainconf "Le_PostHook
" "$Le_PostHook"
2408 _savedomainconf "Le_RenewHook
" "$Le_RenewHook"
2410 if [ "$Le_LocalAddress" ]; then
2411 _savedomainconf "Le_LocalAddress
" "$Le_LocalAddress"
2413 _cleardomainconf "Le_LocalAddress
"
2417 _savedomainconf "Le_API
" "$Le_API"
2419 if [ "$Le_Alt" = "$NO_VALUE" ]; then
2423 if [ "$Le_Keylength" = "$NO_VALUE" ]; then
2427 if ! _on_before_issue; then
2428 _err "_on_before_issue.
"
2432 _saved_account_key_hash="$
(_readcaconf
"CA_KEY_HASH")"
2433 _debug2 _saved_account_key_hash "$_saved_account_key_hash"
2435 if [ -z "$_saved_account_key_hash" ] || [ "$_saved_account_key_hash" != "$
(__calcAccountKeyHash
)" ]; then
2436 if ! _regAccount "$_accountkeylength"; then
2441 _debug "_saved_account_key_hash is not changed
, skip register account.
"
2444 if [ -f "$CSR_PATH" ] && [ ! -f "$CERT_KEY_PATH" ]; then
2445 _info "Signing from existing CSR.
"
2447 _key=$(_readdomainconf Le_Keylength)
2448 _debug "Read key length
:$_key"
2449 if [ ! -f "$CERT_KEY_PATH" ] || [ "$Le_Keylength" != "$_key" ]; then
2450 if ! createDomainKey "$Le_Domain" "$Le_Keylength"; then
2451 _err "Create domain key error.
"
2458 if ! _createcsr "$Le_Domain" "$Le_Alt" "$CERT_KEY_PATH" "$CSR_PATH" "$DOMAIN_SSL_CONF"; then
2459 _err "Create CSR error.
"
2466 _savedomainconf "Le_Keylength
" "$Le_Keylength"
2470 _info "Getting domain auth token
for each domain
"
2472 if [ -z "$vlist" ]; then
2473 alldomains=$(echo "$Le_Domain,$Le_Alt" | tr ',' ' ')
2476 for d in $alldomains; do
2477 _info "Getting webroot
for domain
" "$d"
2478 _w="$
(echo $Le_Webroot | cut
-d , -f $_index)"
2483 _debug "_currentRoot
" "$_currentRoot"
2484 _index=$(_math $_index + 1)
2487 if _startswith "$_currentRoot" "dns
"; then
2491 if [ "$_currentRoot" = "$W_TLS" ]; then
2495 if ! __get_domain_new_authz "$d"; then
2501 if [ -z "$thumbprint" ]; then
2502 accountkey_json=$(printf "%s
" "$jwk" | tr -d ' ')
2503 thumbprint=$(printf "%s
" "$accountkey_json" | _digest "sha256
" | _urlencode)
2506 entry="$
(printf "%s\n" "$response" | _egrep_o
'[^\{]*"type":"'$vtype'"[^\}]*')"
2507 _debug entry "$entry"
2508 if [ -z "$entry" ]; then
2509 _err "Error
, can not get domain token
$d"
2514 token="$
(printf "%s\n" "$entry" | _egrep_o
'"token":"[^"]*' | cut
-d : -f 2 |
tr -d '"')"
2515 _debug token "$token"
2517 uri="$
(printf "%s\n" "$entry" | _egrep_o
'"uri":"[^"]*' | cut
-d : -f 2,3 |
tr -d '"')"
2520 keyauthorization="$token.
$thumbprint"
2521 _debug keyauthorization "$keyauthorization"
2523 if printf "%s
" "$response" | grep '"status
":"valid
"' >/dev/null 2>&1; then
2524 _info "$d is already verified
, skip.
"
2525 keyauthorization="$STATE_VERIFIED"
2526 _debug keyauthorization "$keyauthorization"
2529 dvlist="$d$sep$keyauthorization$sep$uri$sep$vtype$sep$_currentRoot"
2530 _debug dvlist "$dvlist"
2532 vlist="$vlist$dvlist,"
2538 ventries=$(echo "$vlist" | tr ',' ' ')
2539 for ventry in $ventries; do
2540 d=$(echo "$ventry" | cut -d "$sep" -f 1)
2541 keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2)
2542 vtype=$(echo "$ventry" | cut -d "$sep" -f 4)
2543 _currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5)
2545 if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then
2546 _info "$d is already verified
, skip
$vtype.
"
2550 if [ "$vtype" = "$VTYPE_DNS" ]; then
2552 txtdomain="_acme-challenge.
$d"
2553 _debug txtdomain "$txtdomain"
2554 txt="$
(printf "%s" "$keyauthorization" | _digest
"sha256" | _urlencode
)"
2557 d_api="$
(_findHook
"$d" dnsapi
"$_currentRoot")"
2559 _debug d_api "$d_api"
2561 if [ "$d_api" ]; then
2562 _info "Found domain api
file: $d_api"
2564 _err "Add the following TXT record
:"
2565 _err "Domain
: '$(__green "$txtdomain")'"
2566 _err "TXT value
: '$(__green "$txt")'"
2567 _err "Please be aware that you prepend _acme-challenge. before your domain
"
2568 _err "so the resulting subdomain will be
: $txtdomain"
2573 if ! . "$d_api"; then
2574 _err "Load
file $d_api error. Please check your api
file and try again.
"
2578 addcommand="${_currentRoot}_add
"
2579 if ! _exists "$addcommand"; then
2580 _err "It seems that your api
file is not correct
, it must have a
function named
: $addcommand"
2584 if ! $addcommand "$txtdomain" "$txt"; then
2585 _err "Error add txt
for domain
:$txtdomain"
2590 if [ "$?
" != "0" ]; then
2599 if [ "$dnsadded" = '0' ]; then
2600 _savedomainconf "Le_Vlist
" "$vlist"
2601 _debug "Dns record not added yet
, so
, save to
$DOMAIN_CONF and
exit.
"
2602 _err "Please add the TXT records to the domains
, and retry again.
"
2610 if [ "$dnsadded" = '1' ]; then
2611 if [ -z "$Le_DNSSleep" ]; then
2612 Le_DNSSleep="$DEFAULT_DNS_SLEEP"
2614 _savedomainconf "Le_DNSSleep
" "$Le_DNSSleep"
2617 _info "Sleep $
(__green
$Le_DNSSleep) seconds
for the txt records to take effect
"
2618 _sleep "$Le_DNSSleep"
2621 _debug "ok
, let's start to verify"
2624 ventries=$(echo "$vlist" | tr ',' ' ')
2625 for ventry in $ventries; do
2626 d=$(echo "$ventry" | cut -d "$sep" -f 1)
2627 keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2)
2628 uri=$(echo "$ventry" | cut -d "$sep" -f 3)
2629 vtype=$(echo "$ventry" | cut -d "$sep" -f 4)
2630 _currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5)
2632 if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then
2633 _info "$d is already verified, skip $vtype."
2637 _info "Verifying:$d"
2639 _debug "keyauthorization" "$keyauthorization"
2642 token="$(printf "%s" "$keyauthorization" | cut -d '.
' -f 1)"
2644 _debug "_currentRoot" "$_currentRoot"
2646 if [ "$vtype" = "$VTYPE_HTTP" ]; then
2647 if [ "$_currentRoot" = "$NO_VALUE" ]; then
2648 _info "Standalone mode server"
2649 _ncaddr="$(_getfield "$Le_LocalAddress" "$_ncIndex")"
2650 _ncIndex="$(_math $_ncIndex + 1)"
2651 _startserver "$keyauthorization" "$_ncaddr" &
2652 if [ "$?" != "0" ]; then
2659 _debug serverproc "$serverproc"
2662 if [ "$_currentRoot" = "apache" ]; then
2663 wellknown_path="$ACME_DIR"
2665 wellknown_path="$_currentRoot/.well-known/acme-challenge"
2666 if [ ! -d "$_currentRoot/.well-known" ]; then
2668 elif [ ! -d "$_currentRoot/.well-known/acme-challenge" ]; then
2675 _debug wellknown_path "$wellknown_path"
2677 _debug "writing token:$token to $wellknown_path/$token"
2679 mkdir -p "$wellknown_path"
2681 if ! printf "%s" "$keyauthorization" >"$wellknown_path/$token"; then
2682 _err "$d:Can not write token to file : $wellknown_path/$token"
2683 _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
2689 if [ ! "$usingApache" ]; then
2690 if webroot_owner=$(_stat "$_currentRoot"); then
2691 _debug "Changing owner/group of .well-known to $webroot_owner"
2692 chown -R "$webroot_owner" "$_currentRoot/.well-known"
2694 _debug "not chaning owner/group of webroot"
2700 elif [ "$vtype" = "$VTYPE_TLS" ]; then
2702 #_hash_A="$(printf "%s" $token | _digest "sha256" "hex" )"
2703 #_debug2 _hash_A "$_hash_A"
2704 #_x="$(echo $_hash_A | cut -c 1-32)"
2706 #_y="$(echo $_hash_A | cut -c 33-64)"
2708 #_SAN_A="$_x.$_y.token.acme.invalid"
2709 #_debug2 _SAN_A "$_SAN_A"
2712 _hash_B="$(printf "%s" "$keyauthorization" | _digest "sha256" "hex")"
2713 _debug2 _hash_B "$_hash_B"
2714 _x="$(echo "$_hash_B" | cut -c 1-32)"
2716 _y="$(echo "$_hash_B" | cut -c 33-64)"
2719 #_SAN_B="$_x.$_y.ka.acme.invalid"
2721 _SAN_B="$_x.$_y.acme.invalid"
2722 _debug2 _SAN_B "$_SAN_B"
2724 _ncaddr="$(_getfield "$Le_LocalAddress" "$_ncIndex")"
2725 _ncIndex="$(_math "$_ncIndex" + 1)"
2726 if ! _starttlsserver "$_SAN_B" "$_SAN_A" "$Le_TLSPort" "$keyauthorization" "$_ncaddr"; then
2727 _err "Start tls server error."
2728 _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
2735 if ! _send_signed_request "$uri" "{\"resource\": \"challenge\", \"keyAuthorization\": \"$keyauthorization\"}"; then
2736 _err "$d:Can not get challenge: $response"
2737 _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
2743 if [ ! -z "$code" ] && [ ! "$code" = '202' ]; then
2744 _err "$d:Challenge error: $response"
2745 _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
2752 if [ -z "$MAX_RETRY_TIMES" ]; then
2757 waittimes=$(_math "$waittimes" + 1)
2758 if [ "$waittimes" -ge "$MAX_RETRY_TIMES" ]; then
2760 _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
2766 _debug "sleep 2 secs to verify"
2769 response="$(_get "$uri")"
2770 if [ "$?" != "0" ]; then
2771 _err "$d:Verify error:$response"
2772 _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
2777 _debug2 original "$response"
2779 response="$(echo "$response" | _normalizeJson)"
2780 _debug2 response "$response"
2782 status=$(echo "$response" | _egrep_o '"status":"[^"]*' | cut -d : -f 2 | tr -d '"')
2783 if [ "$status" = "valid
" ]; then
2785 _stopserver "$serverproc"
2787 _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
2791 if [ "$status" = "invalid
" ]; then
2792 error="$
(echo "$response" |
tr -d "\r\n" | _egrep_o
'"error":\{[^\}]*')"
2793 _debug2 error "$error"
2794 errordetail="$
(echo "$error" | _egrep_o
'"detail": *"[^"]*' | cut
-d '"' -f 4)"
2795 _debug2 errordetail "$errordetail"
2796 if [ "$errordetail" ]; then
2797 _err "$d:Verify error
:$errordetail"
2799 _err "$d:Verify error
:$error"
2801 if [ "$DEBUG" ]; then
2802 if [ "$vtype" = "$VTYPE_HTTP" ]; then
2803 _debug "Debug
: get token url.
"
2804 _get "http
://$d/.well-known
/acme-challenge
/$token" "" 1
2807 _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
2813 if [ "$status" = "pending
" ]; then
2816 _err "$d:Verify error
:$response"
2817 _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
2828 _info "Verify finished
, start to sign.
"
2829 der="$
(_getfile
"${CSR_PATH}" "${BEGIN_CSR}" "${END_CSR}" |
tr -d "\r\n" | _urlencode
)"
2831 if ! _send_signed_request "$API/acme
/new-cert
" "{\"resource
\": \"new-cert
\", \"csr
\": \"$der\"}" "needbase64
"; then
2838 Le_LinkCert="$
(grep -i '^Location.*$' "$HTTP_HEADER" | _head_n
1 |
tr -d "\r\n" | cut
-d " " -f 2)"
2839 _savedomainconf "Le_LinkCert
" "$Le_LinkCert"
2841 if [ "$Le_LinkCert" ]; then
2842 echo "$BEGIN_CERT" >"$CERT_PATH"
2844 #if ! _get "$Le_LinkCert" | _base64 "multiline
" >> "$CERT_PATH" ; then
2845 # _debug "Get cert failed. Let
's try last response."
2846 # printf -- "%s" "$_rcert" | _dbase64 "multiline" | _base64 "multiline" >> "$CERT_PATH"
2849 if ! printf -- "%s" "$_rcert" | _dbase64 "multiline" | _base64 "multiline" >>"$CERT_PATH"; then
2850 _debug "Try cert link."
2851 _get "$Le_LinkCert" | _base64 "multiline" >>"$CERT_PATH"
2854 echo "$END_CERT" >>"$CERT_PATH"
2855 _info "$(__green "Cert success.")"
2858 _info "Your cert is in $(__green " $CERT_PATH ")"
2860 if [ -f "$CERT_KEY_PATH" ]; then
2861 _info "Your cert key is in $(__green " $CERT_KEY_PATH ")"
2864 cp "$CERT_PATH" "$CERT_FULLCHAIN_PATH"
2866 if [ ! "$USER_PATH" ] || [ ! "$IN_CRON" ]; then
2868 _saveaccountconf "USER_PATH" "$USER_PATH"
2872 if [ -z "$Le_LinkCert" ]; then
2873 response="$(echo "$response" | _dbase64 "multiline" | _normalizeJson)"
2874 _err "Sign failed: $(echo "$response" | _egrep_o '"detail":"[^"]*"')"
2879 _cleardomainconf
"Le_Vlist"
2881 Le_LinkIssuer
=$
(grep -i '^Link' "$HTTP_HEADER" | _head_n
1 | cut
-d " " -f 2 | cut
-d ';' -f 1 |
tr -d '<>')
2882 if ! _contains
"$Le_LinkIssuer" ":"; then
2883 Le_LinkIssuer
="$API$Le_LinkIssuer"
2886 _savedomainconf
"Le_LinkIssuer" "$Le_LinkIssuer"
2888 if [ "$Le_LinkIssuer" ]; then
2889 echo "$BEGIN_CERT" >"$CA_CERT_PATH"
2890 _get
"$Le_LinkIssuer" | _base64
"multiline" >>"$CA_CERT_PATH"
2891 echo "$END_CERT" >>"$CA_CERT_PATH"
2892 _info
"The intermediate CA cert is in $(__green " $CA_CERT_PATH ")"
2893 cat "$CA_CERT_PATH" >>"$CERT_FULLCHAIN_PATH"
2894 _info
"And the full chain certs is there: $(__green " $CERT_FULLCHAIN_PATH ")"
2897 Le_CertCreateTime
=$
(_time
)
2898 _savedomainconf
"Le_CertCreateTime" "$Le_CertCreateTime"
2900 Le_CertCreateTimeStr
=$
(date -u)
2901 _savedomainconf
"Le_CertCreateTimeStr" "$Le_CertCreateTimeStr"
2903 if [ -z "$Le_RenewalDays" ] ||
[ "$Le_RenewalDays" -lt "0" ] ||
[ "$Le_RenewalDays" -gt "$MAX_RENEW" ]; then
2904 Le_RenewalDays
="$MAX_RENEW"
2906 _savedomainconf
"Le_RenewalDays" "$Le_RenewalDays"
2909 if [ "$CA_BUNDLE" ]; then
2910 _saveaccountconf CA_BUNDLE
"$CA_BUNDLE"
2912 _clearaccountconf
"CA_BUNDLE"
2915 if [ "$HTTPS_INSECURE" ]; then
2916 _saveaccountconf HTTPS_INSECURE
"$HTTPS_INSECURE"
2918 _clearaccountconf
"HTTPS_INSECURE"
2921 if [ "$Le_Listen_V4" ]; then
2922 _savedomainconf
"Le_Listen_V4" "$Le_Listen_V4"
2923 _cleardomainconf Le_Listen_V6
2924 elif [ "$Le_Listen_V6" ]; then
2925 _savedomainconf
"Le_Listen_V6" "$Le_Listen_V6"
2926 _cleardomainconf Le_Listen_V4
2929 Le_NextRenewTime
=$
(_math
"$Le_CertCreateTime" + "$Le_RenewalDays" \
* 24 \
* 60 \
* 60)
2931 Le_NextRenewTimeStr
=$
(_time2str
"$Le_NextRenewTime")
2932 _savedomainconf
"Le_NextRenewTimeStr" "$Le_NextRenewTimeStr"
2934 Le_NextRenewTime
=$
(_math
"$Le_NextRenewTime" - 86400)
2935 _savedomainconf
"Le_NextRenewTime" "$Le_NextRenewTime"
2939 if [ "$Le_RealCertPath$Le_RealKeyPath$Le_RealCACertPath$Le_ReloadCmd$Le_RealFullChainPath" ]; then
2948 if [ -z "$Le_Domain" ]; then
2949 _usage
"Usage: $PROJECT_ENTRY --renew -d domain.com [--ecc]"
2955 _initpath
"$Le_Domain" "$_isEcc"
2957 _info
"$(__green "Renew
: '$Le_Domain'")"
2958 if [ ! -f "$DOMAIN_CONF" ]; then
2959 _info
"'$Le_Domain' is not a issued domain, skip."
2963 if [ "$Le_RenewalDays" ]; then
2964 _savedomainconf Le_RenewalDays
"$Le_RenewalDays"
2969 if [ "$Le_API" ]; then
2973 if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(_time)" -lt "$Le_NextRenewTime" ]; then
2974 _info
"Skip, Next renewal time is: $(__green "$Le_NextRenewTimeStr")"
2975 _info
"Add '$(__red '--force')' to force to renew."
2976 return "$RENEW_SKIP"
2980 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"
2982 if [ "$res" != "0" ]; then
2986 if [ "$Le_DeployHook" ]; then
2987 deploy
"$Le_Domain" "$Le_DeployHook" "$Le_Keylength"
2996 #renewAll [stopRenewOnError]
2999 _stopRenewOnError
="$1"
3000 _debug
"_stopRenewOnError" "$_stopRenewOnError"
3003 for di
in "${CERT_HOME}"/*.
*/; do
3008 if _endswith
"$d" "$ECC_SUFFIX"; then
3009 _isEcc
=$
(echo "$d" | cut
-d "$ECC_SEP" -f 2)
3010 d
=$
(echo "$d" | cut
-d "$ECC_SEP" -f 1)
3012 renew
"$d" "$_isEcc"
3015 _debug
"Return code: $rc"
3016 if [ "$rc" != "0" ]; then
3017 if [ "$rc" = "$RENEW_SKIP" ]; then
3019 elif [ "$_stopRenewOnError" ]; then
3020 _err
"Error renew $d, stop now."
3024 _err
"Error renew $d, Go ahead to next one."
3035 if [ -z "$_csrfile" ] ||
[ -z "$_csrW" ]; then
3036 _usage
"Usage: $PROJECT_ENTRY --signcsr --csr mycsr.csr -w /path/to/webroot/a.com/ "
3042 _csrsubj
=$
(_readSubjectFromCSR
"$_csrfile")
3043 if [ "$?" != "0" ]; then
3044 _err
"Can not read subject from csr: $_csrfile"
3047 _debug _csrsubj
"$_csrsubj"
3049 _csrdomainlist
=$
(_readSubjectAltNamesFromCSR
"$_csrfile")
3050 if [ "$?" != "0" ]; then
3051 _err
"Can not read domain list from csr: $_csrfile"
3054 _debug
"_csrdomainlist" "$_csrdomainlist"
3056 if [ -z "$_csrsubj" ]; then
3057 _csrsubj
="$(_getfield "$_csrdomainlist" 1)"
3058 _debug _csrsubj
"$_csrsubj"
3059 _csrdomainlist
="$(echo "$_csrdomainlist" | cut -d , -f 2-)"
3060 _debug
"_csrdomainlist" "$_csrdomainlist"
3063 if [ -z "$_csrsubj" ]; then
3064 _err
"Can not read subject from csr: $_csrfile"
3068 _csrkeylength
=$
(_readKeyLengthFromCSR
"$_csrfile")
3069 if [ "$?" != "0" ] ||
[ -z "$_csrkeylength" ]; then
3070 _err
"Can not read key length from csr: $_csrfile"
3074 _initpath
"$_csrsubj" "$_csrkeylength"
3075 mkdir
-p "$DOMAIN_PATH"
3077 _info
"Copy csr to: $CSR_PATH"
3078 cp "$_csrfile" "$CSR_PATH"
3080 issue
"$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength"
3087 if [ -z "$_csrfile" ] && [ -z "$_csrd" ]; then
3088 _usage
"Usage: $PROJECT_ENTRY --showcsr --csr mycsr.csr"
3094 _csrsubj
=$
(_readSubjectFromCSR
"$_csrfile")
3095 if [ "$?" != "0" ] ||
[ -z "$_csrsubj" ]; then
3096 _err
"Can not read subject from csr: $_csrfile"
3100 _info
"Subject=$_csrsubj"
3102 _csrdomainlist
=$
(_readSubjectAltNamesFromCSR
"$_csrfile")
3103 if [ "$?" != "0" ]; then
3104 _err
"Can not read domain list from csr: $_csrfile"
3107 _debug
"_csrdomainlist" "$_csrdomainlist"
3109 _info
"SubjectAltNames=$_csrdomainlist"
3111 _csrkeylength
=$
(_readKeyLengthFromCSR
"$_csrfile")
3112 if [ "$?" != "0" ] ||
[ -z "$_csrkeylength" ]; then
3113 _err
"Can not read key length from csr: $_csrfile"
3116 _info
"KeyLength=$_csrkeylength"
3124 if [ "$_raw" ]; then
3125 printf "%s\n" "Main_Domain${_sep}KeyLength${_sep}SAN_Domains${_sep}Created${_sep}Renew"
3126 for di
in "${CERT_HOME}"/*.
*/; do
3130 if _endswith
"$d" "$ECC_SUFFIX"; then
3131 _isEcc
=$
(echo "$d" | cut
-d "$ECC_SEP" -f 2)
3132 d
=$
(echo "$d" | cut
-d "$ECC_SEP" -f 1)
3134 _initpath
"$d" "$_isEcc"
3135 if [ -f "$DOMAIN_CONF" ]; then
3137 printf "%s\n" "$Le_Domain${_sep}\"$Le_Keylength\"${_sep}$Le_Alt${_sep}$Le_CertCreateTimeStr${_sep}$Le_NextRenewTimeStr"
3142 if _exists
column; then
3143 list
"raw" |
column -t -s "$_sep"
3145 list
"raw" |
tr "$_sep" '\t'
3155 if [ -z "$Le_DeployHook" ]; then
3156 _usage
"Usage: $PROJECT_ENTRY --deploy -d domain.com --deploy-hook cpanel [--ecc] "
3160 _initpath
"$Le_Domain" "$_isEcc"
3161 if [ ! -d "$DOMAIN_PATH" ]; then
3162 _err
"Domain is not valid:'$Le_Domain'"
3166 _deployApi
="$(_findHook "$Le_Domain" deploy "$Le_DeployHook")"
3167 if [ -z "$_deployApi" ]; then
3168 _err
"The deploy hook $Le_DeployHook is not found."
3171 _debug _deployApi
"$_deployApi"
3173 _savedomainconf Le_DeployHook
"$Le_DeployHook"
3176 if ! .
"$_deployApi"; then
3177 _err
"Load file $_deployApi error. Please check your api file and try again."
3181 d_command
="${Le_DeployHook}_deploy"
3182 if ! _exists
"$d_command"; then
3183 _err
"It seems that your api file is not correct, it must have a function named: $d_command"
3187 if ! $d_command "$Le_Domain" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$CERT_FULLCHAIN_PATH"; then
3188 _err
"Error deploy for domain:$Le_Domain"
3193 _err
"Deploy error."
3196 _info
"$(__green Success)"
3203 if [ -z "$Le_Domain" ]; then
3204 _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]"
3208 Le_RealCertPath
="$2"
3210 Le_RealCACertPath
="$4"
3212 Le_RealFullChainPath
="$6"
3215 _initpath
"$Le_Domain" "$_isEcc"
3216 if [ ! -d "$DOMAIN_PATH" ]; then
3217 _err
"Domain is not valid:'$Le_Domain'"
3225 _savedomainconf
"Le_RealCertPath" "$Le_RealCertPath"
3226 _savedomainconf
"Le_RealCACertPath" "$Le_RealCACertPath"
3227 _savedomainconf
"Le_RealKeyPath" "$Le_RealKeyPath"
3228 _savedomainconf
"Le_ReloadCmd" "$Le_ReloadCmd"
3229 _savedomainconf
"Le_RealFullChainPath" "$Le_RealFullChainPath"
3231 if [ "$Le_RealCertPath" = "$NO_VALUE" ]; then
3234 if [ "$Le_RealKeyPath" = "$NO_VALUE" ]; then
3237 if [ "$Le_RealCACertPath" = "$NO_VALUE" ]; then
3238 Le_RealCACertPath
=""
3240 if [ "$Le_ReloadCmd" = "$NO_VALUE" ]; then
3243 if [ "$Le_RealFullChainPath" = "$NO_VALUE" ]; then
3244 Le_RealFullChainPath
=""
3247 if [ "$Le_RealCertPath" ]; then
3249 _info
"Installing cert to:$Le_RealCertPath"
3250 if [ -f "$Le_RealCertPath" ] && [ ! "$IS_RENEW" ]; then
3251 cp "$Le_RealCertPath" "$Le_RealCertPath".bak
3253 cat "$CERT_PATH" >"$Le_RealCertPath"
3256 if [ "$Le_RealCACertPath" ]; then
3258 _info
"Installing CA to:$Le_RealCACertPath"
3259 if [ "$Le_RealCACertPath" = "$Le_RealCertPath" ]; then
3260 echo "" >>"$Le_RealCACertPath"
3261 cat "$CA_CERT_PATH" >>"$Le_RealCACertPath"
3263 if [ -f "$Le_RealCACertPath" ] && [ ! "$IS_RENEW" ]; then
3264 cp "$Le_RealCACertPath" "$Le_RealCACertPath".bak
3266 cat "$CA_CERT_PATH" >"$Le_RealCACertPath"
3270 if [ "$Le_RealKeyPath" ]; then
3272 _info
"Installing key to:$Le_RealKeyPath"
3273 if [ -f "$Le_RealKeyPath" ] && [ ! "$IS_RENEW" ]; then
3274 cp "$Le_RealKeyPath" "$Le_RealKeyPath".bak
3276 cat "$CERT_KEY_PATH" >"$Le_RealKeyPath"
3279 if [ "$Le_RealFullChainPath" ]; then
3281 _info
"Installing full chain to:$Le_RealFullChainPath"
3282 if [ -f "$Le_RealFullChainPath" ] && [ ! "$IS_RENEW" ]; then
3283 cp "$Le_RealFullChainPath" "$Le_RealFullChainPath".bak
3285 cat "$CERT_FULLCHAIN_PATH" >"$Le_RealFullChainPath"
3288 if [ "$Le_ReloadCmd" ]; then
3290 _info
"Run Le_ReloadCmd: $Le_ReloadCmd"
3291 if (cd "$DOMAIN_PATH" && eval "$Le_ReloadCmd"); then
3292 _info
"$(__green "Reload success
")"
3294 _err
"Reload error for :$Le_Domain"
3302 if ! _exists
"crontab"; then
3303 _err
"crontab doesn't exist, so, we can not install cron jobs."
3304 _err
"All your certs will not be renewed automatically."
3305 _err
"You must add your own cron job to call '$PROJECT_ENTRY --cron' everyday."
3309 _info
"Installing cron job"
3310 if ! crontab
-l |
grep "$PROJECT_ENTRY --cron"; then
3311 if [ -f "$LE_WORKING_DIR/$PROJECT_ENTRY" ]; then
3312 lesh
="\"$LE_WORKING_DIR\"/$PROJECT_ENTRY"
3314 _err
"Can not install cronjob, $PROJECT_ENTRY not found."
3317 if _exists uname
&& uname
-a |
grep solaris
>/dev
/null
; then
3320 echo "0 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" > /dev/null"
3325 echo "0 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" > /dev/null"
3329 if [ "$?" != "0" ]; then
3330 _err
"Install cron job failed. You need to manually renew your certs."
3331 _err
"Or you can add cronjob by yourself:"
3332 _err
"$lesh --cron --home \"$LE_WORKING_DIR\" > /dev/null"
3337 uninstallcronjob
() {
3338 if ! _exists
"crontab"; then
3341 _info
"Removing cron job"
3342 cr
="$(crontab -l | grep "$PROJECT_ENTRY --cron")"
3344 if _exists uname
&& uname
-a |
grep solaris
>/dev
/null
; then
3345 crontab
-l |
sed "/$PROJECT_ENTRY --cron/d" | crontab
--
3347 crontab
-l |
sed "/$PROJECT_ENTRY --cron/d" | crontab
-
3349 LE_WORKING_DIR
="$(echo "$cr" | cut -d ' ' -f 9 | tr -d '"')"
3350 _info LE_WORKING_DIR "$LE_WORKING_DIR"
3358 if [ -z "$Le_Domain" ]; then
3359 _usage "Usage: $PROJECT_ENTRY --revoke -d domain.com"
3365 _initpath "$Le_Domain" "$_isEcc"
3366 if [ ! -f "$DOMAIN_CONF" ]; then
3367 _err "$Le_Domain is not a issued domain, skip."
3371 if [ ! -f "$CERT_PATH" ]; then
3372 _err "Cert for $Le_Domain $CERT_PATH is not found, skip."
3376 cert="$(_getfile "${CERT_PATH}" "${BEGIN_CERT}" "${END_CERT}" | tr -d "\r\n" | _urlencode)"
3378 if [ -z "$cert" ]; then
3379 _err "Cert for $Le_Domain is empty found, skip."
3383 data="{\"resource\": \"revoke-cert\", \"certificate\": \"$cert\"}"
3384 uri="$API/acme/revoke-cert"
3386 if [ -f "$CERT_KEY_PATH" ]; then
3387 _info "Try domain key first."
3388 if _send_signed_request "$uri" "$data" "" "$CERT_KEY_PATH"; then
3389 if [ -z "$response" ]; then
3390 _info "Revoke success."
3394 _err "Revoke error by domain key."
3399 _info "Domain key file doesn't exists.
"
3402 _info "Try account key.
"
3404 if _send_signed_request "$uri" "$data" "" "$ACCOUNT_KEY_PATH"; then
3405 if [ -z "$response" ]; then
3406 _info "Revoke success.
"
3410 _err "Revoke error.
"
3425 while [ "$_d_i" -lt "$_d_max_retry" ]; do
3426 _info "Deactivate
: $_d_domain"
3427 _d_i="$
(_math
$_d_i + 1)"
3429 if ! __get_domain_new_authz "$_d_domain"; then
3430 _err "Can not get domain new authz token.
"
3434 authzUri="$
(echo "$responseHeaders" |
grep "^Location:" | _head_n
1 | cut
-d ' ' -f 2 |
tr -d "\r\n")"
3435 _debug "authzUri
" "$authzUri"
3437 if [ ! -z "$code" ] && [ ! "$code" = '201' ]; then
3438 _err "new-authz error
: $response"
3442 entry="$
(printf "%s\n" "$response" | _egrep_o
'[^\{]*"status":"valid","uri"[^\}]*')"
3443 _debug entry "$entry"
3445 if [ -z "$entry" ]; then
3446 _info "No
more valid entry found.
"
3450 _vtype="$
(printf "%s\n" "$entry" | _egrep_o
'"type": *"[^"]*"' | cut
-d : -f 2 |
tr -d '"')"
3451 _debug _vtype "$_vtype"
3452 _info "Found
$_vtype"
3454 uri="$
(printf "%s\n" "$entry" | _egrep_o
'"uri":"[^"]*' | cut
-d : -f 2,3 |
tr -d '"')"
3457 if [ "$_d_type" ] && [ "$_d_type" != "$_vtype" ]; then
3458 _info "Skip
$_vtype"
3462 _info "Deactivate
: $_vtype"
3464 if ! _send_signed_request "$authzUri" "{\"resource
\": \"authz
\", \"status
\":\"deactivated
\"}"; then
3465 _err "Can not deactivate
$_vtype.
"
3469 _info "Deactivate
: $_vtype success.
"
3473 if [ "$_d_i" -lt "$_d_max_retry" ]; then
3474 _info "Deactivated success
!"
3476 _err "Deactivate failed.
"
3485 _debug _d_domain_list "$_d_domain_list"
3486 if [ -z "$
(echo $_d_domain_list | cut
-d , -f 1)" ]; then
3487 _usage "Usage
: $PROJECT_ENTRY --deactivate -d domain.com
[-d domain.com
]"
3490 for _d_dm in $(echo "$_d_domain_list" | tr ',' ' '); do
3491 if [ -z "$_d_dm" ] || [ "$_d_dm" = "$NO_VALUE" ]; then
3494 if ! _deactivate "$_d_dm" "$_d_type"; then
3500 # Detect profile file if not specified as environment variable
3502 if [ -n "$PROFILE" -a -f "$PROFILE" ]; then
3508 SHELLTYPE="$
(basename "/$SHELL")"
3510 if [ "$SHELLTYPE" = "bash
" ]; then
3511 if [ -f "$HOME/.bashrc
" ]; then
3512 DETECTED_PROFILE="$HOME/.bashrc
"
3513 elif [ -f "$HOME/.bash_profile
" ]; then
3514 DETECTED_PROFILE="$HOME/.bash_profile
"
3516 elif [ "$SHELLTYPE" = "zsh
" ]; then
3517 DETECTED_PROFILE="$HOME/.zshrc
"
3520 if [ -z "$DETECTED_PROFILE" ]; then
3521 if [ -f "$HOME/.profile
" ]; then
3522 DETECTED_PROFILE="$HOME/.profile
"
3523 elif [ -f "$HOME/.bashrc
" ]; then
3524 DETECTED_PROFILE="$HOME/.bashrc
"
3525 elif [ -f "$HOME/.bash_profile
" ]; then
3526 DETECTED_PROFILE="$HOME/.bash_profile
"
3527 elif [ -f "$HOME/.zshrc
" ]; then
3528 DETECTED_PROFILE="$HOME/.zshrc
"
3532 if [ ! -z "$DETECTED_PROFILE" ]; then
3533 echo "$DETECTED_PROFILE"
3539 if [ ! -f "$ACCOUNT_CONF_PATH" ]; then
3540 echo "#ACCOUNT_CONF_PATH=xxxx
3542 #Account configurations:
3543 #Here are the supported macros, uncomment them to make them take effect.
3545 #ACCOUNT_EMAIL=aaa@example.com # the account email used to register account.
3546 #ACCOUNT_KEY_PATH=\"/path/to/account.key\"
3547 #CERT_HOME=\"/path/to/cert/home\"
3551 #LOG_FILE=\"$DEFAULT_LOG_FILE\"
3556 #STAGE=1 # Use the staging api
3557 #FORCE=1 # Force to issue cert
3558 #DEBUG=1 # Debug mode
3561 #USER_AGENT=\"$USER_AGENT\"
3566 #######################
3569 #CF_Key=\"sdfsdfsdfljlbjkljlkjsdfoiwje\"
3571 #CF_Email=\"xxxx@sss.com\"
3573 #######################
3578 #DP_Key=\"sADDsdasdgdsf\"
3580 #######################
3584 #CX_Secret=\"sADDsdasdgdsf\"
3586 #######################
3588 #GD_Key=\"sdfdsgdgdfdasfds\"
3590 #GD_Secret=\"sADDsdasdfsdfdssdgdsf\"
3592 #######################
3594 #NSUPDATE_KEY=\"/path/to/update.key\"
3595 #NSUPDATE_SERVER=\"192.168.0.1\"
3597 #######################
3599 #PDNS_Url=\"http://ns.example.com:8081\"
3600 #PDNS_ServerId=\"localhost\"
3601 #PDNS_Token=\"0123456789ABCDEF\"
3604 " >"$ACCOUNT_CONF_PATH"
3612 if ! _exists "curl
" && ! _exists "wget
"; then
3613 _err "Please
install curl or wget first
, we need to access http resources.
"
3617 if [ -z "$_nocron" ]; then
3618 if ! _exists "crontab
"; then
3619 _err "It is recommended to
install crontab first. try to
install 'cron, crontab, crontabs or vixie-cron'.
"
3620 _err "We need to
set cron job to renew the certs automatically.
"
3621 _err "Otherwise
, your certs will not be able to be renewed automatically.
"
3622 if [ -z "$FORCE" ]; then
3623 _err "Please add
'--force' and try
install again to go without crontab.
"
3624 _err ".
/$PROJECT_ENTRY --install --force"
3630 if ! _exists "openssl
"; then
3631 _err "Please
install openssl first.
"
3632 _err "We need openssl to generate keys.
"
3636 if ! _exists "nc
"; then
3637 _err "It is recommended to
install nc first
, try to
install 'nc' or
'netcat'.
"
3638 _err "We use nc
for standalone server
if you use standalone mode.
"
3639 _err "If you don
't use standalone mode, just ignore this warning."
3648 if [ -z "$_shebang" ]; then
3649 _usage "Usage: file shebang"
3652 cp "$_file" "$_file.tmp"
3653 echo "$_shebang" >"$_file"
3654 sed -n 2,99999p "$_file.tmp" >>"$_file"
3661 _envfile="$LE_WORKING_DIR/$PROJECT_ENTRY.env"
3662 if [ "$_upgrading" ] && [ "$_upgrading" = "1" ]; then
3663 echo "$(cat "$_envfile")" | sed "s|^LE_WORKING_DIR.*$||" >"$_envfile"
3664 echo "$(cat "$_envfile")" | sed "s|^alias le.*$||" >"$_envfile"
3665 echo "$(cat "$_envfile")" | sed "s|^alias le.sh.*$||" >"$_envfile"
3668 _setopt "$_envfile" "export LE_WORKING_DIR" "=" "\"$LE_WORKING_DIR\""
3669 _setopt "$_envfile" "alias $PROJECT_ENTRY" "=" "\"$LE_WORKING_DIR/$PROJECT_ENTRY\""
3671 _profile="$(_detect_profile)"
3672 if [ "$_profile" ]; then
3673 _debug "Found profile: $_profile"
3674 _info "Installing alias to '$_profile'"
3675 _setopt "$_profile" ". \"$_envfile\""
3676 _info "OK, Close and reopen your terminal to start using $PROJECT_NAME"
3678 _info "No profile is found, you will need to go into $LE_WORKING_DIR to use $PROJECT_NAME"
3682 _cshfile="$LE_WORKING_DIR/$PROJECT_ENTRY.csh"
3683 _csh_profile="$HOME/.cshrc"
3684 if [ -f "$_csh_profile" ]; then
3685 _info "Installing alias to '$_csh_profile'"
3686 _setopt "$_cshfile" "setenv LE_WORKING_DIR" " " "\"$LE_WORKING_DIR\""
3687 _setopt "$_cshfile" "alias $PROJECT_ENTRY" " " "\"$LE_WORKING_DIR/$PROJECT_ENTRY\""
3688 _setopt "$_csh_profile" "source \"$_cshfile\""
3692 _tcsh_profile="$HOME/.tcshrc"
3693 if [ -f "$_tcsh_profile" ]; then
3694 _info "Installing alias to '$_tcsh_profile'"
3695 _setopt "$_cshfile" "setenv LE_WORKING_DIR" " " "\"$LE_WORKING_DIR\""
3696 _setopt "$_cshfile" "alias $PROJECT_ENTRY" " " "\"$LE_WORKING_DIR/$PROJECT_ENTRY\""
3697 _setopt "$_tcsh_profile" "source \"$_cshfile\""
3705 if [ -z "$LE_WORKING_DIR" ]; then
3706 LE_WORKING_DIR="$DEFAULT_INSTALL_HOME"
3710 if ! _initpath; then
3711 _err "Install failed."
3714 if [ "$_nocron" ]; then
3715 _debug "Skip install cron job"
3718 if ! _precheck "$_nocron"; then
3719 _err "Pre-check failed, can not install."
3724 if [ -d "$HOME/.le" ]; then
3725 for envfile in "le.env" "le.sh.env"; do
3726 if [ -f "$HOME/.le/$envfile" ]; then
3727 if grep "le.sh" "$HOME/.le/$envfile" >/dev/null; then
3729 _info "You are upgrading from le.sh"
3730 _info "Renaming \"$HOME/.le\" to $LE_WORKING_DIR"
3731 mv "$HOME/.le" "$LE_WORKING_DIR"
3732 mv "$LE_WORKING_DIR/$envfile" "$LE_WORKING_DIR/$PROJECT_ENTRY.env"
3739 _info "Installing to $LE_WORKING_DIR"
3741 if ! mkdir -p "$LE_WORKING_DIR"; then
3742 _err "Can not create working dir: $LE_WORKING_DIR"
3746 chmod 700 "$LE_WORKING_DIR"
3748 cp "$PROJECT_ENTRY" "$LE_WORKING_DIR/" && chmod +x "$LE_WORKING_DIR/$PROJECT_ENTRY"
3750 if [ "$?" != "0" ]; then
3751 _err "Install failed, can not copy $PROJECT_ENTRY"
3755 _info "Installed to $LE_WORKING_DIR/$PROJECT_ENTRY"
3759 for subf in $_SUB_FOLDERS; do
3760 if [ -d "$subf" ]; then
3761 mkdir -p "$LE_WORKING_DIR/$subf"
3762 cp "$subf"/* "$LE_WORKING_DIR"/"$subf"/
3766 if [ ! -f "$ACCOUNT_CONF_PATH" ]; then
3770 if [ "$_DEFAULT_ACCOUNT_CONF_PATH" != "$ACCOUNT_CONF_PATH" ]; then
3771 _setopt "$_DEFAULT_ACCOUNT_CONF_PATH" "ACCOUNT_CONF_PATH" "=" "\"$ACCOUNT_CONF_PATH\""
3774 if [ "$_DEFAULT_CERT_HOME" != "$CERT_HOME" ]; then
3775 _saveaccountconf "CERT_HOME" "$CERT_HOME"
3778 if [ "$_DEFAULT_ACCOUNT_KEY_PATH" != "$ACCOUNT_KEY_PATH" ]; then
3779 _saveaccountconf "ACCOUNT_KEY_PATH" "$ACCOUNT_KEY_PATH"
3782 if [ -z "$_nocron" ]; then
3786 if [ -z "$NO_DETECT_SH" ]; then
3788 if _exists bash; then
3789 _info "Good, bash is found, so change the shebang to use bash as prefered."
3790 _shebang='#!/usr/bin/env bash'
3791 _setShebang
"$LE_WORKING_DIR/$PROJECT_ENTRY" "$_shebang"
3792 for subf
in $_SUB_FOLDERS; do
3793 if [ -d "$LE_WORKING_DIR/$subf" ]; then
3794 for _apifile
in "$LE_WORKING_DIR/$subf/"*.sh
; do
3795 _setShebang
"$_apifile" "$_shebang"
3808 if [ -z "$_nocron" ]; then
3815 rm -f "$LE_WORKING_DIR/$PROJECT_ENTRY"
3816 _info
"The keys and certs are in $LE_WORKING_DIR, you can remove them by yourself."
3823 _profile
="$(_detect_profile)"
3824 if [ "$_profile" ]; then
3825 _info
"Uninstalling alias from: '$_profile'"
3826 text
="$(cat "$_profile")"
3827 echo "$text" |
sed "s|^.*\"$LE_WORKING_DIR/$PROJECT_NAME.env\"$||" >"$_profile"
3830 _csh_profile
="$HOME/.cshrc"
3831 if [ -f "$_csh_profile" ]; then
3832 _info
"Uninstalling alias from: '$_csh_profile'"
3833 text
="$(cat "$_csh_profile")"
3834 echo "$text" |
sed "s|^.*\"$LE_WORKING_DIR/$PROJECT_NAME.csh\"$||" >"$_csh_profile"
3837 _tcsh_profile
="$HOME/.tcshrc"
3838 if [ -f "$_tcsh_profile" ]; then
3839 _info
"Uninstalling alias from: '$_csh_profile'"
3840 text
="$(cat "$_tcsh_profile")"
3841 echo "$text" |
sed "s|^.*\"$LE_WORKING_DIR/$PROJECT_NAME.csh\"$||" >"$_tcsh_profile"
3849 if [ "$AUTO_UPGRADE" = "1" ]; then
3850 export LE_WORKING_DIR
3853 _err
"Cron:Upgrade failed!"
3857 .
"$LE_WORKING_DIR/$PROJECT_ENTRY" >/dev
/null
3863 _info
"Auto upgraded to: $VER"
3879 echo "Usage: $PROJECT_ENTRY command ...[parameters]....
3881 --help, -h Show this help message.
3882 --version, -v Show version info.
3883 --install Install $PROJECT_NAME to your system.
3884 --uninstall Uninstall $PROJECT_NAME, and uninstall the cron job.
3885 --upgrade Upgrade $PROJECT_NAME to the latest code from $PROJECT .
3886 --issue Issue a cert.
3887 --signcsr Issue a cert from an existing csr.
3888 --deploy Deploy the cert to your server.
3889 --installcert Install the issued cert to apache/nginx or any other server.
3890 --renew, -r Renew a cert.
3891 --renewAll Renew all the certs.
3892 --revoke Revoke a cert.
3893 --list List all the certs.
3894 --showcsr Show the content of a csr.
3895 --installcronjob Install the cron job to renew certs, you don't need to call this. The 'install' command can automatically install the cron job.
3896 --uninstallcronjob Uninstall the cron job. The 'uninstall' command can do this automatically.
3897 --cron Run cron job to renew all the certs.
3898 --toPkcs Export the certificate and key to a pfx file.
3899 --updateaccount Update account info.
3900 --registeraccount Register account key.
3901 --createAccountKey, -cak Create an account private key, professional use.
3902 --createDomainKey, -cdk Create an domain private key, professional use.
3903 --createCSR, -ccsr Create CSR , professional use.
3904 --deactivate Deactivate the domain authz, professional use.
3907 --domain, -d domain.tld Specifies a domain, used to issue, renew or revoke etc.
3908 --force, -f Used to force to install or force to renew a cert immediately.
3909 --staging, --test Use staging server, just for test.
3910 --debug Output debug info.
3912 --webroot, -w /path/to/webroot Specifies the web root folder for web root mode.
3913 --standalone Use standalone mode.
3914 --tls Use standalone tls mode.
3915 --apache Use apache mode.
3916 --dns [dns_cf|dns_dp|dns_cx|/path/to/api/file] Use dns mode or dns api.
3917 --dnssleep [$DEFAULT_DNS_SLEEP] The time in seconds to wait for all the txt records to take effect in dns api mode. Default $DEFAULT_DNS_SLEEP seconds.
3919 --keylength, -k [2048] Specifies the domain key length: 2048, 3072, 4096, 8192 or ec-256, ec-384.
3920 --accountkeylength, -ak [2048] Specifies the account key length.
3921 --log [/path/to/logfile] Specifies the log file. The default is: \"$DEFAULT_LOG_FILE\" if you don't give a file path here.
3922 --log-level 1|2 Specifies the log level, default is 1.
3924 These parameters are to install the cert to nginx/apache or anyother server after issue/renew a cert:
3926 --certpath /path/to/real/cert/file After issue/renew, the cert will be copied to this path.
3927 --keypath /path/to/real/key/file After issue/renew, the key will be copied to this path.
3928 --capath /path/to/real/ca/file After issue/renew, the intermediate cert will be copied to this path.
3929 --fullchainpath /path/to/fullchain/file After issue/renew, the fullchain cert will be copied to this path.
3931 --reloadcmd \"service nginx reload\" After issue/renew, it's used to reload the server.
3933 --accountconf Specifies a customized account config file.
3934 --home Specifies the home dir for $PROJECT_NAME .
3935 --certhome Specifies the home dir to save all the certs, only valid for '--install' command.
3936 --useragent Specifies the user agent string. it will be saved for future use too.
3937 --accountemail Specifies the account email for registering, Only valid for the '--install' command.
3938 --accountkey Specifies the account key path, Only valid for the '--install' command.
3939 --days Specifies the days to renew the cert when using '--issue' command. The max value is $MAX_RENEW days.
3940 --httpport Specifies the standalone listening port. Only valid if the server is behind a reverse proxy or load balancer.
3941 --tlsport Specifies the standalone tls listening port. Only valid if the server is behind a reverse proxy or load balancer.
3942 --local-address Specifies the standalone/tls server listening address, in case you have multiple ip addresses.
3943 --listraw Only used for '--list' command, list the certs in raw format.
3944 --stopRenewOnError, -se Only valid for '--renewall' command. Stop if one cert has error in renewal.
3945 --insecure Do not check the server certificate, in some devices, the api server's certificate may not be trusted.
3946 --ca-bundle Specifices the path to the CA certificate bundle to verify api server's certificate.
3947 --nocron Only valid for '--install' command, which means: do not install the default cron job. In this case, the certs will not be renewed automatically.
3948 --ecc Specifies to use the ECC cert. Valid for '--installcert', '--renew', '--revoke', '--toPkcs' and '--createCSR'
3949 --csr Specifies the input csr.
3950 --pre-hook Command to be run before obtaining any certificates.
3951 --post-hook Command to be run after attempting to obtain/renew certificates. No matter the obain/renew is success or failed.
3952 --renew-hook Command to be run once for each successfully renewed certificate.
3953 --deploy-hook The hook file to deploy cert
3954 --ocsp-must-staple, --ocsp Generate ocsp must Staple extension.
3955 --auto-upgrade [0|1] Valid for '--upgrade' command, indicating whether to upgrade automatically in future.
3956 --listen-v4 Force standalone/tls server to listen at ipv4.
3957 --listen-v6 Force standalone/tls server to listen at ipv6.
3963 _info
"Installing from online archive."
3965 if [ ! "$BRANCH" ]; then
3969 target
="$PROJECT/archive/$BRANCH.tar.gz"
3970 _info
"Downloading $target"
3971 localname
="$BRANCH.tar.gz"
3972 if ! _get
"$target" >$localname; then
3973 _err
"Download error."
3977 _info
"Extracting $localname"
3980 cd "$PROJECT_NAME-$BRANCH"
3981 chmod +x
$PROJECT_ENTRY
3982 if .
/$PROJECT_ENTRY install "$_nocron"; then
3983 _info
"Install success!"
3988 rm -rf "$PROJECT_NAME-$BRANCH"
3996 export LE_WORKING_DIR
3997 cd "$LE_WORKING_DIR"
3998 _installOnline
"nocron"
4000 _info
"Upgrade success!"
4003 _err
"Upgrade failed!"
4008 _processAccountConf
() {
4009 if [ "$_useragent" ]; then
4010 _saveaccountconf
"USER_AGENT" "$_useragent"
4011 elif [ "$USER_AGENT" ] && [ "$USER_AGENT" != "$DEFAULT_USER_AGENT" ]; then
4012 _saveaccountconf
"USER_AGENT" "$USER_AGENT"
4015 if [ "$_accountemail" ]; then
4016 _saveaccountconf
"ACCOUNT_EMAIL" "$_accountemail"
4017 elif [ "$ACCOUNT_EMAIL" ] && [ "$ACCOUNT_EMAIL" != "$DEFAULT_ACCOUNT_EMAIL" ]; then
4018 _saveaccountconf
"ACCOUNT_EMAIL" "$ACCOUNT_EMAIL"
4021 if [ "$_auto_upgrade" ]; then
4022 _saveaccountconf
"AUTO_UPGRADE" "$_auto_upgrade"
4023 elif [ "$AUTO_UPGRADE" ]; then
4024 _saveaccountconf
"AUTO_UPGRADE" "$AUTO_UPGRADE"
4032 _altdomains
="$NO_VALUE"
4035 _accountkeylength
=""
4051 _stopRenewOnError
=""
4068 while [ ${#} -gt 0 ]; do
4106 --renewAll |
--renewall)
4116 _CMD
="installcronjob"
4119 _CMD
="uninstallcronjob"
4127 --createAccountKey |
--createaccountkey |
-cak)
4128 _CMD
="createAccountKey"
4130 --createDomainKey |
--createdomainkey |
-cdk)
4131 _CMD
="createDomainKey"
4133 --createCSR |
--createcsr |
-ccr)
4140 _CMD
="updateaccount"
4143 _CMD
="registeraccount"
4148 if [ "$_dvalue" ]; then
4149 if _startswith
"$_dvalue" "-"; then
4150 _err
"'$_dvalue' is not a valid domain for parameter '$1'"
4153 if _is_idn
"$_dvalue" && ! _exists idn
; then
4154 _err
"It seems that $_dvalue is an IDN( Internationalized Domain Names), please install 'idn' command first."
4158 if [ -z "$_domain" ]; then
4161 if [ "$_altdomains" = "$NO_VALUE" ]; then
4162 _altdomains
="$_dvalue"
4164 _altdomains
="$_altdomains,$_dvalue"
4179 if [ -z "$2" ] || _startswith
"$2" "-"; then
4188 if [ -z "$_webroot" ]; then
4191 _webroot
="$_webroot,$wvalue"
4197 if [ -z "$_webroot" ]; then
4200 _webroot
="$_webroot,$wvalue"
4205 _local_address
="$_local_address$lvalue,"
4210 if [ -z "$_webroot" ]; then
4213 _webroot
="$_webroot,$wvalue"
4218 if [ -z "$_webroot" ]; then
4221 _webroot
="$_webroot,$wvalue"
4226 if ! _startswith
"$2" "-"; then
4230 if [ -z "$_webroot" ]; then
4233 _webroot
="$_webroot,$wvalue"
4238 Le_DNSSleep
="$_dnssleep"
4246 --accountkeylength |
-ak)
4247 _accountkeylength
="$2"
4267 --reloadcmd |
--reloadCmd)
4277 ACCOUNT_CONF_PATH
="$_accountconf"
4286 CERT_HOME
="$_certhome"
4291 USER_AGENT
="$_useragent"
4296 ACCOUNT_EMAIL
="$_accountemail"
4301 ACCOUNT_KEY_PATH
="$_accountkey"
4306 Le_RenewalDays
="$_days"
4311 Le_HTTPPort
="$_httpport"
4316 Le_TLSPort
="$_tlsport"
4323 --stopRenewOnError |
--stoprenewonerror |
-se)
4324 _stopRenewOnError
="1"
4331 _ca_bundle
="$(readlink -f "$2")"
4332 CA_BUNDLE
="$_ca_bundle"
4361 --ocsp-must-staple |
--ocsp)
4367 if _startswith
"$_logfile" '-'; then
4372 LOG_FILE
="$_logfile"
4373 if [ -z "$LOG_LEVEL" ]; then
4374 LOG_LEVEL
="$DEFAULT_LOG_LEVEL"
4379 LOG_LEVEL
="$_log_level"
4384 if [ -z "$_auto_upgrade" ] || _startswith
"$_auto_upgrade" '-'; then
4389 AUTO_UPGRADE
="$_auto_upgrade"
4393 Le_Listen_V4
="$_listen_v4"
4397 Le_Listen_V6
="$_listen_v6"
4401 _err
"Unknown parameter : $1"
4409 if [ "${_CMD}" != "install" ]; then
4411 if [ "$_log" ]; then
4412 if [ -z "$_logfile" ]; then
4413 _logfile
="$DEFAULT_LOG_FILE"
4416 if [ "$_logfile" ]; then
4417 _saveaccountconf
"LOG_FILE" "$_logfile"
4418 LOG_FILE
="$_logfile"
4421 if [ "$_log_level" ]; then
4422 _saveaccountconf
"LOG_LEVEL" "$_log_level"
4423 LOG_LEVEL
="$_log_level"
4429 _debug2 LE_WORKING_DIR
"$LE_WORKING_DIR"
4431 if [ "$DEBUG" ]; then
4436 install) install "$_nocron" ;;
4437 uninstall
) uninstall
"$_nocron" ;;
4440 issue
"$_webroot" "$_domain" "$_altdomains" "$_keylength" "$_certpath" "$_keypath" "$_capath" "$_reloadcmd" "$_fullchainpath" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address"
4443 deploy
"$_domain" "$_deploy_hook" "$_ecc"
4446 signcsr
"$_csr" "$_webroot"
4449 showcsr
"$_csr" "$_domain"
4452 installcert
"$_domain" "$_certpath" "$_keypath" "$_capath" "$_reloadcmd" "$_fullchainpath" "$_ecc"
4455 renew
"$_domain" "$_ecc"
4458 renewAll
"$_stopRenewOnError"
4461 revoke
"$_domain" "$_ecc"
4464 deactivate
"$_domain,$_altdomains"
4467 registeraccount
"$_accountkeylength"
4475 installcronjob
) installcronjob
;;
4476 uninstallcronjob
) uninstallcronjob
;;
4479 toPkcs
"$_domain" "$_password" "$_ecc"
4482 createAccountKey
"$_accountkeylength"
4485 createDomainKey
"$_domain" "$_keylength"
4488 createCSR
"$_domain" "$_altdomains" "$_ecc"
4492 _err
"Invalid command: $_CMD"
4498 if [ "$_ret" != "0" ]; then
4502 if [ "${_CMD}" = "install" ]; then
4503 if [ "$_log" ]; then
4504 if [ -z "$LOG_FILE" ]; then
4505 LOG_FILE
="$DEFAULT_LOG_FILE"
4507 _saveaccountconf
"LOG_FILE" "$LOG_FILE"
4510 if [ "$_log_level" ]; then
4511 _saveaccountconf
"LOG_LEVEL" "$_log_level"
4518 if [ "$INSTALLONLINE" ]; then
4520 _installOnline
$BRANCH
4525 [ -z "$1" ] && showhelp
&& return
4526 if _startswith
"$1" '-'; then _process
"$@"; else "$@"; fi