- Timestamp:
- 03/25/20 14:25:12 (5 years ago)
- Branches:
- master
- Children:
- 3c9eb90
- Parents:
- e856512
- Location:
- npl/syn3/acme
- Files:
-
- 2 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
npl/syn3/acme/root/usr/bin/acme.sh
re856512 reb67240 1 1 #!/usr/bin/env sh 2 2 3 VER=2. 7.93 VER=2.8.6 4 4 5 5 PROJECT_NAME="acme.sh" … … 7 7 PROJECT_ENTRY="acme.sh" 8 8 9 PROJECT="https://github.com/ Neilpang/$PROJECT_NAME"9 PROJECT="https://github.com/acmesh-official/$PROJECT_NAME" 10 10 11 11 DEFAULT_INSTALL_HOME="$HOME/.$PROJECT_NAME" 12 13 _WINDOWS_SCHEDULER_NAME="$PROJECT_NAME.cron" 14 12 15 _SCRIPT_="$0" 13 16 14 _SUB_FOLDERS="dnsapi deploy" 17 _SUB_FOLDER_NOTIFY="notify" 18 _SUB_FOLDER_DNSAPI="dnsapi" 19 _SUB_FOLDER_DEPLOY="deploy" 20 21 _SUB_FOLDERS="$_SUB_FOLDER_DNSAPI $_SUB_FOLDER_DEPLOY $_SUB_FOLDER_NOTIFY" 15 22 16 23 LETSENCRYPT_CA_V1="https://acme-v01.api.letsencrypt.org/directory" … … 20 27 LETSENCRYPT_STAGING_CA_V2="https://acme-staging-v02.api.letsencrypt.org/directory" 21 28 22 DEFAULT_CA=$LETSENCRYPT_CA_V 123 DEFAULT_STAGING_CA=$LETSENCRYPT_STAGING_CA_V 129 DEFAULT_CA=$LETSENCRYPT_CA_V2 30 DEFAULT_STAGING_CA=$LETSENCRYPT_STAGING_CA_V2 24 31 25 32 DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)" … … 36 43 VTYPE_HTTP="http-01" 37 44 VTYPE_DNS="dns-01" 38 VTYPE_TLS="tls-sni-01" 39 VTYPE_TLS2="tls-sni-02" 45 VTYPE_ALPN="tls-alpn-01" 40 46 41 47 LOCAL_ANY_ADDRESS="0.0.0.0" 42 48 43 MAX_RENEW=6049 DEFAULT_RENEW=60 44 50 45 51 DEFAULT_DNS_SLEEP=120 … … 47 53 NO_VALUE="no" 48 54 49 W_TLS="tls"50 55 W_DNS="dns" 56 W_ALPN="alpn" 51 57 DNS_ALIAS_PREFIX="=" 52 58 … … 67 73 CONTENT_TYPE_JSON="application/jose+json" 68 74 RENEW_SKIP=2 75 76 B64CONF_START="__ACME_BASE64__START_" 77 B64CONF_END="__ACME_BASE64__END_" 69 78 70 79 ECC_SEP="_" … … 81 90 DEBUG_LEVEL_DEFAULT=$DEBUG_LEVEL_1 82 91 DEBUG_LEVEL_NONE=0 92 93 DOH_CLOUDFLARE=1 94 DOH_GOOGLE=2 83 95 84 96 HIDDEN_VALUE="[hidden](please add '--output-insecure' to see this value)" … … 103 115 SYSLOG_LEVEL_NONE=0 104 116 105 _DEBUG_WIKI="https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh" 106 107 _PREPARE_LINK="https://github.com/Neilpang/acme.sh/wiki/Install-preparations" 108 109 _STATELESS_WIKI="https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode" 110 111 _DNS_ALIAS_WIKI="https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode" 112 113 _DNS_MANUAL_WIKI="https://github.com/Neilpang/acme.sh/wiki/dns-manual-mode" 117 NOTIFY_LEVEL_DISABLE=0 118 NOTIFY_LEVEL_ERROR=1 119 NOTIFY_LEVEL_RENEW=2 120 NOTIFY_LEVEL_SKIP=3 121 122 NOTIFY_LEVEL_DEFAULT=$NOTIFY_LEVEL_RENEW 123 124 NOTIFY_MODE_BULK=0 125 NOTIFY_MODE_CERT=1 126 127 NOTIFY_MODE_DEFAULT=$NOTIFY_MODE_BULK 128 129 _DEBUG_WIKI="https://github.com/acmesh-official/acme.sh/wiki/How-to-debug-acme.sh" 130 131 _PREPARE_LINK="https://github.com/acmesh-official/acme.sh/wiki/Install-preparations" 132 133 _STATELESS_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Stateless-Mode" 134 135 _DNS_ALIAS_WIKI="https://github.com/acmesh-official/acme.sh/wiki/DNS-alias-mode" 136 137 _DNS_MANUAL_WIKI="https://github.com/acmesh-official/acme.sh/wiki/dns-manual-mode" 138 139 _NOTIFY_WIKI="https://github.com/acmesh-official/acme.sh/wiki/notify" 140 141 _SUDO_WIKI="https://github.com/acmesh-official/acme.sh/wiki/sudo" 114 142 115 143 _DNS_MANUAL_ERR="The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead." … … 125 153 126 154 __green() { 127 if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" -o "${ACME_FORCE_COLOR}" = "1" ]; then 128 printf '\033[1;31;32m' 155 if [ "${__INTERACTIVE}${ACME_NO_COLOR:-0}" = "10" -o "${ACME_FORCE_COLOR}" = "1" ]; then 156 printf '\33[1;32m%b\33[0m' "$1" 157 return 129 158 fi 130 159 printf -- "%b" "$1" 131 if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" -o "${ACME_FORCE_COLOR}" = "1" ]; then132 printf '\033[0m'133 fi134 160 } 135 161 136 162 __red() { 137 if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" -o "${ACME_FORCE_COLOR}" = "1" ]; then 138 printf '\033[1;31;40m' 163 if [ "${__INTERACTIVE}${ACME_NO_COLOR:-0}" = "10" -o "${ACME_FORCE_COLOR}" = "1" ]; then 164 printf '\33[1;31m%b\33[0m' "$1" 165 return 139 166 fi 140 167 printf -- "%b" "$1" 141 if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" -o "${ACME_FORCE_COLOR}" = "1" ]; then142 printf '\033[0m'143 fi144 168 } 145 169 146 170 _printargs() { 171 _exitstatus="$?" 147 172 if [ -z "$NO_TIMESTAMP" ] || [ "$NO_TIMESTAMP" = "0" ]; then 148 173 printf -- "%s" "[$(date)] " … … 154 179 fi 155 180 printf "\n" 181 # return the saved exit status 182 return "$_exitstatus" 156 183 } 157 184 … … 181 208 echo "socat:" 182 209 if _exists "socat"; then 183 socat - h2>&1210 socat -V 2>&1 184 211 else 185 212 _debug "socat doesn't exists." … … 189 216 #class 190 217 _syslog() { 218 _exitstatus="$?" 191 219 if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" = "$SYSLOG_LEVEL_NONE" ]; then 192 220 return … … 202 230 fi 203 231 $__logger_i -t "$PROJECT_NAME" -p "$_logclass" "$(_printargs "$@")" >/dev/null 2>&1 232 return "$_exitstatus" 204 233 } 205 234 … … 237 266 } 238 267 268 __debug_bash_helper() { 269 # At this point only do for --debug 3 270 if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -lt "$DEBUG_LEVEL_3" ]; then 271 return 272 fi 273 # Return extra debug info when running with bash, otherwise return empty 274 # string. 275 if [ -z "${BASH_VERSION}" ]; then 276 return 277 fi 278 # We are a bash shell at this point, return the filename, function name, and 279 # line number as a string 280 _dbh_saveIFS=$IFS 281 IFS=" " 282 # Must use eval or syntax error happens under dash. The eval should use 283 # single quotes as older versions of busybox had a bug with double quotes and 284 # eval. 285 # Use 'caller 1' as we want one level up the stack as we should be called 286 # by one of the _debug* functions 287 eval '_dbh_called=($(caller 1))' 288 IFS=$_dbh_saveIFS 289 eval '_dbh_file=${_dbh_called[2]}' 290 if [ -n "${_script_home}" ]; then 291 # Trim off the _script_home directory name 292 eval '_dbh_file=${_dbh_file#$_script_home/}' 293 fi 294 eval '_dbh_function=${_dbh_called[1]}' 295 eval '_dbh_lineno=${_dbh_called[0]}' 296 printf "%-40s " "$_dbh_file:${_dbh_function}:${_dbh_lineno}" 297 } 298 239 299 _debug() { 240 300 if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_1" ]; then … … 245 305 fi 246 306 if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_1" ]; then 247 _printargs "$@" >&2 307 _bash_debug=$(__debug_bash_helper) 308 _printargs "${_bash_debug}$@" >&2 248 309 fi 249 310 } … … 278 339 fi 279 340 if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then 280 _printargs "$@" >&2 341 _bash_debug=$(__debug_bash_helper) 342 _printargs "${_bash_debug}$@" >&2 281 343 fi 282 344 } … … 310 372 fi 311 373 if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_3" ]; then 312 _printargs "$@" >&2 374 _bash_debug=$(__debug_bash_helper) 375 _printargs "${_bash_debug}$@" >&2 313 376 fi 314 377 } … … 779 842 } 780 843 844 _json_encode() { 845 _j_str="$(sed 's/"/\\"/g' | sed "s/\r/\\r/g")" 846 _debug3 "_json_encode" 847 _debug3 "_j_str" "$_j_str" 848 echo "$_j_str" | _hex_dump | _lower_case | sed 's/0a/5c 6e/g' | tr -d ' ' | _h2b | tr -d "\r\n" 849 } 850 781 851 #options file 782 852 _sed_i() { … … 1001 1071 if _isEccKey "$length"; then 1002 1072 _debug "Using ec name: $eccname" 1003 ${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -genkey 2>/dev/null >"$f" 1073 if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -genkey 2>/dev/null)"; then 1074 echo "$_opkey" >"$f" 1075 else 1076 _err "error ecc key name: $eccname" 1077 return 1 1078 fi 1004 1079 else 1005 1080 _debug "Using RSA: $length" 1006 ${ACME_OPENSSL_BIN:-openssl} genrsa "$length" 2>/dev/null >"$f" 1081 if _opkey="$(${ACME_OPENSSL_BIN:-openssl} genrsa "$length" 2>/dev/null)"; then 1082 echo "$_opkey" >"$f" 1083 else 1084 _err "error rsa key: $length" 1085 return 1 1086 fi 1007 1087 fi 1008 1088 … … 1017 1097 _is_idn_d="$1" 1018 1098 _debug2 _is_idn_d "$_is_idn_d" 1019 _idn_temp=$(printf "%s" "$_is_idn_d" | tr -d '0-9' | tr -d 'a-z' | tr -d 'A-Z' | tr -d '*.,- ')1099 _idn_temp=$(printf "%s" "$_is_idn_d" | tr -d '0-9' | tr -d 'a-z' | tr -d 'A-Z' | tr -d '*.,-_') 1020 1100 _debug2 _idn_temp "$_idn_temp" 1021 1101 [ "$_idn_temp" ] … … 1051 1131 } 1052 1132 1053 #_createcsr cn san_list keyfile csrfile conf 1133 #_createcsr cn san_list keyfile csrfile conf acmeValidationv1 1054 1134 _createcsr() { 1055 1135 _debug _createcsr … … 1059 1139 csr="$4" 1060 1140 csrconf="$5" 1141 acmeValidationv1="$6" 1061 1142 _debug2 domain "$domain" 1062 1143 _debug2 domainlist "$domainlist" … … 1067 1148 printf "[ req_distinguished_name ]\n[ req ]\ndistinguished_name = req_distinguished_name\nreq_extensions = v3_req\n[ v3_req ]\n\nkeyUsage = nonRepudiation, digitalSignature, keyEncipherment" >"$csrconf" 1068 1149 1069 if [ -z "$domainlist" ] || [ "$domainlist" = "$NO_VALUE" ]; then 1150 if [ "$acmeValidationv1" ]; then 1151 domainlist="$(_idn "$domainlist")" 1152 printf -- "\nsubjectAltName=DNS:$domainlist" >>"$csrconf" 1153 elif [ -z "$domainlist" ] || [ "$domainlist" = "$NO_VALUE" ]; then 1070 1154 #single domain 1071 1155 _info "Single domain" "$domain" 1072 printf -- "\nsubjectAltName=DNS:$ domain" >>"$csrconf"1156 printf -- "\nsubjectAltName=DNS:$(_idn "$domain")" >>"$csrconf" 1073 1157 else 1074 1158 domainlist="$(_idn "$domainlist")" 1075 1159 _debug2 domainlist "$domainlist" 1076 1160 if _contains "$domainlist" ","; then 1077 alt="DNS:$ domain,DNS:$(echo "$domainlist" | sed "s/,,/,/g" | sed "s/,/,DNS:/g")"1161 alt="DNS:$(_idn "$domain"),DNS:$(echo "$domainlist" | sed "s/,,/,/g" | sed "s/,/,DNS:/g")" 1078 1162 else 1079 alt="DNS:$ domain,DNS:$domainlist"1163 alt="DNS:$(_idn "$domain"),DNS:$domainlist" 1080 1164 fi 1081 1165 #multi … … 1087 1171 _cleardomainconf Le_OCSP_Stable 1088 1172 printf -- "\nbasicConstraints = CA:FALSE\n1.3.6.1.5.5.7.1.24=DER:30:03:02:01:05" >>"$csrconf" 1173 fi 1174 1175 if [ "$acmeValidationv1" ]; then 1176 printf "\n1.3.6.1.5.5.7.1.31=critical,DER:04:20:${acmeValidationv1}" >>"${csrconf}" 1089 1177 fi 1090 1178 … … 1139 1227 if _contains "$_dnsAltnames," "DNS:$_csrsubj,"; then 1140 1228 _debug "AltNames contains subject" 1141 _dnsAltnames="$(printf "%s" "$_dnsAltnames," | sed "s/DNS:$_csrsubj,//g")" 1229 _excapedAlgnames="$(echo "$_dnsAltnames" | tr '*' '#')" 1230 _debug _excapedAlgnames "$_excapedAlgnames" 1231 _escapedSubject="$(echo "$_csrsubj" | tr '*' '#')" 1232 _debug _escapedSubject "$_escapedSubject" 1233 _dnsAltnames="$(echo "$_excapedAlgnames," | sed "s/DNS:$_escapedSubject,//g" | tr '#' '*' | sed "s/,\$//g")" 1234 _debug _dnsAltnames "$_dnsAltnames" 1142 1235 else 1143 1236 _debug "AltNames doesn't contain subject" 1144 1237 fi 1145 1238 1146 printf "%s""$_dnsAltnames" | sed "s/DNS://g"1239 echo "$_dnsAltnames" | sed "s/DNS://g" 1147 1240 } 1148 1241 … … 1182 1275 if _exists "netstat"; then 1183 1276 _debug "Using: netstat" 1184 if netstat -h 2>&1 | grep "\-p proto" >/dev/null; then1277 if netstat -help 2>&1 | grep "\-p proto" >/dev/null; then 1185 1278 #for windows version netstat tool 1186 1279 netstat -an -p tcp | grep "LISTENING" | grep ":$_port " … … 1295 1388 1296 1389 mkdir -p "$CA_DIR" 1297 if [ - f"$ACCOUNT_KEY_PATH" ]; then1390 if [ -s "$ACCOUNT_KEY_PATH" ]; then 1298 1391 _info "Account key exists, skip" 1299 return 1392 return 0 1300 1393 else 1301 1394 #generate account key 1302 _createkey "$length" "$ACCOUNT_KEY_PATH" 1303 chmod 600 "$ACCOUNT_KEY_PATH" 1395 if _createkey "$length" "$ACCOUNT_KEY_PATH"; then 1396 chmod 600 "$ACCOUNT_KEY_PATH" 1397 _info "Create account key ok." 1398 return 0 1399 else 1400 _err "Create account key error." 1401 return 1 1402 fi 1304 1403 fi 1305 1404 … … 1324 1423 _initpath "$domain" "$_cdl" 1325 1424 1326 if [ ! -f "$CERT_KEY_PATH" ] || ([ "$FORCE" ] && ! [ "$IS_RENEW" ]) || [ "$Le_ForceNewDomainKey" = "1" ]; then1425 if [ ! -f "$CERT_KEY_PATH" ] || [ ! -s "$CERT_KEY_PATH" ] || ([ "$FORCE" ] && ! [ "$IS_RENEW" ]) || [ "$Le_ForceNewDomainKey" = "1" ]; then 1327 1426 if _createkey "$_cdl" "$CERT_KEY_PATH"; then 1328 1427 _savedomainconf Le_Keylength "$_cdl" 1329 1428 _info "The domain key is here: $(__green $CERT_KEY_PATH)" 1429 return 0 1430 else 1431 _err "Can not create domain key" 1432 return 1 1330 1433 fi 1331 1434 else … … 1375 1478 1376 1479 _time2str() { 1480 #BSD 1481 if date -u -r "$1" 2>/dev/null; then 1482 return 1483 fi 1484 1377 1485 #Linux 1378 1486 if date -u -d@"$1" 2>/dev/null; then … … 1380 1488 fi 1381 1489 1382 #BSD 1383 if date -u -r "$1" 2>/dev/null; then 1384 return 1385 fi 1386 1387 #Soaris 1490 #Solaris 1388 1491 if _exists adb; then 1389 1492 _t_s_a=$(echo "0t${1}=Y" | adb) … … 1520 1623 JWK_HEADERPLACE_PART2='", "alg": "ES'$__ECC_KEY_LEN'"' 1521 1624 else 1522 _err "Only RSA or EC key is supported." 1625 _err "Only RSA or EC key is supported. keyfile=$keyfile" 1626 _debug2 "$(cat "$keyfile")" 1523 1627 return 1 1524 1628 fi … … 1608 1712 } 1609 1713 1610 # body url [needbase64] [POST|PUT ] [ContentType]1714 # body url [needbase64] [POST|PUT|DELETE] [ContentType] 1611 1715 _post() { 1612 1716 body="$1" … … 1631 1735 _CURL="$_CURL --insecure " 1632 1736 fi 1737 if [ "$httpmethod" = "HEAD" ]; then 1738 _CURL="$_CURL -I " 1739 fi 1633 1740 _debug "_CURL" "$_CURL" 1634 1741 if [ "$needbase64" ]; then 1635 if [ "$_postContentType" ]; then 1636 response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)" 1742 if [ "$body" ]; then 1743 if [ "$_postContentType" ]; then 1744 response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)" 1745 else 1746 response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)" 1747 fi 1637 1748 else 1638 response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)" 1749 if [ "$_postContentType" ]; then 1750 response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$_post_url" | _base64)" 1751 else 1752 response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$_post_url" | _base64)" 1753 fi 1639 1754 fi 1640 1755 else 1641 if [ "$_postContentType" ]; then 1642 response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")" 1756 if [ "$body" ]; then 1757 if [ "$_postContentType" ]; then 1758 response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")" 1759 else 1760 response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")" 1761 fi 1643 1762 else 1644 response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")" 1763 if [ "$_postContentType" ]; then 1764 response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$_post_url")" 1765 else 1766 response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$_post_url")" 1767 fi 1645 1768 fi 1646 1769 fi … … 1657 1780 if [ "$HTTPS_INSECURE" ]; then 1658 1781 _WGET="$_WGET --no-check-certificate " 1782 fi 1783 if [ "$httpmethod" = "HEAD" ]; then 1784 _WGET="$_WGET --read-timeout=3.0 --tries=2 " 1659 1785 fi 1660 1786 _debug "_WGET" "$_WGET" … … 1679 1805 else 1680 1806 response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER")" 1807 fi 1808 elif [ "$httpmethod" = "HEAD" ]; then 1809 if [ "$_postContentType" ]; then 1810 response="$($_WGET --spider -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER")" 1811 else 1812 response="$($_WGET --spider -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER")" 1681 1813 fi 1682 1814 else … … 1796 1928 fi 1797 1929 1798 if [ "$ACME_VERSION" = "2" ]; then 1799 __request_conent_type="$CONTENT_TYPE_JSON" 1800 else 1801 __request_conent_type="" 1802 fi 1930 __request_conent_type="$CONTENT_TYPE_JSON" 1931 1803 1932 payload64=$(printf "%s" "$payload" | _base64 | _url_replace) 1804 1933 _debug3 payload64 "$payload64" 1805 1934 1806 MAX_REQUEST_RETRY_TIMES=5 1935 MAX_REQUEST_RETRY_TIMES=20 1936 _sleep_retry_sec=1 1807 1937 _request_retry_times=0 1808 1938 while [ "${_request_retry_times}" -lt "$MAX_REQUEST_RETRY_TIMES" ]; do … … 1812 1942 _headers="" 1813 1943 if [ "$ACME_NEW_NONCE" ]; then 1814 _debug2 "Get nonce . ACME_NEW_NONCE" "$ACME_NEW_NONCE"1944 _debug2 "Get nonce with HEAD. ACME_NEW_NONCE" "$ACME_NEW_NONCE" 1815 1945 nonceurl="$ACME_NEW_NONCE" 1816 if _post "" "$nonceurl" "" "HEAD" "$__request_conent_type" ; then1946 if _post "" "$nonceurl" "" "HEAD" "$__request_conent_type" >/dev/null; then 1817 1947 _headers="$(cat "$HTTP_HEADER")" 1818 fi 1819 fi 1820 if [ -z "$_headers" ]; then 1821 _debug2 "Get nonce. ACME_DIRECTORY" "$ACME_DIRECTORY" 1948 _debug2 _headers "$_headers" 1949 _CACHED_NONCE="$(echo "$_headers" | grep -i "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)" 1950 fi 1951 fi 1952 if [ -z "$_CACHED_NONCE" ]; then 1953 _debug2 "Get nonce with GET. ACME_DIRECTORY" "$ACME_DIRECTORY" 1822 1954 nonceurl="$ACME_DIRECTORY" 1823 1955 _headers="$(_get "$nonceurl" "onlyheader")" 1824 fi 1825 1956 _debug2 _headers "$_headers" 1957 _CACHED_NONCE="$(echo "$_headers" | grep -i "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)" 1958 fi 1959 if [ -z "$_CACHED_NONCE" ] && [ "$ACME_NEW_NONCE" ]; then 1960 _debug2 "Get nonce with GET. ACME_NEW_NONCE" "$ACME_NEW_NONCE" 1961 nonceurl="$ACME_NEW_NONCE" 1962 _headers="$(_get "$nonceurl" "onlyheader")" 1963 _debug2 _headers "$_headers" 1964 _CACHED_NONCE="$(echo "$_headers" | grep -i "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)" 1965 fi 1966 _debug2 _CACHED_NONCE "$_CACHED_NONCE" 1826 1967 if [ "$?" != "0" ]; then 1827 1968 _err "Can not connect to $nonceurl to get nonce." 1828 1969 return 1 1829 1970 fi 1830 1831 _debug2 _headers "$_headers"1832 1833 _CACHED_NONCE="$(echo "$_headers" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)"1834 _debug2 _CACHED_NONCE "$_CACHED_NONCE"1835 1971 else 1836 1972 _debug2 "Use _CACHED_NONCE" "$_CACHED_NONCE" … … 1866 2002 _debug3 sig "$sig" 1867 2003 1868 if [ "$ACME_VERSION" = "2" ]; then 1869 body="{\"protected\": \"$protected64\", \"payload\": \"$payload64\", \"signature\": \"$sig\"}" 1870 else 1871 body="{\"header\": $JWK_HEADER, \"protected\": \"$protected64\", \"payload\": \"$payload64\", \"signature\": \"$sig\"}" 1872 fi 2004 body="{\"protected\": \"$protected64\", \"payload\": \"$payload64\", \"signature\": \"$sig\"}" 1873 2005 _debug3 body "$body" 1874 2006 … … 1880 2012 return 1 1881 2013 fi 1882 _debug2 original "$response"1883 response="$(echo "$response" | _normalizeJson)"1884 2014 1885 2015 responseHeaders="$(cat "$HTTP_HEADER")" 1886 1887 2016 _debug2 responseHeaders "$responseHeaders" 1888 _debug2 response "$response" 2017 1889 2018 code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\r\n")" 1890 2019 _debug code "$code" 1891 2020 1892 _CACHED_NONCE="$(echo "$responseHeaders" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)" 1893 1894 _body="$response" 1895 if [ "$needbase64" ]; then 1896 _body="$(echo "$_body" | _dbase64 | tr -d '\0')" 1897 _debug3 _body "$_body" 1898 fi 1899 1900 if _contains "$_body" "JWS has invalid anti-replay nonce"; then 1901 _info "It seems the CA server is busy now, let's wait and retry." 1902 _sleep 5 1903 continue 1904 fi 1905 break 2021 _debug2 original "$response" 2022 if echo "$responseHeaders" | grep -i "Content-Type: *application/json" >/dev/null 2>&1; then 2023 response="$(echo "$response" | _normalizeJson)" 2024 fi 2025 _debug2 response "$response" 2026 2027 _CACHED_NONCE="$(echo "$responseHeaders" | grep -i "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)" 2028 2029 if ! _startswith "$code" "2"; then 2030 _body="$response" 2031 if [ "$needbase64" ]; then 2032 _body="$(echo "$_body" | _dbase64 multiline)" 2033 _debug3 _body "$_body" 2034 fi 2035 2036 if _contains "$_body" "JWS has invalid anti-replay nonce" || _contains "$_body" "JWS has an invalid anti-replay nonce"; then 2037 _info "It seems the CA server is busy now, let's wait and retry. Sleeping $_sleep_retry_sec seconds." 2038 _CACHED_NONCE="" 2039 _sleep $_sleep_retry_sec 2040 continue 2041 fi 2042 fi 2043 return 0 1906 2044 done 2045 _info "Giving up sending to CA server after $MAX_REQUEST_RETRY_TIMES retries." 2046 return 1 1907 2047 1908 2048 } … … 1945 2085 } 1946 2086 1947 #_save_conf file key value 2087 #_save_conf file key value base64encode 1948 2088 #save to conf 1949 2089 _save_conf() { … … 1951 2091 _sdkey="$2" 1952 2092 _sdvalue="$3" 2093 _b64encode="$4" 2094 if [ "$_sdvalue" ] && [ "$_b64encode" ]; then 2095 _sdvalue="${B64CONF_START}$(printf "%s" "${_sdvalue}" | _base64)${B64CONF_END}" 2096 fi 1953 2097 if [ "$_s_c_f" ]; then 1954 2098 _setopt "$_s_c_f" "$_sdkey" "=" "'$_sdvalue'" … … 1975 2119 _sdkey="$2" 1976 2120 if [ -f "$_r_c_f" ]; then 1977 (2121 _sdv="$( 1978 2122 eval "$(grep "^$_sdkey *=" "$_r_c_f")" 1979 2123 eval "printf \"%s\" \"\$$_sdkey\"" 1980 ) 2124 )" 2125 if _startswith "$_sdv" "${B64CONF_START}" && _endswith "$_sdv" "${B64CONF_END}"; then 2126 _sdv="$(echo "$_sdv" | sed "s/${B64CONF_START}//" | sed "s/${B64CONF_END}//" | _dbase64)" 2127 fi 2128 printf "%s" "$_sdv" 1981 2129 else 1982 2130 _debug "config file is empty, can not read $_sdkey" … … 1984 2132 } 1985 2133 1986 #_savedomainconf key value 2134 #_savedomainconf key value base64encode 1987 2135 #save to domain.conf 1988 2136 _savedomainconf() { 1989 _save_conf "$DOMAIN_CONF" "$ 1" "$2"2137 _save_conf "$DOMAIN_CONF" "$@" 1990 2138 } 1991 2139 … … 2000 2148 } 2001 2149 2002 #_saveaccountconf key value 2150 #key value base64encode 2151 _savedeployconf() { 2152 _savedomainconf "SAVED_$1" "$2" "$3" 2153 #remove later 2154 _cleardomainconf "$1" 2155 } 2156 2157 #key 2158 _getdeployconf() { 2159 _rac_key="$1" 2160 _rac_value="$(eval echo \$"$_rac_key")" 2161 if [ "$_rac_value" ]; then 2162 if _startswith "$_rac_value" '"' && _endswith "$_rac_value" '"'; then 2163 _debug2 "trim quotation marks" 2164 eval "export $_rac_key=$_rac_value" 2165 fi 2166 return 0 # do nothing 2167 fi 2168 _saved=$(_readdomainconf "SAVED_$_rac_key") 2169 eval "export $_rac_key=\"$_saved\"" 2170 } 2171 2172 #_saveaccountconf key value base64encode 2003 2173 _saveaccountconf() { 2004 _save_conf "$ACCOUNT_CONF_PATH" "$ 1" "$2"2005 } 2006 2007 #key value 2174 _save_conf "$ACCOUNT_CONF_PATH" "$@" 2175 } 2176 2177 #key value base64encode 2008 2178 _saveaccountconf_mutable() { 2009 _save_conf "$ACCOUNT_CONF_PATH" "SAVED_$1" "$2" 2179 _save_conf "$ACCOUNT_CONF_PATH" "SAVED_$1" "$2" "$3" 2010 2180 #remove later 2011 2181 _clearaccountconf "$1" … … 2047 2217 content="$1" 2048 2218 ncaddr="$2" 2219 _debug "content" "$content" 2049 2220 _debug "ncaddr" "$ncaddr" 2050 2221 … … 2073 2244 fi 2074 2245 2246 _content_len="$(printf "%s" "$content" | wc -c)" 2247 _debug _content_len "$_content_len" 2075 2248 _debug "_NC" "$_NC $SOCAT_OPTIONS" 2076 $_NC $SOCAT_OPTIONS SYSTEM:"sleep 1; echo HTTP/1.0 200 OK; echo ; echo $content; echo;" & 2249 $_NC $SOCAT_OPTIONS SYSTEM:"sleep 1; \ 2250 echo 'HTTP/1.0 200 OK'; \ 2251 echo 'Content-Length\: $_content_len'; \ 2252 echo ''; \ 2253 printf -- '$content';" & 2077 2254 serverproc="$!" 2078 2255 } … … 2106 2283 } 2107 2284 2108 # _starttlsserver san_a san_b port content _ncaddr 2285 # _starttlsserver san_a san_b port content _ncaddr acmeValidationv1 2109 2286 _starttlsserver() { 2110 2287 _info "Starting tls server." … … 2114 2291 content="$4" 2115 2292 opaddr="$5" 2293 acmeValidationv1="$6" 2116 2294 2117 2295 _debug san_a "$san_a" 2118 2296 _debug san_b "$san_b" 2119 2297 _debug port "$port" 2298 _debug acmeValidationv1 "$acmeValidationv1" 2120 2299 2121 2300 #create key TLS_KEY … … 2130 2309 alt="$alt,$san_b" 2131 2310 fi 2132 if ! _createcsr "tls.acme.sh" "$alt" "$TLS_KEY" "$TLS_CSR" "$TLS_CONF" ; then2311 if ! _createcsr "tls.acme.sh" "$alt" "$TLS_KEY" "$TLS_CSR" "$TLS_CONF" "$acmeValidationv1"; then 2133 2312 _err "Create tls validation csr error." 2134 2313 return 1 … … 2154 2333 elif [ "$Le_Listen_V6" ]; then 2155 2334 __S_OPENSSL="$__S_OPENSSL -6" 2335 fi 2336 2337 if [ "$acmeValidationv1" ]; then 2338 __S_OPENSSL="$__S_OPENSSL -alpn acme-tls/1" 2156 2339 fi 2157 2340 … … 2233 2416 ACCOUNT_CONF_PATH="$_DEFAULT_ACCOUNT_CONF_PATH" 2234 2417 fi 2235 2418 _debug3 ACCOUNT_CONF_PATH "$ACCOUNT_CONF_PATH" 2236 2419 DEFAULT_LOG_FILE="$LE_CONFIG_HOME/$PROJECT_NAME.log" 2237 2420 … … 2337 2520 fi 2338 2521 2339 if [ "$ IN_CRON" ]; then2522 if [ "$ACME_IN_CRON" ]; then 2340 2523 if [ ! "$_USER_PATH_EXPORTED" ]; then 2341 2524 _USER_PATH_EXPORTED=1 … … 2684 2867 NGINX_CONF="$(echo "$NGINX_CONF" | cut -d = -f 2)" 2685 2868 _debug NGINX_CONF "$NGINX_CONF" 2869 if [ -z "$NGINX_CONF" ]; then 2870 _err "Can not find nginx conf." 2871 NGINX_CONF="" 2872 return 1 2873 fi 2686 2874 if [ ! -f "$NGINX_CONF" ]; then 2687 2875 _err "'$NGINX_CONF' doesn't exist." … … 2844 3032 for _listen_i in $(echo "$_seg_n" | tr "\t" ' ' | grep "^ *listen" | tr -d " "); do 2845 3033 if [ "$_listen_i" ]; then 2846 if [ "$(echo "$_listen_i" | _egrep_o "listen.*ssl [ |;]")" ]; then3034 if [ "$(echo "$_listen_i" | _egrep_o "listen.*ssl")" ]; then 2847 3035 _debug2 "$_listen_i is ssl" 2848 3036 else … … 2910 3098 _clearupdns() { 2911 3099 _debug "_clearupdns" 2912 if [ "$dnsadded" != 1 ] || [ -z "$vlist" ]; then 3100 _debug "dns_entries" "$dns_entries" 3101 3102 if [ -z "$dns_entries" ]; then 2913 3103 _debug "skip dns." 2914 3104 return 2915 3105 fi 2916 3106 _info "Removing DNS records." 2917 ventries=$(echo "$vlist" | tr ',' ' ') 2918 _alias_index=1 2919 for ventry in $ventries; do 2920 d=$(echo "$ventry" | cut -d "$sep" -f 1) 2921 keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2) 2922 vtype=$(echo "$ventry" | cut -d "$sep" -f 4) 2923 _currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5) 2924 txt="$(printf "%s" "$keyauthorization" | _digest "sha256" | _url_replace)" 2925 _debug txt "$txt" 2926 if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then 2927 _debug "$d is already verified, skip $vtype." 2928 continue 2929 fi 2930 2931 if [ "$vtype" != "$VTYPE_DNS" ]; then 2932 _debug "Skip $d for $vtype" 2933 continue 2934 fi 2935 2936 d_api="$(_findHook "$d" dnsapi "$_currentRoot")" 2937 _debug d_api "$d_api" 3107 3108 for entry in $dns_entries; do 3109 d=$(_getfield "$entry" 1) 3110 txtdomain=$(_getfield "$entry" 2) 3111 aliasDomain=$(_getfield "$entry" 3) 3112 _currentRoot=$(_getfield "$entry" 4) 3113 txt=$(_getfield "$entry" 5) 3114 d_api=$(_getfield "$entry" 6) 3115 _debug "d" "$d" 3116 _debug "txtdomain" "$txtdomain" 3117 _debug "aliasDomain" "$aliasDomain" 3118 _debug "_currentRoot" "$_currentRoot" 3119 _debug "txt" "$txt" 3120 _debug "d_api" "$d_api" 3121 if [ "$d_api" = "$txt" ]; then 3122 d_api="" 3123 fi 2938 3124 2939 3125 if [ -z "$d_api" ]; then 2940 3126 _info "Not Found domain api file: $d_api" 2941 3127 continue 3128 fi 3129 3130 if [ "$aliasDomain" ]; then 3131 txtdomain="$aliasDomain" 2942 3132 fi 2943 3133 … … 2953 3143 return 1 2954 3144 fi 2955 2956 _dns_root_d="$d" 2957 if _startswith "$_dns_root_d" "*."; then 2958 _dns_root_d="$(echo "$_dns_root_d" | sed 's/*.//')" 2959 fi 2960 2961 _d_alias="$(_getfield "$_challenge_alias" "$_alias_index")" 2962 _alias_index="$(_math "$_alias_index" + 1)" 2963 _debug "_d_alias" "$_d_alias" 2964 if [ "$_d_alias" ]; then 2965 if _startswith "$_d_alias" "$DNS_ALIAS_PREFIX"; then 2966 txtdomain="$(echo "$_d_alias" | sed "s/$DNS_ALIAS_PREFIX//")" 2967 else 2968 txtdomain="_acme-challenge.$_d_alias" 2969 fi 2970 else 2971 txtdomain="_acme-challenge.$_dns_root_d" 2972 fi 2973 3145 _info "Removing txt: $txt for domain: $txtdomain" 2974 3146 if ! $rmcommand "$txtdomain" "$txt"; then 2975 3147 _err "Error removing txt for domain:$txtdomain" 2976 3148 return 1 2977 3149 fi 3150 _info "Removed: Success" 2978 3151 ) 2979 3152 … … 3061 3234 if [ -z "$Le_HTTPPort" ]; then 3062 3235 Le_HTTPPort=80 3236 _cleardomainconf "Le_HTTPPort" 3063 3237 else 3064 3238 _savedomainconf "Le_HTTPPort" "$Le_HTTPPort" 3065 3239 fi 3066 3240 _checkport="$Le_HTTPPort" 3067 elif [ "$_currentRoot" = "$W_ TLS" ]; then3068 _info "Standalone tlsmode."3241 elif [ "$_currentRoot" = "$W_ALPN" ]; then 3242 _info "Standalone alpn mode." 3069 3243 if [ -z "$Le_TLSPort" ]; then 3070 3244 Le_TLSPort=443 … … 3161 3335 _chk_renew_hook="$2" 3162 3336 _debug _on_issue_success 3337 3163 3338 #run the post hook 3164 3339 if [ "$_chk_post_hook" ]; then 3165 3340 _info "Run post hook:'$_chk_post_hook'" 3166 3341 if ! ( 3342 export CERT_PATH 3343 export CERT_KEY_PATH 3344 export CA_CERT_PATH 3345 export CERT_FULLCHAIN_PATH 3346 export Le_Domain="$_main_domain" 3167 3347 cd "$DOMAIN_PATH" && eval "$_chk_post_hook" 3168 3348 ); then … … 3176 3356 _info "Run renew hook:'$_chk_renew_hook'" 3177 3357 if ! ( 3358 export CERT_PATH 3359 export CERT_KEY_PATH 3360 export CA_CERT_PATH 3361 export CERT_FULLCHAIN_PATH 3362 export Le_Domain="$_main_domain" 3178 3363 cd "$DOMAIN_PATH" && eval "$_chk_renew_hook" 3179 3364 ); then … … 3183 3368 fi 3184 3369 3185 if _hasfield "$Le_Webroot" "$W_DNS" ; then3370 if _hasfield "$Le_Webroot" "$W_DNS" && [ -z "$FORCE_DNS_MANUAL" ]; then 3186 3371 _err "$_DNS_MANUAL_WARN" 3187 3372 fi 3188 3373 3189 }3190 3191 updateaccount() {3192 _initpath3193 _regAccount3194 3374 } 3195 3375 … … 3268 3448 3269 3449 _debug2 responseHeaders "$responseHeaders" 3270 _accUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ' ' -f 2 | tr -d "\r\n")"3450 _accUri="$(echo "$responseHeaders" | grep -i "^Location:" | _head_n 1 | cut -d ':' -f 2- | tr -d "\r\n ")" 3271 3451 _debug "_accUri" "$_accUri" 3272 3452 if [ -z "$_accUri" ]; then … … 3289 3469 ACCOUNT_THUMBPRINT="$(__calc_account_thumbprint)" 3290 3470 _info "ACCOUNT_THUMBPRINT" "$ACCOUNT_THUMBPRINT" 3471 } 3472 3473 #implement updateaccount 3474 updateaccount() { 3475 _initpath 3476 3477 if [ ! -f "$ACCOUNT_KEY_PATH" ] && [ -f "$_OLD_ACCOUNT_KEY" ]; then 3478 _info "mv $_OLD_ACCOUNT_KEY to $ACCOUNT_KEY_PATH" 3479 mv "$_OLD_ACCOUNT_KEY" "$ACCOUNT_KEY_PATH" 3480 fi 3481 3482 if [ ! -f "$ACCOUNT_JSON_PATH" ] && [ -f "$_OLD_ACCOUNT_JSON" ]; then 3483 _info "mv $_OLD_ACCOUNT_JSON to $ACCOUNT_JSON_PATH" 3484 mv "$_OLD_ACCOUNT_JSON" "$ACCOUNT_JSON_PATH" 3485 fi 3486 3487 if [ ! -f "$ACCOUNT_KEY_PATH" ]; then 3488 _err "Account key is not found at: $ACCOUNT_KEY_PATH" 3489 return 1 3490 fi 3491 3492 _accUri=$(_readcaconf "ACCOUNT_URL") 3493 _debug _accUri "$_accUri" 3494 3495 if [ -z "$_accUri" ]; then 3496 _err "The account url is empty, please run '--update-account' first to update the account info first," 3497 _err "Then try again." 3498 return 1 3499 fi 3500 3501 if ! _calcjwk "$ACCOUNT_KEY_PATH"; then 3502 return 1 3503 fi 3504 _initAPI 3505 3506 if [ "$ACME_VERSION" = "2" ]; then 3507 if [ "$ACCOUNT_EMAIL" ]; then 3508 updjson='{"contact": ["mailto: '$ACCOUNT_EMAIL'"]}' 3509 fi 3510 else 3511 # ACMEv1: Updates happen the same way a registration is done. 3512 # https://tools.ietf.org/html/draft-ietf-acme-acme-01#section-6.3 3513 _regAccount 3514 return 3515 fi 3516 3517 # this part handles ACMEv2 account updates. 3518 _send_signed_request "$_accUri" "$updjson" 3519 3520 if [ "$code" = '200' ]; then 3521 _info "account update success for $_accUri." 3522 else 3523 _info "Error. The account was not updated." 3524 return 1 3525 fi 3291 3526 } 3292 3527 … … 3368 3603 elif [ -f "$_SCRIPT_HOME/$_hookcat/$_hookname.sh" ]; then 3369 3604 d_api="$_SCRIPT_HOME/$_hookcat/$_hookname.sh" 3370 elif [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname" ]; then3605 elif [ "$_hookdomain" ] && [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname" ]; then 3371 3606 d_api="$LE_WORKING_DIR/$_hookdomain/$_hookname" 3372 elif [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname.sh" ]; then3607 elif [ "$_hookdomain" ] && [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname.sh" ]; then 3373 3608 d_api="$LE_WORKING_DIR/$_hookdomain/$_hookname.sh" 3374 3609 elif [ -f "$LE_WORKING_DIR/$_hookname" ]; then … … 3426 3661 #uri keyAuthorization 3427 3662 __trigger_validation() { 3428 _debug2 " tigger domain validation."3663 _debug2 "Trigger domain validation." 3429 3664 _t_url="$1" 3430 3665 _debug2 _t_url "$_t_url" 3431 3666 _t_key_authz="$2" 3432 3667 _debug2 _t_key_authz "$_t_key_authz" 3668 _t_vtype="$3" 3669 _debug2 _t_vtype "$_t_vtype" 3433 3670 if [ "$ACME_VERSION" = "2" ]; then 3434 _send_signed_request "$_t_url" "{\"keyAuthorization\": \"$_t_key_authz\"}" 3435 else 3436 _send_signed_request "$_t_url" "{\"resource\": \"challenge\", \"keyAuthorization\": \"$_t_key_authz\"}" 3437 fi 3671 _send_signed_request "$_t_url" "{}" 3672 else 3673 _send_signed_request "$_t_url" "{\"resource\": \"challenge\", \"type\": \"$_t_vtype\", \"keyAuthorization\": \"$_t_key_authz\"}" 3674 fi 3675 } 3676 3677 #endpoint domain type 3678 _ns_lookup_impl() { 3679 _ns_ep="$1" 3680 _ns_domain="$2" 3681 _ns_type="$3" 3682 _debug2 "_ns_ep" "$_ns_ep" 3683 _debug2 "_ns_domain" "$_ns_domain" 3684 _debug2 "_ns_type" "$_ns_type" 3685 3686 response="$(_H1="accept: application/dns-json" _get "$_ns_ep?name=$_ns_domain&type=$_ns_type")" 3687 _ret=$? 3688 _debug2 "response" "$response" 3689 if [ "$_ret" != "0" ]; then 3690 return $_ret 3691 fi 3692 _answers="$(echo "$response" | tr '{}' '<>' | _egrep_o '"Answer":\[[^]]*]' | tr '<>' '\n\n')" 3693 _debug2 "_answers" "$_answers" 3694 echo "$_answers" 3695 } 3696 3697 #domain, type 3698 _ns_lookup_cf() { 3699 _cf_ld="$1" 3700 _cf_ld_type="$2" 3701 _cf_ep="https://cloudflare-dns.com/dns-query" 3702 _ns_lookup_impl "$_cf_ep" "$_cf_ld" "$_cf_ld_type" 3703 } 3704 3705 #domain, type 3706 _ns_purge_cf() { 3707 _cf_d="$1" 3708 _cf_d_type="$2" 3709 _debug "Cloudflare purge $_cf_d_type record for domain $_cf_d" 3710 _cf_purl="https://cloudflare-dns.com/api/v1/purge?domain=$_cf_d&type=$_cf_d_type" 3711 response="$(_post "" "$_cf_purl")" 3712 _debug2 response "$response" 3713 } 3714 3715 #checks if cf server is available 3716 _ns_is_available_cf() { 3717 if _get "https://cloudflare-dns.com" >/dev/null 2>&1; then 3718 return 0 3719 else 3720 return 1 3721 fi 3722 } 3723 3724 #domain, type 3725 _ns_lookup_google() { 3726 _cf_ld="$1" 3727 _cf_ld_type="$2" 3728 _cf_ep="https://dns.google/resolve" 3729 _ns_lookup_impl "$_cf_ep" "$_cf_ld" "$_cf_ld_type" 3730 } 3731 3732 #domain, type 3733 _ns_lookup() { 3734 if [ -z "$DOH_USE" ]; then 3735 _debug "Detect dns server first." 3736 if _ns_is_available_cf; then 3737 _debug "Use cloudflare doh server" 3738 export DOH_USE=$DOH_CLOUDFLARE 3739 else 3740 _debug "Use google doh server" 3741 export DOH_USE=$DOH_GOOGLE 3742 fi 3743 fi 3744 3745 if [ "$DOH_USE" = "$DOH_CLOUDFLARE" ] || [ -z "$DOH_USE" ]; then 3746 _ns_lookup_cf "$@" 3747 else 3748 _ns_lookup_google "$@" 3749 fi 3750 3751 } 3752 3753 #txtdomain, alias, txt 3754 __check_txt() { 3755 _c_txtdomain="$1" 3756 _c_aliasdomain="$2" 3757 _c_txt="$3" 3758 _debug "_c_txtdomain" "$_c_txtdomain" 3759 _debug "_c_aliasdomain" "$_c_aliasdomain" 3760 _debug "_c_txt" "$_c_txt" 3761 _answers="$(_ns_lookup "$_c_aliasdomain" TXT)" 3762 _contains "$_answers" "$_c_txt" 3763 3764 } 3765 3766 #txtdomain 3767 __purge_txt() { 3768 _p_txtdomain="$1" 3769 _debug _p_txtdomain "$_p_txtdomain" 3770 if [ "$DOH_USE" = "$DOH_CLOUDFLARE" ] || [ -z "$DOH_USE" ]; then 3771 _ns_purge_cf "$_p_txtdomain" "TXT" 3772 else 3773 _debug "no purge api for google dns api, just sleep 5 secs" 3774 _sleep 5 3775 fi 3776 3777 } 3778 3779 #wait and check each dns entries 3780 _check_dns_entries() { 3781 _success_txt="," 3782 _end_time="$(_time)" 3783 _end_time="$(_math "$_end_time" + 1200)" #let's check no more than 20 minutes. 3784 3785 while [ "$(_time)" -le "$_end_time" ]; do 3786 _left="" 3787 for entry in $dns_entries; do 3788 d=$(_getfield "$entry" 1) 3789 txtdomain=$(_getfield "$entry" 2) 3790 txtdomain=$(_idn "$txtdomain") 3791 aliasDomain=$(_getfield "$entry" 3) 3792 aliasDomain=$(_idn "$aliasDomain") 3793 txt=$(_getfield "$entry" 5) 3794 d_api=$(_getfield "$entry" 6) 3795 _debug "d" "$d" 3796 _debug "txtdomain" "$txtdomain" 3797 _debug "aliasDomain" "$aliasDomain" 3798 _debug "txt" "$txt" 3799 _debug "d_api" "$d_api" 3800 _info "Checking $d for $aliasDomain" 3801 if _contains "$_success_txt" ",$txt,"; then 3802 _info "Already success, continue next one." 3803 continue 3804 fi 3805 3806 if __check_txt "$txtdomain" "$aliasDomain" "$txt"; then 3807 _info "Domain $d '$aliasDomain' success." 3808 _success_txt="$_success_txt,$txt," 3809 continue 3810 fi 3811 _left=1 3812 _info "Not valid yet, let's wait 10 seconds and check next one." 3813 __purge_txt "$txtdomain" 3814 if [ "$txtdomain" != "$aliasDomain" ]; then 3815 __purge_txt "$aliasDomain" 3816 fi 3817 _sleep 10 3818 done 3819 if [ "$_left" ]; then 3820 _info "Let's wait 10 seconds and check again". 3821 _sleep 10 3822 else 3823 _info "All success, let's return" 3824 return 0 3825 fi 3826 done 3827 _info "Timed out waiting for DNS." 3828 return 1 3829 3438 3830 } 3439 3831 … … 3518 3910 _savedomainconf "Le_Webroot" "$_web_roots" 3519 3911 3520 _savedomainconf "Le_PreHook" "$_pre_hook" 3521 _savedomainconf "Le_PostHook" "$_post_hook" 3522 _savedomainconf "Le_RenewHook" "$_renew_hook" 3912 _savedomainconf "Le_PreHook" "$_pre_hook" "base64" 3913 _savedomainconf "Le_PostHook" "$_post_hook" "base64" 3914 _savedomainconf "Le_RenewHook" "$_renew_hook" "base64" 3523 3915 3524 3916 if [ "$_local_addr" ]; then … … 3533 3925 fi 3534 3926 3535 Le_API="$ACME_DIRECTORY" 3536 _savedomainconf "Le_API" "$Le_API" 3927 if [ "$ACME_DIRECTORY" != "$DEFAULT_CA" ]; then 3928 Le_API="$ACME_DIRECTORY" 3929 _savedomainconf "Le_API" "$Le_API" 3930 else 3931 _cleardomainconf Le_API 3932 fi 3537 3933 3538 3934 if [ "$_alt_domains" = "$NO_VALUE" ]; then … … 3586 3982 3587 3983 vlist="$Le_Vlist" 3588 3984 _cleardomainconf "Le_Vlist" 3589 3985 _info "Getting domain auth token for each domain" 3590 3986 sep='#' … … 3593 3989 if [ "$ACME_VERSION" = "2" ]; then 3594 3990 #make new order request 3595 _identifiers="{\"type\":\"dns\",\"value\":\"$ _main_domain\"}"3991 _identifiers="{\"type\":\"dns\",\"value\":\"$(_idn "$_main_domain")\"}" 3596 3992 _w_index=1 3597 3993 while true; do … … 3602 3998 break 3603 3999 fi 3604 _identifiers="$_identifiers,{\"type\":\"dns\",\"value\":\"$ d\"}"4000 _identifiers="$_identifiers,{\"type\":\"dns\",\"value\":\"$(_idn "$d")\"}" 3605 4001 done 3606 4002 _debug2 _identifiers "$_identifiers" … … 3611 4007 return 1 3612 4008 fi 3613 3614 Le_OrderFinalize="$(echo "$response" | tr -d '\r\n' | _egrep_o '"finalize" *: *"[^"]*"' | cut -d '"' -f 4)" 4009 Le_LinkOrder="$(echo "$responseHeaders" | grep -i '^Location.*$' | _tail_n 1 | tr -d "\r\n " | cut -d ":" -f 2-)" 4010 _debug Le_LinkOrder "$Le_LinkOrder" 4011 Le_OrderFinalize="$(echo "$response" | _egrep_o '"finalize" *: *"[^"]*"' | cut -d '"' -f 4)" 3615 4012 _debug Le_OrderFinalize "$Le_OrderFinalize" 3616 4013 if [ -z "$Le_OrderFinalize" ]; then … … 3624 4021 _savedomainconf "Le_OrderFinalize" "$Le_OrderFinalize" 3625 4022 3626 _authorizations_seg="$(echo "$response" | tr -d '\r\n' |_egrep_o '"authorizations" *: *\[[^\]*\]' | cut -d '[' -f 2 | tr -d ']' | tr -d '"')"4023 _authorizations_seg="$(echo "$response" | _egrep_o '"authorizations" *: *\[[^\]*\]' | cut -d '[' -f 2 | tr -d ']' | tr -d '"')" 3627 4024 _debug2 _authorizations_seg "$_authorizations_seg" 3628 4025 if [ -z "$_authorizations_seg" ]; then … … 3637 4034 for _authz_url in $(echo "$_authorizations_seg" | tr ',' ' '); do 3638 4035 _debug2 "_authz_url" "$_authz_url" 3639 if ! response="$(_get "$_authz_url")"; then4036 if ! _send_signed_request "$_authz_url"; then 3640 4037 _err "get to authz error." 3641 4038 _err "_authorizations_seg" "$_authorizations_seg" … … 3684 4081 fi 3685 4082 3686 if [ "$_currentRoot" = "$W_TLS" ]; then 3687 if [ "$ACME_VERSION" = "2" ]; then 3688 vtype="$VTYPE_TLS2" 3689 else 3690 vtype="$VTYPE_TLS" 3691 fi 4083 if [ "$_currentRoot" = "$W_ALPN" ]; then 4084 vtype="$VTYPE_ALPN" 3692 4085 fi 3693 4086 3694 4087 if [ "$ACME_VERSION" = "2" ]; then 3695 response="$(echo "$_authorizations_map" | grep "^$d," | sed "s/$d,//")" 4088 _idn_d="$(_idn "$d")" 4089 _candindates="$(echo "$_authorizations_map" | grep -i "^$_idn_d,")" 4090 _debug2 _candindates "$_candindates" 4091 if [ "$(echo "$_candindates" | wc -l)" -gt 1 ]; then 4092 for _can in $_candindates; do 4093 if _startswith "$(echo "$_can" | tr '.' '|')" "$(echo "$_idn_d" | tr '.' '|'),"; then 4094 _candindates="$_can" 4095 break 4096 fi 4097 done 4098 fi 4099 response="$(echo "$_candindates" | sed "s/$_idn_d,//")" 3696 4100 _debug2 "response" "$response" 3697 4101 if [ -z "$response" ]; then … … 3714 4118 fi 3715 4119 3716 entry="$( printf "%s\n""$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"4120 entry="$(echo "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')" 3717 4121 _debug entry "$entry" 4122 keyauthorization="" 3718 4123 if [ -z "$entry" ]; then 3719 _err "Error, can not get domain token entry $d" 3720 _supported_vtypes="$(echo "$response" | _egrep_o "\"challenges\":\[[^]]*]" | tr '{' "\n" | grep type | cut -d '"' -f 4 | tr "\n" ' ')" 3721 if [ "$_supported_vtypes" ]; then 3722 _err "The supported validation types are: $_supported_vtypes, but you specified: $vtype" 3723 fi 3724 _clearup 3725 _on_issue_err "$_post_hook" 3726 return 1 3727 fi 3728 token="$(printf "%s\n" "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')" 3729 _debug token "$token" 3730 3731 if [ -z "$token" ]; then 3732 _err "Error, can not get domain token $entry" 3733 _clearup 3734 _on_issue_err "$_post_hook" 3735 return 1 3736 fi 3737 if [ "$ACME_VERSION" = "2" ]; then 3738 uri="$(printf "%s\n" "$entry" | _egrep_o '"url":"[^"]*' | cut -d '"' -f 4 | _head_n 1)" 3739 else 3740 uri="$(printf "%s\n" "$entry" | _egrep_o '"uri":"[^"]*' | cut -d '"' -f 4)" 3741 fi 3742 _debug uri "$uri" 3743 3744 if [ -z "$uri" ]; then 3745 _err "Error, can not get domain uri. $entry" 3746 _clearup 3747 _on_issue_err "$_post_hook" 3748 return 1 3749 fi 3750 keyauthorization="$token.$thumbprint" 3751 _debug keyauthorization "$keyauthorization" 3752 3753 if printf "%s" "$response" | grep '"status":"valid"' >/dev/null 2>&1; then 3754 _debug "$d is already verified." 3755 keyauthorization="$STATE_VERIFIED" 4124 if ! _startswith "$d" '*.'; then 4125 _debug "Not a wildcard domain, lets check whether the validation is already valid." 4126 if echo "$response" | grep '"status":"valid"' >/dev/null 2>&1; then 4127 _debug "$d is already valid." 4128 keyauthorization="$STATE_VERIFIED" 4129 _debug keyauthorization "$keyauthorization" 4130 fi 4131 fi 4132 if [ -z "$keyauthorization" ]; then 4133 _err "Error, can not get domain token entry $d for $vtype" 4134 _supported_vtypes="$(echo "$response" | _egrep_o "\"challenges\":\[[^]]*]" | tr '{' "\n" | grep type | cut -d '"' -f 4 | tr "\n" ' ')" 4135 if [ "$_supported_vtypes" ]; then 4136 _err "The supported validation types are: $_supported_vtypes, but you specified: $vtype" 4137 fi 4138 _clearup 4139 _on_issue_err "$_post_hook" 4140 return 1 4141 fi 4142 fi 4143 4144 if [ -z "$keyauthorization" ]; then 4145 token="$(echo "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')" 4146 _debug token "$token" 4147 4148 if [ -z "$token" ]; then 4149 _err "Error, can not get domain token $entry" 4150 _clearup 4151 _on_issue_err "$_post_hook" 4152 return 1 4153 fi 4154 if [ "$ACME_VERSION" = "2" ]; then 4155 uri="$(echo "$entry" | _egrep_o '"url":"[^"]*' | cut -d '"' -f 4 | _head_n 1)" 4156 else 4157 uri="$(echo "$entry" | _egrep_o '"uri":"[^"]*' | cut -d '"' -f 4)" 4158 fi 4159 _debug uri "$uri" 4160 4161 if [ -z "$uri" ]; then 4162 _err "Error, can not get domain uri. $entry" 4163 _clearup 4164 _on_issue_err "$_post_hook" 4165 return 1 4166 fi 4167 keyauthorization="$token.$thumbprint" 3756 4168 _debug keyauthorization "$keyauthorization" 4169 4170 if printf "%s" "$response" | grep '"status":"valid"' >/dev/null 2>&1; then 4171 _debug "$d is already verified." 4172 keyauthorization="$STATE_VERIFIED" 4173 _debug keyauthorization "$keyauthorization" 4174 fi 3757 4175 fi 3758 4176 … … 3765 4183 _debug vlist "$vlist" 3766 4184 #add entry 4185 dns_entries="" 3767 4186 dnsadded="" 3768 4187 ventries=$(echo "$vlist" | tr "$dvsep" ' ') … … 3776 4195 if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then 3777 4196 _debug "$d is already verified, skip $vtype." 4197 _alias_index="$(_math "$_alias_index" + 1)" 3778 4198 continue 3779 4199 fi … … 3794 4214 txtdomain="_acme-challenge.$_d_alias" 3795 4215 fi 4216 dns_entry="${_dns_root_d}${dvsep}_acme-challenge.$_dns_root_d$dvsep$txtdomain$dvsep$_currentRoot" 3796 4217 else 3797 4218 txtdomain="_acme-challenge.$_dns_root_d" 3798 fi 4219 dns_entry="${_dns_root_d}${dvsep}_acme-challenge.$_dns_root_d$dvsep$dvsep$_currentRoot" 4220 fi 4221 3799 4222 _debug txtdomain "$txtdomain" 3800 4223 txt="$(printf "%s" "$keyauthorization" | _digest "sha256" | _url_replace)" 3801 4224 _debug txt "$txt" 3802 4225 3803 d_api="$(_findHook "$_dns_root_d" dnsapi "$_currentRoot")" 3804 4226 d_api="$(_findHook "$_dns_root_d" $_SUB_FOLDER_DNSAPI "$_currentRoot")" 3805 4227 _debug d_api "$d_api" 3806 4228 4229 dns_entry="$dns_entry$dvsep$txt${dvsep}$d_api" 4230 _debug2 dns_entry "$dns_entry" 3807 4231 if [ "$d_api" ]; then 3808 _ info"Found domain api file: $d_api"4232 _debug "Found domain api file: $d_api" 3809 4233 else 3810 4234 if [ "$_currentRoot" != "$W_DNS" ]; then … … 3831 4255 return 1 3832 4256 fi 3833 4257 _info "Adding txt value: $txt for domain: $txtdomain" 3834 4258 if ! $addcommand "$txtdomain" "$txt"; then 3835 4259 _err "Error add txt for domain:$txtdomain" 3836 4260 return 1 3837 4261 fi 4262 _info "The txt record is added: Success." 3838 4263 ) 3839 4264 3840 4265 if [ "$?" != "0" ]; then 4266 _on_issue_err "$_post_hook" "$vlist" 3841 4267 _clearup 3842 _on_issue_err "$_post_hook" "$vlist"3843 4268 return 1 3844 4269 fi 4270 dns_entries="$dns_entries$dns_entry 4271 " 4272 _debug2 "$dns_entries" 3845 4273 dnsadded='1' 3846 4274 fi … … 3851 4279 _debug "Dns record not added yet, so, save to $DOMAIN_CONF and exit." 3852 4280 _err "Please add the TXT records to the domains, and re-run with --renew." 4281 _on_issue_err "$_post_hook" 3853 4282 _clearup 3854 _on_issue_err "$_post_hook"3855 4283 return 1 3856 4284 fi … … 3858 4286 fi 3859 4287 3860 if [ "$dns added" = '1']; then4288 if [ "$dns_entries" ]; then 3861 4289 if [ -z "$Le_DNSSleep" ]; then 3862 Le_DNSSleep="$DEFAULT_DNS_SLEEP" 4290 _info "Let's check each dns records now. Sleep 20 seconds first." 4291 _sleep 20 4292 if ! _check_dns_entries; then 4293 _err "check dns error." 4294 _on_issue_err "$_post_hook" 4295 _clearup 4296 return 1 4297 fi 3863 4298 else 3864 4299 _savedomainconf "Le_DNSSleep" "$Le_DNSSleep" 3865 fi 3866 3867 _info "Sleep $(__green $Le_DNSSleep) seconds for the txt records to take effect" 3868 _sleep "$Le_DNSSleep" 4300 _info "Sleep $(__green $Le_DNSSleep) seconds for the txt records to take effect" 4301 _sleep "$Le_DNSSleep" 4302 fi 3869 4303 fi 3870 4304 … … 3886 4320 fi 3887 4321 3888 _info "Verifying: $d"4322 _info "Verifying: $d" 3889 4323 _debug "d" "$d" 3890 4324 _debug "keyauthorization" "$keyauthorization" … … 3970 4404 3971 4405 fi 3972 3973 elif [ "$vtype" = "$VTYPE_TLS" ]; then 3974 #create A 3975 #_hash_A="$(printf "%s" $token | _digest "sha256" "hex" )" 3976 #_debug2 _hash_A "$_hash_A" 3977 #_x="$(echo $_hash_A | cut -c 1-32)" 3978 #_debug2 _x "$_x" 3979 #_y="$(echo $_hash_A | cut -c 33-64)" 3980 #_debug2 _y "$_y" 3981 #_SAN_A="$_x.$_y.token.acme.invalid" 3982 #_debug2 _SAN_A "$_SAN_A" 3983 3984 #create B 3985 _hash_B="$(printf "%s" "$keyauthorization" | _digest "sha256" "hex")" 3986 _debug2 _hash_B "$_hash_B" 3987 _x="$(echo "$_hash_B" | cut -c 1-32)" 3988 _debug2 _x "$_x" 3989 _y="$(echo "$_hash_B" | cut -c 33-64)" 3990 _debug2 _y "$_y" 3991 3992 #_SAN_B="$_x.$_y.ka.acme.invalid" 3993 3994 _SAN_B="$_x.$_y.acme.invalid" 3995 _debug2 _SAN_B "$_SAN_B" 3996 3997 _ncaddr="$(_getfield "$_local_addr" "$_ncIndex")" 3998 _ncIndex="$(_math "$_ncIndex" + 1)" 3999 if ! _starttlsserver "$_SAN_B" "$_SAN_A" "$Le_TLSPort" "$keyauthorization" "$_ncaddr"; then 4406 elif [ "$vtype" = "$VTYPE_ALPN" ]; then 4407 acmevalidationv1="$(printf "%s" "$keyauthorization" | _digest "sha256" "hex")" 4408 _debug acmevalidationv1 "$acmevalidationv1" 4409 if ! _starttlsserver "$d" "" "$Le_TLSPort" "$keyauthorization" "$_ncaddr" "$acmevalidationv1"; then 4000 4410 _err "Start tls server error." 4001 4411 _clearupwebbroot "$_currentRoot" "$removelevel" "$token" … … 4006 4416 fi 4007 4417 4008 if ! __trigger_validation "$uri" "$keyauthorization" ; then4418 if ! __trigger_validation "$uri" "$keyauthorization" "$vtype"; then 4009 4419 _err "$d:Can not get challenge: $response" 4010 4420 _clearupwebbroot "$_currentRoot" "$removelevel" "$token" … … 4015 4425 4016 4426 if [ "$code" ] && [ "$code" != '202' ]; then 4017 if [ "$ ACME_VERSION" = "2" ] && [ "$code" = '200' ]; then4427 if [ "$code" = '200' ]; then 4018 4428 _debug "trigger validation code: $code" 4019 4429 else … … 4044 4454 sleep 2 4045 4455 _debug "checking" 4046 response="$(_get "$uri")" 4456 if [ "$ACME_VERSION" = "2" ]; then 4457 _send_signed_request "$uri" 4458 else 4459 response="$(_get "$uri")" 4460 fi 4047 4461 if [ "$?" != "0" ]; then 4048 4462 _err "$d:Verify error:$response" … … 4067 4481 4068 4482 if [ "$status" = "invalid" ]; then 4069 error="$(echo "$response" | tr -d "\r\n" |_egrep_o '"error":\{[^\}]*')"4483 error="$(echo "$response" | _egrep_o '"error":\{[^\}]*')" 4070 4484 _debug2 error "$error" 4071 4485 errordetail="$(echo "$error" | _egrep_o '"detail": *"[^"]*' | cut -d '"' -f 4)" … … 4090 4504 if [ "$status" = "pending" ]; then 4091 4505 _info "Pending" 4506 elif [ "$status" = "processing" ]; then 4507 _info "Processing" 4092 4508 else 4093 4509 _err "$d:Verify error:$response" … … 4107 4523 4108 4524 if [ "$ACME_VERSION" = "2" ]; then 4525 _info "Lets finalize the order, Le_OrderFinalize: $Le_OrderFinalize" 4109 4526 if ! _send_signed_request "${Le_OrderFinalize}" "{\"csr\": \"$der\"}"; then 4110 4527 _err "Sign failed." … … 4113 4530 fi 4114 4531 if [ "$code" != "200" ]; then 4115 _err "Sign failed, code is not 200."4532 _err "Sign failed, finalize code is not 200." 4116 4533 _err "$response" 4117 4534 _on_issue_err "$_post_hook" 4118 4535 return 1 4119 4536 fi 4120 Le_LinkCert="$(echo "$response" | tr -d '\r\n' | _egrep_o '"certificate" *: *"[^"]*"' | cut -d '"' -f 4)" 4121 4122 if ! _get "$Le_LinkCert" >"$CERT_PATH"; then 4537 if [ -z "$Le_LinkOrder" ]; then 4538 Le_LinkOrder="$(echo "$responseHeaders" | grep -i '^Location.*$' | _tail_n 1 | tr -d "\r\n" | cut -d ":" -f 2-)" 4539 fi 4540 4541 _savedomainconf "Le_LinkOrder" "$Le_LinkOrder" 4542 4543 _link_cert_retry=0 4544 _MAX_CERT_RETRY=5 4545 while [ "$_link_cert_retry" -lt "$_MAX_CERT_RETRY" ]; do 4546 if _contains "$response" "\"status\":\"valid\""; then 4547 _debug "Order status is valid." 4548 Le_LinkCert="$(echo "$response" | _egrep_o '"certificate" *: *"[^"]*"' | cut -d '"' -f 4)" 4549 _debug Le_LinkCert "$Le_LinkCert" 4550 if [ -z "$Le_LinkCert" ]; then 4551 _err "Sign error, can not find Le_LinkCert" 4552 _err "$response" 4553 _on_issue_err "$_post_hook" 4554 return 1 4555 fi 4556 break 4557 elif _contains "$response" "\"processing\""; then 4558 _info "Order status is processing, lets sleep and retry." 4559 _sleep 2 4560 else 4561 _err "Sign error, wrong status" 4562 _err "$response" 4563 _on_issue_err "$_post_hook" 4564 return 1 4565 fi 4566 #the order is processing, so we are going to poll order status 4567 if [ -z "$Le_LinkOrder" ]; then 4568 _err "Sign error, can not get order link location header" 4569 _err "responseHeaders" "$responseHeaders" 4570 _on_issue_err "$_post_hook" 4571 return 1 4572 fi 4573 _info "Polling order status: $Le_LinkOrder" 4574 if ! _send_signed_request "$Le_LinkOrder"; then 4575 _err "Sign failed, can not post to Le_LinkOrder cert:$Le_LinkOrder." 4576 _err "$response" 4577 _on_issue_err "$_post_hook" 4578 return 1 4579 fi 4580 _link_cert_retry="$(_math $_link_cert_retry + 1)" 4581 done 4582 4583 if [ -z "$Le_LinkCert" ]; then 4584 _err "Sign failed, can not get Le_LinkCert, retry time limit." 4585 _err "$response" 4586 _on_issue_err "$_post_hook" 4587 return 1 4588 fi 4589 _info "Download cert, Le_LinkCert: $Le_LinkCert" 4590 if ! _send_signed_request "$Le_LinkCert"; then 4123 4591 _err "Sign failed, can not download cert:$Le_LinkCert." 4124 4592 _err "$response" … … 4126 4594 return 1 4127 4595 fi 4596 4597 echo "$response" >"$CERT_PATH" 4128 4598 4129 4599 if [ "$(grep -- "$BEGIN_CERT" "$CERT_PATH" | wc -l)" -gt "1" ]; then … … 4136 4606 sed -n "${_end_n},9999p" "$CERT_FULLCHAIN_PATH" >"$CA_CERT_PATH" 4137 4607 fi 4608 4138 4609 else 4139 4610 if ! _send_signed_request "${ACME_NEW_ORDER}" "{\"resource\": \"$ACME_NEW_ORDER_RES\", \"csr\": \"$der\"}" "needbase64"; then … … 4179 4650 fi 4180 4651 4181 if [ ! "$USER_PATH" ] || [ ! "$ IN_CRON" ]; then4652 if [ ! "$USER_PATH" ] || [ ! "$ACME_IN_CRON" ]; then 4182 4653 USER_PATH="$PATH" 4183 4654 _saveaccountconf "USER_PATH" "$USER_PATH" 4184 4655 fi 4185 4656 fi 4186 4187 _cleardomainconf "Le_Vlist"4188 4657 4189 4658 if [ "$ACME_VERSION" = "2" ]; then … … 4206 4675 _debug _link_issuer_retry "$_link_issuer_retry" 4207 4676 if [ "$ACME_VERSION" = "2" ]; then 4208 if _get "$Le_LinkIssuer" >"$CA_CERT_PATH"; then 4677 if _send_signed_request "$Le_LinkIssuer"; then 4678 echo "$response" >"$CA_CERT_PATH" 4209 4679 break 4210 4680 fi … … 4242 4712 _savedomainconf "Le_CertCreateTimeStr" "$Le_CertCreateTimeStr" 4243 4713 4244 if [ -z "$Le_RenewalDays" ] || [ "$Le_RenewalDays" -lt "0" ] || [ "$Le_RenewalDays" -gt "$MAX_RENEW" ]; then4245 Le_RenewalDays="$ MAX_RENEW"4714 if [ -z "$Le_RenewalDays" ] || [ "$Le_RenewalDays" -lt "0" ]; then 4715 Le_RenewalDays="$DEFAULT_RENEW" 4246 4716 else 4247 4717 _savedomainconf "Le_RenewalDays" "$Le_RenewalDays" … … 4292 4762 _savedomainconf "Le_RealCACertPath" "$_real_ca" 4293 4763 _savedomainconf "Le_RealKeyPath" "$_real_key" 4294 _savedomainconf "Le_ReloadCmd" "$_reload_cmd" 4764 _savedomainconf "Le_ReloadCmd" "$_reload_cmd" "base64" 4295 4765 _savedomainconf "Le_RealFullChainPath" "$_real_fullchain" 4296 4766 if ! _installcert "$_main_domain" "$_real_cert" "$_real_key" "$_real_ca" "$_real_fullchain" "$_reload_cmd"; then … … 4320 4790 if [ ! -f "$DOMAIN_CONF" ]; then 4321 4791 _info "'$Le_Domain' is not a issued domain, skip." 4322 return 04792 return $RENEW_SKIP 4323 4793 fi 4324 4794 … … 4329 4799 . "$DOMAIN_CONF" 4330 4800 _debug Le_API "$Le_API" 4801 4802 if [ "$Le_API" = "$LETSENCRYPT_CA_V1" ]; then 4803 _cleardomainconf Le_API 4804 Le_API="$DEFAULT_CA" 4805 fi 4806 if [ "$Le_API" = "$LETSENCRYPT_STAGING_CA_V1" ]; then 4807 _cleardomainconf Le_API 4808 Le_API="$DEFAULT_STAGING_CA" 4809 fi 4810 4331 4811 if [ "$Le_API" ]; then 4332 4812 if [ "$_OLD_CA_HOST" = "$Le_API" ]; then … … 4353 4833 fi 4354 4834 4355 if [ "$ IN_CRON" = "1" ] && [ -z "$Le_CertCreateTime" ]; then4835 if [ "$ACME_IN_CRON" = "1" ] && [ -z "$Le_CertCreateTime" ]; then 4356 4836 _info "Skip invalid cert for: $Le_Domain" 4357 return 04837 return $RENEW_SKIP 4358 4838 fi 4359 4839 4360 4840 IS_RENEW="1" 4841 Le_ReloadCmd="$(_readdomainconf Le_ReloadCmd)" 4842 Le_PreHook="$(_readdomainconf Le_PreHook)" 4843 Le_PostHook="$(_readdomainconf Le_PostHook)" 4844 Le_RenewHook="$(_readdomainconf Le_RenewHook)" 4361 4845 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" "$Le_ChallengeAlias" 4362 4846 res="$?" … … 4381 4865 _debug "_stopRenewOnError" "$_stopRenewOnError" 4382 4866 _ret="0" 4383 4867 _success_msg="" 4868 _error_msg="" 4869 _skipped_msg="" 4870 _error_level=$NOTIFY_LEVEL_SKIP 4871 _notify_code=$RENEW_SKIP 4872 _set_level=${NOTIFY_LEVEL:-$NOTIFY_LEVEL_DEFAULT} 4873 _debug "_set_level" "$_set_level" 4384 4874 for di in "${CERT_HOME}"/*.*/; do 4385 4875 _debug di "$di" … … 4399 4889 rc="$?" 4400 4890 _debug "Return code: $rc" 4401 if [ "$rc" != "0" ]; then 4402 if [ "$rc" = "$RENEW_SKIP" ]; then 4403 _info "Skipped $d" 4404 elif [ "$_stopRenewOnError" ]; then 4891 if [ "$rc" = "0" ]; then 4892 if [ $_error_level -gt $NOTIFY_LEVEL_RENEW ]; then 4893 _error_level="$NOTIFY_LEVEL_RENEW" 4894 _notify_code=0 4895 fi 4896 if [ "$ACME_IN_CRON" ]; then 4897 if [ $_set_level -ge $NOTIFY_LEVEL_RENEW ]; then 4898 if [ "$NOTIFY_MODE" = "$NOTIFY_MODE_CERT" ]; then 4899 _send_notify "Renew $d success" "Good, the cert is renewed." "$NOTIFY_HOOK" 0 4900 fi 4901 fi 4902 fi 4903 _success_msg="${_success_msg} $d 4904 " 4905 elif [ "$rc" = "$RENEW_SKIP" ]; then 4906 if [ $_error_level -gt $NOTIFY_LEVEL_SKIP ]; then 4907 _error_level="$NOTIFY_LEVEL_SKIP" 4908 _notify_code=$RENEW_SKIP 4909 fi 4910 if [ "$ACME_IN_CRON" ]; then 4911 if [ $_set_level -ge $NOTIFY_LEVEL_SKIP ]; then 4912 if [ "$NOTIFY_MODE" = "$NOTIFY_MODE_CERT" ]; then 4913 _send_notify "Renew $d skipped" "Good, the cert is skipped." "$NOTIFY_HOOK" "$RENEW_SKIP" 4914 fi 4915 fi 4916 fi 4917 _info "Skipped $d" 4918 _skipped_msg="${_skipped_msg} $d 4919 " 4920 else 4921 if [ $_error_level -gt $NOTIFY_LEVEL_ERROR ]; then 4922 _error_level="$NOTIFY_LEVEL_ERROR" 4923 _notify_code=1 4924 fi 4925 if [ "$ACME_IN_CRON" ]; then 4926 if [ $_set_level -ge $NOTIFY_LEVEL_ERROR ]; then 4927 if [ "$NOTIFY_MODE" = "$NOTIFY_MODE_CERT" ]; then 4928 _send_notify "Renew $d error" "There is an error." "$NOTIFY_HOOK" 1 4929 fi 4930 fi 4931 fi 4932 _error_msg="${_error_msg} $d 4933 " 4934 if [ "$_stopRenewOnError" ]; then 4405 4935 _err "Error renew $d, stop now." 4406 return "$rc" 4936 _ret="$rc" 4937 break 4407 4938 else 4408 4939 _ret="$rc" … … 4411 4942 fi 4412 4943 done 4944 _debug _error_level "$_error_level" 4945 _debug _set_level "$_set_level" 4946 if [ "$ACME_IN_CRON" ] && [ $_error_level -le $_set_level ]; then 4947 if [ -z "$NOTIFY_MODE" ] || [ "$NOTIFY_MODE" = "$NOTIFY_MODE_BULK" ]; then 4948 _msg_subject="Renew" 4949 if [ "$_error_msg" ]; then 4950 _msg_subject="${_msg_subject} Error" 4951 _msg_data="Error certs: 4952 ${_error_msg} 4953 " 4954 fi 4955 if [ "$_success_msg" ]; then 4956 _msg_subject="${_msg_subject} Success" 4957 _msg_data="${_msg_data}Success certs: 4958 ${_success_msg} 4959 " 4960 fi 4961 if [ "$_skipped_msg" ]; then 4962 _msg_subject="${_msg_subject} Skipped" 4963 _msg_data="${_msg_data}Skipped certs: 4964 ${_skipped_msg} 4965 " 4966 fi 4967 4968 _send_notify "$_msg_subject" "$_msg_data" "$NOTIFY_HOOK" "$_notify_code" 4969 fi 4970 fi 4971 4413 4972 return "$_ret" 4414 4973 } … … 4526 5085 printf "%s\n" "Main_Domain${_sep}KeyLength${_sep}SAN_Domains${_sep}Created${_sep}Renew" 4527 5086 for di in "${CERT_HOME}"/*.*/; do 4528 if ! [ -d "$di" ]; then4529 _debug "Not directory, skip: $di"4530 continue4531 fi4532 5087 d=$(basename "$di") 4533 5088 _debug d "$d" 4534 5089 ( 4535 5090 if _endswith "$d" "$ECC_SUFFIX"; then 4536 _isEcc= $(echo "$d" | cut -d "$ECC_SEP" -f 2)5091 _isEcc="ecc" 4537 5092 d=$(echo "$d" | cut -d "$ECC_SEP" -f 1) 4538 5093 fi 4539 _initpath "$d" "$_isEcc"5094 DOMAIN_CONF="$di/$d.conf" 4540 5095 if [ -f "$DOMAIN_CONF" ]; then 4541 5096 . "$DOMAIN_CONF" … … 4559 5114 4560 5115 for _d_api in $(echo "$_hooks" | tr ',' " "); do 4561 _deployApi="$(_findHook "$_d" deploy"$_d_api")"5116 _deployApi="$(_findHook "$_d" $_SUB_FOLDER_DEPLOY "$_d_api")" 4562 5117 if [ -z "$_deployApi" ]; then 4563 5118 _err "The deploy hook $_d_api is not found." … … 4603 5158 _initpath "$_d" "$_isEcc" 4604 5159 if [ ! -d "$DOMAIN_PATH" ]; then 4605 _err "Domain is not valid:'$_d'" 5160 _err "The domain '$_d' is not a cert name. You must use the cert name to specify the cert to install." 5161 _err "Can not find path:'$DOMAIN_PATH'" 4606 5162 return 1 4607 5163 fi … … 4630 5186 _initpath "$_main_domain" "$_isEcc" 4631 5187 if [ ! -d "$DOMAIN_PATH" ]; then 4632 _err "Domain is not valid:'$_main_domain'" 5188 _err "The domain '$_main_domain' is not a cert name. You must use the cert name to specify the cert to install." 5189 _err "Can not find path:'$DOMAIN_PATH'" 4633 5190 return 1 4634 5191 fi … … 4637 5194 _savedomainconf "Le_RealCACertPath" "$_real_ca" 4638 5195 _savedomainconf "Le_RealKeyPath" "$_real_key" 4639 _savedomainconf "Le_ReloadCmd" "$_reload_cmd" 5196 _savedomainconf "Le_ReloadCmd" "$_reload_cmd" "base64" 4640 5197 _savedomainconf "Le_RealFullChainPath" "$_real_fullchain" 4641 5198 … … 4721 5278 export CA_CERT_PATH 4722 5279 export CERT_FULLCHAIN_PATH 4723 export Le_Domain 5280 export Le_Domain="$_main_domain" 4724 5281 cd "$DOMAIN_PATH" && eval "$_reload_cmd" 4725 5282 ); then … … 4732 5289 } 4733 5290 5291 __read_password() { 5292 unset _pp 5293 prompt="Enter Password:" 5294 while IFS= read -p "$prompt" -r -s -n 1 char; do 5295 if [ "$char" = $'\0' ]; then 5296 break 5297 fi 5298 prompt='*' 5299 _pp="$_pp$char" 5300 done 5301 echo "$_pp" 5302 } 5303 5304 _install_win_taskscheduler() { 5305 _lesh="$1" 5306 _centry="$2" 5307 _randomminute="$3" 5308 if ! _exists cygpath; then 5309 _err "cygpath not found" 5310 return 1 5311 fi 5312 if ! _exists schtasks; then 5313 _err "schtasks.exe is not found, are you on Windows?" 5314 return 1 5315 fi 5316 _winbash="$(cygpath -w $(which bash))" 5317 _debug _winbash "$_winbash" 5318 if [ -z "$_winbash" ]; then 5319 _err "can not find bash path" 5320 return 1 5321 fi 5322 _myname="$(whoami)" 5323 _debug "_myname" "$_myname" 5324 if [ -z "$_myname" ]; then 5325 _err "can not find my user name" 5326 return 1 5327 fi 5328 _debug "_lesh" "$_lesh" 5329 5330 _info "To install scheduler task in your Windows account, you must input your windows password." 5331 _info "$PROJECT_NAME doesn't save your password." 5332 _info "Please input your Windows password for: $(__green "$_myname")" 5333 _password="$(__read_password)" 5334 #SCHTASKS.exe '/create' '/SC' 'DAILY' '/TN' "$_WINDOWS_SCHEDULER_NAME" '/F' '/ST' "00:$_randomminute" '/RU' "$_myname" '/RP' "$_password" '/TR' "$_winbash -l -c '$_lesh --cron --home \"$LE_WORKING_DIR\" $_centry'" >/dev/null 5335 echo SCHTASKS.exe '/create' '/SC' 'DAILY' '/TN' "$_WINDOWS_SCHEDULER_NAME" '/F' '/ST' "00:$_randomminute" '/RU' "$_myname" '/RP' "$_password" '/TR' "\"$_winbash -l -c '$_lesh --cron --home \"$LE_WORKING_DIR\" $_centry'\"" | cmd.exe >/dev/null 5336 echo 5337 5338 } 5339 5340 _uninstall_win_taskscheduler() { 5341 if ! _exists schtasks; then 5342 _err "schtasks.exe is not found, are you on Windows?" 5343 return 1 5344 fi 5345 if ! echo SCHTASKS /query /tn "$_WINDOWS_SCHEDULER_NAME" | cmd.exe >/dev/null; then 5346 _debug "scheduler $_WINDOWS_SCHEDULER_NAME is not found." 5347 else 5348 _info "Removing $_WINDOWS_SCHEDULER_NAME" 5349 echo SCHTASKS /delete /f /tn "$_WINDOWS_SCHEDULER_NAME" | cmd.exe >/dev/null 5350 fi 5351 } 5352 4734 5353 #confighome 4735 5354 installcronjob() { … … 4737 5356 _initpath 4738 5357 _CRONTAB="crontab" 5358 if [ -f "$LE_WORKING_DIR/$PROJECT_ENTRY" ]; then 5359 lesh="\"$LE_WORKING_DIR\"/$PROJECT_ENTRY" 5360 else 5361 _err "Can not install cronjob, $PROJECT_ENTRY not found." 5362 return 1 5363 fi 5364 if [ "$_c_home" ]; then 5365 _c_entry="--config-home \"$_c_home\" " 5366 fi 5367 _t=$(_time) 5368 random_minute=$(_math $_t % 60) 5369 4739 5370 if ! _exists "$_CRONTAB" && _exists "fcrontab"; then 4740 5371 _CRONTAB="fcrontab" 4741 5372 fi 5373 4742 5374 if ! _exists "$_CRONTAB"; then 5375 if _exists cygpath && _exists schtasks.exe; then 5376 _info "It seems you are on Windows, let's install Windows scheduler task." 5377 if _install_win_taskscheduler "$lesh" "$_c_entry" "$random_minute"; then 5378 _info "Install Windows scheduler task success." 5379 return 0 5380 else 5381 _err "Install Windows scheduler task failed." 5382 return 1 5383 fi 5384 fi 4743 5385 _err "crontab/fcrontab doesn't exist, so, we can not install cron jobs." 4744 5386 _err "All your certs will not be renewed automatically." … … 4746 5388 return 1 4747 5389 fi 4748 4749 5390 _info "Installing cron job" 4750 5391 if ! $_CRONTAB -l | grep "$PROJECT_ENTRY --cron"; then 4751 if [ -f "$LE_WORKING_DIR/$PROJECT_ENTRY" ]; then4752 lesh="\"$LE_WORKING_DIR\"/$PROJECT_ENTRY"4753 else4754 _err "Can not install cronjob, $PROJECT_ENTRY not found."4755 return 14756 fi4757 4758 if [ "$_c_home" ]; then4759 _c_entry="--config-home \"$_c_home\" "4760 fi4761 _t=$(_time)4762 random_minute=$(_math $_t % 60)4763 5392 if _exists uname && uname -a | grep SunOS >/dev/null; then 4764 5393 $_CRONTAB -l | { … … 4788 5417 4789 5418 if ! _exists "$_CRONTAB"; then 5419 if _exists cygpath && _exists schtasks.exe; then 5420 _info "It seems you are on Windows, let's uninstall Windows scheduler task." 5421 if _uninstall_win_taskscheduler; then 5422 _info "Uninstall Windows scheduler task success." 5423 return 0 5424 else 5425 _err "Uninstall Windows scheduler task failed." 5426 return 1 5427 fi 5428 fi 4790 5429 return 4791 5430 fi … … 4919 5558 return 1 4920 5559 fi 4921 _authorizations_seg="$(echo "$response" | tr -d '\r\n' |_egrep_o '"authorizations" *: *\[[^\]*\]' | cut -d '[' -f 2 | tr -d ']' | tr -d '"')"5560 _authorizations_seg="$(echo "$response" | _egrep_o '"authorizations" *: *\[[^\]*\]' | cut -d '[' -f 2 | tr -d ']' | tr -d '"')" 4922 5561 _debug2 _authorizations_seg "$_authorizations_seg" 4923 5562 if [ -z "$_authorizations_seg" ]; then … … 4930 5569 authzUri="$_authorizations_seg" 4931 5570 _debug2 "authzUri" "$authzUri" 4932 if ! response="$(_get "$authzUri")"; then5571 if ! _send_signed_request "$authzUri"; then 4933 5572 _err "get to authz error." 4934 5573 _err "_authorizations_seg" "$_authorizations_seg" … … 4948 5587 fi 4949 5588 4950 authzUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ' ' -f 2| tr -d "\r\n")"5589 authzUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ':' -f 2- | tr -d "\r\n")" 4951 5590 _debug "authzUri" "$authzUri" 4952 5591 if [ "$code" ] && [ ! "$code" = '201' ]; then … … 4965 5604 _debug "Trigger validation." 4966 5605 vtype="$VTYPE_DNS" 4967 entry="$( printf "%s\n""$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"5606 entry="$(echo "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')" 4968 5607 _debug entry "$entry" 4969 5608 if [ -z "$entry" ]; then … … 4971 5610 return 1 4972 5611 fi 4973 token="$( printf "%s\n""$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')"5612 token="$(echo "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')" 4974 5613 _debug token "$token" 4975 5614 4976 uri="$( printf "%s\n""$entry" | _egrep_o "\"$_URL_NAME\":\"[^\"]*" | cut -d : -f 2,3 | tr -d '"')"5615 uri="$(echo "$entry" | _egrep_o "\"$_URL_NAME\":\"[^\"]*" | cut -d : -f 2,3 | tr -d '"')" 4977 5616 _debug uri "$uri" 4978 5617 … … 4996 5635 fi 4997 5636 4998 _vtype="$( printf "%s\n""$entry" | _egrep_o '"type": *"[^"]*"' | cut -d : -f 2 | tr -d '"')"5637 _vtype="$(echo "$entry" | _egrep_o '"type": *"[^"]*"' | cut -d : -f 2 | tr -d '"')" 4999 5638 _debug _vtype "$_vtype" 5000 5639 _info "Found $_vtype" 5001 5640 5002 uri="$( printf "%s\n""$entry" | _egrep_o "\"$_URL_NAME\":\"[^\"]*" | cut -d : -f 2,3 | tr -d '"')"5641 uri="$(echo "$entry" | _egrep_o "\"$_URL_NAME\":\"[^\"]*" | cut -d : -f 2,3 | tr -d '"')" 5003 5642 _debug uri "$uri" 5004 5643 … … 5115 5754 if [ -z "$_nocron" ]; then 5116 5755 if ! _exists "crontab" && ! _exists "fcrontab"; then 5117 _err "It is recommended to install crontab first. try to install 'cron, crontab, crontabs or vixie-cron'." 5118 _err "We need to set cron job to renew the certs automatically." 5119 _err "Otherwise, your certs will not be able to be renewed automatically." 5120 if [ -z "$FORCE" ]; then 5121 _err "Please add '--force' and try install again to go without crontab." 5122 _err "./$PROJECT_ENTRY --install --force" 5123 return 1 5756 if _exists cygpath && _exists schtasks.exe; then 5757 _info "It seems you are on Windows, we will install Windows scheduler task." 5758 else 5759 _err "It is recommended to install crontab first. try to install 'cron, crontab, crontabs or vixie-cron'." 5760 _err "We need to set cron job to renew the certs automatically." 5761 _err "Otherwise, your certs will not be able to be renewed automatically." 5762 if [ -z "$FORCE" ]; then 5763 _err "Please add '--force' and try install again to go without crontab." 5764 _err "./$PROJECT_ENTRY --install --force" 5765 return 1 5766 fi 5124 5767 fi 5125 5768 fi … … 5235 5878 fi 5236 5879 5237 if [ "$ IN_CRON" != "1" ]; then5880 if [ "$ACME_IN_CRON" != "1" ]; then 5238 5881 if ! _precheck "$_nocron"; then 5239 5882 _err "Pre-check failed, can not install." … … 5292 5935 _info "Installed to $LE_WORKING_DIR/$PROJECT_ENTRY" 5293 5936 5294 if [ "$ IN_CRON" != "1" ] && [ -z "$_noprofile" ]; then5937 if [ "$ACME_IN_CRON" != "1" ] && [ -z "$_noprofile" ]; then 5295 5938 _installalias "$_c_home" 5296 5939 fi … … 5390 6033 5391 6034 cron() { 5392 export IN_CRON=16035 export ACME_IN_CRON=1 5393 6036 _initpath 5394 6037 _info "$(__green "===Starting cron===")" … … 5411 6054 renewAll 5412 6055 _ret="$?" 5413 IN_CRON=""6056 ACME_IN_CRON="" 5414 6057 _info "$(__green "===End cron===")" 5415 6058 exit $_ret … … 5419 6062 echo "$PROJECT" 5420 6063 echo "v$VER" 6064 } 6065 6066 # subject content hooks code 6067 _send_notify() { 6068 _nsubject="$1" 6069 _ncontent="$2" 6070 _nhooks="$3" 6071 _nerror="$4" 6072 6073 if [ "$NOTIFY_LEVEL" = "$NOTIFY_LEVEL_DISABLE" ]; then 6074 _debug "The NOTIFY_LEVEL is $NOTIFY_LEVEL, disabled, just return." 6075 return 0 6076 fi 6077 6078 if [ -z "$_nhooks" ]; then 6079 _debug "The NOTIFY_HOOK is empty, just return." 6080 return 0 6081 fi 6082 6083 _send_err=0 6084 for _n_hook in $(echo "$_nhooks" | tr ',' " "); do 6085 _n_hook_file="$(_findHook "" $_SUB_FOLDER_NOTIFY "$_n_hook")" 6086 _info "Sending via: $_n_hook" 6087 _debug "Found $_n_hook_file for $_n_hook" 6088 if [ -z "$_n_hook_file" ]; then 6089 _err "Can not find the hook file for $_n_hook" 6090 continue 6091 fi 6092 if ! ( 6093 if ! . "$_n_hook_file"; then 6094 _err "Load file $_n_hook_file error. Please check your api file and try again." 6095 return 1 6096 fi 6097 6098 d_command="${_n_hook}_send" 6099 if ! _exists "$d_command"; then 6100 _err "It seems that your api file is not correct, it must have a function named: $d_command" 6101 return 1 6102 fi 6103 6104 if ! $d_command "$_nsubject" "$_ncontent" "$_nerror"; then 6105 _err "Error send message by $d_command" 6106 return 1 6107 fi 6108 6109 return 0 6110 ); then 6111 _err "Set $_n_hook_file error." 6112 _send_err=1 6113 else 6114 _info "$_n_hook $(__green Success)" 6115 fi 6116 done 6117 return $_send_err 6118 6119 } 6120 6121 # hook 6122 _set_notify_hook() { 6123 _nhooks="$1" 6124 6125 _test_subject="Hello, this is a notification from $PROJECT_NAME" 6126 _test_content="If you receive this message, your notification works." 6127 6128 _send_notify "$_test_subject" "$_test_content" "$_nhooks" 0 6129 6130 } 6131 6132 #[hook] [level] [mode] 6133 setnotify() { 6134 _nhook="$1" 6135 _nlevel="$2" 6136 _nmode="$3" 6137 6138 _initpath 6139 6140 if [ -z "$_nhook$_nlevel$_nmode" ]; then 6141 _usage "Usage: $PROJECT_ENTRY --set-notify [--notify-hook mailgun] [--notify-level $NOTIFY_LEVEL_DEFAULT] [--notify-mode $NOTIFY_MODE_DEFAULT]" 6142 _usage "$_NOTIFY_WIKI" 6143 return 1 6144 fi 6145 6146 if [ "$_nlevel" ]; then 6147 _info "Set notify level to: $_nlevel" 6148 export "NOTIFY_LEVEL=$_nlevel" 6149 _saveaccountconf "NOTIFY_LEVEL" "$NOTIFY_LEVEL" 6150 fi 6151 6152 if [ "$_nmode" ]; then 6153 _info "Set notify mode to: $_nmode" 6154 export "NOTIFY_MODE=$_nmode" 6155 _saveaccountconf "NOTIFY_MODE" "$NOTIFY_MODE" 6156 fi 6157 6158 if [ "$_nhook" ]; then 6159 _info "Set notify hook to: $_nhook" 6160 if [ "$_nhook" = "$NO_VALUE" ]; then 6161 _info "Clear notify hook" 6162 _clearaccountconf "NOTIFY_HOOK" 6163 else 6164 if _set_notify_hook "$_nhook"; then 6165 export NOTIFY_HOOK="$_nhook" 6166 _saveaccountconf "NOTIFY_HOOK" "$NOTIFY_HOOK" 6167 return 0 6168 else 6169 _err "Can not set notify hook to: $_nhook" 6170 return 1 6171 fi 6172 fi 6173 fi 6174 5421 6175 } 5422 6176 … … 5453 6207 --createCSR, -ccsr Create CSR , professional use. 5454 6208 --deactivate Deactivate the domain authz, professional use. 6209 --set-notify Set the cron notification hook, level or mode. 6210 5455 6211 5456 6212 Parameters: … … 5461 6217 --staging, --test Use staging server, just for test. 5462 6218 --debug Output debug info. 5463 --output-insecure Output all the sensitive messages. By default all the credentials/sensitive messages are hidden from the output/debug/log for secur e.6219 --output-insecure Output all the sensitive messages. By default all the credentials/sensitive messages are hidden from the output/debug/log for security. 5464 6220 --webroot, -w /path/to/webroot Specifies the web root folder for web root mode. 5465 6221 --standalone Use standalone mode. 6222 --alpn Use standalone alpn mode. 5466 6223 --stateless Use stateless mode, see: $_STATELESS_WIKI 5467 6224 --apache Use apache mode. … … 5469 6226 --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. 5470 6227 5471 --keylength, -k [2048] Specifies the domain key length: 2048, 3072, 4096, 8192 or ec-256, ec-384 .5472 --accountkeylength, -ak [2048] Specifies the account key length .6228 --keylength, -k [2048] Specifies the domain key length: 2048, 3072, 4096, 8192 or ec-256, ec-384, ec-521. 6229 --accountkeylength, -ak [2048] Specifies the account key length: 2048, 3072, 4096 5473 6230 --log [/path/to/logfile] Specifies the log file. The default is: \"$DEFAULT_LOG_FILE\" if you don't give a file path here. 5474 6231 --log-level 1|2 Specifies the log level, default is 1. 5475 6232 --syslog [0|3|6|7] Syslog level, 0: disable syslog, 3: error, 6: info, 7: debug. 5476 6233 5477 These parameters are to install the cert to nginx/apache or any other server after issue/renew a cert:6234 These parameters are to install the cert to nginx/apache or any other server after issue/renew a cert: 5478 6235 5479 6236 --cert-file After issue/renew, the cert will be copied to this path. … … 5484 6241 --reloadcmd \"service nginx reload\" After issue/renew, it's used to reload the server. 5485 6242 5486 --server SERVER ACME Directory Resource URI. (default: https://acme-v01.api.letsencrypt.org/directory)6243 --server SERVER ACME Directory Resource URI. (default: $DEFAULT_CA) 5487 6244 --accountconf Specifies a customized account config file. 5488 --home Specifies the home dir for $PROJECT_NAME 6245 --home Specifies the home dir for $PROJECT_NAME. 5489 6246 --cert-home Specifies the home dir to save all the certs, only valid for '--install' command. 5490 6247 --config-home Specifies the home dir to save all the configurations. … … 5492 6249 --accountemail Specifies the account email, only valid for the '--install' and '--update-account' command. 5493 6250 --accountkey Specifies the account key path, only valid for the '--install' command. 5494 --days Specifies the days to renew the cert when using '--issue' command. The max value is $MAX_RENEW days.6251 --days Specifies the days to renew the cert when using '--issue' command. The default value is $DEFAULT_RENEW days. 5495 6252 --httpport Specifies the standalone listening port. Only valid if the server is behind a reverse proxy or load balancer. 6253 --tlsport Specifies the standalone tls listening port. Only valid if the server is behind a reverse proxy or load balancer. 5496 6254 --local-address Specifies the standalone/tls server listening address, in case you have multiple ip addresses. 5497 6255 --listraw Only used for '--list' command, list the certs in raw format. … … 5501 6259 --ca-path Specifies directory containing CA certificates in PEM format, used by wget or curl. 5502 6260 --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. 6261 --noprofile Only valid for '--install' command, which means: do not install aliases to user profile. 5503 6262 --no-color Do not output color text. 5504 6263 --force-color Force output of color text. Useful for non-interactive use with the aha tool for HTML E-Mails. … … 5518 6277 --yes-I-know-dns-manual-mode-enough-go-ahead-please Force to use dns manual mode: $_DNS_MANUAL_WIKI 5519 6278 --branch, -b Only valid for '--upgrade' command, specifies the branch name to upgrade to. 5520 " 6279 6280 --notify-level 0|1|2|3 Set the notification level: Default value is $NOTIFY_LEVEL_DEFAULT. 6281 0: disabled, no notification will be sent. 6282 1: send notifications only when there is an error. 6283 2: send notifications when a cert is successfully renewed, or there is an error. 6284 3: send notifications when a cert is skipped, renewed, or error. 6285 --notify-mode 0|1 Set notification mode. Default value is $NOTIFY_MODE_DEFAULT. 6286 0: Bulk mode. Send all the domain's notifications in one message(mail). 6287 1: Cert mode. Send a message for every single cert. 6288 --notify-hook [hookname] Set the notify hook 6289 6290 " 5521 6291 } 5522 6292 … … 5548 6318 if ./$PROJECT_ENTRY install "$_nocron" "" "$_noprofile"; then 5549 6319 _info "Install success!" 6320 _initpath 6321 _saveaccountconf "UPGRADE_HASH" "$(_getMasterHash)" 5550 6322 fi 5551 6323 … … 5557 6329 } 5558 6330 6331 _getMasterHash() { 6332 _b="$BRANCH" 6333 if [ -z "$_b" ]; then 6334 _b="master" 6335 fi 6336 _hash_url="https://api.github.com/repos/acmesh-official/$PROJECT_NAME/git/refs/heads/$_b" 6337 _get $_hash_url | tr -d "\r\n" | tr '{},' '\n' | grep '"sha":' | cut -d '"' -f 4 6338 } 6339 5559 6340 upgrade() { 5560 6341 if ( 5561 6342 _initpath 6343 [ -z "$FORCE" ] && [ "$(_getMasterHash)" = "$(_readaccountconf "UPGRADE_HASH")" ] && _info "Already uptodate!" && exit 0 5562 6344 export LE_WORKING_DIR 5563 6345 cd "$LE_WORKING_DIR" … … 5603 6385 fi 5604 6386 6387 } 6388 6389 _checkSudo() { 6390 if [ "$SUDO_GID" ] && [ "$SUDO_COMMAND" ] && [ "$SUDO_USER" ] && [ "$SUDO_UID" ]; then 6391 if [ "$SUDO_USER" = "root" ] && [ "$SUDO_UID" = "0" ]; then 6392 #it's root using sudo, no matter it's using sudo or not, just fine 6393 return 0 6394 fi 6395 if [ "$SUDO_COMMAND" = "/bin/su" ] || [ "$SUDO_COMMAND" = "/bin/bash" ]; then 6396 #it's a normal user doing "sudo su", or `sudo -i` or `sudo -s` 6397 #fine 6398 return 0 6399 fi 6400 #otherwise 6401 return 1 6402 fi 6403 return 0 5605 6404 } 5606 6405 … … 5634 6433 _ca_path="" 5635 6434 _nocron="" 6435 _noprofile="" 5636 6436 _ecc="" 5637 6437 _csr="" … … 5651 6451 _use_wget="" 5652 6452 _server="" 6453 _notify_hook="" 6454 _notify_level="" 6455 _notify_mode="" 5653 6456 while [ ${#} -gt 0 ]; do 5654 6457 case "${1}" in … … 5736 6539 --deactivate-account) 5737 6540 _CMD="deactivateaccount" 6541 ;; 6542 --set-notify) 6543 _CMD="setnotify" 5738 6544 ;; 5739 6545 --domain | -d) … … 5818 6624 fi 5819 6625 ;; 6626 --alpn) 6627 wvalue="$W_ALPN" 6628 if [ -z "$_webroot" ]; then 6629 _webroot="$wvalue" 6630 else 6631 _webroot="$_webroot,$wvalue" 6632 fi 6633 ;; 5820 6634 --stateless) 5821 6635 wvalue="$MODE_STATELESS" … … 5841 6655 --nginx) 5842 6656 wvalue="$NGINX" 6657 if [ "$2" ] && ! _startswith "$2" "-"; then 6658 wvalue="$NGINX$2" 6659 shift 6660 fi 5843 6661 if [ -z "$_webroot" ]; then 5844 6662 _webroot="$wvalue" … … 5942 6760 shift 5943 6761 ;; 6762 --tlsport) 6763 _tlsport="$2" 6764 Le_TLSPort="$_tlsport" 6765 shift 6766 ;; 5944 6767 --listraw) 5945 6768 _listraw="raw" … … 5964 6787 --nocron) 5965 6788 _nocron="1" 6789 ;; 6790 --noprofile) 6791 _noprofile="1" 5966 6792 ;; 5967 6793 --no-color) … … 6069 6895 shift 6070 6896 ;; 6897 --notify-hook) 6898 _nhook="$2" 6899 if _startswith "$_nhook" "-"; then 6900 _err "'$_nhook' is not a hook name for '$1'" 6901 return 1 6902 fi 6903 if [ "$_notify_hook" ]; then 6904 _notify_hook="$_notify_hook,$_nhook" 6905 else 6906 _notify_hook="$_nhook" 6907 fi 6908 shift 6909 ;; 6910 --notify-level) 6911 _nlevel="$2" 6912 if _startswith "$_nlevel" "-"; then 6913 _err "'$_nlevel' is not a integer for '$1'" 6914 return 1 6915 fi 6916 _notify_level="$_nlevel" 6917 shift 6918 ;; 6919 --notify-mode) 6920 _nmode="$2" 6921 if _startswith "$_nmode" "-"; then 6922 _err "'$_nmode' is not a integer for '$1'" 6923 return 1 6924 fi 6925 _notify_mode="$_nmode" 6926 shift 6927 ;; 6071 6928 *) 6072 6929 _err "Unknown parameter : $1" … … 6079 6936 6080 6937 if [ "${_CMD}" != "install" ]; then 6938 if [ "$__INTERACTIVE" ] && ! _checkSudo; then 6939 if [ -z "$FORCE" ]; then 6940 #Use "echo" here, instead of _info. it's too early 6941 echo "It seems that you are using sudo, please read this link first:" 6942 echo "$_SUDO_WIKI" 6943 return 1 6944 fi 6945 fi 6081 6946 __initHome 6082 6947 if [ "$_log" ]; then … … 6121 6986 fi 6122 6987 fi 6123 6988 _debug "Running cmd: ${_CMD}" 6124 6989 case "${_CMD}" in 6125 install) install "$_nocron" "$_confighome" ;;6990 install) install "$_nocron" "$_confighome" "$_noprofile" ;; 6126 6991 uninstall) uninstall "$_nocron" ;; 6127 6992 upgrade) upgrade ;; … … 6186 7051 createCSR "$_domain" "$_altdomains" "$_ecc" 6187 7052 ;; 6188 7053 setnotify) 7054 setnotify "$_notify_hook" "$_notify_level" "$_notify_mode" 7055 ;; 6189 7056 *) 6190 7057 if [ "$_CMD" ]; then -
npl/syn3/acme/root/usr/bin/syn3-acme-renew
re856512 reb67240 3 3 #SYN-3 certbot renewal script 4 4 echo "SYN-3: Renewing live certificate" 5 6 if ! [ -e /etc/acme/live ]; then 7 syn3-state certbot OK "Certbot/Letsencrypt not activated." 8 exit 0 9 fi 5 10 6 11 STATUS=/tmp/$$.certbot -
npl/syn3/acme/syn3_acme.build
re856512 reb67240 1 2 1 9 -
npl/syn3/acme/syn3_acme.md5
re856512 reb67240 1 b1b5fa20c0e210b2c48ae0cf40efed3d ./root/usr/bin/acme.sh 1 d41d8cd98f00b204e9800998ecf8427e ./root/etc/webint/SSL_DOMAINS.new 2 9215d7b19618c71a42df9326d86ad16f ./root/usr/bin/acme.sh 2 3 a0e5403f61c08e4eda04cd2e61d7938a ./root/usr/bin/syn3-acme 3 4 cb7232508745b67caad455dd54cd8bb9 ./root/usr/bin/syn3-acme-issue 4 4f8bd14609cbc87090c04ef517bf3c29./root/usr/bin/syn3-acme-renew5 56cc3e0e602dd9c3bc10c130e9528826./syn3_acme.pkg5 f5eca94149edc261a950c497533c71a2 ./root/usr/bin/syn3-acme-renew 6 fe2fd64e8e4592834c27d7978aebcde4 ./syn3_acme.pkg 6 7 1a66f2a0cb707f264b0268ee3d4956d3 ./syn3_acme.SlackBuild 7 4241b5e353f758024dd4e4e03f8344e5 ./syn3_acme.SlackBuild.log.gz8 556f9498697435671507e661abe96a95 ./syn3_acme.SlackBuild.log.gz
Note: See TracChangeset
for help on using the changeset viewer.