Changeset eb67240 for npl


Ignore:
Timestamp:
03/25/20 14:25:12 (5 years ago)
Author:
Edwin Eefting <edwin@datux.nl>
Branches:
master
Children:
3c9eb90
Parents:
e856512
Message:

acme and certbot updates

Location:
npl/syn3/acme
Files:
2 added
6 edited

Legend:

Unmodified
Added
Removed
  • npl/syn3/acme/root/usr/bin/acme.sh

    re856512 reb67240  
    11#!/usr/bin/env sh
    22
    3 VER=2.7.9
     3VER=2.8.6
    44
    55PROJECT_NAME="acme.sh"
     
    77PROJECT_ENTRY="acme.sh"
    88
    9 PROJECT="https://github.com/Neilpang/$PROJECT_NAME"
     9PROJECT="https://github.com/acmesh-official/$PROJECT_NAME"
    1010
    1111DEFAULT_INSTALL_HOME="$HOME/.$PROJECT_NAME"
     12
     13_WINDOWS_SCHEDULER_NAME="$PROJECT_NAME.cron"
     14
    1215_SCRIPT_="$0"
    1316
    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"
    1522
    1623LETSENCRYPT_CA_V1="https://acme-v01.api.letsencrypt.org/directory"
     
    2027LETSENCRYPT_STAGING_CA_V2="https://acme-staging-v02.api.letsencrypt.org/directory"
    2128
    22 DEFAULT_CA=$LETSENCRYPT_CA_V1
    23 DEFAULT_STAGING_CA=$LETSENCRYPT_STAGING_CA_V1
     29DEFAULT_CA=$LETSENCRYPT_CA_V2
     30DEFAULT_STAGING_CA=$LETSENCRYPT_STAGING_CA_V2
    2431
    2532DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)"
     
    3643VTYPE_HTTP="http-01"
    3744VTYPE_DNS="dns-01"
    38 VTYPE_TLS="tls-sni-01"
    39 VTYPE_TLS2="tls-sni-02"
     45VTYPE_ALPN="tls-alpn-01"
    4046
    4147LOCAL_ANY_ADDRESS="0.0.0.0"
    4248
    43 MAX_RENEW=60
     49DEFAULT_RENEW=60
    4450
    4551DEFAULT_DNS_SLEEP=120
     
    4753NO_VALUE="no"
    4854
    49 W_TLS="tls"
    5055W_DNS="dns"
     56W_ALPN="alpn"
    5157DNS_ALIAS_PREFIX="="
    5258
     
    6773CONTENT_TYPE_JSON="application/jose+json"
    6874RENEW_SKIP=2
     75
     76B64CONF_START="__ACME_BASE64__START_"
     77B64CONF_END="__ACME_BASE64__END_"
    6978
    7079ECC_SEP="_"
     
    8190DEBUG_LEVEL_DEFAULT=$DEBUG_LEVEL_1
    8291DEBUG_LEVEL_NONE=0
     92
     93DOH_CLOUDFLARE=1
     94DOH_GOOGLE=2
    8395
    8496HIDDEN_VALUE="[hidden](please add '--output-insecure' to see this value)"
     
    103115SYSLOG_LEVEL_NONE=0
    104116
    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"
     117NOTIFY_LEVEL_DISABLE=0
     118NOTIFY_LEVEL_ERROR=1
     119NOTIFY_LEVEL_RENEW=2
     120NOTIFY_LEVEL_SKIP=3
     121
     122NOTIFY_LEVEL_DEFAULT=$NOTIFY_LEVEL_RENEW
     123
     124NOTIFY_MODE_BULK=0
     125NOTIFY_MODE_CERT=1
     126
     127NOTIFY_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"
    114142
    115143_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."
     
    125153
    126154__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
    129158  fi
    130159  printf -- "%b" "$1"
    131   if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" -o "${ACME_FORCE_COLOR}" = "1" ]; then
    132     printf '\033[0m'
    133   fi
    134160}
    135161
    136162__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
    139166  fi
    140167  printf -- "%b" "$1"
    141   if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" -o "${ACME_FORCE_COLOR}" = "1" ]; then
    142     printf '\033[0m'
    143   fi
    144168}
    145169
    146170_printargs() {
     171  _exitstatus="$?"
    147172  if [ -z "$NO_TIMESTAMP" ] || [ "$NO_TIMESTAMP" = "0" ]; then
    148173    printf -- "%s" "[$(date)] "
     
    154179  fi
    155180  printf "\n"
     181  # return the saved exit status
     182  return "$_exitstatus"
    156183}
    157184
     
    181208  echo "socat:"
    182209  if _exists "socat"; then
    183     socat -h 2>&1
     210    socat -V 2>&1
    184211  else
    185212    _debug "socat doesn't exists."
     
    189216#class
    190217_syslog() {
     218  _exitstatus="$?"
    191219  if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" = "$SYSLOG_LEVEL_NONE" ]; then
    192220    return
     
    202230  fi
    203231  $__logger_i -t "$PROJECT_NAME" -p "$_logclass" "$(_printargs "$@")" >/dev/null 2>&1
     232  return "$_exitstatus"
    204233}
    205234
     
    237266}
    238267
     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
    239299_debug() {
    240300  if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_1" ]; then
     
    245305  fi
    246306  if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_1" ]; then
    247     _printargs "$@" >&2
     307    _bash_debug=$(__debug_bash_helper)
     308    _printargs "${_bash_debug}$@" >&2
    248309  fi
    249310}
     
    278339  fi
    279340  if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then
    280     _printargs "$@" >&2
     341    _bash_debug=$(__debug_bash_helper)
     342    _printargs "${_bash_debug}$@" >&2
    281343  fi
    282344}
     
    310372  fi
    311373  if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_3" ]; then
    312     _printargs "$@" >&2
     374    _bash_debug=$(__debug_bash_helper)
     375    _printargs "${_bash_debug}$@" >&2
    313376  fi
    314377}
     
    779842}
    780843
     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
    781851#options file
    782852_sed_i() {
     
    10011071  if _isEccKey "$length"; then
    10021072    _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
    10041079  else
    10051080    _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
    10071087  fi
    10081088
     
    10171097  _is_idn_d="$1"
    10181098  _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 '*.,-_')
    10201100  _debug2 _idn_temp "$_idn_temp"
    10211101  [ "$_idn_temp" ]
     
    10511131}
    10521132
    1053 #_createcsr  cn  san_list  keyfile csrfile conf
     1133#_createcsr  cn  san_list  keyfile csrfile conf acmeValidationv1
    10541134_createcsr() {
    10551135  _debug _createcsr
     
    10591139  csr="$4"
    10601140  csrconf="$5"
     1141  acmeValidationv1="$6"
    10611142  _debug2 domain "$domain"
    10621143  _debug2 domainlist "$domainlist"
     
    10671148  printf "[ req_distinguished_name ]\n[ req ]\ndistinguished_name = req_distinguished_name\nreq_extensions = v3_req\n[ v3_req ]\n\nkeyUsage = nonRepudiation, digitalSignature, keyEncipherment" >"$csrconf"
    10681149
    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
    10701154    #single domain
    10711155    _info "Single domain" "$domain"
    1072     printf -- "\nsubjectAltName=DNS:$domain" >>"$csrconf"
     1156    printf -- "\nsubjectAltName=DNS:$(_idn "$domain")" >>"$csrconf"
    10731157  else
    10741158    domainlist="$(_idn "$domainlist")"
    10751159    _debug2 domainlist "$domainlist"
    10761160    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")"
    10781162    else
    1079       alt="DNS:$domain,DNS:$domainlist"
     1163      alt="DNS:$(_idn "$domain"),DNS:$domainlist"
    10801164    fi
    10811165    #multi
     
    10871171    _cleardomainconf Le_OCSP_Stable
    10881172    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}"
    10891177  fi
    10901178
     
    11391227  if _contains "$_dnsAltnames," "DNS:$_csrsubj,"; then
    11401228    _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"
    11421235  else
    11431236    _debug "AltNames doesn't contain subject"
    11441237  fi
    11451238
    1146   printf "%s" "$_dnsAltnames" | sed "s/DNS://g"
     1239  echo "$_dnsAltnames" | sed "s/DNS://g"
    11471240}
    11481241
     
    11821275  if _exists "netstat"; then
    11831276    _debug "Using: netstat"
    1184     if netstat -h 2>&1 | grep "\-p proto" >/dev/null; then
     1277    if netstat -help 2>&1 | grep "\-p proto" >/dev/null; then
    11851278      #for windows version netstat tool
    11861279      netstat -an -p tcp | grep "LISTENING" | grep ":$_port "
     
    12951388
    12961389  mkdir -p "$CA_DIR"
    1297   if [ -f "$ACCOUNT_KEY_PATH" ]; then
     1390  if [ -s "$ACCOUNT_KEY_PATH" ]; then
    12981391    _info "Account key exists, skip"
    1299     return
     1392    return 0
    13001393  else
    13011394    #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
    13041403  fi
    13051404
     
    13241423  _initpath "$domain" "$_cdl"
    13251424
    1326   if [ ! -f "$CERT_KEY_PATH" ] || ([ "$FORCE" ] && ! [ "$IS_RENEW" ]) || [ "$Le_ForceNewDomainKey" = "1" ]; then
     1425  if [ ! -f "$CERT_KEY_PATH" ] || [ ! -s "$CERT_KEY_PATH" ] || ([ "$FORCE" ] && ! [ "$IS_RENEW" ]) || [ "$Le_ForceNewDomainKey" = "1" ]; then
    13271426    if _createkey "$_cdl" "$CERT_KEY_PATH"; then
    13281427      _savedomainconf Le_Keylength "$_cdl"
    13291428      _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
    13301433    fi
    13311434  else
     
    13751478
    13761479_time2str() {
     1480  #BSD
     1481  if date -u -r "$1" 2>/dev/null; then
     1482    return
     1483  fi
     1484
    13771485  #Linux
    13781486  if date -u -d@"$1" 2>/dev/null; then
     
    13801488  fi
    13811489
    1382   #BSD
    1383   if date -u -r "$1" 2>/dev/null; then
    1384     return
    1385   fi
    1386 
    1387   #Soaris
     1490  #Solaris
    13881491  if _exists adb; then
    13891492    _t_s_a=$(echo "0t${1}=Y" | adb)
     
    15201623    JWK_HEADERPLACE_PART2='", "alg": "ES'$__ECC_KEY_LEN'"'
    15211624  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")"
    15231627    return 1
    15241628  fi
     
    16081712}
    16091713
    1610 # body  url [needbase64] [POST|PUT] [ContentType]
     1714# body  url [needbase64] [POST|PUT|DELETE] [ContentType]
    16111715_post() {
    16121716  body="$1"
     
    16311735      _CURL="$_CURL --insecure  "
    16321736    fi
     1737    if [ "$httpmethod" = "HEAD" ]; then
     1738      _CURL="$_CURL -I  "
     1739    fi
    16331740    _debug "_CURL" "$_CURL"
    16341741    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
    16371748      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
    16391754      fi
    16401755    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
    16431762      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
    16451768      fi
    16461769    fi
     
    16571780    if [ "$HTTPS_INSECURE" ]; then
    16581781      _WGET="$_WGET --no-check-certificate "
     1782    fi
     1783    if [ "$httpmethod" = "HEAD" ]; then
     1784      _WGET="$_WGET --read-timeout=3.0  --tries=2  "
    16591785    fi
    16601786    _debug "_WGET" "$_WGET"
     
    16791805        else
    16801806          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")"
    16811813        fi
    16821814      else
     
    17961928  fi
    17971929
    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
    18031932  payload64=$(printf "%s" "$payload" | _base64 | _url_replace)
    18041933  _debug3 payload64 "$payload64"
    18051934
    1806   MAX_REQUEST_RETRY_TIMES=5
     1935  MAX_REQUEST_RETRY_TIMES=20
     1936  _sleep_retry_sec=1
    18071937  _request_retry_times=0
    18081938  while [ "${_request_retry_times}" -lt "$MAX_REQUEST_RETRY_TIMES" ]; do
     
    18121942      _headers=""
    18131943      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"
    18151945        nonceurl="$ACME_NEW_NONCE"
    1816         if _post "" "$nonceurl" "" "HEAD" "$__request_conent_type"; then
     1946        if _post "" "$nonceurl" "" "HEAD" "$__request_conent_type" >/dev/null; then
    18171947          _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"
    18221954        nonceurl="$ACME_DIRECTORY"
    18231955        _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"
    18261967      if [ "$?" != "0" ]; then
    18271968        _err "Can not connect to $nonceurl to get nonce."
    18281969        return 1
    18291970      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"
    18351971    else
    18361972      _debug2 "Use _CACHED_NONCE" "$_CACHED_NONCE"
     
    18662002    _debug3 sig "$sig"
    18672003
    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\"}"
    18732005    _debug3 body "$body"
    18742006
     
    18802012      return 1
    18812013    fi
    1882     _debug2 original "$response"
    1883     response="$(echo "$response" | _normalizeJson)"
    18842014
    18852015    responseHeaders="$(cat "$HTTP_HEADER")"
    1886 
    18872016    _debug2 responseHeaders "$responseHeaders"
    1888     _debug2 response "$response"
     2017
    18892018    code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\r\n")"
    18902019    _debug code "$code"
    18912020
    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
    19062044  done
     2045  _info "Giving up sending to CA server after $MAX_REQUEST_RETRY_TIMES retries."
     2046  return 1
    19072047
    19082048}
     
    19452085}
    19462086
    1947 #_save_conf  file key  value
     2087#_save_conf  file key  value base64encode
    19482088#save to conf
    19492089_save_conf() {
     
    19512091  _sdkey="$2"
    19522092  _sdvalue="$3"
     2093  _b64encode="$4"
     2094  if [ "$_sdvalue" ] && [ "$_b64encode" ]; then
     2095    _sdvalue="${B64CONF_START}$(printf "%s" "${_sdvalue}" | _base64)${B64CONF_END}"
     2096  fi
    19532097  if [ "$_s_c_f" ]; then
    19542098    _setopt "$_s_c_f" "$_sdkey" "=" "'$_sdvalue'"
     
    19752119  _sdkey="$2"
    19762120  if [ -f "$_r_c_f" ]; then
    1977     (
     2121    _sdv="$(
    19782122      eval "$(grep "^$_sdkey *=" "$_r_c_f")"
    19792123      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"
    19812129  else
    19822130    _debug "config file is empty, can not read $_sdkey"
     
    19842132}
    19852133
    1986 #_savedomainconf   key  value
     2134#_savedomainconf   key  value  base64encode
    19872135#save to domain.conf
    19882136_savedomainconf() {
    1989   _save_conf "$DOMAIN_CONF" "$1" "$2"
     2137  _save_conf "$DOMAIN_CONF" "$@"
    19902138}
    19912139
     
    20002148}
    20012149
    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
    20032173_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
    20082178_saveaccountconf_mutable() {
    2009   _save_conf "$ACCOUNT_CONF_PATH" "SAVED_$1" "$2"
     2179  _save_conf "$ACCOUNT_CONF_PATH" "SAVED_$1" "$2" "$3"
    20102180  #remove later
    20112181  _clearaccountconf "$1"
     
    20472217  content="$1"
    20482218  ncaddr="$2"
     2219  _debug "content" "$content"
    20492220  _debug "ncaddr" "$ncaddr"
    20502221
     
    20732244  fi
    20742245
     2246  _content_len="$(printf "%s" "$content" | wc -c)"
     2247  _debug _content_len "$_content_len"
    20752248  _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; \
     2250echo 'HTTP/1.0 200 OK'; \
     2251echo 'Content-Length\: $_content_len'; \
     2252echo ''; \
     2253printf -- '$content';" &
    20772254  serverproc="$!"
    20782255}
     
    21062283}
    21072284
    2108 # _starttlsserver  san_a  san_b port content _ncaddr
     2285# _starttlsserver  san_a  san_b port content _ncaddr acmeValidationv1
    21092286_starttlsserver() {
    21102287  _info "Starting tls server."
     
    21142291  content="$4"
    21152292  opaddr="$5"
     2293  acmeValidationv1="$6"
    21162294
    21172295  _debug san_a "$san_a"
    21182296  _debug san_b "$san_b"
    21192297  _debug port "$port"
     2298  _debug acmeValidationv1 "$acmeValidationv1"
    21202299
    21212300  #create key TLS_KEY
     
    21302309    alt="$alt,$san_b"
    21312310  fi
    2132   if ! _createcsr "tls.acme.sh" "$alt" "$TLS_KEY" "$TLS_CSR" "$TLS_CONF"; then
     2311  if ! _createcsr "tls.acme.sh" "$alt" "$TLS_KEY" "$TLS_CSR" "$TLS_CONF" "$acmeValidationv1"; then
    21332312    _err "Create tls validation csr error."
    21342313    return 1
     
    21542333  elif [ "$Le_Listen_V6" ]; then
    21552334    __S_OPENSSL="$__S_OPENSSL -6"
     2335  fi
     2336
     2337  if [ "$acmeValidationv1" ]; then
     2338    __S_OPENSSL="$__S_OPENSSL -alpn acme-tls/1"
    21562339  fi
    21572340
     
    22332416    ACCOUNT_CONF_PATH="$_DEFAULT_ACCOUNT_CONF_PATH"
    22342417  fi
    2235 
     2418  _debug3 ACCOUNT_CONF_PATH "$ACCOUNT_CONF_PATH"
    22362419  DEFAULT_LOG_FILE="$LE_CONFIG_HOME/$PROJECT_NAME.log"
    22372420
     
    23372520  fi
    23382521
    2339   if [ "$IN_CRON" ]; then
     2522  if [ "$ACME_IN_CRON" ]; then
    23402523    if [ ! "$_USER_PATH_EXPORTED" ]; then
    23412524      _USER_PATH_EXPORTED=1
     
    26842867      NGINX_CONF="$(echo "$NGINX_CONF" | cut -d = -f 2)"
    26852868      _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
    26862874      if [ ! -f "$NGINX_CONF" ]; then
    26872875        _err "'$NGINX_CONF' doesn't exist."
     
    28443032        for _listen_i in $(echo "$_seg_n" | tr "\t" ' ' | grep "^ *listen" | tr -d " "); do
    28453033          if [ "$_listen_i" ]; then
    2846             if [ "$(echo "$_listen_i" | _egrep_o "listen.*ssl[ |;]")" ]; then
     3034            if [ "$(echo "$_listen_i" | _egrep_o "listen.*ssl")" ]; then
    28473035              _debug2 "$_listen_i is ssl"
    28483036            else
     
    29103098_clearupdns() {
    29113099  _debug "_clearupdns"
    2912   if [ "$dnsadded" != 1 ] || [ -z "$vlist" ]; then
     3100  _debug "dns_entries" "$dns_entries"
     3101
     3102  if [ -z "$dns_entries" ]; then
    29133103    _debug "skip dns."
    29143104    return
    29153105  fi
    29163106  _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
    29383124
    29393125    if [ -z "$d_api" ]; then
    29403126      _info "Not Found domain api file: $d_api"
    29413127      continue
     3128    fi
     3129
     3130    if [ "$aliasDomain" ]; then
     3131      txtdomain="$aliasDomain"
    29423132    fi
    29433133
     
    29533143        return 1
    29543144      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"
    29743146      if ! $rmcommand "$txtdomain" "$txt"; then
    29753147        _err "Error removing txt for domain:$txtdomain"
    29763148        return 1
    29773149      fi
     3150      _info "Removed: Success"
    29783151    )
    29793152
     
    30613234      if [ -z "$Le_HTTPPort" ]; then
    30623235        Le_HTTPPort=80
     3236        _cleardomainconf "Le_HTTPPort"
    30633237      else
    30643238        _savedomainconf "Le_HTTPPort" "$Le_HTTPPort"
    30653239      fi
    30663240      _checkport="$Le_HTTPPort"
    3067     elif [ "$_currentRoot" = "$W_TLS" ]; then
    3068       _info "Standalone tls mode."
     3241    elif [ "$_currentRoot" = "$W_ALPN" ]; then
     3242      _info "Standalone alpn mode."
    30693243      if [ -z "$Le_TLSPort" ]; then
    30703244        Le_TLSPort=443
     
    31613335  _chk_renew_hook="$2"
    31623336  _debug _on_issue_success
     3337
    31633338  #run the post hook
    31643339  if [ "$_chk_post_hook" ]; then
    31653340    _info "Run post hook:'$_chk_post_hook'"
    31663341    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"
    31673347      cd "$DOMAIN_PATH" && eval "$_chk_post_hook"
    31683348    ); then
     
    31763356    _info "Run renew hook:'$_chk_renew_hook'"
    31773357    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"
    31783363      cd "$DOMAIN_PATH" && eval "$_chk_renew_hook"
    31793364    ); then
     
    31833368  fi
    31843369
    3185   if _hasfield "$Le_Webroot" "$W_DNS"; then
     3370  if _hasfield "$Le_Webroot" "$W_DNS" && [ -z "$FORCE_DNS_MANUAL" ]; then
    31863371    _err "$_DNS_MANUAL_WARN"
    31873372  fi
    31883373
    3189 }
    3190 
    3191 updateaccount() {
    3192   _initpath
    3193   _regAccount
    31943374}
    31953375
     
    32683448
    32693449  _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 ")"
    32713451  _debug "_accUri" "$_accUri"
    32723452  if [ -z "$_accUri" ]; then
     
    32893469  ACCOUNT_THUMBPRINT="$(__calc_account_thumbprint)"
    32903470  _info "ACCOUNT_THUMBPRINT" "$ACCOUNT_THUMBPRINT"
     3471}
     3472
     3473#implement updateaccount
     3474updateaccount() {
     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
    32913526}
    32923527
     
    33683603  elif [ -f "$_SCRIPT_HOME/$_hookcat/$_hookname.sh" ]; then
    33693604    d_api="$_SCRIPT_HOME/$_hookcat/$_hookname.sh"
    3370   elif [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname" ]; then
     3605  elif [ "$_hookdomain" ] && [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname" ]; then
    33713606    d_api="$LE_WORKING_DIR/$_hookdomain/$_hookname"
    3372   elif [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname.sh" ]; then
     3607  elif [ "$_hookdomain" ] && [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname.sh" ]; then
    33733608    d_api="$LE_WORKING_DIR/$_hookdomain/$_hookname.sh"
    33743609  elif [ -f "$LE_WORKING_DIR/$_hookname" ]; then
     
    34263661#uri keyAuthorization
    34273662__trigger_validation() {
    3428   _debug2 "tigger domain validation."
     3663  _debug2 "Trigger domain validation."
    34293664  _t_url="$1"
    34303665  _debug2 _t_url "$_t_url"
    34313666  _t_key_authz="$2"
    34323667  _debug2 _t_key_authz "$_t_key_authz"
     3668  _t_vtype="$3"
     3669  _debug2 _t_vtype "$_t_vtype"
    34333670  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
    34383830}
    34393831
     
    35183910  _savedomainconf "Le_Webroot" "$_web_roots"
    35193911
    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"
    35233915
    35243916  if [ "$_local_addr" ]; then
     
    35333925  fi
    35343926
    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
    35373933
    35383934  if [ "$_alt_domains" = "$NO_VALUE" ]; then
     
    35863982
    35873983  vlist="$Le_Vlist"
    3588 
     3984  _cleardomainconf "Le_Vlist"
    35893985  _info "Getting domain auth token for each domain"
    35903986  sep='#'
     
    35933989    if [ "$ACME_VERSION" = "2" ]; then
    35943990      #make new order request
    3595       _identifiers="{\"type\":\"dns\",\"value\":\"$_main_domain\"}"
     3991      _identifiers="{\"type\":\"dns\",\"value\":\"$(_idn "$_main_domain")\"}"
    35963992      _w_index=1
    35973993      while true; do
     
    36023998          break
    36033999        fi
    3604         _identifiers="$_identifiers,{\"type\":\"dns\",\"value\":\"$d\"}"
     4000        _identifiers="$_identifiers,{\"type\":\"dns\",\"value\":\"$(_idn "$d")\"}"
    36054001      done
    36064002      _debug2 _identifiers "$_identifiers"
     
    36114007        return 1
    36124008      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)"
    36154012      _debug Le_OrderFinalize "$Le_OrderFinalize"
    36164013      if [ -z "$Le_OrderFinalize" ]; then
     
    36244021      _savedomainconf "Le_OrderFinalize" "$Le_OrderFinalize"
    36254022
    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 '"')"
    36274024      _debug2 _authorizations_seg "$_authorizations_seg"
    36284025      if [ -z "$_authorizations_seg" ]; then
     
    36374034      for _authz_url in $(echo "$_authorizations_seg" | tr ',' ' '); do
    36384035        _debug2 "_authz_url" "$_authz_url"
    3639         if ! response="$(_get "$_authz_url")"; then
     4036        if ! _send_signed_request "$_authz_url"; then
    36404037          _err "get to authz error."
    36414038          _err "_authorizations_seg" "$_authorizations_seg"
     
    36844081      fi
    36854082
    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"
    36924085      fi
    36934086
    36944087      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,//")"
    36964100        _debug2 "response" "$response"
    36974101        if [ -z "$response" ]; then
     
    37144118      fi
    37154119
    3716       entry="$(printf "%s\n" "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"
     4120      entry="$(echo "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"
    37174121      _debug entry "$entry"
     4122      keyauthorization=""
    37184123      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"
    37564168        _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
    37574175      fi
    37584176
     
    37654183    _debug vlist "$vlist"
    37664184    #add entry
     4185    dns_entries=""
    37674186    dnsadded=""
    37684187    ventries=$(echo "$vlist" | tr "$dvsep" ' ')
     
    37764195      if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then
    37774196        _debug "$d is already verified, skip $vtype."
     4197        _alias_index="$(_math "$_alias_index" + 1)"
    37784198        continue
    37794199      fi
     
    37944214            txtdomain="_acme-challenge.$_d_alias"
    37954215          fi
     4216          dns_entry="${_dns_root_d}${dvsep}_acme-challenge.$_dns_root_d$dvsep$txtdomain$dvsep$_currentRoot"
    37964217        else
    37974218          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
    37994222        _debug txtdomain "$txtdomain"
    38004223        txt="$(printf "%s" "$keyauthorization" | _digest "sha256" | _url_replace)"
    38014224        _debug txt "$txt"
    38024225
    3803         d_api="$(_findHook "$_dns_root_d" dnsapi "$_currentRoot")"
    3804 
     4226        d_api="$(_findHook "$_dns_root_d" $_SUB_FOLDER_DNSAPI "$_currentRoot")"
    38054227        _debug d_api "$d_api"
    38064228
     4229        dns_entry="$dns_entry$dvsep$txt${dvsep}$d_api"
     4230        _debug2 dns_entry "$dns_entry"
    38074231        if [ "$d_api" ]; then
    3808           _info "Found domain api file: $d_api"
     4232          _debug "Found domain api file: $d_api"
    38094233        else
    38104234          if [ "$_currentRoot" != "$W_DNS" ]; then
     
    38314255            return 1
    38324256          fi
    3833 
     4257          _info "Adding txt value: $txt for domain:  $txtdomain"
    38344258          if ! $addcommand "$txtdomain" "$txt"; then
    38354259            _err "Error add txt for domain:$txtdomain"
    38364260            return 1
    38374261          fi
     4262          _info "The txt record is added: Success."
    38384263        )
    38394264
    38404265        if [ "$?" != "0" ]; then
     4266          _on_issue_err "$_post_hook" "$vlist"
    38414267          _clearup
    3842           _on_issue_err "$_post_hook" "$vlist"
    38434268          return 1
    38444269        fi
     4270        dns_entries="$dns_entries$dns_entry
     4271"
     4272        _debug2 "$dns_entries"
    38454273        dnsadded='1'
    38464274      fi
     
    38514279      _debug "Dns record not added yet, so, save to $DOMAIN_CONF and exit."
    38524280      _err "Please add the TXT records to the domains, and re-run with --renew."
     4281      _on_issue_err "$_post_hook"
    38534282      _clearup
    3854       _on_issue_err "$_post_hook"
    38554283      return 1
    38564284    fi
     
    38584286  fi
    38594287
    3860   if [ "$dnsadded" = '1' ]; then
     4288  if [ "$dns_entries" ]; then
    38614289    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
    38634298    else
    38644299      _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
    38694303  fi
    38704304
     
    38864320    fi
    38874321
    3888     _info "Verifying:$d"
     4322    _info "Verifying: $d"
    38894323    _debug "d" "$d"
    38904324    _debug "keyauthorization" "$keyauthorization"
     
    39704404
    39714405      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
    40004410        _err "Start tls server error."
    40014411        _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
     
    40064416    fi
    40074417
    4008     if ! __trigger_validation "$uri" "$keyauthorization"; then
     4418    if ! __trigger_validation "$uri" "$keyauthorization" "$vtype"; then
    40094419      _err "$d:Can not get challenge: $response"
    40104420      _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
     
    40154425
    40164426    if [ "$code" ] && [ "$code" != '202' ]; then
    4017       if [ "$ACME_VERSION" = "2" ] && [ "$code" = '200' ]; then
     4427      if [ "$code" = '200' ]; then
    40184428        _debug "trigger validation code: $code"
    40194429      else
     
    40444454      sleep 2
    40454455      _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
    40474461      if [ "$?" != "0" ]; then
    40484462        _err "$d:Verify error:$response"
     
    40674481
    40684482      if [ "$status" = "invalid" ]; then
    4069         error="$(echo "$response" | tr -d "\r\n" | _egrep_o '"error":\{[^\}]*')"
     4483        error="$(echo "$response" | _egrep_o '"error":\{[^\}]*')"
    40704484        _debug2 error "$error"
    40714485        errordetail="$(echo "$error" | _egrep_o '"detail": *"[^"]*' | cut -d '"' -f 4)"
     
    40904504      if [ "$status" = "pending" ]; then
    40914505        _info "Pending"
     4506      elif [ "$status" = "processing" ]; then
     4507        _info "Processing"
    40924508      else
    40934509        _err "$d:Verify error:$response"
     
    41074523
    41084524  if [ "$ACME_VERSION" = "2" ]; then
     4525    _info "Lets finalize the order, Le_OrderFinalize: $Le_OrderFinalize"
    41094526    if ! _send_signed_request "${Le_OrderFinalize}" "{\"csr\": \"$der\"}"; then
    41104527      _err "Sign failed."
     
    41134530    fi
    41144531    if [ "$code" != "200" ]; then
    4115       _err "Sign failed, code is not 200."
     4532      _err "Sign failed, finalize code is not 200."
    41164533      _err "$response"
    41174534      _on_issue_err "$_post_hook"
    41184535      return 1
    41194536    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
    41234591      _err "Sign failed, can not download cert:$Le_LinkCert."
    41244592      _err "$response"
     
    41264594      return 1
    41274595    fi
     4596
     4597    echo "$response" >"$CERT_PATH"
    41284598
    41294599    if [ "$(grep -- "$BEGIN_CERT" "$CERT_PATH" | wc -l)" -gt "1" ]; then
     
    41364606      sed -n "${_end_n},9999p" "$CERT_FULLCHAIN_PATH" >"$CA_CERT_PATH"
    41374607    fi
     4608
    41384609  else
    41394610    if ! _send_signed_request "${ACME_NEW_ORDER}" "{\"resource\": \"$ACME_NEW_ORDER_RES\", \"csr\": \"$der\"}" "needbase64"; then
     
    41794650    fi
    41804651
    4181     if [ ! "$USER_PATH" ] || [ ! "$IN_CRON" ]; then
     4652    if [ ! "$USER_PATH" ] || [ ! "$ACME_IN_CRON" ]; then
    41824653      USER_PATH="$PATH"
    41834654      _saveaccountconf "USER_PATH" "$USER_PATH"
    41844655    fi
    41854656  fi
    4186 
    4187   _cleardomainconf "Le_Vlist"
    41884657
    41894658  if [ "$ACME_VERSION" = "2" ]; then
     
    42064675        _debug _link_issuer_retry "$_link_issuer_retry"
    42074676        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"
    42094679            break
    42104680          fi
     
    42424712  _savedomainconf "Le_CertCreateTimeStr" "$Le_CertCreateTimeStr"
    42434713
    4244   if [ -z "$Le_RenewalDays" ] || [ "$Le_RenewalDays" -lt "0" ] || [ "$Le_RenewalDays" -gt "$MAX_RENEW" ]; then
    4245     Le_RenewalDays="$MAX_RENEW"
     4714  if [ -z "$Le_RenewalDays" ] || [ "$Le_RenewalDays" -lt "0" ]; then
     4715    Le_RenewalDays="$DEFAULT_RENEW"
    42464716  else
    42474717    _savedomainconf "Le_RenewalDays" "$Le_RenewalDays"
     
    42924762    _savedomainconf "Le_RealCACertPath" "$_real_ca"
    42934763    _savedomainconf "Le_RealKeyPath" "$_real_key"
    4294     _savedomainconf "Le_ReloadCmd" "$_reload_cmd"
     4764    _savedomainconf "Le_ReloadCmd" "$_reload_cmd" "base64"
    42954765    _savedomainconf "Le_RealFullChainPath" "$_real_fullchain"
    42964766    if ! _installcert "$_main_domain" "$_real_cert" "$_real_key" "$_real_ca" "$_real_fullchain" "$_reload_cmd"; then
     
    43204790  if [ ! -f "$DOMAIN_CONF" ]; then
    43214791    _info "'$Le_Domain' is not a issued domain, skip."
    4322     return 0
     4792    return $RENEW_SKIP
    43234793  fi
    43244794
     
    43294799  . "$DOMAIN_CONF"
    43304800  _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
    43314811  if [ "$Le_API" ]; then
    43324812    if [ "$_OLD_CA_HOST" = "$Le_API" ]; then
     
    43534833  fi
    43544834
    4355   if [ "$IN_CRON" = "1" ] && [ -z "$Le_CertCreateTime" ]; then
     4835  if [ "$ACME_IN_CRON" = "1" ] && [ -z "$Le_CertCreateTime" ]; then
    43564836    _info "Skip invalid cert for: $Le_Domain"
    4357     return 0
     4837    return $RENEW_SKIP
    43584838  fi
    43594839
    43604840  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)"
    43614845  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"
    43624846  res="$?"
     
    43814865  _debug "_stopRenewOnError" "$_stopRenewOnError"
    43824866  _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"
    43844874  for di in "${CERT_HOME}"/*.*/; do
    43854875    _debug di "$di"
     
    43994889    rc="$?"
    44004890    _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
    44054935        _err "Error renew $d,  stop now."
    4406         return "$rc"
     4936        _ret="$rc"
     4937        break
    44074938      else
    44084939        _ret="$rc"
     
    44114942    fi
    44124943  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
    44134972  return "$_ret"
    44144973}
     
    45265085    printf "%s\n" "Main_Domain${_sep}KeyLength${_sep}SAN_Domains${_sep}Created${_sep}Renew"
    45275086    for di in "${CERT_HOME}"/*.*/; do
    4528       if ! [ -d "$di" ]; then
    4529         _debug "Not directory, skip: $di"
    4530         continue
    4531       fi
    45325087      d=$(basename "$di")
    45335088      _debug d "$d"
    45345089      (
    45355090        if _endswith "$d" "$ECC_SUFFIX"; then
    4536           _isEcc=$(echo "$d" | cut -d "$ECC_SEP" -f 2)
     5091          _isEcc="ecc"
    45375092          d=$(echo "$d" | cut -d "$ECC_SEP" -f 1)
    45385093        fi
    4539         _initpath "$d" "$_isEcc"
     5094        DOMAIN_CONF="$di/$d.conf"
    45405095        if [ -f "$DOMAIN_CONF" ]; then
    45415096          . "$DOMAIN_CONF"
     
    45595114
    45605115  for _d_api in $(echo "$_hooks" | tr ',' " "); do
    4561     _deployApi="$(_findHook "$_d" deploy "$_d_api")"
     5116    _deployApi="$(_findHook "$_d" $_SUB_FOLDER_DEPLOY "$_d_api")"
    45625117    if [ -z "$_deployApi" ]; then
    45635118      _err "The deploy hook $_d_api is not found."
     
    46035158  _initpath "$_d" "$_isEcc"
    46045159  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'"
    46065162    return 1
    46075163  fi
     
    46305186  _initpath "$_main_domain" "$_isEcc"
    46315187  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'"
    46335190    return 1
    46345191  fi
     
    46375194  _savedomainconf "Le_RealCACertPath" "$_real_ca"
    46385195  _savedomainconf "Le_RealKeyPath" "$_real_key"
    4639   _savedomainconf "Le_ReloadCmd" "$_reload_cmd"
     5196  _savedomainconf "Le_ReloadCmd" "$_reload_cmd" "base64"
    46405197  _savedomainconf "Le_RealFullChainPath" "$_real_fullchain"
    46415198
     
    47215278      export CA_CERT_PATH
    47225279      export CERT_FULLCHAIN_PATH
    4723       export Le_Domain
     5280      export Le_Domain="$_main_domain"
    47245281      cd "$DOMAIN_PATH" && eval "$_reload_cmd"
    47255282    ); then
     
    47325289}
    47335290
     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
    47345353#confighome
    47355354installcronjob() {
     
    47375356  _initpath
    47385357  _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
    47395370  if ! _exists "$_CRONTAB" && _exists "fcrontab"; then
    47405371    _CRONTAB="fcrontab"
    47415372  fi
     5373
    47425374  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
    47435385    _err "crontab/fcrontab doesn't exist, so, we can not install cron jobs."
    47445386    _err "All your certs will not be renewed automatically."
     
    47465388    return 1
    47475389  fi
    4748 
    47495390  _info "Installing cron job"
    47505391  if ! $_CRONTAB -l | grep "$PROJECT_ENTRY --cron"; then
    4751     if [ -f "$LE_WORKING_DIR/$PROJECT_ENTRY" ]; then
    4752       lesh="\"$LE_WORKING_DIR\"/$PROJECT_ENTRY"
    4753     else
    4754       _err "Can not install cronjob, $PROJECT_ENTRY not found."
    4755       return 1
    4756     fi
    4757 
    4758     if [ "$_c_home" ]; then
    4759       _c_entry="--config-home \"$_c_home\" "
    4760     fi
    4761     _t=$(_time)
    4762     random_minute=$(_math $_t % 60)
    47635392    if _exists uname && uname -a | grep SunOS >/dev/null; then
    47645393      $_CRONTAB -l | {
     
    47885417
    47895418  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
    47905429    return
    47915430  fi
     
    49195558      return 1
    49205559    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 '"')"
    49225561    _debug2 _authorizations_seg "$_authorizations_seg"
    49235562    if [ -z "$_authorizations_seg" ]; then
     
    49305569    authzUri="$_authorizations_seg"
    49315570    _debug2 "authzUri" "$authzUri"
    4932     if ! response="$(_get "$authzUri")"; then
     5571    if ! _send_signed_request "$authzUri"; then
    49335572      _err "get to authz error."
    49345573      _err "_authorizations_seg" "$_authorizations_seg"
     
    49485587    fi
    49495588
    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")"
    49515590    _debug "authzUri" "$authzUri"
    49525591    if [ "$code" ] && [ ! "$code" = '201' ]; then
     
    49655604    _debug "Trigger validation."
    49665605    vtype="$VTYPE_DNS"
    4967     entry="$(printf "%s\n" "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"
     5606    entry="$(echo "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"
    49685607    _debug entry "$entry"
    49695608    if [ -z "$entry" ]; then
     
    49715610      return 1
    49725611    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 '"')"
    49745613    _debug token "$token"
    49755614
    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 '"')"
    49775616    _debug uri "$uri"
    49785617
     
    49965635    fi
    49975636
    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 '"')"
    49995638    _debug _vtype "$_vtype"
    50005639    _info "Found $_vtype"
    50015640
    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 '"')"
    50035642    _debug uri "$uri"
    50045643
     
    51155754  if [ -z "$_nocron" ]; then
    51165755    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
    51245767      fi
    51255768    fi
     
    52355878  fi
    52365879
    5237   if [ "$IN_CRON" != "1" ]; then
     5880  if [ "$ACME_IN_CRON" != "1" ]; then
    52385881    if ! _precheck "$_nocron"; then
    52395882      _err "Pre-check failed, can not install."
     
    52925935  _info "Installed to $LE_WORKING_DIR/$PROJECT_ENTRY"
    52935936
    5294   if [ "$IN_CRON" != "1" ] && [ -z "$_noprofile" ]; then
     5937  if [ "$ACME_IN_CRON" != "1" ] && [ -z "$_noprofile" ]; then
    52955938    _installalias "$_c_home"
    52965939  fi
     
    53906033
    53916034cron() {
    5392   export IN_CRON=1
     6035  export ACME_IN_CRON=1
    53936036  _initpath
    53946037  _info "$(__green "===Starting cron===")"
     
    54116054  renewAll
    54126055  _ret="$?"
    5413   IN_CRON=""
     6056  ACME_IN_CRON=""
    54146057  _info "$(__green "===End cron===")"
    54156058  exit $_ret
     
    54196062  echo "$PROJECT"
    54206063  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]
     6133setnotify() {
     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
    54216175}
    54226176
     
    54536207  --createCSR, -ccsr       Create CSR , professional use.
    54546208  --deactivate             Deactivate the domain authz, professional use.
     6209  --set-notify             Set the cron notification hook, level or mode.
     6210
    54556211
    54566212Parameters:
     
    54616217  --staging, --test                 Use staging server, just for test.
    54626218  --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 secure.
     6219  --output-insecure                 Output all the sensitive messages. By default all the credentials/sensitive messages are hidden from the output/debug/log for security.
    54646220  --webroot, -w  /path/to/webroot   Specifies the web root folder for web root mode.
    54656221  --standalone                      Use standalone mode.
     6222  --alpn                            Use standalone alpn mode.
    54666223  --stateless                       Use stateless mode, see: $_STATELESS_WIKI
    54676224  --apache                          Use apache mode.
     
    54696226  --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.
    54706227
    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
    54736230  --log    [/path/to/logfile]       Specifies the log file. The default is: \"$DEFAULT_LOG_FILE\" if you don't give a file path here.
    54746231  --log-level 1|2                   Specifies the log level, default is 1.
    54756232  --syslog [0|3|6|7]                Syslog level, 0: disable syslog, 3: error, 6: info, 7: debug.
    54766233
    5477   These parameters are to install the cert to nginx/apache or anyother 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:
    54786235
    54796236  --cert-file                       After issue/renew, the cert will be copied to this path.
     
    54846241  --reloadcmd \"service nginx reload\" After issue/renew, it's used to reload the server.
    54856242
    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)
    54876244  --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.
    54896246  --cert-home                       Specifies the home dir to save all the certs, only valid for '--install' command.
    54906247  --config-home                     Specifies the home dir to save all the configurations.
     
    54926249  --accountemail                    Specifies the account email, only valid for the '--install' and '--update-account' command.
    54936250  --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.
    54956252  --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.
    54966254  --local-address                   Specifies the standalone/tls server listening address, in case you have multiple ip addresses.
    54976255  --listraw                         Only used for '--list' command, list the certs in raw format.
     
    55016259  --ca-path                         Specifies directory containing CA certificates in PEM format, used by wget or curl.
    55026260  --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.
    55036262  --no-color                        Do not output color text.
    55046263  --force-color                     Force output of color text. Useful for non-interactive use with the aha tool for HTML E-Mails.
     
    55186277  --yes-I-know-dns-manual-mode-enough-go-ahead-please  Force to use dns manual mode: $_DNS_MANUAL_WIKI
    55196278  --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"
    55216291}
    55226292
     
    55486318    if ./$PROJECT_ENTRY install "$_nocron" "" "$_noprofile"; then
    55496319      _info "Install success!"
     6320      _initpath
     6321      _saveaccountconf "UPGRADE_HASH" "$(_getMasterHash)"
    55506322    fi
    55516323
     
    55576329}
    55586330
     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
    55596340upgrade() {
    55606341  if (
    55616342    _initpath
     6343    [ -z "$FORCE" ] && [ "$(_getMasterHash)" = "$(_readaccountconf "UPGRADE_HASH")" ] && _info "Already uptodate!" && exit 0
    55626344    export LE_WORKING_DIR
    55636345    cd "$LE_WORKING_DIR"
     
    56036385  fi
    56046386
     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
    56056404}
    56066405
     
    56346433  _ca_path=""
    56356434  _nocron=""
     6435  _noprofile=""
    56366436  _ecc=""
    56376437  _csr=""
     
    56516451  _use_wget=""
    56526452  _server=""
     6453  _notify_hook=""
     6454  _notify_level=""
     6455  _notify_mode=""
    56536456  while [ ${#} -gt 0 ]; do
    56546457    case "${1}" in
     
    57366539      --deactivate-account)
    57376540        _CMD="deactivateaccount"
     6541        ;;
     6542      --set-notify)
     6543        _CMD="setnotify"
    57386544        ;;
    57396545      --domain | -d)
     
    58186624        fi
    58196625        ;;
     6626      --alpn)
     6627        wvalue="$W_ALPN"
     6628        if [ -z "$_webroot" ]; then
     6629          _webroot="$wvalue"
     6630        else
     6631          _webroot="$_webroot,$wvalue"
     6632        fi
     6633        ;;
    58206634      --stateless)
    58216635        wvalue="$MODE_STATELESS"
     
    58416655      --nginx)
    58426656        wvalue="$NGINX"
     6657        if [ "$2" ] && ! _startswith "$2" "-"; then
     6658          wvalue="$NGINX$2"
     6659          shift
     6660        fi
    58436661        if [ -z "$_webroot" ]; then
    58446662          _webroot="$wvalue"
     
    59426760        shift
    59436761        ;;
     6762      --tlsport)
     6763        _tlsport="$2"
     6764        Le_TLSPort="$_tlsport"
     6765        shift
     6766        ;;
    59446767      --listraw)
    59456768        _listraw="raw"
     
    59646787      --nocron)
    59656788        _nocron="1"
     6789        ;;
     6790      --noprofile)
     6791        _noprofile="1"
    59666792        ;;
    59676793      --no-color)
     
    60696895        shift
    60706896        ;;
     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        ;;
    60716928      *)
    60726929        _err "Unknown parameter : $1"
     
    60796936
    60806937  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
    60816946    __initHome
    60826947    if [ "$_log" ]; then
     
    61216986    fi
    61226987  fi
    6123 
     6988  _debug "Running cmd: ${_CMD}"
    61246989  case "${_CMD}" in
    6125     install) install "$_nocron" "$_confighome" ;;
     6990    install) install "$_nocron" "$_confighome" "$_noprofile" ;;
    61266991    uninstall) uninstall "$_nocron" ;;
    61276992    upgrade) upgrade ;;
     
    61867051      createCSR "$_domain" "$_altdomains" "$_ecc"
    61877052      ;;
    6188 
     7053    setnotify)
     7054      setnotify "$_notify_hook" "$_notify_level" "$_notify_mode"
     7055      ;;
    61897056    *)
    61907057      if [ "$_CMD" ]; then
  • npl/syn3/acme/root/usr/bin/syn3-acme-renew

    re856512 reb67240  
    33#SYN-3 certbot renewal script
    44echo "SYN-3: Renewing live certificate"
     5
     6if ! [ -e /etc/acme/live ]; then
     7        syn3-state certbot OK "Certbot/Letsencrypt not activated."
     8        exit 0
     9fi
    510
    611STATUS=/tmp/$$.certbot
  • npl/syn3/acme/syn3_acme.build

    re856512 reb67240  
    1 2
     19
  • npl/syn3/acme/syn3_acme.md5

    re856512 reb67240  
    1 b1b5fa20c0e210b2c48ae0cf40efed3d  ./root/usr/bin/acme.sh
     1d41d8cd98f00b204e9800998ecf8427e  ./root/etc/webint/SSL_DOMAINS.new
     29215d7b19618c71a42df9326d86ad16f  ./root/usr/bin/acme.sh
    23a0e5403f61c08e4eda04cd2e61d7938a  ./root/usr/bin/syn3-acme
    34cb7232508745b67caad455dd54cd8bb9  ./root/usr/bin/syn3-acme-issue
    4 4f8bd14609cbc87090c04ef517bf3c29  ./root/usr/bin/syn3-acme-renew
    5 56cc3e0e602dd9c3bc10c130e9528826  ./syn3_acme.pkg
     5f5eca94149edc261a950c497533c71a2  ./root/usr/bin/syn3-acme-renew
     6fe2fd64e8e4592834c27d7978aebcde4  ./syn3_acme.pkg
    671a66f2a0cb707f264b0268ee3d4956d3  ./syn3_acme.SlackBuild
    7 4241b5e353f758024dd4e4e03f8344e5  ./syn3_acme.SlackBuild.log.gz
     8556f9498697435671507e661abe96a95  ./syn3_acme.SlackBuild.log.gz
Note: See TracChangeset for help on using the changeset viewer.