| 
1630
 | 
     1 #!/usr/bin/env sh
 | 
| 
 | 
     2 
 | 
| 
 | 
     3 VER=2.8.8
 | 
| 
 | 
     4 
 | 
| 
 | 
     5 PROJECT_NAME="acme.sh"
 | 
| 
 | 
     6 
 | 
| 
 | 
     7 PROJECT_ENTRY="acme.sh"
 | 
| 
 | 
     8 
 | 
| 
 | 
     9 PROJECT="https://github.com/acmesh-official/$PROJECT_NAME"
 | 
| 
 | 
    10 
 | 
| 
 | 
    11 DEFAULT_INSTALL_HOME="$HOME/.$PROJECT_NAME"
 | 
| 
 | 
    12 
 | 
| 
 | 
    13 _WINDOWS_SCHEDULER_NAME="$PROJECT_NAME.cron"
 | 
| 
 | 
    14 
 | 
| 
 | 
    15 _SCRIPT_="$0"
 | 
| 
 | 
    16 
 | 
| 
 | 
    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"
 | 
| 
 | 
    22 
 | 
| 
 | 
    23 LETSENCRYPT_CA_V1="https://acme-v01.api.letsencrypt.org/directory"
 | 
| 
 | 
    24 LETSENCRYPT_STAGING_CA_V1="https://acme-staging.api.letsencrypt.org/directory"
 | 
| 
 | 
    25 
 | 
| 
 | 
    26 CA_LETSENCRYPT_V2="https://acme-v02.api.letsencrypt.org/directory"
 | 
| 
 | 
    27 CA_LETSENCRYPT_V2_TEST="https://acme-staging-v02.api.letsencrypt.org/directory"
 | 
| 
 | 
    28 
 | 
| 
 | 
    29 CA_BUYPASS="https://api.buypass.com/acme/directory"
 | 
| 
 | 
    30 CA_BUYPASS_TEST="https://api.test4.buypass.no/acme/directory"
 | 
| 
 | 
    31 
 | 
| 
 | 
    32 CA_ZEROSSL="https://acme.zerossl.com/v2/DV90"
 | 
| 
 | 
    33 _ZERO_EAB_ENDPOINT="http://api.zerossl.com/acme/eab-credentials-email"
 | 
| 
 | 
    34 
 | 
| 
 | 
    35 DEFAULT_CA=$CA_LETSENCRYPT_V2
 | 
| 
 | 
    36 DEFAULT_STAGING_CA=$CA_LETSENCRYPT_V2_TEST
 | 
| 
 | 
    37 
 | 
| 
 | 
    38 CA_NAMES="
 | 
| 
 | 
    39 LetsEncrypt.org,letsencrypt
 | 
| 
 | 
    40 LetsEncrypt.org_test,letsencrypt_test,letsencrypttest
 | 
| 
 | 
    41 BuyPass.com,buypass
 | 
| 
 | 
    42 BuyPass.com_test,buypass_test,buypasstest
 | 
| 
 | 
    43 ZeroSSL.com,zerossl
 | 
| 
 | 
    44 "
 | 
| 
 | 
    45 
 | 
| 
 | 
    46 CA_SERVERS="$CA_LETSENCRYPT_V2,$CA_LETSENCRYPT_V2_TEST,$CA_BUYPASS,$CA_BUYPASS_TEST,$CA_ZEROSSL"
 | 
| 
 | 
    47 
 | 
| 
 | 
    48 DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)"
 | 
| 
 | 
    49 
 | 
| 
 | 
    50 DEFAULT_ACCOUNT_KEY_LENGTH=2048
 | 
| 
 | 
    51 DEFAULT_DOMAIN_KEY_LENGTH=2048
 | 
| 
 | 
    52 
 | 
| 
 | 
    53 DEFAULT_OPENSSL_BIN="openssl"
 | 
| 
 | 
    54 
 | 
| 
 | 
    55 VTYPE_HTTP="http-01"
 | 
| 
 | 
    56 VTYPE_DNS="dns-01"
 | 
| 
 | 
    57 VTYPE_ALPN="tls-alpn-01"
 | 
| 
 | 
    58 
 | 
| 
 | 
    59 LOCAL_ANY_ADDRESS="0.0.0.0"
 | 
| 
 | 
    60 
 | 
| 
 | 
    61 DEFAULT_RENEW=60
 | 
| 
 | 
    62 
 | 
| 
 | 
    63 NO_VALUE="no"
 | 
| 
 | 
    64 
 | 
| 
 | 
    65 W_DNS="dns"
 | 
| 
 | 
    66 W_ALPN="alpn"
 | 
| 
 | 
    67 DNS_ALIAS_PREFIX="="
 | 
| 
 | 
    68 
 | 
| 
 | 
    69 MODE_STATELESS="stateless"
 | 
| 
 | 
    70 
 | 
| 
 | 
    71 STATE_VERIFIED="verified_ok"
 | 
| 
 | 
    72 
 | 
| 
 | 
    73 NGINX="nginx:"
 | 
| 
 | 
    74 NGINX_START="#ACME_NGINX_START"
 | 
| 
 | 
    75 NGINX_END="#ACME_NGINX_END"
 | 
| 
 | 
    76 
 | 
| 
 | 
    77 BEGIN_CSR="-----BEGIN CERTIFICATE REQUEST-----"
 | 
| 
 | 
    78 END_CSR="-----END CERTIFICATE REQUEST-----"
 | 
| 
 | 
    79 
 | 
| 
 | 
    80 BEGIN_CERT="-----BEGIN CERTIFICATE-----"
 | 
| 
 | 
    81 END_CERT="-----END CERTIFICATE-----"
 | 
| 
 | 
    82 
 | 
| 
 | 
    83 CONTENT_TYPE_JSON="application/jose+json"
 | 
| 
 | 
    84 RENEW_SKIP=2
 | 
| 
 | 
    85 
 | 
| 
 | 
    86 B64CONF_START="__ACME_BASE64__START_"
 | 
| 
 | 
    87 B64CONF_END="__ACME_BASE64__END_"
 | 
| 
 | 
    88 
 | 
| 
 | 
    89 ECC_SEP="_"
 | 
| 
 | 
    90 ECC_SUFFIX="${ECC_SEP}ecc"
 | 
| 
 | 
    91 
 | 
| 
 | 
    92 LOG_LEVEL_1=1
 | 
| 
 | 
    93 LOG_LEVEL_2=2
 | 
| 
 | 
    94 LOG_LEVEL_3=3
 | 
| 
 | 
    95 DEFAULT_LOG_LEVEL="$LOG_LEVEL_1"
 | 
| 
 | 
    96 
 | 
| 
 | 
    97 DEBUG_LEVEL_1=1
 | 
| 
 | 
    98 DEBUG_LEVEL_2=2
 | 
| 
 | 
    99 DEBUG_LEVEL_3=3
 | 
| 
 | 
   100 DEBUG_LEVEL_DEFAULT=$DEBUG_LEVEL_1
 | 
| 
 | 
   101 DEBUG_LEVEL_NONE=0
 | 
| 
 | 
   102 
 | 
| 
 | 
   103 DOH_CLOUDFLARE=1
 | 
| 
 | 
   104 DOH_GOOGLE=2
 | 
| 
 | 
   105 
 | 
| 
 | 
   106 HIDDEN_VALUE="[hidden](please add '--output-insecure' to see this value)"
 | 
| 
 | 
   107 
 | 
| 
 | 
   108 SYSLOG_ERROR="user.error"
 | 
| 
 | 
   109 SYSLOG_INFO="user.info"
 | 
| 
 | 
   110 SYSLOG_DEBUG="user.debug"
 | 
| 
 | 
   111 
 | 
| 
 | 
   112 #error
 | 
| 
 | 
   113 SYSLOG_LEVEL_ERROR=3
 | 
| 
 | 
   114 #info
 | 
| 
 | 
   115 SYSLOG_LEVEL_INFO=6
 | 
| 
 | 
   116 #debug
 | 
| 
 | 
   117 SYSLOG_LEVEL_DEBUG=7
 | 
| 
 | 
   118 #debug2
 | 
| 
 | 
   119 SYSLOG_LEVEL_DEBUG_2=8
 | 
| 
 | 
   120 #debug3
 | 
| 
 | 
   121 SYSLOG_LEVEL_DEBUG_3=9
 | 
| 
 | 
   122 
 | 
| 
 | 
   123 SYSLOG_LEVEL_DEFAULT=$SYSLOG_LEVEL_ERROR
 | 
| 
 | 
   124 #none
 | 
| 
 | 
   125 SYSLOG_LEVEL_NONE=0
 | 
| 
 | 
   126 
 | 
| 
 | 
   127 NOTIFY_LEVEL_DISABLE=0
 | 
| 
 | 
   128 NOTIFY_LEVEL_ERROR=1
 | 
| 
 | 
   129 NOTIFY_LEVEL_RENEW=2
 | 
| 
 | 
   130 NOTIFY_LEVEL_SKIP=3
 | 
| 
 | 
   131 
 | 
| 
 | 
   132 NOTIFY_LEVEL_DEFAULT=$NOTIFY_LEVEL_RENEW
 | 
| 
 | 
   133 
 | 
| 
 | 
   134 NOTIFY_MODE_BULK=0
 | 
| 
 | 
   135 NOTIFY_MODE_CERT=1
 | 
| 
 | 
   136 
 | 
| 
 | 
   137 NOTIFY_MODE_DEFAULT=$NOTIFY_MODE_BULK
 | 
| 
 | 
   138 
 | 
| 
 | 
   139 _DEBUG_WIKI="https://github.com/acmesh-official/acme.sh/wiki/How-to-debug-acme.sh"
 | 
| 
 | 
   140 
 | 
| 
 | 
   141 _PREPARE_LINK="https://github.com/acmesh-official/acme.sh/wiki/Install-preparations"
 | 
| 
 | 
   142 
 | 
| 
 | 
   143 _STATELESS_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Stateless-Mode"
 | 
| 
 | 
   144 
 | 
| 
 | 
   145 _DNS_ALIAS_WIKI="https://github.com/acmesh-official/acme.sh/wiki/DNS-alias-mode"
 | 
| 
 | 
   146 
 | 
| 
 | 
   147 _DNS_MANUAL_WIKI="https://github.com/acmesh-official/acme.sh/wiki/dns-manual-mode"
 | 
| 
 | 
   148 
 | 
| 
 | 
   149 _DNS_API_WIKI="https://github.com/acmesh-official/acme.sh/wiki/dnsapi"
 | 
| 
 | 
   150 
 | 
| 
 | 
   151 _NOTIFY_WIKI="https://github.com/acmesh-official/acme.sh/wiki/notify"
 | 
| 
 | 
   152 
 | 
| 
 | 
   153 _SUDO_WIKI="https://github.com/acmesh-official/acme.sh/wiki/sudo"
 | 
| 
 | 
   154 
 | 
| 
 | 
   155 _REVOKE_WIKI="https://github.com/acmesh-official/acme.sh/wiki/revokecert"
 | 
| 
 | 
   156 
 | 
| 
 | 
   157 _ZEROSSL_WIKI="https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA"
 | 
| 
 | 
   158 
 | 
| 
 | 
   159 _SERVER_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Server"
 | 
| 
 | 
   160 
 | 
| 
 | 
   161 _PREFERRED_CHAIN_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Preferred-Chain"
 | 
| 
 | 
   162 
 | 
| 
 | 
   163 _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."
 | 
| 
 | 
   164 
 | 
| 
 | 
   165 _DNS_MANUAL_WARN="It seems that you are using dns manual mode. please take care: $_DNS_MANUAL_ERR"
 | 
| 
 | 
   166 
 | 
| 
 | 
   167 _DNS_MANUAL_ERROR="It seems that you are using dns manual mode. Read this link first: $_DNS_MANUAL_WIKI"
 | 
| 
 | 
   168 
 | 
| 
 | 
   169 __INTERACTIVE=""
 | 
| 
 | 
   170 if [ -t 1 ]; then
 | 
| 
 | 
   171   __INTERACTIVE="1"
 | 
| 
 | 
   172 fi
 | 
| 
 | 
   173 
 | 
| 
 | 
   174 __green() {
 | 
| 
 | 
   175   if [ "${__INTERACTIVE}${ACME_NO_COLOR:-0}" = "10" -o "${ACME_FORCE_COLOR}" = "1" ]; then
 | 
| 
 | 
   176     printf '\33[1;32m%b\33[0m' "$1"
 | 
| 
 | 
   177     return
 | 
| 
 | 
   178   fi
 | 
| 
 | 
   179   printf -- "%b" "$1"
 | 
| 
 | 
   180 }
 | 
| 
 | 
   181 
 | 
| 
 | 
   182 __red() {
 | 
| 
 | 
   183   if [ "${__INTERACTIVE}${ACME_NO_COLOR:-0}" = "10" -o "${ACME_FORCE_COLOR}" = "1" ]; then
 | 
| 
 | 
   184     printf '\33[1;31m%b\33[0m' "$1"
 | 
| 
 | 
   185     return
 | 
| 
 | 
   186   fi
 | 
| 
 | 
   187   printf -- "%b" "$1"
 | 
| 
 | 
   188 }
 | 
| 
 | 
   189 
 | 
| 
 | 
   190 _printargs() {
 | 
| 
 | 
   191   _exitstatus="$?"
 | 
| 
 | 
   192   if [ -z "$NO_TIMESTAMP" ] || [ "$NO_TIMESTAMP" = "0" ]; then
 | 
| 
 | 
   193     printf -- "%s" "[$(date)] "
 | 
| 
 | 
   194   fi
 | 
| 
 | 
   195   if [ -z "$2" ]; then
 | 
| 
 | 
   196     printf -- "%s" "$1"
 | 
| 
 | 
   197   else
 | 
| 
 | 
   198     printf -- "%s" "$1='$2'"
 | 
| 
 | 
   199   fi
 | 
| 
 | 
   200   printf "\n"
 | 
| 
 | 
   201   # return the saved exit status
 | 
| 
 | 
   202   return "$_exitstatus"
 | 
| 
 | 
   203 }
 | 
| 
 | 
   204 
 | 
| 
 | 
   205 _dlg_versions() {
 | 
| 
 | 
   206   echo "Diagnosis versions: "
 | 
| 
 | 
   207   echo "openssl:$ACME_OPENSSL_BIN"
 | 
| 
 | 
   208   if _exists "${ACME_OPENSSL_BIN:-openssl}"; then
 | 
| 
 | 
   209     ${ACME_OPENSSL_BIN:-openssl} version 2>&1
 | 
| 
 | 
   210   else
 | 
| 
 | 
   211     echo "$ACME_OPENSSL_BIN doesn't exist."
 | 
| 
 | 
   212   fi
 | 
| 
 | 
   213 
 | 
| 
 | 
   214   echo "apache:"
 | 
| 
 | 
   215   if [ "$_APACHECTL" ] && _exists "$_APACHECTL"; then
 | 
| 
 | 
   216     $_APACHECTL -V 2>&1
 | 
| 
 | 
   217   else
 | 
| 
 | 
   218     echo "apache doesn't exist."
 | 
| 
 | 
   219   fi
 | 
| 
 | 
   220 
 | 
| 
 | 
   221   echo "nginx:"
 | 
| 
 | 
   222   if _exists "nginx"; then
 | 
| 
 | 
   223     nginx -V 2>&1
 | 
| 
 | 
   224   else
 | 
| 
 | 
   225     echo "nginx doesn't exist."
 | 
| 
 | 
   226   fi
 | 
| 
 | 
   227 
 | 
| 
 | 
   228   echo "socat:"
 | 
| 
 | 
   229   if _exists "socat"; then
 | 
| 
 | 
   230     socat -V 2>&1
 | 
| 
 | 
   231   else
 | 
| 
 | 
   232     _debug "socat doesn't exist."
 | 
| 
 | 
   233   fi
 | 
| 
 | 
   234 }
 | 
| 
 | 
   235 
 | 
| 
 | 
   236 #class
 | 
| 
 | 
   237 _syslog() {
 | 
| 
 | 
   238   _exitstatus="$?"
 | 
| 
 | 
   239   if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" = "$SYSLOG_LEVEL_NONE" ]; then
 | 
| 
 | 
   240     return
 | 
| 
 | 
   241   fi
 | 
| 
 | 
   242   _logclass="$1"
 | 
| 
 | 
   243   shift
 | 
| 
 | 
   244   if [ -z "$__logger_i" ]; then
 | 
| 
 | 
   245     if _contains "$(logger --help 2>&1)" "-i"; then
 | 
| 
 | 
   246       __logger_i="logger -i"
 | 
| 
 | 
   247     else
 | 
| 
 | 
   248       __logger_i="logger"
 | 
| 
 | 
   249     fi
 | 
| 
 | 
   250   fi
 | 
| 
 | 
   251   $__logger_i -t "$PROJECT_NAME" -p "$_logclass" "$(_printargs "$@")" >/dev/null 2>&1
 | 
| 
 | 
   252   return "$_exitstatus"
 | 
| 
 | 
   253 }
 | 
| 
 | 
   254 
 | 
| 
 | 
   255 _log() {
 | 
| 
 | 
   256   [ -z "$LOG_FILE" ] && return
 | 
| 
 | 
   257   _printargs "$@" >>"$LOG_FILE"
 | 
| 
 | 
   258 }
 | 
| 
 | 
   259 
 | 
| 
 | 
   260 _info() {
 | 
| 
 | 
   261   _log "$@"
 | 
| 
 | 
   262   if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_INFO" ]; then
 | 
| 
 | 
   263     _syslog "$SYSLOG_INFO" "$@"
 | 
| 
 | 
   264   fi
 | 
| 
 | 
   265   _printargs "$@"
 | 
| 
 | 
   266 }
 | 
| 
 | 
   267 
 | 
| 
 | 
   268 _err() {
 | 
| 
 | 
   269   _syslog "$SYSLOG_ERROR" "$@"
 | 
| 
 | 
   270   _log "$@"
 | 
| 
 | 
   271   if [ -z "$NO_TIMESTAMP" ] || [ "$NO_TIMESTAMP" = "0" ]; then
 | 
| 
 | 
   272     printf -- "%s" "[$(date)] " >&2
 | 
| 
 | 
   273   fi
 | 
| 
 | 
   274   if [ -z "$2" ]; then
 | 
| 
 | 
   275     __red "$1" >&2
 | 
| 
 | 
   276   else
 | 
| 
 | 
   277     __red "$1='$2'" >&2
 | 
| 
 | 
   278   fi
 | 
| 
 | 
   279   printf "\n" >&2
 | 
| 
 | 
   280   return 1
 | 
| 
 | 
   281 }
 | 
| 
 | 
   282 
 | 
| 
 | 
   283 _usage() {
 | 
| 
 | 
   284   __red "$@" >&2
 | 
| 
 | 
   285   printf "\n" >&2
 | 
| 
 | 
   286 }
 | 
| 
 | 
   287 
 | 
| 
 | 
   288 __debug_bash_helper() {
 | 
| 
 | 
   289   # At this point only do for --debug 3
 | 
| 
 | 
   290   if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -lt "$DEBUG_LEVEL_3" ]; then
 | 
| 
 | 
   291     return
 | 
| 
 | 
   292   fi
 | 
| 
 | 
   293   # Return extra debug info when running with bash, otherwise return empty
 | 
| 
 | 
   294   # string.
 | 
| 
 | 
   295   if [ -z "${BASH_VERSION}" ]; then
 | 
| 
 | 
   296     return
 | 
| 
 | 
   297   fi
 | 
| 
 | 
   298   # We are a bash shell at this point, return the filename, function name, and
 | 
| 
 | 
   299   # line number as a string
 | 
| 
 | 
   300   _dbh_saveIFS=$IFS
 | 
| 
 | 
   301   IFS=" "
 | 
| 
 | 
   302   # Must use eval or syntax error happens under dash. The eval should use
 | 
| 
 | 
   303   # single quotes as older versions of busybox had a bug with double quotes and
 | 
| 
 | 
   304   # eval.
 | 
| 
 | 
   305   # Use 'caller 1' as we want one level up the stack as we should be called
 | 
| 
 | 
   306   # by one of the _debug* functions
 | 
| 
 | 
   307   eval '_dbh_called=($(caller 1))'
 | 
| 
 | 
   308   IFS=$_dbh_saveIFS
 | 
| 
 | 
   309   eval '_dbh_file=${_dbh_called[2]}'
 | 
| 
 | 
   310   if [ -n "${_script_home}" ]; then
 | 
| 
 | 
   311     # Trim off the _script_home directory name
 | 
| 
 | 
   312     eval '_dbh_file=${_dbh_file#$_script_home/}'
 | 
| 
 | 
   313   fi
 | 
| 
 | 
   314   eval '_dbh_function=${_dbh_called[1]}'
 | 
| 
 | 
   315   eval '_dbh_lineno=${_dbh_called[0]}'
 | 
| 
 | 
   316   printf "%-40s " "$_dbh_file:${_dbh_function}:${_dbh_lineno}"
 | 
| 
 | 
   317 }
 | 
| 
 | 
   318 
 | 
| 
 | 
   319 _debug() {
 | 
| 
 | 
   320   if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_1" ]; then
 | 
| 
 | 
   321     _log "$@"
 | 
| 
 | 
   322   fi
 | 
| 
 | 
   323   if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG" ]; then
 | 
| 
 | 
   324     _syslog "$SYSLOG_DEBUG" "$@"
 | 
| 
 | 
   325   fi
 | 
| 
 | 
   326   if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_1" ]; then
 | 
| 
 | 
   327     _bash_debug=$(__debug_bash_helper)
 | 
| 
 | 
   328     _printargs "${_bash_debug}$@" >&2
 | 
| 
 | 
   329   fi
 | 
| 
 | 
   330 }
 | 
| 
 | 
   331 
 | 
| 
 | 
   332 #output the sensitive messages
 | 
| 
 | 
   333 _secure_debug() {
 | 
| 
 | 
   334   if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_1" ]; then
 | 
| 
 | 
   335     if [ "$OUTPUT_INSECURE" = "1" ]; then
 | 
| 
 | 
   336       _log "$@"
 | 
| 
 | 
   337     else
 | 
| 
 | 
   338       _log "$1" "$HIDDEN_VALUE"
 | 
| 
 | 
   339     fi
 | 
| 
 | 
   340   fi
 | 
| 
 | 
   341   if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG" ]; then
 | 
| 
 | 
   342     _syslog "$SYSLOG_DEBUG" "$1" "$HIDDEN_VALUE"
 | 
| 
 | 
   343   fi
 | 
| 
 | 
   344   if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_1" ]; then
 | 
| 
 | 
   345     if [ "$OUTPUT_INSECURE" = "1" ]; then
 | 
| 
 | 
   346       _printargs "$@" >&2
 | 
| 
 | 
   347     else
 | 
| 
 | 
   348       _printargs "$1" "$HIDDEN_VALUE" >&2
 | 
| 
 | 
   349     fi
 | 
| 
 | 
   350   fi
 | 
| 
 | 
   351 }
 | 
| 
 | 
   352 
 | 
| 
 | 
   353 _debug2() {
 | 
| 
 | 
   354   if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_2" ]; then
 | 
| 
 | 
   355     _log "$@"
 | 
| 
 | 
   356   fi
 | 
| 
 | 
   357   if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG_2" ]; then
 | 
| 
 | 
   358     _syslog "$SYSLOG_DEBUG" "$@"
 | 
| 
 | 
   359   fi
 | 
| 
 | 
   360   if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then
 | 
| 
 | 
   361     _bash_debug=$(__debug_bash_helper)
 | 
| 
 | 
   362     _printargs "${_bash_debug}$@" >&2
 | 
| 
 | 
   363   fi
 | 
| 
 | 
   364 }
 | 
| 
 | 
   365 
 | 
| 
 | 
   366 _secure_debug2() {
 | 
| 
 | 
   367   if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_2" ]; then
 | 
| 
 | 
   368     if [ "$OUTPUT_INSECURE" = "1" ]; then
 | 
| 
 | 
   369       _log "$@"
 | 
| 
 | 
   370     else
 | 
| 
 | 
   371       _log "$1" "$HIDDEN_VALUE"
 | 
| 
 | 
   372     fi
 | 
| 
 | 
   373   fi
 | 
| 
 | 
   374   if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG_2" ]; then
 | 
| 
 | 
   375     _syslog "$SYSLOG_DEBUG" "$1" "$HIDDEN_VALUE"
 | 
| 
 | 
   376   fi
 | 
| 
 | 
   377   if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then
 | 
| 
 | 
   378     if [ "$OUTPUT_INSECURE" = "1" ]; then
 | 
| 
 | 
   379       _printargs "$@" >&2
 | 
| 
 | 
   380     else
 | 
| 
 | 
   381       _printargs "$1" "$HIDDEN_VALUE" >&2
 | 
| 
 | 
   382     fi
 | 
| 
 | 
   383   fi
 | 
| 
 | 
   384 }
 | 
| 
 | 
   385 
 | 
| 
 | 
   386 _debug3() {
 | 
| 
 | 
   387   if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_3" ]; then
 | 
| 
 | 
   388     _log "$@"
 | 
| 
 | 
   389   fi
 | 
| 
 | 
   390   if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG_3" ]; then
 | 
| 
 | 
   391     _syslog "$SYSLOG_DEBUG" "$@"
 | 
| 
 | 
   392   fi
 | 
| 
 | 
   393   if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_3" ]; then
 | 
| 
 | 
   394     _bash_debug=$(__debug_bash_helper)
 | 
| 
 | 
   395     _printargs "${_bash_debug}$@" >&2
 | 
| 
 | 
   396   fi
 | 
| 
 | 
   397 }
 | 
| 
 | 
   398 
 | 
| 
 | 
   399 _secure_debug3() {
 | 
| 
 | 
   400   if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_3" ]; then
 | 
| 
 | 
   401     if [ "$OUTPUT_INSECURE" = "1" ]; then
 | 
| 
 | 
   402       _log "$@"
 | 
| 
 | 
   403     else
 | 
| 
 | 
   404       _log "$1" "$HIDDEN_VALUE"
 | 
| 
 | 
   405     fi
 | 
| 
 | 
   406   fi
 | 
| 
 | 
   407   if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG_3" ]; then
 | 
| 
 | 
   408     _syslog "$SYSLOG_DEBUG" "$1" "$HIDDEN_VALUE"
 | 
| 
 | 
   409   fi
 | 
| 
 | 
   410   if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_3" ]; then
 | 
| 
 | 
   411     if [ "$OUTPUT_INSECURE" = "1" ]; then
 | 
| 
 | 
   412       _printargs "$@" >&2
 | 
| 
 | 
   413     else
 | 
| 
 | 
   414       _printargs "$1" "$HIDDEN_VALUE" >&2
 | 
| 
 | 
   415     fi
 | 
| 
 | 
   416   fi
 | 
| 
 | 
   417 }
 | 
| 
 | 
   418 
 | 
| 
 | 
   419 _upper_case() {
 | 
| 
 | 
   420   # shellcheck disable=SC2018,SC2019
 | 
| 
 | 
   421   tr 'a-z' 'A-Z'
 | 
| 
 | 
   422 }
 | 
| 
 | 
   423 
 | 
| 
 | 
   424 _lower_case() {
 | 
| 
 | 
   425   # shellcheck disable=SC2018,SC2019
 | 
| 
 | 
   426   tr 'A-Z' 'a-z'
 | 
| 
 | 
   427 }
 | 
| 
 | 
   428 
 | 
| 
 | 
   429 _startswith() {
 | 
| 
 | 
   430   _str="$1"
 | 
| 
 | 
   431   _sub="$2"
 | 
| 
 | 
   432   echo "$_str" | grep "^$_sub" >/dev/null 2>&1
 | 
| 
 | 
   433 }
 | 
| 
 | 
   434 
 | 
| 
 | 
   435 _endswith() {
 | 
| 
 | 
   436   _str="$1"
 | 
| 
 | 
   437   _sub="$2"
 | 
| 
 | 
   438   echo "$_str" | grep -- "$_sub\$" >/dev/null 2>&1
 | 
| 
 | 
   439 }
 | 
| 
 | 
   440 
 | 
| 
 | 
   441 _contains() {
 | 
| 
 | 
   442   _str="$1"
 | 
| 
 | 
   443   _sub="$2"
 | 
| 
 | 
   444   echo "$_str" | grep -- "$_sub" >/dev/null 2>&1
 | 
| 
 | 
   445 }
 | 
| 
 | 
   446 
 | 
| 
 | 
   447 _hasfield() {
 | 
| 
 | 
   448   _str="$1"
 | 
| 
 | 
   449   _field="$2"
 | 
| 
 | 
   450   _sep="$3"
 | 
| 
 | 
   451   if [ -z "$_field" ]; then
 | 
| 
 | 
   452     _usage "Usage: str field  [sep]"
 | 
| 
 | 
   453     return 1
 | 
| 
 | 
   454   fi
 | 
| 
 | 
   455 
 | 
| 
 | 
   456   if [ -z "$_sep" ]; then
 | 
| 
 | 
   457     _sep=","
 | 
| 
 | 
   458   fi
 | 
| 
 | 
   459 
 | 
| 
 | 
   460   for f in $(echo "$_str" | tr "$_sep" ' '); do
 | 
| 
 | 
   461     if [ "$f" = "$_field" ]; then
 | 
| 
 | 
   462       _debug2 "'$_str' contains '$_field'"
 | 
| 
 | 
   463       return 0 #contains ok
 | 
| 
 | 
   464     fi
 | 
| 
 | 
   465   done
 | 
| 
 | 
   466   _debug2 "'$_str' does not contain '$_field'"
 | 
| 
 | 
   467   return 1 #not contains
 | 
| 
 | 
   468 }
 | 
| 
 | 
   469 
 | 
| 
 | 
   470 # str index [sep]
 | 
| 
 | 
   471 _getfield() {
 | 
| 
 | 
   472   _str="$1"
 | 
| 
 | 
   473   _findex="$2"
 | 
| 
 | 
   474   _sep="$3"
 | 
| 
 | 
   475 
 | 
| 
 | 
   476   if [ -z "$_findex" ]; then
 | 
| 
 | 
   477     _usage "Usage: str field  [sep]"
 | 
| 
 | 
   478     return 1
 | 
| 
 | 
   479   fi
 | 
| 
 | 
   480 
 | 
| 
 | 
   481   if [ -z "$_sep" ]; then
 | 
| 
 | 
   482     _sep=","
 | 
| 
 | 
   483   fi
 | 
| 
 | 
   484 
 | 
| 
 | 
   485   _ffi="$_findex"
 | 
| 
 | 
   486   while [ "$_ffi" -gt "0" ]; do
 | 
| 
 | 
   487     _fv="$(echo "$_str" | cut -d "$_sep" -f "$_ffi")"
 | 
| 
 | 
   488     if [ "$_fv" ]; then
 | 
| 
 | 
   489       printf -- "%s" "$_fv"
 | 
| 
 | 
   490       return 0
 | 
| 
 | 
   491     fi
 | 
| 
 | 
   492     _ffi="$(_math "$_ffi" - 1)"
 | 
| 
 | 
   493   done
 | 
| 
 | 
   494 
 | 
| 
 | 
   495   printf -- "%s" "$_str"
 | 
| 
 | 
   496 
 | 
| 
 | 
   497 }
 | 
| 
 | 
   498 
 | 
| 
 | 
   499 _exists() {
 | 
| 
 | 
   500   cmd="$1"
 | 
| 
 | 
   501   if [ -z "$cmd" ]; then
 | 
| 
 | 
   502     _usage "Usage: _exists cmd"
 | 
| 
 | 
   503     return 1
 | 
| 
 | 
   504   fi
 | 
| 
 | 
   505 
 | 
| 
 | 
   506   if eval type type >/dev/null 2>&1; then
 | 
| 
 | 
   507     eval type "$cmd" >/dev/null 2>&1
 | 
| 
 | 
   508   elif command >/dev/null 2>&1; then
 | 
| 
 | 
   509     command -v "$cmd" >/dev/null 2>&1
 | 
| 
 | 
   510   else
 | 
| 
 | 
   511     which "$cmd" >/dev/null 2>&1
 | 
| 
 | 
   512   fi
 | 
| 
 | 
   513   ret="$?"
 | 
| 
 | 
   514   _debug3 "$cmd exists=$ret"
 | 
| 
 | 
   515   return $ret
 | 
| 
 | 
   516 }
 | 
| 
 | 
   517 
 | 
| 
 | 
   518 #a + b
 | 
| 
 | 
   519 _math() {
 | 
| 
 | 
   520   _m_opts="$@"
 | 
| 
 | 
   521   printf "%s" "$(($_m_opts))"
 | 
| 
 | 
   522 }
 | 
| 
 | 
   523 
 | 
| 
 | 
   524 _h_char_2_dec() {
 | 
| 
 | 
   525   _ch=$1
 | 
| 
 | 
   526   case "${_ch}" in
 | 
| 
 | 
   527   a | A)
 | 
| 
 | 
   528     printf "10"
 | 
| 
 | 
   529     ;;
 | 
| 
 | 
   530   b | B)
 | 
| 
 | 
   531     printf "11"
 | 
| 
 | 
   532     ;;
 | 
| 
 | 
   533   c | C)
 | 
| 
 | 
   534     printf "12"
 | 
| 
 | 
   535     ;;
 | 
| 
 | 
   536   d | D)
 | 
| 
 | 
   537     printf "13"
 | 
| 
 | 
   538     ;;
 | 
| 
 | 
   539   e | E)
 | 
| 
 | 
   540     printf "14"
 | 
| 
 | 
   541     ;;
 | 
| 
 | 
   542   f | F)
 | 
| 
 | 
   543     printf "15"
 | 
| 
 | 
   544     ;;
 | 
| 
 | 
   545   *)
 | 
| 
 | 
   546     printf "%s" "$_ch"
 | 
| 
 | 
   547     ;;
 | 
| 
 | 
   548   esac
 | 
| 
 | 
   549 
 | 
| 
 | 
   550 }
 | 
| 
 | 
   551 
 | 
| 
 | 
   552 _URGLY_PRINTF=""
 | 
| 
 | 
   553 if [ "$(printf '\x41')" != 'A' ]; then
 | 
| 
 | 
   554   _URGLY_PRINTF=1
 | 
| 
 | 
   555 fi
 | 
| 
 | 
   556 
 | 
| 
 | 
   557 _ESCAPE_XARGS=""
 | 
| 
 | 
   558 if _exists xargs && [ "$(printf %s '\\x41' | xargs printf)" = 'A' ]; then
 | 
| 
 | 
   559   _ESCAPE_XARGS=1
 | 
| 
 | 
   560 fi
 | 
| 
 | 
   561 
 | 
| 
 | 
   562 _h2b() {
 | 
| 
 | 
   563   if _exists xxd && xxd -r -p 2>/dev/null; then
 | 
| 
 | 
   564     return
 | 
| 
 | 
   565   fi
 | 
| 
 | 
   566 
 | 
| 
 | 
   567   hex=$(cat)
 | 
| 
 | 
   568   ic=""
 | 
| 
 | 
   569   jc=""
 | 
| 
 | 
   570   _debug2 _URGLY_PRINTF "$_URGLY_PRINTF"
 | 
| 
 | 
   571   if [ -z "$_URGLY_PRINTF" ]; then
 | 
| 
 | 
   572     if [ "$_ESCAPE_XARGS" ] && _exists xargs; then
 | 
| 
 | 
   573       _debug2 "xargs"
 | 
| 
 | 
   574       echo "$hex" | _upper_case | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/g' | xargs printf
 | 
| 
 | 
   575     else
 | 
| 
 | 
   576       for h in $(echo "$hex" | _upper_case | sed 's/\([0-9A-F]\{2\}\)/ \1/g'); do
 | 
| 
 | 
   577         if [ -z "$h" ]; then
 | 
| 
 | 
   578           break
 | 
| 
 | 
   579         fi
 | 
| 
 | 
   580         printf "\x$h%s"
 | 
| 
 | 
   581       done
 | 
| 
 | 
   582     fi
 | 
| 
 | 
   583   else
 | 
| 
 | 
   584     for c in $(echo "$hex" | _upper_case | sed 's/\([0-9A-F]\)/ \1/g'); do
 | 
| 
 | 
   585       if [ -z "$ic" ]; then
 | 
| 
 | 
   586         ic=$c
 | 
| 
 | 
   587         continue
 | 
| 
 | 
   588       fi
 | 
| 
 | 
   589       jc=$c
 | 
| 
 | 
   590       ic="$(_h_char_2_dec "$ic")"
 | 
| 
 | 
   591       jc="$(_h_char_2_dec "$jc")"
 | 
| 
 | 
   592       printf '\'"$(printf "%o" "$(_math "$ic" \* 16 + $jc)")""%s"
 | 
| 
 | 
   593       ic=""
 | 
| 
 | 
   594       jc=""
 | 
| 
 | 
   595     done
 | 
| 
 | 
   596   fi
 | 
| 
 | 
   597 
 | 
| 
 | 
   598 }
 | 
| 
 | 
   599 
 | 
| 
 | 
   600 _is_solaris() {
 | 
| 
 | 
   601   _contains "${__OS__:=$(uname -a)}" "solaris" || _contains "${__OS__:=$(uname -a)}" "SunOS"
 | 
| 
 | 
   602 }
 | 
| 
 | 
   603 
 | 
| 
 | 
   604 #_ascii_hex str
 | 
| 
 | 
   605 #this can only process ascii chars, should only be used when od command is missing as a backup way.
 | 
| 
 | 
   606 _ascii_hex() {
 | 
| 
 | 
   607   _debug2 "Using _ascii_hex"
 | 
| 
 | 
   608   _str="$1"
 | 
| 
 | 
   609   _str_len=${#_str}
 | 
| 
 | 
   610   _h_i=1
 | 
| 
 | 
   611   while [ "$_h_i" -le "$_str_len" ]; do
 | 
| 
 | 
   612     _str_c="$(printf "%s" "$_str" | cut -c "$_h_i")"
 | 
| 
 | 
   613     printf " %02x" "'$_str_c"
 | 
| 
 | 
   614     _h_i="$(_math "$_h_i" + 1)"
 | 
| 
 | 
   615   done
 | 
| 
 | 
   616 }
 | 
| 
 | 
   617 
 | 
| 
 | 
   618 #stdin  output hexstr splited by one space
 | 
| 
 | 
   619 #input:"abc"
 | 
| 
 | 
   620 #output: " 61 62 63"
 | 
| 
 | 
   621 _hex_dump() {
 | 
| 
 | 
   622   if _exists od; then
 | 
| 
 | 
   623     od -A n -v -t x1 | tr -s " " | sed 's/ $//' | tr -d "\r\t\n"
 | 
| 
 | 
   624   elif _exists hexdump; then
 | 
| 
 | 
   625     _debug3 "using hexdump"
 | 
| 
 | 
   626     hexdump -v -e '/1 ""' -e '/1 " %02x" ""'
 | 
| 
 | 
   627   elif _exists xxd; then
 | 
| 
 | 
   628     _debug3 "using xxd"
 | 
| 
 | 
   629     xxd -ps -c 20 -i | sed "s/ 0x/ /g" | tr -d ",\n" | tr -s " "
 | 
| 
 | 
   630   else
 | 
| 
 | 
   631     _debug3 "using _ascii_hex"
 | 
| 
 | 
   632     str=$(cat)
 | 
| 
 | 
   633     _ascii_hex "$str"
 | 
| 
 | 
   634   fi
 | 
| 
 | 
   635 }
 | 
| 
 | 
   636 
 | 
| 
 | 
   637 #url encode, no-preserved chars
 | 
| 
 | 
   638 #A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z
 | 
| 
 | 
   639 #41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a
 | 
| 
 | 
   640 
 | 
| 
 | 
   641 #a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z
 | 
| 
 | 
   642 #61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a
 | 
| 
 | 
   643 
 | 
| 
 | 
   644 #0  1  2  3  4  5  6  7  8  9  -  _  .  ~
 | 
| 
 | 
   645 #30 31 32 33 34 35 36 37 38 39 2d 5f 2e 7e
 | 
| 
 | 
   646 
 | 
| 
 | 
   647 #stdin stdout
 | 
| 
 | 
   648 _url_encode() {
 | 
| 
 | 
   649   _hex_str=$(_hex_dump)
 | 
| 
 | 
   650   _debug3 "_url_encode"
 | 
| 
 | 
   651   _debug3 "_hex_str" "$_hex_str"
 | 
| 
 | 
   652   for _hex_code in $_hex_str; do
 | 
| 
 | 
   653     #upper case
 | 
| 
 | 
   654     case "${_hex_code}" in
 | 
| 
 | 
   655     "41")
 | 
| 
 | 
   656       printf "%s" "A"
 | 
| 
 | 
   657       ;;
 | 
| 
 | 
   658     "42")
 | 
| 
 | 
   659       printf "%s" "B"
 | 
| 
 | 
   660       ;;
 | 
| 
 | 
   661     "43")
 | 
| 
 | 
   662       printf "%s" "C"
 | 
| 
 | 
   663       ;;
 | 
| 
 | 
   664     "44")
 | 
| 
 | 
   665       printf "%s" "D"
 | 
| 
 | 
   666       ;;
 | 
| 
 | 
   667     "45")
 | 
| 
 | 
   668       printf "%s" "E"
 | 
| 
 | 
   669       ;;
 | 
| 
 | 
   670     "46")
 | 
| 
 | 
   671       printf "%s" "F"
 | 
| 
 | 
   672       ;;
 | 
| 
 | 
   673     "47")
 | 
| 
 | 
   674       printf "%s" "G"
 | 
| 
 | 
   675       ;;
 | 
| 
 | 
   676     "48")
 | 
| 
 | 
   677       printf "%s" "H"
 | 
| 
 | 
   678       ;;
 | 
| 
 | 
   679     "49")
 | 
| 
 | 
   680       printf "%s" "I"
 | 
| 
 | 
   681       ;;
 | 
| 
 | 
   682     "4a")
 | 
| 
 | 
   683       printf "%s" "J"
 | 
| 
 | 
   684       ;;
 | 
| 
 | 
   685     "4b")
 | 
| 
 | 
   686       printf "%s" "K"
 | 
| 
 | 
   687       ;;
 | 
| 
 | 
   688     "4c")
 | 
| 
 | 
   689       printf "%s" "L"
 | 
| 
 | 
   690       ;;
 | 
| 
 | 
   691     "4d")
 | 
| 
 | 
   692       printf "%s" "M"
 | 
| 
 | 
   693       ;;
 | 
| 
 | 
   694     "4e")
 | 
| 
 | 
   695       printf "%s" "N"
 | 
| 
 | 
   696       ;;
 | 
| 
 | 
   697     "4f")
 | 
| 
 | 
   698       printf "%s" "O"
 | 
| 
 | 
   699       ;;
 | 
| 
 | 
   700     "50")
 | 
| 
 | 
   701       printf "%s" "P"
 | 
| 
 | 
   702       ;;
 | 
| 
 | 
   703     "51")
 | 
| 
 | 
   704       printf "%s" "Q"
 | 
| 
 | 
   705       ;;
 | 
| 
 | 
   706     "52")
 | 
| 
 | 
   707       printf "%s" "R"
 | 
| 
 | 
   708       ;;
 | 
| 
 | 
   709     "53")
 | 
| 
 | 
   710       printf "%s" "S"
 | 
| 
 | 
   711       ;;
 | 
| 
 | 
   712     "54")
 | 
| 
 | 
   713       printf "%s" "T"
 | 
| 
 | 
   714       ;;
 | 
| 
 | 
   715     "55")
 | 
| 
 | 
   716       printf "%s" "U"
 | 
| 
 | 
   717       ;;
 | 
| 
 | 
   718     "56")
 | 
| 
 | 
   719       printf "%s" "V"
 | 
| 
 | 
   720       ;;
 | 
| 
 | 
   721     "57")
 | 
| 
 | 
   722       printf "%s" "W"
 | 
| 
 | 
   723       ;;
 | 
| 
 | 
   724     "58")
 | 
| 
 | 
   725       printf "%s" "X"
 | 
| 
 | 
   726       ;;
 | 
| 
 | 
   727     "59")
 | 
| 
 | 
   728       printf "%s" "Y"
 | 
| 
 | 
   729       ;;
 | 
| 
 | 
   730     "5a")
 | 
| 
 | 
   731       printf "%s" "Z"
 | 
| 
 | 
   732       ;;
 | 
| 
 | 
   733 
 | 
| 
 | 
   734       #lower case
 | 
| 
 | 
   735     "61")
 | 
| 
 | 
   736       printf "%s" "a"
 | 
| 
 | 
   737       ;;
 | 
| 
 | 
   738     "62")
 | 
| 
 | 
   739       printf "%s" "b"
 | 
| 
 | 
   740       ;;
 | 
| 
 | 
   741     "63")
 | 
| 
 | 
   742       printf "%s" "c"
 | 
| 
 | 
   743       ;;
 | 
| 
 | 
   744     "64")
 | 
| 
 | 
   745       printf "%s" "d"
 | 
| 
 | 
   746       ;;
 | 
| 
 | 
   747     "65")
 | 
| 
 | 
   748       printf "%s" "e"
 | 
| 
 | 
   749       ;;
 | 
| 
 | 
   750     "66")
 | 
| 
 | 
   751       printf "%s" "f"
 | 
| 
 | 
   752       ;;
 | 
| 
 | 
   753     "67")
 | 
| 
 | 
   754       printf "%s" "g"
 | 
| 
 | 
   755       ;;
 | 
| 
 | 
   756     "68")
 | 
| 
 | 
   757       printf "%s" "h"
 | 
| 
 | 
   758       ;;
 | 
| 
 | 
   759     "69")
 | 
| 
 | 
   760       printf "%s" "i"
 | 
| 
 | 
   761       ;;
 | 
| 
 | 
   762     "6a")
 | 
| 
 | 
   763       printf "%s" "j"
 | 
| 
 | 
   764       ;;
 | 
| 
 | 
   765     "6b")
 | 
| 
 | 
   766       printf "%s" "k"
 | 
| 
 | 
   767       ;;
 | 
| 
 | 
   768     "6c")
 | 
| 
 | 
   769       printf "%s" "l"
 | 
| 
 | 
   770       ;;
 | 
| 
 | 
   771     "6d")
 | 
| 
 | 
   772       printf "%s" "m"
 | 
| 
 | 
   773       ;;
 | 
| 
 | 
   774     "6e")
 | 
| 
 | 
   775       printf "%s" "n"
 | 
| 
 | 
   776       ;;
 | 
| 
 | 
   777     "6f")
 | 
| 
 | 
   778       printf "%s" "o"
 | 
| 
 | 
   779       ;;
 | 
| 
 | 
   780     "70")
 | 
| 
 | 
   781       printf "%s" "p"
 | 
| 
 | 
   782       ;;
 | 
| 
 | 
   783     "71")
 | 
| 
 | 
   784       printf "%s" "q"
 | 
| 
 | 
   785       ;;
 | 
| 
 | 
   786     "72")
 | 
| 
 | 
   787       printf "%s" "r"
 | 
| 
 | 
   788       ;;
 | 
| 
 | 
   789     "73")
 | 
| 
 | 
   790       printf "%s" "s"
 | 
| 
 | 
   791       ;;
 | 
| 
 | 
   792     "74")
 | 
| 
 | 
   793       printf "%s" "t"
 | 
| 
 | 
   794       ;;
 | 
| 
 | 
   795     "75")
 | 
| 
 | 
   796       printf "%s" "u"
 | 
| 
 | 
   797       ;;
 | 
| 
 | 
   798     "76")
 | 
| 
 | 
   799       printf "%s" "v"
 | 
| 
 | 
   800       ;;
 | 
| 
 | 
   801     "77")
 | 
| 
 | 
   802       printf "%s" "w"
 | 
| 
 | 
   803       ;;
 | 
| 
 | 
   804     "78")
 | 
| 
 | 
   805       printf "%s" "x"
 | 
| 
 | 
   806       ;;
 | 
| 
 | 
   807     "79")
 | 
| 
 | 
   808       printf "%s" "y"
 | 
| 
 | 
   809       ;;
 | 
| 
 | 
   810     "7a")
 | 
| 
 | 
   811       printf "%s" "z"
 | 
| 
 | 
   812       ;;
 | 
| 
 | 
   813       #numbers
 | 
| 
 | 
   814     "30")
 | 
| 
 | 
   815       printf "%s" "0"
 | 
| 
 | 
   816       ;;
 | 
| 
 | 
   817     "31")
 | 
| 
 | 
   818       printf "%s" "1"
 | 
| 
 | 
   819       ;;
 | 
| 
 | 
   820     "32")
 | 
| 
 | 
   821       printf "%s" "2"
 | 
| 
 | 
   822       ;;
 | 
| 
 | 
   823     "33")
 | 
| 
 | 
   824       printf "%s" "3"
 | 
| 
 | 
   825       ;;
 | 
| 
 | 
   826     "34")
 | 
| 
 | 
   827       printf "%s" "4"
 | 
| 
 | 
   828       ;;
 | 
| 
 | 
   829     "35")
 | 
| 
 | 
   830       printf "%s" "5"
 | 
| 
 | 
   831       ;;
 | 
| 
 | 
   832     "36")
 | 
| 
 | 
   833       printf "%s" "6"
 | 
| 
 | 
   834       ;;
 | 
| 
 | 
   835     "37")
 | 
| 
 | 
   836       printf "%s" "7"
 | 
| 
 | 
   837       ;;
 | 
| 
 | 
   838     "38")
 | 
| 
 | 
   839       printf "%s" "8"
 | 
| 
 | 
   840       ;;
 | 
| 
 | 
   841     "39")
 | 
| 
 | 
   842       printf "%s" "9"
 | 
| 
 | 
   843       ;;
 | 
| 
 | 
   844     "2d")
 | 
| 
 | 
   845       printf "%s" "-"
 | 
| 
 | 
   846       ;;
 | 
| 
 | 
   847     "5f")
 | 
| 
 | 
   848       printf "%s" "_"
 | 
| 
 | 
   849       ;;
 | 
| 
 | 
   850     "2e")
 | 
| 
 | 
   851       printf "%s" "."
 | 
| 
 | 
   852       ;;
 | 
| 
 | 
   853     "7e")
 | 
| 
 | 
   854       printf "%s" "~"
 | 
| 
 | 
   855       ;;
 | 
| 
 | 
   856     #other hex
 | 
| 
 | 
   857     *)
 | 
| 
 | 
   858       printf '%%%s' "$_hex_code"
 | 
| 
 | 
   859       ;;
 | 
| 
 | 
   860     esac
 | 
| 
 | 
   861   done
 | 
| 
 | 
   862 }
 | 
| 
 | 
   863 
 | 
| 
 | 
   864 _json_encode() {
 | 
| 
 | 
   865   _j_str="$(sed 's/"/\\"/g' | sed "s/\r/\\r/g")"
 | 
| 
 | 
   866   _debug3 "_json_encode"
 | 
| 
 | 
   867   _debug3 "_j_str" "$_j_str"
 | 
| 
 | 
   868   echo "$_j_str" | _hex_dump | _lower_case | sed 's/0a/5c 6e/g' | tr -d ' ' | _h2b | tr -d "\r\n"
 | 
| 
 | 
   869 }
 | 
| 
 | 
   870 
 | 
| 
 | 
   871 #from: http:\/\/  to http://
 | 
| 
 | 
   872 _json_decode() {
 | 
| 
 | 
   873   _j_str="$(sed 's#\\/#/#g')"
 | 
| 
 | 
   874   _debug3 "_json_decode"
 | 
| 
 | 
   875   _debug3 "_j_str" "$_j_str"
 | 
| 
 | 
   876   echo "$_j_str"
 | 
| 
 | 
   877 }
 | 
| 
 | 
   878 
 | 
| 
 | 
   879 #options file
 | 
| 
 | 
   880 _sed_i() {
 | 
| 
 | 
   881   options="$1"
 | 
| 
 | 
   882   filename="$2"
 | 
| 
 | 
   883   if [ -z "$filename" ]; then
 | 
| 
 | 
   884     _usage "Usage:_sed_i options filename"
 | 
| 
 | 
   885     return 1
 | 
| 
 | 
   886   fi
 | 
| 
 | 
   887   _debug2 options "$options"
 | 
| 
 | 
   888   if sed -h 2>&1 | grep "\-i\[SUFFIX]" >/dev/null 2>&1; then
 | 
| 
 | 
   889     _debug "Using sed  -i"
 | 
| 
 | 
   890     sed -i "$options" "$filename"
 | 
| 
 | 
   891   else
 | 
| 
 | 
   892     _debug "No -i support in sed"
 | 
| 
 | 
   893     text="$(cat "$filename")"
 | 
| 
 | 
   894     echo "$text" | sed "$options" >"$filename"
 | 
| 
 | 
   895   fi
 | 
| 
 | 
   896 }
 | 
| 
 | 
   897 
 | 
| 
 | 
   898 _egrep_o() {
 | 
| 
 | 
   899   if ! egrep -o "$1" 2>/dev/null; then
 | 
| 
 | 
   900     sed -n 's/.*\('"$1"'\).*/\1/p'
 | 
| 
 | 
   901   fi
 | 
| 
 | 
   902 }
 | 
| 
 | 
   903 
 | 
| 
 | 
   904 #Usage: file startline endline
 | 
| 
 | 
   905 _getfile() {
 | 
| 
 | 
   906   filename="$1"
 | 
| 
 | 
   907   startline="$2"
 | 
| 
 | 
   908   endline="$3"
 | 
| 
 | 
   909   if [ -z "$endline" ]; then
 | 
| 
 | 
   910     _usage "Usage: file startline endline"
 | 
| 
 | 
   911     return 1
 | 
| 
 | 
   912   fi
 | 
| 
 | 
   913 
 | 
| 
 | 
   914   i="$(grep -n -- "$startline" "$filename" | cut -d : -f 1)"
 | 
| 
 | 
   915   if [ -z "$i" ]; then
 | 
| 
 | 
   916     _err "Can not find start line: $startline"
 | 
| 
 | 
   917     return 1
 | 
| 
 | 
   918   fi
 | 
| 
 | 
   919   i="$(_math "$i" + 1)"
 | 
| 
 | 
   920   _debug i "$i"
 | 
| 
 | 
   921 
 | 
| 
 | 
   922   j="$(grep -n -- "$endline" "$filename" | cut -d : -f 1)"
 | 
| 
 | 
   923   if [ -z "$j" ]; then
 | 
| 
 | 
   924     _err "Can not find end line: $endline"
 | 
| 
 | 
   925     return 1
 | 
| 
 | 
   926   fi
 | 
| 
 | 
   927   j="$(_math "$j" - 1)"
 | 
| 
 | 
   928   _debug j "$j"
 | 
| 
 | 
   929 
 | 
| 
 | 
   930   sed -n "$i,${j}p" "$filename"
 | 
| 
 | 
   931 
 | 
| 
 | 
   932 }
 | 
| 
 | 
   933 
 | 
| 
 | 
   934 #Usage: multiline
 | 
| 
 | 
   935 _base64() {
 | 
| 
 | 
   936   [ "" ] #urgly
 | 
| 
 | 
   937   if [ "$1" ]; then
 | 
| 
 | 
   938     _debug3 "base64 multiline:'$1'"
 | 
| 
 | 
   939     ${ACME_OPENSSL_BIN:-openssl} base64 -e
 | 
| 
 | 
   940   else
 | 
| 
 | 
   941     _debug3 "base64 single line."
 | 
| 
 | 
   942     ${ACME_OPENSSL_BIN:-openssl} base64 -e | tr -d '\r\n'
 | 
| 
 | 
   943   fi
 | 
| 
 | 
   944 }
 | 
| 
 | 
   945 
 | 
| 
 | 
   946 #Usage: multiline
 | 
| 
 | 
   947 _dbase64() {
 | 
| 
 | 
   948   if [ "$1" ]; then
 | 
| 
 | 
   949     ${ACME_OPENSSL_BIN:-openssl} base64 -d -A
 | 
| 
 | 
   950   else
 | 
| 
 | 
   951     ${ACME_OPENSSL_BIN:-openssl} base64 -d
 | 
| 
 | 
   952   fi
 | 
| 
 | 
   953 }
 | 
| 
 | 
   954 
 | 
| 
 | 
   955 #file
 | 
| 
 | 
   956 _checkcert() {
 | 
| 
 | 
   957   _cf="$1"
 | 
| 
 | 
   958   if [ "$DEBUG" ]; then
 | 
| 
 | 
   959     ${ACME_OPENSSL_BIN:-openssl} x509 -noout -text -in "$_cf"
 | 
| 
 | 
   960   else
 | 
| 
 | 
   961     ${ACME_OPENSSL_BIN:-openssl} x509 -noout -text -in "$_cf" >/dev/null 2>&1
 | 
| 
 | 
   962   fi
 | 
| 
 | 
   963 }
 | 
| 
 | 
   964 
 | 
| 
 | 
   965 #Usage: hashalg  [outputhex]
 | 
| 
 | 
   966 #Output Base64-encoded digest
 | 
| 
 | 
   967 _digest() {
 | 
| 
 | 
   968   alg="$1"
 | 
| 
 | 
   969   if [ -z "$alg" ]; then
 | 
| 
 | 
   970     _usage "Usage: _digest hashalg"
 | 
| 
 | 
   971     return 1
 | 
| 
 | 
   972   fi
 | 
| 
 | 
   973 
 | 
| 
 | 
   974   outputhex="$2"
 | 
| 
 | 
   975 
 | 
| 
 | 
   976   if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ] || [ "$alg" = "md5" ]; then
 | 
| 
 | 
   977     if [ "$outputhex" ]; then
 | 
| 
 | 
   978       ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -hex | cut -d = -f 2 | tr -d ' '
 | 
| 
 | 
   979     else
 | 
| 
 | 
   980       ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -binary | _base64
 | 
| 
 | 
   981     fi
 | 
| 
 | 
   982   else
 | 
| 
 | 
   983     _err "$alg is not supported yet"
 | 
| 
 | 
   984     return 1
 | 
| 
 | 
   985   fi
 | 
| 
 | 
   986 
 | 
| 
 | 
   987 }
 | 
| 
 | 
   988 
 | 
| 
 | 
   989 #Usage: hashalg  secret_hex  [outputhex]
 | 
| 
 | 
   990 #Output binary hmac
 | 
| 
 | 
   991 _hmac() {
 | 
| 
 | 
   992   alg="$1"
 | 
| 
 | 
   993   secret_hex="$2"
 | 
| 
 | 
   994   outputhex="$3"
 | 
| 
 | 
   995 
 | 
| 
 | 
   996   if [ -z "$secret_hex" ]; then
 | 
| 
 | 
   997     _usage "Usage: _hmac hashalg secret [outputhex]"
 | 
| 
 | 
   998     return 1
 | 
| 
 | 
   999   fi
 | 
| 
 | 
  1000 
 | 
| 
 | 
  1001   if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ]; then
 | 
| 
 | 
  1002     if [ "$outputhex" ]; then
 | 
| 
 | 
  1003       (${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" 2>/dev/null || ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)") | cut -d = -f 2 | tr -d ' '
 | 
| 
 | 
  1004     else
 | 
| 
 | 
  1005       ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" -binary 2>/dev/null || ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)" -binary
 | 
| 
 | 
  1006     fi
 | 
| 
 | 
  1007   else
 | 
| 
 | 
  1008     _err "$alg is not supported yet"
 | 
| 
 | 
  1009     return 1
 | 
| 
 | 
  1010   fi
 | 
| 
 | 
  1011 
 | 
| 
 | 
  1012 }
 | 
| 
 | 
  1013 
 | 
| 
 | 
  1014 #Usage: keyfile hashalg
 | 
| 
 | 
  1015 #Output: Base64-encoded signature value
 | 
| 
 | 
  1016 _sign() {
 | 
| 
 | 
  1017   keyfile="$1"
 | 
| 
 | 
  1018   alg="$2"
 | 
| 
 | 
  1019   if [ -z "$alg" ]; then
 | 
| 
 | 
  1020     _usage "Usage: _sign keyfile hashalg"
 | 
| 
 | 
  1021     return 1
 | 
| 
 | 
  1022   fi
 | 
| 
 | 
  1023 
 | 
| 
 | 
  1024   _sign_openssl="${ACME_OPENSSL_BIN:-openssl} dgst -sign $keyfile "
 | 
| 
 | 
  1025 
 | 
| 
 | 
  1026   if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1 || grep "BEGIN PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
 | 
| 
 | 
  1027     $_sign_openssl -$alg | _base64
 | 
| 
 | 
  1028   elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
 | 
| 
 | 
  1029     if ! _signedECText="$($_sign_openssl -sha$__ECC_KEY_LEN | ${ACME_OPENSSL_BIN:-openssl} asn1parse -inform DER)"; then
 | 
| 
 | 
  1030       _err "Sign failed: $_sign_openssl"
 | 
| 
 | 
  1031       _err "Key file: $keyfile"
 | 
| 
 | 
  1032       _err "Key content:$(wc -l <"$keyfile") lines"
 | 
| 
 | 
  1033       return 1
 | 
| 
 | 
  1034     fi
 | 
| 
 | 
  1035     _debug3 "_signedECText" "$_signedECText"
 | 
| 
 | 
  1036     _ec_r="$(echo "$_signedECText" | _head_n 2 | _tail_n 1 | cut -d : -f 4 | tr -d "\r\n")"
 | 
| 
 | 
  1037     _ec_s="$(echo "$_signedECText" | _head_n 3 | _tail_n 1 | cut -d : -f 4 | tr -d "\r\n")"
 | 
| 
 | 
  1038     if [ "$__ECC_KEY_LEN" -eq "256" ]; then
 | 
| 
 | 
  1039       while [ "${#_ec_r}" -lt "64" ]; do
 | 
| 
 | 
  1040         _ec_r="0${_ec_r}"
 | 
| 
 | 
  1041       done
 | 
| 
 | 
  1042       while [ "${#_ec_s}" -lt "64" ]; do
 | 
| 
 | 
  1043         _ec_s="0${_ec_s}"
 | 
| 
 | 
  1044       done
 | 
| 
 | 
  1045     fi
 | 
| 
 | 
  1046     if [ "$__ECC_KEY_LEN" -eq "384" ]; then
 | 
| 
 | 
  1047       while [ "${#_ec_r}" -lt "96" ]; do
 | 
| 
 | 
  1048         _ec_r="0${_ec_r}"
 | 
| 
 | 
  1049       done
 | 
| 
 | 
  1050       while [ "${#_ec_s}" -lt "96" ]; do
 | 
| 
 | 
  1051         _ec_s="0${_ec_s}"
 | 
| 
 | 
  1052       done
 | 
| 
 | 
  1053     fi
 | 
| 
 | 
  1054     if [ "$__ECC_KEY_LEN" -eq "512" ]; then
 | 
| 
 | 
  1055       while [ "${#_ec_r}" -lt "132" ]; do
 | 
| 
 | 
  1056         _ec_r="0${_ec_r}"
 | 
| 
 | 
  1057       done
 | 
| 
 | 
  1058       while [ "${#_ec_s}" -lt "132" ]; do
 | 
| 
 | 
  1059         _ec_s="0${_ec_s}"
 | 
| 
 | 
  1060       done
 | 
| 
 | 
  1061     fi
 | 
| 
 | 
  1062     _debug3 "_ec_r" "$_ec_r"
 | 
| 
 | 
  1063     _debug3 "_ec_s" "$_ec_s"
 | 
| 
 | 
  1064     printf "%s" "$_ec_r$_ec_s" | _h2b | _base64
 | 
| 
 | 
  1065   else
 | 
| 
 | 
  1066     _err "Unknown key file format."
 | 
| 
 | 
  1067     return 1
 | 
| 
 | 
  1068   fi
 | 
| 
 | 
  1069 
 | 
| 
 | 
  1070 }
 | 
| 
 | 
  1071 
 | 
| 
 | 
  1072 #keylength or isEcc flag (empty str => not ecc)
 | 
| 
 | 
  1073 _isEccKey() {
 | 
| 
 | 
  1074   _length="$1"
 | 
| 
 | 
  1075 
 | 
| 
 | 
  1076   if [ -z "$_length" ]; then
 | 
| 
 | 
  1077     return 1
 | 
| 
 | 
  1078   fi
 | 
| 
 | 
  1079 
 | 
| 
 | 
  1080   [ "$_length" != "1024" ] &&
 | 
| 
 | 
  1081     [ "$_length" != "2048" ] &&
 | 
| 
 | 
  1082     [ "$_length" != "3072" ] &&
 | 
| 
 | 
  1083     [ "$_length" != "4096" ] &&
 | 
| 
 | 
  1084     [ "$_length" != "8192" ]
 | 
| 
 | 
  1085 }
 | 
| 
 | 
  1086 
 | 
| 
 | 
  1087 # _createkey  2048|ec-256   file
 | 
| 
 | 
  1088 _createkey() {
 | 
| 
 | 
  1089   length="$1"
 | 
| 
 | 
  1090   f="$2"
 | 
| 
 | 
  1091   _debug2 "_createkey for file:$f"
 | 
| 
 | 
  1092   eccname="$length"
 | 
| 
 | 
  1093   if _startswith "$length" "ec-"; then
 | 
| 
 | 
  1094     length=$(printf "%s" "$length" | cut -d '-' -f 2-100)
 | 
| 
 | 
  1095 
 | 
| 
 | 
  1096     if [ "$length" = "256" ]; then
 | 
| 
 | 
  1097       eccname="prime256v1"
 | 
| 
 | 
  1098     fi
 | 
| 
 | 
  1099     if [ "$length" = "384" ]; then
 | 
| 
 | 
  1100       eccname="secp384r1"
 | 
| 
 | 
  1101     fi
 | 
| 
 | 
  1102     if [ "$length" = "521" ]; then
 | 
| 
 | 
  1103       eccname="secp521r1"
 | 
| 
 | 
  1104     fi
 | 
| 
 | 
  1105 
 | 
| 
 | 
  1106   fi
 | 
| 
 | 
  1107 
 | 
| 
 | 
  1108   if [ -z "$length" ]; then
 | 
| 
 | 
  1109     length=2048
 | 
| 
 | 
  1110   fi
 | 
| 
 | 
  1111 
 | 
| 
 | 
  1112   _debug "Use length $length"
 | 
| 
 | 
  1113 
 | 
| 
 | 
  1114   if ! touch "$f" >/dev/null 2>&1; then
 | 
| 
 | 
  1115     _f_path="$(dirname "$f")"
 | 
| 
 | 
  1116     _debug _f_path "$_f_path"
 | 
| 
 | 
  1117     if ! mkdir -p "$_f_path"; then
 | 
| 
 | 
  1118       _err "Can not create path: $_f_path"
 | 
| 
 | 
  1119       return 1
 | 
| 
 | 
  1120     fi
 | 
| 
 | 
  1121   fi
 | 
| 
 | 
  1122 
 | 
| 
 | 
  1123   if _isEccKey "$length"; then
 | 
| 
 | 
  1124     _debug "Using ec name: $eccname"
 | 
| 
 | 
  1125     if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -genkey 2>/dev/null)"; then
 | 
| 
 | 
  1126       echo "$_opkey" >"$f"
 | 
| 
 | 
  1127     else
 | 
| 
 | 
  1128       _err "error ecc key name: $eccname"
 | 
| 
 | 
  1129       return 1
 | 
| 
 | 
  1130     fi
 | 
| 
 | 
  1131   else
 | 
| 
 | 
  1132     _debug "Using RSA: $length"
 | 
| 
 | 
  1133     if _opkey="$(${ACME_OPENSSL_BIN:-openssl} genrsa "$length" 2>/dev/null)"; then
 | 
| 
 | 
  1134       echo "$_opkey" >"$f"
 | 
| 
 | 
  1135     else
 | 
| 
 | 
  1136       _err "error rsa key: $length"
 | 
| 
 | 
  1137       return 1
 | 
| 
 | 
  1138     fi
 | 
| 
 | 
  1139   fi
 | 
| 
 | 
  1140 
 | 
| 
 | 
  1141   if [ "$?" != "0" ]; then
 | 
| 
 | 
  1142     _err "Create key error."
 | 
| 
 | 
  1143     return 1
 | 
| 
 | 
  1144   fi
 | 
| 
 | 
  1145 }
 | 
| 
 | 
  1146 
 | 
| 
 | 
  1147 #domain
 | 
| 
 | 
  1148 _is_idn() {
 | 
| 
 | 
  1149   _is_idn_d="$1"
 | 
| 
 | 
  1150   _debug2 _is_idn_d "$_is_idn_d"
 | 
| 
 | 
  1151   _idn_temp=$(printf "%s" "$_is_idn_d" | tr -d '0-9' | tr -d 'a-z' | tr -d 'A-Z' | tr -d '*.,-_')
 | 
| 
 | 
  1152   _debug2 _idn_temp "$_idn_temp"
 | 
| 
 | 
  1153   [ "$_idn_temp" ]
 | 
| 
 | 
  1154 }
 | 
| 
 | 
  1155 
 | 
| 
 | 
  1156 #aa.com
 | 
| 
 | 
  1157 #aa.com,bb.com,cc.com
 | 
| 
 | 
  1158 _idn() {
 | 
| 
 | 
  1159   __idn_d="$1"
 | 
| 
 | 
  1160   if ! _is_idn "$__idn_d"; then
 | 
| 
 | 
  1161     printf "%s" "$__idn_d"
 | 
| 
 | 
  1162     return 0
 | 
| 
 | 
  1163   fi
 | 
| 
 | 
  1164 
 | 
| 
 | 
  1165   if _exists idn; then
 | 
| 
 | 
  1166     if _contains "$__idn_d" ','; then
 | 
| 
 | 
  1167       _i_first="1"
 | 
| 
 | 
  1168       for f in $(echo "$__idn_d" | tr ',' ' '); do
 | 
| 
 | 
  1169         [ -z "$f" ] && continue
 | 
| 
 | 
  1170         if [ -z "$_i_first" ]; then
 | 
| 
 | 
  1171           printf "%s" ","
 | 
| 
 | 
  1172         else
 | 
| 
 | 
  1173           _i_first=""
 | 
| 
 | 
  1174         fi
 | 
| 
 | 
  1175         idn --quiet "$f" | tr -d "\r\n"
 | 
| 
 | 
  1176       done
 | 
| 
 | 
  1177     else
 | 
| 
 | 
  1178       idn "$__idn_d" | tr -d "\r\n"
 | 
| 
 | 
  1179     fi
 | 
| 
 | 
  1180   else
 | 
| 
 | 
  1181     _err "Please install idn to process IDN names."
 | 
| 
 | 
  1182   fi
 | 
| 
 | 
  1183 }
 | 
| 
 | 
  1184 
 | 
| 
 | 
  1185 #_createcsr  cn  san_list  keyfile csrfile conf acmeValidationv1
 | 
| 
 | 
  1186 _createcsr() {
 | 
| 
 | 
  1187   _debug _createcsr
 | 
| 
 | 
  1188   domain="$1"
 | 
| 
 | 
  1189   domainlist="$2"
 | 
| 
 | 
  1190   csrkey="$3"
 | 
| 
 | 
  1191   csr="$4"
 | 
| 
 | 
  1192   csrconf="$5"
 | 
| 
 | 
  1193   acmeValidationv1="$6"
 | 
| 
 | 
  1194   _debug2 domain "$domain"
 | 
| 
 | 
  1195   _debug2 domainlist "$domainlist"
 | 
| 
 | 
  1196   _debug2 csrkey "$csrkey"
 | 
| 
 | 
  1197   _debug2 csr "$csr"
 | 
| 
 | 
  1198   _debug2 csrconf "$csrconf"
 | 
| 
 | 
  1199 
 | 
| 
 | 
  1200   printf "[ req_distinguished_name ]\n[ req ]\ndistinguished_name = req_distinguished_name\nreq_extensions = v3_req\n[ v3_req ]\n\nkeyUsage = nonRepudiation, digitalSignature, keyEncipherment" >"$csrconf"
 | 
| 
 | 
  1201 
 | 
| 
 | 
  1202   if [ "$acmeValidationv1" ]; then
 | 
| 
 | 
  1203     domainlist="$(_idn "$domainlist")"
 | 
| 
 | 
  1204     printf -- "\nsubjectAltName=DNS:$domainlist" >>"$csrconf"
 | 
| 
 | 
  1205   elif [ -z "$domainlist" ] || [ "$domainlist" = "$NO_VALUE" ]; then
 | 
| 
 | 
  1206     #single domain
 | 
| 
 | 
  1207     _info "Single domain" "$domain"
 | 
| 
 | 
  1208     printf -- "\nsubjectAltName=DNS:$(_idn "$domain")" >>"$csrconf"
 | 
| 
 | 
  1209   else
 | 
| 
 | 
  1210     domainlist="$(_idn "$domainlist")"
 | 
| 
 | 
  1211     _debug2 domainlist "$domainlist"
 | 
| 
 | 
  1212     if _contains "$domainlist" ","; then
 | 
| 
 | 
  1213       alt="DNS:$(_idn "$domain"),DNS:$(echo "$domainlist" | sed "s/,,/,/g" | sed "s/,/,DNS:/g")"
 | 
| 
 | 
  1214     else
 | 
| 
 | 
  1215       alt="DNS:$(_idn "$domain"),DNS:$domainlist"
 | 
| 
 | 
  1216     fi
 | 
| 
 | 
  1217     #multi
 | 
| 
 | 
  1218     _info "Multi domain" "$alt"
 | 
| 
 | 
  1219     printf -- "\nsubjectAltName=$alt" >>"$csrconf"
 | 
| 
 | 
  1220   fi
 | 
| 
 | 
  1221   if [ "$Le_OCSP_Staple" = "1" ]; then
 | 
| 
 | 
  1222     _savedomainconf Le_OCSP_Staple "$Le_OCSP_Staple"
 | 
| 
 | 
  1223     printf -- "\nbasicConstraints = CA:FALSE\n1.3.6.1.5.5.7.1.24=DER:30:03:02:01:05" >>"$csrconf"
 | 
| 
 | 
  1224   fi
 | 
| 
 | 
  1225 
 | 
| 
 | 
  1226   if [ "$acmeValidationv1" ]; then
 | 
| 
 | 
  1227     printf "\n1.3.6.1.5.5.7.1.31=critical,DER:04:20:${acmeValidationv1}" >>"${csrconf}"
 | 
| 
 | 
  1228   fi
 | 
| 
 | 
  1229 
 | 
| 
 | 
  1230   _csr_cn="$(_idn "$domain")"
 | 
| 
 | 
  1231   _debug2 _csr_cn "$_csr_cn"
 | 
| 
 | 
  1232   if _contains "$(uname -a)" "MINGW"; then
 | 
| 
 | 
  1233     ${ACME_OPENSSL_BIN:-openssl} req -new -sha256 -key "$csrkey" -subj "//CN=$_csr_cn" -config "$csrconf" -out "$csr"
 | 
| 
 | 
  1234   else
 | 
| 
 | 
  1235     ${ACME_OPENSSL_BIN:-openssl} req -new -sha256 -key "$csrkey" -subj "/CN=$_csr_cn" -config "$csrconf" -out "$csr"
 | 
| 
 | 
  1236   fi
 | 
| 
 | 
  1237 }
 | 
| 
 | 
  1238 
 | 
| 
 | 
  1239 #_signcsr key  csr  conf cert
 | 
| 
 | 
  1240 _signcsr() {
 | 
| 
 | 
  1241   key="$1"
 | 
| 
 | 
  1242   csr="$2"
 | 
| 
 | 
  1243   conf="$3"
 | 
| 
 | 
  1244   cert="$4"
 | 
| 
 | 
  1245   _debug "_signcsr"
 | 
| 
 | 
  1246 
 | 
| 
 | 
  1247   _msg="$(${ACME_OPENSSL_BIN:-openssl} x509 -req -days 365 -in "$csr" -signkey "$key" -extensions v3_req -extfile "$conf" -out "$cert" 2>&1)"
 | 
| 
 | 
  1248   _ret="$?"
 | 
| 
 | 
  1249   _debug "$_msg"
 | 
| 
 | 
  1250   return $_ret
 | 
| 
 | 
  1251 }
 | 
| 
 | 
  1252 
 | 
| 
 | 
  1253 #_csrfile
 | 
| 
 | 
  1254 _readSubjectFromCSR() {
 | 
| 
 | 
  1255   _csrfile="$1"
 | 
| 
 | 
  1256   if [ -z "$_csrfile" ]; then
 | 
| 
 | 
  1257     _usage "_readSubjectFromCSR mycsr.csr"
 | 
| 
 | 
  1258     return 1
 | 
| 
 | 
  1259   fi
 | 
| 
 | 
  1260   ${ACME_OPENSSL_BIN:-openssl} req -noout -in "$_csrfile" -subject | tr ',' "\n" | _egrep_o "CN *=.*" | cut -d = -f 2 | cut -d / -f 1 | tr -d ' \n'
 | 
| 
 | 
  1261 }
 | 
| 
 | 
  1262 
 | 
| 
 | 
  1263 #_csrfile
 | 
| 
 | 
  1264 #echo comma separated domain list
 | 
| 
 | 
  1265 _readSubjectAltNamesFromCSR() {
 | 
| 
 | 
  1266   _csrfile="$1"
 | 
| 
 | 
  1267   if [ -z "$_csrfile" ]; then
 | 
| 
 | 
  1268     _usage "_readSubjectAltNamesFromCSR mycsr.csr"
 | 
| 
 | 
  1269     return 1
 | 
| 
 | 
  1270   fi
 | 
| 
 | 
  1271 
 | 
| 
 | 
  1272   _csrsubj="$(_readSubjectFromCSR "$_csrfile")"
 | 
| 
 | 
  1273   _debug _csrsubj "$_csrsubj"
 | 
| 
 | 
  1274 
 | 
| 
 | 
  1275   _dnsAltnames="$(${ACME_OPENSSL_BIN:-openssl} req -noout -text -in "$_csrfile" | grep "^ *DNS:.*" | tr -d ' \n')"
 | 
| 
 | 
  1276   _debug _dnsAltnames "$_dnsAltnames"
 | 
| 
 | 
  1277 
 | 
| 
 | 
  1278   if _contains "$_dnsAltnames," "DNS:$_csrsubj,"; then
 | 
| 
 | 
  1279     _debug "AltNames contains subject"
 | 
| 
 | 
  1280     _excapedAlgnames="$(echo "$_dnsAltnames" | tr '*' '#')"
 | 
| 
 | 
  1281     _debug _excapedAlgnames "$_excapedAlgnames"
 | 
| 
 | 
  1282     _escapedSubject="$(echo "$_csrsubj" | tr '*' '#')"
 | 
| 
 | 
  1283     _debug _escapedSubject "$_escapedSubject"
 | 
| 
 | 
  1284     _dnsAltnames="$(echo "$_excapedAlgnames," | sed "s/DNS:$_escapedSubject,//g" | tr '#' '*' | sed "s/,\$//g")"
 | 
| 
 | 
  1285     _debug _dnsAltnames "$_dnsAltnames"
 | 
| 
 | 
  1286   else
 | 
| 
 | 
  1287     _debug "AltNames doesn't contain subject"
 | 
| 
 | 
  1288   fi
 | 
| 
 | 
  1289 
 | 
| 
 | 
  1290   echo "$_dnsAltnames" | sed "s/DNS://g"
 | 
| 
 | 
  1291 }
 | 
| 
 | 
  1292 
 | 
| 
 | 
  1293 #_csrfile
 | 
| 
 | 
  1294 _readKeyLengthFromCSR() {
 | 
| 
 | 
  1295   _csrfile="$1"
 | 
| 
 | 
  1296   if [ -z "$_csrfile" ]; then
 | 
| 
 | 
  1297     _usage "_readKeyLengthFromCSR mycsr.csr"
 | 
| 
 | 
  1298     return 1
 | 
| 
 | 
  1299   fi
 | 
| 
 | 
  1300 
 | 
| 
 | 
  1301   _outcsr="$(${ACME_OPENSSL_BIN:-openssl} req -noout -text -in "$_csrfile")"
 | 
| 
 | 
  1302   _debug2 _outcsr "$_outcsr"
 | 
| 
 | 
  1303   if _contains "$_outcsr" "Public Key Algorithm: id-ecPublicKey"; then
 | 
| 
 | 
  1304     _debug "ECC CSR"
 | 
| 
 | 
  1305     echo "$_outcsr" | tr "\t" " " | _egrep_o "^ *ASN1 OID:.*" | cut -d ':' -f 2 | tr -d ' '
 | 
| 
 | 
  1306   else
 | 
| 
 | 
  1307     _debug "RSA CSR"
 | 
| 
 | 
  1308     _rkl="$(echo "$_outcsr" | tr "\t" " " | _egrep_o "^ *Public.Key:.*" | cut -d '(' -f 2 | cut -d ' ' -f 1)"
 | 
| 
 | 
  1309     if [ "$_rkl" ]; then
 | 
| 
 | 
  1310       echo "$_rkl"
 | 
| 
 | 
  1311     else
 | 
| 
 | 
  1312       echo "$_outcsr" | tr "\t" " " | _egrep_o "RSA Public.Key:.*" | cut -d '(' -f 2 | cut -d ' ' -f 1
 | 
| 
 | 
  1313     fi
 | 
| 
 | 
  1314   fi
 | 
| 
 | 
  1315 }
 | 
| 
 | 
  1316 
 | 
| 
 | 
  1317 _ss() {
 | 
| 
 | 
  1318   _port="$1"
 | 
| 
 | 
  1319 
 | 
| 
 | 
  1320   if _exists "ss"; then
 | 
| 
 | 
  1321     _debug "Using: ss"
 | 
| 
 | 
  1322     ss -ntpl 2>/dev/null | grep ":$_port "
 | 
| 
 | 
  1323     return 0
 | 
| 
 | 
  1324   fi
 | 
| 
 | 
  1325 
 | 
| 
 | 
  1326   if _exists "netstat"; then
 | 
| 
 | 
  1327     _debug "Using: netstat"
 | 
| 
 | 
  1328     if netstat -help 2>&1 | grep "\-p proto" >/dev/null; then
 | 
| 
 | 
  1329       #for windows version netstat tool
 | 
| 
 | 
  1330       netstat -an -p tcp | grep "LISTENING" | grep ":$_port "
 | 
| 
 | 
  1331     else
 | 
| 
 | 
  1332       if netstat -help 2>&1 | grep "\-p protocol" >/dev/null; then
 | 
| 
 | 
  1333         netstat -an -p tcp | grep LISTEN | grep ":$_port "
 | 
| 
 | 
  1334       elif netstat -help 2>&1 | grep -- '-P protocol' >/dev/null; then
 | 
| 
 | 
  1335         #for solaris
 | 
| 
 | 
  1336         netstat -an -P tcp | grep "\.$_port " | grep "LISTEN"
 | 
| 
 | 
  1337       elif netstat -help 2>&1 | grep "\-p" >/dev/null; then
 | 
| 
 | 
  1338         #for full linux
 | 
| 
 | 
  1339         netstat -ntpl | grep ":$_port "
 | 
| 
 | 
  1340       else
 | 
| 
 | 
  1341         #for busybox (embedded linux; no pid support)
 | 
| 
 | 
  1342         netstat -ntl 2>/dev/null | grep ":$_port "
 | 
| 
 | 
  1343       fi
 | 
| 
 | 
  1344     fi
 | 
| 
 | 
  1345     return 0
 | 
| 
 | 
  1346   fi
 | 
| 
 | 
  1347 
 | 
| 
 | 
  1348   return 1
 | 
| 
 | 
  1349 }
 | 
| 
 | 
  1350 
 | 
| 
 | 
  1351 #outfile key cert cacert [password [name [caname]]]
 | 
| 
 | 
  1352 _toPkcs() {
 | 
| 
 | 
  1353   _cpfx="$1"
 | 
| 
 | 
  1354   _ckey="$2"
 | 
| 
 | 
  1355   _ccert="$3"
 | 
| 
 | 
  1356   _cca="$4"
 | 
| 
 | 
  1357   pfxPassword="$5"
 | 
| 
 | 
  1358   pfxName="$6"
 | 
| 
 | 
  1359   pfxCaname="$7"
 | 
| 
 | 
  1360 
 | 
| 
 | 
  1361   if [ "$pfxCaname" ]; then
 | 
| 
 | 
  1362     ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" -password "pass:$pfxPassword" -name "$pfxName" -caname "$pfxCaname"
 | 
| 
 | 
  1363   elif [ "$pfxName" ]; then
 | 
| 
 | 
  1364     ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" -password "pass:$pfxPassword" -name "$pfxName"
 | 
| 
 | 
  1365   elif [ "$pfxPassword" ]; then
 | 
| 
 | 
  1366     ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" -password "pass:$pfxPassword"
 | 
| 
 | 
  1367   else
 | 
| 
 | 
  1368     ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca"
 | 
| 
 | 
  1369   fi
 | 
| 
 | 
  1370 
 | 
| 
 | 
  1371 }
 | 
| 
 | 
  1372 
 | 
| 
 | 
  1373 #domain [password] [isEcc]
 | 
| 
 | 
  1374 toPkcs() {
 | 
| 
 | 
  1375   domain="$1"
 | 
| 
 | 
  1376   pfxPassword="$2"
 | 
| 
 | 
  1377   if [ -z "$domain" ]; then
 | 
| 
 | 
  1378     _usage "Usage: $PROJECT_ENTRY --to-pkcs12 --domain <domain.tld> [--password <password>] [--ecc]"
 | 
| 
 | 
  1379     return 1
 | 
| 
 | 
  1380   fi
 | 
| 
 | 
  1381 
 | 
| 
 | 
  1382   _isEcc="$3"
 | 
| 
 | 
  1383 
 | 
| 
 | 
  1384   _initpath "$domain" "$_isEcc"
 | 
| 
 | 
  1385 
 | 
| 
 | 
  1386   _toPkcs "$CERT_PFX_PATH" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$pfxPassword"
 | 
| 
 | 
  1387 
 | 
| 
 | 
  1388   if [ "$?" = "0" ]; then
 | 
| 
 | 
  1389     _info "Success, Pfx is exported to: $CERT_PFX_PATH"
 | 
| 
 | 
  1390   fi
 | 
| 
 | 
  1391 
 | 
| 
 | 
  1392 }
 | 
| 
 | 
  1393 
 | 
| 
 | 
  1394 #domain [isEcc]
 | 
| 
 | 
  1395 toPkcs8() {
 | 
| 
 | 
  1396   domain="$1"
 | 
| 
 | 
  1397 
 | 
| 
 | 
  1398   if [ -z "$domain" ]; then
 | 
| 
 | 
  1399     _usage "Usage: $PROJECT_ENTRY --to-pkcs8 --domain <domain.tld> [--ecc]"
 | 
| 
 | 
  1400     return 1
 | 
| 
 | 
  1401   fi
 | 
| 
 | 
  1402 
 | 
| 
 | 
  1403   _isEcc="$2"
 | 
| 
 | 
  1404 
 | 
| 
 | 
  1405   _initpath "$domain" "$_isEcc"
 | 
| 
 | 
  1406 
 | 
| 
 | 
  1407   ${ACME_OPENSSL_BIN:-openssl} pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in "$CERT_KEY_PATH" -out "$CERT_PKCS8_PATH"
 | 
| 
 | 
  1408 
 | 
| 
 | 
  1409   if [ "$?" = "0" ]; then
 | 
| 
 | 
  1410     _info "Success, $CERT_PKCS8_PATH"
 | 
| 
 | 
  1411   fi
 | 
| 
 | 
  1412 
 | 
| 
 | 
  1413 }
 | 
| 
 | 
  1414 
 | 
| 
 | 
  1415 #[2048]
 | 
| 
 | 
  1416 createAccountKey() {
 | 
| 
 | 
  1417   _info "Creating account key"
 | 
| 
 | 
  1418   if [ -z "$1" ]; then
 | 
| 
 | 
  1419     _usage "Usage: $PROJECT_ENTRY --create-account-key [--accountkeylength <bits>]"
 | 
| 
 | 
  1420     return
 | 
| 
 | 
  1421   fi
 | 
| 
 | 
  1422 
 | 
| 
 | 
  1423   length=$1
 | 
| 
 | 
  1424   _create_account_key "$length"
 | 
| 
 | 
  1425 
 | 
| 
 | 
  1426 }
 | 
| 
 | 
  1427 
 | 
| 
 | 
  1428 _create_account_key() {
 | 
| 
 | 
  1429 
 | 
| 
 | 
  1430   length=$1
 | 
| 
 | 
  1431 
 | 
| 
 | 
  1432   if [ -z "$length" ] || [ "$length" = "$NO_VALUE" ]; then
 | 
| 
 | 
  1433     _debug "Use default length $DEFAULT_ACCOUNT_KEY_LENGTH"
 | 
| 
 | 
  1434     length="$DEFAULT_ACCOUNT_KEY_LENGTH"
 | 
| 
 | 
  1435   fi
 | 
| 
 | 
  1436 
 | 
| 
 | 
  1437   _debug length "$length"
 | 
| 
 | 
  1438   _initpath
 | 
| 
 | 
  1439 
 | 
| 
 | 
  1440   mkdir -p "$CA_DIR"
 | 
| 
 | 
  1441   if [ -s "$ACCOUNT_KEY_PATH" ]; then
 | 
| 
 | 
  1442     _info "Account key exists, skip"
 | 
| 
 | 
  1443     return 0
 | 
| 
 | 
  1444   else
 | 
| 
 | 
  1445     #generate account key
 | 
| 
 | 
  1446     if _createkey "$length" "$ACCOUNT_KEY_PATH"; then
 | 
| 
 | 
  1447       chmod 600 "$ACCOUNT_KEY_PATH"
 | 
| 
 | 
  1448       _info "Create account key ok."
 | 
| 
 | 
  1449       return 0
 | 
| 
 | 
  1450     else
 | 
| 
 | 
  1451       _err "Create account key error."
 | 
| 
 | 
  1452       return 1
 | 
| 
 | 
  1453     fi
 | 
| 
 | 
  1454   fi
 | 
| 
 | 
  1455 
 | 
| 
 | 
  1456 }
 | 
| 
 | 
  1457 
 | 
| 
 | 
  1458 #domain [length]
 | 
| 
 | 
  1459 createDomainKey() {
 | 
| 
 | 
  1460   _info "Creating domain key"
 | 
| 
 | 
  1461   if [ -z "$1" ]; then
 | 
| 
 | 
  1462     _usage "Usage: $PROJECT_ENTRY --create-domain-key --domain <domain.tld> [--keylength <bits>]"
 | 
| 
 | 
  1463     return
 | 
| 
 | 
  1464   fi
 | 
| 
 | 
  1465 
 | 
| 
 | 
  1466   domain=$1
 | 
| 
 | 
  1467   _cdl=$2
 | 
| 
 | 
  1468 
 | 
| 
 | 
  1469   if [ -z "$_cdl" ]; then
 | 
| 
 | 
  1470     _debug "Use DEFAULT_DOMAIN_KEY_LENGTH=$DEFAULT_DOMAIN_KEY_LENGTH"
 | 
| 
 | 
  1471     _cdl="$DEFAULT_DOMAIN_KEY_LENGTH"
 | 
| 
 | 
  1472   fi
 | 
| 
 | 
  1473 
 | 
| 
 | 
  1474   _initpath "$domain" "$_cdl"
 | 
| 
 | 
  1475 
 | 
| 
 | 
  1476   if [ ! -f "$CERT_KEY_PATH" ] || [ ! -s "$CERT_KEY_PATH" ] || ([ "$FORCE" ] && ! [ "$_ACME_IS_RENEW" ]) || [ "$Le_ForceNewDomainKey" = "1" ]; then
 | 
| 
 | 
  1477     if _createkey "$_cdl" "$CERT_KEY_PATH"; then
 | 
| 
 | 
  1478       _savedomainconf Le_Keylength "$_cdl"
 | 
| 
 | 
  1479       _info "The domain key is here: $(__green $CERT_KEY_PATH)"
 | 
| 
 | 
  1480       return 0
 | 
| 
 | 
  1481     else
 | 
| 
 | 
  1482       _err "Can not create domain key"
 | 
| 
 | 
  1483       return 1
 | 
| 
 | 
  1484     fi
 | 
| 
 | 
  1485   else
 | 
| 
 | 
  1486     if [ "$_ACME_IS_RENEW" ]; then
 | 
| 
 | 
  1487       _info "Domain key exists, skip"
 | 
| 
 | 
  1488       return 0
 | 
| 
 | 
  1489     else
 | 
| 
 | 
  1490       _err "Domain key exists, do you want to overwrite the key?"
 | 
| 
 | 
  1491       _err "Add '--force', and try again."
 | 
| 
 | 
  1492       return 1
 | 
| 
 | 
  1493     fi
 | 
| 
 | 
  1494   fi
 | 
| 
 | 
  1495 
 | 
| 
 | 
  1496 }
 | 
| 
 | 
  1497 
 | 
| 
 | 
  1498 # domain  domainlist isEcc
 | 
| 
 | 
  1499 createCSR() {
 | 
| 
 | 
  1500   _info "Creating csr"
 | 
| 
 | 
  1501   if [ -z "$1" ]; then
 | 
| 
 | 
  1502     _usage "Usage: $PROJECT_ENTRY --create-csr --domain <domain.tld> [--domain <domain2.tld> ...]"
 | 
| 
 | 
  1503     return
 | 
| 
 | 
  1504   fi
 | 
| 
 | 
  1505 
 | 
| 
 | 
  1506   domain="$1"
 | 
| 
 | 
  1507   domainlist="$2"
 | 
| 
 | 
  1508   _isEcc="$3"
 | 
| 
 | 
  1509 
 | 
| 
 | 
  1510   _initpath "$domain" "$_isEcc"
 | 
| 
 | 
  1511 
 | 
| 
 | 
  1512   if [ -f "$CSR_PATH" ] && [ "$_ACME_IS_RENEW" ] && [ -z "$FORCE" ]; then
 | 
| 
 | 
  1513     _info "CSR exists, skip"
 | 
| 
 | 
  1514     return
 | 
| 
 | 
  1515   fi
 | 
| 
 | 
  1516 
 | 
| 
 | 
  1517   if [ ! -f "$CERT_KEY_PATH" ]; then
 | 
| 
 | 
  1518     _err "The key file is not found: $CERT_KEY_PATH"
 | 
| 
 | 
  1519     _err "Please create the key file first."
 | 
| 
 | 
  1520     return 1
 | 
| 
 | 
  1521   fi
 | 
| 
 | 
  1522   _createcsr "$domain" "$domainlist" "$CERT_KEY_PATH" "$CSR_PATH" "$DOMAIN_SSL_CONF"
 | 
| 
 | 
  1523 
 | 
| 
 | 
  1524 }
 | 
| 
 | 
  1525 
 | 
| 
 | 
  1526 _url_replace() {
 | 
| 
 | 
  1527   tr '/+' '_-' | tr -d '= '
 | 
| 
 | 
  1528 }
 | 
| 
 | 
  1529 
 | 
| 
 | 
  1530 #base64 string
 | 
| 
 | 
  1531 _durl_replace_base64() {
 | 
| 
 | 
  1532   _l=$((${#1} % 4))
 | 
| 
 | 
  1533   if [ $_l -eq 2 ]; then
 | 
| 
 | 
  1534     _s="$1"'=='
 | 
| 
 | 
  1535   elif [ $_l -eq 3 ]; then
 | 
| 
 | 
  1536     _s="$1"'='
 | 
| 
 | 
  1537   else
 | 
| 
 | 
  1538     _s="$1"
 | 
| 
 | 
  1539   fi
 | 
| 
 | 
  1540   echo "$_s" | tr '_-' '/+'
 | 
| 
 | 
  1541 }
 | 
| 
 | 
  1542 
 | 
| 
 | 
  1543 _time2str() {
 | 
| 
 | 
  1544   #BSD
 | 
| 
 | 
  1545   if date -u -r "$1" 2>/dev/null; then
 | 
| 
 | 
  1546     return
 | 
| 
 | 
  1547   fi
 | 
| 
 | 
  1548 
 | 
| 
 | 
  1549   #Linux
 | 
| 
 | 
  1550   if date -u -d@"$1" 2>/dev/null; then
 | 
| 
 | 
  1551     return
 | 
| 
 | 
  1552   fi
 | 
| 
 | 
  1553 
 | 
| 
 | 
  1554   #Solaris
 | 
| 
 | 
  1555   if _exists adb; then
 | 
| 
 | 
  1556     _t_s_a=$(echo "0t${1}=Y" | adb)
 | 
| 
 | 
  1557     echo "$_t_s_a"
 | 
| 
 | 
  1558   fi
 | 
| 
 | 
  1559 
 | 
| 
 | 
  1560   #Busybox
 | 
| 
 | 
  1561   if echo "$1" | awk '{ print strftime("%c", $0); }' 2>/dev/null; then
 | 
| 
 | 
  1562     return
 | 
| 
 | 
  1563   fi
 | 
| 
 | 
  1564 }
 | 
| 
 | 
  1565 
 | 
| 
 | 
  1566 _normalizeJson() {
 | 
| 
 | 
  1567   sed "s/\" *: *\([\"{\[]\)/\":\1/g" | sed "s/^ *\([^ ]\)/\1/" | tr -d "\r\n"
 | 
| 
 | 
  1568 }
 | 
| 
 | 
  1569 
 | 
| 
 | 
  1570 _stat() {
 | 
| 
 | 
  1571   #Linux
 | 
| 
 | 
  1572   if stat -c '%U:%G' "$1" 2>/dev/null; then
 | 
| 
 | 
  1573     return
 | 
| 
 | 
  1574   fi
 | 
| 
 | 
  1575 
 | 
| 
 | 
  1576   #BSD
 | 
| 
 | 
  1577   if stat -f '%Su:%Sg' "$1" 2>/dev/null; then
 | 
| 
 | 
  1578     return
 | 
| 
 | 
  1579   fi
 | 
| 
 | 
  1580 
 | 
| 
 | 
  1581   return 1 #error, 'stat' not found
 | 
| 
 | 
  1582 }
 | 
| 
 | 
  1583 
 | 
| 
 | 
  1584 #keyfile
 | 
| 
 | 
  1585 _calcjwk() {
 | 
| 
 | 
  1586   keyfile="$1"
 | 
| 
 | 
  1587   if [ -z "$keyfile" ]; then
 | 
| 
 | 
  1588     _usage "Usage: _calcjwk keyfile"
 | 
| 
 | 
  1589     return 1
 | 
| 
 | 
  1590   fi
 | 
| 
 | 
  1591 
 | 
| 
 | 
  1592   if [ "$JWK_HEADER" ] && [ "$__CACHED_JWK_KEY_FILE" = "$keyfile" ]; then
 | 
| 
 | 
  1593     _debug2 "Use cached jwk for file: $__CACHED_JWK_KEY_FILE"
 | 
| 
 | 
  1594     return 0
 | 
| 
 | 
  1595   fi
 | 
| 
 | 
  1596 
 | 
| 
 | 
  1597   if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
 | 
| 
 | 
  1598     _debug "RSA key"
 | 
| 
 | 
  1599     pub_exp=$(${ACME_OPENSSL_BIN:-openssl} rsa -in "$keyfile" -noout -text | grep "^publicExponent:" | cut -d '(' -f 2 | cut -d 'x' -f 2 | cut -d ')' -f 1)
 | 
| 
 | 
  1600     if [ "${#pub_exp}" = "5" ]; then
 | 
| 
 | 
  1601       pub_exp=0$pub_exp
 | 
| 
 | 
  1602     fi
 | 
| 
 | 
  1603     _debug3 pub_exp "$pub_exp"
 | 
| 
 | 
  1604 
 | 
| 
 | 
  1605     e=$(echo "$pub_exp" | _h2b | _base64)
 | 
| 
 | 
  1606     _debug3 e "$e"
 | 
| 
 | 
  1607 
 | 
| 
 | 
  1608     modulus=$(${ACME_OPENSSL_BIN:-openssl} rsa -in "$keyfile" -modulus -noout | cut -d '=' -f 2)
 | 
| 
 | 
  1609     _debug3 modulus "$modulus"
 | 
| 
 | 
  1610     n="$(printf "%s" "$modulus" | _h2b | _base64 | _url_replace)"
 | 
| 
 | 
  1611     _debug3 n "$n"
 | 
| 
 | 
  1612 
 | 
| 
 | 
  1613     jwk='{"e": "'$e'", "kty": "RSA", "n": "'$n'"}'
 | 
| 
 | 
  1614     _debug3 jwk "$jwk"
 | 
| 
 | 
  1615 
 | 
| 
 | 
  1616     JWK_HEADER='{"alg": "RS256", "jwk": '$jwk'}'
 | 
| 
 | 
  1617     JWK_HEADERPLACE_PART1='{"nonce": "'
 | 
| 
 | 
  1618     JWK_HEADERPLACE_PART2='", "alg": "RS256"'
 | 
| 
 | 
  1619   elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
 | 
| 
 | 
  1620     _debug "EC key"
 | 
| 
 | 
  1621     crv="$(${ACME_OPENSSL_BIN:-openssl} ec -in "$keyfile" -noout -text 2>/dev/null | grep "^NIST CURVE:" | cut -d ":" -f 2 | tr -d " \r\n")"
 | 
| 
 | 
  1622     _debug3 crv "$crv"
 | 
| 
 | 
  1623     __ECC_KEY_LEN=$(echo "$crv" | cut -d "-" -f 2)
 | 
| 
 | 
  1624     if [ "$__ECC_KEY_LEN" = "521" ]; then
 | 
| 
 | 
  1625       __ECC_KEY_LEN=512
 | 
| 
 | 
  1626     fi
 | 
| 
 | 
  1627     _debug3 __ECC_KEY_LEN "$__ECC_KEY_LEN"
 | 
| 
 | 
  1628     if [ -z "$crv" ]; then
 | 
| 
 | 
  1629       _debug "Let's try ASN1 OID"
 | 
| 
 | 
  1630       crv_oid="$(${ACME_OPENSSL_BIN:-openssl} ec -in "$keyfile" -noout -text 2>/dev/null | grep "^ASN1 OID:" | cut -d ":" -f 2 | tr -d " \r\n")"
 | 
| 
 | 
  1631       _debug3 crv_oid "$crv_oid"
 | 
| 
 | 
  1632       case "${crv_oid}" in
 | 
| 
 | 
  1633       "prime256v1")
 | 
| 
 | 
  1634         crv="P-256"
 | 
| 
 | 
  1635         __ECC_KEY_LEN=256
 | 
| 
 | 
  1636         ;;
 | 
| 
 | 
  1637       "secp384r1")
 | 
| 
 | 
  1638         crv="P-384"
 | 
| 
 | 
  1639         __ECC_KEY_LEN=384
 | 
| 
 | 
  1640         ;;
 | 
| 
 | 
  1641       "secp521r1")
 | 
| 
 | 
  1642         crv="P-521"
 | 
| 
 | 
  1643         __ECC_KEY_LEN=512
 | 
| 
 | 
  1644         ;;
 | 
| 
 | 
  1645       *)
 | 
| 
 | 
  1646         _err "ECC oid : $crv_oid"
 | 
| 
 | 
  1647         return 1
 | 
| 
 | 
  1648         ;;
 | 
| 
 | 
  1649       esac
 | 
| 
 | 
  1650       _debug3 crv "$crv"
 | 
| 
 | 
  1651     fi
 | 
| 
 | 
  1652 
 | 
| 
 | 
  1653     pubi="$(${ACME_OPENSSL_BIN:-openssl} ec -in "$keyfile" -noout -text 2>/dev/null | grep -n pub: | cut -d : -f 1)"
 | 
| 
 | 
  1654     pubi=$(_math "$pubi" + 1)
 | 
| 
 | 
  1655     _debug3 pubi "$pubi"
 | 
| 
 | 
  1656 
 | 
| 
 | 
  1657     pubj="$(${ACME_OPENSSL_BIN:-openssl} ec -in "$keyfile" -noout -text 2>/dev/null | grep -n "ASN1 OID:" | cut -d : -f 1)"
 | 
| 
 | 
  1658     pubj=$(_math "$pubj" - 1)
 | 
| 
 | 
  1659     _debug3 pubj "$pubj"
 | 
| 
 | 
  1660 
 | 
| 
 | 
  1661     pubtext="$(${ACME_OPENSSL_BIN:-openssl} ec -in "$keyfile" -noout -text 2>/dev/null | sed -n "$pubi,${pubj}p" | tr -d " \n\r")"
 | 
| 
 | 
  1662     _debug3 pubtext "$pubtext"
 | 
| 
 | 
  1663 
 | 
| 
 | 
  1664     xlen="$(printf "%s" "$pubtext" | tr -d ':' | wc -c)"
 | 
| 
 | 
  1665     xlen=$(_math "$xlen" / 4)
 | 
| 
 | 
  1666     _debug3 xlen "$xlen"
 | 
| 
 | 
  1667 
 | 
| 
 | 
  1668     xend=$(_math "$xlen" + 1)
 | 
| 
 | 
  1669     x="$(printf "%s" "$pubtext" | cut -d : -f 2-"$xend")"
 | 
| 
 | 
  1670     _debug3 x "$x"
 | 
| 
 | 
  1671 
 | 
| 
 | 
  1672     x64="$(printf "%s" "$x" | tr -d : | _h2b | _base64 | _url_replace)"
 | 
| 
 | 
  1673     _debug3 x64 "$x64"
 | 
| 
 | 
  1674 
 | 
| 
 | 
  1675     xend=$(_math "$xend" + 1)
 | 
| 
 | 
  1676     y="$(printf "%s" "$pubtext" | cut -d : -f "$xend"-10000)"
 | 
| 
 | 
  1677     _debug3 y "$y"
 | 
| 
 | 
  1678 
 | 
| 
 | 
  1679     y64="$(printf "%s" "$y" | tr -d : | _h2b | _base64 | _url_replace)"
 | 
| 
 | 
  1680     _debug3 y64 "$y64"
 | 
| 
 | 
  1681 
 | 
| 
 | 
  1682     jwk='{"crv": "'$crv'", "kty": "EC", "x": "'$x64'", "y": "'$y64'"}'
 | 
| 
 | 
  1683     _debug3 jwk "$jwk"
 | 
| 
 | 
  1684 
 | 
| 
 | 
  1685     JWK_HEADER='{"alg": "ES'$__ECC_KEY_LEN'", "jwk": '$jwk'}'
 | 
| 
 | 
  1686     JWK_HEADERPLACE_PART1='{"nonce": "'
 | 
| 
 | 
  1687     JWK_HEADERPLACE_PART2='", "alg": "ES'$__ECC_KEY_LEN'"'
 | 
| 
 | 
  1688   else
 | 
| 
 | 
  1689     _err "Only RSA or EC key is supported. keyfile=$keyfile"
 | 
| 
 | 
  1690     _debug2 "$(cat "$keyfile")"
 | 
| 
 | 
  1691     return 1
 | 
| 
 | 
  1692   fi
 | 
| 
 | 
  1693 
 | 
| 
 | 
  1694   _debug3 JWK_HEADER "$JWK_HEADER"
 | 
| 
 | 
  1695   __CACHED_JWK_KEY_FILE="$keyfile"
 | 
| 
 | 
  1696 }
 | 
| 
 | 
  1697 
 | 
| 
 | 
  1698 _time() {
 | 
| 
 | 
  1699   date -u "+%s"
 | 
| 
 | 
  1700 }
 | 
| 
 | 
  1701 
 | 
| 
 | 
  1702 _utc_date() {
 | 
| 
 | 
  1703   date -u "+%Y-%m-%d %H:%M:%S"
 | 
| 
 | 
  1704 }
 | 
| 
 | 
  1705 
 | 
| 
 | 
  1706 _mktemp() {
 | 
| 
 | 
  1707   if _exists mktemp; then
 | 
| 
 | 
  1708     if mktemp 2>/dev/null; then
 | 
| 
 | 
  1709       return 0
 | 
| 
 | 
  1710     elif _contains "$(mktemp 2>&1)" "-t prefix" && mktemp -t "$PROJECT_NAME" 2>/dev/null; then
 | 
| 
 | 
  1711       #for Mac osx
 | 
| 
 | 
  1712       return 0
 | 
| 
 | 
  1713     fi
 | 
| 
 | 
  1714   fi
 | 
| 
 | 
  1715   if [ -d "/tmp" ]; then
 | 
| 
 | 
  1716     echo "/tmp/${PROJECT_NAME}wefADf24sf.$(_time).tmp"
 | 
| 
 | 
  1717     return 0
 | 
| 
 | 
  1718   elif [ "$LE_TEMP_DIR" ] && mkdir -p "$LE_TEMP_DIR"; then
 | 
| 
 | 
  1719     echo "/$LE_TEMP_DIR/wefADf24sf.$(_time).tmp"
 | 
| 
 | 
  1720     return 0
 | 
| 
 | 
  1721   fi
 | 
| 
 | 
  1722   _err "Can not create temp file."
 | 
| 
 | 
  1723 }
 | 
| 
 | 
  1724 
 | 
| 
 | 
  1725 _inithttp() {
 | 
| 
 | 
  1726 
 | 
| 
 | 
  1727   if [ -z "$HTTP_HEADER" ] || ! touch "$HTTP_HEADER"; then
 | 
| 
 | 
  1728     HTTP_HEADER="$(_mktemp)"
 | 
| 
 | 
  1729     _debug2 HTTP_HEADER "$HTTP_HEADER"
 | 
| 
 | 
  1730   fi
 | 
| 
 | 
  1731 
 | 
| 
 | 
  1732   if [ "$__HTTP_INITIALIZED" ]; then
 | 
| 
 | 
  1733     if [ "$_ACME_CURL$_ACME_WGET" ]; then
 | 
| 
 | 
  1734       _debug2 "Http already initialized."
 | 
| 
 | 
  1735       return 0
 | 
| 
 | 
  1736     fi
 | 
| 
 | 
  1737   fi
 | 
| 
 | 
  1738 
 | 
| 
 | 
  1739   if [ -z "$_ACME_CURL" ] && _exists "curl"; then
 | 
| 
 | 
  1740     _ACME_CURL="curl -L --silent --dump-header $HTTP_HEADER "
 | 
| 
 | 
  1741     if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
 | 
| 
 | 
  1742       _CURL_DUMP="$(_mktemp)"
 | 
| 
 | 
  1743       _ACME_CURL="$_ACME_CURL --trace-ascii $_CURL_DUMP "
 | 
| 
 | 
  1744     fi
 | 
| 
 | 
  1745 
 | 
| 
 | 
  1746     if [ "$CA_PATH" ]; then
 | 
| 
 | 
  1747       _ACME_CURL="$_ACME_CURL --capath $CA_PATH "
 | 
| 
 | 
  1748     elif [ "$CA_BUNDLE" ]; then
 | 
| 
 | 
  1749       _ACME_CURL="$_ACME_CURL --cacert $CA_BUNDLE "
 | 
| 
 | 
  1750     fi
 | 
| 
 | 
  1751 
 | 
| 
 | 
  1752     if _contains "$(curl --help 2>&1)" "--globoff"; then
 | 
| 
 | 
  1753       _ACME_CURL="$_ACME_CURL -g "
 | 
| 
 | 
  1754     fi
 | 
| 
 | 
  1755   fi
 | 
| 
 | 
  1756 
 | 
| 
 | 
  1757   if [ -z "$_ACME_WGET" ] && _exists "wget"; then
 | 
| 
 | 
  1758     _ACME_WGET="wget -q"
 | 
| 
 | 
  1759     if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
 | 
| 
 | 
  1760       _ACME_WGET="$_ACME_WGET -d "
 | 
| 
 | 
  1761     fi
 | 
| 
 | 
  1762     if [ "$CA_PATH" ]; then
 | 
| 
 | 
  1763       _ACME_WGET="$_ACME_WGET --ca-directory=$CA_PATH "
 | 
| 
 | 
  1764     elif [ "$CA_BUNDLE" ]; then
 | 
| 
 | 
  1765       _ACME_WGET="$_ACME_WGET --ca-certificate=$CA_BUNDLE "
 | 
| 
 | 
  1766     fi
 | 
| 
 | 
  1767   fi
 | 
| 
 | 
  1768 
 | 
| 
 | 
  1769   #from wget 1.14: do not skip body on 404 error
 | 
| 
 | 
  1770   if [ "$_ACME_WGET" ] && _contains "$($_ACME_WGET --help 2>&1)" "--content-on-error"; then
 | 
| 
 | 
  1771     _ACME_WGET="$_ACME_WGET --content-on-error "
 | 
| 
 | 
  1772   fi
 | 
| 
 | 
  1773 
 | 
| 
 | 
  1774   __HTTP_INITIALIZED=1
 | 
| 
 | 
  1775 
 | 
| 
 | 
  1776 }
 | 
| 
 | 
  1777 
 | 
| 
 | 
  1778 # body  url [needbase64] [POST|PUT|DELETE] [ContentType]
 | 
| 
 | 
  1779 _post() {
 | 
| 
 | 
  1780   body="$1"
 | 
| 
 | 
  1781   _post_url="$2"
 | 
| 
 | 
  1782   needbase64="$3"
 | 
| 
 | 
  1783   httpmethod="$4"
 | 
| 
 | 
  1784   _postContentType="$5"
 | 
| 
 | 
  1785 
 | 
| 
 | 
  1786   if [ -z "$httpmethod" ]; then
 | 
| 
 | 
  1787     httpmethod="POST"
 | 
| 
 | 
  1788   fi
 | 
| 
 | 
  1789   _debug $httpmethod
 | 
| 
 | 
  1790   _debug "_post_url" "$_post_url"
 | 
| 
 | 
  1791   _debug2 "body" "$body"
 | 
| 
 | 
  1792   _debug2 "_postContentType" "$_postContentType"
 | 
| 
 | 
  1793 
 | 
| 
 | 
  1794   _inithttp
 | 
| 
 | 
  1795 
 | 
| 
 | 
  1796   if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then
 | 
| 
 | 
  1797     _CURL="$_ACME_CURL"
 | 
| 
 | 
  1798     if [ "$HTTPS_INSECURE" ]; then
 | 
| 
 | 
  1799       _CURL="$_CURL --insecure  "
 | 
| 
 | 
  1800     fi
 | 
| 
 | 
  1801     if [ "$httpmethod" = "HEAD" ]; then
 | 
| 
 | 
  1802       _CURL="$_CURL -I  "
 | 
| 
 | 
  1803     fi
 | 
| 
 | 
  1804     _debug "_CURL" "$_CURL"
 | 
| 
 | 
  1805     if [ "$needbase64" ]; then
 | 
| 
 | 
  1806       if [ "$body" ]; then
 | 
| 
 | 
  1807         if [ "$_postContentType" ]; then
 | 
| 
 | 
  1808           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)"
 | 
| 
 | 
  1809         else
 | 
| 
 | 
  1810           response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)"
 | 
| 
 | 
  1811         fi
 | 
| 
 | 
  1812       else
 | 
| 
 | 
  1813         if [ "$_postContentType" ]; then
 | 
| 
 | 
  1814           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)"
 | 
| 
 | 
  1815         else
 | 
| 
 | 
  1816           response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$_post_url" | _base64)"
 | 
| 
 | 
  1817         fi
 | 
| 
 | 
  1818       fi
 | 
| 
 | 
  1819     else
 | 
| 
 | 
  1820       if [ "$body" ]; then
 | 
| 
 | 
  1821         if [ "$_postContentType" ]; then
 | 
| 
 | 
  1822           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")"
 | 
| 
 | 
  1823         else
 | 
| 
 | 
  1824           response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")"
 | 
| 
 | 
  1825         fi
 | 
| 
 | 
  1826       else
 | 
| 
 | 
  1827         if [ "$_postContentType" ]; then
 | 
| 
 | 
  1828           response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$_post_url")"
 | 
| 
 | 
  1829         else
 | 
| 
 | 
  1830           response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$_post_url")"
 | 
| 
 | 
  1831         fi
 | 
| 
 | 
  1832       fi
 | 
| 
 | 
  1833     fi
 | 
| 
 | 
  1834     _ret="$?"
 | 
| 
 | 
  1835     if [ "$_ret" != "0" ]; then
 | 
| 
 | 
  1836       _err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $_ret"
 | 
| 
 | 
  1837       if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
 | 
| 
 | 
  1838         _err "Here is the curl dump log:"
 | 
| 
 | 
  1839         _err "$(cat "$_CURL_DUMP")"
 | 
| 
 | 
  1840       fi
 | 
| 
 | 
  1841     fi
 | 
| 
 | 
  1842   elif [ "$_ACME_WGET" ]; then
 | 
| 
 | 
  1843     _WGET="$_ACME_WGET"
 | 
| 
 | 
  1844     if [ "$HTTPS_INSECURE" ]; then
 | 
| 
 | 
  1845       _WGET="$_WGET --no-check-certificate "
 | 
| 
 | 
  1846     fi
 | 
| 
 | 
  1847     if [ "$httpmethod" = "HEAD" ]; then
 | 
| 
 | 
  1848       _WGET="$_WGET --read-timeout=3.0  --tries=2  "
 | 
| 
 | 
  1849     fi
 | 
| 
 | 
  1850     _debug "_WGET" "$_WGET"
 | 
| 
 | 
  1851     if [ "$needbase64" ]; then
 | 
| 
 | 
  1852       if [ "$httpmethod" = "POST" ]; then
 | 
| 
 | 
  1853         if [ "$_postContentType" ]; then
 | 
| 
 | 
  1854           response="$($_WGET -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" | _base64)"
 | 
| 
 | 
  1855         else
 | 
| 
 | 
  1856           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" | _base64)"
 | 
| 
 | 
  1857         fi
 | 
| 
 | 
  1858       else
 | 
| 
 | 
  1859         if [ "$_postContentType" ]; then
 | 
| 
 | 
  1860           response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)"
 | 
| 
 | 
  1861         else
 | 
| 
 | 
  1862           response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)"
 | 
| 
 | 
  1863         fi
 | 
| 
 | 
  1864       fi
 | 
| 
 | 
  1865     else
 | 
| 
 | 
  1866       if [ "$httpmethod" = "POST" ]; then
 | 
| 
 | 
  1867         if [ "$_postContentType" ]; then
 | 
| 
 | 
  1868           response="$($_WGET -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")"
 | 
| 
 | 
  1869         else
 | 
| 
 | 
  1870           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")"
 | 
| 
 | 
  1871         fi
 | 
| 
 | 
  1872       elif [ "$httpmethod" = "HEAD" ]; then
 | 
| 
 | 
  1873         if [ "$_postContentType" ]; then
 | 
| 
 | 
  1874           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")"
 | 
| 
 | 
  1875         else
 | 
| 
 | 
  1876           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")"
 | 
| 
 | 
  1877         fi
 | 
| 
 | 
  1878       else
 | 
| 
 | 
  1879         if [ "$_postContentType" ]; then
 | 
| 
 | 
  1880           response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER")"
 | 
| 
 | 
  1881         else
 | 
| 
 | 
  1882           response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER")"
 | 
| 
 | 
  1883         fi
 | 
| 
 | 
  1884       fi
 | 
| 
 | 
  1885     fi
 | 
| 
 | 
  1886     _ret="$?"
 | 
| 
 | 
  1887     if [ "$_ret" = "8" ]; then
 | 
| 
 | 
  1888       _ret=0
 | 
| 
 | 
  1889       _debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later."
 | 
| 
 | 
  1890     fi
 | 
| 
 | 
  1891     if [ "$_ret" != "0" ]; then
 | 
| 
 | 
  1892       _err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $_ret"
 | 
| 
 | 
  1893     fi
 | 
| 
 | 
  1894     _sed_i "s/^ *//g" "$HTTP_HEADER"
 | 
| 
 | 
  1895   else
 | 
| 
 | 
  1896     _ret="$?"
 | 
| 
 | 
  1897     _err "Neither curl nor wget is found, can not do $httpmethod."
 | 
| 
 | 
  1898   fi
 | 
| 
 | 
  1899   _debug "_ret" "$_ret"
 | 
| 
 | 
  1900   printf "%s" "$response"
 | 
| 
 | 
  1901   return $_ret
 | 
| 
 | 
  1902 }
 | 
| 
 | 
  1903 
 | 
| 
 | 
  1904 # url getheader timeout
 | 
| 
 | 
  1905 _get() {
 | 
| 
 | 
  1906   _debug GET
 | 
| 
 | 
  1907   url="$1"
 | 
| 
 | 
  1908   onlyheader="$2"
 | 
| 
 | 
  1909   t="$3"
 | 
| 
 | 
  1910   _debug url "$url"
 | 
| 
 | 
  1911   _debug "timeout=$t"
 | 
| 
 | 
  1912 
 | 
| 
 | 
  1913   _inithttp
 | 
| 
 | 
  1914 
 | 
| 
 | 
  1915   if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then
 | 
| 
 | 
  1916     _CURL="$_ACME_CURL"
 | 
| 
 | 
  1917     if [ "$HTTPS_INSECURE" ]; then
 | 
| 
 | 
  1918       _CURL="$_CURL --insecure  "
 | 
| 
 | 
  1919     fi
 | 
| 
 | 
  1920     if [ "$t" ]; then
 | 
| 
 | 
  1921       _CURL="$_CURL --connect-timeout $t"
 | 
| 
 | 
  1922     fi
 | 
| 
 | 
  1923     _debug "_CURL" "$_CURL"
 | 
| 
 | 
  1924     if [ "$onlyheader" ]; then
 | 
| 
 | 
  1925       $_CURL -I --user-agent "$USER_AGENT" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$url"
 | 
| 
 | 
  1926     else
 | 
| 
 | 
  1927       $_CURL --user-agent "$USER_AGENT" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$url"
 | 
| 
 | 
  1928     fi
 | 
| 
 | 
  1929     ret=$?
 | 
| 
 | 
  1930     if [ "$ret" != "0" ]; then
 | 
| 
 | 
  1931       _err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $ret"
 | 
| 
 | 
  1932       if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
 | 
| 
 | 
  1933         _err "Here is the curl dump log:"
 | 
| 
 | 
  1934         _err "$(cat "$_CURL_DUMP")"
 | 
| 
 | 
  1935       fi
 | 
| 
 | 
  1936     fi
 | 
| 
 | 
  1937   elif [ "$_ACME_WGET" ]; then
 | 
| 
 | 
  1938     _WGET="$_ACME_WGET"
 | 
| 
 | 
  1939     if [ "$HTTPS_INSECURE" ]; then
 | 
| 
 | 
  1940       _WGET="$_WGET --no-check-certificate "
 | 
| 
 | 
  1941     fi
 | 
| 
 | 
  1942     if [ "$t" ]; then
 | 
| 
 | 
  1943       _WGET="$_WGET --timeout=$t"
 | 
| 
 | 
  1944     fi
 | 
| 
 | 
  1945     _debug "_WGET" "$_WGET"
 | 
| 
 | 
  1946     if [ "$onlyheader" ]; then
 | 
| 
 | 
  1947       $_WGET --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" -S -O /dev/null "$url" 2>&1 | sed 's/^[ ]*//g'
 | 
| 
 | 
  1948     else
 | 
| 
 | 
  1949       $_WGET --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" -O - "$url"
 | 
| 
 | 
  1950     fi
 | 
| 
 | 
  1951     ret=$?
 | 
| 
 | 
  1952     if [ "$ret" = "8" ]; then
 | 
| 
 | 
  1953       ret=0
 | 
| 
 | 
  1954       _debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later."
 | 
| 
 | 
  1955     fi
 | 
| 
 | 
  1956     if [ "$ret" != "0" ]; then
 | 
| 
 | 
  1957       _err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $ret"
 | 
| 
 | 
  1958     fi
 | 
| 
 | 
  1959   else
 | 
| 
 | 
  1960     ret=$?
 | 
| 
 | 
  1961     _err "Neither curl nor wget is found, can not do GET."
 | 
| 
 | 
  1962   fi
 | 
| 
 | 
  1963   _debug "ret" "$ret"
 | 
| 
 | 
  1964   return $ret
 | 
| 
 | 
  1965 }
 | 
| 
 | 
  1966 
 | 
| 
 | 
  1967 _head_n() {
 | 
| 
 | 
  1968   head -n "$1"
 | 
| 
 | 
  1969 }
 | 
| 
 | 
  1970 
 | 
| 
 | 
  1971 _tail_n() {
 | 
| 
 | 
  1972   if ! tail -n "$1" 2>/dev/null; then
 | 
| 
 | 
  1973     #fix for solaris
 | 
| 
 | 
  1974     tail -"$1"
 | 
| 
 | 
  1975   fi
 | 
| 
 | 
  1976 }
 | 
| 
 | 
  1977 
 | 
| 
 | 
  1978 # url  payload needbase64  keyfile
 | 
| 
 | 
  1979 _send_signed_request() {
 | 
| 
 | 
  1980   url=$1
 | 
| 
 | 
  1981   payload=$2
 | 
| 
 | 
  1982   needbase64=$3
 | 
| 
 | 
  1983   keyfile=$4
 | 
| 
 | 
  1984   if [ -z "$keyfile" ]; then
 | 
| 
 | 
  1985     keyfile="$ACCOUNT_KEY_PATH"
 | 
| 
 | 
  1986   fi
 | 
| 
 | 
  1987   _debug url "$url"
 | 
| 
 | 
  1988   _debug payload "$payload"
 | 
| 
 | 
  1989 
 | 
| 
 | 
  1990   if ! _calcjwk "$keyfile"; then
 | 
| 
 | 
  1991     return 1
 | 
| 
 | 
  1992   fi
 | 
| 
 | 
  1993 
 | 
| 
 | 
  1994   __request_conent_type="$CONTENT_TYPE_JSON"
 | 
| 
 | 
  1995 
 | 
| 
 | 
  1996   payload64=$(printf "%s" "$payload" | _base64 | _url_replace)
 | 
| 
 | 
  1997   _debug3 payload64 "$payload64"
 | 
| 
 | 
  1998 
 | 
| 
 | 
  1999   MAX_REQUEST_RETRY_TIMES=20
 | 
| 
 | 
  2000   _sleep_retry_sec=1
 | 
| 
 | 
  2001   _request_retry_times=0
 | 
| 
 | 
  2002   while [ "${_request_retry_times}" -lt "$MAX_REQUEST_RETRY_TIMES" ]; do
 | 
| 
 | 
  2003     _request_retry_times=$(_math "$_request_retry_times" + 1)
 | 
| 
 | 
  2004     _debug3 _request_retry_times "$_request_retry_times"
 | 
| 
 | 
  2005     if [ -z "$_CACHED_NONCE" ]; then
 | 
| 
 | 
  2006       _headers=""
 | 
| 
 | 
  2007       if [ "$ACME_NEW_NONCE" ]; then
 | 
| 
 | 
  2008         _debug2 "Get nonce with HEAD. ACME_NEW_NONCE" "$ACME_NEW_NONCE"
 | 
| 
 | 
  2009         nonceurl="$ACME_NEW_NONCE"
 | 
| 
 | 
  2010         if _post "" "$nonceurl" "" "HEAD" "$__request_conent_type" >/dev/null; then
 | 
| 
 | 
  2011           _headers="$(cat "$HTTP_HEADER")"
 | 
| 
 | 
  2012           _debug2 _headers "$_headers"
 | 
| 
 | 
  2013           _CACHED_NONCE="$(echo "$_headers" | grep -i "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)"
 | 
| 
 | 
  2014         fi
 | 
| 
 | 
  2015       fi
 | 
| 
 | 
  2016       if [ -z "$_CACHED_NONCE" ]; then
 | 
| 
 | 
  2017         _debug2 "Get nonce with GET. ACME_DIRECTORY" "$ACME_DIRECTORY"
 | 
| 
 | 
  2018         nonceurl="$ACME_DIRECTORY"
 | 
| 
 | 
  2019         _headers="$(_get "$nonceurl" "onlyheader")"
 | 
| 
 | 
  2020         _debug2 _headers "$_headers"
 | 
| 
 | 
  2021         _CACHED_NONCE="$(echo "$_headers" | grep -i "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)"
 | 
| 
 | 
  2022       fi
 | 
| 
 | 
  2023       if [ -z "$_CACHED_NONCE" ] && [ "$ACME_NEW_NONCE" ]; then
 | 
| 
 | 
  2024         _debug2 "Get nonce with GET. ACME_NEW_NONCE" "$ACME_NEW_NONCE"
 | 
| 
 | 
  2025         nonceurl="$ACME_NEW_NONCE"
 | 
| 
 | 
  2026         _headers="$(_get "$nonceurl" "onlyheader")"
 | 
| 
 | 
  2027         _debug2 _headers "$_headers"
 | 
| 
 | 
  2028         _CACHED_NONCE="$(echo "$_headers" | grep -i "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)"
 | 
| 
 | 
  2029       fi
 | 
| 
 | 
  2030       _debug2 _CACHED_NONCE "$_CACHED_NONCE"
 | 
| 
 | 
  2031       if [ "$?" != "0" ]; then
 | 
| 
 | 
  2032         _err "Can not connect to $nonceurl to get nonce."
 | 
| 
 | 
  2033         return 1
 | 
| 
 | 
  2034       fi
 | 
| 
 | 
  2035     else
 | 
| 
 | 
  2036       _debug2 "Use _CACHED_NONCE" "$_CACHED_NONCE"
 | 
| 
 | 
  2037     fi
 | 
| 
 | 
  2038     nonce="$_CACHED_NONCE"
 | 
| 
 | 
  2039     _debug2 nonce "$nonce"
 | 
| 
 | 
  2040     if [ -z "$nonce" ]; then
 | 
| 
 | 
  2041       _info "Could not get nonce, let's try again."
 | 
| 
 | 
  2042       _sleep 2
 | 
| 
 | 
  2043       continue
 | 
| 
 | 
  2044     fi
 | 
| 
 | 
  2045     if [ "$ACME_VERSION" = "2" ]; then
 | 
| 
 | 
  2046       if [ "$url" = "$ACME_NEW_ACCOUNT" ]; then
 | 
| 
 | 
  2047         protected="$JWK_HEADERPLACE_PART1$nonce\", \"url\": \"${url}$JWK_HEADERPLACE_PART2, \"jwk\": $jwk"'}'
 | 
| 
 | 
  2048       elif [ "$url" = "$ACME_REVOKE_CERT" ] && [ "$keyfile" != "$ACCOUNT_KEY_PATH" ]; then
 | 
| 
 | 
  2049         protected="$JWK_HEADERPLACE_PART1$nonce\", \"url\": \"${url}$JWK_HEADERPLACE_PART2, \"jwk\": $jwk"'}'
 | 
| 
 | 
  2050       else
 | 
| 
 | 
  2051         protected="$JWK_HEADERPLACE_PART1$nonce\", \"url\": \"${url}$JWK_HEADERPLACE_PART2, \"kid\": \"${ACCOUNT_URL}\""'}'
 | 
| 
 | 
  2052       fi
 | 
| 
 | 
  2053     else
 | 
| 
 | 
  2054       protected="$JWK_HEADERPLACE_PART1$nonce\", \"url\": \"${url}$JWK_HEADERPLACE_PART2, \"jwk\": $jwk"'}'
 | 
| 
 | 
  2055     fi
 | 
| 
 | 
  2056     _debug3 protected "$protected"
 | 
| 
 | 
  2057 
 | 
| 
 | 
  2058     protected64="$(printf "%s" "$protected" | _base64 | _url_replace)"
 | 
| 
 | 
  2059     _debug3 protected64 "$protected64"
 | 
| 
 | 
  2060 
 | 
| 
 | 
  2061     if ! _sig_t="$(printf "%s" "$protected64.$payload64" | _sign "$keyfile" "sha256")"; then
 | 
| 
 | 
  2062       _err "Sign request failed."
 | 
| 
 | 
  2063       return 1
 | 
| 
 | 
  2064     fi
 | 
| 
 | 
  2065     _debug3 _sig_t "$_sig_t"
 | 
| 
 | 
  2066 
 | 
| 
 | 
  2067     sig="$(printf "%s" "$_sig_t" | _url_replace)"
 | 
| 
 | 
  2068     _debug3 sig "$sig"
 | 
| 
 | 
  2069 
 | 
| 
 | 
  2070     body="{\"protected\": \"$protected64\", \"payload\": \"$payload64\", \"signature\": \"$sig\"}"
 | 
| 
 | 
  2071     _debug3 body "$body"
 | 
| 
 | 
  2072 
 | 
| 
 | 
  2073     response="$(_post "$body" "$url" "$needbase64" "POST" "$__request_conent_type")"
 | 
| 
 | 
  2074     _CACHED_NONCE=""
 | 
| 
 | 
  2075 
 | 
| 
 | 
  2076     if [ "$?" != "0" ]; then
 | 
| 
 | 
  2077       _err "Can not post to $url"
 | 
| 
 | 
  2078       return 1
 | 
| 
 | 
  2079     fi
 | 
| 
 | 
  2080 
 | 
| 
 | 
  2081     responseHeaders="$(cat "$HTTP_HEADER")"
 | 
| 
 | 
  2082     _debug2 responseHeaders "$responseHeaders"
 | 
| 
 | 
  2083 
 | 
| 
 | 
  2084     code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\r\n")"
 | 
| 
 | 
  2085     _debug code "$code"
 | 
| 
 | 
  2086 
 | 
| 
 | 
  2087     _debug2 original "$response"
 | 
| 
 | 
  2088     if echo "$responseHeaders" | grep -i "Content-Type: *application/json" >/dev/null 2>&1; then
 | 
| 
 | 
  2089       response="$(echo "$response" | _normalizeJson | _json_decode)"
 | 
| 
 | 
  2090     fi
 | 
| 
 | 
  2091     _debug2 response "$response"
 | 
| 
 | 
  2092 
 | 
| 
 | 
  2093     _CACHED_NONCE="$(echo "$responseHeaders" | grep -i "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)"
 | 
| 
 | 
  2094 
 | 
| 
 | 
  2095     if ! _startswith "$code" "2"; then
 | 
| 
 | 
  2096       _body="$response"
 | 
| 
 | 
  2097       if [ "$needbase64" ]; then
 | 
| 
 | 
  2098         _body="$(echo "$_body" | _dbase64 multiline)"
 | 
| 
 | 
  2099         _debug3 _body "$_body"
 | 
| 
 | 
  2100       fi
 | 
| 
 | 
  2101 
 | 
| 
 | 
  2102       if _contains "$_body" "JWS has invalid anti-replay nonce" || _contains "$_body" "JWS has an invalid anti-replay nonce"; then
 | 
| 
 | 
  2103         _info "It seems the CA server is busy now, let's wait and retry. Sleeping $_sleep_retry_sec seconds."
 | 
| 
 | 
  2104         _CACHED_NONCE=""
 | 
| 
 | 
  2105         _sleep $_sleep_retry_sec
 | 
| 
 | 
  2106         continue
 | 
| 
 | 
  2107       fi
 | 
| 
 | 
  2108     fi
 | 
| 
 | 
  2109     return 0
 | 
| 
 | 
  2110   done
 | 
| 
 | 
  2111   _info "Giving up sending to CA server after $MAX_REQUEST_RETRY_TIMES retries."
 | 
| 
 | 
  2112   return 1
 | 
| 
 | 
  2113 
 | 
| 
 | 
  2114 }
 | 
| 
 | 
  2115 
 | 
| 
 | 
  2116 #setopt "file"  "opt"  "="  "value" [";"]
 | 
| 
 | 
  2117 _setopt() {
 | 
| 
 | 
  2118   __conf="$1"
 | 
| 
 | 
  2119   __opt="$2"
 | 
| 
 | 
  2120   __sep="$3"
 | 
| 
 | 
  2121   __val="$4"
 | 
| 
 | 
  2122   __end="$5"
 | 
| 
 | 
  2123   if [ -z "$__opt" ]; then
 | 
| 
 | 
  2124     _usage usage: _setopt '"file"  "opt"  "="  "value" [";"]'
 | 
| 
 | 
  2125     return
 | 
| 
 | 
  2126   fi
 | 
| 
 | 
  2127   if [ ! -f "$__conf" ]; then
 | 
| 
 | 
  2128     touch "$__conf"
 | 
| 
 | 
  2129   fi
 | 
| 
 | 
  2130 
 | 
| 
 | 
  2131   if grep -n "^$__opt$__sep" "$__conf" >/dev/null; then
 | 
| 
 | 
  2132     _debug3 OK
 | 
| 
 | 
  2133     if _contains "$__val" "&"; then
 | 
| 
 | 
  2134       __val="$(echo "$__val" | sed 's/&/\\&/g')"
 | 
| 
 | 
  2135     fi
 | 
| 
 | 
  2136     text="$(cat "$__conf")"
 | 
| 
 | 
  2137     printf -- "%s\n" "$text" | sed "s|^$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf"
 | 
| 
 | 
  2138 
 | 
| 
 | 
  2139   elif grep -n "^#$__opt$__sep" "$__conf" >/dev/null; then
 | 
| 
 | 
  2140     if _contains "$__val" "&"; then
 | 
| 
 | 
  2141       __val="$(echo "$__val" | sed 's/&/\\&/g')"
 | 
| 
 | 
  2142     fi
 | 
| 
 | 
  2143     text="$(cat "$__conf")"
 | 
| 
 | 
  2144     printf -- "%s\n" "$text" | sed "s|^#$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf"
 | 
| 
 | 
  2145 
 | 
| 
 | 
  2146   else
 | 
| 
 | 
  2147     _debug3 APP
 | 
| 
 | 
  2148     echo "$__opt$__sep$__val$__end" >>"$__conf"
 | 
| 
 | 
  2149   fi
 | 
| 
 | 
  2150   _debug3 "$(grep -n "^$__opt$__sep" "$__conf")"
 | 
| 
 | 
  2151 }
 | 
| 
 | 
  2152 
 | 
| 
 | 
  2153 #_save_conf  file key  value base64encode
 | 
| 
 | 
  2154 #save to conf
 | 
| 
 | 
  2155 _save_conf() {
 | 
| 
 | 
  2156   _s_c_f="$1"
 | 
| 
 | 
  2157   _sdkey="$2"
 | 
| 
 | 
  2158   _sdvalue="$3"
 | 
| 
 | 
  2159   _b64encode="$4"
 | 
| 
 | 
  2160   if [ "$_sdvalue" ] && [ "$_b64encode" ]; then
 | 
| 
 | 
  2161     _sdvalue="${B64CONF_START}$(printf "%s" "${_sdvalue}" | _base64)${B64CONF_END}"
 | 
| 
 | 
  2162   fi
 | 
| 
 | 
  2163   if [ "$_s_c_f" ]; then
 | 
| 
 | 
  2164     _setopt "$_s_c_f" "$_sdkey" "=" "'$_sdvalue'"
 | 
| 
 | 
  2165   else
 | 
| 
 | 
  2166     _err "config file is empty, can not save $_sdkey=$_sdvalue"
 | 
| 
 | 
  2167   fi
 | 
| 
 | 
  2168 }
 | 
| 
 | 
  2169 
 | 
| 
 | 
  2170 #_clear_conf file  key
 | 
| 
 | 
  2171 _clear_conf() {
 | 
| 
 | 
  2172   _c_c_f="$1"
 | 
| 
 | 
  2173   _sdkey="$2"
 | 
| 
 | 
  2174   if [ "$_c_c_f" ]; then
 | 
| 
 | 
  2175     _conf_data="$(cat "$_c_c_f")"
 | 
| 
 | 
  2176     echo "$_conf_data" | sed "s/^$_sdkey *=.*$//" >"$_c_c_f"
 | 
| 
 | 
  2177   else
 | 
| 
 | 
  2178     _err "config file is empty, can not clear"
 | 
| 
 | 
  2179   fi
 | 
| 
 | 
  2180 }
 | 
| 
 | 
  2181 
 | 
| 
 | 
  2182 #_read_conf file  key
 | 
| 
 | 
  2183 _read_conf() {
 | 
| 
 | 
  2184   _r_c_f="$1"
 | 
| 
 | 
  2185   _sdkey="$2"
 | 
| 
 | 
  2186   if [ -f "$_r_c_f" ]; then
 | 
| 
 | 
  2187     _sdv="$(
 | 
| 
 | 
  2188       eval "$(grep "^$_sdkey *=" "$_r_c_f")"
 | 
| 
 | 
  2189       eval "printf \"%s\" \"\$$_sdkey\""
 | 
| 
 | 
  2190     )"
 | 
| 
 | 
  2191     if _startswith "$_sdv" "${B64CONF_START}" && _endswith "$_sdv" "${B64CONF_END}"; then
 | 
| 
 | 
  2192       _sdv="$(echo "$_sdv" | sed "s/${B64CONF_START}//" | sed "s/${B64CONF_END}//" | _dbase64)"
 | 
| 
 | 
  2193     fi
 | 
| 
 | 
  2194     printf "%s" "$_sdv"
 | 
| 
 | 
  2195   else
 | 
| 
 | 
  2196     _debug "config file is empty, can not read $_sdkey"
 | 
| 
 | 
  2197   fi
 | 
| 
 | 
  2198 }
 | 
| 
 | 
  2199 
 | 
| 
 | 
  2200 #_savedomainconf   key  value  base64encode
 | 
| 
 | 
  2201 #save to domain.conf
 | 
| 
 | 
  2202 _savedomainconf() {
 | 
| 
 | 
  2203   _save_conf "$DOMAIN_CONF" "$@"
 | 
| 
 | 
  2204 }
 | 
| 
 | 
  2205 
 | 
| 
 | 
  2206 #_cleardomainconf   key
 | 
| 
 | 
  2207 _cleardomainconf() {
 | 
| 
 | 
  2208   _clear_conf "$DOMAIN_CONF" "$1"
 | 
| 
 | 
  2209 }
 | 
| 
 | 
  2210 
 | 
| 
 | 
  2211 #_readdomainconf   key
 | 
| 
 | 
  2212 _readdomainconf() {
 | 
| 
 | 
  2213   _read_conf "$DOMAIN_CONF" "$1"
 | 
| 
 | 
  2214 }
 | 
| 
 | 
  2215 
 | 
| 
 | 
  2216 #key  value  base64encode
 | 
| 
 | 
  2217 _savedeployconf() {
 | 
| 
 | 
  2218   _savedomainconf "SAVED_$1" "$2" "$3"
 | 
| 
 | 
  2219   #remove later
 | 
| 
 | 
  2220   _cleardomainconf "$1"
 | 
| 
 | 
  2221 }
 | 
| 
 | 
  2222 
 | 
| 
 | 
  2223 #key
 | 
| 
 | 
  2224 _getdeployconf() {
 | 
| 
 | 
  2225   _rac_key="$1"
 | 
| 
 | 
  2226   _rac_value="$(eval echo \$"$_rac_key")"
 | 
| 
 | 
  2227   if [ "$_rac_value" ]; then
 | 
| 
 | 
  2228     if _startswith "$_rac_value" '"' && _endswith "$_rac_value" '"'; then
 | 
| 
 | 
  2229       _debug2 "trim quotation marks"
 | 
| 
 | 
  2230       eval "export $_rac_key=$_rac_value"
 | 
| 
 | 
  2231     fi
 | 
| 
 | 
  2232     return 0 # do nothing
 | 
| 
 | 
  2233   fi
 | 
| 
 | 
  2234   _saved=$(_readdomainconf "SAVED_$_rac_key")
 | 
| 
 | 
  2235   eval "export $_rac_key=\"$_saved\""
 | 
| 
 | 
  2236 }
 | 
| 
 | 
  2237 
 | 
| 
 | 
  2238 #_saveaccountconf  key  value  base64encode
 | 
| 
 | 
  2239 _saveaccountconf() {
 | 
| 
 | 
  2240   _save_conf "$ACCOUNT_CONF_PATH" "$@"
 | 
| 
 | 
  2241 }
 | 
| 
 | 
  2242 
 | 
| 
 | 
  2243 #key  value base64encode
 | 
| 
 | 
  2244 _saveaccountconf_mutable() {
 | 
| 
 | 
  2245   _save_conf "$ACCOUNT_CONF_PATH" "SAVED_$1" "$2" "$3"
 | 
| 
 | 
  2246   #remove later
 | 
| 
 | 
  2247   _clearaccountconf "$1"
 | 
| 
 | 
  2248 }
 | 
| 
 | 
  2249 
 | 
| 
 | 
  2250 #key
 | 
| 
 | 
  2251 _readaccountconf() {
 | 
| 
 | 
  2252   _read_conf "$ACCOUNT_CONF_PATH" "$1"
 | 
| 
 | 
  2253 }
 | 
| 
 | 
  2254 
 | 
| 
 | 
  2255 #key
 | 
| 
 | 
  2256 _readaccountconf_mutable() {
 | 
| 
 | 
  2257   _rac_key="$1"
 | 
| 
 | 
  2258   _readaccountconf "SAVED_$_rac_key"
 | 
| 
 | 
  2259 }
 | 
| 
 | 
  2260 
 | 
| 
 | 
  2261 #_clearaccountconf   key
 | 
| 
 | 
  2262 _clearaccountconf() {
 | 
| 
 | 
  2263   _clear_conf "$ACCOUNT_CONF_PATH" "$1"
 | 
| 
 | 
  2264 }
 | 
| 
 | 
  2265 
 | 
| 
 | 
  2266 #_savecaconf  key  value
 | 
| 
 | 
  2267 _savecaconf() {
 | 
| 
 | 
  2268   _save_conf "$CA_CONF" "$1" "$2"
 | 
| 
 | 
  2269 }
 | 
| 
 | 
  2270 
 | 
| 
 | 
  2271 #_readcaconf   key
 | 
| 
 | 
  2272 _readcaconf() {
 | 
| 
 | 
  2273   _read_conf "$CA_CONF" "$1"
 | 
| 
 | 
  2274 }
 | 
| 
 | 
  2275 
 | 
| 
 | 
  2276 #_clearaccountconf   key
 | 
| 
 | 
  2277 _clearcaconf() {
 | 
| 
 | 
  2278   _clear_conf "$CA_CONF" "$1"
 | 
| 
 | 
  2279 }
 | 
| 
 | 
  2280 
 | 
| 
 | 
  2281 # content localaddress
 | 
| 
 | 
  2282 _startserver() {
 | 
| 
 | 
  2283   content="$1"
 | 
| 
 | 
  2284   ncaddr="$2"
 | 
| 
 | 
  2285   _debug "content" "$content"
 | 
| 
 | 
  2286   _debug "ncaddr" "$ncaddr"
 | 
| 
 | 
  2287 
 | 
| 
 | 
  2288   _debug "startserver: $$"
 | 
| 
 | 
  2289 
 | 
| 
 | 
  2290   _debug Le_HTTPPort "$Le_HTTPPort"
 | 
| 
 | 
  2291   _debug Le_Listen_V4 "$Le_Listen_V4"
 | 
| 
 | 
  2292   _debug Le_Listen_V6 "$Le_Listen_V6"
 | 
| 
 | 
  2293 
 | 
| 
 | 
  2294   _NC="socat"
 | 
| 
 | 
  2295   if [ "$Le_Listen_V4" ]; then
 | 
| 
 | 
  2296     _NC="$_NC -4"
 | 
| 
 | 
  2297   elif [ "$Le_Listen_V6" ]; then
 | 
| 
 | 
  2298     _NC="$_NC -6"
 | 
| 
 | 
  2299   fi
 | 
| 
 | 
  2300 
 | 
| 
 | 
  2301   if [ "$DEBUG" ] && [ "$DEBUG" -gt "1" ]; then
 | 
| 
 | 
  2302     _NC="$_NC -d -d -v"
 | 
| 
 | 
  2303   fi
 | 
| 
 | 
  2304 
 | 
| 
 | 
  2305   SOCAT_OPTIONS=TCP-LISTEN:$Le_HTTPPort,crlf,reuseaddr,fork
 | 
| 
 | 
  2306 
 | 
| 
 | 
  2307   #Adding bind to local-address
 | 
| 
 | 
  2308   if [ "$ncaddr" ]; then
 | 
| 
 | 
  2309     SOCAT_OPTIONS="$SOCAT_OPTIONS,bind=${ncaddr}"
 | 
| 
 | 
  2310   fi
 | 
| 
 | 
  2311 
 | 
| 
 | 
  2312   _content_len="$(printf "%s" "$content" | wc -c)"
 | 
| 
 | 
  2313   _debug _content_len "$_content_len"
 | 
| 
 | 
  2314   _debug "_NC" "$_NC $SOCAT_OPTIONS"
 | 
| 
 | 
  2315   $_NC $SOCAT_OPTIONS SYSTEM:"sleep 1; \
 | 
| 
 | 
  2316 echo 'HTTP/1.0 200 OK'; \
 | 
| 
 | 
  2317 echo 'Content-Length\: $_content_len'; \
 | 
| 
 | 
  2318 echo ''; \
 | 
| 
 | 
  2319 printf -- '$content';" &
 | 
| 
 | 
  2320   serverproc="$!"
 | 
| 
 | 
  2321 }
 | 
| 
 | 
  2322 
 | 
| 
 | 
  2323 _stopserver() {
 | 
| 
 | 
  2324   pid="$1"
 | 
| 
 | 
  2325   _debug "pid" "$pid"
 | 
| 
 | 
  2326   if [ -z "$pid" ]; then
 | 
| 
 | 
  2327     return
 | 
| 
 | 
  2328   fi
 | 
| 
 | 
  2329 
 | 
| 
 | 
  2330   kill $pid
 | 
| 
 | 
  2331 
 | 
| 
 | 
  2332 }
 | 
| 
 | 
  2333 
 | 
| 
 | 
  2334 # sleep sec
 | 
| 
 | 
  2335 _sleep() {
 | 
| 
 | 
  2336   _sleep_sec="$1"
 | 
| 
 | 
  2337   if [ "$__INTERACTIVE" ]; then
 | 
| 
 | 
  2338     _sleep_c="$_sleep_sec"
 | 
| 
 | 
  2339     while [ "$_sleep_c" -ge "0" ]; do
 | 
| 
 | 
  2340       printf "\r      \r"
 | 
| 
 | 
  2341       __green "$_sleep_c"
 | 
| 
 | 
  2342       _sleep_c="$(_math "$_sleep_c" - 1)"
 | 
| 
 | 
  2343       sleep 1
 | 
| 
 | 
  2344     done
 | 
| 
 | 
  2345     printf "\r"
 | 
| 
 | 
  2346   else
 | 
| 
 | 
  2347     sleep "$_sleep_sec"
 | 
| 
 | 
  2348   fi
 | 
| 
 | 
  2349 }
 | 
| 
 | 
  2350 
 | 
| 
 | 
  2351 # _starttlsserver  san_a  san_b port content _ncaddr acmeValidationv1
 | 
| 
 | 
  2352 _starttlsserver() {
 | 
| 
 | 
  2353   _info "Starting tls server."
 | 
| 
 | 
  2354   san_a="$1"
 | 
| 
 | 
  2355   san_b="$2"
 | 
| 
 | 
  2356   port="$3"
 | 
| 
 | 
  2357   content="$4"
 | 
| 
 | 
  2358   opaddr="$5"
 | 
| 
 | 
  2359   acmeValidationv1="$6"
 | 
| 
 | 
  2360 
 | 
| 
 | 
  2361   _debug san_a "$san_a"
 | 
| 
 | 
  2362   _debug san_b "$san_b"
 | 
| 
 | 
  2363   _debug port "$port"
 | 
| 
 | 
  2364   _debug acmeValidationv1 "$acmeValidationv1"
 | 
| 
 | 
  2365 
 | 
| 
 | 
  2366   #create key TLS_KEY
 | 
| 
 | 
  2367   if ! _createkey "2048" "$TLS_KEY"; then
 | 
| 
 | 
  2368     _err "Create tls validation key error."
 | 
| 
 | 
  2369     return 1
 | 
| 
 | 
  2370   fi
 | 
| 
 | 
  2371 
 | 
| 
 | 
  2372   #create csr
 | 
| 
 | 
  2373   alt="$san_a"
 | 
| 
 | 
  2374   if [ "$san_b" ]; then
 | 
| 
 | 
  2375     alt="$alt,$san_b"
 | 
| 
 | 
  2376   fi
 | 
| 
 | 
  2377   if ! _createcsr "tls.acme.sh" "$alt" "$TLS_KEY" "$TLS_CSR" "$TLS_CONF" "$acmeValidationv1"; then
 | 
| 
 | 
  2378     _err "Create tls validation csr error."
 | 
| 
 | 
  2379     return 1
 | 
| 
 | 
  2380   fi
 | 
| 
 | 
  2381 
 | 
| 
 | 
  2382   #self signed
 | 
| 
 | 
  2383   if ! _signcsr "$TLS_KEY" "$TLS_CSR" "$TLS_CONF" "$TLS_CERT"; then
 | 
| 
 | 
  2384     _err "Create tls validation cert error."
 | 
| 
 | 
  2385     return 1
 | 
| 
 | 
  2386   fi
 | 
| 
 | 
  2387 
 | 
| 
 | 
  2388   __S_OPENSSL="${ACME_OPENSSL_BIN:-openssl} s_server -www -cert $TLS_CERT  -key $TLS_KEY "
 | 
| 
 | 
  2389   if [ "$opaddr" ]; then
 | 
| 
 | 
  2390     __S_OPENSSL="$__S_OPENSSL -accept $opaddr:$port"
 | 
| 
 | 
  2391   else
 | 
| 
 | 
  2392     __S_OPENSSL="$__S_OPENSSL -accept $port"
 | 
| 
 | 
  2393   fi
 | 
| 
 | 
  2394 
 | 
| 
 | 
  2395   _debug Le_Listen_V4 "$Le_Listen_V4"
 | 
| 
 | 
  2396   _debug Le_Listen_V6 "$Le_Listen_V6"
 | 
| 
 | 
  2397   if [ "$Le_Listen_V4" ]; then
 | 
| 
 | 
  2398     __S_OPENSSL="$__S_OPENSSL -4"
 | 
| 
 | 
  2399   elif [ "$Le_Listen_V6" ]; then
 | 
| 
 | 
  2400     __S_OPENSSL="$__S_OPENSSL -6"
 | 
| 
 | 
  2401   fi
 | 
| 
 | 
  2402 
 | 
| 
 | 
  2403   if [ "$acmeValidationv1" ]; then
 | 
| 
 | 
  2404     __S_OPENSSL="$__S_OPENSSL -alpn acme-tls/1"
 | 
| 
 | 
  2405   fi
 | 
| 
 | 
  2406 
 | 
| 
 | 
  2407   _debug "$__S_OPENSSL"
 | 
| 
 | 
  2408   if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
 | 
| 
 | 
  2409     $__S_OPENSSL -tlsextdebug &
 | 
| 
 | 
  2410   else
 | 
| 
 | 
  2411     $__S_OPENSSL >/dev/null 2>&1 &
 | 
| 
 | 
  2412   fi
 | 
| 
 | 
  2413 
 | 
| 
 | 
  2414   serverproc="$!"
 | 
| 
 | 
  2415   sleep 1
 | 
| 
 | 
  2416   _debug serverproc "$serverproc"
 | 
| 
 | 
  2417 }
 | 
| 
 | 
  2418 
 | 
| 
 | 
  2419 #file
 | 
| 
 | 
  2420 _readlink() {
 | 
| 
 | 
  2421   _rf="$1"
 | 
| 
 | 
  2422   if ! readlink -f "$_rf" 2>/dev/null; then
 | 
| 
 | 
  2423     if _startswith "$_rf" "/"; then
 | 
| 
 | 
  2424       echo "$_rf"
 | 
| 
 | 
  2425       return 0
 | 
| 
 | 
  2426     fi
 | 
| 
 | 
  2427     echo "$(pwd)/$_rf" | _conapath
 | 
| 
 | 
  2428   fi
 | 
| 
 | 
  2429 }
 | 
| 
 | 
  2430 
 | 
| 
 | 
  2431 _conapath() {
 | 
| 
 | 
  2432   sed "s#/\./#/#g"
 | 
| 
 | 
  2433 }
 | 
| 
 | 
  2434 
 | 
| 
 | 
  2435 __initHome() {
 | 
| 
 | 
  2436   if [ -z "$_SCRIPT_HOME" ]; then
 | 
| 
 | 
  2437     if _exists readlink && _exists dirname; then
 | 
| 
 | 
  2438       _debug "Lets find script dir."
 | 
| 
 | 
  2439       _debug "_SCRIPT_" "$_SCRIPT_"
 | 
| 
 | 
  2440       _script="$(_readlink "$_SCRIPT_")"
 | 
| 
 | 
  2441       _debug "_script" "$_script"
 | 
| 
 | 
  2442       _script_home="$(dirname "$_script")"
 | 
| 
 | 
  2443       _debug "_script_home" "$_script_home"
 | 
| 
 | 
  2444       if [ -d "$_script_home" ]; then
 | 
| 
 | 
  2445         _SCRIPT_HOME="$_script_home"
 | 
| 
 | 
  2446       else
 | 
| 
 | 
  2447         _err "It seems the script home is not correct:$_script_home"
 | 
| 
 | 
  2448       fi
 | 
| 
 | 
  2449     fi
 | 
| 
 | 
  2450   fi
 | 
| 
 | 
  2451 
 | 
| 
 | 
  2452   #  if [ -z "$LE_WORKING_DIR" ]; then
 | 
| 
 | 
  2453   #    if [ -f "$DEFAULT_INSTALL_HOME/account.conf" ]; then
 | 
| 
 | 
  2454   #      _debug "It seems that $PROJECT_NAME is already installed in $DEFAULT_INSTALL_HOME"
 | 
| 
 | 
  2455   #      LE_WORKING_DIR="$DEFAULT_INSTALL_HOME"
 | 
| 
 | 
  2456   #    else
 | 
| 
 | 
  2457   #      LE_WORKING_DIR="$_SCRIPT_HOME"
 | 
| 
 | 
  2458   #    fi
 | 
| 
 | 
  2459   #  fi
 | 
| 
 | 
  2460 
 | 
| 
 | 
  2461   if [ -z "$LE_WORKING_DIR" ]; then
 | 
| 
 | 
  2462     _debug "Using default home:$DEFAULT_INSTALL_HOME"
 | 
| 
 | 
  2463     LE_WORKING_DIR="$DEFAULT_INSTALL_HOME"
 | 
| 
 | 
  2464   fi
 | 
| 
 | 
  2465   export LE_WORKING_DIR
 | 
| 
 | 
  2466 
 | 
| 
 | 
  2467   if [ -z "$LE_CONFIG_HOME" ]; then
 | 
| 
 | 
  2468     LE_CONFIG_HOME="$LE_WORKING_DIR"
 | 
| 
 | 
  2469   fi
 | 
| 
 | 
  2470   _debug "Using config home:$LE_CONFIG_HOME"
 | 
| 
 | 
  2471   export LE_CONFIG_HOME
 | 
| 
 | 
  2472 
 | 
| 
 | 
  2473   _DEFAULT_ACCOUNT_CONF_PATH="$LE_CONFIG_HOME/account.conf"
 | 
| 
 | 
  2474 
 | 
| 
 | 
  2475   if [ -z "$ACCOUNT_CONF_PATH" ]; then
 | 
| 
 | 
  2476     if [ -f "$_DEFAULT_ACCOUNT_CONF_PATH" ]; then
 | 
| 
 | 
  2477       . "$_DEFAULT_ACCOUNT_CONF_PATH"
 | 
| 
 | 
  2478     fi
 | 
| 
 | 
  2479   fi
 | 
| 
 | 
  2480 
 | 
| 
 | 
  2481   if [ -z "$ACCOUNT_CONF_PATH" ]; then
 | 
| 
 | 
  2482     ACCOUNT_CONF_PATH="$_DEFAULT_ACCOUNT_CONF_PATH"
 | 
| 
 | 
  2483   fi
 | 
| 
 | 
  2484   _debug3 ACCOUNT_CONF_PATH "$ACCOUNT_CONF_PATH"
 | 
| 
 | 
  2485   DEFAULT_LOG_FILE="$LE_CONFIG_HOME/$PROJECT_NAME.log"
 | 
| 
 | 
  2486 
 | 
| 
 | 
  2487   DEFAULT_CA_HOME="$LE_CONFIG_HOME/ca"
 | 
| 
 | 
  2488 
 | 
| 
 | 
  2489   if [ -z "$LE_TEMP_DIR" ]; then
 | 
| 
 | 
  2490     LE_TEMP_DIR="$LE_CONFIG_HOME/tmp"
 | 
| 
 | 
  2491   fi
 | 
| 
 | 
  2492 }
 | 
| 
 | 
  2493 
 | 
| 
 | 
  2494 #server
 | 
| 
 | 
  2495 _initAPI() {
 | 
| 
 | 
  2496   _api_server="${1:-$ACME_DIRECTORY}"
 | 
| 
 | 
  2497   _debug "_init api for server: $_api_server"
 | 
| 
 | 
  2498 
 | 
| 
 | 
  2499   if [ -z "$ACME_NEW_ACCOUNT" ]; then
 | 
| 
 | 
  2500     response=$(_get "$_api_server")
 | 
| 
 | 
  2501     if [ "$?" != "0" ]; then
 | 
| 
 | 
  2502       _debug2 "response" "$response"
 | 
| 
 | 
  2503       _err "Can not init api."
 | 
| 
 | 
  2504       return 1
 | 
| 
 | 
  2505     fi
 | 
| 
 | 
  2506     response=$(echo "$response" | _json_decode)
 | 
| 
 | 
  2507     _debug2 "response" "$response"
 | 
| 
 | 
  2508 
 | 
| 
 | 
  2509     ACME_KEY_CHANGE=$(echo "$response" | _egrep_o 'key-change" *: *"[^"]*"' | cut -d '"' -f 3)
 | 
| 
 | 
  2510     if [ -z "$ACME_KEY_CHANGE" ]; then
 | 
| 
 | 
  2511       ACME_KEY_CHANGE=$(echo "$response" | _egrep_o 'keyChange" *: *"[^"]*"' | cut -d '"' -f 3)
 | 
| 
 | 
  2512     fi
 | 
| 
 | 
  2513     export ACME_KEY_CHANGE
 | 
| 
 | 
  2514 
 | 
| 
 | 
  2515     ACME_NEW_AUTHZ=$(echo "$response" | _egrep_o 'new-authz" *: *"[^"]*"' | cut -d '"' -f 3)
 | 
| 
 | 
  2516     if [ -z "$ACME_NEW_AUTHZ" ]; then
 | 
| 
 | 
  2517       ACME_NEW_AUTHZ=$(echo "$response" | _egrep_o 'newAuthz" *: *"[^"]*"' | cut -d '"' -f 3)
 | 
| 
 | 
  2518     fi
 | 
| 
 | 
  2519     export ACME_NEW_AUTHZ
 | 
| 
 | 
  2520 
 | 
| 
 | 
  2521     ACME_NEW_ORDER=$(echo "$response" | _egrep_o 'new-cert" *: *"[^"]*"' | cut -d '"' -f 3)
 | 
| 
 | 
  2522     ACME_NEW_ORDER_RES="new-cert"
 | 
| 
 | 
  2523     if [ -z "$ACME_NEW_ORDER" ]; then
 | 
| 
 | 
  2524       ACME_NEW_ORDER=$(echo "$response" | _egrep_o 'new-order" *: *"[^"]*"' | cut -d '"' -f 3)
 | 
| 
 | 
  2525       ACME_NEW_ORDER_RES="new-order"
 | 
| 
 | 
  2526       if [ -z "$ACME_NEW_ORDER" ]; then
 | 
| 
 | 
  2527         ACME_NEW_ORDER=$(echo "$response" | _egrep_o 'newOrder" *: *"[^"]*"' | cut -d '"' -f 3)
 | 
| 
 | 
  2528       fi
 | 
| 
 | 
  2529     fi
 | 
| 
 | 
  2530     export ACME_NEW_ORDER
 | 
| 
 | 
  2531     export ACME_NEW_ORDER_RES
 | 
| 
 | 
  2532 
 | 
| 
 | 
  2533     ACME_NEW_ACCOUNT=$(echo "$response" | _egrep_o 'new-reg" *: *"[^"]*"' | cut -d '"' -f 3)
 | 
| 
 | 
  2534     ACME_NEW_ACCOUNT_RES="new-reg"
 | 
| 
 | 
  2535     if [ -z "$ACME_NEW_ACCOUNT" ]; then
 | 
| 
 | 
  2536       ACME_NEW_ACCOUNT=$(echo "$response" | _egrep_o 'new-account" *: *"[^"]*"' | cut -d '"' -f 3)
 | 
| 
 | 
  2537       ACME_NEW_ACCOUNT_RES="new-account"
 | 
| 
 | 
  2538       if [ -z "$ACME_NEW_ACCOUNT" ]; then
 | 
| 
 | 
  2539         ACME_NEW_ACCOUNT=$(echo "$response" | _egrep_o 'newAccount" *: *"[^"]*"' | cut -d '"' -f 3)
 | 
| 
 | 
  2540         if [ "$ACME_NEW_ACCOUNT" ]; then
 | 
| 
 | 
  2541           export ACME_VERSION=2
 | 
| 
 | 
  2542         fi
 | 
| 
 | 
  2543       fi
 | 
| 
 | 
  2544     fi
 | 
| 
 | 
  2545     export ACME_NEW_ACCOUNT
 | 
| 
 | 
  2546     export ACME_NEW_ACCOUNT_RES
 | 
| 
 | 
  2547 
 | 
| 
 | 
  2548     ACME_REVOKE_CERT=$(echo "$response" | _egrep_o 'revoke-cert" *: *"[^"]*"' | cut -d '"' -f 3)
 | 
| 
 | 
  2549     if [ -z "$ACME_REVOKE_CERT" ]; then
 | 
| 
 | 
  2550       ACME_REVOKE_CERT=$(echo "$response" | _egrep_o 'revokeCert" *: *"[^"]*"' | cut -d '"' -f 3)
 | 
| 
 | 
  2551     fi
 | 
| 
 | 
  2552     export ACME_REVOKE_CERT
 | 
| 
 | 
  2553 
 | 
| 
 | 
  2554     ACME_NEW_NONCE=$(echo "$response" | _egrep_o 'new-nonce" *: *"[^"]*"' | cut -d '"' -f 3)
 | 
| 
 | 
  2555     if [ -z "$ACME_NEW_NONCE" ]; then
 | 
| 
 | 
  2556       ACME_NEW_NONCE=$(echo "$response" | _egrep_o 'newNonce" *: *"[^"]*"' | cut -d '"' -f 3)
 | 
| 
 | 
  2557     fi
 | 
| 
 | 
  2558     export ACME_NEW_NONCE
 | 
| 
 | 
  2559 
 | 
| 
 | 
  2560     ACME_AGREEMENT=$(echo "$response" | _egrep_o 'terms-of-service" *: *"[^"]*"' | cut -d '"' -f 3)
 | 
| 
 | 
  2561     if [ -z "$ACME_AGREEMENT" ]; then
 | 
| 
 | 
  2562       ACME_AGREEMENT=$(echo "$response" | _egrep_o 'termsOfService" *: *"[^"]*"' | cut -d '"' -f 3)
 | 
| 
 | 
  2563     fi
 | 
| 
 | 
  2564     export ACME_AGREEMENT
 | 
| 
 | 
  2565 
 | 
| 
 | 
  2566     _debug "ACME_KEY_CHANGE" "$ACME_KEY_CHANGE"
 | 
| 
 | 
  2567     _debug "ACME_NEW_AUTHZ" "$ACME_NEW_AUTHZ"
 | 
| 
 | 
  2568     _debug "ACME_NEW_ORDER" "$ACME_NEW_ORDER"
 | 
| 
 | 
  2569     _debug "ACME_NEW_ACCOUNT" "$ACME_NEW_ACCOUNT"
 | 
| 
 | 
  2570     _debug "ACME_REVOKE_CERT" "$ACME_REVOKE_CERT"
 | 
| 
 | 
  2571     _debug "ACME_AGREEMENT" "$ACME_AGREEMENT"
 | 
| 
 | 
  2572     _debug "ACME_NEW_NONCE" "$ACME_NEW_NONCE"
 | 
| 
 | 
  2573     _debug "ACME_VERSION" "$ACME_VERSION"
 | 
| 
 | 
  2574 
 | 
| 
 | 
  2575   fi
 | 
| 
 | 
  2576 }
 | 
| 
 | 
  2577 
 | 
| 
 | 
  2578 #[domain]  [keylength or isEcc flag]
 | 
| 
 | 
  2579 _initpath() {
 | 
| 
 | 
  2580   domain="$1"
 | 
| 
 | 
  2581   _ilength="$2"
 | 
| 
 | 
  2582 
 | 
| 
 | 
  2583   __initHome
 | 
| 
 | 
  2584 
 | 
| 
 | 
  2585   if [ -f "$ACCOUNT_CONF_PATH" ]; then
 | 
| 
 | 
  2586     . "$ACCOUNT_CONF_PATH"
 | 
| 
 | 
  2587   fi
 | 
| 
 | 
  2588 
 | 
| 
 | 
  2589   if [ "$_ACME_IN_CRON" ]; then
 | 
| 
 | 
  2590     if [ ! "$_USER_PATH_EXPORTED" ]; then
 | 
| 
 | 
  2591       _USER_PATH_EXPORTED=1
 | 
| 
 | 
  2592       export PATH="$USER_PATH:$PATH"
 | 
| 
 | 
  2593     fi
 | 
| 
 | 
  2594   fi
 | 
| 
 | 
  2595 
 | 
| 
 | 
  2596   if [ -z "$CA_HOME" ]; then
 | 
| 
 | 
  2597     CA_HOME="$DEFAULT_CA_HOME"
 | 
| 
 | 
  2598   fi
 | 
| 
 | 
  2599 
 | 
| 
 | 
  2600   if [ -z "$ACME_DIRECTORY" ]; then
 | 
| 
 | 
  2601     if [ "$STAGE" ]; then
 | 
| 
 | 
  2602       ACME_DIRECTORY="$DEFAULT_STAGING_CA"
 | 
| 
 | 
  2603       _info "Using ACME_DIRECTORY: $ACME_DIRECTORY"
 | 
| 
 | 
  2604     else
 | 
| 
 | 
  2605       default_acme_server=$(_readaccountconf "DEFAULT_ACME_SERVER")
 | 
| 
 | 
  2606       _debug default_acme_server "$default_acme_server"
 | 
| 
 | 
  2607       if [ "$default_acme_server" ]; then
 | 
| 
 | 
  2608         ACME_DIRECTORY="$default_acme_server"
 | 
| 
 | 
  2609       else
 | 
| 
 | 
  2610         ACME_DIRECTORY="$DEFAULT_CA"
 | 
| 
 | 
  2611       fi
 | 
| 
 | 
  2612     fi
 | 
| 
 | 
  2613   fi
 | 
| 
 | 
  2614 
 | 
| 
 | 
  2615   _debug ACME_DIRECTORY "$ACME_DIRECTORY"
 | 
| 
 | 
  2616   _ACME_SERVER_HOST="$(echo "$ACME_DIRECTORY" | cut -d : -f 2 | tr -s / | cut -d / -f 2)"
 | 
| 
 | 
  2617   _debug2 "_ACME_SERVER_HOST" "$_ACME_SERVER_HOST"
 | 
| 
 | 
  2618 
 | 
| 
 | 
  2619   CA_DIR="$CA_HOME/$_ACME_SERVER_HOST"
 | 
| 
 | 
  2620 
 | 
| 
 | 
  2621   _DEFAULT_CA_CONF="$CA_DIR/ca.conf"
 | 
| 
 | 
  2622 
 | 
| 
 | 
  2623   if [ -z "$CA_CONF" ]; then
 | 
| 
 | 
  2624     CA_CONF="$_DEFAULT_CA_CONF"
 | 
| 
 | 
  2625   fi
 | 
| 
 | 
  2626   _debug3 CA_CONF "$CA_CONF"
 | 
| 
 | 
  2627 
 | 
| 
 | 
  2628   if [ -f "$CA_CONF" ]; then
 | 
| 
 | 
  2629     . "$CA_CONF"
 | 
| 
 | 
  2630   fi
 | 
| 
 | 
  2631 
 | 
| 
 | 
  2632   if [ -z "$ACME_DIR" ]; then
 | 
| 
 | 
  2633     ACME_DIR="/home/.acme"
 | 
| 
 | 
  2634   fi
 | 
| 
 | 
  2635 
 | 
| 
 | 
  2636   if [ -z "$APACHE_CONF_BACKUP_DIR" ]; then
 | 
| 
 | 
  2637     APACHE_CONF_BACKUP_DIR="$LE_CONFIG_HOME"
 | 
| 
 | 
  2638   fi
 | 
| 
 | 
  2639 
 | 
| 
 | 
  2640   if [ -z "$USER_AGENT" ]; then
 | 
| 
 | 
  2641     USER_AGENT="$DEFAULT_USER_AGENT"
 | 
| 
 | 
  2642   fi
 | 
| 
 | 
  2643 
 | 
| 
 | 
  2644   if [ -z "$HTTP_HEADER" ]; then
 | 
| 
 | 
  2645     HTTP_HEADER="$LE_CONFIG_HOME/http.header"
 | 
| 
 | 
  2646   fi
 | 
| 
 | 
  2647 
 | 
| 
 | 
  2648   _OLD_ACCOUNT_KEY="$LE_WORKING_DIR/account.key"
 | 
| 
 | 
  2649   _OLD_ACCOUNT_JSON="$LE_WORKING_DIR/account.json"
 | 
| 
 | 
  2650 
 | 
| 
 | 
  2651   _DEFAULT_ACCOUNT_KEY_PATH="$CA_DIR/account.key"
 | 
| 
 | 
  2652   _DEFAULT_ACCOUNT_JSON_PATH="$CA_DIR/account.json"
 | 
| 
 | 
  2653   if [ -z "$ACCOUNT_KEY_PATH" ]; then
 | 
| 
 | 
  2654     ACCOUNT_KEY_PATH="$_DEFAULT_ACCOUNT_KEY_PATH"
 | 
| 
 | 
  2655   fi
 | 
| 
 | 
  2656 
 | 
| 
 | 
  2657   if [ -z "$ACCOUNT_JSON_PATH" ]; then
 | 
| 
 | 
  2658     ACCOUNT_JSON_PATH="$_DEFAULT_ACCOUNT_JSON_PATH"
 | 
| 
 | 
  2659   fi
 | 
| 
 | 
  2660 
 | 
| 
 | 
  2661   _DEFAULT_CERT_HOME="$LE_CONFIG_HOME"
 | 
| 
 | 
  2662   if [ -z "$CERT_HOME" ]; then
 | 
| 
 | 
  2663     CERT_HOME="$_DEFAULT_CERT_HOME"
 | 
| 
 | 
  2664   fi
 | 
| 
 | 
  2665 
 | 
| 
 | 
  2666   if [ -z "$ACME_OPENSSL_BIN" ] || [ ! -f "$ACME_OPENSSL_BIN" ] || [ ! -x "$ACME_OPENSSL_BIN" ]; then
 | 
| 
 | 
  2667     ACME_OPENSSL_BIN="$DEFAULT_OPENSSL_BIN"
 | 
| 
 | 
  2668   fi
 | 
| 
 | 
  2669 
 | 
| 
 | 
  2670   if [ -z "$domain" ]; then
 | 
| 
 | 
  2671     return 0
 | 
| 
 | 
  2672   fi
 | 
| 
 | 
  2673 
 | 
| 
 | 
  2674   if [ -z "$DOMAIN_PATH" ]; then
 | 
| 
 | 
  2675     domainhome="$CERT_HOME/$domain"
 | 
| 
 | 
  2676     domainhomeecc="$CERT_HOME/$domain$ECC_SUFFIX"
 | 
| 
 | 
  2677 
 | 
| 
 | 
  2678     DOMAIN_PATH="$domainhome"
 | 
| 
 | 
  2679 
 | 
| 
 | 
  2680     if _isEccKey "$_ilength"; then
 | 
| 
 | 
  2681       DOMAIN_PATH="$domainhomeecc"
 | 
| 
 | 
  2682     else
 | 
| 
 | 
  2683       if [ ! -d "$domainhome" ] && [ -d "$domainhomeecc" ]; then
 | 
| 
 | 
  2684         _info "The domain '$domain' seems to have a ECC cert already, please add '$(__red "--ecc")' parameter if you want to use that cert."
 | 
| 
 | 
  2685       fi
 | 
| 
 | 
  2686     fi
 | 
| 
 | 
  2687     _debug DOMAIN_PATH "$DOMAIN_PATH"
 | 
| 
 | 
  2688   fi
 | 
| 
 | 
  2689 
 | 
| 
 | 
  2690   if [ -z "$DOMAIN_BACKUP_PATH" ]; then
 | 
| 
 | 
  2691     DOMAIN_BACKUP_PATH="$DOMAIN_PATH/backup"
 | 
| 
 | 
  2692   fi
 | 
| 
 | 
  2693 
 | 
| 
 | 
  2694   if [ -z "$DOMAIN_CONF" ]; then
 | 
| 
 | 
  2695     DOMAIN_CONF="$DOMAIN_PATH/$domain.conf"
 | 
| 
 | 
  2696   fi
 | 
| 
 | 
  2697 
 | 
| 
 | 
  2698   if [ -z "$DOMAIN_SSL_CONF" ]; then
 | 
| 
 | 
  2699     DOMAIN_SSL_CONF="$DOMAIN_PATH/$domain.csr.conf"
 | 
| 
 | 
  2700   fi
 | 
| 
 | 
  2701 
 | 
| 
 | 
  2702   if [ -z "$CSR_PATH" ]; then
 | 
| 
 | 
  2703     CSR_PATH="$DOMAIN_PATH/$domain.csr"
 | 
| 
 | 
  2704   fi
 | 
| 
 | 
  2705   if [ -z "$CERT_KEY_PATH" ]; then
 | 
| 
 | 
  2706     CERT_KEY_PATH="$DOMAIN_PATH/$domain.key"
 | 
| 
 | 
  2707   fi
 | 
| 
 | 
  2708   if [ -z "$CERT_PATH" ]; then
 | 
| 
 | 
  2709     CERT_PATH="$DOMAIN_PATH/$domain.cer"
 | 
| 
 | 
  2710   fi
 | 
| 
 | 
  2711   if [ -z "$CA_CERT_PATH" ]; then
 | 
| 
 | 
  2712     CA_CERT_PATH="$DOMAIN_PATH/ca.cer"
 | 
| 
 | 
  2713   fi
 | 
| 
 | 
  2714   if [ -z "$CERT_FULLCHAIN_PATH" ]; then
 | 
| 
 | 
  2715     CERT_FULLCHAIN_PATH="$DOMAIN_PATH/fullchain.cer"
 | 
| 
 | 
  2716   fi
 | 
| 
 | 
  2717   if [ -z "$CERT_PFX_PATH" ]; then
 | 
| 
 | 
  2718     CERT_PFX_PATH="$DOMAIN_PATH/$domain.pfx"
 | 
| 
 | 
  2719   fi
 | 
| 
 | 
  2720   if [ -z "$CERT_PKCS8_PATH" ]; then
 | 
| 
 | 
  2721     CERT_PKCS8_PATH="$DOMAIN_PATH/$domain.pkcs8"
 | 
| 
 | 
  2722   fi
 | 
| 
 | 
  2723 
 | 
| 
 | 
  2724   if [ -z "$TLS_CONF" ]; then
 | 
| 
 | 
  2725     TLS_CONF="$DOMAIN_PATH/tls.validation.conf"
 | 
| 
 | 
  2726   fi
 | 
| 
 | 
  2727   if [ -z "$TLS_CERT" ]; then
 | 
| 
 | 
  2728     TLS_CERT="$DOMAIN_PATH/tls.validation.cert"
 | 
| 
 | 
  2729   fi
 | 
| 
 | 
  2730   if [ -z "$TLS_KEY" ]; then
 | 
| 
 | 
  2731     TLS_KEY="$DOMAIN_PATH/tls.validation.key"
 | 
| 
 | 
  2732   fi
 | 
| 
 | 
  2733   if [ -z "$TLS_CSR" ]; then
 | 
| 
 | 
  2734     TLS_CSR="$DOMAIN_PATH/tls.validation.csr"
 | 
| 
 | 
  2735   fi
 | 
| 
 | 
  2736 
 | 
| 
 | 
  2737 }
 | 
| 
 | 
  2738 
 | 
| 
 | 
  2739 _exec() {
 | 
| 
 | 
  2740   if [ -z "$_EXEC_TEMP_ERR" ]; then
 | 
| 
 | 
  2741     _EXEC_TEMP_ERR="$(_mktemp)"
 | 
| 
 | 
  2742   fi
 | 
| 
 | 
  2743 
 | 
| 
 | 
  2744   if [ "$_EXEC_TEMP_ERR" ]; then
 | 
| 
 | 
  2745     eval "$@ 2>>$_EXEC_TEMP_ERR"
 | 
| 
 | 
  2746   else
 | 
| 
 | 
  2747     eval "$@"
 | 
| 
 | 
  2748   fi
 | 
| 
 | 
  2749 }
 | 
| 
 | 
  2750 
 | 
| 
 | 
  2751 _exec_err() {
 | 
| 
 | 
  2752   [ "$_EXEC_TEMP_ERR" ] && _err "$(cat "$_EXEC_TEMP_ERR")" && echo "" >"$_EXEC_TEMP_ERR"
 | 
| 
 | 
  2753 }
 | 
| 
 | 
  2754 
 | 
| 
 | 
  2755 _apachePath() {
 | 
| 
 | 
  2756   _APACHECTL="apachectl"
 | 
| 
 | 
  2757   if ! _exists apachectl; then
 | 
| 
 | 
  2758     if _exists apache2ctl; then
 | 
| 
 | 
  2759       _APACHECTL="apache2ctl"
 | 
| 
 | 
  2760     else
 | 
| 
 | 
  2761       _err "'apachectl not found. It seems that apache is not installed, or you are not root user.'"
 | 
| 
 | 
  2762       _err "Please use webroot mode to try again."
 | 
| 
 | 
  2763       return 1
 | 
| 
 | 
  2764     fi
 | 
| 
 | 
  2765   fi
 | 
| 
 | 
  2766 
 | 
| 
 | 
  2767   if ! _exec $_APACHECTL -V >/dev/null; then
 | 
| 
 | 
  2768     _exec_err
 | 
| 
 | 
  2769     return 1
 | 
| 
 | 
  2770   fi
 | 
| 
 | 
  2771 
 | 
| 
 | 
  2772   if [ "$APACHE_HTTPD_CONF" ]; then
 | 
| 
 | 
  2773     _saveaccountconf APACHE_HTTPD_CONF "$APACHE_HTTPD_CONF"
 | 
| 
 | 
  2774     httpdconf="$APACHE_HTTPD_CONF"
 | 
| 
 | 
  2775     httpdconfname="$(basename "$httpdconfname")"
 | 
| 
 | 
  2776   else
 | 
| 
 | 
  2777     httpdconfname="$($_APACHECTL -V | grep SERVER_CONFIG_FILE= | cut -d = -f 2 | tr -d '"')"
 | 
| 
 | 
  2778     _debug httpdconfname "$httpdconfname"
 | 
| 
 | 
  2779 
 | 
| 
 | 
  2780     if [ -z "$httpdconfname" ]; then
 | 
| 
 | 
  2781       _err "Can not read apache config file."
 | 
| 
 | 
  2782       return 1
 | 
| 
 | 
  2783     fi
 | 
| 
 | 
  2784 
 | 
| 
 | 
  2785     if _startswith "$httpdconfname" '/'; then
 | 
| 
 | 
  2786       httpdconf="$httpdconfname"
 | 
| 
 | 
  2787       httpdconfname="$(basename "$httpdconfname")"
 | 
| 
 | 
  2788     else
 | 
| 
 | 
  2789       httpdroot="$($_APACHECTL -V | grep HTTPD_ROOT= | cut -d = -f 2 | tr -d '"')"
 | 
| 
 | 
  2790       _debug httpdroot "$httpdroot"
 | 
| 
 | 
  2791       httpdconf="$httpdroot/$httpdconfname"
 | 
| 
 | 
  2792       httpdconfname="$(basename "$httpdconfname")"
 | 
| 
 | 
  2793     fi
 | 
| 
 | 
  2794   fi
 | 
| 
 | 
  2795   _debug httpdconf "$httpdconf"
 | 
| 
 | 
  2796   _debug httpdconfname "$httpdconfname"
 | 
| 
 | 
  2797   if [ ! -f "$httpdconf" ]; then
 | 
| 
 | 
  2798     _err "Apache Config file not found" "$httpdconf"
 | 
| 
 | 
  2799     return 1
 | 
| 
 | 
  2800   fi
 | 
| 
 | 
  2801   return 0
 | 
| 
 | 
  2802 }
 | 
| 
 | 
  2803 
 | 
| 
 | 
  2804 _restoreApache() {
 | 
| 
 | 
  2805   if [ -z "$usingApache" ]; then
 | 
| 
 | 
  2806     return 0
 | 
| 
 | 
  2807   fi
 | 
| 
 | 
  2808   _initpath
 | 
| 
 | 
  2809   if ! _apachePath; then
 | 
| 
 | 
  2810     return 1
 | 
| 
 | 
  2811   fi
 | 
| 
 | 
  2812 
 | 
| 
 | 
  2813   if [ ! -f "$APACHE_CONF_BACKUP_DIR/$httpdconfname" ]; then
 | 
| 
 | 
  2814     _debug "No config file to restore."
 | 
| 
 | 
  2815     return 0
 | 
| 
 | 
  2816   fi
 | 
| 
 | 
  2817 
 | 
| 
 | 
  2818   cat "$APACHE_CONF_BACKUP_DIR/$httpdconfname" >"$httpdconf"
 | 
| 
 | 
  2819   _debug "Restored: $httpdconf."
 | 
| 
 | 
  2820   if ! _exec $_APACHECTL -t; then
 | 
| 
 | 
  2821     _exec_err
 | 
| 
 | 
  2822     _err "Sorry, restore apache config error, please contact me."
 | 
| 
 | 
  2823     return 1
 | 
| 
 | 
  2824   fi
 | 
| 
 | 
  2825   _debug "Restored successfully."
 | 
| 
 | 
  2826   rm -f "$APACHE_CONF_BACKUP_DIR/$httpdconfname"
 | 
| 
 | 
  2827   return 0
 | 
| 
 | 
  2828 }
 | 
| 
 | 
  2829 
 | 
| 
 | 
  2830 _setApache() {
 | 
| 
 | 
  2831   _initpath
 | 
| 
 | 
  2832   if ! _apachePath; then
 | 
| 
 | 
  2833     return 1
 | 
| 
 | 
  2834   fi
 | 
| 
 | 
  2835 
 | 
| 
 | 
  2836   #test the conf first
 | 
| 
 | 
  2837   _info "Checking if there is an error in the apache config file before starting."
 | 
| 
 | 
  2838 
 | 
| 
 | 
  2839   if ! _exec "$_APACHECTL" -t >/dev/null; then
 | 
| 
 | 
  2840     _exec_err
 | 
| 
 | 
  2841     _err "The apache config file has error, please fix it first, then try again."
 | 
| 
 | 
  2842     _err "Don't worry, there is nothing changed to your system."
 | 
| 
 | 
  2843     return 1
 | 
| 
 | 
  2844   else
 | 
| 
 | 
  2845     _info "OK"
 | 
| 
 | 
  2846   fi
 | 
| 
 | 
  2847 
 | 
| 
 | 
  2848   #backup the conf
 | 
| 
 | 
  2849   _debug "Backup apache config file" "$httpdconf"
 | 
| 
 | 
  2850   if ! cp "$httpdconf" "$APACHE_CONF_BACKUP_DIR/"; then
 | 
| 
 | 
  2851     _err "Can not backup apache config file, so abort. Don't worry, the apache config is not changed."
 | 
| 
 | 
  2852     _err "This might be a bug of $PROJECT_NAME , please report issue: $PROJECT"
 | 
| 
 | 
  2853     return 1
 | 
| 
 | 
  2854   fi
 | 
| 
 | 
  2855   _info "JFYI, Config file $httpdconf is backuped to $APACHE_CONF_BACKUP_DIR/$httpdconfname"
 | 
| 
 | 
  2856   _info "In case there is an error that can not be restored automatically, you may try restore it yourself."
 | 
| 
 | 
  2857   _info "The backup file will be deleted on success, just forget it."
 | 
| 
 | 
  2858 
 | 
| 
 | 
  2859   #add alias
 | 
| 
 | 
  2860 
 | 
| 
 | 
  2861   apacheVer="$($_APACHECTL -V | grep "Server version:" | cut -d : -f 2 | cut -d " " -f 2 | cut -d '/' -f 2)"
 | 
| 
 | 
  2862   _debug "apacheVer" "$apacheVer"
 | 
| 
 | 
  2863   apacheMajor="$(echo "$apacheVer" | cut -d . -f 1)"
 | 
| 
 | 
  2864   apacheMinor="$(echo "$apacheVer" | cut -d . -f 2)"
 | 
| 
 | 
  2865 
 | 
| 
 | 
  2866   if [ "$apacheVer" ] && [ "$apacheMajor$apacheMinor" -ge "24" ]; then
 | 
| 
 | 
  2867     echo "
 | 
| 
 | 
  2868 Alias /.well-known/acme-challenge  $ACME_DIR
 | 
| 
 | 
  2869 <Directory $ACME_DIR >
 | 
| 
 | 
  2870 Require all granted
 | 
| 
 | 
  2871 </Directory>
 | 
| 
 | 
  2872   " >>"$httpdconf"
 | 
| 
 | 
  2873   else
 | 
| 
 | 
  2874     echo "
 | 
| 
 | 
  2875 Alias /.well-known/acme-challenge  $ACME_DIR
 | 
| 
 | 
  2876 <Directory $ACME_DIR >
 | 
| 
 | 
  2877 Order allow,deny
 | 
| 
 | 
  2878 Allow from all
 | 
| 
 | 
  2879 </Directory>
 | 
| 
 | 
  2880   " >>"$httpdconf"
 | 
| 
 | 
  2881   fi
 | 
| 
 | 
  2882 
 | 
| 
 | 
  2883   _msg="$($_APACHECTL -t 2>&1)"
 | 
| 
 | 
  2884   if [ "$?" != "0" ]; then
 | 
| 
 | 
  2885     _err "Sorry, apache config error"
 | 
| 
 | 
  2886     if _restoreApache; then
 | 
| 
 | 
  2887       _err "The apache config file is restored."
 | 
| 
 | 
  2888     else
 | 
| 
 | 
  2889       _err "Sorry, the apache config file can not be restored, please report bug."
 | 
| 
 | 
  2890     fi
 | 
| 
 | 
  2891     return 1
 | 
| 
 | 
  2892   fi
 | 
| 
 | 
  2893 
 | 
| 
 | 
  2894   if [ ! -d "$ACME_DIR" ]; then
 | 
| 
 | 
  2895     mkdir -p "$ACME_DIR"
 | 
| 
 | 
  2896     chmod 755 "$ACME_DIR"
 | 
| 
 | 
  2897   fi
 | 
| 
 | 
  2898 
 | 
| 
 | 
  2899   if ! _exec "$_APACHECTL" graceful; then
 | 
| 
 | 
  2900     _exec_err
 | 
| 
 | 
  2901     _err "$_APACHECTL  graceful error, please contact me."
 | 
| 
 | 
  2902     _restoreApache
 | 
| 
 | 
  2903     return 1
 | 
| 
 | 
  2904   fi
 | 
| 
 | 
  2905   usingApache="1"
 | 
| 
 | 
  2906   return 0
 | 
| 
 | 
  2907 }
 | 
| 
 | 
  2908 
 | 
| 
 | 
  2909 #find the real nginx conf file
 | 
| 
 | 
  2910 #backup
 | 
| 
 | 
  2911 #set the nginx conf
 | 
| 
 | 
  2912 #returns the real nginx conf file
 | 
| 
 | 
  2913 _setNginx() {
 | 
| 
 | 
  2914   _d="$1"
 | 
| 
 | 
  2915   _croot="$2"
 | 
| 
 | 
  2916   _thumbpt="$3"
 | 
| 
 | 
  2917 
 | 
| 
 | 
  2918   FOUND_REAL_NGINX_CONF=""
 | 
| 
 | 
  2919   FOUND_REAL_NGINX_CONF_LN=""
 | 
| 
 | 
  2920   BACKUP_NGINX_CONF=""
 | 
| 
 | 
  2921   _debug _croot "$_croot"
 | 
| 
 | 
  2922   _start_f="$(echo "$_croot" | cut -d : -f 2)"
 | 
| 
 | 
  2923   _debug _start_f "$_start_f"
 | 
| 
 | 
  2924   if [ -z "$_start_f" ]; then
 | 
| 
 | 
  2925     _debug "find start conf from nginx command"
 | 
| 
 | 
  2926     if [ -z "$NGINX_CONF" ]; then
 | 
| 
 | 
  2927       if ! _exists "nginx"; then
 | 
| 
 | 
  2928         _err "nginx command is not found."
 | 
| 
 | 
  2929         return 1
 | 
| 
 | 
  2930       fi
 | 
| 
 | 
  2931       NGINX_CONF="$(nginx -V 2>&1 | _egrep_o "--conf-path=[^ ]* " | tr -d " ")"
 | 
| 
 | 
  2932       _debug NGINX_CONF "$NGINX_CONF"
 | 
| 
 | 
  2933       NGINX_CONF="$(echo "$NGINX_CONF" | cut -d = -f 2)"
 | 
| 
 | 
  2934       _debug NGINX_CONF "$NGINX_CONF"
 | 
| 
 | 
  2935       if [ -z "$NGINX_CONF" ]; then
 | 
| 
 | 
  2936         _err "Can not find nginx conf."
 | 
| 
 | 
  2937         NGINX_CONF=""
 | 
| 
 | 
  2938         return 1
 | 
| 
 | 
  2939       fi
 | 
| 
 | 
  2940       if [ ! -f "$NGINX_CONF" ]; then
 | 
| 
 | 
  2941         _err "'$NGINX_CONF' doesn't exist."
 | 
| 
 | 
  2942         NGINX_CONF=""
 | 
| 
 | 
  2943         return 1
 | 
| 
 | 
  2944       fi
 | 
| 
 | 
  2945       _debug "Found nginx conf file:$NGINX_CONF"
 | 
| 
 | 
  2946     fi
 | 
| 
 | 
  2947     _start_f="$NGINX_CONF"
 | 
| 
 | 
  2948   fi
 | 
| 
 | 
  2949   _debug "Start detect nginx conf for $_d from:$_start_f"
 | 
| 
 | 
  2950   if ! _checkConf "$_d" "$_start_f"; then
 | 
| 
 | 
  2951     _err "Can not find conf file for domain $d"
 | 
| 
 | 
  2952     return 1
 | 
| 
 | 
  2953   fi
 | 
| 
 | 
  2954   _info "Found conf file: $FOUND_REAL_NGINX_CONF"
 | 
| 
 | 
  2955 
 | 
| 
 | 
  2956   _ln=$FOUND_REAL_NGINX_CONF_LN
 | 
| 
 | 
  2957   _debug "_ln" "$_ln"
 | 
| 
 | 
  2958 
 | 
| 
 | 
  2959   _lnn=$(_math $_ln + 1)
 | 
| 
 | 
  2960   _debug _lnn "$_lnn"
 | 
| 
 | 
  2961   _start_tag="$(sed -n "$_lnn,${_lnn}p" "$FOUND_REAL_NGINX_CONF")"
 | 
| 
 | 
  2962   _debug "_start_tag" "$_start_tag"
 | 
| 
 | 
  2963   if [ "$_start_tag" = "$NGINX_START" ]; then
 | 
| 
 | 
  2964     _info "The domain $_d is already configured, skip"
 | 
| 
 | 
  2965     FOUND_REAL_NGINX_CONF=""
 | 
| 
 | 
  2966     return 0
 | 
| 
 | 
  2967   fi
 | 
| 
 | 
  2968 
 | 
| 
 | 
  2969   mkdir -p "$DOMAIN_BACKUP_PATH"
 | 
| 
 | 
  2970   _backup_conf="$DOMAIN_BACKUP_PATH/$_d.nginx.conf"
 | 
| 
 | 
  2971   _debug _backup_conf "$_backup_conf"
 | 
| 
 | 
  2972   BACKUP_NGINX_CONF="$_backup_conf"
 | 
| 
 | 
  2973   _info "Backup $FOUND_REAL_NGINX_CONF to $_backup_conf"
 | 
| 
 | 
  2974   if ! cp "$FOUND_REAL_NGINX_CONF" "$_backup_conf"; then
 | 
| 
 | 
  2975     _err "backup error."
 | 
| 
 | 
  2976     FOUND_REAL_NGINX_CONF=""
 | 
| 
 | 
  2977     return 1
 | 
| 
 | 
  2978   fi
 | 
| 
 | 
  2979 
 | 
| 
 | 
  2980   if ! _exists "nginx"; then
 | 
| 
 | 
  2981     _err "nginx command is not found."
 | 
| 
 | 
  2982     return 1
 | 
| 
 | 
  2983   fi
 | 
| 
 | 
  2984   _info "Check the nginx conf before setting up."
 | 
| 
 | 
  2985   if ! _exec "nginx -t" >/dev/null; then
 | 
| 
 | 
  2986     _exec_err
 | 
| 
 | 
  2987     return 1
 | 
| 
 | 
  2988   fi
 | 
| 
 | 
  2989 
 | 
| 
 | 
  2990   _info "OK, Set up nginx config file"
 | 
| 
 | 
  2991 
 | 
| 
 | 
  2992   if ! sed -n "1,${_ln}p" "$_backup_conf" >"$FOUND_REAL_NGINX_CONF"; then
 | 
| 
 | 
  2993     cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF"
 | 
| 
 | 
  2994     _err "write nginx conf error, but don't worry, the file is restored to the original version."
 | 
| 
 | 
  2995     return 1
 | 
| 
 | 
  2996   fi
 | 
| 
 | 
  2997 
 | 
| 
 | 
  2998   echo "$NGINX_START
 | 
| 
 | 
  2999 location ~ \"^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)\$\" {
 | 
| 
 | 
  3000   default_type text/plain;
 | 
| 
 | 
  3001   return 200 \"\$1.$_thumbpt\";
 | 
| 
 | 
  3002 }
 | 
| 
 | 
  3003 #NGINX_START
 | 
| 
 | 
  3004 " >>"$FOUND_REAL_NGINX_CONF"
 | 
| 
 | 
  3005 
 | 
| 
 | 
  3006   if ! sed -n "${_lnn},99999p" "$_backup_conf" >>"$FOUND_REAL_NGINX_CONF"; then
 | 
| 
 | 
  3007     cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF"
 | 
| 
 | 
  3008     _err "write nginx conf error, but don't worry, the file is restored."
 | 
| 
 | 
  3009     return 1
 | 
| 
 | 
  3010   fi
 | 
| 
 | 
  3011   _debug3 "Modified config:$(cat $FOUND_REAL_NGINX_CONF)"
 | 
| 
 | 
  3012   _info "nginx conf is done, let's check it again."
 | 
| 
 | 
  3013   if ! _exec "nginx -t" >/dev/null; then
 | 
| 
 | 
  3014     _exec_err
 | 
| 
 | 
  3015     _err "It seems that nginx conf was broken, let's restore."
 | 
| 
 | 
  3016     cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF"
 | 
| 
 | 
  3017     return 1
 | 
| 
 | 
  3018   fi
 | 
| 
 | 
  3019 
 | 
| 
 | 
  3020   _info "Reload nginx"
 | 
| 
 | 
  3021   if ! _exec "nginx -s reload" >/dev/null; then
 | 
| 
 | 
  3022     _exec_err
 | 
| 
 | 
  3023     _err "It seems that nginx reload error, let's restore."
 | 
| 
 | 
  3024     cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF"
 | 
| 
 | 
  3025     return 1
 | 
| 
 | 
  3026   fi
 | 
| 
 | 
  3027 
 | 
| 
 | 
  3028   return 0
 | 
| 
 | 
  3029 }
 | 
| 
 | 
  3030 
 | 
| 
 | 
  3031 #d , conf
 | 
| 
 | 
  3032 _checkConf() {
 | 
| 
 | 
  3033   _d="$1"
 | 
| 
 | 
  3034   _c_file="$2"
 | 
| 
 | 
  3035   _debug "Start _checkConf from:$_c_file"
 | 
| 
 | 
  3036   if [ ! -f "$2" ] && ! echo "$2" | grep '*$' >/dev/null && echo "$2" | grep '*' >/dev/null; then
 | 
| 
 | 
  3037     _debug "wildcard"
 | 
| 
 | 
  3038     for _w_f in $2; do
 | 
| 
 | 
  3039       if [ -f "$_w_f" ] && _checkConf "$1" "$_w_f"; then
 | 
| 
 | 
  3040         return 0
 | 
| 
 | 
  3041       fi
 | 
| 
 | 
  3042     done
 | 
| 
 | 
  3043     #not found
 | 
| 
 | 
  3044     return 1
 | 
| 
 | 
  3045   elif [ -f "$2" ]; then
 | 
| 
 | 
  3046     _debug "single"
 | 
| 
 | 
  3047     if _isRealNginxConf "$1" "$2"; then
 | 
| 
 | 
  3048       _debug "$2 is found."
 | 
| 
 | 
  3049       FOUND_REAL_NGINX_CONF="$2"
 | 
| 
 | 
  3050       return 0
 | 
| 
 | 
  3051     fi
 | 
| 
 | 
  3052     if cat "$2" | tr "\t" " " | grep "^ *include *.*;" >/dev/null; then
 | 
| 
 | 
  3053       _debug "Try include files"
 | 
| 
 | 
  3054       for included in $(cat "$2" | tr "\t" " " | grep "^ *include *.*;" | sed "s/include //" | tr -d " ;"); do
 | 
| 
 | 
  3055         _debug "check included $included"
 | 
| 
 | 
  3056         if _checkConf "$1" "$included"; then
 | 
| 
 | 
  3057           return 0
 | 
| 
 | 
  3058         fi
 | 
| 
 | 
  3059       done
 | 
| 
 | 
  3060     fi
 | 
| 
 | 
  3061     return 1
 | 
| 
 | 
  3062   else
 | 
| 
 | 
  3063     _debug "$2 not found."
 | 
| 
 | 
  3064     return 1
 | 
| 
 | 
  3065   fi
 | 
| 
 | 
  3066   return 1
 | 
| 
 | 
  3067 }
 | 
| 
 | 
  3068 
 | 
| 
 | 
  3069 #d , conf
 | 
| 
 | 
  3070 _isRealNginxConf() {
 | 
| 
 | 
  3071   _debug "_isRealNginxConf $1 $2"
 | 
| 
 | 
  3072   if [ -f "$2" ]; then
 | 
| 
 | 
  3073     for _fln in $(tr "\t" ' ' <"$2" | grep -n "^ *server_name.* $1" | cut -d : -f 1); do
 | 
| 
 | 
  3074       _debug _fln "$_fln"
 | 
| 
 | 
  3075       if [ "$_fln" ]; then
 | 
| 
 | 
  3076         _start=$(tr "\t" ' ' <"$2" | _head_n "$_fln" | grep -n "^ *server *" | grep -v server_name | _tail_n 1)
 | 
| 
 | 
  3077         _debug "_start" "$_start"
 | 
| 
 | 
  3078         _start_n=$(echo "$_start" | cut -d : -f 1)
 | 
| 
 | 
  3079         _start_nn=$(_math $_start_n + 1)
 | 
| 
 | 
  3080         _debug "_start_n" "$_start_n"
 | 
| 
 | 
  3081         _debug "_start_nn" "$_start_nn"
 | 
| 
 | 
  3082 
 | 
| 
 | 
  3083         _left="$(sed -n "${_start_nn},99999p" "$2")"
 | 
| 
 | 
  3084         _debug2 _left "$_left"
 | 
| 
 | 
  3085         _end="$(echo "$_left" | tr "\t" ' ' | grep -n "^ *server *" | grep -v server_name | _head_n 1)"
 | 
| 
 | 
  3086         _debug "_end" "$_end"
 | 
| 
 | 
  3087         if [ "$_end" ]; then
 | 
| 
 | 
  3088           _end_n=$(echo "$_end" | cut -d : -f 1)
 | 
| 
 | 
  3089           _debug "_end_n" "$_end_n"
 | 
| 
 | 
  3090           _seg_n=$(echo "$_left" | sed -n "1,${_end_n}p")
 | 
| 
 | 
  3091         else
 | 
| 
 | 
  3092           _seg_n="$_left"
 | 
| 
 | 
  3093         fi
 | 
| 
 | 
  3094 
 | 
| 
 | 
  3095         _debug "_seg_n" "$_seg_n"
 | 
| 
 | 
  3096 
 | 
| 
 | 
  3097         _skip_ssl=1
 | 
| 
 | 
  3098         for _listen_i in $(echo "$_seg_n" | tr "\t" ' ' | grep "^ *listen" | tr -d " "); do
 | 
| 
 | 
  3099           if [ "$_listen_i" ]; then
 | 
| 
 | 
  3100             if [ "$(echo "$_listen_i" | _egrep_o "listen.*ssl")" ]; then
 | 
| 
 | 
  3101               _debug2 "$_listen_i is ssl"
 | 
| 
 | 
  3102             else
 | 
| 
 | 
  3103               _debug2 "$_listen_i is plain text"
 | 
| 
 | 
  3104               _skip_ssl=""
 | 
| 
 | 
  3105               break
 | 
| 
 | 
  3106             fi
 | 
| 
 | 
  3107           fi
 | 
| 
 | 
  3108         done
 | 
| 
 | 
  3109 
 | 
| 
 | 
  3110         if [ "$_skip_ssl" = "1" ]; then
 | 
| 
 | 
  3111           _debug "ssl on, skip"
 | 
| 
 | 
  3112         else
 | 
| 
 | 
  3113           FOUND_REAL_NGINX_CONF_LN=$_fln
 | 
| 
 | 
  3114           _debug3 "found FOUND_REAL_NGINX_CONF_LN" "$FOUND_REAL_NGINX_CONF_LN"
 | 
| 
 | 
  3115           return 0
 | 
| 
 | 
  3116         fi
 | 
| 
 | 
  3117       fi
 | 
| 
 | 
  3118     done
 | 
| 
 | 
  3119   fi
 | 
| 
 | 
  3120   return 1
 | 
| 
 | 
  3121 }
 | 
| 
 | 
  3122 
 | 
| 
 | 
  3123 #restore all the nginx conf
 | 
| 
 | 
  3124 _restoreNginx() {
 | 
| 
 | 
  3125   if [ -z "$NGINX_RESTORE_VLIST" ]; then
 | 
| 
 | 
  3126     _debug "No need to restore nginx, skip."
 | 
| 
 | 
  3127     return
 | 
| 
 | 
  3128   fi
 | 
| 
 | 
  3129   _debug "_restoreNginx"
 | 
| 
 | 
  3130   _debug "NGINX_RESTORE_VLIST" "$NGINX_RESTORE_VLIST"
 | 
| 
 | 
  3131 
 | 
| 
 | 
  3132   for ng_entry in $(echo "$NGINX_RESTORE_VLIST" | tr "$dvsep" ' '); do
 | 
| 
 | 
  3133     _debug "ng_entry" "$ng_entry"
 | 
| 
 | 
  3134     _nd=$(echo "$ng_entry" | cut -d "$sep" -f 1)
 | 
| 
 | 
  3135     _ngconf=$(echo "$ng_entry" | cut -d "$sep" -f 2)
 | 
| 
 | 
  3136     _ngbackupconf=$(echo "$ng_entry" | cut -d "$sep" -f 3)
 | 
| 
 | 
  3137     _info "Restoring from $_ngbackupconf to $_ngconf"
 | 
| 
 | 
  3138     cat "$_ngbackupconf" >"$_ngconf"
 | 
| 
 | 
  3139   done
 | 
| 
 | 
  3140 
 | 
| 
 | 
  3141   _info "Reload nginx"
 | 
| 
 | 
  3142   if ! _exec "nginx -s reload" >/dev/null; then
 | 
| 
 | 
  3143     _exec_err
 | 
| 
 | 
  3144     _err "It seems that nginx reload error, please report bug."
 | 
| 
 | 
  3145     return 1
 | 
| 
 | 
  3146   fi
 | 
| 
 | 
  3147   return 0
 | 
| 
 | 
  3148 }
 | 
| 
 | 
  3149 
 | 
| 
 | 
  3150 _clearup() {
 | 
| 
 | 
  3151   _stopserver "$serverproc"
 | 
| 
 | 
  3152   serverproc=""
 | 
| 
 | 
  3153   _restoreApache
 | 
| 
 | 
  3154   _restoreNginx
 | 
| 
 | 
  3155   _clearupdns
 | 
| 
 | 
  3156   if [ -z "$DEBUG" ]; then
 | 
| 
 | 
  3157     rm -f "$TLS_CONF"
 | 
| 
 | 
  3158     rm -f "$TLS_CERT"
 | 
| 
 | 
  3159     rm -f "$TLS_KEY"
 | 
| 
 | 
  3160     rm -f "$TLS_CSR"
 | 
| 
 | 
  3161   fi
 | 
| 
 | 
  3162 }
 | 
| 
 | 
  3163 
 | 
| 
 | 
  3164 _clearupdns() {
 | 
| 
 | 
  3165   _debug "_clearupdns"
 | 
| 
 | 
  3166   _debug "dns_entries" "$dns_entries"
 | 
| 
 | 
  3167 
 | 
| 
 | 
  3168   if [ -z "$dns_entries" ]; then
 | 
| 
 | 
  3169     _debug "skip dns."
 | 
| 
 | 
  3170     return
 | 
| 
 | 
  3171   fi
 | 
| 
 | 
  3172   _info "Removing DNS records."
 | 
| 
 | 
  3173 
 | 
| 
 | 
  3174   for entry in $dns_entries; do
 | 
| 
 | 
  3175     d=$(_getfield "$entry" 1)
 | 
| 
 | 
  3176     txtdomain=$(_getfield "$entry" 2)
 | 
| 
 | 
  3177     aliasDomain=$(_getfield "$entry" 3)
 | 
| 
 | 
  3178     _currentRoot=$(_getfield "$entry" 4)
 | 
| 
 | 
  3179     txt=$(_getfield "$entry" 5)
 | 
| 
 | 
  3180     d_api=$(_getfield "$entry" 6)
 | 
| 
 | 
  3181     _debug "d" "$d"
 | 
| 
 | 
  3182     _debug "txtdomain" "$txtdomain"
 | 
| 
 | 
  3183     _debug "aliasDomain" "$aliasDomain"
 | 
| 
 | 
  3184     _debug "_currentRoot" "$_currentRoot"
 | 
| 
 | 
  3185     _debug "txt" "$txt"
 | 
| 
 | 
  3186     _debug "d_api" "$d_api"
 | 
| 
 | 
  3187     if [ "$d_api" = "$txt" ]; then
 | 
| 
 | 
  3188       d_api=""
 | 
| 
 | 
  3189     fi
 | 
| 
 | 
  3190 
 | 
| 
 | 
  3191     if [ -z "$d_api" ]; then
 | 
| 
 | 
  3192       _info "Not Found domain api file: $d_api"
 | 
| 
 | 
  3193       continue
 | 
| 
 | 
  3194     fi
 | 
| 
 | 
  3195 
 | 
| 
 | 
  3196     if [ "$aliasDomain" ]; then
 | 
| 
 | 
  3197       txtdomain="$aliasDomain"
 | 
| 
 | 
  3198     fi
 | 
| 
 | 
  3199 
 | 
| 
 | 
  3200     (
 | 
| 
 | 
  3201       if ! . "$d_api"; then
 | 
| 
 | 
  3202         _err "Load file $d_api error. Please check your api file and try again."
 | 
| 
 | 
  3203         return 1
 | 
| 
 | 
  3204       fi
 | 
| 
 | 
  3205 
 | 
| 
 | 
  3206       rmcommand="${_currentRoot}_rm"
 | 
| 
 | 
  3207       if ! _exists "$rmcommand"; then
 | 
| 
 | 
  3208         _err "It seems that your api file doesn't define $rmcommand"
 | 
| 
 | 
  3209         return 1
 | 
| 
 | 
  3210       fi
 | 
| 
 | 
  3211       _info "Removing txt: $txt for domain: $txtdomain"
 | 
| 
 | 
  3212       if ! $rmcommand "$txtdomain" "$txt"; then
 | 
| 
 | 
  3213         _err "Error removing txt for domain:$txtdomain"
 | 
| 
 | 
  3214         return 1
 | 
| 
 | 
  3215       fi
 | 
| 
 | 
  3216       _info "Removed: Success"
 | 
| 
 | 
  3217     )
 | 
| 
 | 
  3218 
 | 
| 
 | 
  3219   done
 | 
| 
 | 
  3220 }
 | 
| 
 | 
  3221 
 | 
| 
 | 
  3222 # webroot  removelevel tokenfile
 | 
| 
 | 
  3223 _clearupwebbroot() {
 | 
| 
 | 
  3224   __webroot="$1"
 | 
| 
 | 
  3225   if [ -z "$__webroot" ]; then
 | 
| 
 | 
  3226     _debug "no webroot specified, skip"
 | 
| 
 | 
  3227     return 0
 | 
| 
 | 
  3228   fi
 | 
| 
 | 
  3229 
 | 
| 
 | 
  3230   _rmpath=""
 | 
| 
 | 
  3231   if [ "$2" = '1' ]; then
 | 
| 
 | 
  3232     _rmpath="$__webroot/.well-known"
 | 
| 
 | 
  3233   elif [ "$2" = '2' ]; then
 | 
| 
 | 
  3234     _rmpath="$__webroot/.well-known/acme-challenge"
 | 
| 
 | 
  3235   elif [ "$2" = '3' ]; then
 | 
| 
 | 
  3236     _rmpath="$__webroot/.well-known/acme-challenge/$3"
 | 
| 
 | 
  3237   else
 | 
| 
 | 
  3238     _debug "Skip for removelevel:$2"
 | 
| 
 | 
  3239   fi
 | 
| 
 | 
  3240 
 | 
| 
 | 
  3241   if [ "$_rmpath" ]; then
 | 
| 
 | 
  3242     if [ "$DEBUG" ]; then
 | 
| 
 | 
  3243       _debug "Debugging, skip removing: $_rmpath"
 | 
| 
 | 
  3244     else
 | 
| 
 | 
  3245       rm -rf "$_rmpath"
 | 
| 
 | 
  3246     fi
 | 
| 
 | 
  3247   fi
 | 
| 
 | 
  3248 
 | 
| 
 | 
  3249   return 0
 | 
| 
 | 
  3250 
 | 
| 
 | 
  3251 }
 | 
| 
 | 
  3252 
 | 
| 
 | 
  3253 _on_before_issue() {
 | 
| 
 | 
  3254   _chk_web_roots="$1"
 | 
| 
 | 
  3255   _chk_main_domain="$2"
 | 
| 
 | 
  3256   _chk_alt_domains="$3"
 | 
| 
 | 
  3257   _chk_pre_hook="$4"
 | 
| 
 | 
  3258   _chk_local_addr="$5"
 | 
| 
 | 
  3259   _debug _on_before_issue
 | 
| 
 | 
  3260   _debug _chk_main_domain "$_chk_main_domain"
 | 
| 
 | 
  3261   _debug _chk_alt_domains "$_chk_alt_domains"
 | 
| 
 | 
  3262   #run pre hook
 | 
| 
 | 
  3263   if [ "$_chk_pre_hook" ]; then
 | 
| 
 | 
  3264     _info "Run pre hook:'$_chk_pre_hook'"
 | 
| 
 | 
  3265     if ! (
 | 
| 
 | 
  3266       cd "$DOMAIN_PATH" && eval "$_chk_pre_hook"
 | 
| 
 | 
  3267     ); then
 | 
| 
 | 
  3268       _err "Error when run pre hook."
 | 
| 
 | 
  3269       return 1
 | 
| 
 | 
  3270     fi
 | 
| 
 | 
  3271   fi
 | 
| 
 | 
  3272 
 | 
| 
 | 
  3273   if _hasfield "$_chk_web_roots" "$NO_VALUE"; then
 | 
| 
 | 
  3274     if ! _exists "socat"; then
 | 
| 
 | 
  3275       _err "Please install socat tools first."
 | 
| 
 | 
  3276       return 1
 | 
| 
 | 
  3277     fi
 | 
| 
 | 
  3278   fi
 | 
| 
 | 
  3279 
 | 
| 
 | 
  3280   _debug Le_LocalAddress "$_chk_local_addr"
 | 
| 
 | 
  3281 
 | 
| 
 | 
  3282   _index=1
 | 
| 
 | 
  3283   _currentRoot=""
 | 
| 
 | 
  3284   _addrIndex=1
 | 
| 
 | 
  3285   _w_index=1
 | 
| 
 | 
  3286   while true; do
 | 
| 
 | 
  3287     d="$(echo "$_chk_main_domain,$_chk_alt_domains," | cut -d , -f "$_w_index")"
 | 
| 
 | 
  3288     _w_index="$(_math "$_w_index" + 1)"
 | 
| 
 | 
  3289     _debug d "$d"
 | 
| 
 | 
  3290     if [ -z "$d" ]; then
 | 
| 
 | 
  3291       break
 | 
| 
 | 
  3292     fi
 | 
| 
 | 
  3293     _debug "Check for domain" "$d"
 | 
| 
 | 
  3294     _currentRoot="$(_getfield "$_chk_web_roots" $_index)"
 | 
| 
 | 
  3295     _debug "_currentRoot" "$_currentRoot"
 | 
| 
 | 
  3296     _index=$(_math $_index + 1)
 | 
| 
 | 
  3297     _checkport=""
 | 
| 
 | 
  3298     if [ "$_currentRoot" = "$NO_VALUE" ]; then
 | 
| 
 | 
  3299       _info "Standalone mode."
 | 
| 
 | 
  3300       if [ -z "$Le_HTTPPort" ]; then
 | 
| 
 | 
  3301         Le_HTTPPort=80
 | 
| 
 | 
  3302         _cleardomainconf "Le_HTTPPort"
 | 
| 
 | 
  3303       else
 | 
| 
 | 
  3304         _savedomainconf "Le_HTTPPort" "$Le_HTTPPort"
 | 
| 
 | 
  3305       fi
 | 
| 
 | 
  3306       _checkport="$Le_HTTPPort"
 | 
| 
 | 
  3307     elif [ "$_currentRoot" = "$W_ALPN" ]; then
 | 
| 
 | 
  3308       _info "Standalone alpn mode."
 | 
| 
 | 
  3309       if [ -z "$Le_TLSPort" ]; then
 | 
| 
 | 
  3310         Le_TLSPort=443
 | 
| 
 | 
  3311       else
 | 
| 
 | 
  3312         _savedomainconf "Le_TLSPort" "$Le_TLSPort"
 | 
| 
 | 
  3313       fi
 | 
| 
 | 
  3314       _checkport="$Le_TLSPort"
 | 
| 
 | 
  3315     fi
 | 
| 
 | 
  3316 
 | 
| 
 | 
  3317     if [ "$_checkport" ]; then
 | 
| 
 | 
  3318       _debug _checkport "$_checkport"
 | 
| 
 | 
  3319       _checkaddr="$(_getfield "$_chk_local_addr" $_addrIndex)"
 | 
| 
 | 
  3320       _debug _checkaddr "$_checkaddr"
 | 
| 
 | 
  3321 
 | 
| 
 | 
  3322       _addrIndex="$(_math $_addrIndex + 1)"
 | 
| 
 | 
  3323 
 | 
| 
 | 
  3324       _netprc="$(_ss "$_checkport" | grep "$_checkport")"
 | 
| 
 | 
  3325       netprc="$(echo "$_netprc" | grep "$_checkaddr")"
 | 
| 
 | 
  3326       if [ -z "$netprc" ]; then
 | 
| 
 | 
  3327         netprc="$(echo "$_netprc" | grep "$LOCAL_ANY_ADDRESS")"
 | 
| 
 | 
  3328       fi
 | 
| 
 | 
  3329       if [ "$netprc" ]; then
 | 
| 
 | 
  3330         _err "$netprc"
 | 
| 
 | 
  3331         _err "tcp port $_checkport is already used by $(echo "$netprc" | cut -d : -f 4)"
 | 
| 
 | 
  3332         _err "Please stop it first"
 | 
| 
 | 
  3333         return 1
 | 
| 
 | 
  3334       fi
 | 
| 
 | 
  3335     fi
 | 
| 
 | 
  3336   done
 | 
| 
 | 
  3337 
 | 
| 
 | 
  3338   if _hasfield "$_chk_web_roots" "apache"; then
 | 
| 
 | 
  3339     if ! _setApache; then
 | 
| 
 | 
  3340       _err "set up apache error. Report error to me."
 | 
| 
 | 
  3341       return 1
 | 
| 
 | 
  3342     fi
 | 
| 
 | 
  3343   else
 | 
| 
 | 
  3344     usingApache=""
 | 
| 
 | 
  3345   fi
 | 
| 
 | 
  3346 
 | 
| 
 | 
  3347 }
 | 
| 
 | 
  3348 
 | 
| 
 | 
  3349 _on_issue_err() {
 | 
| 
 | 
  3350   _chk_post_hook="$1"
 | 
| 
 | 
  3351   _chk_vlist="$2"
 | 
| 
 | 
  3352   _debug _on_issue_err
 | 
| 
 | 
  3353 
 | 
| 
 | 
  3354   if [ "$LOG_FILE" ]; then
 | 
| 
 | 
  3355     _err "Please check log file for more details: $LOG_FILE"
 | 
| 
 | 
  3356   else
 | 
| 
 | 
  3357     _err "Please add '--debug' or '--log' to check more details."
 | 
| 
 | 
  3358     _err "See: $_DEBUG_WIKI"
 | 
| 
 | 
  3359   fi
 | 
| 
 | 
  3360 
 | 
| 
 | 
  3361   #run the post hook
 | 
| 
 | 
  3362   if [ "$_chk_post_hook" ]; then
 | 
| 
 | 
  3363     _info "Run post hook:'$_chk_post_hook'"
 | 
| 
 | 
  3364     if ! (
 | 
| 
 | 
  3365       cd "$DOMAIN_PATH" && eval "$_chk_post_hook"
 | 
| 
 | 
  3366     ); then
 | 
| 
 | 
  3367       _err "Error when run post hook."
 | 
| 
 | 
  3368       return 1
 | 
| 
 | 
  3369     fi
 | 
| 
 | 
  3370   fi
 | 
| 
 | 
  3371 
 | 
| 
 | 
  3372   #trigger the validation to flush the pending authz
 | 
| 
 | 
  3373   _debug2 "_chk_vlist" "$_chk_vlist"
 | 
| 
 | 
  3374   if [ "$_chk_vlist" ]; then
 | 
| 
 | 
  3375     (
 | 
| 
 | 
  3376       _debug2 "start to deactivate authz"
 | 
| 
 | 
  3377       ventries=$(echo "$_chk_vlist" | tr "$dvsep" ' ')
 | 
| 
 | 
  3378       for ventry in $ventries; do
 | 
| 
 | 
  3379         d=$(echo "$ventry" | cut -d "$sep" -f 1)
 | 
| 
 | 
  3380         keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2)
 | 
| 
 | 
  3381         uri=$(echo "$ventry" | cut -d "$sep" -f 3)
 | 
| 
 | 
  3382         vtype=$(echo "$ventry" | cut -d "$sep" -f 4)
 | 
| 
 | 
  3383         _currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5)
 | 
| 
 | 
  3384         __trigger_validation "$uri" "$keyauthorization"
 | 
| 
 | 
  3385       done
 | 
| 
 | 
  3386     )
 | 
| 
 | 
  3387   fi
 | 
| 
 | 
  3388 
 | 
| 
 | 
  3389   if [ "$_ACME_IS_RENEW" = "1" ] && _hasfield "$Le_Webroot" "$W_DNS"; then
 | 
| 
 | 
  3390     _err "$_DNS_MANUAL_ERR"
 | 
| 
 | 
  3391   fi
 | 
| 
 | 
  3392 
 | 
| 
 | 
  3393   if [ "$DEBUG" ] && [ "$DEBUG" -gt "0" ]; then
 | 
| 
 | 
  3394     _debug "$(_dlg_versions)"
 | 
| 
 | 
  3395   fi
 | 
| 
 | 
  3396 
 | 
| 
 | 
  3397 }
 | 
| 
 | 
  3398 
 | 
| 
 | 
  3399 _on_issue_success() {
 | 
| 
 | 
  3400   _chk_post_hook="$1"
 | 
| 
 | 
  3401   _chk_renew_hook="$2"
 | 
| 
 | 
  3402   _debug _on_issue_success
 | 
| 
 | 
  3403 
 | 
| 
 | 
  3404   #run the post hook
 | 
| 
 | 
  3405   if [ "$_chk_post_hook" ]; then
 | 
| 
 | 
  3406     _info "Run post hook:'$_chk_post_hook'"
 | 
| 
 | 
  3407     if ! (
 | 
| 
 | 
  3408       export CERT_PATH
 | 
| 
 | 
  3409       export CERT_KEY_PATH
 | 
| 
 | 
  3410       export CA_CERT_PATH
 | 
| 
 | 
  3411       export CERT_FULLCHAIN_PATH
 | 
| 
 | 
  3412       export Le_Domain="$_main_domain"
 | 
| 
 | 
  3413       cd "$DOMAIN_PATH" && eval "$_chk_post_hook"
 | 
| 
 | 
  3414     ); then
 | 
| 
 | 
  3415       _err "Error when run post hook."
 | 
| 
 | 
  3416       return 1
 | 
| 
 | 
  3417     fi
 | 
| 
 | 
  3418   fi
 | 
| 
 | 
  3419 
 | 
| 
 | 
  3420   #run renew hook
 | 
| 
 | 
  3421   if [ "$_ACME_IS_RENEW" ] && [ "$_chk_renew_hook" ]; then
 | 
| 
 | 
  3422     _info "Run renew hook:'$_chk_renew_hook'"
 | 
| 
 | 
  3423     if ! (
 | 
| 
 | 
  3424       export CERT_PATH
 | 
| 
 | 
  3425       export CERT_KEY_PATH
 | 
| 
 | 
  3426       export CA_CERT_PATH
 | 
| 
 | 
  3427       export CERT_FULLCHAIN_PATH
 | 
| 
 | 
  3428       export Le_Domain="$_main_domain"
 | 
| 
 | 
  3429       cd "$DOMAIN_PATH" && eval "$_chk_renew_hook"
 | 
| 
 | 
  3430     ); then
 | 
| 
 | 
  3431       _err "Error when run renew hook."
 | 
| 
 | 
  3432       return 1
 | 
| 
 | 
  3433     fi
 | 
| 
 | 
  3434   fi
 | 
| 
 | 
  3435 
 | 
| 
 | 
  3436   if _hasfield "$Le_Webroot" "$W_DNS" && [ -z "$FORCE_DNS_MANUAL" ]; then
 | 
| 
 | 
  3437     _err "$_DNS_MANUAL_WARN"
 | 
| 
 | 
  3438   fi
 | 
| 
 | 
  3439 
 | 
| 
 | 
  3440 }
 | 
| 
 | 
  3441 
 | 
| 
 | 
  3442 #account_key_length   eab-kid  eab-hmac-key
 | 
| 
 | 
  3443 registeraccount() {
 | 
| 
 | 
  3444   _account_key_length="$1"
 | 
| 
 | 
  3445   _eab_id="$2"
 | 
| 
 | 
  3446   _eab_hmac_key="$3"
 | 
| 
 | 
  3447   _initpath
 | 
| 
 | 
  3448   _regAccount "$_account_key_length" "$_eab_id" "$_eab_hmac_key"
 | 
| 
 | 
  3449 }
 | 
| 
 | 
  3450 
 | 
| 
 | 
  3451 __calcAccountKeyHash() {
 | 
| 
 | 
  3452   [ -f "$ACCOUNT_KEY_PATH" ] && _digest sha256 <"$ACCOUNT_KEY_PATH"
 | 
| 
 | 
  3453 }
 | 
| 
 | 
  3454 
 | 
| 
 | 
  3455 __calc_account_thumbprint() {
 | 
| 
 | 
  3456   printf "%s" "$jwk" | tr -d ' ' | _digest "sha256" | _url_replace
 | 
| 
 | 
  3457 }
 | 
| 
 | 
  3458 
 | 
| 
 | 
  3459 _getAccountEmail() {
 | 
| 
 | 
  3460   if [ "$ACCOUNT_EMAIL" ]; then
 | 
| 
 | 
  3461     echo "$ACCOUNT_EMAIL"
 | 
| 
 | 
  3462     return 0
 | 
| 
 | 
  3463   fi
 | 
| 
 | 
  3464   if [ -z "$CA_EMAIL" ]; then
 | 
| 
 | 
  3465     CA_EMAIL="$(_readcaconf CA_EMAIL)"
 | 
| 
 | 
  3466   fi
 | 
| 
 | 
  3467   if [ "$CA_EMAIL" ]; then
 | 
| 
 | 
  3468     echo "$CA_EMAIL"
 | 
| 
 | 
  3469     return 0
 | 
| 
 | 
  3470   fi
 | 
| 
 | 
  3471   _readaccountconf "ACCOUNT_EMAIL"
 | 
| 
 | 
  3472 }
 | 
| 
 | 
  3473 
 | 
| 
 | 
  3474 #keylength
 | 
| 
 | 
  3475 _regAccount() {
 | 
| 
 | 
  3476   _initpath
 | 
| 
 | 
  3477   _reg_length="$1"
 | 
| 
 | 
  3478   _eab_id="$2"
 | 
| 
 | 
  3479   _eab_hmac_key="$3"
 | 
| 
 | 
  3480   _debug3 _regAccount "$_regAccount"
 | 
| 
 | 
  3481   _initAPI
 | 
| 
 | 
  3482 
 | 
| 
 | 
  3483   mkdir -p "$CA_DIR"
 | 
| 
 | 
  3484   if [ ! -f "$ACCOUNT_KEY_PATH" ] && [ -f "$_OLD_ACCOUNT_KEY" ]; then
 | 
| 
 | 
  3485     _info "mv $_OLD_ACCOUNT_KEY to $ACCOUNT_KEY_PATH"
 | 
| 
 | 
  3486     mv "$_OLD_ACCOUNT_KEY" "$ACCOUNT_KEY_PATH"
 | 
| 
 | 
  3487   fi
 | 
| 
 | 
  3488 
 | 
| 
 | 
  3489   if [ ! -f "$ACCOUNT_JSON_PATH" ] && [ -f "$_OLD_ACCOUNT_JSON" ]; then
 | 
| 
 | 
  3490     _info "mv $_OLD_ACCOUNT_JSON to $ACCOUNT_JSON_PATH"
 | 
| 
 | 
  3491     mv "$_OLD_ACCOUNT_JSON" "$ACCOUNT_JSON_PATH"
 | 
| 
 | 
  3492   fi
 | 
| 
 | 
  3493 
 | 
| 
 | 
  3494   if [ ! -f "$ACCOUNT_KEY_PATH" ]; then
 | 
| 
 | 
  3495     if ! _create_account_key "$_reg_length"; then
 | 
| 
 | 
  3496       _err "Create account key error."
 | 
| 
 | 
  3497       return 1
 | 
| 
 | 
  3498     fi
 | 
| 
 | 
  3499   fi
 | 
| 
 | 
  3500 
 | 
| 
 | 
  3501   if ! _calcjwk "$ACCOUNT_KEY_PATH"; then
 | 
| 
 | 
  3502     return 1
 | 
| 
 | 
  3503   fi
 | 
| 
 | 
  3504   if [ "$_eab_id" ] && [ "$_eab_hmac_key" ]; then
 | 
| 
 | 
  3505     _savecaconf CA_EAB_KEY_ID "$_eab_id"
 | 
| 
 | 
  3506     _savecaconf CA_EAB_HMAC_KEY "$_eab_hmac_key"
 | 
| 
 | 
  3507   fi
 | 
| 
 | 
  3508   _eab_id=$(_readcaconf "CA_EAB_KEY_ID")
 | 
| 
 | 
  3509   _eab_hmac_key=$(_readcaconf "CA_EAB_HMAC_KEY")
 | 
| 
 | 
  3510   _secure_debug3 _eab_id "$_eab_id"
 | 
| 
 | 
  3511   _secure_debug3 _eab_hmac_key "$_eab_hmac_key"
 | 
| 
 | 
  3512   _email="$(_getAccountEmail)"
 | 
| 
 | 
  3513   if [ "$_email" ]; then
 | 
| 
 | 
  3514     _savecaconf "CA_EMAIL" "$_email"
 | 
| 
 | 
  3515   fi
 | 
| 
 | 
  3516   if [ "$ACME_VERSION" = "2" ]; then
 | 
| 
 | 
  3517     if [ "$ACME_DIRECTORY" = "$CA_ZEROSSL" ]; then
 | 
| 
 | 
  3518       if [ -z "$_eab_id" ] || [ -z "$_eab_hmac_key" ]; then
 | 
| 
 | 
  3519         _info "No EAB credentials found for ZeroSSL, let's get one"
 | 
| 
 | 
  3520         if [ -z "$_email" ]; then
 | 
| 
 | 
  3521           _err "Please provide a email address for ZeroSSL account."
 | 
| 
 | 
  3522           _err "See ZeroSSL usage: $_ZEROSSL_WIKI"
 | 
| 
 | 
  3523           return 1
 | 
| 
 | 
  3524         fi
 | 
| 
 | 
  3525         _eabresp=$(_post "email=$_email" $_ZERO_EAB_ENDPOINT)
 | 
| 
 | 
  3526         if [ "$?" != "0" ]; then
 | 
| 
 | 
  3527           _debug2 "$_eabresp"
 | 
| 
 | 
  3528           _err "Can not get EAB credentials from ZeroSSL."
 | 
| 
 | 
  3529           return 1
 | 
| 
 | 
  3530         fi
 | 
| 
 | 
  3531         _eab_id="$(echo "$_eabresp" | tr ',}' '\n' | grep '"eab_kid"' | cut -d : -f 2 | tr -d '"')"
 | 
| 
 | 
  3532         if [ -z "$_eab_id" ]; then
 | 
| 
 | 
  3533           _err "Can not resolve _eab_id"
 | 
| 
 | 
  3534           return 1
 | 
| 
 | 
  3535         fi
 | 
| 
 | 
  3536         _eab_hmac_key="$(echo "$_eabresp" | tr ',}' '\n' | grep '"eab_hmac_key"' | cut -d : -f 2 | tr -d '"')"
 | 
| 
 | 
  3537         if [ -z "$_eab_hmac_key" ]; then
 | 
| 
 | 
  3538           _err "Can not resolve _eab_hmac_key"
 | 
| 
 | 
  3539           return 1
 | 
| 
 | 
  3540         fi
 | 
| 
 | 
  3541         _savecaconf CA_EAB_KEY_ID "$_eab_id"
 | 
| 
 | 
  3542         _savecaconf CA_EAB_HMAC_KEY "$_eab_hmac_key"
 | 
| 
 | 
  3543       fi
 | 
| 
 | 
  3544     fi
 | 
| 
 | 
  3545     if [ "$_eab_id" ] && [ "$_eab_hmac_key" ]; then
 | 
| 
 | 
  3546       eab_protected="{\"alg\":\"HS256\",\"kid\":\"$_eab_id\",\"url\":\"${ACME_NEW_ACCOUNT}\"}"
 | 
| 
 | 
  3547       _debug3 eab_protected "$eab_protected"
 | 
| 
 | 
  3548 
 | 
| 
 | 
  3549       eab_protected64=$(printf "%s" "$eab_protected" | _base64 | _url_replace)
 | 
| 
 | 
  3550       _debug3 eab_protected64 "$eab_protected64"
 | 
| 
 | 
  3551 
 | 
| 
 | 
  3552       eab_payload64=$(printf "%s" "$jwk" | _base64 | _url_replace)
 | 
| 
 | 
  3553       _debug3 eab_payload64 "$eab_payload64"
 | 
| 
 | 
  3554 
 | 
| 
 | 
  3555       eab_sign_t="$eab_protected64.$eab_payload64"
 | 
| 
 | 
  3556       _debug3 eab_sign_t "$eab_sign_t"
 | 
| 
 | 
  3557 
 | 
| 
 | 
  3558       key_hex="$(_durl_replace_base64 "$_eab_hmac_key" | _dbase64 | _hex_dump | tr -d ' ')"
 | 
| 
 | 
  3559       _debug3 key_hex "$key_hex"
 | 
| 
 | 
  3560 
 | 
| 
 | 
  3561       eab_signature=$(printf "%s" "$eab_sign_t" | _hmac sha256 $key_hex | _base64 | _url_replace)
 | 
| 
 | 
  3562       _debug3 eab_signature "$eab_signature"
 | 
| 
 | 
  3563 
 | 
| 
 | 
  3564       externalBinding=",\"externalAccountBinding\":{\"protected\":\"$eab_protected64\", \"payload\":\"$eab_payload64\", \"signature\":\"$eab_signature\"}"
 | 
| 
 | 
  3565       _debug3 externalBinding "$externalBinding"
 | 
| 
 | 
  3566     fi
 | 
| 
 | 
  3567     if [ "$_email" ]; then
 | 
| 
 | 
  3568       email_sg="\"contact\": [\"mailto:$_email\"], "
 | 
| 
 | 
  3569     fi
 | 
| 
 | 
  3570     regjson="{$email_sg\"termsOfServiceAgreed\": true$externalBinding}"
 | 
| 
 | 
  3571   else
 | 
| 
 | 
  3572     _reg_res="$ACME_NEW_ACCOUNT_RES"
 | 
| 
 | 
  3573     regjson='{"resource": "'$_reg_res'", "terms-of-service-agreed": true, "agreement": "'$ACME_AGREEMENT'"}'
 | 
| 
 | 
  3574     if [ "$_email" ]; then
 | 
| 
 | 
  3575       regjson='{"resource": "'$_reg_res'", "contact": ["mailto:'$_email'"], "terms-of-service-agreed": true, "agreement": "'$ACME_AGREEMENT'"}'
 | 
| 
 | 
  3576     fi
 | 
| 
 | 
  3577   fi
 | 
| 
 | 
  3578 
 | 
| 
 | 
  3579   _info "Registering account: $ACME_DIRECTORY"
 | 
| 
 | 
  3580 
 | 
| 
 | 
  3581   if ! _send_signed_request "${ACME_NEW_ACCOUNT}" "$regjson"; then
 | 
| 
 | 
  3582     _err "Register account Error: $response"
 | 
| 
 | 
  3583     return 1
 | 
| 
 | 
  3584   fi
 | 
| 
 | 
  3585 
 | 
| 
 | 
  3586   _eabAlreadyBound=""
 | 
| 
 | 
  3587   if [ "$code" = "" ] || [ "$code" = '201' ]; then
 | 
| 
 | 
  3588     echo "$response" >"$ACCOUNT_JSON_PATH"
 | 
| 
 | 
  3589     _info "Registered"
 | 
| 
 | 
  3590   elif [ "$code" = '409' ] || [ "$code" = '200' ]; then
 | 
| 
 | 
  3591     _info "Already registered"
 | 
| 
 | 
  3592   elif [ "$code" = '400' ] && _contains "$response" 'The account is not awaiting external account binding'; then
 | 
| 
 | 
  3593     _info "Already register EAB."
 | 
| 
 | 
  3594     _eabAlreadyBound=1
 | 
| 
 | 
  3595   else
 | 
| 
 | 
  3596     _err "Register account Error: $response"
 | 
| 
 | 
  3597     return 1
 | 
| 
 | 
  3598   fi
 | 
| 
 | 
  3599 
 | 
| 
 | 
  3600   if [ -z "$_eabAlreadyBound" ]; then
 | 
| 
 | 
  3601     _debug2 responseHeaders "$responseHeaders"
 | 
| 
 | 
  3602     _accUri="$(echo "$responseHeaders" | grep -i "^Location:" | _head_n 1 | cut -d ':' -f 2- | tr -d "\r\n ")"
 | 
| 
 | 
  3603     _debug "_accUri" "$_accUri"
 | 
| 
 | 
  3604     if [ -z "$_accUri" ]; then
 | 
| 
 | 
  3605       _err "Can not find account id url."
 | 
| 
 | 
  3606       _err "$responseHeaders"
 | 
| 
 | 
  3607       return 1
 | 
| 
 | 
  3608     fi
 | 
| 
 | 
  3609     _savecaconf "ACCOUNT_URL" "$_accUri"
 | 
| 
 | 
  3610   else
 | 
| 
 | 
  3611     ACCOUNT_URL="$(_readcaconf ACCOUNT_URL)"
 | 
| 
 | 
  3612   fi
 | 
| 
 | 
  3613   export ACCOUNT_URL="$_accUri"
 | 
| 
 | 
  3614 
 | 
| 
 | 
  3615   CA_KEY_HASH="$(__calcAccountKeyHash)"
 | 
| 
 | 
  3616   _debug "Calc CA_KEY_HASH" "$CA_KEY_HASH"
 | 
| 
 | 
  3617   _savecaconf CA_KEY_HASH "$CA_KEY_HASH"
 | 
| 
 | 
  3618 
 | 
| 
 | 
  3619   if [ "$code" = '403' ]; then
 | 
| 
 | 
  3620     _err "It seems that the account key is already deactivated, please use a new account key."
 | 
| 
 | 
  3621     return 1
 | 
| 
 | 
  3622   fi
 | 
| 
 | 
  3623 
 | 
| 
 | 
  3624   ACCOUNT_THUMBPRINT="$(__calc_account_thumbprint)"
 | 
| 
 | 
  3625   _info "ACCOUNT_THUMBPRINT" "$ACCOUNT_THUMBPRINT"
 | 
| 
 | 
  3626 }
 | 
| 
 | 
  3627 
 | 
| 
 | 
  3628 #implement updateaccount
 | 
| 
 | 
  3629 updateaccount() {
 | 
| 
 | 
  3630   _initpath
 | 
| 
 | 
  3631 
 | 
| 
 | 
  3632   if [ ! -f "$ACCOUNT_KEY_PATH" ] && [ -f "$_OLD_ACCOUNT_KEY" ]; then
 | 
| 
 | 
  3633     _info "mv $_OLD_ACCOUNT_KEY to $ACCOUNT_KEY_PATH"
 | 
| 
 | 
  3634     mv "$_OLD_ACCOUNT_KEY" "$ACCOUNT_KEY_PATH"
 | 
| 
 | 
  3635   fi
 | 
| 
 | 
  3636 
 | 
| 
 | 
  3637   if [ ! -f "$ACCOUNT_JSON_PATH" ] && [ -f "$_OLD_ACCOUNT_JSON" ]; then
 | 
| 
 | 
  3638     _info "mv $_OLD_ACCOUNT_JSON to $ACCOUNT_JSON_PATH"
 | 
| 
 | 
  3639     mv "$_OLD_ACCOUNT_JSON" "$ACCOUNT_JSON_PATH"
 | 
| 
 | 
  3640   fi
 | 
| 
 | 
  3641 
 | 
| 
 | 
  3642   if [ ! -f "$ACCOUNT_KEY_PATH" ]; then
 | 
| 
 | 
  3643     _err "Account key is not found at: $ACCOUNT_KEY_PATH"
 | 
| 
 | 
  3644     return 1
 | 
| 
 | 
  3645   fi
 | 
| 
 | 
  3646 
 | 
| 
 | 
  3647   _accUri=$(_readcaconf "ACCOUNT_URL")
 | 
| 
 | 
  3648   _debug _accUri "$_accUri"
 | 
| 
 | 
  3649 
 | 
| 
 | 
  3650   if [ -z "$_accUri" ]; then
 | 
| 
 | 
  3651     _err "The account url is empty, please run '--update-account' first to update the account info first,"
 | 
| 
 | 
  3652     _err "Then try again."
 | 
| 
 | 
  3653     return 1
 | 
| 
 | 
  3654   fi
 | 
| 
 | 
  3655 
 | 
| 
 | 
  3656   if ! _calcjwk "$ACCOUNT_KEY_PATH"; then
 | 
| 
 | 
  3657     return 1
 | 
| 
 | 
  3658   fi
 | 
| 
 | 
  3659   _initAPI
 | 
| 
 | 
  3660 
 | 
| 
 | 
  3661   _email="$(_getAccountEmail)"
 | 
| 
 | 
  3662   if [ "$ACME_VERSION" = "2" ]; then
 | 
| 
 | 
  3663     if [ "$ACCOUNT_EMAIL" ]; then
 | 
| 
 | 
  3664       updjson='{"contact": ["mailto:'$_email'"]}'
 | 
| 
 | 
  3665     else
 | 
| 
 | 
  3666       updjson='{"contact": []}'
 | 
| 
 | 
  3667     fi
 | 
| 
 | 
  3668   else
 | 
| 
 | 
  3669     # ACMEv1: Updates happen the same way a registration is done.
 | 
| 
 | 
  3670     # https://tools.ietf.org/html/draft-ietf-acme-acme-01#section-6.3
 | 
| 
 | 
  3671     _regAccount
 | 
| 
 | 
  3672     return
 | 
| 
 | 
  3673   fi
 | 
| 
 | 
  3674 
 | 
| 
 | 
  3675   # this part handles ACMEv2 account updates.
 | 
| 
 | 
  3676   _send_signed_request "$_accUri" "$updjson"
 | 
| 
 | 
  3677 
 | 
| 
 | 
  3678   if [ "$code" = '200' ]; then
 | 
| 
 | 
  3679     echo "$response" >"$ACCOUNT_JSON_PATH"
 | 
| 
 | 
  3680     _info "account update success for $_accUri."
 | 
| 
 | 
  3681   else
 | 
| 
 | 
  3682     _info "Error. The account was not updated."
 | 
| 
 | 
  3683     return 1
 | 
| 
 | 
  3684   fi
 | 
| 
 | 
  3685 }
 | 
| 
 | 
  3686 
 | 
| 
 | 
  3687 #Implement deactivate account
 | 
| 
 | 
  3688 deactivateaccount() {
 | 
| 
 | 
  3689   _initpath
 | 
| 
 | 
  3690 
 | 
| 
 | 
  3691   if [ ! -f "$ACCOUNT_KEY_PATH" ] && [ -f "$_OLD_ACCOUNT_KEY" ]; then
 | 
| 
 | 
  3692     _info "mv $_OLD_ACCOUNT_KEY to $ACCOUNT_KEY_PATH"
 | 
| 
 | 
  3693     mv "$_OLD_ACCOUNT_KEY" "$ACCOUNT_KEY_PATH"
 | 
| 
 | 
  3694   fi
 | 
| 
 | 
  3695 
 | 
| 
 | 
  3696   if [ ! -f "$ACCOUNT_JSON_PATH" ] && [ -f "$_OLD_ACCOUNT_JSON" ]; then
 | 
| 
 | 
  3697     _info "mv $_OLD_ACCOUNT_JSON to $ACCOUNT_JSON_PATH"
 | 
| 
 | 
  3698     mv "$_OLD_ACCOUNT_JSON" "$ACCOUNT_JSON_PATH"
 | 
| 
 | 
  3699   fi
 | 
| 
 | 
  3700 
 | 
| 
 | 
  3701   if [ ! -f "$ACCOUNT_KEY_PATH" ]; then
 | 
| 
 | 
  3702     _err "Account key is not found at: $ACCOUNT_KEY_PATH"
 | 
| 
 | 
  3703     return 1
 | 
| 
 | 
  3704   fi
 | 
| 
 | 
  3705 
 | 
| 
 | 
  3706   _accUri=$(_readcaconf "ACCOUNT_URL")
 | 
| 
 | 
  3707   _debug _accUri "$_accUri"
 | 
| 
 | 
  3708 
 | 
| 
 | 
  3709   if [ -z "$_accUri" ]; then
 | 
| 
 | 
  3710     _err "The account url is empty, please run '--update-account' first to update the account info first,"
 | 
| 
 | 
  3711     _err "Then try again."
 | 
| 
 | 
  3712     return 1
 | 
| 
 | 
  3713   fi
 | 
| 
 | 
  3714 
 | 
| 
 | 
  3715   if ! _calcjwk "$ACCOUNT_KEY_PATH"; then
 | 
| 
 | 
  3716     return 1
 | 
| 
 | 
  3717   fi
 | 
| 
 | 
  3718   _initAPI
 | 
| 
 | 
  3719 
 | 
| 
 | 
  3720   if [ "$ACME_VERSION" = "2" ]; then
 | 
| 
 | 
  3721     _djson="{\"status\":\"deactivated\"}"
 | 
| 
 | 
  3722   else
 | 
| 
 | 
  3723     _djson="{\"resource\": \"reg\", \"status\":\"deactivated\"}"
 | 
| 
 | 
  3724   fi
 | 
| 
 | 
  3725   if _send_signed_request "$_accUri" "$_djson" && _contains "$response" '"deactivated"'; then
 | 
| 
 | 
  3726     _info "Deactivate account success for $_accUri."
 | 
| 
 | 
  3727     _accid=$(echo "$response" | _egrep_o "\"id\" *: *[^,]*," | cut -d : -f 2 | tr -d ' ,')
 | 
| 
 | 
  3728   elif [ "$code" = "403" ]; then
 | 
| 
 | 
  3729     _info "The account is already deactivated."
 | 
| 
 | 
  3730     _accid=$(_getfield "$_accUri" "999" "/")
 | 
| 
 | 
  3731   else
 | 
| 
 | 
  3732     _err "Deactivate: account failed for $_accUri."
 | 
| 
 | 
  3733     return 1
 | 
| 
 | 
  3734   fi
 | 
| 
 | 
  3735 
 | 
| 
 | 
  3736   _debug "Account id: $_accid"
 | 
| 
 | 
  3737   if [ "$_accid" ]; then
 | 
| 
 | 
  3738     _deactivated_account_path="$CA_DIR/deactivated/$_accid"
 | 
| 
 | 
  3739     _debug _deactivated_account_path "$_deactivated_account_path"
 | 
| 
 | 
  3740     if mkdir -p "$_deactivated_account_path"; then
 | 
| 
 | 
  3741       _info "Moving deactivated account info to $_deactivated_account_path/"
 | 
| 
 | 
  3742       mv "$CA_CONF" "$_deactivated_account_path/"
 | 
| 
 | 
  3743       mv "$ACCOUNT_JSON_PATH" "$_deactivated_account_path/"
 | 
| 
 | 
  3744       mv "$ACCOUNT_KEY_PATH" "$_deactivated_account_path/"
 | 
| 
 | 
  3745     else
 | 
| 
 | 
  3746       _err "Can not create dir: $_deactivated_account_path, try to remove the deactivated account key."
 | 
| 
 | 
  3747       rm -f "$CA_CONF"
 | 
| 
 | 
  3748       rm -f "$ACCOUNT_JSON_PATH"
 | 
| 
 | 
  3749       rm -f "$ACCOUNT_KEY_PATH"
 | 
| 
 | 
  3750     fi
 | 
| 
 | 
  3751   fi
 | 
| 
 | 
  3752 }
 | 
| 
 | 
  3753 
 | 
| 
 | 
  3754 # domain folder  file
 | 
| 
 | 
  3755 _findHook() {
 | 
| 
 | 
  3756   _hookdomain="$1"
 | 
| 
 | 
  3757   _hookcat="$2"
 | 
| 
 | 
  3758   _hookname="$3"
 | 
| 
 | 
  3759 
 | 
| 
 | 
  3760   if [ -f "$_SCRIPT_HOME/$_hookcat/$_hookname" ]; then
 | 
| 
 | 
  3761     d_api="$_SCRIPT_HOME/$_hookcat/$_hookname"
 | 
| 
 | 
  3762   elif [ -f "$_SCRIPT_HOME/$_hookcat/$_hookname.sh" ]; then
 | 
| 
 | 
  3763     d_api="$_SCRIPT_HOME/$_hookcat/$_hookname.sh"
 | 
| 
 | 
  3764   elif [ "$_hookdomain" ] && [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname" ]; then
 | 
| 
 | 
  3765     d_api="$LE_WORKING_DIR/$_hookdomain/$_hookname"
 | 
| 
 | 
  3766   elif [ "$_hookdomain" ] && [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname.sh" ]; then
 | 
| 
 | 
  3767     d_api="$LE_WORKING_DIR/$_hookdomain/$_hookname.sh"
 | 
| 
 | 
  3768   elif [ -f "$LE_WORKING_DIR/$_hookname" ]; then
 | 
| 
 | 
  3769     d_api="$LE_WORKING_DIR/$_hookname"
 | 
| 
 | 
  3770   elif [ -f "$LE_WORKING_DIR/$_hookname.sh" ]; then
 | 
| 
 | 
  3771     d_api="$LE_WORKING_DIR/$_hookname.sh"
 | 
| 
 | 
  3772   elif [ -f "$LE_WORKING_DIR/$_hookcat/$_hookname" ]; then
 | 
| 
 | 
  3773     d_api="$LE_WORKING_DIR/$_hookcat/$_hookname"
 | 
| 
 | 
  3774   elif [ -f "$LE_WORKING_DIR/$_hookcat/$_hookname.sh" ]; then
 | 
| 
 | 
  3775     d_api="$LE_WORKING_DIR/$_hookcat/$_hookname.sh"
 | 
| 
 | 
  3776   fi
 | 
| 
 | 
  3777 
 | 
| 
 | 
  3778   printf "%s" "$d_api"
 | 
| 
 | 
  3779 }
 | 
| 
 | 
  3780 
 | 
| 
 | 
  3781 #domain
 | 
| 
 | 
  3782 __get_domain_new_authz() {
 | 
| 
 | 
  3783   _gdnd="$1"
 | 
| 
 | 
  3784   _info "Getting new-authz for domain" "$_gdnd"
 | 
| 
 | 
  3785   _initAPI
 | 
| 
 | 
  3786   _Max_new_authz_retry_times=5
 | 
| 
 | 
  3787   _authz_i=0
 | 
| 
 | 
  3788   while [ "$_authz_i" -lt "$_Max_new_authz_retry_times" ]; do
 | 
| 
 | 
  3789     _debug "Try new-authz for the $_authz_i time."
 | 
| 
 | 
  3790     if ! _send_signed_request "${ACME_NEW_AUTHZ}" "{\"resource\": \"new-authz\", \"identifier\": {\"type\": \"dns\", \"value\": \"$(_idn "$_gdnd")\"}}"; then
 | 
| 
 | 
  3791       _err "Can not get domain new authz."
 | 
| 
 | 
  3792       return 1
 | 
| 
 | 
  3793     fi
 | 
| 
 | 
  3794     if _contains "$response" "No registration exists matching provided key"; then
 | 
| 
 | 
  3795       _err "It seems there is an error, but it's recovered now, please try again."
 | 
| 
 | 
  3796       _err "If you see this message for a second time, please report bug: $(__green "$PROJECT")"
 | 
| 
 | 
  3797       _clearcaconf "CA_KEY_HASH"
 | 
| 
 | 
  3798       break
 | 
| 
 | 
  3799     fi
 | 
| 
 | 
  3800     if ! _contains "$response" "An error occurred while processing your request"; then
 | 
| 
 | 
  3801       _info "The new-authz request is ok."
 | 
| 
 | 
  3802       break
 | 
| 
 | 
  3803     fi
 | 
| 
 | 
  3804     _authz_i="$(_math "$_authz_i" + 1)"
 | 
| 
 | 
  3805     _info "The server is busy, Sleep $_authz_i to retry."
 | 
| 
 | 
  3806     _sleep "$_authz_i"
 | 
| 
 | 
  3807   done
 | 
| 
 | 
  3808 
 | 
| 
 | 
  3809   if [ "$_authz_i" = "$_Max_new_authz_retry_times" ]; then
 | 
| 
 | 
  3810     _err "new-authz retry reach the max $_Max_new_authz_retry_times times."
 | 
| 
 | 
  3811   fi
 | 
| 
 | 
  3812 
 | 
| 
 | 
  3813   if [ "$code" ] && [ "$code" != '201' ]; then
 | 
| 
 | 
  3814     _err "new-authz error: $response"
 | 
| 
 | 
  3815     return 1
 | 
| 
 | 
  3816   fi
 | 
| 
 | 
  3817 
 | 
| 
 | 
  3818 }
 | 
| 
 | 
  3819 
 | 
| 
 | 
  3820 #uri keyAuthorization
 | 
| 
 | 
  3821 __trigger_validation() {
 | 
| 
 | 
  3822   _debug2 "Trigger domain validation."
 | 
| 
 | 
  3823   _t_url="$1"
 | 
| 
 | 
  3824   _debug2 _t_url "$_t_url"
 | 
| 
 | 
  3825   _t_key_authz="$2"
 | 
| 
 | 
  3826   _debug2 _t_key_authz "$_t_key_authz"
 | 
| 
 | 
  3827   _t_vtype="$3"
 | 
| 
 | 
  3828   _debug2 _t_vtype "$_t_vtype"
 | 
| 
 | 
  3829   if [ "$ACME_VERSION" = "2" ]; then
 | 
| 
 | 
  3830     _send_signed_request "$_t_url" "{}"
 | 
| 
 | 
  3831   else
 | 
| 
 | 
  3832     _send_signed_request "$_t_url" "{\"resource\": \"challenge\", \"type\": \"$_t_vtype\", \"keyAuthorization\": \"$_t_key_authz\"}"
 | 
| 
 | 
  3833   fi
 | 
| 
 | 
  3834 }
 | 
| 
 | 
  3835 
 | 
| 
 | 
  3836 #endpoint  domain type
 | 
| 
 | 
  3837 _ns_lookup_impl() {
 | 
| 
 | 
  3838   _ns_ep="$1"
 | 
| 
 | 
  3839   _ns_domain="$2"
 | 
| 
 | 
  3840   _ns_type="$3"
 | 
| 
 | 
  3841   _debug2 "_ns_ep" "$_ns_ep"
 | 
| 
 | 
  3842   _debug2 "_ns_domain" "$_ns_domain"
 | 
| 
 | 
  3843   _debug2 "_ns_type" "$_ns_type"
 | 
| 
 | 
  3844 
 | 
| 
 | 
  3845   response="$(_H1="accept: application/dns-json" _get "$_ns_ep?name=$_ns_domain&type=$_ns_type")"
 | 
| 
 | 
  3846   _ret=$?
 | 
| 
 | 
  3847   _debug2 "response" "$response"
 | 
| 
 | 
  3848   if [ "$_ret" != "0" ]; then
 | 
| 
 | 
  3849     return $_ret
 | 
| 
 | 
  3850   fi
 | 
| 
 | 
  3851   _answers="$(echo "$response" | tr '{}' '<>' | _egrep_o '"Answer":\[[^]]*]' | tr '<>' '\n\n')"
 | 
| 
 | 
  3852   _debug2 "_answers" "$_answers"
 | 
| 
 | 
  3853   echo "$_answers"
 | 
| 
 | 
  3854 }
 | 
| 
 | 
  3855 
 | 
| 
 | 
  3856 #domain, type
 | 
| 
 | 
  3857 _ns_lookup_cf() {
 | 
| 
 | 
  3858   _cf_ld="$1"
 | 
| 
 | 
  3859   _cf_ld_type="$2"
 | 
| 
 | 
  3860   _cf_ep="https://cloudflare-dns.com/dns-query"
 | 
| 
 | 
  3861   _ns_lookup_impl "$_cf_ep" "$_cf_ld" "$_cf_ld_type"
 | 
| 
 | 
  3862 }
 | 
| 
 | 
  3863 
 | 
| 
 | 
  3864 #domain, type
 | 
| 
 | 
  3865 _ns_purge_cf() {
 | 
| 
 | 
  3866   _cf_d="$1"
 | 
| 
 | 
  3867   _cf_d_type="$2"
 | 
| 
 | 
  3868   _debug "Cloudflare purge $_cf_d_type record for domain $_cf_d"
 | 
| 
 | 
  3869   _cf_purl="https://cloudflare-dns.com/api/v1/purge?domain=$_cf_d&type=$_cf_d_type"
 | 
| 
 | 
  3870   response="$(_post "" "$_cf_purl")"
 | 
| 
 | 
  3871   _debug2 response "$response"
 | 
| 
 | 
  3872 }
 | 
| 
 | 
  3873 
 | 
| 
 | 
  3874 #checks if cf server is available
 | 
| 
 | 
  3875 _ns_is_available_cf() {
 | 
| 
 | 
  3876   if _get "https://cloudflare-dns.com" >/dev/null 2>&1; then
 | 
| 
 | 
  3877     return 0
 | 
| 
 | 
  3878   else
 | 
| 
 | 
  3879     return 1
 | 
| 
 | 
  3880   fi
 | 
| 
 | 
  3881 }
 | 
| 
 | 
  3882 
 | 
| 
 | 
  3883 #domain, type
 | 
| 
 | 
  3884 _ns_lookup_google() {
 | 
| 
 | 
  3885   _cf_ld="$1"
 | 
| 
 | 
  3886   _cf_ld_type="$2"
 | 
| 
 | 
  3887   _cf_ep="https://dns.google/resolve"
 | 
| 
 | 
  3888   _ns_lookup_impl "$_cf_ep" "$_cf_ld" "$_cf_ld_type"
 | 
| 
 | 
  3889 }
 | 
| 
 | 
  3890 
 | 
| 
 | 
  3891 #domain, type
 | 
| 
 | 
  3892 _ns_lookup() {
 | 
| 
 | 
  3893   if [ -z "$DOH_USE" ]; then
 | 
| 
 | 
  3894     _debug "Detect dns server first."
 | 
| 
 | 
  3895     if _ns_is_available_cf; then
 | 
| 
 | 
  3896       _debug "Use cloudflare doh server"
 | 
| 
 | 
  3897       export DOH_USE=$DOH_CLOUDFLARE
 | 
| 
 | 
  3898     else
 | 
| 
 | 
  3899       _debug "Use google doh server"
 | 
| 
 | 
  3900       export DOH_USE=$DOH_GOOGLE
 | 
| 
 | 
  3901     fi
 | 
| 
 | 
  3902   fi
 | 
| 
 | 
  3903 
 | 
| 
 | 
  3904   if [ "$DOH_USE" = "$DOH_CLOUDFLARE" ] || [ -z "$DOH_USE" ]; then
 | 
| 
 | 
  3905     _ns_lookup_cf "$@"
 | 
| 
 | 
  3906   else
 | 
| 
 | 
  3907     _ns_lookup_google "$@"
 | 
| 
 | 
  3908   fi
 | 
| 
 | 
  3909 
 | 
| 
 | 
  3910 }
 | 
| 
 | 
  3911 
 | 
| 
 | 
  3912 #txtdomain, alias, txt
 | 
| 
 | 
  3913 __check_txt() {
 | 
| 
 | 
  3914   _c_txtdomain="$1"
 | 
| 
 | 
  3915   _c_aliasdomain="$2"
 | 
| 
 | 
  3916   _c_txt="$3"
 | 
| 
 | 
  3917   _debug "_c_txtdomain" "$_c_txtdomain"
 | 
| 
 | 
  3918   _debug "_c_aliasdomain" "$_c_aliasdomain"
 | 
| 
 | 
  3919   _debug "_c_txt" "$_c_txt"
 | 
| 
 | 
  3920   _answers="$(_ns_lookup "$_c_aliasdomain" TXT)"
 | 
| 
 | 
  3921   _contains "$_answers" "$_c_txt"
 | 
| 
 | 
  3922 
 | 
| 
 | 
  3923 }
 | 
| 
 | 
  3924 
 | 
| 
 | 
  3925 #txtdomain
 | 
| 
 | 
  3926 __purge_txt() {
 | 
| 
 | 
  3927   _p_txtdomain="$1"
 | 
| 
 | 
  3928   _debug _p_txtdomain "$_p_txtdomain"
 | 
| 
 | 
  3929   if [ "$DOH_USE" = "$DOH_CLOUDFLARE" ] || [ -z "$DOH_USE" ]; then
 | 
| 
 | 
  3930     _ns_purge_cf "$_p_txtdomain" "TXT"
 | 
| 
 | 
  3931   else
 | 
| 
 | 
  3932     _debug "no purge api for google dns api, just sleep 5 secs"
 | 
| 
 | 
  3933     _sleep 5
 | 
| 
 | 
  3934   fi
 | 
| 
 | 
  3935 
 | 
| 
 | 
  3936 }
 | 
| 
 | 
  3937 
 | 
| 
 | 
  3938 #wait and check each dns entries
 | 
| 
 | 
  3939 _check_dns_entries() {
 | 
| 
 | 
  3940   _success_txt=","
 | 
| 
 | 
  3941   _end_time="$(_time)"
 | 
| 
 | 
  3942   _end_time="$(_math "$_end_time" + 1200)" #let's check no more than 20 minutes.
 | 
| 
 | 
  3943 
 | 
| 
 | 
  3944   while [ "$(_time)" -le "$_end_time" ]; do
 | 
| 
 | 
  3945     _left=""
 | 
| 
 | 
  3946     for entry in $dns_entries; do
 | 
| 
 | 
  3947       d=$(_getfield "$entry" 1)
 | 
| 
 | 
  3948       txtdomain=$(_getfield "$entry" 2)
 | 
| 
 | 
  3949       txtdomain=$(_idn "$txtdomain")
 | 
| 
 | 
  3950       aliasDomain=$(_getfield "$entry" 3)
 | 
| 
 | 
  3951       aliasDomain=$(_idn "$aliasDomain")
 | 
| 
 | 
  3952       txt=$(_getfield "$entry" 5)
 | 
| 
 | 
  3953       d_api=$(_getfield "$entry" 6)
 | 
| 
 | 
  3954       _debug "d" "$d"
 | 
| 
 | 
  3955       _debug "txtdomain" "$txtdomain"
 | 
| 
 | 
  3956       _debug "aliasDomain" "$aliasDomain"
 | 
| 
 | 
  3957       _debug "txt" "$txt"
 | 
| 
 | 
  3958       _debug "d_api" "$d_api"
 | 
| 
 | 
  3959       _info "Checking $d for $aliasDomain"
 | 
| 
 | 
  3960       if _contains "$_success_txt" ",$txt,"; then
 | 
| 
 | 
  3961         _info "Already success, continue next one."
 | 
| 
 | 
  3962         continue
 | 
| 
 | 
  3963       fi
 | 
| 
 | 
  3964 
 | 
| 
 | 
  3965       if __check_txt "$txtdomain" "$aliasDomain" "$txt"; then
 | 
| 
 | 
  3966         _info "Domain $d '$aliasDomain' success."
 | 
| 
 | 
  3967         _success_txt="$_success_txt,$txt,"
 | 
| 
 | 
  3968         continue
 | 
| 
 | 
  3969       fi
 | 
| 
 | 
  3970       _left=1
 | 
| 
 | 
  3971       _info "Not valid yet, let's wait 10 seconds and check next one."
 | 
| 
 | 
  3972       __purge_txt "$txtdomain"
 | 
| 
 | 
  3973       if [ "$txtdomain" != "$aliasDomain" ]; then
 | 
| 
 | 
  3974         __purge_txt "$aliasDomain"
 | 
| 
 | 
  3975       fi
 | 
| 
 | 
  3976       _sleep 10
 | 
| 
 | 
  3977     done
 | 
| 
 | 
  3978     if [ "$_left" ]; then
 | 
| 
 | 
  3979       _info "Let's wait 10 seconds and check again".
 | 
| 
 | 
  3980       _sleep 10
 | 
| 
 | 
  3981     else
 | 
| 
 | 
  3982       _info "All success, let's return"
 | 
| 
 | 
  3983       return 0
 | 
| 
 | 
  3984     fi
 | 
| 
 | 
  3985   done
 | 
| 
 | 
  3986   _info "Timed out waiting for DNS."
 | 
| 
 | 
  3987   return 1
 | 
| 
 | 
  3988 
 | 
| 
 | 
  3989 }
 | 
| 
 | 
  3990 
 | 
| 
 | 
  3991 #file
 | 
| 
 | 
  3992 _get_cert_issuers() {
 | 
| 
 | 
  3993   _cfile="$1"
 | 
| 
 | 
  3994   if _contains "$(${ACME_OPENSSL_BIN:-openssl} help crl2pkcs7 2>&1)" "Usage: crl2pkcs7"; then
 | 
| 
 | 
  3995     ${ACME_OPENSSL_BIN:-openssl} crl2pkcs7 -nocrl -certfile $_cfile | ${ACME_OPENSSL_BIN:-openssl} pkcs7 -print_certs -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2
 | 
| 
 | 
  3996   else
 | 
| 
 | 
  3997     ${ACME_OPENSSL_BIN:-openssl} x509 -in $_cfile -text -noout | grep 'Issuer:' | _egrep_o "CN *=[^,]*" | cut -d = -f 2
 | 
| 
 | 
  3998   fi
 | 
| 
 | 
  3999 }
 | 
| 
 | 
  4000 
 | 
| 
 | 
  4001 #cert  issuer
 | 
| 
 | 
  4002 _match_issuer() {
 | 
| 
 | 
  4003   _cfile="$1"
 | 
| 
 | 
  4004   _missuer="$2"
 | 
| 
 | 
  4005   _fissuers="$(_get_cert_issuers $_cfile)"
 | 
| 
 | 
  4006   _debug2 _fissuers "$_fissuers"
 | 
| 
 | 
  4007   if _contains "$_fissuers" "$_missuer"; then
 | 
| 
 | 
  4008     return 0
 | 
| 
 | 
  4009   fi
 | 
| 
 | 
  4010   _fissuers="$(echo "$_fissuers" | _lower_case)"
 | 
| 
 | 
  4011   _missuer="$(echo "$_missuer" | _lower_case)"
 | 
| 
 | 
  4012   _contains "$_fissuers" "$_missuer"
 | 
| 
 | 
  4013 }
 | 
| 
 | 
  4014 
 | 
| 
 | 
  4015 #webroot, domain domainlist  keylength
 | 
| 
 | 
  4016 issue() {
 | 
| 
 | 
  4017   if [ -z "$2" ]; then
 | 
| 
 | 
  4018     _usage "Usage: $PROJECT_ENTRY --issue --domain <domain.tld> --webroot <directory>"
 | 
| 
 | 
  4019     return 1
 | 
| 
 | 
  4020   fi
 | 
| 
 | 
  4021   if [ -z "$1" ]; then
 | 
| 
 | 
  4022     _usage "Please specify at least one validation method: '--webroot', '--standalone', '--apache', '--nginx' or '--dns' etc."
 | 
| 
 | 
  4023     return 1
 | 
| 
 | 
  4024   fi
 | 
| 
 | 
  4025   _web_roots="$1"
 | 
| 
 | 
  4026   _main_domain="$2"
 | 
| 
 | 
  4027   _alt_domains="$3"
 | 
| 
 | 
  4028 
 | 
| 
 | 
  4029   if _contains "$_main_domain" ","; then
 | 
| 
 | 
  4030     _main_domain=$(echo "$2,$3" | cut -d , -f 1)
 | 
| 
 | 
  4031     _alt_domains=$(echo "$2,$3" | cut -d , -f 2- | sed "s/,${NO_VALUE}$//")
 | 
| 
 | 
  4032   fi
 | 
| 
 | 
  4033   _debug _main_domain "$_main_domain"
 | 
| 
 | 
  4034   _debug _alt_domains "$_alt_domains"
 | 
| 
 | 
  4035 
 | 
| 
 | 
  4036   _key_length="$4"
 | 
| 
 | 
  4037   _real_cert="$5"
 | 
| 
 | 
  4038   _real_key="$6"
 | 
| 
 | 
  4039   _real_ca="$7"
 | 
| 
 | 
  4040   _reload_cmd="$8"
 | 
| 
 | 
  4041   _real_fullchain="$9"
 | 
| 
 | 
  4042   _pre_hook="${10}"
 | 
| 
 | 
  4043   _post_hook="${11}"
 | 
| 
 | 
  4044   _renew_hook="${12}"
 | 
| 
 | 
  4045   _local_addr="${13}"
 | 
| 
 | 
  4046   _challenge_alias="${14}"
 | 
| 
 | 
  4047   _preferred_chain="${15}"
 | 
| 
 | 
  4048 
 | 
| 
 | 
  4049   if [ -z "$_ACME_IS_RENEW" ]; then
 | 
| 
 | 
  4050     _initpath "$_main_domain" "$_key_length"
 | 
| 
 | 
  4051     mkdir -p "$DOMAIN_PATH"
 | 
| 
 | 
  4052   fi
 | 
| 
 | 
  4053 
 | 
| 
 | 
  4054   if _hasfield "$_web_roots" "$W_DNS" && [ -z "$FORCE_DNS_MANUAL" ]; then
 | 
| 
 | 
  4055     _err "$_DNS_MANUAL_ERROR"
 | 
| 
 | 
  4056     return 1
 | 
| 
 | 
  4057   fi
 | 
| 
 | 
  4058 
 | 
| 
 | 
  4059   _debug "Using ACME_DIRECTORY: $ACME_DIRECTORY"
 | 
| 
 | 
  4060 
 | 
| 
 | 
  4061   _initAPI
 | 
| 
 | 
  4062 
 | 
| 
 | 
  4063   if [ -f "$DOMAIN_CONF" ]; then
 | 
| 
 | 
  4064     Le_NextRenewTime=$(_readdomainconf Le_NextRenewTime)
 | 
| 
 | 
  4065     _debug Le_NextRenewTime "$Le_NextRenewTime"
 | 
| 
 | 
  4066     if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(_time)" -lt "$Le_NextRenewTime" ]; then
 | 
| 
 | 
  4067       _saved_domain=$(_readdomainconf Le_Domain)
 | 
| 
 | 
  4068       _debug _saved_domain "$_saved_domain"
 | 
| 
 | 
  4069       _saved_alt=$(_readdomainconf Le_Alt)
 | 
| 
 | 
  4070       _debug _saved_alt "$_saved_alt"
 | 
| 
 | 
  4071       if [ "$_saved_domain,$_saved_alt" = "$_main_domain,$_alt_domains" ]; then
 | 
| 
 | 
  4072         _info "Domains not changed."
 | 
| 
 | 
  4073         _info "Skip, Next renewal time is: $(__green "$(_readdomainconf Le_NextRenewTimeStr)")"
 | 
| 
 | 
  4074         _info "Add '$(__red '--force')' to force to renew."
 | 
| 
 | 
  4075         return $RENEW_SKIP
 | 
| 
 | 
  4076       else
 | 
| 
 | 
  4077         _info "Domains have changed."
 | 
| 
 | 
  4078       fi
 | 
| 
 | 
  4079     fi
 | 
| 
 | 
  4080   fi
 | 
| 
 | 
  4081 
 | 
| 
 | 
  4082   _savedomainconf "Le_Domain" "$_main_domain"
 | 
| 
 | 
  4083   _savedomainconf "Le_Alt" "$_alt_domains"
 | 
| 
 | 
  4084   _savedomainconf "Le_Webroot" "$_web_roots"
 | 
| 
 | 
  4085 
 | 
| 
 | 
  4086   _savedomainconf "Le_PreHook" "$_pre_hook" "base64"
 | 
| 
 | 
  4087   _savedomainconf "Le_PostHook" "$_post_hook" "base64"
 | 
| 
 | 
  4088   _savedomainconf "Le_RenewHook" "$_renew_hook" "base64"
 | 
| 
 | 
  4089 
 | 
| 
 | 
  4090   if [ "$_local_addr" ]; then
 | 
| 
 | 
  4091     _savedomainconf "Le_LocalAddress" "$_local_addr"
 | 
| 
 | 
  4092   else
 | 
| 
 | 
  4093     _cleardomainconf "Le_LocalAddress"
 | 
| 
 | 
  4094   fi
 | 
| 
 | 
  4095   if [ "$_challenge_alias" ]; then
 | 
| 
 | 
  4096     _savedomainconf "Le_ChallengeAlias" "$_challenge_alias"
 | 
| 
 | 
  4097   else
 | 
| 
 | 
  4098     _cleardomainconf "Le_ChallengeAlias"
 | 
| 
 | 
  4099   fi
 | 
| 
 | 
  4100   if [ "$_preferred_chain" ]; then
 | 
| 
 | 
  4101     _savedomainconf "Le_Preferred_Chain" "$_preferred_chain" "base64"
 | 
| 
 | 
  4102   else
 | 
| 
 | 
  4103     _cleardomainconf "Le_Preferred_Chain"
 | 
| 
 | 
  4104   fi
 | 
| 
 | 
  4105 
 | 
| 
 | 
  4106   Le_API="$ACME_DIRECTORY"
 | 
| 
 | 
  4107   _savedomainconf "Le_API" "$Le_API"
 | 
| 
 | 
  4108 
 | 
| 
 | 
  4109   _info "Using CA: $ACME_DIRECTORY"
 | 
| 
 | 
  4110   if [ "$_alt_domains" = "$NO_VALUE" ]; then
 | 
| 
 | 
  4111     _alt_domains=""
 | 
| 
 | 
  4112   fi
 | 
| 
 | 
  4113 
 | 
| 
 | 
  4114   if [ "$_key_length" = "$NO_VALUE" ]; then
 | 
| 
 | 
  4115     _key_length=""
 | 
| 
 | 
  4116   fi
 | 
| 
 | 
  4117 
 | 
| 
 | 
  4118   if ! _on_before_issue "$_web_roots" "$_main_domain" "$_alt_domains" "$_pre_hook" "$_local_addr"; then
 | 
| 
 | 
  4119     _err "_on_before_issue."
 | 
| 
 | 
  4120     return 1
 | 
| 
 | 
  4121   fi
 | 
| 
 | 
  4122 
 | 
| 
 | 
  4123   _saved_account_key_hash="$(_readcaconf "CA_KEY_HASH")"
 | 
| 
 | 
  4124   _debug2 _saved_account_key_hash "$_saved_account_key_hash"
 | 
| 
 | 
  4125 
 | 
| 
 | 
  4126   if [ -z "$ACCOUNT_URL" ] || [ -z "$_saved_account_key_hash" ] || [ "$_saved_account_key_hash" != "$(__calcAccountKeyHash)" ]; then
 | 
| 
 | 
  4127     if ! _regAccount "$_accountkeylength"; then
 | 
| 
 | 
  4128       _on_issue_err "$_post_hook"
 | 
| 
 | 
  4129       return 1
 | 
| 
 | 
  4130     fi
 | 
| 
 | 
  4131   else
 | 
| 
 | 
  4132     _debug "_saved_account_key_hash is not changed, skip register account."
 | 
| 
 | 
  4133   fi
 | 
| 
 | 
  4134 
 | 
| 
 | 
  4135   if [ -f "$CSR_PATH" ] && [ ! -f "$CERT_KEY_PATH" ]; then
 | 
| 
 | 
  4136     _info "Signing from existing CSR."
 | 
| 
 | 
  4137   else
 | 
| 
 | 
  4138     _key=$(_readdomainconf Le_Keylength)
 | 
| 
 | 
  4139     _debug "Read key length:$_key"
 | 
| 
 | 
  4140     if [ ! -f "$CERT_KEY_PATH" ] || [ "$_key_length" != "$_key" ] || [ "$Le_ForceNewDomainKey" = "1" ]; then
 | 
| 
 | 
  4141       if ! createDomainKey "$_main_domain" "$_key_length"; then
 | 
| 
 | 
  4142         _err "Create domain key error."
 | 
| 
 | 
  4143         _clearup
 | 
| 
 | 
  4144         _on_issue_err "$_post_hook"
 | 
| 
 | 
  4145         return 1
 | 
| 
 | 
  4146       fi
 | 
| 
 | 
  4147     fi
 | 
| 
 | 
  4148 
 | 
| 
 | 
  4149     if ! _createcsr "$_main_domain" "$_alt_domains" "$CERT_KEY_PATH" "$CSR_PATH" "$DOMAIN_SSL_CONF"; then
 | 
| 
 | 
  4150       _err "Create CSR error."
 | 
| 
 | 
  4151       _clearup
 | 
| 
 | 
  4152       _on_issue_err "$_post_hook"
 | 
| 
 | 
  4153       return 1
 | 
| 
 | 
  4154     fi
 | 
| 
 | 
  4155   fi
 | 
| 
 | 
  4156 
 | 
| 
 | 
  4157   _savedomainconf "Le_Keylength" "$_key_length"
 | 
| 
 | 
  4158 
 | 
| 
 | 
  4159   vlist="$Le_Vlist"
 | 
| 
 | 
  4160   _cleardomainconf "Le_Vlist"
 | 
| 
 | 
  4161   _info "Getting domain auth token for each domain"
 | 
| 
 | 
  4162   sep='#'
 | 
| 
 | 
  4163   dvsep=','
 | 
| 
 | 
  4164   if [ -z "$vlist" ]; then
 | 
| 
 | 
  4165     if [ "$ACME_VERSION" = "2" ]; then
 | 
| 
 | 
  4166       #make new order request
 | 
| 
 | 
  4167       _identifiers="{\"type\":\"dns\",\"value\":\"$(_idn "$_main_domain")\"}"
 | 
| 
 | 
  4168       _w_index=1
 | 
| 
 | 
  4169       while true; do
 | 
| 
 | 
  4170         d="$(echo "$_alt_domains," | cut -d , -f "$_w_index")"
 | 
| 
 | 
  4171         _w_index="$(_math "$_w_index" + 1)"
 | 
| 
 | 
  4172         _debug d "$d"
 | 
| 
 | 
  4173         if [ -z "$d" ]; then
 | 
| 
 | 
  4174           break
 | 
| 
 | 
  4175         fi
 | 
| 
 | 
  4176         _identifiers="$_identifiers,{\"type\":\"dns\",\"value\":\"$(_idn "$d")\"}"
 | 
| 
 | 
  4177       done
 | 
| 
 | 
  4178       _debug2 _identifiers "$_identifiers"
 | 
| 
 | 
  4179       if ! _send_signed_request "$ACME_NEW_ORDER" "{\"identifiers\": [$_identifiers]}"; then
 | 
| 
 | 
  4180         _err "Create new order error."
 | 
| 
 | 
  4181         _clearup
 | 
| 
 | 
  4182         _on_issue_err "$_post_hook"
 | 
| 
 | 
  4183         return 1
 | 
| 
 | 
  4184       fi
 | 
| 
 | 
  4185       Le_LinkOrder="$(echo "$responseHeaders" | grep -i '^Location.*$' | _tail_n 1 | tr -d "\r\n " | cut -d ":" -f 2-)"
 | 
| 
 | 
  4186       _debug Le_LinkOrder "$Le_LinkOrder"
 | 
| 
 | 
  4187       Le_OrderFinalize="$(echo "$response" | _egrep_o '"finalize" *: *"[^"]*"' | cut -d '"' -f 4)"
 | 
| 
 | 
  4188       _debug Le_OrderFinalize "$Le_OrderFinalize"
 | 
| 
 | 
  4189       if [ -z "$Le_OrderFinalize" ]; then
 | 
| 
 | 
  4190         _err "Create new order error. Le_OrderFinalize not found. $response"
 | 
| 
 | 
  4191         _clearup
 | 
| 
 | 
  4192         _on_issue_err "$_post_hook"
 | 
| 
 | 
  4193         return 1
 | 
| 
 | 
  4194       fi
 | 
| 
 | 
  4195 
 | 
| 
 | 
  4196       #for dns manual mode
 | 
| 
 | 
  4197       _savedomainconf "Le_OrderFinalize" "$Le_OrderFinalize"
 | 
| 
 | 
  4198 
 | 
| 
 | 
  4199       _authorizations_seg="$(echo "$response" | _json_decode | _egrep_o '"authorizations" *: *\[[^\[]*\]' | cut -d '[' -f 2 | tr -d ']' | tr -d '"')"
 | 
| 
 | 
  4200       _debug2 _authorizations_seg "$_authorizations_seg"
 | 
| 
 | 
  4201       if [ -z "$_authorizations_seg" ]; then
 | 
| 
 | 
  4202         _err "_authorizations_seg not found."
 | 
| 
 | 
  4203         _clearup
 | 
| 
 | 
  4204         _on_issue_err "$_post_hook"
 | 
| 
 | 
  4205         return 1
 | 
| 
 | 
  4206       fi
 | 
| 
 | 
  4207 
 | 
| 
 | 
  4208       #domain and authz map
 | 
| 
 | 
  4209       _authorizations_map=""
 | 
| 
 | 
  4210       for _authz_url in $(echo "$_authorizations_seg" | tr ',' ' '); do
 | 
| 
 | 
  4211         _debug2 "_authz_url" "$_authz_url"
 | 
| 
 | 
  4212         if ! _send_signed_request "$_authz_url"; then
 | 
| 
 | 
  4213           _err "get to authz error."
 | 
| 
 | 
  4214           _err "_authorizations_seg" "$_authorizations_seg"
 | 
| 
 | 
  4215           _err "_authz_url" "$_authz_url"
 | 
| 
 | 
  4216           _clearup
 | 
| 
 | 
  4217           _on_issue_err "$_post_hook"
 | 
| 
 | 
  4218           return 1
 | 
| 
 | 
  4219         fi
 | 
| 
 | 
  4220 
 | 
| 
 | 
  4221         response="$(echo "$response" | _normalizeJson)"
 | 
| 
 | 
  4222         _debug2 response "$response"
 | 
| 
 | 
  4223         _d="$(echo "$response" | _egrep_o '"value" *: *"[^"]*"' | cut -d : -f 2 | tr -d ' "')"
 | 
| 
 | 
  4224         if _contains "$response" "\"wildcard\" *: *true"; then
 | 
| 
 | 
  4225           _d="*.$_d"
 | 
| 
 | 
  4226         fi
 | 
| 
 | 
  4227         _debug2 _d "$_d"
 | 
| 
 | 
  4228         _authorizations_map="$_d,$response
 | 
| 
 | 
  4229 $_authorizations_map"
 | 
| 
 | 
  4230       done
 | 
| 
 | 
  4231       _debug2 _authorizations_map "$_authorizations_map"
 | 
| 
 | 
  4232     fi
 | 
| 
 | 
  4233 
 | 
| 
 | 
  4234     _index=0
 | 
| 
 | 
  4235     _currentRoot=""
 | 
| 
 | 
  4236     _w_index=1
 | 
| 
 | 
  4237     while true; do
 | 
| 
 | 
  4238       d="$(echo "$_main_domain,$_alt_domains," | cut -d , -f "$_w_index")"
 | 
| 
 | 
  4239       _w_index="$(_math "$_w_index" + 1)"
 | 
| 
 | 
  4240       _debug d "$d"
 | 
| 
 | 
  4241       if [ -z "$d" ]; then
 | 
| 
 | 
  4242         break
 | 
| 
 | 
  4243       fi
 | 
| 
 | 
  4244       _info "Getting webroot for domain" "$d"
 | 
| 
 | 
  4245       _index=$(_math $_index + 1)
 | 
| 
 | 
  4246       _w="$(echo $_web_roots | cut -d , -f $_index)"
 | 
| 
 | 
  4247       _debug _w "$_w"
 | 
| 
 | 
  4248       if [ "$_w" ]; then
 | 
| 
 | 
  4249         _currentRoot="$_w"
 | 
| 
 | 
  4250       fi
 | 
| 
 | 
  4251       _debug "_currentRoot" "$_currentRoot"
 | 
| 
 | 
  4252 
 | 
| 
 | 
  4253       vtype="$VTYPE_HTTP"
 | 
| 
 | 
  4254       #todo, v2 wildcard force to use dns
 | 
| 
 | 
  4255       if _startswith "$_currentRoot" "$W_DNS"; then
 | 
| 
 | 
  4256         vtype="$VTYPE_DNS"
 | 
| 
 | 
  4257       fi
 | 
| 
 | 
  4258 
 | 
| 
 | 
  4259       if [ "$_currentRoot" = "$W_ALPN" ]; then
 | 
| 
 | 
  4260         vtype="$VTYPE_ALPN"
 | 
| 
 | 
  4261       fi
 | 
| 
 | 
  4262 
 | 
| 
 | 
  4263       if [ "$ACME_VERSION" = "2" ]; then
 | 
| 
 | 
  4264         _idn_d="$(_idn "$d")"
 | 
| 
 | 
  4265         _candidates="$(echo "$_authorizations_map" | grep -i "^$_idn_d,")"
 | 
| 
 | 
  4266         _debug2 _candidates "$_candidates"
 | 
| 
 | 
  4267         if [ "$(echo "$_candidates" | wc -l)" -gt 1 ]; then
 | 
| 
 | 
  4268           for _can in $_candidates; do
 | 
| 
 | 
  4269             if _startswith "$(echo "$_can" | tr '.' '|')" "$(echo "$_idn_d" | tr '.' '|'),"; then
 | 
| 
 | 
  4270               _candidates="$_can"
 | 
| 
 | 
  4271               break
 | 
| 
 | 
  4272             fi
 | 
| 
 | 
  4273           done
 | 
| 
 | 
  4274         fi
 | 
| 
 | 
  4275         response="$(echo "$_candidates" | sed "s/$_idn_d,//")"
 | 
| 
 | 
  4276         _debug2 "response" "$response"
 | 
| 
 | 
  4277         if [ -z "$response" ]; then
 | 
| 
 | 
  4278           _err "get to authz error."
 | 
| 
 | 
  4279           _err "_authorizations_map" "$_authorizations_map"
 | 
| 
 | 
  4280           _clearup
 | 
| 
 | 
  4281           _on_issue_err "$_post_hook"
 | 
| 
 | 
  4282           return 1
 | 
| 
 | 
  4283         fi
 | 
| 
 | 
  4284       else
 | 
| 
 | 
  4285         if ! __get_domain_new_authz "$d"; then
 | 
| 
 | 
  4286           _clearup
 | 
| 
 | 
  4287           _on_issue_err "$_post_hook"
 | 
| 
 | 
  4288           return 1
 | 
| 
 | 
  4289         fi
 | 
| 
 | 
  4290       fi
 | 
| 
 | 
  4291 
 | 
| 
 | 
  4292       if [ -z "$thumbprint" ]; then
 | 
| 
 | 
  4293         thumbprint="$(__calc_account_thumbprint)"
 | 
| 
 | 
  4294       fi
 | 
| 
 | 
  4295 
 | 
| 
 | 
  4296       entry="$(echo "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"
 | 
| 
 | 
  4297       _debug entry "$entry"
 | 
| 
 | 
  4298       keyauthorization=""
 | 
| 
 | 
  4299       if [ -z "$entry" ]; then
 | 
| 
 | 
  4300         if ! _startswith "$d" '*.'; then
 | 
| 
 | 
  4301           _debug "Not a wildcard domain, lets check whether the validation is already valid."
 | 
| 
 | 
  4302           if echo "$response" | grep '"status":"valid"' >/dev/null 2>&1; then
 | 
| 
 | 
  4303             _debug "$d is already valid."
 | 
| 
 | 
  4304             keyauthorization="$STATE_VERIFIED"
 | 
| 
 | 
  4305             _debug keyauthorization "$keyauthorization"
 | 
| 
 | 
  4306           fi
 | 
| 
 | 
  4307         fi
 | 
| 
 | 
  4308         if [ -z "$keyauthorization" ]; then
 | 
| 
 | 
  4309           _err "Error, can not get domain token entry $d for $vtype"
 | 
| 
 | 
  4310           _supported_vtypes="$(echo "$response" | _egrep_o "\"challenges\":\[[^]]*]" | tr '{' "\n" | grep type | cut -d '"' -f 4 | tr "\n" ' ')"
 | 
| 
 | 
  4311           if [ "$_supported_vtypes" ]; then
 | 
| 
 | 
  4312             _err "The supported validation types are: $_supported_vtypes, but you specified: $vtype"
 | 
| 
 | 
  4313           fi
 | 
| 
 | 
  4314           _clearup
 | 
| 
 | 
  4315           _on_issue_err "$_post_hook"
 | 
| 
 | 
  4316           return 1
 | 
| 
 | 
  4317         fi
 | 
| 
 | 
  4318       fi
 | 
| 
 | 
  4319 
 | 
| 
 | 
  4320       if [ -z "$keyauthorization" ]; then
 | 
| 
 | 
  4321         token="$(echo "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')"
 | 
| 
 | 
  4322         _debug token "$token"
 | 
| 
 | 
  4323 
 | 
| 
 | 
  4324         if [ -z "$token" ]; then
 | 
| 
 | 
  4325           _err "Error, can not get domain token $entry"
 | 
| 
 | 
  4326           _clearup
 | 
| 
 | 
  4327           _on_issue_err "$_post_hook"
 | 
| 
 | 
  4328           return 1
 | 
| 
 | 
  4329         fi
 | 
| 
 | 
  4330         if [ "$ACME_VERSION" = "2" ]; then
 | 
| 
 | 
  4331           uri="$(echo "$entry" | _egrep_o '"url":"[^"]*' | cut -d '"' -f 4 | _head_n 1)"
 | 
| 
 | 
  4332         else
 | 
| 
 | 
  4333           uri="$(echo "$entry" | _egrep_o '"uri":"[^"]*' | cut -d '"' -f 4)"
 | 
| 
 | 
  4334         fi
 | 
| 
 | 
  4335         _debug uri "$uri"
 | 
| 
 | 
  4336 
 | 
| 
 | 
  4337         if [ -z "$uri" ]; then
 | 
| 
 | 
  4338           _err "Error, can not get domain uri. $entry"
 | 
| 
 | 
  4339           _clearup
 | 
| 
 | 
  4340           _on_issue_err "$_post_hook"
 | 
| 
 | 
  4341           return 1
 | 
| 
 | 
  4342         fi
 | 
| 
 | 
  4343         keyauthorization="$token.$thumbprint"
 | 
| 
 | 
  4344         _debug keyauthorization "$keyauthorization"
 | 
| 
 | 
  4345 
 | 
| 
 | 
  4346         if printf "%s" "$response" | grep '"status":"valid"' >/dev/null 2>&1; then
 | 
| 
 | 
  4347           _debug "$d is already verified."
 | 
| 
 | 
  4348           keyauthorization="$STATE_VERIFIED"
 | 
| 
 | 
  4349           _debug keyauthorization "$keyauthorization"
 | 
| 
 | 
  4350         fi
 | 
| 
 | 
  4351       fi
 | 
| 
 | 
  4352 
 | 
| 
 | 
  4353       dvlist="$d$sep$keyauthorization$sep$uri$sep$vtype$sep$_currentRoot"
 | 
| 
 | 
  4354       _debug dvlist "$dvlist"
 | 
| 
 | 
  4355 
 | 
| 
 | 
  4356       vlist="$vlist$dvlist$dvsep"
 | 
| 
 | 
  4357 
 | 
| 
 | 
  4358     done
 | 
| 
 | 
  4359     _debug vlist "$vlist"
 | 
| 
 | 
  4360     #add entry
 | 
| 
 | 
  4361     dns_entries=""
 | 
| 
 | 
  4362     dnsadded=""
 | 
| 
 | 
  4363     ventries=$(echo "$vlist" | tr "$dvsep" ' ')
 | 
| 
 | 
  4364     _alias_index=1
 | 
| 
 | 
  4365     for ventry in $ventries; do
 | 
| 
 | 
  4366       d=$(echo "$ventry" | cut -d "$sep" -f 1)
 | 
| 
 | 
  4367       keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2)
 | 
| 
 | 
  4368       vtype=$(echo "$ventry" | cut -d "$sep" -f 4)
 | 
| 
 | 
  4369       _currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5)
 | 
| 
 | 
  4370       _debug d "$d"
 | 
| 
 | 
  4371       if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then
 | 
| 
 | 
  4372         _debug "$d is already verified, skip $vtype."
 | 
| 
 | 
  4373         _alias_index="$(_math "$_alias_index" + 1)"
 | 
| 
 | 
  4374         continue
 | 
| 
 | 
  4375       fi
 | 
| 
 | 
  4376 
 | 
| 
 | 
  4377       if [ "$vtype" = "$VTYPE_DNS" ]; then
 | 
| 
 | 
  4378         dnsadded='0'
 | 
| 
 | 
  4379         _dns_root_d="$d"
 | 
| 
 | 
  4380         if _startswith "$_dns_root_d" "*."; then
 | 
| 
 | 
  4381           _dns_root_d="$(echo "$_dns_root_d" | sed 's/*.//')"
 | 
| 
 | 
  4382         fi
 | 
| 
 | 
  4383         _d_alias="$(_getfield "$_challenge_alias" "$_alias_index")"
 | 
| 
 | 
  4384         _alias_index="$(_math "$_alias_index" + 1)"
 | 
| 
 | 
  4385         _debug "_d_alias" "$_d_alias"
 | 
| 
 | 
  4386         if [ "$_d_alias" ]; then
 | 
| 
 | 
  4387           if _startswith "$_d_alias" "$DNS_ALIAS_PREFIX"; then
 | 
| 
 | 
  4388             txtdomain="$(echo "$_d_alias" | sed "s/$DNS_ALIAS_PREFIX//")"
 | 
| 
 | 
  4389           else
 | 
| 
 | 
  4390             txtdomain="_acme-challenge.$_d_alias"
 | 
| 
 | 
  4391           fi
 | 
| 
 | 
  4392           dns_entry="${_dns_root_d}${dvsep}_acme-challenge.$_dns_root_d$dvsep$txtdomain$dvsep$_currentRoot"
 | 
| 
 | 
  4393         else
 | 
| 
 | 
  4394           txtdomain="_acme-challenge.$_dns_root_d"
 | 
| 
 | 
  4395           dns_entry="${_dns_root_d}${dvsep}_acme-challenge.$_dns_root_d$dvsep$dvsep$_currentRoot"
 | 
| 
 | 
  4396         fi
 | 
| 
 | 
  4397 
 | 
| 
 | 
  4398         _debug txtdomain "$txtdomain"
 | 
| 
 | 
  4399         txt="$(printf "%s" "$keyauthorization" | _digest "sha256" | _url_replace)"
 | 
| 
 | 
  4400         _debug txt "$txt"
 | 
| 
 | 
  4401 
 | 
| 
 | 
  4402         d_api="$(_findHook "$_dns_root_d" $_SUB_FOLDER_DNSAPI "$_currentRoot")"
 | 
| 
 | 
  4403         _debug d_api "$d_api"
 | 
| 
 | 
  4404 
 | 
| 
 | 
  4405         dns_entry="$dns_entry$dvsep$txt${dvsep}$d_api"
 | 
| 
 | 
  4406         _debug2 dns_entry "$dns_entry"
 | 
| 
 | 
  4407         if [ "$d_api" ]; then
 | 
| 
 | 
  4408           _debug "Found domain api file: $d_api"
 | 
| 
 | 
  4409         else
 | 
| 
 | 
  4410           if [ "$_currentRoot" != "$W_DNS" ]; then
 | 
| 
 | 
  4411             _err "Can not find dns api hook for: $_currentRoot"
 | 
| 
 | 
  4412             _info "You need to add the txt record manually."
 | 
| 
 | 
  4413           fi
 | 
| 
 | 
  4414           _info "$(__red "Add the following TXT record:")"
 | 
| 
 | 
  4415           _info "$(__red "Domain: '$(__green "$txtdomain")'")"
 | 
| 
 | 
  4416           _info "$(__red "TXT value: '$(__green "$txt")'")"
 | 
| 
 | 
  4417           _info "$(__red "Please be aware that you prepend _acme-challenge. before your domain")"
 | 
| 
 | 
  4418           _info "$(__red "so the resulting subdomain will be: $txtdomain")"
 | 
| 
 | 
  4419           continue
 | 
| 
 | 
  4420         fi
 | 
| 
 | 
  4421 
 | 
| 
 | 
  4422         (
 | 
| 
 | 
  4423           if ! . "$d_api"; then
 | 
| 
 | 
  4424             _err "Load file $d_api error. Please check your api file and try again."
 | 
| 
 | 
  4425             return 1
 | 
| 
 | 
  4426           fi
 | 
| 
 | 
  4427 
 | 
| 
 | 
  4428           addcommand="${_currentRoot}_add"
 | 
| 
 | 
  4429           if ! _exists "$addcommand"; then
 | 
| 
 | 
  4430             _err "It seems that your api file is not correct, it must have a function named: $addcommand"
 | 
| 
 | 
  4431             return 1
 | 
| 
 | 
  4432           fi
 | 
| 
 | 
  4433           _info "Adding txt value: $txt for domain:  $txtdomain"
 | 
| 
 | 
  4434           if ! $addcommand "$txtdomain" "$txt"; then
 | 
| 
 | 
  4435             _err "Error add txt for domain:$txtdomain"
 | 
| 
 | 
  4436             return 1
 | 
| 
 | 
  4437           fi
 | 
| 
 | 
  4438           _info "The txt record is added: Success."
 | 
| 
 | 
  4439         )
 | 
| 
 | 
  4440 
 | 
| 
 | 
  4441         if [ "$?" != "0" ]; then
 | 
| 
 | 
  4442           _on_issue_err "$_post_hook" "$vlist"
 | 
| 
 | 
  4443           _clearup
 | 
| 
 | 
  4444           return 1
 | 
| 
 | 
  4445         fi
 | 
| 
 | 
  4446         dns_entries="$dns_entries$dns_entry
 | 
| 
 | 
  4447 "
 | 
| 
 | 
  4448         _debug2 "$dns_entries"
 | 
| 
 | 
  4449         dnsadded='1'
 | 
| 
 | 
  4450       fi
 | 
| 
 | 
  4451     done
 | 
| 
 | 
  4452 
 | 
| 
 | 
  4453     if [ "$dnsadded" = '0' ]; then
 | 
| 
 | 
  4454       _savedomainconf "Le_Vlist" "$vlist"
 | 
| 
 | 
  4455       _debug "Dns record not added yet, so, save to $DOMAIN_CONF and exit."
 | 
| 
 | 
  4456       _err "Please add the TXT records to the domains, and re-run with --renew."
 | 
| 
 | 
  4457       _on_issue_err "$_post_hook"
 | 
| 
 | 
  4458       _clearup
 | 
| 
 | 
  4459       return 1
 | 
| 
 | 
  4460     fi
 | 
| 
 | 
  4461 
 | 
| 
 | 
  4462   fi
 | 
| 
 | 
  4463 
 | 
| 
 | 
  4464   if [ "$dns_entries" ]; then
 | 
| 
 | 
  4465     if [ -z "$Le_DNSSleep" ]; then
 | 
| 
 | 
  4466       _info "Let's check each DNS record now. Sleep 20 seconds first."
 | 
| 
 | 
  4467       _sleep 20
 | 
| 
 | 
  4468       if ! _check_dns_entries; then
 | 
| 
 | 
  4469         _err "check dns error."
 | 
| 
 | 
  4470         _on_issue_err "$_post_hook"
 | 
| 
 | 
  4471         _clearup
 | 
| 
 | 
  4472         return 1
 | 
| 
 | 
  4473       fi
 | 
| 
 | 
  4474     else
 | 
| 
 | 
  4475       _savedomainconf "Le_DNSSleep" "$Le_DNSSleep"
 | 
| 
 | 
  4476       _info "Sleep $(__green $Le_DNSSleep) seconds for the txt records to take effect"
 | 
| 
 | 
  4477       _sleep "$Le_DNSSleep"
 | 
| 
 | 
  4478     fi
 | 
| 
 | 
  4479   fi
 | 
| 
 | 
  4480 
 | 
| 
 | 
  4481   NGINX_RESTORE_VLIST=""
 | 
| 
 | 
  4482   _debug "ok, let's start to verify"
 | 
| 
 | 
  4483 
 | 
| 
 | 
  4484   _ncIndex=1
 | 
| 
 | 
  4485   ventries=$(echo "$vlist" | tr "$dvsep" ' ')
 | 
| 
 | 
  4486   for ventry in $ventries; do
 | 
| 
 | 
  4487     d=$(echo "$ventry" | cut -d "$sep" -f 1)
 | 
| 
 | 
  4488     keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2)
 | 
| 
 | 
  4489     uri=$(echo "$ventry" | cut -d "$sep" -f 3)
 | 
| 
 | 
  4490     vtype=$(echo "$ventry" | cut -d "$sep" -f 4)
 | 
| 
 | 
  4491     _currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5)
 | 
| 
 | 
  4492 
 | 
| 
 | 
  4493     if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then
 | 
| 
 | 
  4494       _info "$d is already verified, skip $vtype."
 | 
| 
 | 
  4495       continue
 | 
| 
 | 
  4496     fi
 | 
| 
 | 
  4497 
 | 
| 
 | 
  4498     _info "Verifying: $d"
 | 
| 
 | 
  4499     _debug "d" "$d"
 | 
| 
 | 
  4500     _debug "keyauthorization" "$keyauthorization"
 | 
| 
 | 
  4501     _debug "uri" "$uri"
 | 
| 
 | 
  4502     removelevel=""
 | 
| 
 | 
  4503     token="$(printf "%s" "$keyauthorization" | cut -d '.' -f 1)"
 | 
| 
 | 
  4504 
 | 
| 
 | 
  4505     _debug "_currentRoot" "$_currentRoot"
 | 
| 
 | 
  4506 
 | 
| 
 | 
  4507     if [ "$vtype" = "$VTYPE_HTTP" ]; then
 | 
| 
 | 
  4508       if [ "$_currentRoot" = "$NO_VALUE" ]; then
 | 
| 
 | 
  4509         _info "Standalone mode server"
 | 
| 
 | 
  4510         _ncaddr="$(_getfield "$_local_addr" "$_ncIndex")"
 | 
| 
 | 
  4511         _ncIndex="$(_math $_ncIndex + 1)"
 | 
| 
 | 
  4512         _startserver "$keyauthorization" "$_ncaddr"
 | 
| 
 | 
  4513         if [ "$?" != "0" ]; then
 | 
| 
 | 
  4514           _clearup
 | 
| 
 | 
  4515           _on_issue_err "$_post_hook" "$vlist"
 | 
| 
 | 
  4516           return 1
 | 
| 
 | 
  4517         fi
 | 
| 
 | 
  4518         sleep 1
 | 
| 
 | 
  4519         _debug serverproc "$serverproc"
 | 
| 
 | 
  4520       elif [ "$_currentRoot" = "$MODE_STATELESS" ]; then
 | 
| 
 | 
  4521         _info "Stateless mode for domain:$d"
 | 
| 
 | 
  4522         _sleep 1
 | 
| 
 | 
  4523       elif _startswith "$_currentRoot" "$NGINX"; then
 | 
| 
 | 
  4524         _info "Nginx mode for domain:$d"
 | 
| 
 | 
  4525         #set up nginx server
 | 
| 
 | 
  4526         FOUND_REAL_NGINX_CONF=""
 | 
| 
 | 
  4527         BACKUP_NGINX_CONF=""
 | 
| 
 | 
  4528         if ! _setNginx "$d" "$_currentRoot" "$thumbprint"; then
 | 
| 
 | 
  4529           _clearup
 | 
| 
 | 
  4530           _on_issue_err "$_post_hook" "$vlist"
 | 
| 
 | 
  4531           return 1
 | 
| 
 | 
  4532         fi
 | 
| 
 | 
  4533 
 | 
| 
 | 
  4534         if [ "$FOUND_REAL_NGINX_CONF" ]; then
 | 
| 
 | 
  4535           _realConf="$FOUND_REAL_NGINX_CONF"
 | 
| 
 | 
  4536           _backup="$BACKUP_NGINX_CONF"
 | 
| 
 | 
  4537           _debug _realConf "$_realConf"
 | 
| 
 | 
  4538           NGINX_RESTORE_VLIST="$d$sep$_realConf$sep$_backup$dvsep$NGINX_RESTORE_VLIST"
 | 
| 
 | 
  4539         fi
 | 
| 
 | 
  4540         _sleep 1
 | 
| 
 | 
  4541       else
 | 
| 
 | 
  4542         if [ "$_currentRoot" = "apache" ]; then
 | 
| 
 | 
  4543           wellknown_path="$ACME_DIR"
 | 
| 
 | 
  4544         else
 | 
| 
 | 
  4545           wellknown_path="$_currentRoot/.well-known/acme-challenge"
 | 
| 
 | 
  4546           if [ ! -d "$_currentRoot/.well-known" ]; then
 | 
| 
 | 
  4547             removelevel='1'
 | 
| 
 | 
  4548           elif [ ! -d "$_currentRoot/.well-known/acme-challenge" ]; then
 | 
| 
 | 
  4549             removelevel='2'
 | 
| 
 | 
  4550           else
 | 
| 
 | 
  4551             removelevel='3'
 | 
| 
 | 
  4552           fi
 | 
| 
 | 
  4553         fi
 | 
| 
 | 
  4554 
 | 
| 
 | 
  4555         _debug wellknown_path "$wellknown_path"
 | 
| 
 | 
  4556 
 | 
| 
 | 
  4557         _debug "writing token:$token to $wellknown_path/$token"
 | 
| 
 | 
  4558 
 | 
| 
 | 
  4559         mkdir -p "$wellknown_path"
 | 
| 
 | 
  4560 
 | 
| 
 | 
  4561         if ! printf "%s" "$keyauthorization" >"$wellknown_path/$token"; then
 | 
| 
 | 
  4562           _err "$d:Can not write token to file : $wellknown_path/$token"
 | 
| 
 | 
  4563           _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
 | 
| 
 | 
  4564           _clearup
 | 
| 
 | 
  4565           _on_issue_err "$_post_hook" "$vlist"
 | 
| 
 | 
  4566           return 1
 | 
| 
 | 
  4567         fi
 | 
| 
 | 
  4568 
 | 
| 
 | 
  4569         if [ ! "$usingApache" ]; then
 | 
| 
 | 
  4570           if webroot_owner=$(_stat "$_currentRoot"); then
 | 
| 
 | 
  4571             _debug "Changing owner/group of .well-known to $webroot_owner"
 | 
| 
 | 
  4572             if ! _exec "chown -R \"$webroot_owner\" \"$_currentRoot/.well-known\""; then
 | 
| 
 | 
  4573               _debug "$(cat "$_EXEC_TEMP_ERR")"
 | 
| 
 | 
  4574               _exec_err >/dev/null 2>&1
 | 
| 
 | 
  4575             fi
 | 
| 
 | 
  4576           else
 | 
| 
 | 
  4577             _debug "not changing owner/group of webroot"
 | 
| 
 | 
  4578           fi
 | 
| 
 | 
  4579         fi
 | 
| 
 | 
  4580 
 | 
| 
 | 
  4581       fi
 | 
| 
 | 
  4582     elif [ "$vtype" = "$VTYPE_ALPN" ]; then
 | 
| 
 | 
  4583       acmevalidationv1="$(printf "%s" "$keyauthorization" | _digest "sha256" "hex")"
 | 
| 
 | 
  4584       _debug acmevalidationv1 "$acmevalidationv1"
 | 
| 
 | 
  4585       if ! _starttlsserver "$d" "" "$Le_TLSPort" "$keyauthorization" "$_ncaddr" "$acmevalidationv1"; then
 | 
| 
 | 
  4586         _err "Start tls server error."
 | 
| 
 | 
  4587         _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
 | 
| 
 | 
  4588         _clearup
 | 
| 
 | 
  4589         _on_issue_err "$_post_hook" "$vlist"
 | 
| 
 | 
  4590         return 1
 | 
| 
 | 
  4591       fi
 | 
| 
 | 
  4592     fi
 | 
| 
 | 
  4593 
 | 
| 
 | 
  4594     if ! __trigger_validation "$uri" "$keyauthorization" "$vtype"; then
 | 
| 
 | 
  4595       _err "$d:Can not get challenge: $response"
 | 
| 
 | 
  4596       _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
 | 
| 
 | 
  4597       _clearup
 | 
| 
 | 
  4598       _on_issue_err "$_post_hook" "$vlist"
 | 
| 
 | 
  4599       return 1
 | 
| 
 | 
  4600     fi
 | 
| 
 | 
  4601 
 | 
| 
 | 
  4602     if [ "$code" ] && [ "$code" != '202' ]; then
 | 
| 
 | 
  4603       if [ "$code" = '200' ]; then
 | 
| 
 | 
  4604         _debug "trigger validation code: $code"
 | 
| 
 | 
  4605       else
 | 
| 
 | 
  4606         _err "$d:Challenge error: $response"
 | 
| 
 | 
  4607         _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
 | 
| 
 | 
  4608         _clearup
 | 
| 
 | 
  4609         _on_issue_err "$_post_hook" "$vlist"
 | 
| 
 | 
  4610         return 1
 | 
| 
 | 
  4611       fi
 | 
| 
 | 
  4612     fi
 | 
| 
 | 
  4613 
 | 
| 
 | 
  4614     waittimes=0
 | 
| 
 | 
  4615     if [ -z "$MAX_RETRY_TIMES" ]; then
 | 
| 
 | 
  4616       MAX_RETRY_TIMES=30
 | 
| 
 | 
  4617     fi
 | 
| 
 | 
  4618 
 | 
| 
 | 
  4619     while true; do
 | 
| 
 | 
  4620       waittimes=$(_math "$waittimes" + 1)
 | 
| 
 | 
  4621       if [ "$waittimes" -ge "$MAX_RETRY_TIMES" ]; then
 | 
| 
 | 
  4622         _err "$d:Timeout"
 | 
| 
 | 
  4623         _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
 | 
| 
 | 
  4624         _clearup
 | 
| 
 | 
  4625         _on_issue_err "$_post_hook" "$vlist"
 | 
| 
 | 
  4626         return 1
 | 
| 
 | 
  4627       fi
 | 
| 
 | 
  4628 
 | 
| 
 | 
  4629       _debug "sleep 2 secs to verify"
 | 
| 
 | 
  4630       sleep 2
 | 
| 
 | 
  4631       _debug "checking"
 | 
| 
 | 
  4632       if [ "$ACME_VERSION" = "2" ]; then
 | 
| 
 | 
  4633         _send_signed_request "$uri"
 | 
| 
 | 
  4634       else
 | 
| 
 | 
  4635         response="$(_get "$uri")"
 | 
| 
 | 
  4636       fi
 | 
| 
 | 
  4637       if [ "$?" != "0" ]; then
 | 
| 
 | 
  4638         _err "$d:Verify error:$response"
 | 
| 
 | 
  4639         _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
 | 
| 
 | 
  4640         _clearup
 | 
| 
 | 
  4641         _on_issue_err "$_post_hook" "$vlist"
 | 
| 
 | 
  4642         return 1
 | 
| 
 | 
  4643       fi
 | 
| 
 | 
  4644       _debug2 original "$response"
 | 
| 
 | 
  4645 
 | 
| 
 | 
  4646       response="$(echo "$response" | _normalizeJson)"
 | 
| 
 | 
  4647       _debug2 response "$response"
 | 
| 
 | 
  4648 
 | 
| 
 | 
  4649       status=$(echo "$response" | _egrep_o '"status":"[^"]*' | cut -d : -f 2 | tr -d '"')
 | 
| 
 | 
  4650       if [ "$status" = "valid" ]; then
 | 
| 
 | 
  4651         _info "$(__green Success)"
 | 
| 
 | 
  4652         _stopserver "$serverproc"
 | 
| 
 | 
  4653         serverproc=""
 | 
| 
 | 
  4654         _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
 | 
| 
 | 
  4655         break
 | 
| 
 | 
  4656       fi
 | 
| 
 | 
  4657 
 | 
| 
 | 
  4658       if [ "$status" = "invalid" ]; then
 | 
| 
 | 
  4659         error="$(echo "$response" | _egrep_o '"error":\{[^\}]*')"
 | 
| 
 | 
  4660         _debug2 error "$error"
 | 
| 
 | 
  4661         errordetail="$(echo "$error" | _egrep_o '"detail": *"[^"]*' | cut -d '"' -f 4)"
 | 
| 
 | 
  4662         _debug2 errordetail "$errordetail"
 | 
| 
 | 
  4663         if [ "$errordetail" ]; then
 | 
| 
 | 
  4664           _err "$d:Verify error:$errordetail"
 | 
| 
 | 
  4665         else
 | 
| 
 | 
  4666           _err "$d:Verify error:$error"
 | 
| 
 | 
  4667         fi
 | 
| 
 | 
  4668         if [ "$DEBUG" ]; then
 | 
| 
 | 
  4669           if [ "$vtype" = "$VTYPE_HTTP" ]; then
 | 
| 
 | 
  4670             _debug "Debug: get token url."
 | 
| 
 | 
  4671             _get "http://$d/.well-known/acme-challenge/$token" "" 1
 | 
| 
 | 
  4672           fi
 | 
| 
 | 
  4673         fi
 | 
| 
 | 
  4674         _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
 | 
| 
 | 
  4675         _clearup
 | 
| 
 | 
  4676         _on_issue_err "$_post_hook" "$vlist"
 | 
| 
 | 
  4677         return 1
 | 
| 
 | 
  4678       fi
 | 
| 
 | 
  4679 
 | 
| 
 | 
  4680       if [ "$status" = "pending" ]; then
 | 
| 
 | 
  4681         _info "Pending"
 | 
| 
 | 
  4682       elif [ "$status" = "processing" ]; then
 | 
| 
 | 
  4683         _info "Processing"
 | 
| 
 | 
  4684       else
 | 
| 
 | 
  4685         _err "$d:Verify error:$response"
 | 
| 
 | 
  4686         _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
 | 
| 
 | 
  4687         _clearup
 | 
| 
 | 
  4688         _on_issue_err "$_post_hook" "$vlist"
 | 
| 
 | 
  4689         return 1
 | 
| 
 | 
  4690       fi
 | 
| 
 | 
  4691 
 | 
| 
 | 
  4692     done
 | 
| 
 | 
  4693 
 | 
| 
 | 
  4694   done
 | 
| 
 | 
  4695 
 | 
| 
 | 
  4696   _clearup
 | 
| 
 | 
  4697   _info "Verify finished, start to sign."
 | 
| 
 | 
  4698   der="$(_getfile "${CSR_PATH}" "${BEGIN_CSR}" "${END_CSR}" | tr -d "\r\n" | _url_replace)"
 | 
| 
 | 
  4699 
 | 
| 
 | 
  4700   if [ "$ACME_VERSION" = "2" ]; then
 | 
| 
 | 
  4701     _info "Lets finalize the order."
 | 
| 
 | 
  4702     _info "Le_OrderFinalize" "$Le_OrderFinalize"
 | 
| 
 | 
  4703     if ! _send_signed_request "${Le_OrderFinalize}" "{\"csr\": \"$der\"}"; then
 | 
| 
 | 
  4704       _err "Sign failed."
 | 
| 
 | 
  4705       _on_issue_err "$_post_hook"
 | 
| 
 | 
  4706       return 1
 | 
| 
 | 
  4707     fi
 | 
| 
 | 
  4708     if [ "$code" != "200" ]; then
 | 
| 
 | 
  4709       _err "Sign failed, finalize code is not 200."
 | 
| 
 | 
  4710       _err "$response"
 | 
| 
 | 
  4711       _on_issue_err "$_post_hook"
 | 
| 
 | 
  4712       return 1
 | 
| 
 | 
  4713     fi
 | 
| 
 | 
  4714     if [ -z "$Le_LinkOrder" ]; then
 | 
| 
 | 
  4715       Le_LinkOrder="$(echo "$responseHeaders" | grep -i '^Location.*$' | _tail_n 1 | tr -d "\r\n \t" | cut -d ":" -f 2-)"
 | 
| 
 | 
  4716     fi
 | 
| 
 | 
  4717 
 | 
| 
 | 
  4718     _savedomainconf "Le_LinkOrder" "$Le_LinkOrder"
 | 
| 
 | 
  4719 
 | 
| 
 | 
  4720     _link_cert_retry=0
 | 
| 
 | 
  4721     _MAX_CERT_RETRY=30
 | 
| 
 | 
  4722     while [ "$_link_cert_retry" -lt "$_MAX_CERT_RETRY" ]; do
 | 
| 
 | 
  4723       if _contains "$response" "\"status\":\"valid\""; then
 | 
| 
 | 
  4724         _debug "Order status is valid."
 | 
| 
 | 
  4725         Le_LinkCert="$(echo "$response" | _egrep_o '"certificate" *: *"[^"]*"' | cut -d '"' -f 4)"
 | 
| 
 | 
  4726         _debug Le_LinkCert "$Le_LinkCert"
 | 
| 
 | 
  4727         if [ -z "$Le_LinkCert" ]; then
 | 
| 
 | 
  4728           _err "Sign error, can not find Le_LinkCert"
 | 
| 
 | 
  4729           _err "$response"
 | 
| 
 | 
  4730           _on_issue_err "$_post_hook"
 | 
| 
 | 
  4731           return 1
 | 
| 
 | 
  4732         fi
 | 
| 
 | 
  4733         break
 | 
| 
 | 
  4734       elif _contains "$response" "\"processing\""; then
 | 
| 
 | 
  4735         _info "Order status is processing, lets sleep and retry."
 | 
| 
 | 
  4736         _retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *:" | cut -d : -f 2 | tr -d ' ' | tr -d '\r')
 | 
| 
 | 
  4737         _debug "_retryafter" "$_retryafter"
 | 
| 
 | 
  4738         if [ "$_retryafter" ]; then
 | 
| 
 | 
  4739           _info "Retry after: $_retryafter"
 | 
| 
 | 
  4740           _sleep $_retryafter
 | 
| 
 | 
  4741         else
 | 
| 
 | 
  4742           _sleep 2
 | 
| 
 | 
  4743         fi
 | 
| 
 | 
  4744       else
 | 
| 
 | 
  4745         _err "Sign error, wrong status"
 | 
| 
 | 
  4746         _err "$response"
 | 
| 
 | 
  4747         _on_issue_err "$_post_hook"
 | 
| 
 | 
  4748         return 1
 | 
| 
 | 
  4749       fi
 | 
| 
 | 
  4750       #the order is processing, so we are going to poll order status
 | 
| 
 | 
  4751       if [ -z "$Le_LinkOrder" ]; then
 | 
| 
 | 
  4752         _err "Sign error, can not get order link location header"
 | 
| 
 | 
  4753         _err "responseHeaders" "$responseHeaders"
 | 
| 
 | 
  4754         _on_issue_err "$_post_hook"
 | 
| 
 | 
  4755         return 1
 | 
| 
 | 
  4756       fi
 | 
| 
 | 
  4757       _info "Polling order status: $Le_LinkOrder"
 | 
| 
 | 
  4758       if ! _send_signed_request "$Le_LinkOrder"; then
 | 
| 
 | 
  4759         _err "Sign failed, can not post to Le_LinkOrder cert:$Le_LinkOrder."
 | 
| 
 | 
  4760         _err "$response"
 | 
| 
 | 
  4761         _on_issue_err "$_post_hook"
 | 
| 
 | 
  4762         return 1
 | 
| 
 | 
  4763       fi
 | 
| 
 | 
  4764       _link_cert_retry="$(_math $_link_cert_retry + 1)"
 | 
| 
 | 
  4765     done
 | 
| 
 | 
  4766 
 | 
| 
 | 
  4767     if [ -z "$Le_LinkCert" ]; then
 | 
| 
 | 
  4768       _err "Sign failed, can not get Le_LinkCert, retry time limit."
 | 
| 
 | 
  4769       _err "$response"
 | 
| 
 | 
  4770       _on_issue_err "$_post_hook"
 | 
| 
 | 
  4771       return 1
 | 
| 
 | 
  4772     fi
 | 
| 
 | 
  4773     _info "Downloading cert."
 | 
| 
 | 
  4774     _info "Le_LinkCert" "$Le_LinkCert"
 | 
| 
 | 
  4775     if ! _send_signed_request "$Le_LinkCert"; then
 | 
| 
 | 
  4776       _err "Sign failed, can not download cert:$Le_LinkCert."
 | 
| 
 | 
  4777       _err "$response"
 | 
| 
 | 
  4778       _on_issue_err "$_post_hook"
 | 
| 
 | 
  4779       return 1
 | 
| 
 | 
  4780     fi
 | 
| 
 | 
  4781 
 | 
| 
 | 
  4782     echo "$response" >"$CERT_PATH"
 | 
| 
 | 
  4783     _split_cert_chain "$CERT_PATH" "$CERT_FULLCHAIN_PATH" "$CA_CERT_PATH"
 | 
| 
 | 
  4784 
 | 
| 
 | 
  4785     if [ "$_preferred_chain" ] && [ -f "$CERT_FULLCHAIN_PATH" ]; then
 | 
| 
 | 
  4786       if ! _match_issuer "$CERT_FULLCHAIN_PATH" "$_preferred_chain"; then
 | 
| 
 | 
  4787         rels="$(echo "$responseHeaders" | tr -d ' <>' | grep -i "^link:" | grep -i 'rel="alternate"' | cut -d : -f 2- | cut -d ';' -f 1)"
 | 
| 
 | 
  4788         _debug2 "rels" "$rels"
 | 
| 
 | 
  4789         for rel in $rels; do
 | 
| 
 | 
  4790           _info "Try rel: $rel"
 | 
| 
 | 
  4791           if ! _send_signed_request "$rel"; then
 | 
| 
 | 
  4792             _err "Sign failed, can not download cert:$rel"
 | 
| 
 | 
  4793             _err "$response"
 | 
| 
 | 
  4794             continue
 | 
| 
 | 
  4795           fi
 | 
| 
 | 
  4796           _relcert="$CERT_PATH.alt"
 | 
| 
 | 
  4797           _relfullchain="$CERT_FULLCHAIN_PATH.alt"
 | 
| 
 | 
  4798           _relca="$CA_CERT_PATH.alt"
 | 
| 
 | 
  4799           echo "$response" >"$_relcert"
 | 
| 
 | 
  4800           _split_cert_chain "$_relcert" "$_relfullchain" "$_relca"
 | 
| 
 | 
  4801           if _match_issuer "$_relfullchain" "$_preferred_chain"; then
 | 
| 
 | 
  4802             _info "Matched issuer in: $rel"
 | 
| 
 | 
  4803             cat $_relcert >"$CERT_PATH"
 | 
| 
 | 
  4804             cat $_relfullchain >"$CERT_FULLCHAIN_PATH"
 | 
| 
 | 
  4805             cat $_relca >"$CA_CERT_PATH"
 | 
| 
 | 
  4806             break
 | 
| 
 | 
  4807           fi
 | 
| 
 | 
  4808         done
 | 
| 
 | 
  4809       fi
 | 
| 
 | 
  4810     fi
 | 
| 
 | 
  4811   else
 | 
| 
 | 
  4812     if ! _send_signed_request "${ACME_NEW_ORDER}" "{\"resource\": \"$ACME_NEW_ORDER_RES\", \"csr\": \"$der\"}" "needbase64"; then
 | 
| 
 | 
  4813       _err "Sign failed. $response"
 | 
| 
 | 
  4814       _on_issue_err "$_post_hook"
 | 
| 
 | 
  4815       return 1
 | 
| 
 | 
  4816     fi
 | 
| 
 | 
  4817     _rcert="$response"
 | 
| 
 | 
  4818     Le_LinkCert="$(grep -i '^Location.*$' "$HTTP_HEADER" | _tail_n 1 | tr -d "\r\n" | cut -d " " -f 2)"
 | 
| 
 | 
  4819     echo "$BEGIN_CERT" >"$CERT_PATH"
 | 
| 
 | 
  4820 
 | 
| 
 | 
  4821     #if ! _get "$Le_LinkCert" | _base64 "multiline"  >> "$CERT_PATH" ; then
 | 
| 
 | 
  4822     #  _debug "Get cert failed. Let's try last response."
 | 
| 
 | 
  4823     #  printf -- "%s" "$_rcert" | _dbase64 "multiline" | _base64 "multiline" >> "$CERT_PATH"
 | 
| 
 | 
  4824     #fi
 | 
| 
 | 
  4825 
 | 
| 
 | 
  4826     if ! printf -- "%s" "$_rcert" | _dbase64 "multiline" | _base64 "multiline" >>"$CERT_PATH"; then
 | 
| 
 | 
  4827       _debug "Try cert link."
 | 
| 
 | 
  4828       _get "$Le_LinkCert" | _base64 "multiline" >>"$CERT_PATH"
 | 
| 
 | 
  4829     fi
 | 
| 
 | 
  4830 
 | 
| 
 | 
  4831     echo "$END_CERT" >>"$CERT_PATH"
 | 
| 
 | 
  4832   fi
 | 
| 
 | 
  4833 
 | 
| 
 | 
  4834   _debug "Le_LinkCert" "$Le_LinkCert"
 | 
| 
 | 
  4835   _savedomainconf "Le_LinkCert" "$Le_LinkCert"
 | 
| 
 | 
  4836 
 | 
| 
 | 
  4837   if [ -z "$Le_LinkCert" ] || ! _checkcert "$CERT_PATH"; then
 | 
| 
 | 
  4838     response="$(echo "$response" | _dbase64 "multiline" | tr -d '\0' | _normalizeJson)"
 | 
| 
 | 
  4839     _err "Sign failed: $(echo "$response" | _egrep_o '"detail":"[^"]*"')"
 | 
| 
 | 
  4840     _on_issue_err "$_post_hook"
 | 
| 
 | 
  4841     return 1
 | 
| 
 | 
  4842   fi
 | 
| 
 | 
  4843 
 | 
| 
 | 
  4844   if [ "$Le_LinkCert" ]; then
 | 
| 
 | 
  4845     _info "$(__green "Cert success.")"
 | 
| 
 | 
  4846     cat "$CERT_PATH"
 | 
| 
 | 
  4847 
 | 
| 
 | 
  4848     _info "Your cert is in $(__green " $CERT_PATH ")"
 | 
| 
 | 
  4849 
 | 
| 
 | 
  4850     if [ -f "$CERT_KEY_PATH" ]; then
 | 
| 
 | 
  4851       _info "Your cert key is in $(__green " $CERT_KEY_PATH ")"
 | 
| 
 | 
  4852     fi
 | 
| 
 | 
  4853 
 | 
| 
 | 
  4854     if [ ! "$USER_PATH" ] || [ ! "$_ACME_IN_CRON" ]; then
 | 
| 
 | 
  4855       USER_PATH="$PATH"
 | 
| 
 | 
  4856       _saveaccountconf "USER_PATH" "$USER_PATH"
 | 
| 
 | 
  4857     fi
 | 
| 
 | 
  4858   fi
 | 
| 
 | 
  4859 
 | 
| 
 | 
  4860   if [ "$ACME_VERSION" = "2" ]; then
 | 
| 
 | 
  4861     _debug "v2 chain."
 | 
| 
 | 
  4862   else
 | 
| 
 | 
  4863     cp "$CERT_PATH" "$CERT_FULLCHAIN_PATH"
 | 
| 
 | 
  4864     Le_LinkIssuer=$(grep -i '^Link' "$HTTP_HEADER" | _head_n 1 | cut -d " " -f 2 | cut -d ';' -f 1 | tr -d '<>')
 | 
| 
 | 
  4865 
 | 
| 
 | 
  4866     if [ "$Le_LinkIssuer" ]; then
 | 
| 
 | 
  4867       if ! _contains "$Le_LinkIssuer" ":"; then
 | 
| 
 | 
  4868         _info "$(__red "Relative issuer link found.")"
 | 
| 
 | 
  4869         Le_LinkIssuer="$_ACME_SERVER_HOST$Le_LinkIssuer"
 | 
| 
 | 
  4870       fi
 | 
| 
 | 
  4871       _debug Le_LinkIssuer "$Le_LinkIssuer"
 | 
| 
 | 
  4872       _savedomainconf "Le_LinkIssuer" "$Le_LinkIssuer"
 | 
| 
 | 
  4873 
 | 
| 
 | 
  4874       _link_issuer_retry=0
 | 
| 
 | 
  4875       _MAX_ISSUER_RETRY=5
 | 
| 
 | 
  4876       while [ "$_link_issuer_retry" -lt "$_MAX_ISSUER_RETRY" ]; do
 | 
| 
 | 
  4877         _debug _link_issuer_retry "$_link_issuer_retry"
 | 
| 
 | 
  4878         if [ "$ACME_VERSION" = "2" ]; then
 | 
| 
 | 
  4879           if _send_signed_request "$Le_LinkIssuer"; then
 | 
| 
 | 
  4880             echo "$response" >"$CA_CERT_PATH"
 | 
| 
 | 
  4881             break
 | 
| 
 | 
  4882           fi
 | 
| 
 | 
  4883         else
 | 
| 
 | 
  4884           if _get "$Le_LinkIssuer" >"$CA_CERT_PATH.der"; then
 | 
| 
 | 
  4885             echo "$BEGIN_CERT" >"$CA_CERT_PATH"
 | 
| 
 | 
  4886             _base64 "multiline" <"$CA_CERT_PATH.der" >>"$CA_CERT_PATH"
 | 
| 
 | 
  4887             echo "$END_CERT" >>"$CA_CERT_PATH"
 | 
| 
 | 
  4888             if ! _checkcert "$CA_CERT_PATH"; then
 | 
| 
 | 
  4889               _err "Can not get the ca cert."
 | 
| 
 | 
  4890               break
 | 
| 
 | 
  4891             fi
 | 
| 
 | 
  4892             cat "$CA_CERT_PATH" >>"$CERT_FULLCHAIN_PATH"
 | 
| 
 | 
  4893             rm -f "$CA_CERT_PATH.der"
 | 
| 
 | 
  4894             break
 | 
| 
 | 
  4895           fi
 | 
| 
 | 
  4896         fi
 | 
| 
 | 
  4897         _link_issuer_retry=$(_math $_link_issuer_retry + 1)
 | 
| 
 | 
  4898         _sleep "$_link_issuer_retry"
 | 
| 
 | 
  4899       done
 | 
| 
 | 
  4900       if [ "$_link_issuer_retry" = "$_MAX_ISSUER_RETRY" ]; then
 | 
| 
 | 
  4901         _err "Max retry for issuer ca cert is reached."
 | 
| 
 | 
  4902       fi
 | 
| 
 | 
  4903     else
 | 
| 
 | 
  4904       _debug "No Le_LinkIssuer header found."
 | 
| 
 | 
  4905     fi
 | 
| 
 | 
  4906   fi
 | 
| 
 | 
  4907   [ -f "$CA_CERT_PATH" ] && _info "The intermediate CA cert is in $(__green " $CA_CERT_PATH ")"
 | 
| 
 | 
  4908   [ -f "$CERT_FULLCHAIN_PATH" ] && _info "And the full chain certs is there: $(__green " $CERT_FULLCHAIN_PATH ")"
 | 
| 
 | 
  4909 
 | 
| 
 | 
  4910   Le_CertCreateTime=$(_time)
 | 
| 
 | 
  4911   _savedomainconf "Le_CertCreateTime" "$Le_CertCreateTime"
 | 
| 
 | 
  4912 
 | 
| 
 | 
  4913   Le_CertCreateTimeStr=$(date -u)
 | 
| 
 | 
  4914   _savedomainconf "Le_CertCreateTimeStr" "$Le_CertCreateTimeStr"
 | 
| 
 | 
  4915 
 | 
| 
 | 
  4916   if [ -z "$Le_RenewalDays" ] || [ "$Le_RenewalDays" -lt "0" ]; then
 | 
| 
 | 
  4917     Le_RenewalDays="$DEFAULT_RENEW"
 | 
| 
 | 
  4918   else
 | 
| 
 | 
  4919     _savedomainconf "Le_RenewalDays" "$Le_RenewalDays"
 | 
| 
 | 
  4920   fi
 | 
| 
 | 
  4921 
 | 
| 
 | 
  4922   if [ "$CA_BUNDLE" ]; then
 | 
| 
 | 
  4923     _saveaccountconf CA_BUNDLE "$CA_BUNDLE"
 | 
| 
 | 
  4924   else
 | 
| 
 | 
  4925     _clearaccountconf "CA_BUNDLE"
 | 
| 
 | 
  4926   fi
 | 
| 
 | 
  4927 
 | 
| 
 | 
  4928   if [ "$CA_PATH" ]; then
 | 
| 
 | 
  4929     _saveaccountconf CA_PATH "$CA_PATH"
 | 
| 
 | 
  4930   else
 | 
| 
 | 
  4931     _clearaccountconf "CA_PATH"
 | 
| 
 | 
  4932   fi
 | 
| 
 | 
  4933 
 | 
| 
 | 
  4934   if [ "$HTTPS_INSECURE" ]; then
 | 
| 
 | 
  4935     _saveaccountconf HTTPS_INSECURE "$HTTPS_INSECURE"
 | 
| 
 | 
  4936   else
 | 
| 
 | 
  4937     _clearaccountconf "HTTPS_INSECURE"
 | 
| 
 | 
  4938   fi
 | 
| 
 | 
  4939 
 | 
| 
 | 
  4940   if [ "$Le_Listen_V4" ]; then
 | 
| 
 | 
  4941     _savedomainconf "Le_Listen_V4" "$Le_Listen_V4"
 | 
| 
 | 
  4942     _cleardomainconf Le_Listen_V6
 | 
| 
 | 
  4943   elif [ "$Le_Listen_V6" ]; then
 | 
| 
 | 
  4944     _savedomainconf "Le_Listen_V6" "$Le_Listen_V6"
 | 
| 
 | 
  4945     _cleardomainconf Le_Listen_V4
 | 
| 
 | 
  4946   fi
 | 
| 
 | 
  4947 
 | 
| 
 | 
  4948   if [ "$Le_ForceNewDomainKey" = "1" ]; then
 | 
| 
 | 
  4949     _savedomainconf "Le_ForceNewDomainKey" "$Le_ForceNewDomainKey"
 | 
| 
 | 
  4950   else
 | 
| 
 | 
  4951     _cleardomainconf Le_ForceNewDomainKey
 | 
| 
 | 
  4952   fi
 | 
| 
 | 
  4953 
 | 
| 
 | 
  4954   Le_NextRenewTime=$(_math "$Le_CertCreateTime" + "$Le_RenewalDays" \* 24 \* 60 \* 60)
 | 
| 
 | 
  4955 
 | 
| 
 | 
  4956   Le_NextRenewTimeStr=$(_time2str "$Le_NextRenewTime")
 | 
| 
 | 
  4957   _savedomainconf "Le_NextRenewTimeStr" "$Le_NextRenewTimeStr"
 | 
| 
 | 
  4958 
 | 
| 
 | 
  4959   Le_NextRenewTime=$(_math "$Le_NextRenewTime" - 86400)
 | 
| 
 | 
  4960   _savedomainconf "Le_NextRenewTime" "$Le_NextRenewTime"
 | 
| 
 | 
  4961 
 | 
| 
 | 
  4962   if [ "$_real_cert$_real_key$_real_ca$_reload_cmd$_real_fullchain" ]; then
 | 
| 
 | 
  4963     _savedomainconf "Le_RealCertPath" "$_real_cert"
 | 
| 
 | 
  4964     _savedomainconf "Le_RealCACertPath" "$_real_ca"
 | 
| 
 | 
  4965     _savedomainconf "Le_RealKeyPath" "$_real_key"
 | 
| 
 | 
  4966     _savedomainconf "Le_ReloadCmd" "$_reload_cmd" "base64"
 | 
| 
 | 
  4967     _savedomainconf "Le_RealFullChainPath" "$_real_fullchain"
 | 
| 
 | 
  4968     if ! _installcert "$_main_domain" "$_real_cert" "$_real_key" "$_real_ca" "$_real_fullchain" "$_reload_cmd"; then
 | 
| 
 | 
  4969       return 1
 | 
| 
 | 
  4970     fi
 | 
| 
 | 
  4971   fi
 | 
| 
 | 
  4972 
 | 
| 
 | 
  4973   if ! _on_issue_success "$_post_hook" "$_renew_hook"; then
 | 
| 
 | 
  4974     _err "Call hook error."
 | 
| 
 | 
  4975     return 1
 | 
| 
 | 
  4976   fi
 | 
| 
 | 
  4977 }
 | 
| 
 | 
  4978 
 | 
| 
 | 
  4979 #in_out_cert   out_fullchain   out_ca
 | 
| 
 | 
  4980 _split_cert_chain() {
 | 
| 
 | 
  4981   _certf="$1"
 | 
| 
 | 
  4982   _fullchainf="$2"
 | 
| 
 | 
  4983   _caf="$3"
 | 
| 
 | 
  4984   if [ "$(grep -- "$BEGIN_CERT" "$_certf" | wc -l)" -gt "1" ]; then
 | 
| 
 | 
  4985     _debug "Found cert chain"
 | 
| 
 | 
  4986     cat "$_certf" >"$_fullchainf"
 | 
| 
 | 
  4987     _end_n="$(grep -n -- "$END_CERT" "$_fullchainf" | _head_n 1 | cut -d : -f 1)"
 | 
| 
 | 
  4988     _debug _end_n "$_end_n"
 | 
| 
 | 
  4989     sed -n "1,${_end_n}p" "$_fullchainf" >"$_certf"
 | 
| 
 | 
  4990     _end_n="$(_math $_end_n + 1)"
 | 
| 
 | 
  4991     sed -n "${_end_n},9999p" "$_fullchainf" >"$_caf"
 | 
| 
 | 
  4992   fi
 | 
| 
 | 
  4993 }
 | 
| 
 | 
  4994 
 | 
| 
 | 
  4995 #domain  [isEcc]
 | 
| 
 | 
  4996 renew() {
 | 
| 
 | 
  4997   Le_Domain="$1"
 | 
| 
 | 
  4998   if [ -z "$Le_Domain" ]; then
 | 
| 
 | 
  4999     _usage "Usage: $PROJECT_ENTRY --renew --domain <domain.tld> [--ecc]"
 | 
| 
 | 
  5000     return 1
 | 
| 
 | 
  5001   fi
 | 
| 
 | 
  5002 
 | 
| 
 | 
  5003   _isEcc="$2"
 | 
| 
 | 
  5004 
 | 
| 
 | 
  5005   _initpath "$Le_Domain" "$_isEcc"
 | 
| 
 | 
  5006 
 | 
| 
 | 
  5007   _info "$(__green "Renew: '$Le_Domain'")"
 | 
| 
 | 
  5008   if [ ! -f "$DOMAIN_CONF" ]; then
 | 
| 
 | 
  5009     _info "'$Le_Domain' is not an issued domain, skip."
 | 
| 
 | 
  5010     return $RENEW_SKIP
 | 
| 
 | 
  5011   fi
 | 
| 
 | 
  5012 
 | 
| 
 | 
  5013   if [ "$Le_RenewalDays" ]; then
 | 
| 
 | 
  5014     _savedomainconf Le_RenewalDays "$Le_RenewalDays"
 | 
| 
 | 
  5015   fi
 | 
| 
 | 
  5016 
 | 
| 
 | 
  5017   . "$DOMAIN_CONF"
 | 
| 
 | 
  5018   _debug Le_API "$Le_API"
 | 
| 
 | 
  5019 
 | 
| 
 | 
  5020   if [ "$Le_API" = "$LETSENCRYPT_CA_V1" ]; then
 | 
| 
 | 
  5021     _cleardomainconf Le_API
 | 
| 
 | 
  5022     Le_API="$DEFAULT_CA"
 | 
| 
 | 
  5023   fi
 | 
| 
 | 
  5024   if [ "$Le_API" = "$LETSENCRYPT_STAGING_CA_V1" ]; then
 | 
| 
 | 
  5025     _cleardomainconf Le_API
 | 
| 
 | 
  5026     Le_API="$DEFAULT_STAGING_CA"
 | 
| 
 | 
  5027   fi
 | 
| 
 | 
  5028 
 | 
| 
 | 
  5029   if [ "$Le_API" ]; then
 | 
| 
 | 
  5030     export ACME_DIRECTORY="$Le_API"
 | 
| 
 | 
  5031     #reload ca configs
 | 
| 
 | 
  5032     ACCOUNT_KEY_PATH=""
 | 
| 
 | 
  5033     ACCOUNT_JSON_PATH=""
 | 
| 
 | 
  5034     CA_CONF=""
 | 
| 
 | 
  5035     _debug3 "initpath again."
 | 
| 
 | 
  5036     _initpath "$Le_Domain" "$_isEcc"
 | 
| 
 | 
  5037   fi
 | 
| 
 | 
  5038 
 | 
| 
 | 
  5039   if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(_time)" -lt "$Le_NextRenewTime" ]; then
 | 
| 
 | 
  5040     _info "Skip, Next renewal time is: $(__green "$Le_NextRenewTimeStr")"
 | 
| 
 | 
  5041     _info "Add '$(__red '--force')' to force to renew."
 | 
| 
 | 
  5042     return "$RENEW_SKIP"
 | 
| 
 | 
  5043   fi
 | 
| 
 | 
  5044 
 | 
| 
 | 
  5045   if [ "$_ACME_IN_CRON" = "1" ] && [ -z "$Le_CertCreateTime" ]; then
 | 
| 
 | 
  5046     _info "Skip invalid cert for: $Le_Domain"
 | 
| 
 | 
  5047     return $RENEW_SKIP
 | 
| 
 | 
  5048   fi
 | 
| 
 | 
  5049 
 | 
| 
 | 
  5050   _ACME_IS_RENEW="1"
 | 
| 
 | 
  5051   Le_ReloadCmd="$(_readdomainconf Le_ReloadCmd)"
 | 
| 
 | 
  5052   Le_PreHook="$(_readdomainconf Le_PreHook)"
 | 
| 
 | 
  5053   Le_PostHook="$(_readdomainconf Le_PostHook)"
 | 
| 
 | 
  5054   Le_RenewHook="$(_readdomainconf Le_RenewHook)"
 | 
| 
 | 
  5055   Le_Preferred_Chain="$(_readdomainconf Le_Preferred_Chain)"
 | 
| 
 | 
  5056   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" "$Le_Preferred_Chain"
 | 
| 
 | 
  5057   res="$?"
 | 
| 
 | 
  5058   if [ "$res" != "0" ]; then
 | 
| 
 | 
  5059     return "$res"
 | 
| 
 | 
  5060   fi
 | 
| 
 | 
  5061 
 | 
| 
 | 
  5062   if [ "$Le_DeployHook" ]; then
 | 
| 
 | 
  5063     _deploy "$Le_Domain" "$Le_DeployHook"
 | 
| 
 | 
  5064     res="$?"
 | 
| 
 | 
  5065   fi
 | 
| 
 | 
  5066 
 | 
| 
 | 
  5067   _ACME_IS_RENEW=""
 | 
| 
 | 
  5068 
 | 
| 
 | 
  5069   return "$res"
 | 
| 
 | 
  5070 }
 | 
| 
 | 
  5071 
 | 
| 
 | 
  5072 #renewAll  [stopRenewOnError]
 | 
| 
 | 
  5073 renewAll() {
 | 
| 
 | 
  5074   _initpath
 | 
| 
 | 
  5075   _stopRenewOnError="$1"
 | 
| 
 | 
  5076   _debug "_stopRenewOnError" "$_stopRenewOnError"
 | 
| 
 | 
  5077   _ret="0"
 | 
| 
 | 
  5078   _success_msg=""
 | 
| 
 | 
  5079   _error_msg=""
 | 
| 
 | 
  5080   _skipped_msg=""
 | 
| 
 | 
  5081   _error_level=$NOTIFY_LEVEL_SKIP
 | 
| 
 | 
  5082   _notify_code=$RENEW_SKIP
 | 
| 
 | 
  5083   _set_level=${NOTIFY_LEVEL:-$NOTIFY_LEVEL_DEFAULT}
 | 
| 
 | 
  5084   _debug "_set_level" "$_set_level"
 | 
| 
 | 
  5085   for di in "${CERT_HOME}"/*.*/; do
 | 
| 
 | 
  5086     _debug di "$di"
 | 
| 
 | 
  5087     if ! [ -d "$di" ]; then
 | 
| 
 | 
  5088       _debug "Not a directory, skip: $di"
 | 
| 
 | 
  5089       continue
 | 
| 
 | 
  5090     fi
 | 
| 
 | 
  5091     d=$(basename "$di")
 | 
| 
 | 
  5092     _debug d "$d"
 | 
| 
 | 
  5093     (
 | 
| 
 | 
  5094       if _endswith "$d" "$ECC_SUFFIX"; then
 | 
| 
 | 
  5095         _isEcc=$(echo "$d" | cut -d "$ECC_SEP" -f 2)
 | 
| 
 | 
  5096         d=$(echo "$d" | cut -d "$ECC_SEP" -f 1)
 | 
| 
 | 
  5097       fi
 | 
| 
 | 
  5098       renew "$d" "$_isEcc"
 | 
| 
 | 
  5099     )
 | 
| 
 | 
  5100     rc="$?"
 | 
| 
 | 
  5101     _debug "Return code: $rc"
 | 
| 
 | 
  5102     if [ "$rc" = "0" ]; then
 | 
| 
 | 
  5103       if [ $_error_level -gt $NOTIFY_LEVEL_RENEW ]; then
 | 
| 
 | 
  5104         _error_level="$NOTIFY_LEVEL_RENEW"
 | 
| 
 | 
  5105         _notify_code=0
 | 
| 
 | 
  5106       fi
 | 
| 
 | 
  5107       if [ "$_ACME_IN_CRON" ]; then
 | 
| 
 | 
  5108         if [ $_set_level -ge $NOTIFY_LEVEL_RENEW ]; then
 | 
| 
 | 
  5109           if [ "$NOTIFY_MODE" = "$NOTIFY_MODE_CERT" ]; then
 | 
| 
 | 
  5110             _send_notify "Renew $d success" "Good, the cert is renewed." "$NOTIFY_HOOK" 0
 | 
| 
 | 
  5111           fi
 | 
| 
 | 
  5112         fi
 | 
| 
 | 
  5113       fi
 | 
| 
 | 
  5114       _success_msg="${_success_msg}    $d
 | 
| 
 | 
  5115 "
 | 
| 
 | 
  5116     elif [ "$rc" = "$RENEW_SKIP" ]; then
 | 
| 
 | 
  5117       if [ $_error_level -gt $NOTIFY_LEVEL_SKIP ]; then
 | 
| 
 | 
  5118         _error_level="$NOTIFY_LEVEL_SKIP"
 | 
| 
 | 
  5119         _notify_code=$RENEW_SKIP
 | 
| 
 | 
  5120       fi
 | 
| 
 | 
  5121       if [ "$_ACME_IN_CRON" ]; then
 | 
| 
 | 
  5122         if [ $_set_level -ge $NOTIFY_LEVEL_SKIP ]; then
 | 
| 
 | 
  5123           if [ "$NOTIFY_MODE" = "$NOTIFY_MODE_CERT" ]; then
 | 
| 
 | 
  5124             _send_notify "Renew $d skipped" "Good, the cert is skipped." "$NOTIFY_HOOK" "$RENEW_SKIP"
 | 
| 
 | 
  5125           fi
 | 
| 
 | 
  5126         fi
 | 
| 
 | 
  5127       fi
 | 
| 
 | 
  5128       _info "Skipped $d"
 | 
| 
 | 
  5129       _skipped_msg="${_skipped_msg}    $d
 | 
| 
 | 
  5130 "
 | 
| 
 | 
  5131     else
 | 
| 
 | 
  5132       if [ $_error_level -gt $NOTIFY_LEVEL_ERROR ]; then
 | 
| 
 | 
  5133         _error_level="$NOTIFY_LEVEL_ERROR"
 | 
| 
 | 
  5134         _notify_code=1
 | 
| 
 | 
  5135       fi
 | 
| 
 | 
  5136       if [ "$_ACME_IN_CRON" ]; then
 | 
| 
 | 
  5137         if [ $_set_level -ge $NOTIFY_LEVEL_ERROR ]; then
 | 
| 
 | 
  5138           if [ "$NOTIFY_MODE" = "$NOTIFY_MODE_CERT" ]; then
 | 
| 
 | 
  5139             _send_notify "Renew $d error" "There is an error." "$NOTIFY_HOOK" 1
 | 
| 
 | 
  5140           fi
 | 
| 
 | 
  5141         fi
 | 
| 
 | 
  5142       fi
 | 
| 
 | 
  5143       _error_msg="${_error_msg}    $d
 | 
| 
 | 
  5144 "
 | 
| 
 | 
  5145       if [ "$_stopRenewOnError" ]; then
 | 
| 
 | 
  5146         _err "Error renew $d,  stop now."
 | 
| 
 | 
  5147         _ret="$rc"
 | 
| 
 | 
  5148         break
 | 
| 
 | 
  5149       else
 | 
| 
 | 
  5150         _ret="$rc"
 | 
| 
 | 
  5151         _err "Error renew $d."
 | 
| 
 | 
  5152       fi
 | 
| 
 | 
  5153     fi
 | 
| 
 | 
  5154   done
 | 
| 
 | 
  5155   _debug _error_level "$_error_level"
 | 
| 
 | 
  5156   _debug _set_level "$_set_level"
 | 
| 
 | 
  5157   if [ "$_ACME_IN_CRON" ] && [ $_error_level -le $_set_level ]; then
 | 
| 
 | 
  5158     if [ -z "$NOTIFY_MODE" ] || [ "$NOTIFY_MODE" = "$NOTIFY_MODE_BULK" ]; then
 | 
| 
 | 
  5159       _msg_subject="Renew"
 | 
| 
 | 
  5160       if [ "$_error_msg" ]; then
 | 
| 
 | 
  5161         _msg_subject="${_msg_subject} Error"
 | 
| 
 | 
  5162         _msg_data="Error certs:
 | 
| 
 | 
  5163 ${_error_msg}
 | 
| 
 | 
  5164 "
 | 
| 
 | 
  5165       fi
 | 
| 
 | 
  5166       if [ "$_success_msg" ]; then
 | 
| 
 | 
  5167         _msg_subject="${_msg_subject} Success"
 | 
| 
 | 
  5168         _msg_data="${_msg_data}Success certs:
 | 
| 
 | 
  5169 ${_success_msg}
 | 
| 
 | 
  5170 "
 | 
| 
 | 
  5171       fi
 | 
| 
 | 
  5172       if [ "$_skipped_msg" ]; then
 | 
| 
 | 
  5173         _msg_subject="${_msg_subject} Skipped"
 | 
| 
 | 
  5174         _msg_data="${_msg_data}Skipped certs:
 | 
| 
 | 
  5175 ${_skipped_msg}
 | 
| 
 | 
  5176 "
 | 
| 
 | 
  5177       fi
 | 
| 
 | 
  5178 
 | 
| 
 | 
  5179       _send_notify "$_msg_subject" "$_msg_data" "$NOTIFY_HOOK" "$_notify_code"
 | 
| 
 | 
  5180     fi
 | 
| 
 | 
  5181   fi
 | 
| 
 | 
  5182 
 | 
| 
 | 
  5183   return "$_ret"
 | 
| 
 | 
  5184 }
 | 
| 
 | 
  5185 
 | 
| 
 | 
  5186 #csr webroot
 | 
| 
 | 
  5187 signcsr() {
 | 
| 
 | 
  5188   _csrfile="$1"
 | 
| 
 | 
  5189   _csrW="$2"
 | 
| 
 | 
  5190   if [ -z "$_csrfile" ] || [ -z "$_csrW" ]; then
 | 
| 
 | 
  5191     _usage "Usage: $PROJECT_ENTRY --sign-csr --csr <csr-file> --webroot <directory>"
 | 
| 
 | 
  5192     return 1
 | 
| 
 | 
  5193   fi
 | 
| 
 | 
  5194 
 | 
| 
 | 
  5195   _real_cert="$3"
 | 
| 
 | 
  5196   _real_key="$4"
 | 
| 
 | 
  5197   _real_ca="$5"
 | 
| 
 | 
  5198   _reload_cmd="$6"
 | 
| 
 | 
  5199   _real_fullchain="$7"
 | 
| 
 | 
  5200   _pre_hook="${8}"
 | 
| 
 | 
  5201   _post_hook="${9}"
 | 
| 
 | 
  5202   _renew_hook="${10}"
 | 
| 
 | 
  5203   _local_addr="${11}"
 | 
| 
 | 
  5204   _challenge_alias="${12}"
 | 
| 
 | 
  5205 
 | 
| 
 | 
  5206   _csrsubj=$(_readSubjectFromCSR "$_csrfile")
 | 
| 
 | 
  5207   if [ "$?" != "0" ]; then
 | 
| 
 | 
  5208     _err "Can not read subject from csr: $_csrfile"
 | 
| 
 | 
  5209     return 1
 | 
| 
 | 
  5210   fi
 | 
| 
 | 
  5211   _debug _csrsubj "$_csrsubj"
 | 
| 
 | 
  5212   if _contains "$_csrsubj" ' ' || ! _contains "$_csrsubj" '.'; then
 | 
| 
 | 
  5213     _info "It seems that the subject: $_csrsubj is not a valid domain name. Drop it."
 | 
| 
 | 
  5214     _csrsubj=""
 | 
| 
 | 
  5215   fi
 | 
| 
 | 
  5216 
 | 
| 
 | 
  5217   _csrdomainlist=$(_readSubjectAltNamesFromCSR "$_csrfile")
 | 
| 
 | 
  5218   if [ "$?" != "0" ]; then
 | 
| 
 | 
  5219     _err "Can not read domain list from csr: $_csrfile"
 | 
| 
 | 
  5220     return 1
 | 
| 
 | 
  5221   fi
 | 
| 
 | 
  5222   _debug "_csrdomainlist" "$_csrdomainlist"
 | 
| 
 | 
  5223 
 | 
| 
 | 
  5224   if [ -z "$_csrsubj" ]; then
 | 
| 
 | 
  5225     _csrsubj="$(_getfield "$_csrdomainlist" 1)"
 | 
| 
 | 
  5226     _debug _csrsubj "$_csrsubj"
 | 
| 
 | 
  5227     _csrdomainlist="$(echo "$_csrdomainlist" | cut -d , -f 2-)"
 | 
| 
 | 
  5228     _debug "_csrdomainlist" "$_csrdomainlist"
 | 
| 
 | 
  5229   fi
 | 
| 
 | 
  5230 
 | 
| 
 | 
  5231   if [ -z "$_csrsubj" ]; then
 | 
| 
 | 
  5232     _err "Can not read subject from csr: $_csrfile"
 | 
| 
 | 
  5233     return 1
 | 
| 
 | 
  5234   fi
 | 
| 
 | 
  5235 
 | 
| 
 | 
  5236   _csrkeylength=$(_readKeyLengthFromCSR "$_csrfile")
 | 
| 
 | 
  5237   if [ "$?" != "0" ] || [ -z "$_csrkeylength" ]; then
 | 
| 
 | 
  5238     _err "Can not read key length from csr: $_csrfile"
 | 
| 
 | 
  5239     return 1
 | 
| 
 | 
  5240   fi
 | 
| 
 | 
  5241 
 | 
| 
 | 
  5242   if [ -z "$ACME_VERSION" ] && _contains "$_csrsubj,$_csrdomainlist" "*."; then
 | 
| 
 | 
  5243     export ACME_VERSION=2
 | 
| 
 | 
  5244   fi
 | 
| 
 | 
  5245   _initpath "$_csrsubj" "$_csrkeylength"
 | 
| 
 | 
  5246   mkdir -p "$DOMAIN_PATH"
 | 
| 
 | 
  5247 
 | 
| 
 | 
  5248   _info "Copy csr to: $CSR_PATH"
 | 
| 
 | 
  5249   cp "$_csrfile" "$CSR_PATH"
 | 
| 
 | 
  5250 
 | 
| 
 | 
  5251   issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_addr" "$_challenge_alias"
 | 
| 
 | 
  5252 
 | 
| 
 | 
  5253 }
 | 
| 
 | 
  5254 
 | 
| 
 | 
  5255 showcsr() {
 | 
| 
 | 
  5256   _csrfile="$1"
 | 
| 
 | 
  5257   _csrd="$2"
 | 
| 
 | 
  5258   if [ -z "$_csrfile" ] && [ -z "$_csrd" ]; then
 | 
| 
 | 
  5259     _usage "Usage: $PROJECT_ENTRY --show-csr --csr <csr-file>"
 | 
| 
 | 
  5260     return 1
 | 
| 
 | 
  5261   fi
 | 
| 
 | 
  5262 
 | 
| 
 | 
  5263   _initpath
 | 
| 
 | 
  5264 
 | 
| 
 | 
  5265   _csrsubj=$(_readSubjectFromCSR "$_csrfile")
 | 
| 
 | 
  5266   if [ "$?" != "0" ] || [ -z "$_csrsubj" ]; then
 | 
| 
 | 
  5267     _err "Can not read subject from csr: $_csrfile"
 | 
| 
 | 
  5268     return 1
 | 
| 
 | 
  5269   fi
 | 
| 
 | 
  5270 
 | 
| 
 | 
  5271   _info "Subject=$_csrsubj"
 | 
| 
 | 
  5272 
 | 
| 
 | 
  5273   _csrdomainlist=$(_readSubjectAltNamesFromCSR "$_csrfile")
 | 
| 
 | 
  5274   if [ "$?" != "0" ]; then
 | 
| 
 | 
  5275     _err "Can not read domain list from csr: $_csrfile"
 | 
| 
 | 
  5276     return 1
 | 
| 
 | 
  5277   fi
 | 
| 
 | 
  5278   _debug "_csrdomainlist" "$_csrdomainlist"
 | 
| 
 | 
  5279 
 | 
| 
 | 
  5280   _info "SubjectAltNames=$_csrdomainlist"
 | 
| 
 | 
  5281 
 | 
| 
 | 
  5282   _csrkeylength=$(_readKeyLengthFromCSR "$_csrfile")
 | 
| 
 | 
  5283   if [ "$?" != "0" ] || [ -z "$_csrkeylength" ]; then
 | 
| 
 | 
  5284     _err "Can not read key length from csr: $_csrfile"
 | 
| 
 | 
  5285     return 1
 | 
| 
 | 
  5286   fi
 | 
| 
 | 
  5287   _info "KeyLength=$_csrkeylength"
 | 
| 
 | 
  5288 }
 | 
| 
 | 
  5289 
 | 
| 
 | 
  5290 #listraw  domain
 | 
| 
 | 
  5291 list() {
 | 
| 
 | 
  5292   _raw="$1"
 | 
| 
 | 
  5293   _domain="$2"
 | 
| 
 | 
  5294   _initpath
 | 
| 
 | 
  5295 
 | 
| 
 | 
  5296   _sep="|"
 | 
| 
 | 
  5297   if [ "$_raw" ]; then
 | 
| 
 | 
  5298     if [ -z "$_domain" ]; then
 | 
| 
 | 
  5299       printf "%s\n" "Main_Domain${_sep}KeyLength${_sep}SAN_Domains${_sep}CA${_sep}Created${_sep}Renew"
 | 
| 
 | 
  5300     fi
 | 
| 
 | 
  5301     for di in "${CERT_HOME}"/*.*/; do
 | 
| 
 | 
  5302       d=$(basename "$di")
 | 
| 
 | 
  5303       _debug d "$d"
 | 
| 
 | 
  5304       (
 | 
| 
 | 
  5305         if _endswith "$d" "$ECC_SUFFIX"; then
 | 
| 
 | 
  5306           _isEcc="ecc"
 | 
| 
 | 
  5307           d=$(echo "$d" | cut -d "$ECC_SEP" -f 1)
 | 
| 
 | 
  5308         fi
 | 
| 
 | 
  5309         DOMAIN_CONF="$di/$d.conf"
 | 
| 
 | 
  5310         if [ -f "$DOMAIN_CONF" ]; then
 | 
| 
 | 
  5311           . "$DOMAIN_CONF"
 | 
| 
 | 
  5312           _ca="$(_getCAShortName "$Le_API")"
 | 
| 
 | 
  5313           if [ -z "$_domain" ]; then
 | 
| 
 | 
  5314             printf "%s\n" "$Le_Domain${_sep}\"$Le_Keylength\"${_sep}$Le_Alt${_sep}$_ca${_sep}$Le_CertCreateTimeStr${_sep}$Le_NextRenewTimeStr"
 | 
| 
 | 
  5315           else
 | 
| 
 | 
  5316             if [ "$_domain" = "$d" ]; then
 | 
| 
 | 
  5317               cat "$DOMAIN_CONF"
 | 
| 
 | 
  5318             fi
 | 
| 
 | 
  5319           fi
 | 
| 
 | 
  5320         fi
 | 
| 
 | 
  5321       )
 | 
| 
 | 
  5322     done
 | 
| 
 | 
  5323   else
 | 
| 
 | 
  5324     if _exists column; then
 | 
| 
 | 
  5325       list "raw" "$_domain" | column -t -s "$_sep"
 | 
| 
 | 
  5326     else
 | 
| 
 | 
  5327       list "raw" "$_domain" | tr "$_sep" '\t'
 | 
| 
 | 
  5328     fi
 | 
| 
 | 
  5329   fi
 | 
| 
 | 
  5330 
 | 
| 
 | 
  5331 }
 | 
| 
 | 
  5332 
 | 
| 
 | 
  5333 _deploy() {
 | 
| 
 | 
  5334   _d="$1"
 | 
| 
 | 
  5335   _hooks="$2"
 | 
| 
 | 
  5336 
 | 
| 
 | 
  5337   for _d_api in $(echo "$_hooks" | tr ',' " "); do
 | 
| 
 | 
  5338     _deployApi="$(_findHook "$_d" $_SUB_FOLDER_DEPLOY "$_d_api")"
 | 
| 
 | 
  5339     if [ -z "$_deployApi" ]; then
 | 
| 
 | 
  5340       _err "The deploy hook $_d_api is not found."
 | 
| 
 | 
  5341       return 1
 | 
| 
 | 
  5342     fi
 | 
| 
 | 
  5343     _debug _deployApi "$_deployApi"
 | 
| 
 | 
  5344 
 | 
| 
 | 
  5345     if ! (
 | 
| 
 | 
  5346       if ! . "$_deployApi"; then
 | 
| 
 | 
  5347         _err "Load file $_deployApi error. Please check your api file and try again."
 | 
| 
 | 
  5348         return 1
 | 
| 
 | 
  5349       fi
 | 
| 
 | 
  5350 
 | 
| 
 | 
  5351       d_command="${_d_api}_deploy"
 | 
| 
 | 
  5352       if ! _exists "$d_command"; then
 | 
| 
 | 
  5353         _err "It seems that your api file is not correct, it must have a function named: $d_command"
 | 
| 
 | 
  5354         return 1
 | 
| 
 | 
  5355       fi
 | 
| 
 | 
  5356 
 | 
| 
 | 
  5357       if ! $d_command "$_d" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$CERT_FULLCHAIN_PATH"; then
 | 
| 
 | 
  5358         _err "Error deploy for domain:$_d"
 | 
| 
 | 
  5359         return 1
 | 
| 
 | 
  5360       fi
 | 
| 
 | 
  5361     ); then
 | 
| 
 | 
  5362       _err "Deploy error."
 | 
| 
 | 
  5363       return 1
 | 
| 
 | 
  5364     else
 | 
| 
 | 
  5365       _info "$(__green Success)"
 | 
| 
 | 
  5366     fi
 | 
| 
 | 
  5367   done
 | 
| 
 | 
  5368 }
 | 
| 
 | 
  5369 
 | 
| 
 | 
  5370 #domain hooks
 | 
| 
 | 
  5371 deploy() {
 | 
| 
 | 
  5372   _d="$1"
 | 
| 
 | 
  5373   _hooks="$2"
 | 
| 
 | 
  5374   _isEcc="$3"
 | 
| 
 | 
  5375   if [ -z "$_hooks" ]; then
 | 
| 
 | 
  5376     _usage "Usage: $PROJECT_ENTRY --deploy --domain <domain.tld> --deploy-hook <hookname> [--ecc] "
 | 
| 
 | 
  5377     return 1
 | 
| 
 | 
  5378   fi
 | 
| 
 | 
  5379 
 | 
| 
 | 
  5380   _initpath "$_d" "$_isEcc"
 | 
| 
 | 
  5381   if [ ! -d "$DOMAIN_PATH" ]; then
 | 
| 
 | 
  5382     _err "The domain '$_d' is not a cert name. You must use the cert name to specify the cert to install."
 | 
| 
 | 
  5383     _err "Can not find path:'$DOMAIN_PATH'"
 | 
| 
 | 
  5384     return 1
 | 
| 
 | 
  5385   fi
 | 
| 
 | 
  5386 
 | 
| 
 | 
  5387   . "$DOMAIN_CONF"
 | 
| 
 | 
  5388 
 | 
| 
 | 
  5389   _savedomainconf Le_DeployHook "$_hooks"
 | 
| 
 | 
  5390 
 | 
| 
 | 
  5391   _deploy "$_d" "$_hooks"
 | 
| 
 | 
  5392 }
 | 
| 
 | 
  5393 
 | 
| 
 | 
  5394 installcert() {
 | 
| 
 | 
  5395   _main_domain="$1"
 | 
| 
 | 
  5396   if [ -z "$_main_domain" ]; then
 | 
| 
 | 
  5397     _usage "Usage: $PROJECT_ENTRY --install-cert --domain <domain.tld> [--ecc] [--cert-file <file>] [--key-file <file>] [--ca-file <file>] [ --reloadcmd <command>] [--fullchain-file <file>]"
 | 
| 
 | 
  5398     return 1
 | 
| 
 | 
  5399   fi
 | 
| 
 | 
  5400 
 | 
| 
 | 
  5401   _real_cert="$2"
 | 
| 
 | 
  5402   _real_key="$3"
 | 
| 
 | 
  5403   _real_ca="$4"
 | 
| 
 | 
  5404   _reload_cmd="$5"
 | 
| 
 | 
  5405   _real_fullchain="$6"
 | 
| 
 | 
  5406   _isEcc="$7"
 | 
| 
 | 
  5407 
 | 
| 
 | 
  5408   _initpath "$_main_domain" "$_isEcc"
 | 
| 
 | 
  5409   if [ ! -d "$DOMAIN_PATH" ]; then
 | 
| 
 | 
  5410     _err "The domain '$_main_domain' is not a cert name. You must use the cert name to specify the cert to install."
 | 
| 
 | 
  5411     _err "Can not find path:'$DOMAIN_PATH'"
 | 
| 
 | 
  5412     return 1
 | 
| 
 | 
  5413   fi
 | 
| 
 | 
  5414 
 | 
| 
 | 
  5415   _savedomainconf "Le_RealCertPath" "$_real_cert"
 | 
| 
 | 
  5416   _savedomainconf "Le_RealCACertPath" "$_real_ca"
 | 
| 
 | 
  5417   _savedomainconf "Le_RealKeyPath" "$_real_key"
 | 
| 
 | 
  5418   _savedomainconf "Le_ReloadCmd" "$_reload_cmd" "base64"
 | 
| 
 | 
  5419   _savedomainconf "Le_RealFullChainPath" "$_real_fullchain"
 | 
| 
 | 
  5420 
 | 
| 
 | 
  5421   _installcert "$_main_domain" "$_real_cert" "$_real_key" "$_real_ca" "$_real_fullchain" "$_reload_cmd"
 | 
| 
 | 
  5422 }
 | 
| 
 | 
  5423 
 | 
| 
 | 
  5424 #domain  cert  key  ca  fullchain reloadcmd backup-prefix
 | 
| 
 | 
  5425 _installcert() {
 | 
| 
 | 
  5426   _main_domain="$1"
 | 
| 
 | 
  5427   _real_cert="$2"
 | 
| 
 | 
  5428   _real_key="$3"
 | 
| 
 | 
  5429   _real_ca="$4"
 | 
| 
 | 
  5430   _real_fullchain="$5"
 | 
| 
 | 
  5431   _reload_cmd="$6"
 | 
| 
 | 
  5432   _backup_prefix="$7"
 | 
| 
 | 
  5433 
 | 
| 
 | 
  5434   if [ "$_real_cert" = "$NO_VALUE" ]; then
 | 
| 
 | 
  5435     _real_cert=""
 | 
| 
 | 
  5436   fi
 | 
| 
 | 
  5437   if [ "$_real_key" = "$NO_VALUE" ]; then
 | 
| 
 | 
  5438     _real_key=""
 | 
| 
 | 
  5439   fi
 | 
| 
 | 
  5440   if [ "$_real_ca" = "$NO_VALUE" ]; then
 | 
| 
 | 
  5441     _real_ca=""
 | 
| 
 | 
  5442   fi
 | 
| 
 | 
  5443   if [ "$_reload_cmd" = "$NO_VALUE" ]; then
 | 
| 
 | 
  5444     _reload_cmd=""
 | 
| 
 | 
  5445   fi
 | 
| 
 | 
  5446   if [ "$_real_fullchain" = "$NO_VALUE" ]; then
 | 
| 
 | 
  5447     _real_fullchain=""
 | 
| 
 | 
  5448   fi
 | 
| 
 | 
  5449 
 | 
| 
 | 
  5450   _backup_path="$DOMAIN_BACKUP_PATH/$_backup_prefix"
 | 
| 
 | 
  5451   mkdir -p "$_backup_path"
 | 
| 
 | 
  5452 
 | 
| 
 | 
  5453   if [ "$_real_cert" ]; then
 | 
| 
 | 
  5454     _info "Installing cert to:$_real_cert"
 | 
| 
 | 
  5455     if [ -f "$_real_cert" ] && [ ! "$_ACME_IS_RENEW" ]; then
 | 
| 
 | 
  5456       cp "$_real_cert" "$_backup_path/cert.bak"
 | 
| 
 | 
  5457     fi
 | 
| 
 | 
  5458     cat "$CERT_PATH" >"$_real_cert" || return 1
 | 
| 
 | 
  5459   fi
 | 
| 
 | 
  5460 
 | 
| 
 | 
  5461   if [ "$_real_ca" ]; then
 | 
| 
 | 
  5462     _info "Installing CA to:$_real_ca"
 | 
| 
 | 
  5463     if [ "$_real_ca" = "$_real_cert" ]; then
 | 
| 
 | 
  5464       echo "" >>"$_real_ca"
 | 
| 
 | 
  5465       cat "$CA_CERT_PATH" >>"$_real_ca" || return 1
 | 
| 
 | 
  5466     else
 | 
| 
 | 
  5467       if [ -f "$_real_ca" ] && [ ! "$_ACME_IS_RENEW" ]; then
 | 
| 
 | 
  5468         cp "$_real_ca" "$_backup_path/ca.bak"
 | 
| 
 | 
  5469       fi
 | 
| 
 | 
  5470       cat "$CA_CERT_PATH" >"$_real_ca" || return 1
 | 
| 
 | 
  5471     fi
 | 
| 
 | 
  5472   fi
 | 
| 
 | 
  5473 
 | 
| 
 | 
  5474   if [ "$_real_key" ]; then
 | 
| 
 | 
  5475     _info "Installing key to:$_real_key"
 | 
| 
 | 
  5476     if [ -f "$_real_key" ] && [ ! "$_ACME_IS_RENEW" ]; then
 | 
| 
 | 
  5477       cp "$_real_key" "$_backup_path/key.bak"
 | 
| 
 | 
  5478     fi
 | 
| 
 | 
  5479     if [ -f "$_real_key" ]; then
 | 
| 
 | 
  5480       cat "$CERT_KEY_PATH" >"$_real_key" || return 1
 | 
| 
 | 
  5481     else
 | 
| 
 | 
  5482       cat "$CERT_KEY_PATH" >"$_real_key" || return 1
 | 
| 
 | 
  5483       chmod 600 "$_real_key"
 | 
| 
 | 
  5484     fi
 | 
| 
 | 
  5485   fi
 | 
| 
 | 
  5486 
 | 
| 
 | 
  5487   if [ "$_real_fullchain" ]; then
 | 
| 
 | 
  5488     _info "Installing full chain to:$_real_fullchain"
 | 
| 
 | 
  5489     if [ -f "$_real_fullchain" ] && [ ! "$_ACME_IS_RENEW" ]; then
 | 
| 
 | 
  5490       cp "$_real_fullchain" "$_backup_path/fullchain.bak"
 | 
| 
 | 
  5491     fi
 | 
| 
 | 
  5492     cat "$CERT_FULLCHAIN_PATH" >"$_real_fullchain" || return 1
 | 
| 
 | 
  5493   fi
 | 
| 
 | 
  5494 
 | 
| 
 | 
  5495   if [ "$_reload_cmd" ]; then
 | 
| 
 | 
  5496     _info "Run reload cmd: $_reload_cmd"
 | 
| 
 | 
  5497     if (
 | 
| 
 | 
  5498       export CERT_PATH
 | 
| 
 | 
  5499       export CERT_KEY_PATH
 | 
| 
 | 
  5500       export CA_CERT_PATH
 | 
| 
 | 
  5501       export CERT_FULLCHAIN_PATH
 | 
| 
 | 
  5502       export Le_Domain="$_main_domain"
 | 
| 
 | 
  5503       cd "$DOMAIN_PATH" && eval "$_reload_cmd"
 | 
| 
 | 
  5504     ); then
 | 
| 
 | 
  5505       _info "$(__green "Reload success")"
 | 
| 
 | 
  5506     else
 | 
| 
 | 
  5507       _err "Reload error for :$Le_Domain"
 | 
| 
 | 
  5508     fi
 | 
| 
 | 
  5509   fi
 | 
| 
 | 
  5510 
 | 
| 
 | 
  5511 }
 | 
| 
 | 
  5512 
 | 
| 
 | 
  5513 __read_password() {
 | 
| 
 | 
  5514   unset _pp
 | 
| 
 | 
  5515   prompt="Enter Password:"
 | 
| 
 | 
  5516   while IFS= read -p "$prompt" -r -s -n 1 char; do
 | 
| 
 | 
  5517     if [ "$char" = $'\0' ]; then
 | 
| 
 | 
  5518       break
 | 
| 
 | 
  5519     fi
 | 
| 
 | 
  5520     prompt='*'
 | 
| 
 | 
  5521     _pp="$_pp$char"
 | 
| 
 | 
  5522   done
 | 
| 
 | 
  5523   echo "$_pp"
 | 
| 
 | 
  5524 }
 | 
| 
 | 
  5525 
 | 
| 
 | 
  5526 _install_win_taskscheduler() {
 | 
| 
 | 
  5527   _lesh="$1"
 | 
| 
 | 
  5528   _centry="$2"
 | 
| 
 | 
  5529   _randomminute="$3"
 | 
| 
 | 
  5530   if ! _exists cygpath; then
 | 
| 
 | 
  5531     _err "cygpath not found"
 | 
| 
 | 
  5532     return 1
 | 
| 
 | 
  5533   fi
 | 
| 
 | 
  5534   if ! _exists schtasks; then
 | 
| 
 | 
  5535     _err "schtasks.exe is not found, are you on Windows?"
 | 
| 
 | 
  5536     return 1
 | 
| 
 | 
  5537   fi
 | 
| 
 | 
  5538   _winbash="$(cygpath -w $(which bash))"
 | 
| 
 | 
  5539   _debug _winbash "$_winbash"
 | 
| 
 | 
  5540   if [ -z "$_winbash" ]; then
 | 
| 
 | 
  5541     _err "can not find bash path"
 | 
| 
 | 
  5542     return 1
 | 
| 
 | 
  5543   fi
 | 
| 
 | 
  5544   _myname="$(whoami)"
 | 
| 
 | 
  5545   _debug "_myname" "$_myname"
 | 
| 
 | 
  5546   if [ -z "$_myname" ]; then
 | 
| 
 | 
  5547     _err "can not find my user name"
 | 
| 
 | 
  5548     return 1
 | 
| 
 | 
  5549   fi
 | 
| 
 | 
  5550   _debug "_lesh" "$_lesh"
 | 
| 
 | 
  5551 
 | 
| 
 | 
  5552   _info "To install scheduler task in your Windows account, you must input your windows password."
 | 
| 
 | 
  5553   _info "$PROJECT_NAME doesn't save your password."
 | 
| 
 | 
  5554   _info "Please input your Windows password for: $(__green "$_myname")"
 | 
| 
 | 
  5555   _password="$(__read_password)"
 | 
| 
 | 
  5556   #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
 | 
| 
 | 
  5557   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
 | 
| 
 | 
  5558   echo
 | 
| 
 | 
  5559 
 | 
| 
 | 
  5560 }
 | 
| 
 | 
  5561 
 | 
| 
 | 
  5562 _uninstall_win_taskscheduler() {
 | 
| 
 | 
  5563   if ! _exists schtasks; then
 | 
| 
 | 
  5564     _err "schtasks.exe is not found, are you on Windows?"
 | 
| 
 | 
  5565     return 1
 | 
| 
 | 
  5566   fi
 | 
| 
 | 
  5567   if ! echo SCHTASKS /query /tn "$_WINDOWS_SCHEDULER_NAME" | cmd.exe >/dev/null; then
 | 
| 
 | 
  5568     _debug "scheduler $_WINDOWS_SCHEDULER_NAME is not found."
 | 
| 
 | 
  5569   else
 | 
| 
 | 
  5570     _info "Removing $_WINDOWS_SCHEDULER_NAME"
 | 
| 
 | 
  5571     echo SCHTASKS /delete /f /tn "$_WINDOWS_SCHEDULER_NAME" | cmd.exe >/dev/null
 | 
| 
 | 
  5572   fi
 | 
| 
 | 
  5573 }
 | 
| 
 | 
  5574 
 | 
| 
 | 
  5575 #confighome
 | 
| 
 | 
  5576 installcronjob() {
 | 
| 
 | 
  5577   _c_home="$1"
 | 
| 
 | 
  5578   _initpath
 | 
| 
 | 
  5579   _CRONTAB="crontab"
 | 
| 
 | 
  5580   if [ -f "$LE_WORKING_DIR/$PROJECT_ENTRY" ]; then
 | 
| 
 | 
  5581     lesh="\"$LE_WORKING_DIR\"/$PROJECT_ENTRY"
 | 
| 
 | 
  5582   else
 | 
| 
 | 
  5583     _err "Can not install cronjob, $PROJECT_ENTRY not found."
 | 
| 
 | 
  5584     return 1
 | 
| 
 | 
  5585   fi
 | 
| 
 | 
  5586   if [ "$_c_home" ]; then
 | 
| 
 | 
  5587     _c_entry="--config-home \"$_c_home\" "
 | 
| 
 | 
  5588   fi
 | 
| 
 | 
  5589   _t=$(_time)
 | 
| 
 | 
  5590   random_minute=$(_math $_t % 60)
 | 
| 
 | 
  5591 
 | 
| 
 | 
  5592   if ! _exists "$_CRONTAB" && _exists "fcrontab"; then
 | 
| 
 | 
  5593     _CRONTAB="fcrontab"
 | 
| 
 | 
  5594   fi
 | 
| 
 | 
  5595 
 | 
| 
 | 
  5596   if ! _exists "$_CRONTAB"; then
 | 
| 
 | 
  5597     if _exists cygpath && _exists schtasks.exe; then
 | 
| 
 | 
  5598       _info "It seems you are on Windows,  let's install Windows scheduler task."
 | 
| 
 | 
  5599       if _install_win_taskscheduler "$lesh" "$_c_entry" "$random_minute"; then
 | 
| 
 | 
  5600         _info "Install Windows scheduler task success."
 | 
| 
 | 
  5601         return 0
 | 
| 
 | 
  5602       else
 | 
| 
 | 
  5603         _err "Install Windows scheduler task failed."
 | 
| 
 | 
  5604         return 1
 | 
| 
 | 
  5605       fi
 | 
| 
 | 
  5606     fi
 | 
| 
 | 
  5607     _err "crontab/fcrontab doesn't exist, so, we can not install cron jobs."
 | 
| 
 | 
  5608     _err "All your certs will not be renewed automatically."
 | 
| 
 | 
  5609     _err "You must add your own cron job to call '$PROJECT_ENTRY --cron' everyday."
 | 
| 
 | 
  5610     return 1
 | 
| 
 | 
  5611   fi
 | 
| 
 | 
  5612   _info "Installing cron job"
 | 
| 
 | 
  5613   if ! $_CRONTAB -l | grep "$PROJECT_ENTRY --cron"; then
 | 
| 
 | 
  5614     if _exists uname && uname -a | grep SunOS >/dev/null; then
 | 
| 
 | 
  5615       $_CRONTAB -l | {
 | 
| 
 | 
  5616         cat
 | 
| 
 | 
  5617         echo "$random_minute 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" $_c_entry> /dev/null"
 | 
| 
 | 
  5618       } | $_CRONTAB --
 | 
| 
 | 
  5619     else
 | 
| 
 | 
  5620       $_CRONTAB -l | {
 | 
| 
 | 
  5621         cat
 | 
| 
 | 
  5622         echo "$random_minute 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" $_c_entry> /dev/null"
 | 
| 
 | 
  5623       } | $_CRONTAB -
 | 
| 
 | 
  5624     fi
 | 
| 
 | 
  5625   fi
 | 
| 
 | 
  5626   if [ "$?" != "0" ]; then
 | 
| 
 | 
  5627     _err "Install cron job failed. You need to manually renew your certs."
 | 
| 
 | 
  5628     _err "Or you can add cronjob by yourself:"
 | 
| 
 | 
  5629     _err "$lesh --cron --home \"$LE_WORKING_DIR\" > /dev/null"
 | 
| 
 | 
  5630     return 1
 | 
| 
 | 
  5631   fi
 | 
| 
 | 
  5632 }
 | 
| 
 | 
  5633 
 | 
| 
 | 
  5634 uninstallcronjob() {
 | 
| 
 | 
  5635   _CRONTAB="crontab"
 | 
| 
 | 
  5636   if ! _exists "$_CRONTAB" && _exists "fcrontab"; then
 | 
| 
 | 
  5637     _CRONTAB="fcrontab"
 | 
| 
 | 
  5638   fi
 | 
| 
 | 
  5639 
 | 
| 
 | 
  5640   if ! _exists "$_CRONTAB"; then
 | 
| 
 | 
  5641     if _exists cygpath && _exists schtasks.exe; then
 | 
| 
 | 
  5642       _info "It seems you are on Windows,  let's uninstall Windows scheduler task."
 | 
| 
 | 
  5643       if _uninstall_win_taskscheduler; then
 | 
| 
 | 
  5644         _info "Uninstall Windows scheduler task success."
 | 
| 
 | 
  5645         return 0
 | 
| 
 | 
  5646       else
 | 
| 
 | 
  5647         _err "Uninstall Windows scheduler task failed."
 | 
| 
 | 
  5648         return 1
 | 
| 
 | 
  5649       fi
 | 
| 
 | 
  5650     fi
 | 
| 
 | 
  5651     return
 | 
| 
 | 
  5652   fi
 | 
| 
 | 
  5653   _info "Removing cron job"
 | 
| 
 | 
  5654   cr="$($_CRONTAB -l | grep "$PROJECT_ENTRY --cron")"
 | 
| 
 | 
  5655   if [ "$cr" ]; then
 | 
| 
 | 
  5656     if _exists uname && uname -a | grep solaris >/dev/null; then
 | 
| 
 | 
  5657       $_CRONTAB -l | sed "/$PROJECT_ENTRY --cron/d" | $_CRONTAB --
 | 
| 
 | 
  5658     else
 | 
| 
 | 
  5659       $_CRONTAB -l | sed "/$PROJECT_ENTRY --cron/d" | $_CRONTAB -
 | 
| 
 | 
  5660     fi
 | 
| 
 | 
  5661     LE_WORKING_DIR="$(echo "$cr" | cut -d ' ' -f 9 | tr -d '"')"
 | 
| 
 | 
  5662     _info LE_WORKING_DIR "$LE_WORKING_DIR"
 | 
| 
 | 
  5663     if _contains "$cr" "--config-home"; then
 | 
| 
 | 
  5664       LE_CONFIG_HOME="$(echo "$cr" | cut -d ' ' -f 11 | tr -d '"')"
 | 
| 
 | 
  5665       _debug LE_CONFIG_HOME "$LE_CONFIG_HOME"
 | 
| 
 | 
  5666     fi
 | 
| 
 | 
  5667   fi
 | 
| 
 | 
  5668   _initpath
 | 
| 
 | 
  5669 
 | 
| 
 | 
  5670 }
 | 
| 
 | 
  5671 
 | 
| 
 | 
  5672 #domain  isECC  revokeReason
 | 
| 
 | 
  5673 revoke() {
 | 
| 
 | 
  5674   Le_Domain="$1"
 | 
| 
 | 
  5675   if [ -z "$Le_Domain" ]; then
 | 
| 
 | 
  5676     _usage "Usage: $PROJECT_ENTRY --revoke --domain <domain.tld> [--ecc]"
 | 
| 
 | 
  5677     return 1
 | 
| 
 | 
  5678   fi
 | 
| 
 | 
  5679 
 | 
| 
 | 
  5680   _isEcc="$2"
 | 
| 
 | 
  5681   _reason="$3"
 | 
| 
 | 
  5682   if [ -z "$_reason" ]; then
 | 
| 
 | 
  5683     _reason="0"
 | 
| 
 | 
  5684   fi
 | 
| 
 | 
  5685   _initpath "$Le_Domain" "$_isEcc"
 | 
| 
 | 
  5686   if [ ! -f "$DOMAIN_CONF" ]; then
 | 
| 
 | 
  5687     _err "$Le_Domain is not a issued domain, skip."
 | 
| 
 | 
  5688     return 1
 | 
| 
 | 
  5689   fi
 | 
| 
 | 
  5690 
 | 
| 
 | 
  5691   if [ ! -f "$CERT_PATH" ]; then
 | 
| 
 | 
  5692     _err "Cert for $Le_Domain $CERT_PATH is not found, skip."
 | 
| 
 | 
  5693     return 1
 | 
| 
 | 
  5694   fi
 | 
| 
 | 
  5695 
 | 
| 
 | 
  5696   cert="$(_getfile "${CERT_PATH}" "${BEGIN_CERT}" "${END_CERT}" | tr -d "\r\n" | _url_replace)"
 | 
| 
 | 
  5697 
 | 
| 
 | 
  5698   if [ -z "$cert" ]; then
 | 
| 
 | 
  5699     _err "Cert for $Le_Domain is empty found, skip."
 | 
| 
 | 
  5700     return 1
 | 
| 
 | 
  5701   fi
 | 
| 
 | 
  5702 
 | 
| 
 | 
  5703   _initAPI
 | 
| 
 | 
  5704 
 | 
| 
 | 
  5705   if [ "$ACME_VERSION" = "2" ]; then
 | 
| 
 | 
  5706     data="{\"certificate\": \"$cert\",\"reason\":$_reason}"
 | 
| 
 | 
  5707   else
 | 
| 
 | 
  5708     data="{\"resource\": \"revoke-cert\", \"certificate\": \"$cert\"}"
 | 
| 
 | 
  5709   fi
 | 
| 
 | 
  5710   uri="${ACME_REVOKE_CERT}"
 | 
| 
 | 
  5711 
 | 
| 
 | 
  5712   if [ -f "$CERT_KEY_PATH" ]; then
 | 
| 
 | 
  5713     _info "Try domain key first."
 | 
| 
 | 
  5714     if _send_signed_request "$uri" "$data" "" "$CERT_KEY_PATH"; then
 | 
| 
 | 
  5715       if [ -z "$response" ]; then
 | 
| 
 | 
  5716         _info "Revoke success."
 | 
| 
 | 
  5717         rm -f "$CERT_PATH"
 | 
| 
 | 
  5718         return 0
 | 
| 
 | 
  5719       else
 | 
| 
 | 
  5720         _err "Revoke error by domain key."
 | 
| 
 | 
  5721         _err "$response"
 | 
| 
 | 
  5722       fi
 | 
| 
 | 
  5723     fi
 | 
| 
 | 
  5724   else
 | 
| 
 | 
  5725     _info "Domain key file doesn't exist."
 | 
| 
 | 
  5726   fi
 | 
| 
 | 
  5727 
 | 
| 
 | 
  5728   _info "Try account key."
 | 
| 
 | 
  5729 
 | 
| 
 | 
  5730   if _send_signed_request "$uri" "$data" "" "$ACCOUNT_KEY_PATH"; then
 | 
| 
 | 
  5731     if [ -z "$response" ]; then
 | 
| 
 | 
  5732       _info "Revoke success."
 | 
| 
 | 
  5733       rm -f "$CERT_PATH"
 | 
| 
 | 
  5734       return 0
 | 
| 
 | 
  5735     else
 | 
| 
 | 
  5736       _err "Revoke error."
 | 
| 
 | 
  5737       _debug "$response"
 | 
| 
 | 
  5738     fi
 | 
| 
 | 
  5739   fi
 | 
| 
 | 
  5740   return 1
 | 
| 
 | 
  5741 }
 | 
| 
 | 
  5742 
 | 
| 
 | 
  5743 #domain  ecc
 | 
| 
 | 
  5744 remove() {
 | 
| 
 | 
  5745   Le_Domain="$1"
 | 
| 
 | 
  5746   if [ -z "$Le_Domain" ]; then
 | 
| 
 | 
  5747     _usage "Usage: $PROJECT_ENTRY --remove --domain <domain.tld> [--ecc]"
 | 
| 
 | 
  5748     return 1
 | 
| 
 | 
  5749   fi
 | 
| 
 | 
  5750 
 | 
| 
 | 
  5751   _isEcc="$2"
 | 
| 
 | 
  5752 
 | 
| 
 | 
  5753   _initpath "$Le_Domain" "$_isEcc"
 | 
| 
 | 
  5754   _removed_conf="$DOMAIN_CONF.removed"
 | 
| 
 | 
  5755   if [ ! -f "$DOMAIN_CONF" ]; then
 | 
| 
 | 
  5756     if [ -f "$_removed_conf" ]; then
 | 
| 
 | 
  5757       _err "$Le_Domain is already removed, You can remove the folder by yourself: $DOMAIN_PATH"
 | 
| 
 | 
  5758     else
 | 
| 
 | 
  5759       _err "$Le_Domain is not a issued domain, skip."
 | 
| 
 | 
  5760     fi
 | 
| 
 | 
  5761     return 1
 | 
| 
 | 
  5762   fi
 | 
| 
 | 
  5763 
 | 
| 
 | 
  5764   if mv "$DOMAIN_CONF" "$_removed_conf"; then
 | 
| 
 | 
  5765     _info "$Le_Domain is removed, the key and cert files are in $(__green $DOMAIN_PATH)"
 | 
| 
 | 
  5766     _info "You can remove them by yourself."
 | 
| 
 | 
  5767     return 0
 | 
| 
 | 
  5768   else
 | 
| 
 | 
  5769     _err "Remove $Le_Domain failed."
 | 
| 
 | 
  5770     return 1
 | 
| 
 | 
  5771   fi
 | 
| 
 | 
  5772 }
 | 
| 
 | 
  5773 
 | 
| 
 | 
  5774 #domain vtype
 | 
| 
 | 
  5775 _deactivate() {
 | 
| 
 | 
  5776   _d_domain="$1"
 | 
| 
 | 
  5777   _d_type="$2"
 | 
| 
 | 
  5778   _initpath
 | 
| 
 | 
  5779 
 | 
| 
 | 
  5780   if [ "$ACME_VERSION" = "2" ]; then
 | 
| 
 | 
  5781     _identifiers="{\"type\":\"dns\",\"value\":\"$_d_domain\"}"
 | 
| 
 | 
  5782     if ! _send_signed_request "$ACME_NEW_ORDER" "{\"identifiers\": [$_identifiers]}"; then
 | 
| 
 | 
  5783       _err "Can not get domain new order."
 | 
| 
 | 
  5784       return 1
 | 
| 
 | 
  5785     fi
 | 
| 
 | 
  5786     _authorizations_seg="$(echo "$response" | _egrep_o '"authorizations" *: *\[[^\]*\]' | cut -d '[' -f 2 | tr -d ']' | tr -d '"')"
 | 
| 
 | 
  5787     _debug2 _authorizations_seg "$_authorizations_seg"
 | 
| 
 | 
  5788     if [ -z "$_authorizations_seg" ]; then
 | 
| 
 | 
  5789       _err "_authorizations_seg not found."
 | 
| 
 | 
  5790       _clearup
 | 
| 
 | 
  5791       _on_issue_err "$_post_hook"
 | 
| 
 | 
  5792       return 1
 | 
| 
 | 
  5793     fi
 | 
| 
 | 
  5794 
 | 
| 
 | 
  5795     authzUri="$_authorizations_seg"
 | 
| 
 | 
  5796     _debug2 "authzUri" "$authzUri"
 | 
| 
 | 
  5797     if ! _send_signed_request "$authzUri"; then
 | 
| 
 | 
  5798       _err "get to authz error."
 | 
| 
 | 
  5799       _err "_authorizations_seg" "$_authorizations_seg"
 | 
| 
 | 
  5800       _err "authzUri" "$authzUri"
 | 
| 
 | 
  5801       _clearup
 | 
| 
 | 
  5802       _on_issue_err "$_post_hook"
 | 
| 
 | 
  5803       return 1
 | 
| 
 | 
  5804     fi
 | 
| 
 | 
  5805 
 | 
| 
 | 
  5806     response="$(echo "$response" | _normalizeJson)"
 | 
| 
 | 
  5807     _debug2 response "$response"
 | 
| 
 | 
  5808     _URL_NAME="url"
 | 
| 
 | 
  5809   else
 | 
| 
 | 
  5810     if ! __get_domain_new_authz "$_d_domain"; then
 | 
| 
 | 
  5811       _err "Can not get domain new authz token."
 | 
| 
 | 
  5812       return 1
 | 
| 
 | 
  5813     fi
 | 
| 
 | 
  5814 
 | 
| 
 | 
  5815     authzUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ':' -f 2- | tr -d "\r\n")"
 | 
| 
 | 
  5816     _debug "authzUri" "$authzUri"
 | 
| 
 | 
  5817     if [ "$code" ] && [ ! "$code" = '201' ]; then
 | 
| 
 | 
  5818       _err "new-authz error: $response"
 | 
| 
 | 
  5819       return 1
 | 
| 
 | 
  5820     fi
 | 
| 
 | 
  5821     _URL_NAME="uri"
 | 
| 
 | 
  5822   fi
 | 
| 
 | 
  5823 
 | 
| 
 | 
  5824   entries="$(echo "$response" | _egrep_o "[^{]*\"type\":\"[^\"]*\", *\"status\": *\"valid\", *\"$_URL_NAME\"[^}]*")"
 | 
| 
 | 
  5825   if [ -z "$entries" ]; then
 | 
| 
 | 
  5826     _info "No valid entries found."
 | 
| 
 | 
  5827     if [ -z "$thumbprint" ]; then
 | 
| 
 | 
  5828       thumbprint="$(__calc_account_thumbprint)"
 | 
| 
 | 
  5829     fi
 | 
| 
 | 
  5830     _debug "Trigger validation."
 | 
| 
 | 
  5831     vtype="$VTYPE_DNS"
 | 
| 
 | 
  5832     entry="$(echo "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"
 | 
| 
 | 
  5833     _debug entry "$entry"
 | 
| 
 | 
  5834     if [ -z "$entry" ]; then
 | 
| 
 | 
  5835       _err "Error, can not get domain token $d"
 | 
| 
 | 
  5836       return 1
 | 
| 
 | 
  5837     fi
 | 
| 
 | 
  5838     token="$(echo "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')"
 | 
| 
 | 
  5839     _debug token "$token"
 | 
| 
 | 
  5840 
 | 
| 
 | 
  5841     uri="$(echo "$entry" | _egrep_o "\"$_URL_NAME\":\"[^\"]*" | cut -d : -f 2,3 | tr -d '"')"
 | 
| 
 | 
  5842     _debug uri "$uri"
 | 
| 
 | 
  5843 
 | 
| 
 | 
  5844     keyauthorization="$token.$thumbprint"
 | 
| 
 | 
  5845     _debug keyauthorization "$keyauthorization"
 | 
| 
 | 
  5846     __trigger_validation "$uri" "$keyauthorization"
 | 
| 
 | 
  5847 
 | 
| 
 | 
  5848   fi
 | 
| 
 | 
  5849 
 | 
| 
 | 
  5850   _d_i=0
 | 
| 
 | 
  5851   _d_max_retry=$(echo "$entries" | wc -l)
 | 
| 
 | 
  5852   while [ "$_d_i" -lt "$_d_max_retry" ]; do
 | 
| 
 | 
  5853     _info "Deactivate: $_d_domain"
 | 
| 
 | 
  5854     _d_i="$(_math $_d_i + 1)"
 | 
| 
 | 
  5855     entry="$(echo "$entries" | sed -n "${_d_i}p")"
 | 
| 
 | 
  5856     _debug entry "$entry"
 | 
| 
 | 
  5857 
 | 
| 
 | 
  5858     if [ -z "$entry" ]; then
 | 
| 
 | 
  5859       _info "No more valid entry found."
 | 
| 
 | 
  5860       break
 | 
| 
 | 
  5861     fi
 | 
| 
 | 
  5862 
 | 
| 
 | 
  5863     _vtype="$(echo "$entry" | _egrep_o '"type": *"[^"]*"' | cut -d : -f 2 | tr -d '"')"
 | 
| 
 | 
  5864     _debug _vtype "$_vtype"
 | 
| 
 | 
  5865     _info "Found $_vtype"
 | 
| 
 | 
  5866 
 | 
| 
 | 
  5867     uri="$(echo "$entry" | _egrep_o "\"$_URL_NAME\":\"[^\"]*" | cut -d : -f 2,3 | tr -d '"')"
 | 
| 
 | 
  5868     _debug uri "$uri"
 | 
| 
 | 
  5869 
 | 
| 
 | 
  5870     if [ "$_d_type" ] && [ "$_d_type" != "$_vtype" ]; then
 | 
| 
 | 
  5871       _info "Skip $_vtype"
 | 
| 
 | 
  5872       continue
 | 
| 
 | 
  5873     fi
 | 
| 
 | 
  5874 
 | 
| 
 | 
  5875     _info "Deactivate: $_vtype"
 | 
| 
 | 
  5876 
 | 
| 
 | 
  5877     if [ "$ACME_VERSION" = "2" ]; then
 | 
| 
 | 
  5878       _djson="{\"status\":\"deactivated\"}"
 | 
| 
 | 
  5879     else
 | 
| 
 | 
  5880       _djson="{\"resource\": \"authz\", \"status\":\"deactivated\"}"
 | 
| 
 | 
  5881     fi
 | 
| 
 | 
  5882 
 | 
| 
 | 
  5883     if _send_signed_request "$authzUri" "$_djson" && _contains "$response" '"deactivated"'; then
 | 
| 
 | 
  5884       _info "Deactivate: $_vtype success."
 | 
| 
 | 
  5885     else
 | 
| 
 | 
  5886       _err "Can not deactivate $_vtype."
 | 
| 
 | 
  5887       break
 | 
| 
 | 
  5888     fi
 | 
| 
 | 
  5889 
 | 
| 
 | 
  5890   done
 | 
| 
 | 
  5891   _debug "$_d_i"
 | 
| 
 | 
  5892   if [ "$_d_i" -eq "$_d_max_retry" ]; then
 | 
| 
 | 
  5893     _info "Deactivated success!"
 | 
| 
 | 
  5894   else
 | 
| 
 | 
  5895     _err "Deactivate failed."
 | 
| 
 | 
  5896   fi
 | 
| 
 | 
  5897 
 | 
| 
 | 
  5898 }
 | 
| 
 | 
  5899 
 | 
| 
 | 
  5900 deactivate() {
 | 
| 
 | 
  5901   _d_domain_list="$1"
 | 
| 
 | 
  5902   _d_type="$2"
 | 
| 
 | 
  5903   _initpath
 | 
| 
 | 
  5904   _initAPI
 | 
| 
 | 
  5905   _debug _d_domain_list "$_d_domain_list"
 | 
| 
 | 
  5906   if [ -z "$(echo $_d_domain_list | cut -d , -f 1)" ]; then
 | 
| 
 | 
  5907     _usage "Usage: $PROJECT_ENTRY --deactivate --domain <domain.tld> [--domain <domain2.tld> ...]"
 | 
| 
 | 
  5908     return 1
 | 
| 
 | 
  5909   fi
 | 
| 
 | 
  5910   for _d_dm in $(echo "$_d_domain_list" | tr ',' ' '); do
 | 
| 
 | 
  5911     if [ -z "$_d_dm" ] || [ "$_d_dm" = "$NO_VALUE" ]; then
 | 
| 
 | 
  5912       continue
 | 
| 
 | 
  5913     fi
 | 
| 
 | 
  5914     if ! _deactivate "$_d_dm" "$_d_type"; then
 | 
| 
 | 
  5915       return 1
 | 
| 
 | 
  5916     fi
 | 
| 
 | 
  5917   done
 | 
| 
 | 
  5918 }
 | 
| 
 | 
  5919 
 | 
| 
 | 
  5920 # Detect profile file if not specified as environment variable
 | 
| 
 | 
  5921 _detect_profile() {
 | 
| 
 | 
  5922   if [ -n "$PROFILE" -a -f "$PROFILE" ]; then
 | 
| 
 | 
  5923     echo "$PROFILE"
 | 
| 
 | 
  5924     return
 | 
| 
 | 
  5925   fi
 | 
| 
 | 
  5926 
 | 
| 
 | 
  5927   DETECTED_PROFILE=''
 | 
| 
 | 
  5928   SHELLTYPE="$(basename "/$SHELL")"
 | 
| 
 | 
  5929 
 | 
| 
 | 
  5930   if [ "$SHELLTYPE" = "bash" ]; then
 | 
| 
 | 
  5931     if [ -f "$HOME/.bashrc" ]; then
 | 
| 
 | 
  5932       DETECTED_PROFILE="$HOME/.bashrc"
 | 
| 
 | 
  5933     elif [ -f "$HOME/.bash_profile" ]; then
 | 
| 
 | 
  5934       DETECTED_PROFILE="$HOME/.bash_profile"
 | 
| 
 | 
  5935     fi
 | 
| 
 | 
  5936   elif [ "$SHELLTYPE" = "zsh" ]; then
 | 
| 
 | 
  5937     DETECTED_PROFILE="$HOME/.zshrc"
 | 
| 
 | 
  5938   fi
 | 
| 
 | 
  5939 
 | 
| 
 | 
  5940   if [ -z "$DETECTED_PROFILE" ]; then
 | 
| 
 | 
  5941     if [ -f "$HOME/.profile" ]; then
 | 
| 
 | 
  5942       DETECTED_PROFILE="$HOME/.profile"
 | 
| 
 | 
  5943     elif [ -f "$HOME/.bashrc" ]; then
 | 
| 
 | 
  5944       DETECTED_PROFILE="$HOME/.bashrc"
 | 
| 
 | 
  5945     elif [ -f "$HOME/.bash_profile" ]; then
 | 
| 
 | 
  5946       DETECTED_PROFILE="$HOME/.bash_profile"
 | 
| 
 | 
  5947     elif [ -f "$HOME/.zshrc" ]; then
 | 
| 
 | 
  5948       DETECTED_PROFILE="$HOME/.zshrc"
 | 
| 
 | 
  5949     fi
 | 
| 
 | 
  5950   fi
 | 
| 
 | 
  5951 
 | 
| 
 | 
  5952   echo "$DETECTED_PROFILE"
 | 
| 
 | 
  5953 }
 | 
| 
 | 
  5954 
 | 
| 
 | 
  5955 _initconf() {
 | 
| 
 | 
  5956   _initpath
 | 
| 
 | 
  5957   if [ ! -f "$ACCOUNT_CONF_PATH" ]; then
 | 
| 
 | 
  5958     echo "
 | 
| 
 | 
  5959 #LOG_FILE=\"$DEFAULT_LOG_FILE\"
 | 
| 
 | 
  5960 #LOG_LEVEL=1
 | 
| 
 | 
  5961 #AUTO_UPGRADE=\"1\"
 | 
| 
 | 
  5962 #NO_TIMESTAMP=1
 | 
| 
 | 
  5963     " >"$ACCOUNT_CONF_PATH"
 | 
| 
 | 
  5964   fi
 | 
| 
 | 
  5965 }
 | 
| 
 | 
  5966 
 | 
| 
 | 
  5967 # nocron
 | 
| 
 | 
  5968 _precheck() {
 | 
| 
 | 
  5969   _nocron="$1"
 | 
| 
 | 
  5970 
 | 
| 
 | 
  5971   if ! _exists "curl" && ! _exists "wget"; then
 | 
| 
 | 
  5972     _err "Please install curl or wget first, we need to access http resources."
 | 
| 
 | 
  5973     return 1
 | 
| 
 | 
  5974   fi
 | 
| 
 | 
  5975 
 | 
| 
 | 
  5976   if [ -z "$_nocron" ]; then
 | 
| 
 | 
  5977     if ! _exists "crontab" && ! _exists "fcrontab"; then
 | 
| 
 | 
  5978       if _exists cygpath && _exists schtasks.exe; then
 | 
| 
 | 
  5979         _info "It seems you are on Windows,  we will install Windows scheduler task."
 | 
| 
 | 
  5980       else
 | 
| 
 | 
  5981         _err "It is recommended to install crontab first. try to install 'cron, crontab, crontabs or vixie-cron'."
 | 
| 
 | 
  5982         _err "We need to set cron job to renew the certs automatically."
 | 
| 
 | 
  5983         _err "Otherwise, your certs will not be able to be renewed automatically."
 | 
| 
 | 
  5984         if [ -z "$FORCE" ]; then
 | 
| 
 | 
  5985           _err "Please add '--force' and try install again to go without crontab."
 | 
| 
 | 
  5986           _err "./$PROJECT_ENTRY --install --force"
 | 
| 
 | 
  5987           return 1
 | 
| 
 | 
  5988         fi
 | 
| 
 | 
  5989       fi
 | 
| 
 | 
  5990     fi
 | 
| 
 | 
  5991   fi
 | 
| 
 | 
  5992 
 | 
| 
 | 
  5993   if ! _exists "${ACME_OPENSSL_BIN:-openssl}"; then
 | 
| 
 | 
  5994     _err "Please install openssl first. ACME_OPENSSL_BIN=$ACME_OPENSSL_BIN"
 | 
| 
 | 
  5995     _err "We need openssl to generate keys."
 | 
| 
 | 
  5996     return 1
 | 
| 
 | 
  5997   fi
 | 
| 
 | 
  5998 
 | 
| 
 | 
  5999   if ! _exists "socat"; then
 | 
| 
 | 
  6000     _err "It is recommended to install socat first."
 | 
| 
 | 
  6001     _err "We use socat for standalone server if you use standalone mode."
 | 
| 
 | 
  6002     _err "If you don't use standalone mode, just ignore this warning."
 | 
| 
 | 
  6003   fi
 | 
| 
 | 
  6004 
 | 
| 
 | 
  6005   return 0
 | 
| 
 | 
  6006 }
 | 
| 
 | 
  6007 
 | 
| 
 | 
  6008 _setShebang() {
 | 
| 
 | 
  6009   _file="$1"
 | 
| 
 | 
  6010   _shebang="$2"
 | 
| 
 | 
  6011   if [ -z "$_shebang" ]; then
 | 
| 
 | 
  6012     _usage "Usage: file shebang"
 | 
| 
 | 
  6013     return 1
 | 
| 
 | 
  6014   fi
 | 
| 
 | 
  6015   cp "$_file" "$_file.tmp"
 | 
| 
 | 
  6016   echo "$_shebang" >"$_file"
 | 
| 
 | 
  6017   sed -n 2,99999p "$_file.tmp" >>"$_file"
 | 
| 
 | 
  6018   rm -f "$_file.tmp"
 | 
| 
 | 
  6019 }
 | 
| 
 | 
  6020 
 | 
| 
 | 
  6021 #confighome
 | 
| 
 | 
  6022 _installalias() {
 | 
| 
 | 
  6023   _c_home="$1"
 | 
| 
 | 
  6024   _initpath
 | 
| 
 | 
  6025 
 | 
| 
 | 
  6026   _envfile="$LE_WORKING_DIR/$PROJECT_ENTRY.env"
 | 
| 
 | 
  6027   if [ "$_upgrading" ] && [ "$_upgrading" = "1" ]; then
 | 
| 
 | 
  6028     echo "$(cat "$_envfile")" | sed "s|^LE_WORKING_DIR.*$||" >"$_envfile"
 | 
| 
 | 
  6029     echo "$(cat "$_envfile")" | sed "s|^alias le.*$||" >"$_envfile"
 | 
| 
 | 
  6030     echo "$(cat "$_envfile")" | sed "s|^alias le.sh.*$||" >"$_envfile"
 | 
| 
 | 
  6031   fi
 | 
| 
 | 
  6032 
 | 
| 
 | 
  6033   if [ "$_c_home" ]; then
 | 
| 
 | 
  6034     _c_entry=" --config-home '$_c_home'"
 | 
| 
 | 
  6035   fi
 | 
| 
 | 
  6036 
 | 
| 
 | 
  6037   _setopt "$_envfile" "export LE_WORKING_DIR" "=" "\"$LE_WORKING_DIR\""
 | 
| 
 | 
  6038   if [ "$_c_home" ]; then
 | 
| 
 | 
  6039     _setopt "$_envfile" "export LE_CONFIG_HOME" "=" "\"$LE_CONFIG_HOME\""
 | 
| 
 | 
  6040   else
 | 
| 
 | 
  6041     _sed_i "/^export LE_CONFIG_HOME/d" "$_envfile"
 | 
| 
 | 
  6042   fi
 | 
| 
 | 
  6043   _setopt "$_envfile" "alias $PROJECT_ENTRY" "=" "\"$LE_WORKING_DIR/$PROJECT_ENTRY$_c_entry\""
 | 
| 
 | 
  6044 
 | 
| 
 | 
  6045   _profile="$(_detect_profile)"
 | 
| 
 | 
  6046   if [ "$_profile" ]; then
 | 
| 
 | 
  6047     _debug "Found profile: $_profile"
 | 
| 
 | 
  6048     _info "Installing alias to '$_profile'"
 | 
| 
 | 
  6049     _setopt "$_profile" ". \"$_envfile\""
 | 
| 
 | 
  6050     _info "OK, Close and reopen your terminal to start using $PROJECT_NAME"
 | 
| 
 | 
  6051   else
 | 
| 
 | 
  6052     _info "No profile is found, you will need to go into $LE_WORKING_DIR to use $PROJECT_NAME"
 | 
| 
 | 
  6053   fi
 | 
| 
 | 
  6054 
 | 
| 
 | 
  6055   #for csh
 | 
| 
 | 
  6056   _cshfile="$LE_WORKING_DIR/$PROJECT_ENTRY.csh"
 | 
| 
 | 
  6057   _csh_profile="$HOME/.cshrc"
 | 
| 
 | 
  6058   if [ -f "$_csh_profile" ]; then
 | 
| 
 | 
  6059     _info "Installing alias to '$_csh_profile'"
 | 
| 
 | 
  6060     _setopt "$_cshfile" "setenv LE_WORKING_DIR" " " "\"$LE_WORKING_DIR\""
 | 
| 
 | 
  6061     if [ "$_c_home" ]; then
 | 
| 
 | 
  6062       _setopt "$_cshfile" "setenv LE_CONFIG_HOME" " " "\"$LE_CONFIG_HOME\""
 | 
| 
 | 
  6063     else
 | 
| 
 | 
  6064       _sed_i "/^setenv LE_CONFIG_HOME/d" "$_cshfile"
 | 
| 
 | 
  6065     fi
 | 
| 
 | 
  6066     _setopt "$_cshfile" "alias $PROJECT_ENTRY" " " "\"$LE_WORKING_DIR/$PROJECT_ENTRY$_c_entry\""
 | 
| 
 | 
  6067     _setopt "$_csh_profile" "source \"$_cshfile\""
 | 
| 
 | 
  6068   fi
 | 
| 
 | 
  6069 
 | 
| 
 | 
  6070   #for tcsh
 | 
| 
 | 
  6071   _tcsh_profile="$HOME/.tcshrc"
 | 
| 
 | 
  6072   if [ -f "$_tcsh_profile" ]; then
 | 
| 
 | 
  6073     _info "Installing alias to '$_tcsh_profile'"
 | 
| 
 | 
  6074     _setopt "$_cshfile" "setenv LE_WORKING_DIR" " " "\"$LE_WORKING_DIR\""
 | 
| 
 | 
  6075     if [ "$_c_home" ]; then
 | 
| 
 | 
  6076       _setopt "$_cshfile" "setenv LE_CONFIG_HOME" " " "\"$LE_CONFIG_HOME\""
 | 
| 
 | 
  6077     fi
 | 
| 
 | 
  6078     _setopt "$_cshfile" "alias $PROJECT_ENTRY" " " "\"$LE_WORKING_DIR/$PROJECT_ENTRY$_c_entry\""
 | 
| 
 | 
  6079     _setopt "$_tcsh_profile" "source \"$_cshfile\""
 | 
| 
 | 
  6080   fi
 | 
| 
 | 
  6081 
 | 
| 
 | 
  6082 }
 | 
| 
 | 
  6083 
 | 
| 
 | 
  6084 # nocron confighome noprofile
 | 
| 
 | 
  6085 install() {
 | 
| 
 | 
  6086 
 | 
| 
 | 
  6087   if [ -z "$LE_WORKING_DIR" ]; then
 | 
| 
 | 
  6088     LE_WORKING_DIR="$DEFAULT_INSTALL_HOME"
 | 
| 
 | 
  6089   fi
 | 
| 
 | 
  6090 
 | 
| 
 | 
  6091   _nocron="$1"
 | 
| 
 | 
  6092   _c_home="$2"
 | 
| 
 | 
  6093   _noprofile="$3"
 | 
| 
 | 
  6094   if ! _initpath; then
 | 
| 
 | 
  6095     _err "Install failed."
 | 
| 
 | 
  6096     return 1
 | 
| 
 | 
  6097   fi
 | 
| 
 | 
  6098   if [ "$_nocron" ]; then
 | 
| 
 | 
  6099     _debug "Skip install cron job"
 | 
| 
 | 
  6100   fi
 | 
| 
 | 
  6101 
 | 
| 
 | 
  6102   if [ "$_ACME_IN_CRON" != "1" ]; then
 | 
| 
 | 
  6103     if ! _precheck "$_nocron"; then
 | 
| 
 | 
  6104       _err "Pre-check failed, can not install."
 | 
| 
 | 
  6105       return 1
 | 
| 
 | 
  6106     fi
 | 
| 
 | 
  6107   fi
 | 
| 
 | 
  6108 
 | 
| 
 | 
  6109   if [ -z "$_c_home" ] && [ "$LE_CONFIG_HOME" != "$LE_WORKING_DIR" ]; then
 | 
| 
 | 
  6110     _info "Using config home: $LE_CONFIG_HOME"
 | 
| 
 | 
  6111     _c_home="$LE_CONFIG_HOME"
 | 
| 
 | 
  6112   fi
 | 
| 
 | 
  6113 
 | 
| 
 | 
  6114   #convert from le
 | 
| 
 | 
  6115   if [ -d "$HOME/.le" ]; then
 | 
| 
 | 
  6116     for envfile in "le.env" "le.sh.env"; do
 | 
| 
 | 
  6117       if [ -f "$HOME/.le/$envfile" ]; then
 | 
| 
 | 
  6118         if grep "le.sh" "$HOME/.le/$envfile" >/dev/null; then
 | 
| 
 | 
  6119           _upgrading="1"
 | 
| 
 | 
  6120           _info "You are upgrading from le.sh"
 | 
| 
 | 
  6121           _info "Renaming \"$HOME/.le\" to $LE_WORKING_DIR"
 | 
| 
 | 
  6122           mv "$HOME/.le" "$LE_WORKING_DIR"
 | 
| 
 | 
  6123           mv "$LE_WORKING_DIR/$envfile" "$LE_WORKING_DIR/$PROJECT_ENTRY.env"
 | 
| 
 | 
  6124           break
 | 
| 
 | 
  6125         fi
 | 
| 
 | 
  6126       fi
 | 
| 
 | 
  6127     done
 | 
| 
 | 
  6128   fi
 | 
| 
 | 
  6129 
 | 
| 
 | 
  6130   _info "Installing to $LE_WORKING_DIR"
 | 
| 
 | 
  6131 
 | 
| 
 | 
  6132   if [ ! -d "$LE_WORKING_DIR" ]; then
 | 
| 
 | 
  6133     if ! mkdir -p "$LE_WORKING_DIR"; then
 | 
| 
 | 
  6134       _err "Can not create working dir: $LE_WORKING_DIR"
 | 
| 
 | 
  6135       return 1
 | 
| 
 | 
  6136     fi
 | 
| 
 | 
  6137 
 | 
| 
 | 
  6138     chmod 700 "$LE_WORKING_DIR"
 | 
| 
 | 
  6139   fi
 | 
| 
 | 
  6140 
 | 
| 
 | 
  6141   if [ ! -d "$LE_CONFIG_HOME" ]; then
 | 
| 
 | 
  6142     if ! mkdir -p "$LE_CONFIG_HOME"; then
 | 
| 
 | 
  6143       _err "Can not create config dir: $LE_CONFIG_HOME"
 | 
| 
 | 
  6144       return 1
 | 
| 
 | 
  6145     fi
 | 
| 
 | 
  6146 
 | 
| 
 | 
  6147     chmod 700 "$LE_CONFIG_HOME"
 | 
| 
 | 
  6148   fi
 | 
| 
 | 
  6149 
 | 
| 
 | 
  6150   cp "$PROJECT_ENTRY" "$LE_WORKING_DIR/" && chmod +x "$LE_WORKING_DIR/$PROJECT_ENTRY"
 | 
| 
 | 
  6151 
 | 
| 
 | 
  6152   if [ "$?" != "0" ]; then
 | 
| 
 | 
  6153     _err "Install failed, can not copy $PROJECT_ENTRY"
 | 
| 
 | 
  6154     return 1
 | 
| 
 | 
  6155   fi
 | 
| 
 | 
  6156 
 | 
| 
 | 
  6157   _info "Installed to $LE_WORKING_DIR/$PROJECT_ENTRY"
 | 
| 
 | 
  6158 
 | 
| 
 | 
  6159   if [ "$_ACME_IN_CRON" != "1" ] && [ -z "$_noprofile" ]; then
 | 
| 
 | 
  6160     _installalias "$_c_home"
 | 
| 
 | 
  6161   fi
 | 
| 
 | 
  6162 
 | 
| 
 | 
  6163   for subf in $_SUB_FOLDERS; do
 | 
| 
 | 
  6164     if [ -d "$subf" ]; then
 | 
| 
 | 
  6165       mkdir -p "$LE_WORKING_DIR/$subf"
 | 
| 
 | 
  6166       cp "$subf"/* "$LE_WORKING_DIR"/"$subf"/
 | 
| 
 | 
  6167     fi
 | 
| 
 | 
  6168   done
 | 
| 
 | 
  6169 
 | 
| 
 | 
  6170   if [ ! -f "$ACCOUNT_CONF_PATH" ]; then
 | 
| 
 | 
  6171     _initconf
 | 
| 
 | 
  6172   fi
 | 
| 
 | 
  6173 
 | 
| 
 | 
  6174   if [ "$_DEFAULT_ACCOUNT_CONF_PATH" != "$ACCOUNT_CONF_PATH" ]; then
 | 
| 
 | 
  6175     _setopt "$_DEFAULT_ACCOUNT_CONF_PATH" "ACCOUNT_CONF_PATH" "=" "\"$ACCOUNT_CONF_PATH\""
 | 
| 
 | 
  6176   fi
 | 
| 
 | 
  6177 
 | 
| 
 | 
  6178   if [ "$_DEFAULT_CERT_HOME" != "$CERT_HOME" ]; then
 | 
| 
 | 
  6179     _saveaccountconf "CERT_HOME" "$CERT_HOME"
 | 
| 
 | 
  6180   fi
 | 
| 
 | 
  6181 
 | 
| 
 | 
  6182   if [ "$_DEFAULT_ACCOUNT_KEY_PATH" != "$ACCOUNT_KEY_PATH" ]; then
 | 
| 
 | 
  6183     _saveaccountconf "ACCOUNT_KEY_PATH" "$ACCOUNT_KEY_PATH"
 | 
| 
 | 
  6184   fi
 | 
| 
 | 
  6185 
 | 
| 
 | 
  6186   if [ -z "$_nocron" ]; then
 | 
| 
 | 
  6187     installcronjob "$_c_home"
 | 
| 
 | 
  6188   fi
 | 
| 
 | 
  6189 
 | 
| 
 | 
  6190   if [ -z "$NO_DETECT_SH" ]; then
 | 
| 
 | 
  6191     #Modify shebang
 | 
| 
 | 
  6192     if _exists bash; then
 | 
| 
 | 
  6193       _bash_path="$(bash -c "command -v bash 2>/dev/null")"
 | 
| 
 | 
  6194       if [ -z "$_bash_path" ]; then
 | 
| 
 | 
  6195         _bash_path="$(bash -c 'echo $SHELL')"
 | 
| 
 | 
  6196       fi
 | 
| 
 | 
  6197     fi
 | 
| 
 | 
  6198     if [ "$_bash_path" ]; then
 | 
| 
 | 
  6199       _info "Good, bash is found, so change the shebang to use bash as preferred."
 | 
| 
 | 
  6200       _shebang='#!'"$_bash_path"
 | 
| 
 | 
  6201       _setShebang "$LE_WORKING_DIR/$PROJECT_ENTRY" "$_shebang"
 | 
| 
 | 
  6202       for subf in $_SUB_FOLDERS; do
 | 
| 
 | 
  6203         if [ -d "$LE_WORKING_DIR/$subf" ]; then
 | 
| 
 | 
  6204           for _apifile in "$LE_WORKING_DIR/$subf/"*.sh; do
 | 
| 
 | 
  6205             _setShebang "$_apifile" "$_shebang"
 | 
| 
 | 
  6206           done
 | 
| 
 | 
  6207         fi
 | 
| 
 | 
  6208       done
 | 
| 
 | 
  6209     fi
 | 
| 
 | 
  6210   fi
 | 
| 
 | 
  6211 
 | 
| 
 | 
  6212   _info OK
 | 
| 
 | 
  6213 }
 | 
| 
 | 
  6214 
 | 
| 
 | 
  6215 # nocron
 | 
| 
 | 
  6216 uninstall() {
 | 
| 
 | 
  6217   _nocron="$1"
 | 
| 
 | 
  6218   if [ -z "$_nocron" ]; then
 | 
| 
 | 
  6219     uninstallcronjob
 | 
| 
 | 
  6220   fi
 | 
| 
 | 
  6221   _initpath
 | 
| 
 | 
  6222 
 | 
| 
 | 
  6223   _uninstallalias
 | 
| 
 | 
  6224 
 | 
| 
 | 
  6225   rm -f "$LE_WORKING_DIR/$PROJECT_ENTRY"
 | 
| 
 | 
  6226   _info "The keys and certs are in \"$(__green "$LE_CONFIG_HOME")\", you can remove them by yourself."
 | 
| 
 | 
  6227 
 | 
| 
 | 
  6228 }
 | 
| 
 | 
  6229 
 | 
| 
 | 
  6230 _uninstallalias() {
 | 
| 
 | 
  6231   _initpath
 | 
| 
 | 
  6232 
 | 
| 
 | 
  6233   _profile="$(_detect_profile)"
 | 
| 
 | 
  6234   if [ "$_profile" ]; then
 | 
| 
 | 
  6235     _info "Uninstalling alias from: '$_profile'"
 | 
| 
 | 
  6236     text="$(cat "$_profile")"
 | 
| 
 | 
  6237     echo "$text" | sed "s|^.*\"$LE_WORKING_DIR/$PROJECT_NAME.env\"$||" >"$_profile"
 | 
| 
 | 
  6238   fi
 | 
| 
 | 
  6239 
 | 
| 
 | 
  6240   _csh_profile="$HOME/.cshrc"
 | 
| 
 | 
  6241   if [ -f "$_csh_profile" ]; then
 | 
| 
 | 
  6242     _info "Uninstalling alias from: '$_csh_profile'"
 | 
| 
 | 
  6243     text="$(cat "$_csh_profile")"
 | 
| 
 | 
  6244     echo "$text" | sed "s|^.*\"$LE_WORKING_DIR/$PROJECT_NAME.csh\"$||" >"$_csh_profile"
 | 
| 
 | 
  6245   fi
 | 
| 
 | 
  6246 
 | 
| 
 | 
  6247   _tcsh_profile="$HOME/.tcshrc"
 | 
| 
 | 
  6248   if [ -f "$_tcsh_profile" ]; then
 | 
| 
 | 
  6249     _info "Uninstalling alias from: '$_csh_profile'"
 | 
| 
 | 
  6250     text="$(cat "$_tcsh_profile")"
 | 
| 
 | 
  6251     echo "$text" | sed "s|^.*\"$LE_WORKING_DIR/$PROJECT_NAME.csh\"$||" >"$_tcsh_profile"
 | 
| 
 | 
  6252   fi
 | 
| 
 | 
  6253 
 | 
| 
 | 
  6254 }
 | 
| 
 | 
  6255 
 | 
| 
 | 
  6256 cron() {
 | 
| 
 | 
  6257   export _ACME_IN_CRON=1
 | 
| 
 | 
  6258   _initpath
 | 
| 
 | 
  6259   _info "$(__green "===Starting cron===")"
 | 
| 
 | 
  6260   if [ "$AUTO_UPGRADE" = "1" ]; then
 | 
| 
 | 
  6261     export LE_WORKING_DIR
 | 
| 
 | 
  6262     (
 | 
| 
 | 
  6263       if ! upgrade; then
 | 
| 
 | 
  6264         _err "Cron:Upgrade failed!"
 | 
| 
 | 
  6265         return 1
 | 
| 
 | 
  6266       fi
 | 
| 
 | 
  6267     )
 | 
| 
 | 
  6268     . "$LE_WORKING_DIR/$PROJECT_ENTRY" >/dev/null
 | 
| 
 | 
  6269 
 | 
| 
 | 
  6270     if [ -t 1 ]; then
 | 
| 
 | 
  6271       __INTERACTIVE="1"
 | 
| 
 | 
  6272     fi
 | 
| 
 | 
  6273 
 | 
| 
 | 
  6274     _info "Auto upgraded to: $VER"
 | 
| 
 | 
  6275   fi
 | 
| 
 | 
  6276   renewAll
 | 
| 
 | 
  6277   _ret="$?"
 | 
| 
 | 
  6278   _ACME_IN_CRON=""
 | 
| 
 | 
  6279   _info "$(__green "===End cron===")"
 | 
| 
 | 
  6280   exit $_ret
 | 
| 
 | 
  6281 }
 | 
| 
 | 
  6282 
 | 
| 
 | 
  6283 version() {
 | 
| 
 | 
  6284   echo "$PROJECT"
 | 
| 
 | 
  6285   echo "v$VER"
 | 
| 
 | 
  6286 }
 | 
| 
 | 
  6287 
 | 
| 
 | 
  6288 # subject content hooks code
 | 
| 
 | 
  6289 _send_notify() {
 | 
| 
 | 
  6290   _nsubject="$1"
 | 
| 
 | 
  6291   _ncontent="$2"
 | 
| 
 | 
  6292   _nhooks="$3"
 | 
| 
 | 
  6293   _nerror="$4"
 | 
| 
 | 
  6294 
 | 
| 
 | 
  6295   if [ "$NOTIFY_LEVEL" = "$NOTIFY_LEVEL_DISABLE" ]; then
 | 
| 
 | 
  6296     _debug "The NOTIFY_LEVEL is $NOTIFY_LEVEL, disabled, just return."
 | 
| 
 | 
  6297     return 0
 | 
| 
 | 
  6298   fi
 | 
| 
 | 
  6299 
 | 
| 
 | 
  6300   if [ -z "$_nhooks" ]; then
 | 
| 
 | 
  6301     _debug "The NOTIFY_HOOK is empty, just return."
 | 
| 
 | 
  6302     return 0
 | 
| 
 | 
  6303   fi
 | 
| 
 | 
  6304 
 | 
| 
 | 
  6305   _send_err=0
 | 
| 
 | 
  6306   for _n_hook in $(echo "$_nhooks" | tr ',' " "); do
 | 
| 
 | 
  6307     _n_hook_file="$(_findHook "" $_SUB_FOLDER_NOTIFY "$_n_hook")"
 | 
| 
 | 
  6308     _info "Sending via: $_n_hook"
 | 
| 
 | 
  6309     _debug "Found $_n_hook_file for $_n_hook"
 | 
| 
 | 
  6310     if [ -z "$_n_hook_file" ]; then
 | 
| 
 | 
  6311       _err "Can not find the hook file for $_n_hook"
 | 
| 
 | 
  6312       continue
 | 
| 
 | 
  6313     fi
 | 
| 
 | 
  6314     if ! (
 | 
| 
 | 
  6315       if ! . "$_n_hook_file"; then
 | 
| 
 | 
  6316         _err "Load file $_n_hook_file error. Please check your api file and try again."
 | 
| 
 | 
  6317         return 1
 | 
| 
 | 
  6318       fi
 | 
| 
 | 
  6319 
 | 
| 
 | 
  6320       d_command="${_n_hook}_send"
 | 
| 
 | 
  6321       if ! _exists "$d_command"; then
 | 
| 
 | 
  6322         _err "It seems that your api file is not correct, it must have a function named: $d_command"
 | 
| 
 | 
  6323         return 1
 | 
| 
 | 
  6324       fi
 | 
| 
 | 
  6325 
 | 
| 
 | 
  6326       if ! $d_command "$_nsubject" "$_ncontent" "$_nerror"; then
 | 
| 
 | 
  6327         _err "Error send message by $d_command"
 | 
| 
 | 
  6328         return 1
 | 
| 
 | 
  6329       fi
 | 
| 
 | 
  6330 
 | 
| 
 | 
  6331       return 0
 | 
| 
 | 
  6332     ); then
 | 
| 
 | 
  6333       _err "Set $_n_hook_file error."
 | 
| 
 | 
  6334       _send_err=1
 | 
| 
 | 
  6335     else
 | 
| 
 | 
  6336       _info "$_n_hook $(__green Success)"
 | 
| 
 | 
  6337     fi
 | 
| 
 | 
  6338   done
 | 
| 
 | 
  6339   return $_send_err
 | 
| 
 | 
  6340 
 | 
| 
 | 
  6341 }
 | 
| 
 | 
  6342 
 | 
| 
 | 
  6343 # hook
 | 
| 
 | 
  6344 _set_notify_hook() {
 | 
| 
 | 
  6345   _nhooks="$1"
 | 
| 
 | 
  6346 
 | 
| 
 | 
  6347   _test_subject="Hello, this is a notification from $PROJECT_NAME"
 | 
| 
 | 
  6348   _test_content="If you receive this message, your notification works."
 | 
| 
 | 
  6349 
 | 
| 
 | 
  6350   _send_notify "$_test_subject" "$_test_content" "$_nhooks" 0
 | 
| 
 | 
  6351 
 | 
| 
 | 
  6352 }
 | 
| 
 | 
  6353 
 | 
| 
 | 
  6354 #[hook] [level] [mode]
 | 
| 
 | 
  6355 setnotify() {
 | 
| 
 | 
  6356   _nhook="$1"
 | 
| 
 | 
  6357   _nlevel="$2"
 | 
| 
 | 
  6358   _nmode="$3"
 | 
| 
 | 
  6359 
 | 
| 
 | 
  6360   _initpath
 | 
| 
 | 
  6361 
 | 
| 
 | 
  6362   if [ -z "$_nhook$_nlevel$_nmode" ]; then
 | 
| 
 | 
  6363     _usage "Usage: $PROJECT_ENTRY --set-notify [--notify-hook <hookname>] [--notify-level <0|1|2|3>] [--notify-mode <0|1>]"
 | 
| 
 | 
  6364     _usage "$_NOTIFY_WIKI"
 | 
| 
 | 
  6365     return 1
 | 
| 
 | 
  6366   fi
 | 
| 
 | 
  6367 
 | 
| 
 | 
  6368   if [ "$_nlevel" ]; then
 | 
| 
 | 
  6369     _info "Set notify level to: $_nlevel"
 | 
| 
 | 
  6370     export "NOTIFY_LEVEL=$_nlevel"
 | 
| 
 | 
  6371     _saveaccountconf "NOTIFY_LEVEL" "$NOTIFY_LEVEL"
 | 
| 
 | 
  6372   fi
 | 
| 
 | 
  6373 
 | 
| 
 | 
  6374   if [ "$_nmode" ]; then
 | 
| 
 | 
  6375     _info "Set notify mode to: $_nmode"
 | 
| 
 | 
  6376     export "NOTIFY_MODE=$_nmode"
 | 
| 
 | 
  6377     _saveaccountconf "NOTIFY_MODE" "$NOTIFY_MODE"
 | 
| 
 | 
  6378   fi
 | 
| 
 | 
  6379 
 | 
| 
 | 
  6380   if [ "$_nhook" ]; then
 | 
| 
 | 
  6381     _info "Set notify hook to: $_nhook"
 | 
| 
 | 
  6382     if [ "$_nhook" = "$NO_VALUE" ]; then
 | 
| 
 | 
  6383       _info "Clear notify hook"
 | 
| 
 | 
  6384       _clearaccountconf "NOTIFY_HOOK"
 | 
| 
 | 
  6385     else
 | 
| 
 | 
  6386       if _set_notify_hook "$_nhook"; then
 | 
| 
 | 
  6387         export NOTIFY_HOOK="$_nhook"
 | 
| 
 | 
  6388         _saveaccountconf "NOTIFY_HOOK" "$NOTIFY_HOOK"
 | 
| 
 | 
  6389         return 0
 | 
| 
 | 
  6390       else
 | 
| 
 | 
  6391         _err "Can not set notify hook to: $_nhook"
 | 
| 
 | 
  6392         return 1
 | 
| 
 | 
  6393       fi
 | 
| 
 | 
  6394     fi
 | 
| 
 | 
  6395   fi
 | 
| 
 | 
  6396 
 | 
| 
 | 
  6397 }
 | 
| 
 | 
  6398 
 | 
| 
 | 
  6399 showhelp() {
 | 
| 
 | 
  6400   _initpath
 | 
| 
 | 
  6401   version
 | 
| 
 | 
  6402   echo "Usage: $PROJECT_ENTRY <command> ... [parameters ...]
 | 
| 
 | 
  6403 Commands:
 | 
| 
 | 
  6404   -h, --help               Show this help message.
 | 
| 
 | 
  6405   -v, --version            Show version info.
 | 
| 
 | 
  6406   --install                Install $PROJECT_NAME to your system.
 | 
| 
 | 
  6407   --uninstall              Uninstall $PROJECT_NAME, and uninstall the cron job.
 | 
| 
 | 
  6408   --upgrade                Upgrade $PROJECT_NAME to the latest code from $PROJECT.
 | 
| 
 | 
  6409   --issue                  Issue a cert.
 | 
| 
 | 
  6410   --deploy                 Deploy the cert to your server.
 | 
| 
 | 
  6411   -i, --install-cert       Install the issued cert to apache/nginx or any other server.
 | 
| 
 | 
  6412   -r, --renew              Renew a cert.
 | 
| 
 | 
  6413   --renew-all              Renew all the certs.
 | 
| 
 | 
  6414   --revoke                 Revoke a cert.
 | 
| 
 | 
  6415   --remove                 Remove the cert from list of certs known to $PROJECT_NAME.
 | 
| 
 | 
  6416   --list                   List all the certs.
 | 
| 
 | 
  6417   --to-pkcs12              Export the certificate and key to a pfx file.
 | 
| 
 | 
  6418   --to-pkcs8               Convert to pkcs8 format.
 | 
| 
 | 
  6419   --sign-csr               Issue a cert from an existing csr.
 | 
| 
 | 
  6420   --show-csr               Show the content of a csr.
 | 
| 
 | 
  6421   -ccr, --create-csr       Create CSR, professional use.
 | 
| 
 | 
  6422   --create-domain-key      Create an domain private key, professional use.
 | 
| 
 | 
  6423   --update-account         Update account info.
 | 
| 
 | 
  6424   --register-account       Register account key.
 | 
| 
 | 
  6425   --deactivate-account     Deactivate the account.
 | 
| 
 | 
  6426   --create-account-key     Create an account private key, professional use.
 | 
| 
 | 
  6427   --install-cronjob        Install the cron job to renew certs, you don't need to call this. The 'install' command can automatically install the cron job.
 | 
| 
 | 
  6428   --uninstall-cronjob      Uninstall the cron job. The 'uninstall' command can do this automatically.
 | 
| 
 | 
  6429   --cron                   Run cron job to renew all the certs.
 | 
| 
 | 
  6430   --set-notify             Set the cron notification hook, level or mode.
 | 
| 
 | 
  6431   --deactivate             Deactivate the domain authz, professional use.
 | 
| 
 | 
  6432   --set-default-ca         Used with '--server', Set the default CA to use.
 | 
| 
 | 
  6433                            See: $_SERVER_WIKI
 | 
| 
 | 
  6434 Parameters:
 | 
| 
 | 
  6435   -d, --domain <domain.tld>         Specifies a domain, used to issue, renew or revoke etc.
 | 
| 
 | 
  6436   --challenge-alias <domain.tld>    The challenge domain alias for DNS alias mode.
 | 
| 
 | 
  6437                                     See: $_DNS_ALIAS_WIKI
 | 
| 
 | 
  6438   --domain-alias <domain.tld>       The domain alias for DNS alias mode.
 | 
| 
 | 
  6439                                     See: $_DNS_ALIAS_WIKI
 | 
| 
 | 
  6440   --preferred-chain <chain>         If the CA offers multiple certificate chains, prefer the chain with an issuer matching this Subject Common Name.
 | 
| 
 | 
  6441                                     If no match, the default offered chain will be used. (default: empty)
 | 
| 
 | 
  6442                                     See: $_PREFERRED_CHAIN_WIKI
 | 
| 
 | 
  6443   -f, --force                       Force install, force cert renewal or override sudo restrictions.
 | 
| 
 | 
  6444   --staging, --test                 Use staging server, for testing.
 | 
| 
 | 
  6445   --debug [0|1|2|3]                 Output debug info. Defaults to 1 if argument is omitted.
 | 
| 
 | 
  6446   --output-insecure                 Output all the sensitive messages.
 | 
| 
 | 
  6447                                     By default all the credentials/sensitive messages are hidden from the output/debug/log for security.
 | 
| 
 | 
  6448   -w, --webroot <directory>         Specifies the web root folder for web root mode.
 | 
| 
 | 
  6449   --standalone                      Use standalone mode.
 | 
| 
 | 
  6450   --alpn                            Use standalone alpn mode.
 | 
| 
 | 
  6451   --stateless                       Use stateless mode.
 | 
| 
 | 
  6452                                     See: $_STATELESS_WIKI
 | 
| 
 | 
  6453   --apache                          Use apache mode.
 | 
| 
 | 
  6454   --dns [dns_hook]                  Use dns manual mode or dns api. Defaults to manual mode when argument is omitted.
 | 
| 
 | 
  6455                                     See: $_DNS_API_WIKI
 | 
| 
 | 
  6456   --dnssleep <seconds>              The time in seconds to wait for all the txt records to propagate in dns api mode.
 | 
| 
 | 
  6457                                     It's not necessary to use this by default, $PROJECT_NAME polls dns status by DOH automatically.
 | 
| 
 | 
  6458   -k, --keylength <bits>            Specifies the domain key length: 2048, 3072, 4096, 8192 or ec-256, ec-384, ec-521.
 | 
| 
 | 
  6459   -ak, --accountkeylength <bits>    Specifies the account key length: 2048, 3072, 4096
 | 
| 
 | 
  6460   --log [file]                      Specifies the log file. Defaults to \"$DEFAULT_LOG_FILE\" if argument is omitted.
 | 
| 
 | 
  6461   --log-level <1|2>                 Specifies the log level, default is 1.
 | 
| 
 | 
  6462   --syslog <0|3|6|7>                Syslog level, 0: disable syslog, 3: error, 6: info, 7: debug.
 | 
| 
 | 
  6463   --eab-kid <eab_key_id>            Key Identifier for External Account Binding.
 | 
| 
 | 
  6464   --eab-hmac-key <eab_hmac_key>     HMAC key for External Account Binding.
 | 
| 
 | 
  6465   These parameters are to install the cert to nginx/apache or any other server after issue/renew a cert:
 | 
| 
 | 
  6466   --cert-file <file>                Path to copy the cert file to after issue/renew..
 | 
| 
 | 
  6467   --key-file <file>                 Path to copy the key file to after issue/renew.
 | 
| 
 | 
  6468   --ca-file <file>                  Path to copy the intermediate cert file to after issue/renew.
 | 
| 
 | 
  6469   --fullchain-file <file>           Path to copy the fullchain cert file to after issue/renew.
 | 
| 
 | 
  6470   --reloadcmd <command>             Command to execute after issue/renew to reload the server.
 | 
| 
 | 
  6471   --server <server_uri>             ACME Directory Resource URI. (default: $DEFAULT_CA)
 | 
| 
 | 
  6472                                     See: $_SERVER_WIKI
 | 
| 
 | 
  6473   --accountconf <file>              Specifies a customized account config file.
 | 
| 
 | 
  6474   --home <directory>                Specifies the home dir for $PROJECT_NAME.
 | 
| 
 | 
  6475   --cert-home <directory>           Specifies the home dir to save all the certs, only valid for '--install' command.
 | 
| 
 | 
  6476   --config-home <directory>         Specifies the home dir to save all the configurations.
 | 
| 
 | 
  6477   --useragent <string>              Specifies the user agent string. it will be saved for future use too.
 | 
| 
 | 
  6478   -m, --accountemail <email>        Specifies the account email, only valid for the '--install' and '--update-account' command.
 | 
| 
 | 
  6479   --accountkey <file>               Specifies the account key path, only valid for the '--install' command.
 | 
| 
 | 
  6480   --days <ndays>                    Specifies the days to renew the cert when using '--issue' command. The default value is $DEFAULT_RENEW days.
 | 
| 
 | 
  6481   --httpport <port>                 Specifies the standalone listening port. Only valid if the server is behind a reverse proxy or load balancer.
 | 
| 
 | 
  6482   --tlsport <port>                  Specifies the standalone tls listening port. Only valid if the server is behind a reverse proxy or load balancer.
 | 
| 
 | 
  6483   --local-address <ip>              Specifies the standalone/tls server listening address, in case you have multiple ip addresses.
 | 
| 
 | 
  6484   --listraw                         Only used for '--list' command, list the certs in raw format.
 | 
| 
 | 
  6485   -se, --stop-renew-on-error        Only valid for '--renew-all' command. Stop if one cert has error in renewal.
 | 
| 
 | 
  6486   --insecure                        Do not check the server certificate, in some devices, the api server's certificate may not be trusted.
 | 
| 
 | 
  6487   --ca-bundle <file>                Specifies the path to the CA certificate bundle to verify api server's certificate.
 | 
| 
 | 
  6488   --ca-path <directory>             Specifies directory containing CA certificates in PEM format, used by wget or curl.
 | 
| 
 | 
  6489   --nocron                          Only valid for '--install' command, which means: do not install the default cron job.
 | 
| 
 | 
  6490                                     In this case, the certs will not be renewed automatically.
 | 
| 
 | 
  6491   --noprofile                       Only valid for '--install' command, which means: do not install aliases to user profile.
 | 
| 
 | 
  6492   --no-color                        Do not output color text.
 | 
| 
 | 
  6493   --force-color                     Force output of color text. Useful for non-interactive use with the aha tool for HTML E-Mails.
 | 
| 
 | 
  6494   --ecc                             Specifies to use the ECC cert. Valid for '--install-cert', '--renew', '--revoke', '--to-pkcs12' and '--create-csr'
 | 
| 
 | 
  6495   --csr <file>                      Specifies the input csr.
 | 
| 
 | 
  6496   --pre-hook <command>              Command to be run before obtaining any certificates.
 | 
| 
 | 
  6497   --post-hook <command>             Command to be run after attempting to obtain/renew certificates. Runs regardless of whether obtain/renew succeeded or failed.
 | 
| 
 | 
  6498   --renew-hook <command>            Command to be run after each successfully renewed certificate.
 | 
| 
 | 
  6499   --deploy-hook <hookname>          The hook file to deploy cert
 | 
| 
 | 
  6500   --ocsp, --ocsp-must-staple        Generate OCSP-Must-Staple extension.
 | 
| 
 | 
  6501   --always-force-new-domain-key     Generate new domain key on renewal. Otherwise, the domain key is not changed by default.
 | 
| 
 | 
  6502   --auto-upgrade [0|1]              Valid for '--upgrade' command, indicating whether to upgrade automatically in future. Defaults to 1 if argument is omitted.
 | 
| 
 | 
  6503   --listen-v4                       Force standalone/tls server to listen at ipv4.
 | 
| 
 | 
  6504   --listen-v6                       Force standalone/tls server to listen at ipv6.
 | 
| 
 | 
  6505   --openssl-bin <file>              Specifies a custom openssl bin location.
 | 
| 
 | 
  6506   --use-wget                        Force to use wget, if you have both curl and wget installed.
 | 
| 
 | 
  6507   --yes-I-know-dns-manual-mode-enough-go-ahead-please  Force use of dns manual mode.
 | 
| 
 | 
  6508                                     See:  $_DNS_MANUAL_WIKI
 | 
| 
 | 
  6509   -b, --branch <branch>             Only valid for '--upgrade' command, specifies the branch name to upgrade to.
 | 
| 
 | 
  6510   --notify-level <0|1|2|3>          Set the notification level:  Default value is $NOTIFY_LEVEL_DEFAULT.
 | 
| 
 | 
  6511                                     0: disabled, no notification will be sent.
 | 
| 
 | 
  6512                                     1: send notifications only when there is an error.
 | 
| 
 | 
  6513                                     2: send notifications when a cert is successfully renewed, or there is an error.
 | 
| 
 | 
  6514                                     3: send notifications when a cert is skipped, renewed, or error.
 | 
| 
 | 
  6515   --notify-mode <0|1>               Set notification mode. Default value is $NOTIFY_MODE_DEFAULT.
 | 
| 
 | 
  6516                                     0: Bulk mode. Send all the domain's notifications in one message(mail).
 | 
| 
 | 
  6517                                     1: Cert mode. Send a message for every single cert.
 | 
| 
 | 
  6518   --notify-hook <hookname>          Set the notify hook
 | 
| 
 | 
  6519   --revoke-reason <0-10>            The reason for revocation, can be used in conjunction with the '--revoke' command.
 | 
| 
 | 
  6520                                     See: $_REVOKE_WIKI
 | 
| 
 | 
  6521   --password <password>             Add a password to exported pfx file. Use with --to-pkcs12.
 | 
| 
 | 
  6522 "
 | 
| 
 | 
  6523 }
 | 
| 
 | 
  6524 
 | 
| 
 | 
  6525 # nocron noprofile
 | 
| 
 | 
  6526 _installOnline() {
 | 
| 
 | 
  6527   _info "Installing from online archive."
 | 
| 
 | 
  6528   _nocron="$1"
 | 
| 
 | 
  6529   _noprofile="$2"
 | 
| 
 | 
  6530   if [ ! "$BRANCH" ]; then
 | 
| 
 | 
  6531     BRANCH="master"
 | 
| 
 | 
  6532   fi
 | 
| 
 | 
  6533 
 | 
| 
 | 
  6534   target="$PROJECT/archive/$BRANCH.tar.gz"
 | 
| 
 | 
  6535   _info "Downloading $target"
 | 
| 
 | 
  6536   localname="$BRANCH.tar.gz"
 | 
| 
 | 
  6537   if ! _get "$target" >$localname; then
 | 
| 
 | 
  6538     _err "Download error."
 | 
| 
 | 
  6539     return 1
 | 
| 
 | 
  6540   fi
 | 
| 
 | 
  6541   (
 | 
| 
 | 
  6542     _info "Extracting $localname"
 | 
| 
 | 
  6543     if ! (tar xzf $localname || gtar xzf $localname); then
 | 
| 
 | 
  6544       _err "Extraction error."
 | 
| 
 | 
  6545       exit 1
 | 
| 
 | 
  6546     fi
 | 
| 
 | 
  6547 
 | 
| 
 | 
  6548     cd "$PROJECT_NAME-$BRANCH"
 | 
| 
 | 
  6549     chmod +x $PROJECT_ENTRY
 | 
| 
 | 
  6550     if ./$PROJECT_ENTRY install "$_nocron" "" "$_noprofile"; then
 | 
| 
 | 
  6551       _info "Install success!"
 | 
| 
 | 
  6552       _initpath
 | 
| 
 | 
  6553       _saveaccountconf "UPGRADE_HASH" "$(_getUpgradeHash)"
 | 
| 
 | 
  6554     fi
 | 
| 
 | 
  6555 
 | 
| 
 | 
  6556     cd ..
 | 
| 
 | 
  6557 
 | 
| 
 | 
  6558     rm -rf "$PROJECT_NAME-$BRANCH"
 | 
| 
 | 
  6559     rm -f "$localname"
 | 
| 
 | 
  6560   )
 | 
| 
 | 
  6561 }
 | 
| 
 | 
  6562 
 | 
| 
 | 
  6563 _getRepoHash() {
 | 
| 
 | 
  6564   _hash_path=$1
 | 
| 
 | 
  6565   shift
 | 
| 
 | 
  6566   _hash_url="https://api.github.com/repos/acmesh-official/$PROJECT_NAME/git/refs/$_hash_path"
 | 
| 
 | 
  6567   _get $_hash_url | tr -d "\r\n" | tr '{},' '\n' | grep '"sha":' | cut -d '"' -f 4
 | 
| 
 | 
  6568 }
 | 
| 
 | 
  6569 
 | 
| 
 | 
  6570 _getUpgradeHash() {
 | 
| 
 | 
  6571   _b="$BRANCH"
 | 
| 
 | 
  6572   if [ -z "$_b" ]; then
 | 
| 
 | 
  6573     _b="master"
 | 
| 
 | 
  6574   fi
 | 
| 
 | 
  6575   _hash=$(_getRepoHash "heads/$_b")
 | 
| 
 | 
  6576   if [ -z "$_hash" ]; then _hash=$(_getRepoHash "tags/$_b"); fi
 | 
| 
 | 
  6577   echo $_hash
 | 
| 
 | 
  6578 }
 | 
| 
 | 
  6579 
 | 
| 
 | 
  6580 upgrade() {
 | 
| 
 | 
  6581   if (
 | 
| 
 | 
  6582     _initpath
 | 
| 
 | 
  6583     [ -z "$FORCE" ] && [ "$(_getUpgradeHash)" = "$(_readaccountconf "UPGRADE_HASH")" ] && _info "Already uptodate!" && exit 0
 | 
| 
 | 
  6584     export LE_WORKING_DIR
 | 
| 
 | 
  6585     cd "$LE_WORKING_DIR"
 | 
| 
 | 
  6586     _installOnline "nocron" "noprofile"
 | 
| 
 | 
  6587   ); then
 | 
| 
 | 
  6588     _info "Upgrade success!"
 | 
| 
 | 
  6589     exit 0
 | 
| 
 | 
  6590   else
 | 
| 
 | 
  6591     _err "Upgrade failed!"
 | 
| 
 | 
  6592     exit 1
 | 
| 
 | 
  6593   fi
 | 
| 
 | 
  6594 }
 | 
| 
 | 
  6595 
 | 
| 
 | 
  6596 _processAccountConf() {
 | 
| 
 | 
  6597   if [ "$_useragent" ]; then
 | 
| 
 | 
  6598     _saveaccountconf "USER_AGENT" "$_useragent"
 | 
| 
 | 
  6599   elif [ "$USER_AGENT" ] && [ "$USER_AGENT" != "$DEFAULT_USER_AGENT" ]; then
 | 
| 
 | 
  6600     _saveaccountconf "USER_AGENT" "$USER_AGENT"
 | 
| 
 | 
  6601   fi
 | 
| 
 | 
  6602 
 | 
| 
 | 
  6603   if [ "$_openssl_bin" ]; then
 | 
| 
 | 
  6604     _saveaccountconf "ACME_OPENSSL_BIN" "$_openssl_bin"
 | 
| 
 | 
  6605   elif [ "$ACME_OPENSSL_BIN" ] && [ "$ACME_OPENSSL_BIN" != "$DEFAULT_OPENSSL_BIN" ]; then
 | 
| 
 | 
  6606     _saveaccountconf "ACME_OPENSSL_BIN" "$ACME_OPENSSL_BIN"
 | 
| 
 | 
  6607   fi
 | 
| 
 | 
  6608 
 | 
| 
 | 
  6609   if [ "$_auto_upgrade" ]; then
 | 
| 
 | 
  6610     _saveaccountconf "AUTO_UPGRADE" "$_auto_upgrade"
 | 
| 
 | 
  6611   elif [ "$AUTO_UPGRADE" ]; then
 | 
| 
 | 
  6612     _saveaccountconf "AUTO_UPGRADE" "$AUTO_UPGRADE"
 | 
| 
 | 
  6613   fi
 | 
| 
 | 
  6614 
 | 
| 
 | 
  6615   if [ "$_use_wget" ]; then
 | 
| 
 | 
  6616     _saveaccountconf "ACME_USE_WGET" "$_use_wget"
 | 
| 
 | 
  6617   elif [ "$ACME_USE_WGET" ]; then
 | 
| 
 | 
  6618     _saveaccountconf "ACME_USE_WGET" "$ACME_USE_WGET"
 | 
| 
 | 
  6619   fi
 | 
| 
 | 
  6620 
 | 
| 
 | 
  6621 }
 | 
| 
 | 
  6622 
 | 
| 
 | 
  6623 _checkSudo() {
 | 
| 
 | 
  6624   if [ "$SUDO_GID" ] && [ "$SUDO_COMMAND" ] && [ "$SUDO_USER" ] && [ "$SUDO_UID" ]; then
 | 
| 
 | 
  6625     if [ "$SUDO_USER" = "root" ] && [ "$SUDO_UID" = "0" ]; then
 | 
| 
 | 
  6626       #it's root using sudo, no matter it's using sudo or not, just fine
 | 
| 
 | 
  6627       return 0
 | 
| 
 | 
  6628     fi
 | 
| 
 | 
  6629     if [ -n "$SUDO_COMMAND" ]; then
 | 
| 
 | 
  6630       #it's a normal user doing "sudo su", or `sudo -i` or `sudo -s`
 | 
| 
 | 
  6631       _endswith "$SUDO_COMMAND" /bin/su || grep "^$SUDO_COMMAND\$" /etc/shells >/dev/null 2>&1
 | 
| 
 | 
  6632       return $?
 | 
| 
 | 
  6633     fi
 | 
| 
 | 
  6634     #otherwise
 | 
| 
 | 
  6635     return 1
 | 
| 
 | 
  6636   fi
 | 
| 
 | 
  6637   return 0
 | 
| 
 | 
  6638 }
 | 
| 
 | 
  6639 
 | 
| 
 | 
  6640 #server
 | 
| 
 | 
  6641 _selectServer() {
 | 
| 
 | 
  6642   _server="$1"
 | 
| 
 | 
  6643   _server_lower="$(echo "$_server" | _lower_case)"
 | 
| 
 | 
  6644   _sindex=0
 | 
| 
 | 
  6645   for snames in $CA_NAMES; do
 | 
| 
 | 
  6646     snames="$(echo "$snames" | _lower_case)"
 | 
| 
 | 
  6647     _sindex="$(_math $_sindex + 1)"
 | 
| 
 | 
  6648     _debug2 "_selectServer try snames" "$snames"
 | 
| 
 | 
  6649     for sname in $(echo "$snames" | tr ',' ' '); do
 | 
| 
 | 
  6650       if [ "$_server_lower" = "$sname" ]; then
 | 
| 
 | 
  6651         _debug2 "_selectServer match $sname"
 | 
| 
 | 
  6652         _serverdir="$(_getfield "$CA_SERVERS" $_sindex)"
 | 
| 
 | 
  6653         _debug "Selected server: $_serverdir"
 | 
| 
 | 
  6654         ACME_DIRECTORY="$_serverdir"
 | 
| 
 | 
  6655         export ACME_DIRECTORY
 | 
| 
 | 
  6656         return
 | 
| 
 | 
  6657       fi
 | 
| 
 | 
  6658     done
 | 
| 
 | 
  6659   done
 | 
| 
 | 
  6660   ACME_DIRECTORY="$_server"
 | 
| 
 | 
  6661   export ACME_DIRECTORY
 | 
| 
 | 
  6662 }
 | 
| 
 | 
  6663 
 | 
| 
 | 
  6664 #url
 | 
| 
 | 
  6665 _getCAShortName() {
 | 
| 
 | 
  6666   caurl="$1"
 | 
| 
 | 
  6667   if [ -z "$caurl" ]; then
 | 
| 
 | 
  6668     caurl="$DEFAULT_CA"
 | 
| 
 | 
  6669   fi
 | 
| 
 | 
  6670   caurl_lower="$(echo $caurl | _lower_case)"
 | 
| 
 | 
  6671   _sindex=0
 | 
| 
 | 
  6672   for surl in $(echo "$CA_SERVERS" | _lower_case | tr , ' '); do
 | 
| 
 | 
  6673     _sindex="$(_math $_sindex + 1)"
 | 
| 
 | 
  6674     if [ "$caurl_lower" = "$surl" ]; then
 | 
| 
 | 
  6675       _nindex=0
 | 
| 
 | 
  6676       for snames in $CA_NAMES; do
 | 
| 
 | 
  6677         _nindex="$(_math $_nindex + 1)"
 | 
| 
 | 
  6678         if [ $_nindex -ge $_sindex ]; then
 | 
| 
 | 
  6679           _getfield "$snames" 1
 | 
| 
 | 
  6680           return
 | 
| 
 | 
  6681         fi
 | 
| 
 | 
  6682       done
 | 
| 
 | 
  6683     fi
 | 
| 
 | 
  6684   done
 | 
| 
 | 
  6685   echo "$caurl"
 | 
| 
 | 
  6686 }
 | 
| 
 | 
  6687 
 | 
| 
 | 
  6688 #set default ca to $ACME_DIRECTORY
 | 
| 
 | 
  6689 setdefaultca() {
 | 
| 
 | 
  6690   if [ -z "$ACME_DIRECTORY" ]; then
 | 
| 
 | 
  6691     _err "Please give a --server parameter."
 | 
| 
 | 
  6692     return 1
 | 
| 
 | 
  6693   fi
 | 
| 
 | 
  6694   _saveaccountconf "DEFAULT_ACME_SERVER" "$ACME_DIRECTORY"
 | 
| 
 | 
  6695   _info "Changed default CA to: $(__green "$ACME_DIRECTORY")"
 | 
| 
 | 
  6696 }
 | 
| 
 | 
  6697 
 | 
| 
 | 
  6698 _process() {
 | 
| 
 | 
  6699   _CMD=""
 | 
| 
 | 
  6700   _domain=""
 | 
| 
 | 
  6701   _altdomains="$NO_VALUE"
 | 
| 
 | 
  6702   _webroot=""
 | 
| 
 | 
  6703   _challenge_alias=""
 | 
| 
 | 
  6704   _keylength=""
 | 
| 
 | 
  6705   _accountkeylength=""
 | 
| 
 | 
  6706   _cert_file=""
 | 
| 
 | 
  6707   _key_file=""
 | 
| 
 | 
  6708   _ca_file=""
 | 
| 
 | 
  6709   _fullchain_file=""
 | 
| 
 | 
  6710   _reloadcmd=""
 | 
| 
 | 
  6711   _password=""
 | 
| 
 | 
  6712   _accountconf=""
 | 
| 
 | 
  6713   _useragent=""
 | 
| 
 | 
  6714   _accountemail=""
 | 
| 
 | 
  6715   _accountkey=""
 | 
| 
 | 
  6716   _certhome=""
 | 
| 
 | 
  6717   _confighome=""
 | 
| 
 | 
  6718   _httpport=""
 | 
| 
 | 
  6719   _tlsport=""
 | 
| 
 | 
  6720   _dnssleep=""
 | 
| 
 | 
  6721   _listraw=""
 | 
| 
 | 
  6722   _stopRenewOnError=""
 | 
| 
 | 
  6723   #_insecure=""
 | 
| 
 | 
  6724   _ca_bundle=""
 | 
| 
 | 
  6725   _ca_path=""
 | 
| 
 | 
  6726   _nocron=""
 | 
| 
 | 
  6727   _noprofile=""
 | 
| 
 | 
  6728   _ecc=""
 | 
| 
 | 
  6729   _csr=""
 | 
| 
 | 
  6730   _pre_hook=""
 | 
| 
 | 
  6731   _post_hook=""
 | 
| 
 | 
  6732   _renew_hook=""
 | 
| 
 | 
  6733   _deploy_hook=""
 | 
| 
 | 
  6734   _logfile=""
 | 
| 
 | 
  6735   _log=""
 | 
| 
 | 
  6736   _local_address=""
 | 
| 
 | 
  6737   _log_level=""
 | 
| 
 | 
  6738   _auto_upgrade=""
 | 
| 
 | 
  6739   _listen_v4=""
 | 
| 
 | 
  6740   _listen_v6=""
 | 
| 
 | 
  6741   _openssl_bin=""
 | 
| 
 | 
  6742   _syslog=""
 | 
| 
 | 
  6743   _use_wget=""
 | 
| 
 | 
  6744   _server=""
 | 
| 
 | 
  6745   _notify_hook=""
 | 
| 
 | 
  6746   _notify_level=""
 | 
| 
 | 
  6747   _notify_mode=""
 | 
| 
 | 
  6748   _revoke_reason=""
 | 
| 
 | 
  6749   _eab_kid=""
 | 
| 
 | 
  6750   _eab_hmac_key=""
 | 
| 
 | 
  6751   _preferred_chain=""
 | 
| 
 | 
  6752   while [ ${#} -gt 0 ]; do
 | 
| 
 | 
  6753     case "${1}" in
 | 
| 
 | 
  6754 
 | 
| 
 | 
  6755     --help | -h)
 | 
| 
 | 
  6756       showhelp
 | 
| 
 | 
  6757       return
 | 
| 
 | 
  6758       ;;
 | 
| 
 | 
  6759     --version | -v)
 | 
| 
 | 
  6760       version
 | 
| 
 | 
  6761       return
 | 
| 
 | 
  6762       ;;
 | 
| 
 | 
  6763     --install)
 | 
| 
 | 
  6764       _CMD="install"
 | 
| 
 | 
  6765       ;;
 | 
| 
 | 
  6766     --uninstall)
 | 
| 
 | 
  6767       _CMD="uninstall"
 | 
| 
 | 
  6768       ;;
 | 
| 
 | 
  6769     --upgrade)
 | 
| 
 | 
  6770       _CMD="upgrade"
 | 
| 
 | 
  6771       ;;
 | 
| 
 | 
  6772     --issue)
 | 
| 
 | 
  6773       _CMD="issue"
 | 
| 
 | 
  6774       ;;
 | 
| 
 | 
  6775     --deploy)
 | 
| 
 | 
  6776       _CMD="deploy"
 | 
| 
 | 
  6777       ;;
 | 
| 
 | 
  6778     --sign-csr | --signcsr)
 | 
| 
 | 
  6779       _CMD="signcsr"
 | 
| 
 | 
  6780       ;;
 | 
| 
 | 
  6781     --show-csr | --showcsr)
 | 
| 
 | 
  6782       _CMD="showcsr"
 | 
| 
 | 
  6783       ;;
 | 
| 
 | 
  6784     -i | --install-cert | --installcert)
 | 
| 
 | 
  6785       _CMD="installcert"
 | 
| 
 | 
  6786       ;;
 | 
| 
 | 
  6787     --renew | -r)
 | 
| 
 | 
  6788       _CMD="renew"
 | 
| 
 | 
  6789       ;;
 | 
| 
 | 
  6790     --renew-all | --renewAll | --renewall)
 | 
| 
 | 
  6791       _CMD="renewAll"
 | 
| 
 | 
  6792       ;;
 | 
| 
 | 
  6793     --revoke)
 | 
| 
 | 
  6794       _CMD="revoke"
 | 
| 
 | 
  6795       ;;
 | 
| 
 | 
  6796     --remove)
 | 
| 
 | 
  6797       _CMD="remove"
 | 
| 
 | 
  6798       ;;
 | 
| 
 | 
  6799     --list)
 | 
| 
 | 
  6800       _CMD="list"
 | 
| 
 | 
  6801       ;;
 | 
| 
 | 
  6802     --install-cronjob | --installcronjob)
 | 
| 
 | 
  6803       _CMD="installcronjob"
 | 
| 
 | 
  6804       ;;
 | 
| 
 | 
  6805     --uninstall-cronjob | --uninstallcronjob)
 | 
| 
 | 
  6806       _CMD="uninstallcronjob"
 | 
| 
 | 
  6807       ;;
 | 
| 
 | 
  6808     --cron)
 | 
| 
 | 
  6809       _CMD="cron"
 | 
| 
 | 
  6810       ;;
 | 
| 
 | 
  6811     --to-pkcs12 | --to-pkcs | --toPkcs)
 | 
| 
 | 
  6812       _CMD="toPkcs"
 | 
| 
 | 
  6813       ;;
 | 
| 
 | 
  6814     --to-pkcs8 | --toPkcs8)
 | 
| 
 | 
  6815       _CMD="toPkcs8"
 | 
| 
 | 
  6816       ;;
 | 
| 
 | 
  6817     --create-account-key | --createAccountKey | --createaccountkey | -cak)
 | 
| 
 | 
  6818       _CMD="createAccountKey"
 | 
| 
 | 
  6819       ;;
 | 
| 
 | 
  6820     --create-domain-key | --createDomainKey | --createdomainkey | -cdk)
 | 
| 
 | 
  6821       _CMD="createDomainKey"
 | 
| 
 | 
  6822       ;;
 | 
| 
 | 
  6823     -ccr | --create-csr | --createCSR | --createcsr)
 | 
| 
 | 
  6824       _CMD="createCSR"
 | 
| 
 | 
  6825       ;;
 | 
| 
 | 
  6826     --deactivate)
 | 
| 
 | 
  6827       _CMD="deactivate"
 | 
| 
 | 
  6828       ;;
 | 
| 
 | 
  6829     --update-account | --updateaccount)
 | 
| 
 | 
  6830       _CMD="updateaccount"
 | 
| 
 | 
  6831       ;;
 | 
| 
 | 
  6832     --register-account | --registeraccount)
 | 
| 
 | 
  6833       _CMD="registeraccount"
 | 
| 
 | 
  6834       ;;
 | 
| 
 | 
  6835     --deactivate-account)
 | 
| 
 | 
  6836       _CMD="deactivateaccount"
 | 
| 
 | 
  6837       ;;
 | 
| 
 | 
  6838     --set-notify)
 | 
| 
 | 
  6839       _CMD="setnotify"
 | 
| 
 | 
  6840       ;;
 | 
| 
 | 
  6841     --set-default-ca)
 | 
| 
 | 
  6842       _CMD="setdefaultca"
 | 
| 
 | 
  6843       ;;
 | 
| 
 | 
  6844     -d | --domain)
 | 
| 
 | 
  6845       _dvalue="$2"
 | 
| 
 | 
  6846 
 | 
| 
 | 
  6847       if [ "$_dvalue" ]; then
 | 
| 
 | 
  6848         if _startswith "$_dvalue" "-"; then
 | 
| 
 | 
  6849           _err "'$_dvalue' is not a valid domain for parameter '$1'"
 | 
| 
 | 
  6850           return 1
 | 
| 
 | 
  6851         fi
 | 
| 
 | 
  6852         if _is_idn "$_dvalue" && ! _exists idn; then
 | 
| 
 | 
  6853           _err "It seems that $_dvalue is an IDN( Internationalized Domain Names), please install 'idn' command first."
 | 
| 
 | 
  6854           return 1
 | 
| 
 | 
  6855         fi
 | 
| 
 | 
  6856 
 | 
| 
 | 
  6857         if _startswith "$_dvalue" "*."; then
 | 
| 
 | 
  6858           _debug "Wildcard domain"
 | 
| 
 | 
  6859           export ACME_VERSION=2
 | 
| 
 | 
  6860         fi
 | 
| 
 | 
  6861         if [ -z "$_domain" ]; then
 | 
| 
 | 
  6862           _domain="$_dvalue"
 | 
| 
 | 
  6863         else
 | 
| 
 | 
  6864           if [ "$_altdomains" = "$NO_VALUE" ]; then
 | 
| 
 | 
  6865             _altdomains="$_dvalue"
 | 
| 
 | 
  6866           else
 | 
| 
 | 
  6867             _altdomains="$_altdomains,$_dvalue"
 | 
| 
 | 
  6868           fi
 | 
| 
 | 
  6869         fi
 | 
| 
 | 
  6870       fi
 | 
| 
 | 
  6871 
 | 
| 
 | 
  6872       shift
 | 
| 
 | 
  6873       ;;
 | 
| 
 | 
  6874 
 | 
| 
 | 
  6875     -f | --force)
 | 
| 
 | 
  6876       FORCE="1"
 | 
| 
 | 
  6877       ;;
 | 
| 
 | 
  6878     --staging | --test)
 | 
| 
 | 
  6879       STAGE="1"
 | 
| 
 | 
  6880       ;;
 | 
| 
 | 
  6881     --server)
 | 
| 
 | 
  6882       _server="$2"
 | 
| 
 | 
  6883       _selectServer "$_server"
 | 
| 
 | 
  6884       shift
 | 
| 
 | 
  6885       ;;
 | 
| 
 | 
  6886     --debug)
 | 
| 
 | 
  6887       if [ -z "$2" ] || _startswith "$2" "-"; then
 | 
| 
 | 
  6888         DEBUG="$DEBUG_LEVEL_DEFAULT"
 | 
| 
 | 
  6889       else
 | 
| 
 | 
  6890         DEBUG="$2"
 | 
| 
 | 
  6891         shift
 | 
| 
 | 
  6892       fi
 | 
| 
 | 
  6893       ;;
 | 
| 
 | 
  6894     --output-insecure)
 | 
| 
 | 
  6895       export OUTPUT_INSECURE=1
 | 
| 
 | 
  6896       ;;
 | 
| 
 | 
  6897     -w | --webroot)
 | 
| 
 | 
  6898       wvalue="$2"
 | 
| 
 | 
  6899       if [ -z "$_webroot" ]; then
 | 
| 
 | 
  6900         _webroot="$wvalue"
 | 
| 
 | 
  6901       else
 | 
| 
 | 
  6902         _webroot="$_webroot,$wvalue"
 | 
| 
 | 
  6903       fi
 | 
| 
 | 
  6904       shift
 | 
| 
 | 
  6905       ;;
 | 
| 
 | 
  6906     --challenge-alias)
 | 
| 
 | 
  6907       cvalue="$2"
 | 
| 
 | 
  6908       _challenge_alias="$_challenge_alias$cvalue,"
 | 
| 
 | 
  6909       shift
 | 
| 
 | 
  6910       ;;
 | 
| 
 | 
  6911     --domain-alias)
 | 
| 
 | 
  6912       cvalue="$DNS_ALIAS_PREFIX$2"
 | 
| 
 | 
  6913       _challenge_alias="$_challenge_alias$cvalue,"
 | 
| 
 | 
  6914       shift
 | 
| 
 | 
  6915       ;;
 | 
| 
 | 
  6916     --standalone)
 | 
| 
 | 
  6917       wvalue="$NO_VALUE"
 | 
| 
 | 
  6918       if [ -z "$_webroot" ]; then
 | 
| 
 | 
  6919         _webroot="$wvalue"
 | 
| 
 | 
  6920       else
 | 
| 
 | 
  6921         _webroot="$_webroot,$wvalue"
 | 
| 
 | 
  6922       fi
 | 
| 
 | 
  6923       ;;
 | 
| 
 | 
  6924     --alpn)
 | 
| 
 | 
  6925       wvalue="$W_ALPN"
 | 
| 
 | 
  6926       if [ -z "$_webroot" ]; then
 | 
| 
 | 
  6927         _webroot="$wvalue"
 | 
| 
 | 
  6928       else
 | 
| 
 | 
  6929         _webroot="$_webroot,$wvalue"
 | 
| 
 | 
  6930       fi
 | 
| 
 | 
  6931       ;;
 | 
| 
 | 
  6932     --stateless)
 | 
| 
 | 
  6933       wvalue="$MODE_STATELESS"
 | 
| 
 | 
  6934       if [ -z "$_webroot" ]; then
 | 
| 
 | 
  6935         _webroot="$wvalue"
 | 
| 
 | 
  6936       else
 | 
| 
 | 
  6937         _webroot="$_webroot,$wvalue"
 | 
| 
 | 
  6938       fi
 | 
| 
 | 
  6939       ;;
 | 
| 
 | 
  6940     --local-address)
 | 
| 
 | 
  6941       lvalue="$2"
 | 
| 
 | 
  6942       _local_address="$_local_address$lvalue,"
 | 
| 
 | 
  6943       shift
 | 
| 
 | 
  6944       ;;
 | 
| 
 | 
  6945     --apache)
 | 
| 
 | 
  6946       wvalue="apache"
 | 
| 
 | 
  6947       if [ -z "$_webroot" ]; then
 | 
| 
 | 
  6948         _webroot="$wvalue"
 | 
| 
 | 
  6949       else
 | 
| 
 | 
  6950         _webroot="$_webroot,$wvalue"
 | 
| 
 | 
  6951       fi
 | 
| 
 | 
  6952       ;;
 | 
| 
 | 
  6953     --nginx)
 | 
| 
 | 
  6954       wvalue="$NGINX"
 | 
| 
 | 
  6955       if [ "$2" ] && ! _startswith "$2" "-"; then
 | 
| 
 | 
  6956         wvalue="$NGINX$2"
 | 
| 
 | 
  6957         shift
 | 
| 
 | 
  6958       fi
 | 
| 
 | 
  6959       if [ -z "$_webroot" ]; then
 | 
| 
 | 
  6960         _webroot="$wvalue"
 | 
| 
 | 
  6961       else
 | 
| 
 | 
  6962         _webroot="$_webroot,$wvalue"
 | 
| 
 | 
  6963       fi
 | 
| 
 | 
  6964       ;;
 | 
| 
 | 
  6965     --dns)
 | 
| 
 | 
  6966       wvalue="$W_DNS"
 | 
| 
 | 
  6967       if [ "$2" ] && ! _startswith "$2" "-"; then
 | 
| 
 | 
  6968         wvalue="$2"
 | 
| 
 | 
  6969         shift
 | 
| 
 | 
  6970       fi
 | 
| 
 | 
  6971       if [ -z "$_webroot" ]; then
 | 
| 
 | 
  6972         _webroot="$wvalue"
 | 
| 
 | 
  6973       else
 | 
| 
 | 
  6974         _webroot="$_webroot,$wvalue"
 | 
| 
 | 
  6975       fi
 | 
| 
 | 
  6976       ;;
 | 
| 
 | 
  6977     --dnssleep)
 | 
| 
 | 
  6978       _dnssleep="$2"
 | 
| 
 | 
  6979       Le_DNSSleep="$_dnssleep"
 | 
| 
 | 
  6980       shift
 | 
| 
 | 
  6981       ;;
 | 
| 
 | 
  6982 
 | 
| 
 | 
  6983     --keylength | -k)
 | 
| 
 | 
  6984       _keylength="$2"
 | 
| 
 | 
  6985       shift
 | 
| 
 | 
  6986       ;;
 | 
| 
 | 
  6987     -ak | --accountkeylength)
 | 
| 
 | 
  6988       _accountkeylength="$2"
 | 
| 
 | 
  6989       shift
 | 
| 
 | 
  6990       ;;
 | 
| 
 | 
  6991 
 | 
| 
 | 
  6992     --cert-file | --certpath)
 | 
| 
 | 
  6993       _cert_file="$2"
 | 
| 
 | 
  6994       shift
 | 
| 
 | 
  6995       ;;
 | 
| 
 | 
  6996     --key-file | --keypath)
 | 
| 
 | 
  6997       _key_file="$2"
 | 
| 
 | 
  6998       shift
 | 
| 
 | 
  6999       ;;
 | 
| 
 | 
  7000     --ca-file | --capath)
 | 
| 
 | 
  7001       _ca_file="$2"
 | 
| 
 | 
  7002       shift
 | 
| 
 | 
  7003       ;;
 | 
| 
 | 
  7004     --fullchain-file | --fullchainpath)
 | 
| 
 | 
  7005       _fullchain_file="$2"
 | 
| 
 | 
  7006       shift
 | 
| 
 | 
  7007       ;;
 | 
| 
 | 
  7008     --reloadcmd | --reloadCmd)
 | 
| 
 | 
  7009       _reloadcmd="$2"
 | 
| 
 | 
  7010       shift
 | 
| 
 | 
  7011       ;;
 | 
| 
 | 
  7012     --password)
 | 
| 
 | 
  7013       _password="$2"
 | 
| 
 | 
  7014       shift
 | 
| 
 | 
  7015       ;;
 | 
| 
 | 
  7016     --accountconf)
 | 
| 
 | 
  7017       _accountconf="$2"
 | 
| 
 | 
  7018       ACCOUNT_CONF_PATH="$_accountconf"
 | 
| 
 | 
  7019       shift
 | 
| 
 | 
  7020       ;;
 | 
| 
 | 
  7021     --home)
 | 
| 
 | 
  7022       LE_WORKING_DIR="$2"
 | 
| 
 | 
  7023       shift
 | 
| 
 | 
  7024       ;;
 | 
| 
 | 
  7025     --cert-home | --certhome)
 | 
| 
 | 
  7026       _certhome="$2"
 | 
| 
 | 
  7027       CERT_HOME="$_certhome"
 | 
| 
 | 
  7028       shift
 | 
| 
 | 
  7029       ;;
 | 
| 
 | 
  7030     --config-home)
 | 
| 
 | 
  7031       _confighome="$2"
 | 
| 
 | 
  7032       LE_CONFIG_HOME="$_confighome"
 | 
| 
 | 
  7033       shift
 | 
| 
 | 
  7034       ;;
 | 
| 
 | 
  7035     --useragent)
 | 
| 
 | 
  7036       _useragent="$2"
 | 
| 
 | 
  7037       USER_AGENT="$_useragent"
 | 
| 
 | 
  7038       shift
 | 
| 
 | 
  7039       ;;
 | 
| 
 | 
  7040     -m | --accountemail)
 | 
| 
 | 
  7041       _accountemail="$2"
 | 
| 
 | 
  7042       ACCOUNT_EMAIL="$_accountemail"
 | 
| 
 | 
  7043       shift
 | 
| 
 | 
  7044       ;;
 | 
| 
 | 
  7045     --accountkey)
 | 
| 
 | 
  7046       _accountkey="$2"
 | 
| 
 | 
  7047       ACCOUNT_KEY_PATH="$_accountkey"
 | 
| 
 | 
  7048       shift
 | 
| 
 | 
  7049       ;;
 | 
| 
 | 
  7050     --days)
 | 
| 
 | 
  7051       _days="$2"
 | 
| 
 | 
  7052       Le_RenewalDays="$_days"
 | 
| 
 | 
  7053       shift
 | 
| 
 | 
  7054       ;;
 | 
| 
 | 
  7055     --httpport)
 | 
| 
 | 
  7056       _httpport="$2"
 | 
| 
 | 
  7057       Le_HTTPPort="$_httpport"
 | 
| 
 | 
  7058       shift
 | 
| 
 | 
  7059       ;;
 | 
| 
 | 
  7060     --tlsport)
 | 
| 
 | 
  7061       _tlsport="$2"
 | 
| 
 | 
  7062       Le_TLSPort="$_tlsport"
 | 
| 
 | 
  7063       shift
 | 
| 
 | 
  7064       ;;
 | 
| 
 | 
  7065     --listraw)
 | 
| 
 | 
  7066       _listraw="raw"
 | 
| 
 | 
  7067       ;;
 | 
| 
 | 
  7068     -se | --stop-renew-on-error | --stopRenewOnError | --stoprenewonerror)
 | 
| 
 | 
  7069       _stopRenewOnError="1"
 | 
| 
 | 
  7070       ;;
 | 
| 
 | 
  7071     --insecure)
 | 
| 
 | 
  7072       #_insecure="1"
 | 
| 
 | 
  7073       HTTPS_INSECURE="1"
 | 
| 
 | 
  7074       ;;
 | 
| 
 | 
  7075     --ca-bundle)
 | 
| 
 | 
  7076       _ca_bundle="$(_readlink "$2")"
 | 
| 
 | 
  7077       CA_BUNDLE="$_ca_bundle"
 | 
| 
 | 
  7078       shift
 | 
| 
 | 
  7079       ;;
 | 
| 
 | 
  7080     --ca-path)
 | 
| 
 | 
  7081       _ca_path="$2"
 | 
| 
 | 
  7082       CA_PATH="$_ca_path"
 | 
| 
 | 
  7083       shift
 | 
| 
 | 
  7084       ;;
 | 
| 
 | 
  7085     --nocron)
 | 
| 
 | 
  7086       _nocron="1"
 | 
| 
 | 
  7087       ;;
 | 
| 
 | 
  7088     --noprofile)
 | 
| 
 | 
  7089       _noprofile="1"
 | 
| 
 | 
  7090       ;;
 | 
| 
 | 
  7091     --no-color)
 | 
| 
 | 
  7092       export ACME_NO_COLOR=1
 | 
| 
 | 
  7093       ;;
 | 
| 
 | 
  7094     --force-color)
 | 
| 
 | 
  7095       export ACME_FORCE_COLOR=1
 | 
| 
 | 
  7096       ;;
 | 
| 
 | 
  7097     --ecc)
 | 
| 
 | 
  7098       _ecc="isEcc"
 | 
| 
 | 
  7099       ;;
 | 
| 
 | 
  7100     --csr)
 | 
| 
 | 
  7101       _csr="$2"
 | 
| 
 | 
  7102       shift
 | 
| 
 | 
  7103       ;;
 | 
| 
 | 
  7104     --pre-hook)
 | 
| 
 | 
  7105       _pre_hook="$2"
 | 
| 
 | 
  7106       shift
 | 
| 
 | 
  7107       ;;
 | 
| 
 | 
  7108     --post-hook)
 | 
| 
 | 
  7109       _post_hook="$2"
 | 
| 
 | 
  7110       shift
 | 
| 
 | 
  7111       ;;
 | 
| 
 | 
  7112     --renew-hook)
 | 
| 
 | 
  7113       _renew_hook="$2"
 | 
| 
 | 
  7114       shift
 | 
| 
 | 
  7115       ;;
 | 
| 
 | 
  7116     --deploy-hook)
 | 
| 
 | 
  7117       if [ -z "$2" ] || _startswith "$2" "-"; then
 | 
| 
 | 
  7118         _usage "Please specify a value for '--deploy-hook'"
 | 
| 
 | 
  7119         return 1
 | 
| 
 | 
  7120       fi
 | 
| 
 | 
  7121       _deploy_hook="$_deploy_hook$2,"
 | 
| 
 | 
  7122       shift
 | 
| 
 | 
  7123       ;;
 | 
| 
 | 
  7124     --ocsp-must-staple | --ocsp)
 | 
| 
 | 
  7125       Le_OCSP_Staple="1"
 | 
| 
 | 
  7126       ;;
 | 
| 
 | 
  7127     --always-force-new-domain-key)
 | 
| 
 | 
  7128       if [ -z "$2" ] || _startswith "$2" "-"; then
 | 
| 
 | 
  7129         Le_ForceNewDomainKey=1
 | 
| 
 | 
  7130       else
 | 
| 
 | 
  7131         Le_ForceNewDomainKey="$2"
 | 
| 
 | 
  7132         shift
 | 
| 
 | 
  7133       fi
 | 
| 
 | 
  7134       ;;
 | 
| 
 | 
  7135     --yes-I-know-dns-manual-mode-enough-go-ahead-please)
 | 
| 
 | 
  7136       export FORCE_DNS_MANUAL=1
 | 
| 
 | 
  7137       ;;
 | 
| 
 | 
  7138     --log | --logfile)
 | 
| 
 | 
  7139       _log="1"
 | 
| 
 | 
  7140       _logfile="$2"
 | 
| 
 | 
  7141       if _startswith "$_logfile" '-'; then
 | 
| 
 | 
  7142         _logfile=""
 | 
| 
 | 
  7143       else
 | 
| 
 | 
  7144         shift
 | 
| 
 | 
  7145       fi
 | 
| 
 | 
  7146       LOG_FILE="$_logfile"
 | 
| 
 | 
  7147       if [ -z "$LOG_LEVEL" ]; then
 | 
| 
 | 
  7148         LOG_LEVEL="$DEFAULT_LOG_LEVEL"
 | 
| 
 | 
  7149       fi
 | 
| 
 | 
  7150       ;;
 | 
| 
 | 
  7151     --log-level)
 | 
| 
 | 
  7152       _log_level="$2"
 | 
| 
 | 
  7153       LOG_LEVEL="$_log_level"
 | 
| 
 | 
  7154       shift
 | 
| 
 | 
  7155       ;;
 | 
| 
 | 
  7156     --syslog)
 | 
| 
 | 
  7157       if ! _startswith "$2" '-'; then
 | 
| 
 | 
  7158         _syslog="$2"
 | 
| 
 | 
  7159         shift
 | 
| 
 | 
  7160       fi
 | 
| 
 | 
  7161       if [ -z "$_syslog" ]; then
 | 
| 
 | 
  7162         _syslog="$SYSLOG_LEVEL_DEFAULT"
 | 
| 
 | 
  7163       fi
 | 
| 
 | 
  7164       ;;
 | 
| 
 | 
  7165     --auto-upgrade)
 | 
| 
 | 
  7166       _auto_upgrade="$2"
 | 
| 
 | 
  7167       if [ -z "$_auto_upgrade" ] || _startswith "$_auto_upgrade" '-'; then
 | 
| 
 | 
  7168         _auto_upgrade="1"
 | 
| 
 | 
  7169       else
 | 
| 
 | 
  7170         shift
 | 
| 
 | 
  7171       fi
 | 
| 
 | 
  7172       AUTO_UPGRADE="$_auto_upgrade"
 | 
| 
 | 
  7173       ;;
 | 
| 
 | 
  7174     --listen-v4)
 | 
| 
 | 
  7175       _listen_v4="1"
 | 
| 
 | 
  7176       Le_Listen_V4="$_listen_v4"
 | 
| 
 | 
  7177       ;;
 | 
| 
 | 
  7178     --listen-v6)
 | 
| 
 | 
  7179       _listen_v6="1"
 | 
| 
 | 
  7180       Le_Listen_V6="$_listen_v6"
 | 
| 
 | 
  7181       ;;
 | 
| 
 | 
  7182     --openssl-bin)
 | 
| 
 | 
  7183       _openssl_bin="$2"
 | 
| 
 | 
  7184       ACME_OPENSSL_BIN="$_openssl_bin"
 | 
| 
 | 
  7185       shift
 | 
| 
 | 
  7186       ;;
 | 
| 
 | 
  7187     --use-wget)
 | 
| 
 | 
  7188       _use_wget="1"
 | 
| 
 | 
  7189       ACME_USE_WGET="1"
 | 
| 
 | 
  7190       ;;
 | 
| 
 | 
  7191     --branch | -b)
 | 
| 
 | 
  7192       export BRANCH="$2"
 | 
| 
 | 
  7193       shift
 | 
| 
 | 
  7194       ;;
 | 
| 
 | 
  7195     --notify-hook)
 | 
| 
 | 
  7196       _nhook="$2"
 | 
| 
 | 
  7197       if _startswith "$_nhook" "-"; then
 | 
| 
 | 
  7198         _err "'$_nhook' is not a hook name for '$1'"
 | 
| 
 | 
  7199         return 1
 | 
| 
 | 
  7200       fi
 | 
| 
 | 
  7201       if [ "$_notify_hook" ]; then
 | 
| 
 | 
  7202         _notify_hook="$_notify_hook,$_nhook"
 | 
| 
 | 
  7203       else
 | 
| 
 | 
  7204         _notify_hook="$_nhook"
 | 
| 
 | 
  7205       fi
 | 
| 
 | 
  7206       shift
 | 
| 
 | 
  7207       ;;
 | 
| 
 | 
  7208     --notify-level)
 | 
| 
 | 
  7209       _nlevel="$2"
 | 
| 
 | 
  7210       if _startswith "$_nlevel" "-"; then
 | 
| 
 | 
  7211         _err "'$_nlevel' is not a integer for '$1'"
 | 
| 
 | 
  7212         return 1
 | 
| 
 | 
  7213       fi
 | 
| 
 | 
  7214       _notify_level="$_nlevel"
 | 
| 
 | 
  7215       shift
 | 
| 
 | 
  7216       ;;
 | 
| 
 | 
  7217     --notify-mode)
 | 
| 
 | 
  7218       _nmode="$2"
 | 
| 
 | 
  7219       if _startswith "$_nmode" "-"; then
 | 
| 
 | 
  7220         _err "'$_nmode' is not a integer for '$1'"
 | 
| 
 | 
  7221         return 1
 | 
| 
 | 
  7222       fi
 | 
| 
 | 
  7223       _notify_mode="$_nmode"
 | 
| 
 | 
  7224       shift
 | 
| 
 | 
  7225       ;;
 | 
| 
 | 
  7226     --revoke-reason)
 | 
| 
 | 
  7227       _revoke_reason="$2"
 | 
| 
 | 
  7228       if _startswith "$_revoke_reason" "-"; then
 | 
| 
 | 
  7229         _err "'$_revoke_reason' is not a integer for '$1'"
 | 
| 
 | 
  7230         return 1
 | 
| 
 | 
  7231       fi
 | 
| 
 | 
  7232       shift
 | 
| 
 | 
  7233       ;;
 | 
| 
 | 
  7234     --eab-kid)
 | 
| 
 | 
  7235       _eab_kid="$2"
 | 
| 
 | 
  7236       shift
 | 
| 
 | 
  7237       ;;
 | 
| 
 | 
  7238     --eab-hmac-key)
 | 
| 
 | 
  7239       _eab_hmac_key="$2"
 | 
| 
 | 
  7240       shift
 | 
| 
 | 
  7241       ;;
 | 
| 
 | 
  7242     --preferred-chain)
 | 
| 
 | 
  7243       _preferred_chain="$2"
 | 
| 
 | 
  7244       shift
 | 
| 
 | 
  7245       ;;
 | 
| 
 | 
  7246     *)
 | 
| 
 | 
  7247       _err "Unknown parameter : $1"
 | 
| 
 | 
  7248       return 1
 | 
| 
 | 
  7249       ;;
 | 
| 
 | 
  7250     esac
 | 
| 
 | 
  7251 
 | 
| 
 | 
  7252     shift 1
 | 
| 
 | 
  7253   done
 | 
| 
 | 
  7254 
 | 
| 
 | 
  7255   if [ "${_CMD}" != "install" ]; then
 | 
| 
 | 
  7256     if [ "$__INTERACTIVE" ] && ! _checkSudo; then
 | 
| 
 | 
  7257       if [ -z "$FORCE" ]; then
 | 
| 
 | 
  7258         #Use "echo" here, instead of _info. it's too early
 | 
| 
 | 
  7259         echo "It seems that you are using sudo, please read this link first:"
 | 
| 
 | 
  7260         echo "$_SUDO_WIKI"
 | 
| 
 | 
  7261         return 1
 | 
| 
 | 
  7262       fi
 | 
| 
 | 
  7263     fi
 | 
| 
 | 
  7264     __initHome
 | 
| 
 | 
  7265     if [ "$_log" ]; then
 | 
| 
 | 
  7266       if [ -z "$_logfile" ]; then
 | 
| 
 | 
  7267         _logfile="$DEFAULT_LOG_FILE"
 | 
| 
 | 
  7268       fi
 | 
| 
 | 
  7269     fi
 | 
| 
 | 
  7270     if [ "$_logfile" ]; then
 | 
| 
 | 
  7271       _saveaccountconf "LOG_FILE" "$_logfile"
 | 
| 
 | 
  7272       LOG_FILE="$_logfile"
 | 
| 
 | 
  7273     fi
 | 
| 
 | 
  7274 
 | 
| 
 | 
  7275     if [ "$_log_level" ]; then
 | 
| 
 | 
  7276       _saveaccountconf "LOG_LEVEL" "$_log_level"
 | 
| 
 | 
  7277       LOG_LEVEL="$_log_level"
 | 
| 
 | 
  7278     fi
 | 
| 
 | 
  7279 
 | 
| 
 | 
  7280     if [ "$_syslog" ]; then
 | 
| 
 | 
  7281       if _exists logger; then
 | 
| 
 | 
  7282         if [ "$_syslog" = "0" ]; then
 | 
| 
 | 
  7283           _clearaccountconf "SYS_LOG"
 | 
| 
 | 
  7284         else
 | 
| 
 | 
  7285           _saveaccountconf "SYS_LOG" "$_syslog"
 | 
| 
 | 
  7286         fi
 | 
| 
 | 
  7287         SYS_LOG="$_syslog"
 | 
| 
 | 
  7288       else
 | 
| 
 | 
  7289         _err "The 'logger' command is not found, can not enable syslog."
 | 
| 
 | 
  7290         _clearaccountconf "SYS_LOG"
 | 
| 
 | 
  7291         SYS_LOG=""
 | 
| 
 | 
  7292       fi
 | 
| 
 | 
  7293     fi
 | 
| 
 | 
  7294 
 | 
| 
 | 
  7295     _processAccountConf
 | 
| 
 | 
  7296   fi
 | 
| 
 | 
  7297 
 | 
| 
 | 
  7298   _debug2 LE_WORKING_DIR "$LE_WORKING_DIR"
 | 
| 
 | 
  7299 
 | 
| 
 | 
  7300   if [ "$DEBUG" ]; then
 | 
| 
 | 
  7301     version
 | 
| 
 | 
  7302     if [ "$_server" ]; then
 | 
| 
 | 
  7303       _debug "Using server: $_server"
 | 
| 
 | 
  7304     fi
 | 
| 
 | 
  7305   fi
 | 
| 
 | 
  7306   _debug "Running cmd: ${_CMD}"
 | 
| 
 | 
  7307   case "${_CMD}" in
 | 
| 
 | 
  7308   install) install "$_nocron" "$_confighome" "$_noprofile" ;;
 | 
| 
 | 
  7309   uninstall) uninstall "$_nocron" ;;
 | 
| 
 | 
  7310   upgrade) upgrade ;;
 | 
| 
 | 
  7311   issue)
 | 
| 
 | 
  7312     issue "$_webroot" "$_domain" "$_altdomains" "$_keylength" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" "$_preferred_chain"
 | 
| 
 | 
  7313     ;;
 | 
| 
 | 
  7314   deploy)
 | 
| 
 | 
  7315     deploy "$_domain" "$_deploy_hook" "$_ecc"
 | 
| 
 | 
  7316     ;;
 | 
| 
 | 
  7317   signcsr)
 | 
| 
 | 
  7318     signcsr "$_csr" "$_webroot" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias"
 | 
| 
 | 
  7319     ;;
 | 
| 
 | 
  7320   showcsr)
 | 
| 
 | 
  7321     showcsr "$_csr" "$_domain"
 | 
| 
 | 
  7322     ;;
 | 
| 
 | 
  7323   installcert)
 | 
| 
 | 
  7324     installcert "$_domain" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_ecc"
 | 
| 
 | 
  7325     ;;
 | 
| 
 | 
  7326   renew)
 | 
| 
 | 
  7327     renew "$_domain" "$_ecc"
 | 
| 
 | 
  7328     ;;
 | 
| 
 | 
  7329   renewAll)
 | 
| 
 | 
  7330     renewAll "$_stopRenewOnError"
 | 
| 
 | 
  7331     ;;
 | 
| 
 | 
  7332   revoke)
 | 
| 
 | 
  7333     revoke "$_domain" "$_ecc" "$_revoke_reason"
 | 
| 
 | 
  7334     ;;
 | 
| 
 | 
  7335   remove)
 | 
| 
 | 
  7336     remove "$_domain" "$_ecc"
 | 
| 
 | 
  7337     ;;
 | 
| 
 | 
  7338   deactivate)
 | 
| 
 | 
  7339     deactivate "$_domain,$_altdomains"
 | 
| 
 | 
  7340     ;;
 | 
| 
 | 
  7341   registeraccount)
 | 
| 
 | 
  7342     registeraccount "$_accountkeylength" "$_eab_kid" "$_eab_hmac_key"
 | 
| 
 | 
  7343     ;;
 | 
| 
 | 
  7344   updateaccount)
 | 
| 
 | 
  7345     updateaccount
 | 
| 
 | 
  7346     ;;
 | 
| 
 | 
  7347   deactivateaccount)
 | 
| 
 | 
  7348     deactivateaccount
 | 
| 
 | 
  7349     ;;
 | 
| 
 | 
  7350   list)
 | 
| 
 | 
  7351     list "$_listraw" "$_domain"
 | 
| 
 | 
  7352     ;;
 | 
| 
 | 
  7353   installcronjob) installcronjob "$_confighome" ;;
 | 
| 
 | 
  7354   uninstallcronjob) uninstallcronjob ;;
 | 
| 
 | 
  7355   cron) cron ;;
 | 
| 
 | 
  7356   toPkcs)
 | 
| 
 | 
  7357     toPkcs "$_domain" "$_password" "$_ecc"
 | 
| 
 | 
  7358     ;;
 | 
| 
 | 
  7359   toPkcs8)
 | 
| 
 | 
  7360     toPkcs8 "$_domain" "$_ecc"
 | 
| 
 | 
  7361     ;;
 | 
| 
 | 
  7362   createAccountKey)
 | 
| 
 | 
  7363     createAccountKey "$_accountkeylength"
 | 
| 
 | 
  7364     ;;
 | 
| 
 | 
  7365   createDomainKey)
 | 
| 
 | 
  7366     createDomainKey "$_domain" "$_keylength"
 | 
| 
 | 
  7367     ;;
 | 
| 
 | 
  7368   createCSR)
 | 
| 
 | 
  7369     createCSR "$_domain" "$_altdomains" "$_ecc"
 | 
| 
 | 
  7370     ;;
 | 
| 
 | 
  7371   setnotify)
 | 
| 
 | 
  7372     setnotify "$_notify_hook" "$_notify_level" "$_notify_mode"
 | 
| 
 | 
  7373     ;;
 | 
| 
 | 
  7374   setdefaultca)
 | 
| 
 | 
  7375     setdefaultca
 | 
| 
 | 
  7376     ;;
 | 
| 
 | 
  7377   *)
 | 
| 
 | 
  7378     if [ "$_CMD" ]; then
 | 
| 
 | 
  7379       _err "Invalid command: $_CMD"
 | 
| 
 | 
  7380     fi
 | 
| 
 | 
  7381     showhelp
 | 
| 
 | 
  7382     return 1
 | 
| 
 | 
  7383     ;;
 | 
| 
 | 
  7384   esac
 | 
| 
 | 
  7385   _ret="$?"
 | 
| 
 | 
  7386   if [ "$_ret" != "0" ]; then
 | 
| 
 | 
  7387     return $_ret
 | 
| 
 | 
  7388   fi
 | 
| 
 | 
  7389 
 | 
| 
 | 
  7390   if [ "${_CMD}" = "install" ]; then
 | 
| 
 | 
  7391     if [ "$_log" ]; then
 | 
| 
 | 
  7392       if [ -z "$LOG_FILE" ]; then
 | 
| 
 | 
  7393         LOG_FILE="$DEFAULT_LOG_FILE"
 | 
| 
 | 
  7394       fi
 | 
| 
 | 
  7395       _saveaccountconf "LOG_FILE" "$LOG_FILE"
 | 
| 
 | 
  7396     fi
 | 
| 
 | 
  7397 
 | 
| 
 | 
  7398     if [ "$_log_level" ]; then
 | 
| 
 | 
  7399       _saveaccountconf "LOG_LEVEL" "$_log_level"
 | 
| 
 | 
  7400     fi
 | 
| 
 | 
  7401 
 | 
| 
 | 
  7402     if [ "$_syslog" ]; then
 | 
| 
 | 
  7403       if _exists logger; then
 | 
| 
 | 
  7404         if [ "$_syslog" = "0" ]; then
 | 
| 
 | 
  7405           _clearaccountconf "SYS_LOG"
 | 
| 
 | 
  7406         else
 | 
| 
 | 
  7407           _saveaccountconf "SYS_LOG" "$_syslog"
 | 
| 
 | 
  7408         fi
 | 
| 
 | 
  7409       else
 | 
| 
 | 
  7410         _err "The 'logger' command is not found, can not enable syslog."
 | 
| 
 | 
  7411         _clearaccountconf "SYS_LOG"
 | 
| 
 | 
  7412         SYS_LOG=""
 | 
| 
 | 
  7413       fi
 | 
| 
 | 
  7414     fi
 | 
| 
 | 
  7415 
 | 
| 
 | 
  7416     _processAccountConf
 | 
| 
 | 
  7417   fi
 | 
| 
 | 
  7418 
 | 
| 
 | 
  7419 }
 | 
| 
 | 
  7420 
 | 
| 
 | 
  7421 if [ "$INSTALLONLINE" ]; then
 | 
| 
 | 
  7422   INSTALLONLINE=""
 | 
| 
 | 
  7423   _installOnline
 | 
| 
 | 
  7424   exit
 | 
| 
 | 
  7425 fi
 | 
| 
 | 
  7426 
 | 
| 
 | 
  7427 main() {
 | 
| 
 | 
  7428   [ -z "$1" ] && showhelp && return
 | 
| 
 | 
  7429   if _startswith "$1" '-'; then _process "$@"; else "$@"; fi
 | 
| 
 | 
  7430 }
 | 
| 
 | 
  7431 
 | 
| 
 | 
  7432 main "$@"
 |