From a63b05a9e761eb7d89811be4b714d818dd7c76c0 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 9 Apr 2016 23:40:59 +0800 Subject: [PATCH] le.sh v2.0.0 1. Unix-like command api 2. 100% compatible with le.sh 1.x command api. 3. Support different webroot for each domain in the same cert. ``` le.sh --issue -d a.com -w /wwwroot/a.com -d b.com -w /wwwroot/b.com ``` 4. Support different authentication methods for each domain in the same cert. Hybrid usage: ``` le.sh --issue -d a.com -w /wwwroot/a.com -d b.com -dns dns-cf ``` 5. Two different debug levels to provide useful debug info. `--debug` or `--debug 2` 6. Support to install `fullchain.cer` after renewal. 7. Better performance. --- README.md | 134 ++++---- dnsapi/dns-cf.sh | 32 +- dnsapi/dns-cx.sh | 32 +- dnsapi/dns-dp.sh | 34 +- dnsapi/dns-myapi.sh | 45 +-- le.sh | 814 ++++++++++++++++++++++++++++++-------------- 6 files changed, 654 insertions(+), 437 deletions(-) diff --git a/README.md b/README.md index a9f5966a..e8d18386 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ Clone this project: ``` git clone https://github.com/Neilpang/le.git cd le -./le.sh install +./le.sh --install ``` You don't have to be root then, although it is recommended. @@ -78,76 +78,73 @@ Show help message: ``` root@v1:~# le.sh https://github.com/Neilpang/le -v1.2.3 -Usage: le.sh [command] ...[args].... -Available commands: +v2.0.0 +Usage: le.sh command ...[parameters].... +Commands: + --help, -h Show this help message. + --version, -v Show version info. + --install Install le.sh to your system. + --uninstall Uninstall le.sh, and uninstall the cron job. + --issue Issue a cert. + --installcert Install the issued cert to apache/nginx or any other server. + --renew, -r Renew a cert. + --renewAll Renew all the certs + --revoke Revoke a cert. + --installcronjob Install the cron job to renew certs, you don't need to call this. The 'install' command can automatically install the cron job. + --uninstallcronjob Uninstall the cron job. The 'uninstall' command can do this automatically. + --cron Run cron job to renew all the certs. + --toPkcs Export the certificate and key to a pfx file. + --createAccountKey, -cak Create an account private key, professional use. + --createDomainKey, -cdk Create an domain private key, professional use. + --createCSR, -ccsr Create CSR , professional use. -install: - Install le.sh to your system. -issue: - Issue a cert. -installcert: - Install the issued cert to apache/nginx or any other server. -renew: - Renew a cert. -renewAll: - Renew all the certs. -uninstall: - Uninstall le.sh, and uninstall the cron job. -revoke: - Revoke a cert. -version: - Show version info. -installcronjob: - Install the cron job to renew certs, you don't need to call this. The 'install' command can automatically install the cron job. -uninstallcronjob: - Uninstall the cron job. The 'uninstall' command can do this automatically. -toPkcs: - Export the certificate and key to a pfx file. -createAccountKey: - Create an account private key, professional use. -createDomainKey: - Create an domain private key, professional use. -createCSR: - Create CSR , professional use. +Parameters: + --domain, -d domain.tld Specifies a domain, used to issue, renew or revoke etc. + --force, -f Used to force to install or force to renew a cert immediately. + --staging, --test Use staging server, just for test. + --debug Output debug info. + --webroot, -w /path/to/webroot Specifies the web root folder for web root mode. + --standalone Use standalone mode. + --apache Use apache mode. + --dns [dns-cf|dns-dp|dns-cx|/path/to/api/file] Use dns mode or dns api. + --keylength, -k [2048] Specifies the domain key length: 2048, 3072, 4096, 8192 or ec-256, ec-384. + --accountkeylength, -ak [2048] Specifies the account key length. + These parameters are to install the cert to nginx/apache or anyother server after issue/renew a cert: -root@v1:~/le# le issue -Usage: le issue webroot|no|apache|dns a.com [www.a.com,b.com,c.com]|no [key-length]|no + --certpath /path/to/real/cert/file After issue/renew, the cert will be copied to this path. + --keypath /path/to/real/key/file After issue/renew, the key will be copied to this path. + --capath /path/to/real/ca/file After issue/renew, the intermediate cert will be copied to this path. + --fullchainpath /path/to/fullchain/file After issue/renew, the fullchain cert will be copied to this path. + + --reloadcmd "service nginx reload" After issue/renew, it's used to reload the server. + + --accountconf Specifies a customized account config file. + --leworkingdir Specifies the home dir for le.sh ``` - -Set the param value to "no" means you want to ignore it. - -For example, if you give "no" to "key-length", it will use default length 2048. - -And if you give 'no' to 'cert-file-path', it will not copy the issued cert to the "cert-file-path". - -In all the cases, the issued cert will be placed in "~/.le/domain.com/" - # Just issue a cert: Example 1: Only one domain: ``` -le issue /home/wwwroot/aa.com aa.com +le --issue -d aa.com -w /home/wwwroot/aa.com ``` Example 2: Multiple domains in the same cert: ``` -le issue /home/wwwroot/aa.com aa.com www.aa.com,cp.aa.com +le --issue -d aa.com -d www.aa.com -d cp.aa.com -w /home/wwwroot/aa.com ``` -First argument `/home/wwwroot/aa.com` is the web root folder, You must have `write` access to this folder. +The parameter `/home/wwwroot/aa.com` is the web root folder, You must have `write` access to this folder. Second argument "aa.com" is the main domain you want to issue cert for. - -Third argument is the additional domain list you want to use. Comma separated list, which is Optional. +You must have at least domain there. You must point and bind all the domains to the same webroot dir:`/home/wwwroot/aa.com` @@ -155,41 +152,60 @@ The cert will be placed in `~/.le/aa.com/` The issued cert will be renewed every 80 days automatically. + +More examples: https://github.com/Neilpang/le/wiki/How-to-issue-a-cert + + # Install issued cert to apache/nginx etc. +After you issue a cert, you probably want to install the cert to you nginx/apache or other servers to use. + ``` -le installcert aa.com /path/to/certfile/in/apache/nginx /path/to/keyfile/in/apache/nginx /path/to/ca/certfile/apache/nginx "service apache2|nginx reload" +le --installcert -d aa.com \ +--certpath /path/to/certfile/in/apache/nginx \ +--keypath /path/to/keyfile/in/apache/nginx \ +--capath /path/to/ca/certfile/apache/nginx \ +--fullchainpath path/to/fullchain/certfile/apache/nginx \ +--reloadcmd "service apache2|nginx reload" ``` +Only the domain is required, all the other parameters are optional. + Install the issued cert/key to the production apache or nginx path. The cert will be renewed every 80 days by default (which is configurable), Once the cert is renewed, the apache/nginx will be automatically reloaded by the command: `service apache2 reload` or `service nginx reload` -# Use Standalone server to issue cert (requires you be root/sudoer, or you have permission to listen tcp 80 port): +# Use Standalone server to issue cert +(requires you be root/sudoer, or you have permission to listen tcp 80 port): Same usage as all above, just give `no` as the webroot. The tcp `80` port must be free to listen, otherwise you will be prompted to free the `80` port and try again. ``` -le issue no aa.com www.aa.com,cp.aa.com +le --issue --standalone -d aa.com -d www.aa.com -d cp.aa.com ``` -# Use Apache mode (requires you be root/sudoer, since it is required to interact with apache server): +More examples: https://github.com/Neilpang/le/wiki/How-to-issue-a-cert + + +# Use Apache mode +(requires you be root/sudoer, since it is required to interact with apache server): If you are running a web server, apache or nginx, it is recommended to use the Webroot mode. Particularly, if you are running an apache server, you can use apache mode instead. Which doesn't write any file to your web root folder. Just set string "apache" to the first argument, it will use apache plugin automatically. ``` -le issue apache aa.com www.aa.com,user.aa.com +le --issue --apache -d aa.com -d www.aa.com -d user.aa.com ``` -All the other arguments are the same with previous. + +More examples: https://github.com/Neilpang/le/wiki/How-to-issue-a-cert # Use DNS mode: -Support the latest dns-01 challenge. +Support the dns-01 challenge. ``` -le issue dns aa.com www.aa.com,user.aa.com +le --issue --dns -d aa.com -d www.aa.com -d user.aa.com ``` You will get the output like bellow: @@ -208,7 +224,7 @@ Please add those txt records to the domains. Waiting for the dns to take effect. Then just retry with 'renew' command: ``` -le renew aa.com +le --renew -d aa.com ``` Ok, it's finished. @@ -242,12 +258,12 @@ For example: Single domain: ``` -le issue /home/wwwroot/aa.com aa.com no ec-256 +le --issue -w /home/wwwroot/aa.com -d aa.com --keylength ec-256 ``` SAN multiple domains: ``` -le issue /home/wwwroot/aa.com aa.com www.aa.com,cp.aa.com ec-256 +le --issue -w /home/wwwroot/aa.com -d aa.com -d www.aa.com --keylength ec-256 ``` Please look at the last parameter above. diff --git a/dnsapi/dns-cf.sh b/dnsapi/dns-cf.sh index 159969d2..dc56bf13 100755 --- a/dnsapi/dns-cf.sh +++ b/dnsapi/dns-cf.sh @@ -134,38 +134,8 @@ _cf_rest() { _err "error $ep" return 1 fi - _debug response "$response" + _debug2 response "$response" return 0 } -_debug() { - - if [ -z "$DEBUG" ] ; then - return - fi - - if [ -z "$2" ] ; then - echo $1 - else - echo "$1"="$2" - fi -} - -_info() { - if [ -z "$2" ] ; then - echo "$1" - else - echo "$1"="$2" - fi -} - -_err() { - if [ -z "$2" ] ; then - echo "$1" >&2 - else - echo "$1"="$2" >&2 - fi -} - - diff --git a/dnsapi/dns-cx.sh b/dnsapi/dns-cx.sh index 07c9cf08..2a455a32 100644 --- a/dnsapi/dns-cx.sh +++ b/dnsapi/dns-cx.sh @@ -194,7 +194,7 @@ _rest() { _err "error $ep" return 1 fi - _debug response "$response" + _debug2 response "$response" if ! printf "$response" | grep '"message":"success"' > /dev/null ; then return 1 fi @@ -202,33 +202,3 @@ _rest() { } -_debug() { - - if [ -z "$DEBUG" ] ; then - return - fi - - if [ -z "$2" ] ; then - echo $1 - else - echo "$1"="$2" - fi -} - -_info() { - if [ -z "$2" ] ; then - echo "$1" - else - echo "$1"="$2" - fi -} - -_err() { - if [ -z "$2" ] ; then - echo "$1" >&2 - else - echo "$1"="$2" >&2 - fi -} - - diff --git a/dnsapi/dns-dp.sh b/dnsapi/dns-dp.sh index b39e3c40..f58b9d3a 100644 --- a/dnsapi/dns-dp.sh +++ b/dnsapi/dns-dp.sh @@ -182,7 +182,7 @@ _rest() { if [ "$3" ] ; then data="$3" - _debug data "$data" + _debug2 data "$data" response="$(curl --silent -X $m "$url" -d $data)" else response="$(curl --silent -X $m "$url" )" @@ -192,38 +192,8 @@ _rest() { _err "error $ep" return 1 fi - _debug response "$response" + _debug2 response "$response" return 0 } -_debug() { - - if [ -z "$DEBUG" ] ; then - return - fi - - if [ -z "$2" ] ; then - echo $1 - else - echo "$1"="$2" - fi -} - -_info() { - if [ -z "$2" ] ; then - echo "$1" - else - echo "$1"="$2" - fi -} - -_err() { - if [ -z "$2" ] ; then - echo "$1" >&2 - else - echo "$1"="$2" >&2 - fi -} - - diff --git a/dnsapi/dns-myapi.sh b/dnsapi/dns-myapi.sh index af7dda7a..9d53c7f7 100644 --- a/dnsapi/dns-myapi.sh +++ b/dnsapi/dns-myapi.sh @@ -25,37 +25,38 @@ dns-myapi-add() { - #################### Private functions bellow ################################## - -_debug() { - - if [ -z "$DEBUG" ] ; then - return - fi - - if [ -z "$2" ] ; then - echo $1 - else - echo "$1"="$2" - fi -} - _info() { - if [ -z "$2" ] ; then - echo "$1" + if [[ -z "$2" ]] ; then + echo "[$(date)] $1" else - echo "$1"="$2" + echo "[$(date)] $1"="'$2'" fi } _err() { - if [ -z "$2" ] ; then - echo "$1" >&2 - else - echo "$1"="$2" >&2 + _info "$@" >&2 + return 1 +} + +_debug() { + if [[ -z "$DEBUG" ]] ; then + return fi + _err "$@" + return 0 +} + +_debug2() { + if [[ "$DEBUG" -ge "2" ]] ; then + _debug "$@" + fi + return } + + +#################### Private functions bellow ################################## + diff --git a/le.sh b/le.sh index c1fa62f2..afd7a110 100755 --- a/le.sh +++ b/le.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -VER=1.2.3 +VER=2.0.0 PROJECT="https://github.com/Neilpang/le" DEFAULT_CA="https://acme-v01.api.letsencrypt.org" @@ -18,45 +18,48 @@ END_CSR="-----END CERTIFICATE REQUEST-----" BEGIN_CERT="-----BEGIN CERTIFICATE-----" END_CERT="-----END CERTIFICATE-----" -if [ -z "$AGREEMENT" ] ; then +if [[ -z "$AGREEMENT" ]] ; then AGREEMENT="$DEFAULT_AGREEMENT" fi _info() { - if [ -z "$2" ] ; then - echo "$1" + if [[ -z "$2" ]] ; then + echo "[$(date)] $1" else - echo "$1"="$2" + echo "[$(date)] $1"="'$2'" fi } _err() { - if [ -z "$2" ] ; then - echo "$1" >&2 - else - echo "$1"="'$2'" >&2 - fi + _info "$@" >&2 return 1 } _debug() { - if [ -z "$DEBUG" ] ; then + if [[ -z "$DEBUG" ]] ; then return fi - _err "$1" "$2" + _err "$@" return 0 } +_debug2() { + if [[ "$DEBUG" -ge "2" ]] ; then + _debug "$@" + fi + return +} + _exists() { cmd="$1" - if [ -z "$cmd" ] ; then + if [[ -z "$cmd" ]] ; then _err "Usage: _exists cmd" return 1 fi command -v $cmd >/dev/null 2>&1 ret="$?" - _debug "$cmd exists=$ret" + _debug2 "$cmd exists=$ret" return $ret } @@ -66,7 +69,7 @@ _h2b() { j=2 while [ '1' ] ; do h=$(printf $hex | cut -c $i-$j) - if [ -z "$h" ] ; then + if [[ -z "$h" ]] ; then break; fi printf "\x$h" @@ -79,7 +82,7 @@ _h2b() { _sed_i() { options="$1" filename="$2" - if [ -z "$filename" ] ; then + if [[ -z "$filename" ]] ; then _err "Usage:_sed_i options filename" return 1 fi @@ -99,13 +102,13 @@ _getfile() { filename="$1" startline="$2" endline="$3" - if [ -z "$endline" ] ; then + if [[ -z "$endline" ]] ; then _err "Usage: file startline endline" return 1 fi i="$(grep -n -- "$startline" $filename | cut -d : -f 1)" - if [ -z "$i" ] ; then + if [[ -z "$i" ]] ; then _err "Can not find start line: $startline" return 1 fi @@ -113,7 +116,7 @@ _getfile() { _debug i $i j="$(grep -n -- "$endline" $filename | cut -d : -f 1)" - if [ -z "$j" ] ; then + if [[ -z "$j" ]] ; then _err "Can not find end line: $endline" return 1 fi @@ -126,7 +129,7 @@ _getfile() { #Usage: multiline _base64() { - if [ "$1" ] ; then + if [[ "$1" ]] ; then openssl base64 -e else openssl base64 -e | tr -d '\r\n' @@ -135,7 +138,7 @@ _base64() { #Usage: multiline _dbase64() { - if [ "$1" ] ; then + if [[ "$1" ]] ; then openssl base64 -d -A else openssl base64 -d @@ -146,12 +149,12 @@ _dbase64() { #Output Base64-encoded digest _digest() { alg="$1" - if [ -z "$alg" ] ; then + if [[ -z "$alg" ]] ; then _err "Usage: _digest hashalg" return 1 fi - if [ "$alg" == "sha256" ] ; then + if [[ "$alg" == "sha256" ]] ; then openssl dgst -sha256 -binary | _base64 else _err "$alg is not supported yet" @@ -165,12 +168,12 @@ _digest() { _sign() { keyfile="$1" alg="$2" - if [ -z "$alg" ] ; then + if [[ -z "$alg" ]] ; then _err "Usage: _sign keyfile hashalg" return 1 fi - if [ "$alg" == "sha256" ] ; then + if [[ "$alg" == "sha256" ]] ; then openssl dgst -sha256 -sign "$keyfile" | _base64 else _err "$alg is not supported yet" @@ -210,7 +213,7 @@ toPkcs() { domain="$1" pfxPassword="$2" if [[ -z "$domain" ]] ; then - _err "Usage: toPkcs domain [pfx-password]" + echo "Usage: le.sh --toPkcs -d domain [--password pfx-password]" return 1 fi @@ -231,8 +234,8 @@ toPkcs() { #domain [2048] createAccountKey() { _info "Creating account key" - if [ -z "$1" ] ; then - echo Usage: createAccountKey account-domain [2048] + if [[ -z "$1" ]] ; then + echo Usage: le.sh --createAccountKey -d domain.com [--accountkeylength 2048] return fi @@ -243,13 +246,13 @@ createAccountKey() { length=2048 fi - if [ -z "$2" ] ; then + if [[ -z "$2" ]] ; then _info "Use default length 2048" length=2048 fi _initpath - if [ -f "$ACCOUNT_KEY_PATH" ] ; then + if [[ -f "$ACCOUNT_KEY_PATH" ]] ; then _info "Account key exists, skip" return else @@ -262,8 +265,8 @@ createAccountKey() { #domain length createDomainKey() { _info "Creating domain key" - if [ -z "$1" ] ; then - echo Usage: createDomainKey domain [2048] + if [[ -z "$1" ]] ; then + echo Usage: le.sh --createDomainKey -d domain.com [ --keylength 2048 ] return fi @@ -276,8 +279,8 @@ createDomainKey() { eccname="$length" fi - if [ -z "$length" ] ; then - if [ "$isec" ] ; then + if [[ -z "$length" ]] ; then + if [[ "$isec" ]] ; then length=256 else length=2048 @@ -285,14 +288,14 @@ createDomainKey() { fi _info "Use length $length" - if [ "$isec" ] ; then - if [ "$length" == "256" ] ; then + if [[ "$isec" ]] ; then + if [[ "$length" == "256" ]] ; then eccname="prime256v1" fi - if [ "$length" == "384" ] ; then + if [[ "$length" == "384" ]] ; then eccname="secp384r1" fi - if [ "$length" == "521" ] ; then + if [[ "$length" == "521" ]] ; then eccname="secp521r1" fi _info "Using ec name: $eccname" @@ -300,15 +303,15 @@ createDomainKey() { _initpath $domain - if [ ! -f "$CERT_KEY_PATH" ] || ( [ "$FORCE" ] && ! [ "$IS_RENEW" ] ); then + if [[ ! -f "$CERT_KEY_PATH" ]] || ( [[ "$FORCE" ]] && ! [[ "$IS_RENEW" ]] ); then #generate account key - if [ "$isec" ] ; then + if [[ "$isec" ]] ; then openssl ecparam -name $eccname -genkey 2>/dev/null > "$CERT_KEY_PATH" else openssl genrsa $length 2>/dev/null > "$CERT_KEY_PATH" fi else - if [ "$IS_RENEW" ] ; then + if [[ "$IS_RENEW" ]] ; then _info "Domain key exists, skip" return 0 else @@ -323,8 +326,8 @@ createDomainKey() { # domain domainlist createCSR() { _info "Creating csr" - if [ -z "$1" ] ; then - echo Usage: $0 domain [domainlist] + if [[ -z "$1" ]] ; then + echo Usage: le.sh --createCSR -d domain1.com [-d domain2.com -d domain3.com ... ] return fi domain=$1 @@ -332,12 +335,12 @@ createCSR() { domainlist=$2 - if [ -f "$CSR_PATH" ] && [ "$IS_RENEW" ] && ! [ "$FORCE" ]; then + if [[ -f "$CSR_PATH" ]] && [[ "$IS_RENEW" ]] && [[ -z "$FORCE" ]]; then _info "CSR exists, skip" return fi - if [ -z "$domainlist" ] ; then + if [[ -z "$domainlist" ]] || [[ "$domainlist" == "no" ]]; then #single domain _info "Single domain" $domain printf "[ req_distinguished_name ]\n[ req ]\ndistinguished_name = req_distinguished_name\n" > "$DOMAIN_SSL_CONF" @@ -385,7 +388,7 @@ _stat() { #keyfile _calcjwk() { keyfile="$1" - if [ -z "$keyfile" ] ; then + if [[ -z "$keyfile" ]] ; then _err "Usage: _calcjwk keyfile" return 1 fi @@ -393,18 +396,18 @@ _calcjwk() { if grep "BEGIN RSA PRIVATE KEY" "$keyfile" > /dev/null 2>&1 ; then _debug "RSA key" pub_exp=$(openssl rsa -in $keyfile -noout -text | grep "^publicExponent:"| cut -d '(' -f 2 | cut -d 'x' -f 2 | cut -d ')' -f 1) - if [ "${#pub_exp}" == "5" ] ; then + if [[ "${#pub_exp}" == "5" ]] ; then pub_exp=0$pub_exp fi - _debug pub_exp "$pub_exp" + _debug2 pub_exp "$pub_exp" e=$(echo $pub_exp | _h2b | _base64) - _debug e "$e" + _debug2 e "$e" modulus=$(openssl rsa -in $keyfile -modulus -noout | cut -d '=' -f 2 ) n=$(echo $modulus| _h2b | _base64 | _urlencode ) jwk='{"e": "'$e'", "kty": "RSA", "n": "'$n'"}' - _debug jwk "$jwk" + _debug2 jwk "$jwk" HEADER='{"alg": "RS256", "jwk": '$jwk'}' HEADERPLACE='{"nonce": "NONCE", "alg": "RS256", "jwk": '$jwk'}' @@ -412,39 +415,39 @@ _calcjwk() { _debug "EC key" EC_SIGN="1" crv="$(openssl ec -in $keyfile -noout -text 2>/dev/null | grep "^NIST CURVE:" | cut -d ":" -f 2 | tr -d " \r\n")" - _debug crv $crv + _debug2 crv $crv pubi="$(openssl ec -in $keyfile -noout -text 2>/dev/null | grep -n pub: | cut -d : -f 1)" - _debug pubi $pubi + _debug2 pubi $pubi let "pubi=pubi+1" pubj="$(openssl ec -in $keyfile -noout -text 2>/dev/null | grep -n "ASN1 OID:" | cut -d : -f 1)" - _debug pubj $pubj + _debug2 pubj $pubj let "pubj=pubj-1" pubtext="$(openssl ec -in $keyfile -noout -text 2>/dev/null | sed -n "$pubi,${pubj}p" | tr -d " \n\r")" - _debug pubtext "$pubtext" + _debug2 pubtext "$pubtext" xlen="$(printf "$pubtext" | tr -d ':' | wc -c)" let "xlen=xlen/4" - _debug xlen $xlen + _debug2 xlen $xlen let "xend=xlen+1" x="$(printf $pubtext | cut -d : -f 2-$xend)" - _debug x $x + _debug2 x $x x64="$(printf $x | tr -d : | _h2b | _base64 | _urlencode)" - _debug x64 $x64 + _debug2 x64 $x64 let "xend+=1" y="$(printf $pubtext | cut -d : -f $xend-10000)" - _debug y $y + _debug2 y $y y64="$(printf $y | tr -d : | _h2b | _base64 | _urlencode)" - _debug y64 $y64 + _debug2 y64 $y64 jwk='{"kty": "EC", "crv": "'$crv'", "x": "'$x64'", "y": "'$y64'"}' - _debug jwk "$jwk" + _debug2 jwk "$jwk" HEADER='{"alg": "ES256", "jwk": '$jwk'}' HEADERPLACE='{"nonce": "NONCE", "alg": "ES256", "jwk": '$jwk'}' @@ -454,7 +457,7 @@ _calcjwk() { return 1 fi - _debug HEADER "$HEADER" + _debug2 HEADER "$HEADER" } # body url [needbase64] _post() { @@ -464,13 +467,13 @@ _post() { if _exists "curl" ; then CURL="$CURL --dump-header $HTTP_HEADER " - if [ "$needbase64" ] ; then + if [[ "$needbase64" ]] ; then response="$($CURL -A "User-Agent: $USER_AGENT" -X POST --data "$body" $url | _base64)" else response="$($CURL -A "User-Agent: $USER_AGENT" -X POST --data "$body" $url)" fi else - if [ "$needbase64" ] ; then + if [[ "$needbase64" ]] ; then response="$($WGET -S -O - --user-agent="$USER_AGENT" --post-data="$body" $url 2>"$HTTP_HEADER" | _base64)" else response="$($WGET -S -O - --user-agent="$USER_AGENT" --post-data="$body" $url 2>"$HTTP_HEADER")" @@ -487,14 +490,14 @@ _get() { onlyheader="$2" _debug url $url if _exists "curl" ; then - if [ "$onlyheader" ] ; then + if [[ "$onlyheader" ]] ; then $CURL -I -A "User-Agent: $USER_AGENT" $url else $CURL -A "User-Agent: $USER_AGENT" $url fi else _debug "WGET" "$WGET" - if [ "$onlyheader" ] ; then + if [[ "$onlyheader" ]] ; then eval $WGET --user-agent=\"$USER_AGENT\" -S -O /dev/null $url 2>&1 | sed 's/^[ ]*//g' else eval $WGET --user-agent=\"$USER_AGENT\" -O - $url @@ -510,7 +513,7 @@ _send_signed_request() { payload=$2 needbase64=$3 keyfile=$4 - if [ -z "$keyfile" ] ; then + if [[ -z "$keyfile" ]] ; then keyfile="$ACCOUNT_KEY_PATH" fi _debug url $url @@ -521,7 +524,7 @@ _send_signed_request() { fi payload64=$(echo -n $payload | _base64 | _urlencode) - _debug payload64 $payload64 + _debug2 payload64 $payload64 nonceurl="$API/directory" nonce="$(_get $nonceurl "onlyheader" | grep -o "Replay-Nonce:.*$" | head -1 | tr -d "\r\n" | cut -d ' ' -f 2)" @@ -529,24 +532,24 @@ _send_signed_request() { _debug nonce "$nonce" protected="$(printf "$HEADERPLACE" | sed "s/NONCE/$nonce/" )" - _debug protected "$protected" + _debug2 protected "$protected" protected64="$(printf "$protected" | _base64 | _urlencode)" - _debug protected64 "$protected64" + _debug2 protected64 "$protected64" sig=$(echo -n "$protected64.$payload64" | _sign "$keyfile" "sha256" | _urlencode) - _debug sig "$sig" + _debug2 sig "$sig" body="{\"header\": $HEADER, \"protected\": \"$protected64\", \"payload\": \"$payload64\", \"signature\": \"$sig\"}" - _debug body "$body" + _debug2 body "$body" response="$(_post "$body" $url "$needbase64" )" responseHeaders="$(cat $HTTP_HEADER)" - _debug responseHeaders "$responseHeaders" - _debug response "$response" + _debug2 responseHeaders "$responseHeaders" + _debug2 response "$response" code="$(grep "^HTTP" $HTTP_HEADER | tail -1 | cut -d " " -f 2 | tr -d "\r\n" )" _debug code $code @@ -560,16 +563,16 @@ _setopt() { __sep="$3" __val="$4" __end="$5" - if [ -z "$__opt" ] ; then + if [[ -z "$__opt" ]] ; then echo usage: _setopt '"file" "opt" "=" "value" [";"]' return fi - if [ ! -f "$__conf" ] ; then + if [[ ! -f "$__conf" ]] ; then touch "$__conf" fi if grep -H -n "^$__opt$__sep" "$__conf" > /dev/null ; then - _debug OK + _debug2 OK if [[ "$__val" == *"&"* ]] ; then __val="$(echo $__val | sed 's/&/\\&/g')" fi @@ -584,7 +587,7 @@ _setopt() { echo "$text" | sed "s|^#$__opt$__sep.*$|$__opt$__sep$__val$__end|" > "$__conf" else - _debug APP + _debug2 APP echo "$__opt$__sep$__val$__end" >> "$__conf" fi _debug "$(grep -H -n "^$__opt$__sep" $__conf)" @@ -595,7 +598,7 @@ _setopt() { _savedomainconf() { key="$1" value="$2" - if [ "$DOMAIN_CONF" ] ; then + if [[ "$DOMAIN_CONF" ]] ; then _setopt $DOMAIN_CONF "$key" "=" "$value" else _err "DOMAIN_CONF is empty, can not save $key=$value" @@ -606,7 +609,7 @@ _savedomainconf() { _saveaccountconf() { key="$1" value="$2" - if [ "$ACCOUNT_CONF_PATH" ] ; then + if [[ "$ACCOUNT_CONF_PATH" ]] ; then _setopt $ACCOUNT_CONF_PATH "$key" "=" "\"$value\"" else _err "ACCOUNT_CONF_PATH is empty, can not save $key=$value" @@ -632,7 +635,7 @@ _startserver() { _debug "_NC" "$_NC" # while true ; do - if [ "$DEBUG" ] ; then + if [[ "$DEBUG" ]] ; then if ! echo -e -n "HTTP/1.1 200 OK\r\n\r\n$content" | $_NC -p $Le_HTTPPort -vv ; then echo -e -n "HTTP/1.1 200 OK\r\n\r\n$content" | $_NC $Le_HTTPPort -vv ; fi @@ -641,7 +644,7 @@ _startserver() { echo -e -n "HTTP/1.1 200 OK\r\n\r\n$content" | $_NC $Le_HTTPPort > /dev/null 2>&1 fi fi - if [ "$?" != "0" ] ; then + if [[ "$?" != "0" ]] ; then _err "nc listen error." return 1 fi @@ -655,15 +658,15 @@ _stopserver() { _initpath() { - if [ -z "$LE_WORKING_DIR" ]; then + if [[ -z "$LE_WORKING_DIR" ]] ; then LE_WORKING_DIR=$HOME/.le fi - if [ -z "$ACCOUNT_CONF_PATH" ] ; then + if [[ -z "$ACCOUNT_CONF_PATH" ]] ; then ACCOUNT_CONF_PATH="$LE_WORKING_DIR/account.conf" fi - if [ -f "$ACCOUNT_CONF_PATH" ] ; then + if [[ -f "$ACCOUNT_CONF_PATH" ]] ; then source "$ACCOUNT_CONF_PATH" fi @@ -674,8 +677,8 @@ _initpath() { fi fi - if [ -z "$API" ] ; then - if [ -z "$STAGE" ] ; then + if [[ -z "$API" ]] ; then + if [[ -z "$STAGE" ]] ; then API="$DEFAULT_CA" else API="$STAGE_CA" @@ -683,71 +686,71 @@ _initpath() { fi fi - if [ -z "$ACME_DIR" ] ; then + if [[ -z "$ACME_DIR" ]] ; then ACME_DIR="/home/.acme" fi - if [ -z "$APACHE_CONF_BACKUP_DIR" ] ; then + if [[ -z "$APACHE_CONF_BACKUP_DIR" ]] ; then APACHE_CONF_BACKUP_DIR="$LE_WORKING_DIR" fi - if [ -z "$USER_AGENT" ] ; then + if [[ -z "$USER_AGENT" ]] ; then USER_AGENT="$DEFAULT_USER_AGENT" fi HTTP_HEADER="$LE_WORKING_DIR/http.header" WGET="wget -q" - if [ "$DEBUG" ] ; then + if [[ "$DEBUG" -ge "2" ]] ; then WGET="$WGET -d " fi dp="$LE_WORKING_DIR/curl.dump" CURL="curl -L --silent" - if [ "$DEBUG" ] ; then + if [[ "$DEBUG" -ge "2" ]] ; then CURL="$CURL -L --trace-ascii $dp " fi domain="$1" - if [ -z "$ACCOUNT_KEY_PATH" ] ; then + if [[ -z "$ACCOUNT_KEY_PATH" ]] ; then ACCOUNT_KEY_PATH="$LE_WORKING_DIR/account.key" fi - if [ -z "$domain" ] ; then + if [[ -z "$domain" ]] ; then return 0 fi domainhome="$LE_WORKING_DIR/$domain" mkdir -p "$domainhome" - if [ -z "$DOMAIN_PATH" ] ; then + if [[ -z "$DOMAIN_PATH" ]] ; then DOMAIN_PATH="$domainhome" fi - if [ -z "$DOMAIN_CONF" ] ; then + if [[ -z "$DOMAIN_CONF" ]] ; then DOMAIN_CONF="$domainhome/$domain.conf" fi - if [ -z "$DOMAIN_SSL_CONF" ] ; then + if [[ -z "$DOMAIN_SSL_CONF" ]] ; then DOMAIN_SSL_CONF="$domainhome/$domain.ssl.conf" fi - if [ -z "$CSR_PATH" ] ; then + if [[ -z "$CSR_PATH" ]] ; then CSR_PATH="$domainhome/$domain.csr" fi - if [ -z "$CERT_KEY_PATH" ] ; then + if [[ -z "$CERT_KEY_PATH" ]] ; then CERT_KEY_PATH="$domainhome/$domain.key" fi - if [ -z "$CERT_PATH" ] ; then + if [[ -z "$CERT_PATH" ]] ; then CERT_PATH="$domainhome/$domain.cer" fi - if [ -z "$CA_CERT_PATH" ] ; then + if [[ -z "$CA_CERT_PATH" ]] ; then CA_CERT_PATH="$domainhome/ca.cer" fi - if [ -z "$CERT_FULLCHAIN_PATH" ] ; then + if [[ -z "$CERT_FULLCHAIN_PATH" ]] ; then CERT_FULLCHAIN_PATH="$domainhome/fullchain.cer" fi - if [ -z "$CERT_PFX_PATH" ] ; then + if [[ -z "$CERT_PFX_PATH" ]] ; then CERT_PFX_PATH="$domainhome/$domain.pfx" fi } @@ -763,7 +766,7 @@ _apachePath() { httpdconf="$httpdroot/$httpdconfname" fi - if [ ! -f $httpdconf ] ; then + if [[ ! -f $httpdconf ]] ; then _err "Apache Config file not found" $httpdconf return 1 fi @@ -771,7 +774,7 @@ _apachePath() { } _restoreApache() { - if [ -z "$usingApache" ] ; then + if [[ -z "$usingApache" ]] ; then return 0 fi _initpath @@ -779,7 +782,7 @@ _restoreApache() { return 1 fi - if [ ! -f "$APACHE_CONF_BACKUP_DIR/$httpdconfname" ] ; then + if [[ ! -f "$APACHE_CONF_BACKUP_DIR/$httpdconfname" ]] ; then _debug "No config file to restore." return 0 fi @@ -839,7 +842,7 @@ Allow from all return 1; fi - if [ ! -d "$ACME_DIR" ] ; then + if [[ ! -d "$ACME_DIR" ]] ; then mkdir -p "$ACME_DIR" chmod 755 "$ACME_DIR" fi @@ -862,18 +865,18 @@ _clearup () { # webroot removelevel tokenfile _clearupwebbroot() { __webroot="$1" - if [ -z "$__webroot" ] ; then + if [[ -z "$__webroot" ]] ; then _debug "no webroot specified, skip" return 0 fi - if [ "$2" == '1' ] ; then + if [[ "$2" == '1' ]] ; then _debug "remove $__webroot/.well-known" rm -rf "$__webroot/.well-known" - elif [ "$2" == '2' ] ; then + elif [[ "$2" == '2' ]] ; then _debug "remove $__webroot/.well-known/acme-challenge" rm -rf "$__webroot/.well-known/acme-challenge" - elif [ "$2" == '3' ] ; then + elif [[ "$2" == '3' ]] ; then _debug "remove $__webroot/.well-known/acme-challenge/$3" rm -rf "$__webroot/.well-known/acme-challenge/$3" else @@ -885,8 +888,8 @@ _clearupwebbroot() { } issue() { - if [ -z "$2" ] ; then - _err "Usage: le issue webroot|no|apache|dns a.com [www.a.com,b.com,c.com]|no [key-length]|no" + if [[ -z "$2" ]] ; then + echo "Usage: le --issue -d a.com -w /path/to/webroot/a.com/ " return 1 fi Le_Webroot="$1" @@ -897,13 +900,13 @@ issue() { Le_RealKeyPath="$6" Le_RealCACertPath="$7" Le_ReloadCmd="$8" - + Le_RealFullChainPath="$9" _initpath $Le_Domain - if [ -f "$DOMAIN_CONF" ] ; then + if [[ -f "$DOMAIN_CONF" ]] ; then Le_NextRenewTime=$(grep "^Le_NextRenewTime=" "$DOMAIN_CONF" | cut -d '=' -f 2) - if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(date -u "+%s" )" -lt "$Le_NextRenewTime" ] ; then + if [[ -z "$FORCE" ]] && [[ "$Le_NextRenewTime" ]] && [[ "$(date -u "+%s" )" -lt "$Le_NextRenewTime" ]] ; then _info "Skip, Next renewal time is: $(grep "^Le_NextRenewTimeStr" "$DOMAIN_CONF" | cut -d '=' -f 2)" return 2 fi @@ -917,42 +920,45 @@ issue() { _setopt "$DOMAIN_CONF" "Le_RealCACertPath" "=" "\"$Le_RealCACertPath\"" _setopt "$DOMAIN_CONF" "Le_RealKeyPath" "=" "\"$Le_RealKeyPath\"" _setopt "$DOMAIN_CONF" "Le_ReloadCmd" "=" "\"$Le_ReloadCmd\"" + _setopt "$DOMAIN_CONF" "Le_RealFullChainPath" "=" "\"$Le_RealFullChainPath\"" - if [ "$Le_Alt" == "no" ] ; then + if [[ "$Le_Alt" == "no" ]] ; then Le_Alt="" fi - if [ "$Le_Keylength" == "no" ] ; then + if [[ "$Le_Keylength" == "no" ]] ; then Le_Keylength="" fi - if [ "$Le_RealCertPath" == "no" ] ; then + if [[ "$Le_RealCertPath" == "no" ]] ; then Le_RealCertPath="" fi - if [ "$Le_RealKeyPath" == "no" ] ; then + if [[ "$Le_RealKeyPath" == "no" ]] ; then Le_RealKeyPath="" fi - if [ "$Le_RealCACertPath" == "no" ] ; then + if [[ "$Le_RealCACertPath" == "no" ]] ; then Le_RealCACertPath="" fi - if [ "$Le_ReloadCmd" == "no" ] ; then + if [[ "$Le_ReloadCmd" == "no" ]] ; then Le_ReloadCmd="" fi - + if [[ "$Le_RealFullChainPath" == "no" ]] ; then + Le_RealFullChainPath="" + fi - if [ "$Le_Webroot" == "no" ] ; then + if [[ "$Le_Webroot" == *"no"* ]] ; then _info "Standalone mode." if ! command -v "nc" > /dev/null ; then _err "Please install netcat(nc) tools first." return 1 fi - if [ -z "$Le_HTTPPort" ] ; then + if [[ -z "$Le_HTTPPort" ]] ; then Le_HTTPPort=80 fi _setopt "$DOMAIN_CONF" "Le_HTTPPort" "=" "$Le_HTTPPort" netprc="$(_ss "$Le_HTTPPort" | grep "$Le_HTTPPort")" - if [ "$netprc" ] ; then + if [[ "$netprc" ]] ; then _err "$netprc" _err "tcp port $Le_HTTPPort is already used by $(echo "$netprc" | cut -d : -f 4)" _err "Please stop it first" @@ -960,7 +966,7 @@ issue() { fi fi - if [ "$Le_Webroot" == "apache" ] ; then + if [[ "$Le_Webroot" == *"apache"* ]] ; then if ! _setApache ; then _err "set up apache error. Report error to me." return 1 @@ -980,19 +986,19 @@ issue() { thumbprint=$(echo -n "$accountkey_json" | _digest "sha256" | _urlencode) accountkeyhash="$(cat "$ACCOUNT_KEY_PATH" | _digest "sha256" )" - - if [ "$accountkeyhash" != "$ACCOUNT_KEY_HASH" ] ; then + accountkeyhash="$(echo $accountkeyhash$API | _digest "sha256" )" + if [[ "$accountkeyhash" != "$ACCOUNT_KEY_HASH" ]] ; then _info "Registering account" regjson='{"resource": "new-reg", "agreement": "'$AGREEMENT'"}' - if [ "$ACCOUNT_EMAIL" ] ; then + if [[ "$ACCOUNT_EMAIL" ]] ; then regjson='{"resource": "new-reg", "contact": ["mailto: '$ACCOUNT_EMAIL'"], "agreement": "'$AGREEMENT'"}' fi _send_signed_request "$API/acme/new-reg" "$regjson" - if [ "$code" == "" ] || [ "$code" == '201' ] ; then + if [[ "$code" == "" ]] || [[ "$code" == '201' ]] ; then _info "Registered" echo $response > $LE_WORKING_DIR/account.json - elif [ "$code" == '409' ] ; then + elif [[ "$code" == '409' ]] ; then _info "Already registered" else _err "Register account Error: $response" @@ -1014,23 +1020,33 @@ issue() { _err "Create CSR error." return 1 fi - - vtype="$VTYPE_HTTP" - if [[ "$Le_Webroot" == "dns"* ]] ; then - vtype="$VTYPE_DNS" - fi - + vlist="$Le_Vlist" # verify each domain _info "Verify each domain" sep='#' - if [ -z "$vlist" ] ; then + if [[ -z "$vlist" ]] ; then alldomains=$(echo "$Le_Domain,$Le_Alt" | tr ',' ' ' ) + _index=1 + _currentRoot="" for d in $alldomains - do + do + _info "Getting webroot for domain" $d + _w="$(echo $Le_Webroot | cut -d , -f $_index)" + _debug _w "$_w" + if [[ "$_w" ]] ; then + _currentRoot="$_w" + fi + _debug "_currentRoot" "$_currentRoot" + let "_index+=1" + + vtype="$VTYPE_HTTP" + if [[ "$_currentRoot" == "dns"* ]] ; then + vtype="$VTYPE_DNS" + fi _info "Getting token for domain" $d _send_signed_request "$API/acme/new-authz" "{\"resource\": \"new-authz\", \"identifier\": {\"type\": \"dns\", \"value\": \"$d\"}}" - if [ ! -z "$code" ] && [ ! "$code" == '201' ] ; then + if [[ ! -z "$code" ]] && [[ ! "$code" == '201' ]] ; then _err "new-authz error: $response" _clearup return 1 @@ -1048,7 +1064,7 @@ issue() { keyauthorization="$token.$thumbprint" _debug keyauthorization "$keyauthorization" - dvlist="$d$sep$keyauthorization$sep$uri" + dvlist="$d$sep$keyauthorization$sep$uri$sep$vtype$sep$_currentRoot" _debug dvlist "$dvlist" vlist="$vlist$dvlist," @@ -1062,8 +1078,9 @@ issue() { do d=$(echo $ventry | cut -d $sep -f 1) keyauthorization=$(echo $ventry | cut -d $sep -f 2) - - if [ "$vtype" == "$VTYPE_DNS" ] ; then + vtype=$(echo $ventry | cut -d $sep -f 4) + _currentRoot=$(echo $ventry | cut -d $sep -f 5) + if [[ "$vtype" == "$VTYPE_DNS" ]] ; then dnsadded='0' txtdomain="_acme-challenge.$d" _debug txtdomain "$txtdomain" @@ -1072,22 +1089,22 @@ issue() { #dns #1. check use api d_api="" - if [ -f "$LE_WORKING_DIR/$d/$Le_Webroot" ] ; then - d_api="$LE_WORKING_DIR/$d/$Le_Webroot" - elif [ -f "$LE_WORKING_DIR/$d/$Le_Webroot.sh" ] ; then - d_api="$LE_WORKING_DIR/$d/$Le_Webroot.sh" - elif [ -f "$LE_WORKING_DIR/$Le_Webroot" ] ; then - d_api="$LE_WORKING_DIR/$Le_Webroot" - elif [ -f "$LE_WORKING_DIR/$Le_Webroot.sh" ] ; then - d_api="$LE_WORKING_DIR/$Le_Webroot.sh" - elif [ -f "$LE_WORKING_DIR/dnsapi/$Le_Webroot" ] ; then - d_api="$LE_WORKING_DIR/dnsapi/$Le_Webroot" - elif [ -f "$LE_WORKING_DIR/dnsapi/$Le_Webroot.sh" ] ; then - d_api="$LE_WORKING_DIR/dnsapi/$Le_Webroot.sh" + if [[ -f "$LE_WORKING_DIR/$d/$_currentRoot" ]] ; then + d_api="$LE_WORKING_DIR/$d/$_currentRoot" + elif [[ -f "$LE_WORKING_DIR/$d/$_currentRoot.sh" ]] ; then + d_api="$LE_WORKING_DIR/$d/$_currentRoot.sh" + elif [[ -f "$LE_WORKING_DIR/$_currentRoot" ]] ; then + d_api="$LE_WORKING_DIR/$_currentRoot" + elif [[ -f "$LE_WORKING_DIR/$_currentRoot.sh" ]] ; then + d_api="$LE_WORKING_DIR/$_currentRoot.sh" + elif [[ -f "$LE_WORKING_DIR/dnsapi/$_currentRoot" ]] ; then + d_api="$LE_WORKING_DIR/dnsapi/$_currentRoot" + elif [[ -f "$LE_WORKING_DIR/dnsapi/$_currentRoot.sh" ]] ; then + d_api="$LE_WORKING_DIR/dnsapi/$_currentRoot.sh" fi _debug d_api "$d_api" - if [ "$d_api" ]; then + if [[ "$d_api" ]] ; then _info "Found domain api file: $d_api" else _err "Add the following TXT record:" @@ -1104,7 +1121,7 @@ issue() { return 1 fi - addcommand="$Le_Webroot-add" + addcommand="$_currentRoot-add" if ! command -v $addcommand ; then _err "It seems that your api file is not correct, it must have a function named: $addcommand" return 1 @@ -1123,7 +1140,7 @@ issue() { fi done - if [ "$dnsadded" == '0' ] ; then + if [[ "$dnsadded" == '0' ]] ; then _setopt "$DOMAIN_CONF" "Le_Vlist" "=" "\"$vlist\"" _debug "Dns record not added yet, so, save to $DOMAIN_CONF and exit." _err "Please add the TXT records to the domains, and retry again." @@ -1132,40 +1149,47 @@ issue() { fi - if [ "$dnsadded" == '1' ] ; then + if [[ "$dnsadded" == '1' ]] ; then _info "Sleep 60 seconds for the txt records to take effect" sleep 60 fi _debug "ok, let's start to verify" + ventries=$(echo "$vlist" | tr ',' ' ' ) for ventry in $ventries do d=$(echo $ventry | cut -d $sep -f 1) keyauthorization=$(echo $ventry | cut -d $sep -f 2) uri=$(echo $ventry | cut -d $sep -f 3) + vtype=$(echo $ventry | cut -d $sep -f 4) + _currentRoot=$(echo $ventry | cut -d $sep -f 5) _info "Verifying:$d" _debug "d" "$d" _debug "keyauthorization" "$keyauthorization" _debug "uri" "$uri" removelevel="" token="" - if [ "$vtype" == "$VTYPE_HTTP" ] ; then - if [ "$Le_Webroot" == "no" ] ; then + + _debug "_currentRoot" "$_currentRoot" + + + if [[ "$vtype" == "$VTYPE_HTTP" ]] ; then + if [[ "$_currentRoot" == "no" ]] ; then _info "Standalone mode server" _startserver "$keyauthorization" & serverproc="$!" sleep 2 _debug serverproc $serverproc else - if [ -z "$wellknown_path" ] ; then - wellknown_path="$Le_Webroot/.well-known/acme-challenge" + if [[ -z "$wellknown_path" ]] ; then + wellknown_path="$_currentRoot/.well-known/acme-challenge" fi _debug wellknown_path "$wellknown_path" - if [ ! -d "$Le_Webroot/.well-known" ] ; then + if [[ ! -d "$_currentRoot/.well-known" ]] ; then removelevel='1' - elif [ ! -d "$Le_Webroot/.well-known/acme-challenge" ] ; then + elif [[ ! -d "$_currentRoot/.well-known/acme-challenge" ]] ; then removelevel='2' else removelevel='3' @@ -1177,9 +1201,9 @@ issue() { mkdir -p "$wellknown_path" echo -n "$keyauthorization" > "$wellknown_path/$token" if [[ ! "$usingApache" ]] ; then - webroot_owner=$(_stat $Le_Webroot) + webroot_owner=$(_stat $_currentRoot) _debug "Changing owner/group of .well-known to $webroot_owner" - chown -R $webroot_owner "$Le_Webroot/.well-known" + chown -R $webroot_owner "$_currentRoot/.well-known" fi fi @@ -1187,47 +1211,47 @@ issue() { _send_signed_request $uri "{\"resource\": \"challenge\", \"keyAuthorization\": \"$keyauthorization\"}" - if [ ! -z "$code" ] && [ ! "$code" == '202' ] ; then + if [[ ! -z "$code" ]] && [[ ! "$code" == '202' ]] ; then _err "$d:Challenge error: $response" - _clearupwebbroot "$Le_Webroot" "$removelevel" "$token" + _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup return 1 fi - while [ "1" ] ; do + while [[ "1" ]] ; do _debug "sleep 5 secs to verify" sleep 5 _debug "checking" response="$(_get $uri)" - if [ "$?" != "0" ] ; then + if [[ "$?" != "0" ]] ; then _err "$d:Verify error:$response" - _clearupwebbroot "$Le_Webroot" "$removelevel" "$token" + _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup return 1 fi status=$(echo $response | egrep -o '"status":"[^"]*' | cut -d : -f 2 | tr -d '"') - if [ "$status" == "valid" ] ; then + if [[ "$status" == "valid" ]] ; then _info "Success" _stopserver $serverproc serverproc="" - _clearupwebbroot "$Le_Webroot" "$removelevel" "$token" + _clearupwebbroot "$_currentRoot" "$removelevel" "$token" break; fi - if [ "$status" == "invalid" ] ; then + if [[ "$status" == "invalid" ]] ; then error=$(echo $response | egrep -o '"error":{[^}]*}' | grep -o '"detail":"[^"]*"' | cut -d '"' -f 4) _err "$d:Verify error:$error" - _clearupwebbroot "$Le_Webroot" "$removelevel" "$token" + _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup return 1; fi - if [ "$status" == "pending" ] ; then + if [[ "$status" == "pending" ]] ; then _info "Pending" else _err "$d:Verify error:$response" - _clearupwebbroot "$Le_Webroot" "$removelevel" "$token" + _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup return 1 fi @@ -1245,7 +1269,7 @@ issue() { Le_LinkCert="$(grep -i -o '^Location.*$' $HTTP_HEADER | head -1 | tr -d "\r\n" | cut -d " " -f 2)" _setopt "$DOMAIN_CONF" "Le_LinkCert" "=" "$Le_LinkCert" - if [ "$Le_LinkCert" ] ; then + if [[ "$Le_LinkCert" ]] ; then echo "$BEGIN_CERT" > "$CERT_PATH" _get "$Le_LinkCert" | _base64 "multiline" >> "$CERT_PATH" echo "$END_CERT" >> "$CERT_PATH" @@ -1262,7 +1286,7 @@ issue() { fi - if [ -z "$Le_LinkCert" ] ; then + if [[ -z "$Le_LinkCert" ]] ; then response="$(echo $response | _dbase64 "multiline" )" _err "Sign failed: $(echo "$response" | grep -o '"detail":"[^"]*"')" return 1 @@ -1273,7 +1297,7 @@ issue() { Le_LinkIssuer=$(grep -i '^Link' $HTTP_HEADER | head -1 | cut -d " " -f 2| cut -d ';' -f 1 | tr -d '<>' ) _setopt "$DOMAIN_CONF" "Le_LinkIssuer" "=" "$Le_LinkIssuer" - if [ "$Le_LinkIssuer" ] ; then + if [[ "$Le_LinkIssuer" ]] ; then echo "$BEGIN_CERT" > "$CA_CERT_PATH" _get "$Le_LinkIssuer" | _base64 "multiline" >> "$CA_CERT_PATH" echo "$END_CERT" >> "$CA_CERT_PATH" @@ -1288,7 +1312,7 @@ issue() { Le_CertCreateTimeStr=$(date -u ) _setopt "$DOMAIN_CONF" "Le_CertCreateTimeStr" "=" "\"$Le_CertCreateTimeStr\"" - if [ ! "$Le_RenewalDays" ] ; then + if [[ ! "$Le_RenewalDays" ]] ; then Le_RenewalDays=80 fi @@ -1301,32 +1325,32 @@ issue() { _setopt "$DOMAIN_CONF" "Le_NextRenewTimeStr" "=" "\"$Le_NextRenewTimeStr\"" - installcert $Le_Domain "$Le_RealCertPath" "$Le_RealKeyPath" "$Le_RealCACertPath" "$Le_ReloadCmd" + installcert $Le_Domain "$Le_RealCertPath" "$Le_RealKeyPath" "$Le_RealCACertPath" "$Le_ReloadCmd" "$Le_RealFullChainPath" } renew() { Le_Domain="$1" - if [ -z "$Le_Domain" ] ; then - _err "Usage: $0 domain.com" + if [[ -z "$Le_Domain" ]] ; then + _err "Usage: le.sh --renew -d domain.com" return 1 fi _initpath $Le_Domain - if [ ! -f "$DOMAIN_CONF" ] ; then + if [[ ! -f "$DOMAIN_CONF" ]] ; then _info "$Le_Domain is not a issued domain, skip." return 0; fi source "$DOMAIN_CONF" - if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(date -u "+%s" )" -lt "$Le_NextRenewTime" ] ; then + if [[ -z "$FORCE" ]] && [[ "$Le_NextRenewTime" ]] && [[ "$(date -u "+%s" )" -lt "$Le_NextRenewTime" ]] ; then _info "Skip, Next renewal time is: $Le_NextRenewTimeStr" return 2 fi IS_RENEW="1" - issue "$Le_Webroot" "$Le_Domain" "$Le_Alt" "$Le_Keylength" "$Le_RealCertPath" "$Le_RealKeyPath" "$Le_RealCACertPath" "$Le_ReloadCmd" + issue "$Le_Webroot" "$Le_Domain" "$Le_Alt" "$Le_Keylength" "$Le_RealCertPath" "$Le_RealKeyPath" "$Le_RealCACertPath" "$Le_ReloadCmd" "$Le_RealFullChainPath" local res=$? IS_RENEW="" @@ -1360,6 +1384,7 @@ renewAll() { Le_RealCACertPath="" Le_ReloadCmd="" + Le_RealFullChainPath="" DOMAIN_PATH="" DOMAIN_CONF="" @@ -1381,8 +1406,8 @@ renewAll() { installcert() { Le_Domain="$1" - if [ -z "$Le_Domain" ] ; then - _err "Usage: $0 domain.com [cert-file-path]|no [key-file-path]|no [ca-cert-file-path]|no [reloadCmd]|no" + if [[ -z "$Le_Domain" ]] ; then + echo "Usage: le.sh --installcert -d domain.com [--certpath cert-file-path] [--keypath key-file-path] [--capath ca-cert-file-path] [ --reloadCmd reloadCmd] [--fullchainpath fullchain-path]" return 1 fi @@ -1390,6 +1415,7 @@ installcert() { Le_RealKeyPath="$3" Le_RealCACertPath="$4" Le_ReloadCmd="$5" + Le_RealFullChainPath="$6" _initpath $Le_Domain @@ -1397,20 +1423,21 @@ installcert() { _setopt "$DOMAIN_CONF" "Le_RealCACertPath" "=" "\"$Le_RealCACertPath\"" _setopt "$DOMAIN_CONF" "Le_RealKeyPath" "=" "\"$Le_RealKeyPath\"" _setopt "$DOMAIN_CONF" "Le_ReloadCmd" "=" "\"$Le_ReloadCmd\"" + _setopt "$DOMAIN_CONF" "Le_RealFullChainPath" "=" "\"$Le_RealFullChainPath\"" - if [ "$Le_RealCertPath" ] ; then - if [ -f "$Le_RealCertPath" ] ; then + if [[ "$Le_RealCertPath" ]] ; then + if [[ -f "$Le_RealCertPath" ]] ; then cp -p "$Le_RealCertPath" "$Le_RealCertPath".bak fi cat "$CERT_PATH" > "$Le_RealCertPath" fi - if [ "$Le_RealCACertPath" ] ; then - if [ "$Le_RealCACertPath" == "$Le_RealCertPath" ] ; then + if [[ "$Le_RealCACertPath" ]] ; then + if [[ "$Le_RealCACertPath" == "$Le_RealCertPath" ]] ; then echo "" >> "$Le_RealCACertPath" cat "$CA_CERT_PATH" >> "$Le_RealCACertPath" else - if [ -f "$Le_RealCACertPath" ] ; then + if [[ -f "$Le_RealCACertPath" ]] ; then cp -p "$Le_RealCACertPath" "$Le_RealCACertPath".bak fi cat "$CA_CERT_PATH" > "$Le_RealCACertPath" @@ -1418,14 +1445,21 @@ installcert() { fi - if [ "$Le_RealKeyPath" ] ; then - if [ -f "$Le_RealKeyPath" ] ; then + if [[ "$Le_RealKeyPath" ]] ; then + if [[ -f "$Le_RealKeyPath" ]] ; then cp -p "$Le_RealKeyPath" "$Le_RealKeyPath".bak fi cat "$CERT_KEY_PATH" > "$Le_RealKeyPath" fi + + if [[ "$Le_RealFullChainPath" ]] ; then + if [[ -f "$Le_RealFullChainPath" ]] ; then + cp -p "$Le_RealFullChainPath" "$Le_RealFullChainPath".bak + fi + cat "$CERT_FULLCHAIN_PATH" > "$Le_RealFullChainPath" + fi - if [ "$Le_ReloadCmd" ] ; then + if [[ "$Le_ReloadCmd" ]] ; then _info "Run Le_ReloadCmd: $Le_ReloadCmd" (cd "$DOMAIN_PATH" && eval "$Le_ReloadCmd") fi @@ -1443,7 +1477,7 @@ installcronjob() { _info "Installing cron job" if ! crontab -l | grep 'le.sh cron' ; then - if [ -f "$LE_WORKING_DIR/le.sh" ] ; then + if [[ -f "$LE_WORKING_DIR/le.sh" ]] ; then lesh="\"$LE_WORKING_DIR\"/le.sh" else _err "Can not install cronjob, le.sh not found." @@ -1451,7 +1485,7 @@ installcronjob() { fi crontab -l | { cat; echo "0 0 * * * LE_WORKING_DIR=\"$LE_WORKING_DIR\" $lesh cron > /dev/null"; } | crontab - fi - if [ "$?" != "0" ] ; then + if [[ "$?" != "0" ]] ; then _err "Install cron job failed. You need to manually renew your certs." _err "Or you can add cronjob by yourself:" _err "LE_WORKING_DIR=\"$LE_WORKING_DIR\" $lesh cron > /dev/null" @@ -1465,7 +1499,7 @@ uninstallcronjob() { fi _info "Removing cron job" cr="$(crontab -l | grep 'le.sh cron')" - if [ "$cr" ] ; then + if [[ "$cr" ]] ; then crontab -l | sed "/le.sh cron/d" | crontab - LE_WORKING_DIR="$(echo "$cr" | cut -d ' ' -f 6 | cut -d '=' -f 2 | tr -d '"')" _info LE_WORKING_DIR "$LE_WORKING_DIR" @@ -1476,25 +1510,25 @@ uninstallcronjob() { revoke() { Le_Domain="$1" - if [ -z "$Le_Domain" ] ; then - _err "Usage: revoke domain.com" + if [[ -z "$Le_Domain" ]] ; then + echo "Usage: le.sh --revoke -d domain.com" return 1 fi _initpath $Le_Domain - if [ ! -f "$DOMAIN_CONF" ] ; then + if [[ ! -f "$DOMAIN_CONF" ]] ; then _err "$Le_Domain is not a issued domain, skip." return 1; fi - if [ ! -f "$CERT_PATH" ] ; then + if [[ ! -f "$CERT_PATH" ]] ; then _err "Cert for $Le_Domain $CERT_PATH is not found, skip." return 1 fi cert="$(_getfile "${CERT_PATH}" "${BEGIN_CERT}" "${END_CERT}"| tr -d "\r\n" | _urlencode)" - if [ -z "$cert" ] ; then + if [[ -z "$cert" ]] ; then _err "Cert for $Le_Domain is empty found, skip." return 1 fi @@ -1504,7 +1538,7 @@ revoke() { _info "Try domain key first." if _send_signed_request $uri "$data" "" "$CERT_KEY_PATH"; then - if [ -z "$response" ] ; then + if [[ -z "$response" ]] ; then _info "Revoke success." rm -f $CERT_PATH return 0 @@ -1517,7 +1551,7 @@ revoke() { _info "Then try account key." if _send_signed_request $uri "$data" "" "$ACCOUNT_KEY_PATH" ; then - if [ -z "$response" ] ; then + if [[ -z "$response" ]] ; then _info "Revoke success." rm -f $CERT_PATH return 0 @@ -1531,7 +1565,7 @@ revoke() { # Detect profile file if not specified as environment variable _detect_profile() { - if [ -n "$PROFILE" -a -f "$PROFILE" ]; then + if [ -n "$PROFILE" -a -f "$PROFILE" ] ; then echo "$PROFILE" return fi @@ -1541,36 +1575,36 @@ _detect_profile() { local SHELLTYPE SHELLTYPE="$(basename "/$SHELL")" - if [ "$SHELLTYPE" = "bash" ]; then - if [ -f "$HOME/.bashrc" ]; then + if [[ "$SHELLTYPE" = "bash" ]] ; then + if [[ -f "$HOME/.bashrc" ]] ; then DETECTED_PROFILE="$HOME/.bashrc" - elif [ -f "$HOME/.bash_profile" ]; then + elif [[ -f "$HOME/.bash_profile" ]] ; then DETECTED_PROFILE="$HOME/.bash_profile" fi - elif [ "$SHELLTYPE" = "zsh" ]; then + elif [[ "$SHELLTYPE" = "zsh" ]] ; then DETECTED_PROFILE="$HOME/.zshrc" fi - if [ -z "$DETECTED_PROFILE" ]; then - if [ -f "$HOME/.profile" ]; then + if [[ -z "$DETECTED_PROFILE" ]] ; then + if [[ -f "$HOME/.profile" ]] ; then DETECTED_PROFILE="$HOME/.profile" - elif [ -f "$HOME/.bashrc" ]; then + elif [[ -f "$HOME/.bashrc" ]] ; then DETECTED_PROFILE="$HOME/.bashrc" - elif [ -f "$HOME/.bash_profile" ]; then + elif [[ -f "$HOME/.bash_profile" ]] ; then DETECTED_PROFILE="$HOME/.bash_profile" - elif [ -f "$HOME/.zshrc" ]; then + elif [[ -f "$HOME/.zshrc" ]] ; then DETECTED_PROFILE="$HOME/.zshrc" fi fi - if [ ! -z "$DETECTED_PROFILE" ]; then + if [[ ! -z "$DETECTED_PROFILE" ]] ; then echo "$DETECTED_PROFILE" fi } _initconf() { _initpath - if [ ! -f "$ACCOUNT_CONF_PATH" ] ; then + if [[ ! -f "$ACCOUNT_CONF_PATH" ]] ; then echo "#Account configurations: #Here are the supported macros, uncomment them to make them take effect. #ACCOUNT_EMAIL=aaa@aaa.com # the account email used to register account. @@ -1621,7 +1655,7 @@ _precheck() { _err "It is recommended to install crontab first. try to install 'cron, crontab, crontabs or vixie-cron'." _err "We need to set cron job to renew the certs automatically." _err "Otherwise, your certs will not be able to be renewed automatically." - if [ -z "$FORCE" ] ; then + if [[ -z "$FORCE" ]] ; then _err "Please define 'FORCE=1' and try install again to go without crontab." _err "FORCE=1 ./le.sh install" return 1 @@ -1663,7 +1697,7 @@ install() { cp le.sh "$LE_WORKING_DIR/" && chmod +x "$LE_WORKING_DIR/le.sh" - if [ "$?" != "0" ] ; then + if [[ "$?" != "0" ]] ; then _err "Install failed, can not copy le.sh" return 1 fi @@ -1671,7 +1705,7 @@ install() { _info "Installed to $LE_WORKING_DIR/le.sh" _profile="$(_detect_profile)" - if [ "$_profile" ] ; then + if [[ "$_profile" ]] ; then _debug "Found profile: $_profile" echo "LE_WORKING_DIR=$LE_WORKING_DIR @@ -1689,13 +1723,13 @@ alias le.sh=\"$LE_WORKING_DIR/le.sh\" cp dnsapi/* $LE_WORKING_DIR/dnsapi/ #to keep compatible mv the .acc file to .key file - if [ -f "$LE_WORKING_DIR/account.acc" ] ; then + if [[ -f "$LE_WORKING_DIR/account.acc" ]] ; then mv "$LE_WORKING_DIR/account.acc" "$LE_WORKING_DIR/account.key" fi installcronjob - if [ ! -f "$ACCOUNT_CONF_PATH" ] ; then + if [[ ! -f "$ACCOUNT_CONF_PATH" ]] ; then _initconf fi _info OK @@ -1706,7 +1740,7 @@ uninstall() { _initpath _profile="$(_detect_profile)" - if [ "$_profile" ] ; then + if [[ "$_profile" ]] ; then text="$(cat $_profile)" echo "$text" | sed "s|^source.*le.env.*$||" > "$_profile" fi @@ -1723,49 +1757,63 @@ cron() { } version() { - _info "$PROJECT" - _info "v$VER" + echo "$PROJECT" + echo "v$VER" } showhelp() { version - echo "Usage: le.sh [command] ...[args].... -Available commands: + echo "Usage: le.sh command ...[parameters].... +Commands: + --help, -h Show this help message. + --version, -v Show version info. + --install Install le.sh to your system. + --uninstall Uninstall le.sh, and uninstall the cron job. + --issue Issue a cert. + --installcert Install the issued cert to apache/nginx or any other server. + --renew, -r Renew a cert. + --renewAll Renew all the certs + --revoke Revoke a cert. + --installcronjob Install the cron job to renew certs, you don't need to call this. The 'install' command can automatically install the cron job. + --uninstallcronjob Uninstall the cron job. The 'uninstall' command can do this automatically. + --cron Run cron job to renew all the certs. + --toPkcs Export the certificate and key to a pfx file. + --createAccountKey, -cak Create an account private key, professional use. + --createDomainKey, -cdk Create an domain private key, professional use. + --createCSR, -ccsr Create CSR , professional use. + +Parameters: + --domain, -d domain.tld Specifies a domain, used to issue, renew or revoke etc. + --force, -f Used to force to install or force to renew a cert immediately. + --staging, --test Use staging server, just for test. + --debug Output debug info. + + --webroot, -w /path/to/webroot Specifies the web root folder for web root mode. + --standalone Use standalone mode. + --apache Use apache mode. + --dns [dns-cf|dns-dp|dns-cx|/path/to/api/file] Use dns mode or dns api. + + --keylength, -k [2048] Specifies the domain key length: 2048, 3072, 4096, 8192 or ec-256, ec-384. + --accountkeylength, -ak [2048] Specifies the account key length. + + These parameters are to install the cert to nginx/apache or anyother server after issue/renew a cert: + + --certpath /path/to/real/cert/file After issue/renew, the cert will be copied to this path. + --keypath /path/to/real/key/file After issue/renew, the key will be copied to this path. + --capath /path/to/real/ca/file After issue/renew, the intermediate cert will be copied to this path. + --fullchainpath /path/to/fullchain/file After issue/renew, the fullchain cert will be copied to this path. + + --reloadcmd \"service nginx reload\" After issue/renew, it's used to reload the server. -install: - Install le.sh to your system. -issue: - Issue a cert. -installcert: - Install the issued cert to apache/nginx or any other server. -renew: - Renew a cert. -renewAll: - Renew all the certs. -uninstall: - Uninstall le.sh, and uninstall the cron job. -revoke: - Revoke a cert. -version: - Show version info. -installcronjob: - Install the cron job to renew certs, you don't need to call this. The 'install' command can automatically install the cron job. -uninstallcronjob: - Uninstall the cron job. The 'uninstall' command can do this automatically. -toPkcs: - Export the certificate and key to a pfx file. -createAccountKey: - Create an account private key, professional use. -createDomainKey: - Create an domain private key, professional use. -createCSR: - Create CSR , professional use. + --accountconf Specifies a customized account config file. + --leworkingdir Specifies the home dir for le.sh + " } _installOnline() { _info "Installing from online archive." - if [ ! "$BRANCH" ] ; then + if [[ ! "$BRANCH" ]] ; then BRANCH="master" fi _initpath @@ -1789,14 +1837,256 @@ _installOnline() { rm -f "$localname" } -if [ "$INSTALLONLINE" ] ; then + +_process() { + _CMD="" + _domain="" + _altdomains="no" + _webroot="" + _keylength="no" + _accountkeylength="no" + _certpath="no" + _keypath="no" + _capath="no" + _fullchainpath="no" + _reloadcmd="no" + _password="" + while (( ${#} )); do + case "${1}" in + + --help|-h) + showhelp + return + ;; + --version|-v) + version + return + ;; + --install) + _CMD="install" + ;; + --uninstall) + _CMD="uninstall" + ;; + --issue) + _CMD="issue" + ;; + --installcert|-i) + _CMD="installcert" + ;; + --renew|-r) + _CMD="renew" + ;; + --renewAll|-renewall) + _CMD="renewAll" + ;; + --revoke) + _CMD="revoke" + ;; + --installcronjob) + _CMD="installcronjob" + ;; + --uninstallcronjob) + _CMD="uninstallcronjob" + ;; + --cron) + _CMD="cron" + ;; + --toPkcs) + _CMD="toPkcs" + ;; + --createAccountKey|--createaccountkey|-cak) + _CMD="createAccountKey" + ;; + --createDomainKey|--createdomainkey|-cdk) + _CMD="createDomainKey" + ;; + --createCSR|--createcsr|-ccr) + _CMD="createCSR" + ;; + + + --domain|-d) + _dvalue="$2" + + if [[ -z "$_dvalue" ]] || [[ "$_dvalue" == "-"* ]] ; then + _err "'$_dvalue' is not a valid domain for parameter '$1'" + return 1 + fi + + if [[ -z "$_domain" ]] ; then + _domain="$_dvalue" + else + if [[ "$_altdomains" == "no" ]] ; then + _altdomains="$_dvalue" + else + _altdomains="$_altdomains,$_dvalue" + fi + fi + shift + ;; + + --force|-f) + FORCE="1" + ;; + --staging|--test) + STAGE="1" + ;; + --debug) + if [[ "$2" == "-"* ]] ; then + DEBUG="1" + else + DEBUG="$2" + shift + fi + ;; + + --webroot|-w) + wvalue="$2" + if [[ -z "$_webroot" ]] ; then + _webroot="$wvalue" + else + _webroot="$_webroot,$wvalue" + fi + shift + ;; + --standalone) + wvalue="no" + if [[ -z "$_webroot" ]] ; then + _webroot="$wvalue" + else + _webroot="$_webroot,$wvalue" + fi + ;; + --apache) + wvalue="apache" + if [[ -z "$_webroot" ]] ; then + _webroot="$wvalue" + else + _webroot="$_webroot,$wvalue" + fi + ;; + --dns) + wvalue="dns" + if [[ "$2" != "-"* ]] ; then + wvalue="$2" + shift + fi + if [[ -z "$_webroot" ]] ; then + _webroot="$wvalue" + else + _webroot="$_webroot,$wvalue" + fi + ;; + --keylength|-k) + _keylength="$2" + accountkeylength="$2" + shift + ;; + --accountkeylength|-ak) + accountkeylength="$2" + shift + ;; + + --certpath) + _certpath="$2" + shift + ;; + --keypath) + _keypath="$2" + shift + ;; + --capath) + _capath="$2" + shift + ;; + --fullchainpath) + _fullchainpath="$2" + shift + ;; + --reloadcmd) + _reloadcmd="$2" + shift + ;; + --password) + _password="$2" + shift + ;; + --accountconf) + ACCOUNT_CONF_PATH="$2" + ;; + --leworkingdir) + LE_WORKING_DIR="$2" + ;; + + *) + _err "Unknown parameter : $1" + return 1 + ;; + esac + + shift 1 + done + + + case "${_CMD}" in + install) install ;; + uninstall) uninstall ;; + issue) + issue "$_webroot" "$_domain" "$_altdomains" "$_keylength" "$_certpath" "$_keylength" "$_capath" "$_reloadcmd" "$_fullchainpath" + ;; + installcert) + installcert "$_domain" "$_certpath" "$_keylength" "$_capath" "$_reloadcmd" "$_fullchainpath" + ;; + renew) + renew "$_domain" + ;; + renewAll) + renewAll + ;; + revoke) + revoke "$_domain" + ;; + installcronjob) installcronjob ;; + uninstallcronjob) uninstallcronjob ;; + cron) cron ;; + toPkcs) + toPkcs "$_domain" "$_password" + ;; + createAccountKey) + createAccountKey "$_domain" "$_accountkeylength" + ;; + createDomainKey) + createDomainKey "$_domain" "$_keylength" + ;; + createCSR) + createCSR "$_domain" "$_altdomains" + ;; + + *) + _err "Invalid command: $_CMD" + showhelp; + return 1 + ;; + esac + +} + + +if [[ "$INSTALLONLINE" ]] ; then INSTALLONLINE="" _installOnline $BRANCH exit fi -if [ -z "$1" ] ; then +if [[ -z "$1" ]] ; then showhelp else - "$@" + if [[ "$1" == "-"* ]] ; then + _process "$@" + else + "$@" + fi fi + +