]> git.proxmox.com Git - mirror_acme.sh.git/blame - acme.sh
fix issue where keyauthorization starts with a - character (#184)
[mirror_acme.sh.git] / acme.sh
CommitLineData
0a7c9364 1#!/usr/bin/env sh
bfdf1f48 2
a4270efa 3VER=2.2.4
a7b7355d 4
6cc11ffb 5PROJECT_NAME="acme.sh"
a7b7355d 6
6cc11ffb 7PROJECT_ENTRY="acme.sh"
8
9PROJECT="https://github.com/Neilpang/$PROJECT_NAME"
4c3b3608 10
11DEFAULT_CA="https://acme-v01.api.letsencrypt.org"
12DEFAULT_AGREEMENT="https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf"
13
a7b7355d 14DEFAULT_USER_AGENT="$PROJECT_ENTRY client: $PROJECT"
bbbdcb09 15
4c3b3608 16STAGE_CA="https://acme-staging.api.letsencrypt.org"
17
18VTYPE_HTTP="http-01"
19VTYPE_DNS="dns-01"
20
88fab7d6 21BEGIN_CSR="-----BEGIN CERTIFICATE REQUEST-----"
22END_CSR="-----END CERTIFICATE REQUEST-----"
23
24BEGIN_CERT="-----BEGIN CERTIFICATE-----"
25END_CERT="-----END CERTIFICATE-----"
26
8663fb7e 27if [ -z "$AGREEMENT" ] ; then
4c3b3608 28 AGREEMENT="$DEFAULT_AGREEMENT"
29fi
30
4c3b3608 31
00a50605 32
33_URGLY_PRINTF=""
f4312b44 34if [ "$(printf '\x41')" != 'A' ] ; then
00a50605 35 _URGLY_PRINTF=1
36fi
37
38
4c3b3608 39_info() {
8663fb7e 40 if [ -z "$2" ] ; then
a63b05a9 41 echo "[$(date)] $1"
4c3b3608 42 else
a63b05a9 43 echo "[$(date)] $1"="'$2'"
4c3b3608 44 fi
45}
46
47_err() {
a63b05a9 48 _info "$@" >&2
4c3b3608 49 return 1
50}
51
c60883ef 52_debug() {
8663fb7e 53 if [ -z "$DEBUG" ] ; then
c60883ef 54 return
55 fi
a63b05a9 56 _err "$@"
c60883ef 57 return 0
58}
59
a63b05a9 60_debug2() {
8663fb7e 61 if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ] ; then
a63b05a9 62 _debug "$@"
63 fi
64 return
65}
66
dceb3aca 67_startswith(){
68 _str="$1"
69 _sub="$2"
70 echo $_str | grep ^$_sub >/dev/null 2>&1
71}
72
73_contains(){
74 _str="$1"
75 _sub="$2"
76 echo $_str | grep $_sub >/dev/null 2>&1
77}
78
c53da1ef 79_hasfield() {
80 _str="$1"
81 _field="$2"
82 _sep="$3"
83 if [ -z "$_field" ] ; then
84 _err "Usage: str field [sep]"
85 return 1
86 fi
87
88 if [ -z "$_sep" ] ; then
89 _sep=","
90 fi
91
92 for f in $(echo "$_str" | tr ',' ' ') ; do
93 if [ "$f" = "$_field" ] ; then
94 _debug "'$_str' contains '$_field'"
95 return 0 #contains ok
96 fi
97 done
98 _debug "'$_str' does not contain '$_field'"
99 return 1 #not contains
100}
101
dceb3aca 102_exists(){
c60883ef 103 cmd="$1"
8663fb7e 104 if [ -z "$cmd" ] ; then
c60883ef 105 _err "Usage: _exists cmd"
106 return 1
107 fi
eac18b1c 108 if type command >/dev/null 2>&1 ; then
109 command -v $cmd >/dev/null 2>&1
110 else
111 type $cmd >/dev/null 2>&1
112 fi
c60883ef 113 ret="$?"
a63b05a9 114 _debug2 "$cmd exists=$ret"
c60883ef 115 return $ret
116}
117
00a50605 118#a + b
119_math(){
120 expr "$@"
121}
122
123_h_char_2_dec() {
124 _ch=$1
125 case "${_ch}" in
126 a|A)
127 echo -n 10
128 ;;
129 b|B)
130 echo -n 11
131 ;;
132 c|C)
133 echo -n 12
134 ;;
135 d|D)
136 echo -n 13
137 ;;
138 e|E)
139 echo -n 14
140 ;;
141 f|F)
142 echo -n 15
143 ;;
144 *)
145 echo -n $_ch
146 ;;
147 esac
148
149}
150
4c3b3608 151_h2b() {
152 hex=$(cat)
153 i=1
154 j=2
00a50605 155 if _exists let ; then
156 uselet="1"
157 fi
158 _debug uselet "$uselet"
f4312b44 159 _debug _URGLY_PRINTF "$_URGLY_PRINTF"
4c3b3608 160 while [ '1' ] ; do
00a50605 161 if [ -z "$_URGLY_PRINTF" ] ; then
162 h=$(printf $hex | cut -c $i-$j)
163 if [ -z "$h" ] ; then
164 break;
165 fi
166 printf "\x$h"
167 else
168 ic=$(printf $hex | cut -c $i)
169 jc=$(printf $hex | cut -c $j)
170 if [ -z "$ic$jc" ] ; then
171 break;
172 fi
173 ic="$(_h_char_2_dec $ic)"
174 jc="$(_h_char_2_dec $jc)"
175 printf '\'"$(printf %o "$(_math $ic \* 16 + $jc)")"
4c3b3608 176 fi
00a50605 177 if [ "$uselet" ] ; then
f4312b44 178 let "i+=2" >/dev/null
179 let "j+=2" >/dev/null
00a50605 180 else
181 i="$(_math $i + 2)"
182 j="$(_math $j + 2)"
183 fi
4c3b3608 184 done
185}
186
c60883ef 187#options file
188_sed_i() {
189 options="$1"
190 filename="$2"
8663fb7e 191 if [ -z "$filename" ] ; then
c60883ef 192 _err "Usage:_sed_i options filename"
193 return 1
194 fi
14f3dbb7 195 _debug2 options "$options"
196 if sed -h 2>&1 | grep "\-i\[SUFFIX]" >/dev/null 2>&1; then
c60883ef 197 _debug "Using sed -i"
14f3dbb7 198 sed -i "$options" "$filename"
c60883ef 199 else
200 _debug "No -i support in sed"
201 text="$(cat $filename)"
202 echo "$text" | sed "$options" > "$filename"
203 fi
204}
205
88fab7d6 206#Usage: file startline endline
207_getfile() {
208 filename="$1"
209 startline="$2"
210 endline="$3"
8663fb7e 211 if [ -z "$endline" ] ; then
88fab7d6 212 _err "Usage: file startline endline"
213 return 1
214 fi
215
216 i="$(grep -n -- "$startline" $filename | cut -d : -f 1)"
8663fb7e 217 if [ -z "$i" ] ; then
88fab7d6 218 _err "Can not find start line: $startline"
219 return 1
220 fi
c5f2df5c 221 i="$(_math $i + 1)"
88fab7d6 222 _debug i $i
223
224 j="$(grep -n -- "$endline" $filename | cut -d : -f 1)"
8663fb7e 225 if [ -z "$j" ] ; then
88fab7d6 226 _err "Can not find end line: $endline"
227 return 1
228 fi
c5f2df5c 229 j="$(_math $j - 1)"
88fab7d6 230 _debug j $j
231
c5f2df5c 232 sed -n $i,${j}p "$filename"
88fab7d6 233
234}
235
236#Usage: multiline
4c3b3608 237_base64() {
8663fb7e 238 if [ "$1" ] ; then
88fab7d6 239 openssl base64 -e
240 else
241 openssl base64 -e | tr -d '\r\n'
242 fi
243}
244
245#Usage: multiline
246_dbase64() {
8663fb7e 247 if [ "$1" ] ; then
88fab7d6 248 openssl base64 -d -A
249 else
250 openssl base64 -d
251 fi
252}
253
254#Usage: hashalg
255#Output Base64-encoded digest
256_digest() {
257 alg="$1"
8663fb7e 258 if [ -z "$alg" ] ; then
88fab7d6 259 _err "Usage: _digest hashalg"
260 return 1
261 fi
262
8663fb7e 263 if [ "$alg" = "sha256" ] ; then
88fab7d6 264 openssl dgst -sha256 -binary | _base64
265 else
266 _err "$alg is not supported yet"
267 return 1
268 fi
269
270}
271
272#Usage: keyfile hashalg
273#Output: Base64-encoded signature value
274_sign() {
275 keyfile="$1"
276 alg="$2"
8663fb7e 277 if [ -z "$alg" ] ; then
88fab7d6 278 _err "Usage: _sign keyfile hashalg"
279 return 1
280 fi
281
8663fb7e 282 if [ "$alg" = "sha256" ] ; then
88fab7d6 283 openssl dgst -sha256 -sign "$keyfile" | _base64
284 else
285 _err "$alg is not supported yet"
286 return 1
287 fi
288
4c3b3608 289}
290
34c27e09 291_ss() {
292 _port="$1"
edf08da6 293
294 if _exists "ss" ; then
295 _debug "Using: ss"
296 ss -ntpl | grep :$_port" "
297 return 0
298 fi
299
300 if _exists "netstat" ; then
251fc37c 301 _debug "Using: netstat"
ccb96535 302 if netstat -h 2>&1 | grep "\-p proto" >/dev/null ; then
303 #for windows version netstat tool
50a4ef9c 304 netstat -anb -p tcp | grep "LISTENING" | grep :$_port" "
ccb96535 305 else
14165e5a 306 if netstat -help 2>&1 | grep "\-p protocol" >/dev/null ; then
edf08da6 307 netstat -an -p tcp | grep LISTEN | grep :$_port" "
308 else
309 netstat -ntpl | grep :$_port" "
310 fi
ccb96535 311 fi
34c27e09 312 return 0
313 fi
edf08da6 314
34c27e09 315 return 1
316}
317
ac2d5123 318toPkcs() {
319 domain="$1"
320 pfxPassword="$2"
8663fb7e 321 if [ -z "$domain" ] ; then
a7b7355d 322 echo "Usage: $PROJECT_ENTRY --toPkcs -d domain [--password pfx-password]"
ac2d5123 323 return 1
324 fi
325
326 _initpath "$domain"
327
8663fb7e 328 if [ "$pfxPassword" ] ; then
ac2d5123 329 openssl pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH" -password "pass:$pfxPassword"
330 else
331 openssl pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH"
332 fi
333
8663fb7e 334 if [ "$?" = "0" ] ; then
ac2d5123 335 _info "Success, Pfx is exported to: $CERT_PFX_PATH"
336 fi
337
338}
339
4c3b3608 340#domain [2048]
341createAccountKey() {
342 _info "Creating account key"
8663fb7e 343 if [ -z "$1" ] ; then
a7b7355d 344 echo Usage: $PROJECT_ENTRY --createAccountKey -d domain.com [--accountkeylength 2048]
4c3b3608 345 return
346 fi
347
348 account=$1
349 length=$2
b5eb4b90 350 _debug account "$account"
351 _debug length "$length"
dceb3aca 352 if _startswith "$length" "ec-" ; then
4c3b3608 353 length=2048
354 fi
355
8663fb7e 356 if [ -z "$2" ] || [ "$2" = "no" ] ; then
4c3b3608 357 _info "Use default length 2048"
358 length=2048
359 fi
360 _initpath
361
8663fb7e 362 if [ -f "$ACCOUNT_KEY_PATH" ] ; then
4c3b3608 363 _info "Account key exists, skip"
364 return
365 else
366 #generate account key
f89d991d 367 openssl genrsa $length 2>/dev/null > "$ACCOUNT_KEY_PATH"
4c3b3608 368 fi
369
370}
371
372#domain length
373createDomainKey() {
374 _info "Creating domain key"
8663fb7e 375 if [ -z "$1" ] ; then
a7b7355d 376 echo Usage: $PROJECT_ENTRY --createDomainKey -d domain.com [ --keylength 2048 ]
4c3b3608 377 return
378 fi
379
380 domain=$1
381 length=$2
382 isec=""
dceb3aca 383 if _startswith "$length" "ec-" ; then
4c3b3608 384 isec="1"
385 length=$(printf $length | cut -d '-' -f 2-100)
386 eccname="$length"
387 fi
388
8663fb7e 389 if [ -z "$length" ] ; then
390 if [ "$isec" ] ; then
4c3b3608 391 length=256
392 else
393 length=2048
394 fi
395 fi
396 _info "Use length $length"
397
8663fb7e 398 if [ "$isec" ] ; then
399 if [ "$length" = "256" ] ; then
4c3b3608 400 eccname="prime256v1"
401 fi
8663fb7e 402 if [ "$length" = "384" ] ; then
4c3b3608 403 eccname="secp384r1"
404 fi
8663fb7e 405 if [ "$length" = "521" ] ; then
4c3b3608 406 eccname="secp521r1"
407 fi
408 _info "Using ec name: $eccname"
409 fi
410
411 _initpath $domain
412
8663fb7e 413 if [ ! -f "$CERT_KEY_PATH" ] || ( [ "$FORCE" ] && ! [ "$IS_RENEW" ] ); then
4c3b3608 414 #generate account key
8663fb7e 415 if [ "$isec" ] ; then
4c3b3608 416 openssl ecparam -name $eccname -genkey 2>/dev/null > "$CERT_KEY_PATH"
417 else
418 openssl genrsa $length 2>/dev/null > "$CERT_KEY_PATH"
419 fi
420 else
8663fb7e 421 if [ "$IS_RENEW" ] ; then
4c3b3608 422 _info "Domain key exists, skip"
423 return 0
424 else
425 _err "Domain key exists, do you want to overwrite the key?"
41e3eafa 426 _err "Add '--force', and try again."
4c3b3608 427 return 1
428 fi
429 fi
430
431}
432
433# domain domainlist
434createCSR() {
435 _info "Creating csr"
8663fb7e 436 if [ -z "$1" ] ; then
a7b7355d 437 echo Usage: $PROJECT_ENTRY --createCSR -d domain1.com [-d domain2.com -d domain3.com ... ]
4c3b3608 438 return
439 fi
440 domain=$1
441 _initpath $domain
442
443 domainlist=$2
444
8663fb7e 445 if [ -f "$CSR_PATH" ] && [ "$IS_RENEW" ] && [ -z "$FORCE" ]; then
4c3b3608 446 _info "CSR exists, skip"
447 return
448 fi
449
8663fb7e 450 if [ -z "$domainlist" ] || [ "$domainlist" = "no" ]; then
4c3b3608 451 #single domain
452 _info "Single domain" $domain
1ad65f7d 453 printf "[ req_distinguished_name ]\n[ req ]\ndistinguished_name = req_distinguished_name\n" > "$DOMAIN_SSL_CONF"
454 openssl req -new -sha256 -key "$CERT_KEY_PATH" -subj "/CN=$domain" -config "$DOMAIN_SSL_CONF" -out "$CSR_PATH"
4c3b3608 455 else
456 alt="DNS:$(echo $domainlist | sed "s/,/,DNS:/g")"
457 #multi
458 _info "Multi domain" "$alt"
459 printf "[ req_distinguished_name ]\n[ req ]\ndistinguished_name = req_distinguished_name\n[SAN]\nsubjectAltName=$alt" > "$DOMAIN_SSL_CONF"
460 openssl req -new -sha256 -key "$CERT_KEY_PATH" -subj "/CN=$domain" -reqexts SAN -config "$DOMAIN_SSL_CONF" -out "$CSR_PATH"
461 fi
462
463}
464
166096dc 465_urlencode() {
4c3b3608 466 __n=$(cat)
467 echo $__n | tr '/+' '_-' | tr -d '= '
468}
469
470_time2str() {
471 #BSD
472 if date -u -d@$1 2>/dev/null ; then
473 return
474 fi
475
476 #Linux
477 if date -u -r $1 2>/dev/null ; then
478 return
479 fi
480
481}
482
44df2967 483_stat() {
484 #Linux
485 if stat -c '%U:%G' "$1" 2>/dev/null ; then
486 return
487 fi
488
489 #BSD
490 if stat -f '%Su:%Sg' "$1" 2>/dev/null ; then
491 return
492 fi
493}
494
166096dc 495#keyfile
496_calcjwk() {
497 keyfile="$1"
8663fb7e 498 if [ -z "$keyfile" ] ; then
166096dc 499 _err "Usage: _calcjwk keyfile"
500 return 1
501 fi
502 EC_SIGN=""
503 if grep "BEGIN RSA PRIVATE KEY" "$keyfile" > /dev/null 2>&1 ; then
504 _debug "RSA key"
505 pub_exp=$(openssl rsa -in $keyfile -noout -text | grep "^publicExponent:"| cut -d '(' -f 2 | cut -d 'x' -f 2 | cut -d ')' -f 1)
8663fb7e 506 if [ "${#pub_exp}" = "5" ] ; then
166096dc 507 pub_exp=0$pub_exp
508 fi
a63b05a9 509 _debug2 pub_exp "$pub_exp"
166096dc 510
511 e=$(echo $pub_exp | _h2b | _base64)
a63b05a9 512 _debug2 e "$e"
166096dc 513
514 modulus=$(openssl rsa -in $keyfile -modulus -noout | cut -d '=' -f 2 )
00a50605 515 _debug2 modulus "$modulus"
516 n=$(echo -n $modulus| _h2b | _base64 | _urlencode )
166096dc 517 jwk='{"e": "'$e'", "kty": "RSA", "n": "'$n'"}'
a63b05a9 518 _debug2 jwk "$jwk"
166096dc 519
520 HEADER='{"alg": "RS256", "jwk": '$jwk'}'
521 HEADERPLACE='{"nonce": "NONCE", "alg": "RS256", "jwk": '$jwk'}'
522 elif grep "BEGIN EC PRIVATE KEY" "$keyfile" > /dev/null 2>&1 ; then
523 _debug "EC key"
524 EC_SIGN="1"
525 crv="$(openssl ec -in $keyfile -noout -text 2>/dev/null | grep "^NIST CURVE:" | cut -d ":" -f 2 | tr -d " \r\n")"
a63b05a9 526 _debug2 crv $crv
166096dc 527
528 pubi="$(openssl ec -in $keyfile -noout -text 2>/dev/null | grep -n pub: | cut -d : -f 1)"
00a50605 529 pubi=$(_math $pubi + 1)
a63b05a9 530 _debug2 pubi $pubi
166096dc 531
532 pubj="$(openssl ec -in $keyfile -noout -text 2>/dev/null | grep -n "ASN1 OID:" | cut -d : -f 1)"
00a50605 533 pubj=$(_math $pubj + 1)
a63b05a9 534 _debug2 pubj $pubj
166096dc 535
536 pubtext="$(openssl ec -in $keyfile -noout -text 2>/dev/null | sed -n "$pubi,${pubj}p" | tr -d " \n\r")"
a63b05a9 537 _debug2 pubtext "$pubtext"
166096dc 538
539 xlen="$(printf "$pubtext" | tr -d ':' | wc -c)"
00a50605 540 xlen=$(_math $xlen / 4)
a63b05a9 541 _debug2 xlen $xlen
00a50605 542
543 xend=$(_math $xend + 1)
166096dc 544 x="$(printf $pubtext | cut -d : -f 2-$xend)"
a63b05a9 545 _debug2 x $x
166096dc 546
547 x64="$(printf $x | tr -d : | _h2b | _base64 | _urlencode)"
a63b05a9 548 _debug2 x64 $x64
00a50605 549
550 xend=$(_math $xend + 1)
166096dc 551 y="$(printf $pubtext | cut -d : -f $xend-10000)"
a63b05a9 552 _debug2 y $y
166096dc 553
554 y64="$(printf $y | tr -d : | _h2b | _base64 | _urlencode)"
a63b05a9 555 _debug2 y64 $y64
166096dc 556
557 jwk='{"kty": "EC", "crv": "'$crv'", "x": "'$x64'", "y": "'$y64'"}'
a63b05a9 558 _debug2 jwk "$jwk"
166096dc 559
560 HEADER='{"alg": "ES256", "jwk": '$jwk'}'
561 HEADERPLACE='{"nonce": "NONCE", "alg": "ES256", "jwk": '$jwk'}'
562
563 else
564 _err "Only RSA or EC key is supported."
565 return 1
566 fi
567
a63b05a9 568 _debug2 HEADER "$HEADER"
166096dc 569}
a4270efa 570# body url [needbase64] [POST]
c60883ef 571_post() {
572 body="$1"
573 url="$2"
574 needbase64="$3"
a4270efa 575 httpmethod="$4"
c60883ef 576
a4270efa 577 if [ -z "$httpmethod" ] ; then
578 httpmethod="POST"
579 fi
580 _debug $httpmethod
c60883ef 581 if _exists "curl" ; then
bbbdcb09 582 CURL="$CURL --dump-header $HTTP_HEADER "
8663fb7e 583 if [ "$needbase64" ] ; then
a4270efa 584 response="$($CURL -A "User-Agent: $USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" --data "$body" $url | _base64)"
c60883ef 585 else
a4270efa 586 response="$($CURL -A "User-Agent: $USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" --data "$body" $url)"
c60883ef 587 fi
588 else
8663fb7e 589 if [ "$needbase64" ] ; then
a4270efa 590 response="$($WGET -S -O - --user-agent="$USER_AGENT" --method $httpmethod --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --body-data="$body" $url 2>"$HTTP_HEADER" | _base64)"
c60883ef 591 else
a4270efa 592 response="$($WGET -S -O - --user-agent="$USER_AGENT" --method $httpmethod --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --body-data="$body" $url 2>"$HTTP_HEADER")"
c60883ef 593 fi
594 _sed_i "s/^ *//g" "$HTTP_HEADER"
595 fi
596 echo -n "$response"
597
598}
599
600# url getheader
601_get() {
a4270efa 602 _debug GET
c60883ef 603 url="$1"
604 onlyheader="$2"
605 _debug url $url
606 if _exists "curl" ; then
8663fb7e 607 if [ "$onlyheader" ] ; then
a4270efa 608 $CURL -I -A "User-Agent: $USER_AGENT" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" $url
c60883ef 609 else
a4270efa 610 $CURL -A "User-Agent: $USER_AGENT" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" $url
c60883ef 611 fi
612 else
bbbdcb09 613 _debug "WGET" "$WGET"
8663fb7e 614 if [ "$onlyheader" ] ; then
a4270efa 615 $WGET --user-agent="$USER_AGENT" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" -S -O /dev/null $url 2>&1 | sed 's/^[ ]*//g'
c60883ef 616 else
a4270efa 617 $WGET --user-agent="$USER_AGENT" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" -O - $url
c60883ef 618 fi
619 fi
620 ret=$?
621 return $ret
622}
166096dc 623
624# url payload needbase64 keyfile
4c3b3608 625_send_signed_request() {
626 url=$1
627 payload=$2
628 needbase64=$3
166096dc 629 keyfile=$4
8663fb7e 630 if [ -z "$keyfile" ] ; then
166096dc 631 keyfile="$ACCOUNT_KEY_PATH"
632 fi
4c3b3608 633 _debug url $url
634 _debug payload "$payload"
635
166096dc 636 if ! _calcjwk "$keyfile" ; then
637 return 1
638 fi
c60883ef 639
166096dc 640 payload64=$(echo -n $payload | _base64 | _urlencode)
a63b05a9 641 _debug2 payload64 $payload64
4c3b3608 642
643 nonceurl="$API/directory"
bbbdcb09 644 nonce="$(_get $nonceurl "onlyheader" | grep -o "Replay-Nonce:.*$" | head -1 | tr -d "\r\n" | cut -d ' ' -f 2)"
4c3b3608 645
646 _debug nonce "$nonce"
647
648 protected="$(printf "$HEADERPLACE" | sed "s/NONCE/$nonce/" )"
a63b05a9 649 _debug2 protected "$protected"
4c3b3608 650
166096dc 651 protected64="$(printf "$protected" | _base64 | _urlencode)"
a63b05a9 652 _debug2 protected64 "$protected64"
166096dc 653
88fab7d6 654 sig=$(echo -n "$protected64.$payload64" | _sign "$keyfile" "sha256" | _urlencode)
a63b05a9 655 _debug2 sig "$sig"
4c3b3608 656
657 body="{\"header\": $HEADER, \"protected\": \"$protected64\", \"payload\": \"$payload64\", \"signature\": \"$sig\"}"
a63b05a9 658 _debug2 body "$body"
4c3b3608 659
bbbdcb09 660
c60883ef 661 response="$(_post "$body" $url "$needbase64" )"
4c3b3608 662
c60883ef 663 responseHeaders="$(cat $HTTP_HEADER)"
4c3b3608 664
a63b05a9 665 _debug2 responseHeaders "$responseHeaders"
666 _debug2 response "$response"
c60883ef 667 code="$(grep "^HTTP" $HTTP_HEADER | tail -1 | cut -d " " -f 2 | tr -d "\r\n" )"
4c3b3608 668 _debug code $code
669
670}
671
4c3b3608 672
673#setopt "file" "opt" "=" "value" [";"]
674_setopt() {
675 __conf="$1"
676 __opt="$2"
677 __sep="$3"
678 __val="$4"
679 __end="$5"
8663fb7e 680 if [ -z "$__opt" ] ; then
4c3b3608 681 echo usage: _setopt '"file" "opt" "=" "value" [";"]'
682 return
683 fi
8663fb7e 684 if [ ! -f "$__conf" ] ; then
4c3b3608 685 touch "$__conf"
686 fi
687
688 if grep -H -n "^$__opt$__sep" "$__conf" > /dev/null ; then
a63b05a9 689 _debug2 OK
dceb3aca 690 if _contains "$__val" "&" ; then
4c3b3608 691 __val="$(echo $__val | sed 's/&/\\&/g')"
692 fi
693 text="$(cat $__conf)"
6dfaaa70 694 echo "$text" | sed "s|^$__opt$__sep.*$|$__opt$__sep$__val$__end|" > "$__conf"
4c3b3608 695
696 elif grep -H -n "^#$__opt$__sep" "$__conf" > /dev/null ; then
dceb3aca 697 if _contains "$__val" "&" ; then
4c3b3608 698 __val="$(echo $__val | sed 's/&/\\&/g')"
699 fi
700 text="$(cat $__conf)"
6dfaaa70 701 echo "$text" | sed "s|^#$__opt$__sep.*$|$__opt$__sep$__val$__end|" > "$__conf"
4c3b3608 702
703 else
a63b05a9 704 _debug2 APP
4c3b3608 705 echo "$__opt$__sep$__val$__end" >> "$__conf"
706 fi
707 _debug "$(grep -H -n "^$__opt$__sep" $__conf)"
708}
709
710#_savedomainconf key value
711#save to domain.conf
712_savedomainconf() {
713 key="$1"
714 value="$2"
8663fb7e 715 if [ "$DOMAIN_CONF" ] ; then
4d2f38b0 716 _setopt "$DOMAIN_CONF" "$key" "=" "\"$value\""
717 else
718 _err "DOMAIN_CONF is empty, can not save $key=$value"
719 fi
720}
721
722#_cleardomainconf key
723_cleardomainconf() {
724 key="$1"
725 if [ "$DOMAIN_CONF" ] ; then
726 _sed_i "s/^$key.*$//" "$DOMAIN_CONF"
4c3b3608 727 else
728 _err "DOMAIN_CONF is empty, can not save $key=$value"
729 fi
730}
731
732#_saveaccountconf key value
733_saveaccountconf() {
734 key="$1"
735 value="$2"
8663fb7e 736 if [ "$ACCOUNT_CONF_PATH" ] ; then
4d2f38b0 737 _setopt "$ACCOUNT_CONF_PATH" "$key" "=" "\"$value\""
4c3b3608 738 else
739 _err "ACCOUNT_CONF_PATH is empty, can not save $key=$value"
740 fi
741}
742
743_startserver() {
744 content="$1"
6fc1447f 745 _debug "startserver: $$"
1b2e940d 746 nchelp="$(nc -h 2>&1)"
850c1128 747
399306a1 748 if echo "$nchelp" | grep "\-q[ ,]" >/dev/null ; then
850c1128 749 _NC="nc -q 1 -l"
750 else
f76eb452 751 if echo "$nchelp" | grep "GNU netcat" >/dev/null && echo "$nchelp" | grep "\-c, \-\-close" >/dev/null ; then
752 _NC="nc -c -l"
6d60f288 753 elif echo "$nchelp" | grep "\-N" |grep "Shutdown the network socket after EOF on stdin" >/dev/null ; then
754 _NC="nc -N -l"
f76eb452 755 else
756 _NC="nc -l"
757 fi
4c3b3608 758 fi
1b2e940d 759
f76eb452 760 _debug "_NC" "$_NC"
4c3b3608 761# while true ; do
8663fb7e 762 if [ "$DEBUG" ] ; then
c8b6fe62 763 if ! printf "HTTP/1.1 200 OK\r\n\r\n$content" | $_NC -p $Le_HTTPPort ; then
764 printf "HTTP/1.1 200 OK\r\n\r\n$content" | $_NC $Le_HTTPPort ;
3aff11f6 765 fi
4c3b3608 766 else
a1048c48 767 if ! printf "HTTP/1.1 200 OK\r\n\r\n$content" | $_NC -p $Le_HTTPPort > /dev/null 2>&1; then
768 printf "HTTP/1.1 200 OK\r\n\r\n$content" | $_NC $Le_HTTPPort > /dev/null 2>&1
3aff11f6 769 fi
4c3b3608 770 fi
8663fb7e 771 if [ "$?" != "0" ] ; then
051c706d 772 _err "nc listen error."
6fc1447f 773 exit 1
051c706d 774 fi
4c3b3608 775# done
776}
777
6fc1447f 778_stopserver(){
4c3b3608 779 pid="$1"
6fc1447f 780 _debug "pid" "$pid"
8663fb7e 781 if [ -z "$pid" ] ; then
6fc1447f 782 return
783 fi
784
3d434e43 785 _get "http://localhost:$Le_HTTPPort" >/dev/null 2>&1
4c3b3608 786
787}
788
789_initpath() {
790
8663fb7e 791 if [ -z "$LE_WORKING_DIR" ] ; then
6cc11ffb 792 LE_WORKING_DIR=$HOME/.$PROJECT_NAME
4c3b3608 793 fi
794
d53289d7 795 _DEFAULT_ACCOUNT_CONF_PATH="$LE_WORKING_DIR/account.conf"
796
8663fb7e 797 if [ -z "$ACCOUNT_CONF_PATH" ] ; then
798 if [ -f "$_DEFAULT_ACCOUNT_CONF_PATH" ] ; then
799 . "$_DEFAULT_ACCOUNT_CONF_PATH"
635695ec 800 fi
d53289d7 801 fi
802
8663fb7e 803 if [ -z "$ACCOUNT_CONF_PATH" ] ; then
d53289d7 804 ACCOUNT_CONF_PATH="$_DEFAULT_ACCOUNT_CONF_PATH"
4c3b3608 805 fi
806
8663fb7e 807 if [ -f "$ACCOUNT_CONF_PATH" ] ; then
808 . "$ACCOUNT_CONF_PATH"
4c3b3608 809 fi
810
8663fb7e 811 if [ "$IN_CRON" ] ; then
812 if [ ! "$_USER_PATH_EXPORTED" ] ; then
281aa349 813 _USER_PATH_EXPORTED=1
814 export PATH="$USER_PATH:$PATH"
815 fi
816 fi
817
8663fb7e 818 if [ -z "$API" ] ; then
819 if [ -z "$STAGE" ] ; then
4c3b3608 820 API="$DEFAULT_CA"
821 else
822 API="$STAGE_CA"
823 _info "Using stage api:$API"
824 fi
825 fi
826
8663fb7e 827 if [ -z "$ACME_DIR" ] ; then
4c3b3608 828 ACME_DIR="/home/.acme"
829 fi
830
8663fb7e 831 if [ -z "$APACHE_CONF_BACKUP_DIR" ] ; then
8a144f4d 832 APACHE_CONF_BACKUP_DIR="$LE_WORKING_DIR"
4c3b3608 833 fi
834
8663fb7e 835 if [ -z "$USER_AGENT" ] ; then
bbbdcb09 836 USER_AGENT="$DEFAULT_USER_AGENT"
837 fi
838
839 HTTP_HEADER="$LE_WORKING_DIR/http.header"
840
841 WGET="wget -q"
8663fb7e 842 if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ] ; then
bbbdcb09 843 WGET="$WGET -d "
844 fi
845
846 dp="$LE_WORKING_DIR/curl.dump"
4a0f23e2 847 CURL="curl -L --silent"
8663fb7e 848 if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ] ; then
4a0f23e2 849 CURL="$CURL -L --trace-ascii $dp "
bbbdcb09 850 fi
b2817897 851
852 _DEFAULT_ACCOUNT_KEY_PATH="$LE_WORKING_DIR/account.key"
8663fb7e 853 if [ -z "$ACCOUNT_KEY_PATH" ] ; then
b2817897 854 ACCOUNT_KEY_PATH="$_DEFAULT_ACCOUNT_KEY_PATH"
4c3b3608 855 fi
b2817897 856
a79b26af
RD
857 _DEFAULT_CERT_HOME="$LE_WORKING_DIR"
858 if [ -z "$CERT_HOME" ] ; then
859 CERT_HOME="$_DEFAULT_CERT_HOME"
860 fi
861
b2817897 862 domain="$1"
4c3b3608 863
8663fb7e 864 if [ -z "$domain" ] ; then
4c3b3608 865 return 0
866 fi
867
b2817897 868 domainhome="$CERT_HOME/$domain"
4c3b3608 869 mkdir -p "$domainhome"
870
8663fb7e 871 if [ -z "$DOMAIN_PATH" ] ; then
4c3b3608 872 DOMAIN_PATH="$domainhome"
873 fi
8663fb7e 874 if [ -z "$DOMAIN_CONF" ] ; then
1ad65f7d 875 DOMAIN_CONF="$domainhome/$domain.conf"
4c3b3608 876 fi
877
8663fb7e 878 if [ -z "$DOMAIN_SSL_CONF" ] ; then
1ad65f7d 879 DOMAIN_SSL_CONF="$domainhome/$domain.ssl.conf"
4c3b3608 880 fi
881
8663fb7e 882 if [ -z "$CSR_PATH" ] ; then
4c3b3608 883 CSR_PATH="$domainhome/$domain.csr"
884 fi
8663fb7e 885 if [ -z "$CERT_KEY_PATH" ] ; then
4c3b3608 886 CERT_KEY_PATH="$domainhome/$domain.key"
887 fi
8663fb7e 888 if [ -z "$CERT_PATH" ] ; then
4c3b3608 889 CERT_PATH="$domainhome/$domain.cer"
890 fi
8663fb7e 891 if [ -z "$CA_CERT_PATH" ] ; then
4c3b3608 892 CA_CERT_PATH="$domainhome/ca.cer"
893 fi
8663fb7e 894 if [ -z "$CERT_FULLCHAIN_PATH" ] ; then
850db6d4 895 CERT_FULLCHAIN_PATH="$domainhome/fullchain.cer"
caf1fc10 896 fi
8663fb7e 897 if [ -z "$CERT_PFX_PATH" ] ; then
ac2d5123 898 CERT_PFX_PATH="$domainhome/$domain.pfx"
899 fi
4c3b3608 900}
901
902
903_apachePath() {
80a0a7b5 904 if ! _exists apachectl ; then
905 _err "'apachecrl not found. It seems that apache is not installed, or you are not root user.'"
906 _err "Please use webroot mode to try again."
907 return 1
908 fi
4c3b3608 909 httpdconfname="$(apachectl -V | grep SERVER_CONFIG_FILE= | cut -d = -f 2 | tr -d '"' )"
dceb3aca 910 if _startswith "$httpdconfname" '/' ; then
d62ee940 911 httpdconf="$httpdconfname"
c456d954 912 httpdconfname="$(basename $httpdconfname)"
d62ee940 913 else
914 httpdroot="$(apachectl -V | grep HTTPD_ROOT= | cut -d = -f 2 | tr -d '"' )"
915 httpdconf="$httpdroot/$httpdconfname"
916 fi
917
8663fb7e 918 if [ ! -f $httpdconf ] ; then
4c3b3608 919 _err "Apache Config file not found" $httpdconf
920 return 1
921 fi
922 return 0
923}
924
925_restoreApache() {
8663fb7e 926 if [ -z "$usingApache" ] ; then
4c3b3608 927 return 0
928 fi
929 _initpath
930 if ! _apachePath ; then
931 return 1
932 fi
933
8663fb7e 934 if [ ! -f "$APACHE_CONF_BACKUP_DIR/$httpdconfname" ] ; then
4c3b3608 935 _debug "No config file to restore."
936 return 0
937 fi
938
ff3bce32 939 cat "$APACHE_CONF_BACKUP_DIR/$httpdconfname" > "$httpdconf"
5ef501c5 940 _debug "Restored: $httpdconf."
4c3b3608 941 if ! apachectl -t ; then
942 _err "Sorry, restore apache config error, please contact me."
943 return 1;
944 fi
5ef501c5 945 _debug "Restored successfully."
4c3b3608 946 rm -f "$APACHE_CONF_BACKUP_DIR/$httpdconfname"
947 return 0
948}
949
950_setApache() {
951 _initpath
952 if ! _apachePath ; then
953 return 1
954 fi
955
956 #backup the conf
957 _debug "Backup apache config file" $httpdconf
ff3bce32 958 cp $httpdconf $APACHE_CONF_BACKUP_DIR/
4c3b3608 959 _info "JFYI, Config file $httpdconf is backuped to $APACHE_CONF_BACKUP_DIR/$httpdconfname"
960 _info "In case there is an error that can not be restored automatically, you may try restore it yourself."
961 _info "The backup file will be deleted on sucess, just forget it."
962
963 #add alias
b09d597c 964
965 apacheVer="$(apachectl -V | grep "Server version:" | cut -d : -f 2 | cut -d " " -f 2 | cut -d '/' -f 2 )"
966 _debug "apacheVer" "$apacheVer"
967 apacheMajer="$(echo "$apacheVer" | cut -d . -f 1)"
968 apacheMinor="$(echo "$apacheVer" | cut -d . -f 2)"
969
8663fb7e 970 if [ "$apacheVer" ] && [ "$apacheMajer" -ge "2" ] && [ "$apacheMinor" -ge "4" ] ; then
b09d597c 971 echo "
4c3b3608 972Alias /.well-known/acme-challenge $ACME_DIR
973
974<Directory $ACME_DIR >
975Require all granted
b09d597c 976</Directory>
977 " >> $httpdconf
978 else
979 echo "
980Alias /.well-known/acme-challenge $ACME_DIR
981
982<Directory $ACME_DIR >
983Order allow,deny
984Allow from all
4c3b3608 985</Directory>
986 " >> $httpdconf
b09d597c 987 fi
988
4c3b3608 989
990 if ! apachectl -t ; then
991 _err "Sorry, apache config error, please contact me."
992 _restoreApache
993 return 1;
994 fi
995
8663fb7e 996 if [ ! -d "$ACME_DIR" ] ; then
4c3b3608 997 mkdir -p "$ACME_DIR"
998 chmod 755 "$ACME_DIR"
999 fi
1000
1001 if ! apachectl graceful ; then
1002 _err "Sorry, apachectl graceful error, please contact me."
1003 _restoreApache
1004 return 1;
1005 fi
1006 usingApache="1"
1007 return 0
1008}
1009
5ef501c5 1010_clearup() {
4c3b3608 1011 _stopserver $serverproc
1012 serverproc=""
1013 _restoreApache
1014}
1015
1016# webroot removelevel tokenfile
1017_clearupwebbroot() {
1018 __webroot="$1"
8663fb7e 1019 if [ -z "$__webroot" ] ; then
4c3b3608 1020 _debug "no webroot specified, skip"
1021 return 0
1022 fi
1023
8663fb7e 1024 if [ "$2" = '1' ] ; then
4c3b3608 1025 _debug "remove $__webroot/.well-known"
1026 rm -rf "$__webroot/.well-known"
8663fb7e 1027 elif [ "$2" = '2' ] ; then
4c3b3608 1028 _debug "remove $__webroot/.well-known/acme-challenge"
1029 rm -rf "$__webroot/.well-known/acme-challenge"
8663fb7e 1030 elif [ "$2" = '3' ] ; then
4c3b3608 1031 _debug "remove $__webroot/.well-known/acme-challenge/$3"
1032 rm -rf "$__webroot/.well-known/acme-challenge/$3"
1033 else
1034 _info "Skip for removelevel:$2"
1035 fi
1036
1037 return 0
1038
1039}
1040
1041issue() {
8663fb7e 1042 if [ -z "$2" ] ; then
a7b7355d 1043 echo "Usage: $PROJECT_ENTRY --issue -d a.com -w /path/to/webroot/a.com/ "
4c3b3608 1044 return 1
1045 fi
1046 Le_Webroot="$1"
1047 Le_Domain="$2"
1048 Le_Alt="$3"
1049 Le_Keylength="$4"
1050 Le_RealCertPath="$5"
1051 Le_RealKeyPath="$6"
1052 Le_RealCACertPath="$7"
1053 Le_ReloadCmd="$8"
a63b05a9 1054 Le_RealFullChainPath="$9"
4c3b3608 1055
eccec5f6 1056 #remove these later.
8663fb7e 1057 if [ "$Le_Webroot" = "dns-cf" ] ; then
eccec5f6 1058 Le_Webroot="dns_cf"
1059 fi
8663fb7e 1060 if [ "$Le_Webroot" = "dns-dp" ] ; then
eccec5f6 1061 Le_Webroot="dns_dp"
1062 fi
8663fb7e 1063 if [ "$Le_Webroot" = "dns-cx" ] ; then
eccec5f6 1064 Le_Webroot="dns_cx"
1065 fi
4c3b3608 1066
eccec5f6 1067 _initpath $Le_Domain
1068
8663fb7e 1069 if [ -f "$DOMAIN_CONF" ] ; then
a4270efa 1070 Le_NextRenewTime=$(grep "^Le_NextRenewTime=" "$DOMAIN_CONF" | cut -d '=' -f 2 | tr -d "'\"")
1071 _debug Le_NextRenewTime "$Le_NextRenewTime"
1072 if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ $(date -u "+%s" ) -lt $Le_NextRenewTime ] ; then
4c3b3608 1073 _info "Skip, Next renewal time is: $(grep "^Le_NextRenewTimeStr" "$DOMAIN_CONF" | cut -d '=' -f 2)"
1074 return 2
1075 fi
1076 fi
96a46cfc 1077
4d2f38b0 1078 _savedomainconf "Le_Domain" "$Le_Domain"
1079 _savedomainconf "Le_Alt" "$Le_Alt"
1080 _savedomainconf "Le_Webroot" "$Le_Webroot"
1081 _savedomainconf "Le_Keylength" "$Le_Keylength"
4c3b3608 1082
8663fb7e 1083 if [ "$Le_Alt" = "no" ] ; then
4c3b3608 1084 Le_Alt=""
1085 fi
8663fb7e 1086 if [ "$Le_Keylength" = "no" ] ; then
4c3b3608 1087 Le_Keylength=""
1088 fi
4c3b3608 1089
c53da1ef 1090 if _hasfield "$Le_Webroot" "no" ; then
4c3b3608 1091 _info "Standalone mode."
5ef501c5 1092 if ! _exists "nc" ; then
4c3b3608 1093 _err "Please install netcat(nc) tools first."
1094 return 1
1095 fi
1096
8663fb7e 1097 if [ -z "$Le_HTTPPort" ] ; then
4c3b3608 1098 Le_HTTPPort=80
1099 fi
4d2f38b0 1100 _savedomainconf "Le_HTTPPort" "$Le_HTTPPort"
4c3b3608 1101
251fc37c 1102 netprc="$(_ss "$Le_HTTPPort" | grep "$Le_HTTPPort")"
8663fb7e 1103 if [ "$netprc" ] ; then
4c3b3608 1104 _err "$netprc"
1105 _err "tcp port $Le_HTTPPort is already used by $(echo "$netprc" | cut -d : -f 4)"
1106 _err "Please stop it first"
1107 return 1
1108 fi
1109 fi
1110
c53da1ef 1111 if _hasfield "$Le_Webroot" "apache" ; then
4c3b3608 1112 if ! _setApache ; then
1113 _err "set up apache error. Report error to me."
1114 return 1
1115 fi
4c3b3608 1116 else
1117 usingApache=""
1118 fi
1119
8663fb7e 1120 if [ ! -f "$ACCOUNT_KEY_PATH" ] ; then
41e3eafa 1121 if ! createAccountKey $Le_Domain $Le_Keylength ; then
1122 _err "Create account key error."
8663fb7e 1123 if [ "$usingApache" ] ; then
5ef501c5 1124 _restoreApache
1125 fi
41e3eafa 1126 return 1
1127 fi
1128 fi
1129
166096dc 1130 if ! _calcjwk "$ACCOUNT_KEY_PATH" ; then
8663fb7e 1131 if [ "$usingApache" ] ; then
5ef501c5 1132 _restoreApache
1133 fi
166096dc 1134 return 1
1135 fi
1136
1137 accountkey_json=$(echo -n "$jwk" | tr -d ' ' )
88fab7d6 1138 thumbprint=$(echo -n "$accountkey_json" | _digest "sha256" | _urlencode)
4c3b3608 1139
88fab7d6 1140 accountkeyhash="$(cat "$ACCOUNT_KEY_PATH" | _digest "sha256" )"
a63b05a9 1141 accountkeyhash="$(echo $accountkeyhash$API | _digest "sha256" )"
8663fb7e 1142 if [ "$accountkeyhash" != "$ACCOUNT_KEY_HASH" ] ; then
166096dc 1143 _info "Registering account"
1144 regjson='{"resource": "new-reg", "agreement": "'$AGREEMENT'"}'
8663fb7e 1145 if [ "$ACCOUNT_EMAIL" ] ; then
166096dc 1146 regjson='{"resource": "new-reg", "contact": ["mailto: '$ACCOUNT_EMAIL'"], "agreement": "'$AGREEMENT'"}'
1147 fi
1148 _send_signed_request "$API/acme/new-reg" "$regjson"
1149
8663fb7e 1150 if [ "$code" = "" ] || [ "$code" = '201' ] ; then
166096dc 1151 _info "Registered"
1152 echo $response > $LE_WORKING_DIR/account.json
8663fb7e 1153 elif [ "$code" = '409' ] ; then
166096dc 1154 _info "Already registered"
1155 else
1156 _err "Register account Error: $response"
1157 _clearup
1158 return 1
1159 fi
1160 ACCOUNT_KEY_HASH="$accountkeyhash"
1161 _saveaccountconf "ACCOUNT_KEY_HASH" "$ACCOUNT_KEY_HASH"
1162 else
1163 _info "Skip register account key"
1164 fi
1165
8663fb7e 1166 if [ ! -f "$CERT_KEY_PATH" ] ; then
41e3eafa 1167 if ! createDomainKey $Le_Domain $Le_Keylength ; then
1168 _err "Create domain key error."
5ef501c5 1169 _clearup
41e3eafa 1170 return 1
1171 fi
4c3b3608 1172 fi
1173
1174 if ! createCSR $Le_Domain $Le_Alt ; then
1175 _err "Create CSR error."
5ef501c5 1176 _clearup
4c3b3608 1177 return 1
1178 fi
a63b05a9 1179
4c3b3608 1180 vlist="$Le_Vlist"
1181 # verify each domain
1182 _info "Verify each domain"
1183 sep='#'
8663fb7e 1184 if [ -z "$vlist" ] ; then
4c3b3608 1185 alldomains=$(echo "$Le_Domain,$Le_Alt" | tr ',' ' ' )
a63b05a9 1186 _index=1
1187 _currentRoot=""
4c3b3608 1188 for d in $alldomains
a63b05a9 1189 do
1190 _info "Getting webroot for domain" $d
1191 _w="$(echo $Le_Webroot | cut -d , -f $_index)"
1192 _debug _w "$_w"
8663fb7e 1193 if [ "$_w" ] ; then
a63b05a9 1194 _currentRoot="$_w"
1195 fi
1196 _debug "_currentRoot" "$_currentRoot"
00a50605 1197 _index=$(_math $_index + 1)
a63b05a9 1198
1199 vtype="$VTYPE_HTTP"
dceb3aca 1200 if _startswith "$_currentRoot" "dns" ; then
a63b05a9 1201 vtype="$VTYPE_DNS"
1202 fi
4c3b3608 1203 _info "Getting token for domain" $d
1204 _send_signed_request "$API/acme/new-authz" "{\"resource\": \"new-authz\", \"identifier\": {\"type\": \"dns\", \"value\": \"$d\"}}"
8663fb7e 1205 if [ ! -z "$code" ] && [ ! "$code" = '201' ] ; then
4c3b3608 1206 _err "new-authz error: $response"
1207 _clearup
1208 return 1
1209 fi
1210
230234e7 1211 entry="$(printf "$response" | egrep -o '\{[^{]*"type":"'$vtype'"[^}]*')"
4c3b3608 1212 _debug entry "$entry"
1213
1214 token="$(printf "$entry" | egrep -o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')"
1215 _debug token $token
1216
1217 uri="$(printf "$entry" | egrep -o '"uri":"[^"]*'| cut -d : -f 2,3 | tr -d '"' )"
1218 _debug uri $uri
1219
1220 keyauthorization="$token.$thumbprint"
1221 _debug keyauthorization "$keyauthorization"
1222
a63b05a9 1223 dvlist="$d$sep$keyauthorization$sep$uri$sep$vtype$sep$_currentRoot"
4c3b3608 1224 _debug dvlist "$dvlist"
1225
1226 vlist="$vlist$dvlist,"
1227
1228 done
1229
1230 #add entry
1231 dnsadded=""
1232 ventries=$(echo "$vlist" | tr ',' ' ' )
1233 for ventry in $ventries
1234 do
1235 d=$(echo $ventry | cut -d $sep -f 1)
1236 keyauthorization=$(echo $ventry | cut -d $sep -f 2)
a63b05a9 1237 vtype=$(echo $ventry | cut -d $sep -f 4)
1238 _currentRoot=$(echo $ventry | cut -d $sep -f 5)
8663fb7e 1239 if [ "$vtype" = "$VTYPE_DNS" ] ; then
4c3b3608 1240 dnsadded='0'
1241 txtdomain="_acme-challenge.$d"
1242 _debug txtdomain "$txtdomain"
c1c7d87b 1243 txt="$(echo -n $keyauthorization | _digest "sha256" | _urlencode)"
4c3b3608 1244 _debug txt "$txt"
1245 #dns
1246 #1. check use api
1247 d_api=""
8663fb7e 1248 if [ -f "$LE_WORKING_DIR/$d/$_currentRoot" ] ; then
a63b05a9 1249 d_api="$LE_WORKING_DIR/$d/$_currentRoot"
8663fb7e 1250 elif [ -f "$LE_WORKING_DIR/$d/$_currentRoot.sh" ] ; then
a63b05a9 1251 d_api="$LE_WORKING_DIR/$d/$_currentRoot.sh"
8663fb7e 1252 elif [ -f "$LE_WORKING_DIR/$_currentRoot" ] ; then
a63b05a9 1253 d_api="$LE_WORKING_DIR/$_currentRoot"
8663fb7e 1254 elif [ -f "$LE_WORKING_DIR/$_currentRoot.sh" ] ; then
a63b05a9 1255 d_api="$LE_WORKING_DIR/$_currentRoot.sh"
8663fb7e 1256 elif [ -f "$LE_WORKING_DIR/dnsapi/$_currentRoot" ] ; then
a63b05a9 1257 d_api="$LE_WORKING_DIR/dnsapi/$_currentRoot"
8663fb7e 1258 elif [ -f "$LE_WORKING_DIR/dnsapi/$_currentRoot.sh" ] ; then
a63b05a9 1259 d_api="$LE_WORKING_DIR/dnsapi/$_currentRoot.sh"
4c3b3608 1260 fi
1261 _debug d_api "$d_api"
1262
8663fb7e 1263 if [ "$d_api" ] ; then
4c3b3608 1264 _info "Found domain api file: $d_api"
1265 else
1266 _err "Add the following TXT record:"
1267 _err "Domain: $txtdomain"
1268 _err "TXT value: $txt"
1269 _err "Please be aware that you prepend _acme-challenge. before your domain"
1270 _err "so the resulting subdomain will be: $txtdomain"
1271 continue
1272 fi
4c3b3608 1273
73b8b120 1274 (
8663fb7e 1275 if ! . $d_api ; then
73b8b120 1276 _err "Load file $d_api error. Please check your api file and try again."
1277 return 1
1278 fi
1279
158f22f7 1280 addcommand="${_currentRoot}_add"
d53289d7 1281 if ! _exists $addcommand ; then
73b8b120 1282 _err "It seems that your api file is not correct, it must have a function named: $addcommand"
1283 return 1
1284 fi
1285
1286 if ! $addcommand $txtdomain $txt ; then
1287 _err "Error add txt for domain:$txtdomain"
1288 return 1
1289 fi
1290 )
4c3b3608 1291
8663fb7e 1292 if [ "$?" != "0" ] ; then
5ef501c5 1293 _clearup
4c3b3608 1294 return 1
1295 fi
1296 dnsadded='1'
1297 fi
1298 done
1299
8663fb7e 1300 if [ "$dnsadded" = '0' ] ; then
4d2f38b0 1301 _savedomainconf "Le_Vlist" "$vlist"
4c3b3608 1302 _debug "Dns record not added yet, so, save to $DOMAIN_CONF and exit."
1303 _err "Please add the TXT records to the domains, and retry again."
5ef501c5 1304 _clearup
4c3b3608 1305 return 1
1306 fi
1307
1308 fi
1309
8663fb7e 1310 if [ "$dnsadded" = '1' ] ; then
4c3b3608 1311 _info "Sleep 60 seconds for the txt records to take effect"
1312 sleep 60
1313 fi
1314
1315 _debug "ok, let's start to verify"
a63b05a9 1316
4c3b3608 1317 ventries=$(echo "$vlist" | tr ',' ' ' )
1318 for ventry in $ventries
1319 do
1320 d=$(echo $ventry | cut -d $sep -f 1)
1321 keyauthorization=$(echo $ventry | cut -d $sep -f 2)
1322 uri=$(echo $ventry | cut -d $sep -f 3)
a63b05a9 1323 vtype=$(echo $ventry | cut -d $sep -f 4)
1324 _currentRoot=$(echo $ventry | cut -d $sep -f 5)
4c3b3608 1325 _info "Verifying:$d"
1326 _debug "d" "$d"
1327 _debug "keyauthorization" "$keyauthorization"
1328 _debug "uri" "$uri"
1329 removelevel=""
1330 token=""
a63b05a9 1331
1332 _debug "_currentRoot" "$_currentRoot"
1333
1334
8663fb7e 1335 if [ "$vtype" = "$VTYPE_HTTP" ] ; then
1336 if [ "$_currentRoot" = "no" ] ; then
4c3b3608 1337 _info "Standalone mode server"
1338 _startserver "$keyauthorization" &
8663fb7e 1339 if [ "$?" != "0" ] ; then
5ef501c5 1340 _clearup
6fc1447f 1341 return 1
1342 fi
4c3b3608 1343 serverproc="$!"
1344 sleep 2
1345 _debug serverproc $serverproc
6fc1447f 1346
4c3b3608 1347 else
8663fb7e 1348 if [ "$_currentRoot" = "apache" ] ; then
6f930641 1349 wellknown_path="$ACME_DIR"
1350 else
a63b05a9 1351 wellknown_path="$_currentRoot/.well-known/acme-challenge"
8663fb7e 1352 if [ ! -d "$_currentRoot/.well-known" ] ; then
6f930641 1353 removelevel='1'
8663fb7e 1354 elif [ ! -d "$_currentRoot/.well-known/acme-challenge" ] ; then
6f930641 1355 removelevel='2'
1356 else
1357 removelevel='3'
1358 fi
4c3b3608 1359 fi
6f930641 1360
4c3b3608 1361 _debug wellknown_path "$wellknown_path"
6f930641 1362
7939b419 1363 token="$(printf "%s" "$keyauthorization" | cut -d '.' -f 1)"
4c3b3608 1364 _debug "writing token:$token to $wellknown_path/$token"
1365
1366 mkdir -p "$wellknown_path"
7939b419 1367 printf "%s" "$keyauthorization" > "$wellknown_path/$token"
8663fb7e 1368 if [ ! "$usingApache" ] ; then
a63b05a9 1369 webroot_owner=$(_stat $_currentRoot)
df886ffa 1370 _debug "Changing owner/group of .well-known to $webroot_owner"
a63b05a9 1371 chown -R $webroot_owner "$_currentRoot/.well-known"
df886ffa 1372 fi
4c3b3608 1373
1374 fi
1375 fi
1376
1377 _send_signed_request $uri "{\"resource\": \"challenge\", \"keyAuthorization\": \"$keyauthorization\"}"
1378
8663fb7e 1379 if [ ! -z "$code" ] && [ ! "$code" = '202' ] ; then
c60883ef 1380 _err "$d:Challenge error: $response"
a63b05a9 1381 _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
4c3b3608 1382 _clearup
1383 return 1
1384 fi
1385
6fc1447f 1386 waittimes=0
8663fb7e 1387 if [ -z "$MAX_RETRY_TIMES" ] ; then
6fc1447f 1388 MAX_RETRY_TIMES=30
1389 fi
1390
8663fb7e 1391 while [ "1" ] ; do
00a50605 1392 waittimes=$(_math $waittimes + 1)
8663fb7e 1393 if [ "$waittimes" -ge "$MAX_RETRY_TIMES" ] ; then
6fc1447f 1394 _err "$d:Timeout"
1395 _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
1396 _clearup
1397 return 1
1398 fi
1399
4c3b3608 1400 _debug "sleep 5 secs to verify"
1401 sleep 5
1402 _debug "checking"
c60883ef 1403 response="$(_get $uri)"
8663fb7e 1404 if [ "$?" != "0" ] ; then
c60883ef 1405 _err "$d:Verify error:$response"
a63b05a9 1406 _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
4c3b3608 1407 _clearup
1408 return 1
1409 fi
1410
7d91e35f 1411 status=$(echo $response | egrep -o '"status":"[^"]*' | cut -d : -f 2 | tr -d '"')
8663fb7e 1412 if [ "$status" = "valid" ] ; then
4c3b3608 1413 _info "Success"
1414 _stopserver $serverproc
1415 serverproc=""
a63b05a9 1416 _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
4c3b3608 1417 break;
1418 fi
1419
8663fb7e 1420 if [ "$status" = "invalid" ] ; then
4c3b3608 1421 error=$(echo $response | egrep -o '"error":{[^}]*}' | grep -o '"detail":"[^"]*"' | cut -d '"' -f 4)
1422 _err "$d:Verify error:$error"
a63b05a9 1423 _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
4c3b3608 1424 _clearup
1425 return 1;
1426 fi
1427
8663fb7e 1428 if [ "$status" = "pending" ] ; then
4c3b3608 1429 _info "Pending"
1430 else
1431 _err "$d:Verify error:$response"
a63b05a9 1432 _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
4c3b3608 1433 _clearup
1434 return 1
1435 fi
1436
1437 done
1438
1439 done
1440
1441 _clearup
1442 _info "Verify finished, start to sign."
fa8311dc 1443 der="$(_getfile "${CSR_PATH}" "${BEGIN_CSR}" "${END_CSR}" | tr -d "\r\n" | _urlencode)"
4c3b3608 1444 _send_signed_request "$API/acme/new-cert" "{\"resource\": \"new-cert\", \"csr\": \"$der\"}" "needbase64"
1445
1446
bbbdcb09 1447 Le_LinkCert="$(grep -i -o '^Location.*$' $HTTP_HEADER | head -1 | tr -d "\r\n" | cut -d " " -f 2)"
4d2f38b0 1448 _savedomainconf "Le_LinkCert" "$Le_LinkCert"
4c3b3608 1449
8663fb7e 1450 if [ "$Le_LinkCert" ] ; then
88fab7d6 1451 echo "$BEGIN_CERT" > "$CERT_PATH"
c60883ef 1452 _get "$Le_LinkCert" | _base64 "multiline" >> "$CERT_PATH"
88fab7d6 1453 echo "$END_CERT" >> "$CERT_PATH"
4c3b3608 1454 _info "Cert success."
1455 cat "$CERT_PATH"
1456
1457 _info "Your cert is in $CERT_PATH"
caf1fc10 1458 cp "$CERT_PATH" "$CERT_FULLCHAIN_PATH"
281aa349 1459
8663fb7e 1460 if [ ! "$USER_PATH" ] || [ ! "$IN_CRON" ] ; then
281aa349 1461 USER_PATH="$PATH"
1462 _saveaccountconf "USER_PATH" "$USER_PATH"
1463 fi
4c3b3608 1464 fi
1465
1466
8663fb7e 1467 if [ -z "$Le_LinkCert" ] ; then
88fab7d6 1468 response="$(echo $response | _dbase64 "multiline" )"
4c3b3608 1469 _err "Sign failed: $(echo "$response" | grep -o '"detail":"[^"]*"')"
1470 return 1
1471 fi
1472
4d2f38b0 1473 _cleardomainconf "Le_Vlist"
4c3b3608 1474
bbbdcb09 1475 Le_LinkIssuer=$(grep -i '^Link' $HTTP_HEADER | head -1 | cut -d " " -f 2| cut -d ';' -f 1 | tr -d '<>' )
4d2f38b0 1476 _savedomainconf "Le_LinkIssuer" "$Le_LinkIssuer"
4c3b3608 1477
8663fb7e 1478 if [ "$Le_LinkIssuer" ] ; then
88fab7d6 1479 echo "$BEGIN_CERT" > "$CA_CERT_PATH"
c60883ef 1480 _get "$Le_LinkIssuer" | _base64 "multiline" >> "$CA_CERT_PATH"
88fab7d6 1481 echo "$END_CERT" >> "$CA_CERT_PATH"
4c3b3608 1482 _info "The intermediate CA cert is in $CA_CERT_PATH"
caf1fc10 1483 cat "$CA_CERT_PATH" >> "$CERT_FULLCHAIN_PATH"
1484 _info "And the full chain certs is there: $CERT_FULLCHAIN_PATH"
4c3b3608 1485 fi
1486
1487 Le_CertCreateTime=$(date -u "+%s")
4d2f38b0 1488 _savedomainconf "Le_CertCreateTime" "$Le_CertCreateTime"
4c3b3608 1489
1490 Le_CertCreateTimeStr=$(date -u )
4d2f38b0 1491 _savedomainconf "Le_CertCreateTimeStr" "$Le_CertCreateTimeStr"
4c3b3608 1492
8663fb7e 1493 if [ -z "$Le_RenewalDays" ] || [ "$Le_RenewalDays" -lt "0" ] || [ "$Le_RenewalDays" -gt "80" ] ; then
4c3b3608 1494 Le_RenewalDays=80
1495 fi
1496
4d2f38b0 1497 _savedomainconf "Le_RenewalDays" "$Le_RenewalDays"
00a50605 1498
1499 Le_NextRenewTime=$(_math $Le_CertCreateTime + $Le_RenewalDays \* 24 \* 60 \* 60)
4d2f38b0 1500 _savedomainconf "Le_NextRenewTime" "$Le_NextRenewTime"
4c3b3608 1501
1502 Le_NextRenewTimeStr=$( _time2str $Le_NextRenewTime )
4d2f38b0 1503 _savedomainconf "Le_NextRenewTimeStr" "$Le_NextRenewTimeStr"
4c3b3608 1504
1505
01f54558 1506 _output="$(installcert $Le_Domain "$Le_RealCertPath" "$Le_RealKeyPath" "$Le_RealCACertPath" "$Le_ReloadCmd" "$Le_RealFullChainPath" 2>&1)"
1507 _ret="$?"
1508 if [ "$_ret" = "9" ] ; then
ca2a96b3 1509 #ignore the empty install error.
1510 return 0
1511 fi
01f54558 1512 if [ "$_ret" != "0" ] ; then
1513 _err "$_output"
1514 return 1
1515 fi
4c3b3608 1516}
1517
1518renew() {
1519 Le_Domain="$1"
8663fb7e 1520 if [ -z "$Le_Domain" ] ; then
a7b7355d 1521 _err "Usage: $PROJECT_ENTRY --renew -d domain.com"
4c3b3608 1522 return 1
1523 fi
1524
1525 _initpath $Le_Domain
1526
8663fb7e 1527 if [ ! -f "$DOMAIN_CONF" ] ; then
4c3b3608 1528 _info "$Le_Domain is not a issued domain, skip."
1529 return 0;
1530 fi
1531
8663fb7e 1532 . "$DOMAIN_CONF"
1533 if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(date -u "+%s" )" -lt "$Le_NextRenewTime" ] ; then
4c3b3608 1534 _info "Skip, Next renewal time is: $Le_NextRenewTimeStr"
1535 return 2
1536 fi
1537
1538 IS_RENEW="1"
a63b05a9 1539 issue "$Le_Webroot" "$Le_Domain" "$Le_Alt" "$Le_Keylength" "$Le_RealCertPath" "$Le_RealKeyPath" "$Le_RealCACertPath" "$Le_ReloadCmd" "$Le_RealFullChainPath"
4c3b3608 1540 local res=$?
1541 IS_RENEW=""
1542
1543 return $res
1544}
1545
1546renewAll() {
1547 _initpath
b2817897 1548 for d in $(ls -F ${CERT_HOME}/ | grep [^.].*[.].*/$ ) ; do
4c3b3608 1549 d=$(echo $d | cut -d '/' -f 1)
4d2f38b0 1550 (
1551 _info "Renew: $d"
1552 renew "$d"
1553 )
4c3b3608 1554 done
1555
1556}
1557
1558installcert() {
1559 Le_Domain="$1"
8663fb7e 1560 if [ -z "$Le_Domain" ] ; then
a7b7355d 1561 echo "Usage: $PROJECT_ENTRY --installcert -d domain.com [--certpath cert-file-path] [--keypath key-file-path] [--capath ca-cert-file-path] [ --reloadCmd reloadCmd] [--fullchainpath fullchain-path]"
4c3b3608 1562 return 1
1563 fi
1564
1565 Le_RealCertPath="$2"
1566 Le_RealKeyPath="$3"
1567 Le_RealCACertPath="$4"
1568 Le_ReloadCmd="$5"
a63b05a9 1569 Le_RealFullChainPath="$6"
4c3b3608 1570
1571 _initpath $Le_Domain
1572
4d2f38b0 1573 _savedomainconf "Le_RealCertPath" "$Le_RealCertPath"
1574 _savedomainconf "Le_RealCACertPath" "$Le_RealCACertPath"
1575 _savedomainconf "Le_RealKeyPath" "$Le_RealKeyPath"
1576 _savedomainconf "Le_ReloadCmd" "$Le_ReloadCmd"
1577 _savedomainconf "Le_RealFullChainPath" "$Le_RealFullChainPath"
4c3b3608 1578
4d2f38b0 1579 if [ "$Le_RealCertPath" = "no" ] ; then
1580 Le_RealCertPath=""
1581 fi
1582 if [ "$Le_RealKeyPath" = "no" ] ; then
1583 Le_RealKeyPath=""
1584 fi
1585 if [ "$Le_RealCACertPath" = "no" ] ; then
1586 Le_RealCACertPath=""
1587 fi
1588 if [ "$Le_ReloadCmd" = "no" ] ; then
1589 Le_ReloadCmd=""
1590 fi
1591 if [ "$Le_RealFullChainPath" = "no" ] ; then
1592 Le_RealFullChainPath=""
1593 fi
1594
1595 _installed="0"
8663fb7e 1596 if [ "$Le_RealCertPath" ] ; then
4d2f38b0 1597 _installed=1
1598 _info "Installing cert to:$Le_RealCertPath"
8663fb7e 1599 if [ -f "$Le_RealCertPath" ] ; then
ff3bce32 1600 cp "$Le_RealCertPath" "$Le_RealCertPath".bak
4c3b3608 1601 fi
1602 cat "$CERT_PATH" > "$Le_RealCertPath"
1603 fi
1604
8663fb7e 1605 if [ "$Le_RealCACertPath" ] ; then
4d2f38b0 1606 _installed=1
1607 _info "Installing CA to:$Le_RealCACertPath"
8663fb7e 1608 if [ "$Le_RealCACertPath" = "$Le_RealCertPath" ] ; then
4c3b3608 1609 echo "" >> "$Le_RealCACertPath"
1610 cat "$CA_CERT_PATH" >> "$Le_RealCACertPath"
1611 else
8663fb7e 1612 if [ -f "$Le_RealCACertPath" ] ; then
ff3bce32 1613 cp "$Le_RealCACertPath" "$Le_RealCACertPath".bak
78552b18 1614 fi
4c3b3608 1615 cat "$CA_CERT_PATH" > "$Le_RealCACertPath"
1616 fi
1617 fi
1618
1619
8663fb7e 1620 if [ "$Le_RealKeyPath" ] ; then
4d2f38b0 1621 _installed=1
1622 _info "Installing key to:$Le_RealKeyPath"
8663fb7e 1623 if [ -f "$Le_RealKeyPath" ] ; then
ff3bce32 1624 cp "$Le_RealKeyPath" "$Le_RealKeyPath".bak
4c3b3608 1625 fi
1626 cat "$CERT_KEY_PATH" > "$Le_RealKeyPath"
1627 fi
a63b05a9 1628
8663fb7e 1629 if [ "$Le_RealFullChainPath" ] ; then
4d2f38b0 1630 _installed=1
1631 _info "Installing full chain to:$Le_RealFullChainPath"
8663fb7e 1632 if [ -f "$Le_RealFullChainPath" ] ; then
ff3bce32 1633 cp "$Le_RealFullChainPath" "$Le_RealFullChainPath".bak
a63b05a9 1634 fi
1635 cat "$CERT_FULLCHAIN_PATH" > "$Le_RealFullChainPath"
1636 fi
4c3b3608 1637
8663fb7e 1638 if [ "$Le_ReloadCmd" ] ; then
4d2f38b0 1639 _installed=1
4c3b3608 1640 _info "Run Le_ReloadCmd: $Le_ReloadCmd"
4d2f38b0 1641 if (cd "$DOMAIN_PATH" && eval "$Le_ReloadCmd") ; then
1642 _info "Reload success."
1643 else
1644 _err "Reload error for :$Le_Domain"
1645 fi
1646 fi
1647
1648 if [ "$_installed" = "0" ] ; then
1649 _err "Nothing to install. You don't specify any parameter."
ca2a96b3 1650 return 9
4c3b3608 1651 fi
1652
1653}
1654
1655installcronjob() {
1656 _initpath
77546ea5 1657 if ! _exists "crontab" ; then
1658 _err "crontab doesn't exist, so, we can not install cron jobs."
1659 _err "All your certs will not be renewed automatically."
a7b7355d 1660 _err "You must add your own cron job to call '$PROJECT_ENTRY --cron' everyday."
77546ea5 1661 return 1
1662 fi
1663
4c3b3608 1664 _info "Installing cron job"
a7b7355d 1665 if ! crontab -l | grep "$PROJECT_ENTRY --cron" ; then
8663fb7e 1666 if [ -f "$LE_WORKING_DIR/$PROJECT_ENTRY" ] ; then
a7b7355d 1667 lesh="\"$LE_WORKING_DIR\"/$PROJECT_ENTRY"
4c3b3608 1668 else
a7b7355d 1669 _err "Can not install cronjob, $PROJECT_ENTRY not found."
4c3b3608 1670 return 1
1671 fi
a7b7355d 1672 crontab -l | { cat; echo "0 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" > /dev/null"; } | crontab -
4c3b3608 1673 fi
8663fb7e 1674 if [ "$?" != "0" ] ; then
4c3b3608 1675 _err "Install cron job failed. You need to manually renew your certs."
1676 _err "Or you can add cronjob by yourself:"
a7b7355d 1677 _err "$lesh --cron --home \"$LE_WORKING_DIR\" > /dev/null"
4c3b3608 1678 return 1
1679 fi
1680}
1681
1682uninstallcronjob() {
37db5b81 1683 if ! _exists "crontab" ; then
1684 return
1685 fi
4c3b3608 1686 _info "Removing cron job"
a7b7355d 1687 cr="$(crontab -l | grep "$PROJECT_ENTRY --cron")"
8663fb7e 1688 if [ "$cr" ] ; then
a7b7355d 1689 crontab -l | sed "/$PROJECT_ENTRY --cron/d" | crontab -
1690 LE_WORKING_DIR="$(echo "$cr" | cut -d ' ' -f 9 | tr -d '"')"
4c3b3608 1691 _info LE_WORKING_DIR "$LE_WORKING_DIR"
1692 fi
1693 _initpath
a7b7355d 1694
4c3b3608 1695}
1696
6cb415f5 1697revoke() {
1698 Le_Domain="$1"
8663fb7e 1699 if [ -z "$Le_Domain" ] ; then
a7b7355d 1700 echo "Usage: $PROJECT_ENTRY --revoke -d domain.com"
6cb415f5 1701 return 1
1702 fi
1703
1704 _initpath $Le_Domain
8663fb7e 1705 if [ ! -f "$DOMAIN_CONF" ] ; then
6cb415f5 1706 _err "$Le_Domain is not a issued domain, skip."
1707 return 1;
1708 fi
1709
8663fb7e 1710 if [ ! -f "$CERT_PATH" ] ; then
6cb415f5 1711 _err "Cert for $Le_Domain $CERT_PATH is not found, skip."
1712 return 1
1713 fi
1714
1715 cert="$(_getfile "${CERT_PATH}" "${BEGIN_CERT}" "${END_CERT}"| tr -d "\r\n" | _urlencode)"
1716
8663fb7e 1717 if [ -z "$cert" ] ; then
6cb415f5 1718 _err "Cert for $Le_Domain is empty found, skip."
1719 return 1
1720 fi
1721
1722 data="{\"resource\": \"revoke-cert\", \"certificate\": \"$cert\"}"
1723 uri="$API/acme/revoke-cert"
1724
1725 _info "Try domain key first."
1726 if _send_signed_request $uri "$data" "" "$CERT_KEY_PATH"; then
8663fb7e 1727 if [ -z "$response" ] ; then
6cb415f5 1728 _info "Revoke success."
1729 rm -f $CERT_PATH
1730 return 0
1731 else
1732 _err "Revoke error by domain key."
1733 _err "$resource"
1734 fi
1735 fi
1736
1737 _info "Then try account key."
1738
1739 if _send_signed_request $uri "$data" "" "$ACCOUNT_KEY_PATH" ; then
8663fb7e 1740 if [ -z "$response" ] ; then
6cb415f5 1741 _info "Revoke success."
1742 rm -f $CERT_PATH
1743 return 0
1744 else
1745 _err "Revoke error."
1746 _debug "$resource"
1747 fi
1748 fi
1749 return 1
1750}
4c3b3608 1751
1752# Detect profile file if not specified as environment variable
1753_detect_profile() {
a63b05a9 1754 if [ -n "$PROFILE" -a -f "$PROFILE" ] ; then
4c3b3608 1755 echo "$PROFILE"
1756 return
1757 fi
1758
1759 local DETECTED_PROFILE
1760 DETECTED_PROFILE=''
1761 local SHELLTYPE
1762 SHELLTYPE="$(basename "/$SHELL")"
1763
8663fb7e 1764 if [ "$SHELLTYPE" = "bash" ] ; then
1765 if [ -f "$HOME/.bashrc" ] ; then
4c3b3608 1766 DETECTED_PROFILE="$HOME/.bashrc"
8663fb7e 1767 elif [ -f "$HOME/.bash_profile" ] ; then
4c3b3608 1768 DETECTED_PROFILE="$HOME/.bash_profile"
1769 fi
8663fb7e 1770 elif [ "$SHELLTYPE" = "zsh" ] ; then
4c3b3608 1771 DETECTED_PROFILE="$HOME/.zshrc"
1772 fi
1773
8663fb7e 1774 if [ -z "$DETECTED_PROFILE" ] ; then
1775 if [ -f "$HOME/.profile" ] ; then
4c3b3608 1776 DETECTED_PROFILE="$HOME/.profile"
8663fb7e 1777 elif [ -f "$HOME/.bashrc" ] ; then
4c3b3608 1778 DETECTED_PROFILE="$HOME/.bashrc"
8663fb7e 1779 elif [ -f "$HOME/.bash_profile" ] ; then
4c3b3608 1780 DETECTED_PROFILE="$HOME/.bash_profile"
8663fb7e 1781 elif [ -f "$HOME/.zshrc" ] ; then
4c3b3608 1782 DETECTED_PROFILE="$HOME/.zshrc"
1783 fi
1784 fi
1785
8663fb7e 1786 if [ ! -z "$DETECTED_PROFILE" ] ; then
4c3b3608 1787 echo "$DETECTED_PROFILE"
1788 fi
1789}
1790
1791_initconf() {
1792 _initpath
8663fb7e 1793 if [ ! -f "$ACCOUNT_CONF_PATH" ] ; then
d53289d7 1794 echo "#ACCOUNT_CONF_PATH=xxxx
1795
1796#Account configurations:
4c3b3608 1797#Here are the supported macros, uncomment them to make them take effect.
d53289d7 1798
4c3b3608 1799#ACCOUNT_EMAIL=aaa@aaa.com # the account email used to register account.
5fd3f21b 1800#ACCOUNT_KEY_PATH=\"/path/to/account.key\"
b2817897 1801#CERT_HOME=\"/path/to/cert/home\"
4c3b3608 1802
1803#STAGE=1 # Use the staging api
1804#FORCE=1 # Force to issue cert
1805#DEBUG=1 # Debug mode
1806
166096dc 1807#ACCOUNT_KEY_HASH=account key hash
1808
635695ec 1809USER_AGENT=\"$USER_AGENT\"
281aa349 1810
1811#USER_PATH=""
1812
4c3b3608 1813#dns api
1814#######################
1815#Cloudflare:
1816#api key
3d49985a 1817#CF_Key=\"sdfsdfsdfljlbjkljlkjsdfoiwje\"
4c3b3608 1818#account email
3d49985a 1819#CF_Email=\"xxxx@sss.com\"
4c3b3608 1820
1821#######################
1822#Dnspod.cn:
1823#api key id
3d49985a 1824#DP_Id=\"1234\"
4c3b3608 1825#api key
3d49985a 1826#DP_Key=\"sADDsdasdgdsf\"
4c3b3608 1827
1828#######################
1829#Cloudxns.com:
3d49985a 1830#CX_Key=\"1234\"
4c3b3608 1831#
3d49985a 1832#CX_Secret=\"sADDsdasdgdsf\"
4c3b3608 1833
1834 " > $ACCOUNT_CONF_PATH
1835 fi
1836}
1837
c60883ef 1838_precheck() {
1839 if ! _exists "curl" && ! _exists "wget"; then
1840 _err "Please install curl or wget first, we need to access http resources."
4c3b3608 1841 return 1
1842 fi
1843
c60883ef 1844 if ! _exists "crontab" ; then
77546ea5 1845 _err "It is recommended to install crontab first. try to install 'cron, crontab, crontabs or vixie-cron'."
c60883ef 1846 _err "We need to set cron job to renew the certs automatically."
77546ea5 1847 _err "Otherwise, your certs will not be able to be renewed automatically."
8663fb7e 1848 if [ -z "$FORCE" ] ; then
a7b7355d 1849 _err "Please add '--force' and try install again to go without crontab."
1850 _err "./$PROJECT_ENTRY --install --force"
77546ea5 1851 return 1
1852 fi
4c3b3608 1853 fi
1854
c60883ef 1855 if ! _exists "openssl" ; then
1856 _err "Please install openssl first."
1857 _err "We need openssl to generate keys."
4c3b3608 1858 return 1
1859 fi
1860
c60883ef 1861 if ! _exists "nc" ; then
1862 _err "It is recommended to install nc first, try to install 'nc' or 'netcat'."
1863 _err "We use nc for standalone server if you use standalone mode."
1864 _err "If you don't use standalone mode, just ignore this warning."
1865 fi
1866
1867 return 0
1868}
1869
0a7c9364 1870_setShebang() {
1871 _file="$1"
1872 _shebang="$2"
1873 if [ -z "$_shebang" ] ; then
1874 _err "Usage: file shebang"
1875 return 1
1876 fi
1877 cp "$_file" "$_file.tmp"
1878 echo "$_shebang" > "$_file"
1879 sed -n 2,99999p "$_file.tmp" >> "$_file"
1880 rm -f "$_file.tmp"
1881}
1882
94dc5f33 1883_installalias() {
1884 _initpath
1885
1886 _envfile="$LE_WORKING_DIR/$PROJECT_ENTRY.env"
1887 if [ "$_upgrading" ] && [ "$_upgrading" = "1" ] ; then
1888 echo "$(cat $_envfile)" | sed "s|^LE_WORKING_DIR.*$||" > "$_envfile"
1889 echo "$(cat $_envfile)" | sed "s|^alias le.*$||" > "$_envfile"
1890 echo "$(cat $_envfile)" | sed "s|^alias le.sh.*$||" > "$_envfile"
1891 fi
1892
1786a5e5 1893 _setopt "$_envfile" "export LE_WORKING_DIR" "=" "\"$LE_WORKING_DIR\""
94dc5f33 1894 _setopt "$_envfile" "alias $PROJECT_ENTRY" "=" "\"$LE_WORKING_DIR/$PROJECT_ENTRY\""
1895
1896 _profile="$(_detect_profile)"
1897 if [ "$_profile" ] ; then
1898 _debug "Found profile: $_profile"
1899 _setopt "$_profile" ". \"$_envfile\""
1900 _info "OK, Close and reopen your terminal to start using $PROJECT_NAME"
1901 else
1902 _info "No profile is found, you will need to go into $LE_WORKING_DIR to use $PROJECT_NAME"
1903 fi
1904
1905
1906 #for csh
1907 _cshfile="$LE_WORKING_DIR/$PROJECT_ENTRY.csh"
94dc5f33 1908 _csh_profile="$HOME/.cshrc"
1909 if [ -f "$_csh_profile" ] ; then
6626371d 1910 _setopt "$_cshfile" "setenv LE_WORKING_DIR" " " "\"$LE_WORKING_DIR\""
1911 _setopt "$_cshfile" "alias $PROJECT_ENTRY" " " "\"$LE_WORKING_DIR/$PROJECT_ENTRY\""
94dc5f33 1912 _setopt "$_csh_profile" "source \"$_cshfile\""
1913 fi
1914
1915}
1916
c60883ef 1917install() {
635695ec 1918
c60883ef 1919 if ! _initpath ; then
1920 _err "Install failed."
4c3b3608 1921 return 1
1922 fi
635695ec 1923
c60883ef 1924 if ! _precheck ; then
1925 _err "Pre-check failed, can not install."
4c3b3608 1926 return 1
1927 fi
c60883ef 1928
6cc11ffb 1929 #convert from le
8663fb7e 1930 if [ -d "$HOME/.le" ] ; then
6cc11ffb 1931 for envfile in "le.env" "le.sh.env"
1932 do
8663fb7e 1933 if [ -f "$HOME/.le/$envfile" ] ; then
6cc11ffb 1934 if grep "le.sh" "$HOME/.le/$envfile" >/dev/null ; then
1935 _upgrading="1"
1936 _info "You are upgrading from le.sh"
1937 _info "Renaming \"$HOME/.le\" to $LE_WORKING_DIR"
1938 mv "$HOME/.le" "$LE_WORKING_DIR"
1939 mv "$LE_WORKING_DIR/$envfile" "$LE_WORKING_DIR/$PROJECT_ENTRY.env"
1940 break;
1941 fi
1942 fi
1943 done
1944 fi
1945
4c3b3608 1946 _info "Installing to $LE_WORKING_DIR"
635695ec 1947
4a0f23e2 1948 if ! mkdir -p "$LE_WORKING_DIR" ; then
1949 _err "Can not craete working dir: $LE_WORKING_DIR"
1950 return 1
1951 fi
1952
762978f8 1953 chmod 700 "$LE_WORKING_DIR"
1954
a7b7355d 1955 cp $PROJECT_ENTRY "$LE_WORKING_DIR/" && chmod +x "$LE_WORKING_DIR/$PROJECT_ENTRY"
4c3b3608 1956
8663fb7e 1957 if [ "$?" != "0" ] ; then
a7b7355d 1958 _err "Install failed, can not copy $PROJECT_ENTRY"
4c3b3608 1959 return 1
1960 fi
1961
a7b7355d 1962 _info "Installed to $LE_WORKING_DIR/$PROJECT_ENTRY"
4c3b3608 1963
94dc5f33 1964 _installalias
4c3b3608 1965
8663fb7e 1966 if [ -d "dnsapi" ] ; then
6ed1c718 1967 mkdir -p $LE_WORKING_DIR/dnsapi
1968 cp dnsapi/* $LE_WORKING_DIR/dnsapi/
1969 fi
d53289d7 1970
8663fb7e 1971 if [ ! -f "$ACCOUNT_CONF_PATH" ] ; then
4c3b3608 1972 _initconf
1973 fi
6cc11ffb 1974
8663fb7e 1975 if [ "$_DEFAULT_ACCOUNT_CONF_PATH" != "$ACCOUNT_CONF_PATH" ] ; then
635695ec 1976 _setopt "$_DEFAULT_ACCOUNT_CONF_PATH" "ACCOUNT_CONF_PATH" "=" "\"$ACCOUNT_CONF_PATH\""
6cc11ffb 1977 fi
1978
8663fb7e 1979 if [ "$_DEFAULT_CERT_HOME" != "$CERT_HOME" ] ; then
b2817897 1980 _saveaccountconf "CERT_HOME" "$CERT_HOME"
1981 fi
1982
8663fb7e 1983 if [ "$_DEFAULT_ACCOUNT_KEY_PATH" != "$ACCOUNT_KEY_PATH" ] ; then
b2817897 1984 _saveaccountconf "ACCOUNT_KEY_PATH" "$ACCOUNT_KEY_PATH"
1985 fi
1986
d53289d7 1987 installcronjob
0a7c9364 1988
641989fd 1989 if [ -z "$NO_DETECT_SH" ] ; then
1990 #Modify shebang
1991 if _exists bash ; then
1992 _info "Good, bash is installed, change the shebang to use bash as prefered."
1993 _shebang='#!/usr/bin/env bash'
1994 _setShebang "$LE_WORKING_DIR/$PROJECT_ENTRY" "$_shebang"
1995 if [ -d "$LE_WORKING_DIR/dnsapi" ] ; then
1996 for _apifile in $(ls "$LE_WORKING_DIR/dnsapi/"*.sh) ; do
1997 _setShebang "$_apifile" "$_shebang"
1998 done
1999 fi
0a7c9364 2000 fi
2001 fi
2002
4c3b3608 2003 _info OK
2004}
2005
2006uninstall() {
2007 uninstallcronjob
2008 _initpath
2009
2010 _profile="$(_detect_profile)"
8663fb7e 2011 if [ "$_profile" ] ; then
7203a1c1 2012 text="$(cat $_profile)"
94dc5f33 2013 echo "$text" | sed "s|^.*\"$LE_WORKING_DIR/$PROJECT_NAME.env\"$||" > "$_profile"
4c3b3608 2014 fi
2015
94dc5f33 2016 _csh_profile="$HOME/.cshrc"
2017 if [ -f "$_csh_profile" ] ; then
2018 text="$(cat $_csh_profile)"
2019 echo "$text" | sed "s|^.*\"$LE_WORKING_DIR/$PROJECT_NAME.csh\"$||" > "$_csh_profile"
2020 fi
2021
a7b7355d 2022 rm -f $LE_WORKING_DIR/$PROJECT_ENTRY
4c3b3608 2023 _info "The keys and certs are in $LE_WORKING_DIR, you can remove them by yourself."
2024
2025}
2026
2027cron() {
281aa349 2028 IN_CRON=1
4c3b3608 2029 renewAll
281aa349 2030 IN_CRON=""
4c3b3608 2031}
2032
2033version() {
a63b05a9 2034 echo "$PROJECT"
2035 echo "v$VER"
4c3b3608 2036}
2037
2038showhelp() {
2039 version
a7b7355d 2040 echo "Usage: $PROJECT_ENTRY command ...[parameters]....
a63b05a9 2041Commands:
2042 --help, -h Show this help message.
2043 --version, -v Show version info.
a7b7355d 2044 --install Install $PROJECT_NAME to your system.
2045 --uninstall Uninstall $PROJECT_NAME, and uninstall the cron job.
a63b05a9 2046 --issue Issue a cert.
2047 --installcert Install the issued cert to apache/nginx or any other server.
2048 --renew, -r Renew a cert.
2049 --renewAll Renew all the certs
2050 --revoke Revoke a cert.
2051 --installcronjob Install the cron job to renew certs, you don't need to call this. The 'install' command can automatically install the cron job.
2052 --uninstallcronjob Uninstall the cron job. The 'uninstall' command can do this automatically.
2053 --cron Run cron job to renew all the certs.
2054 --toPkcs Export the certificate and key to a pfx file.
2055 --createAccountKey, -cak Create an account private key, professional use.
2056 --createDomainKey, -cdk Create an domain private key, professional use.
2057 --createCSR, -ccsr Create CSR , professional use.
2058
2059Parameters:
2060 --domain, -d domain.tld Specifies a domain, used to issue, renew or revoke etc.
2061 --force, -f Used to force to install or force to renew a cert immediately.
2062 --staging, --test Use staging server, just for test.
2063 --debug Output debug info.
2064
2065 --webroot, -w /path/to/webroot Specifies the web root folder for web root mode.
2066 --standalone Use standalone mode.
2067 --apache Use apache mode.
eccec5f6 2068 --dns [dns_cf|dns_dp|dns_cx|/path/to/api/file] Use dns mode or dns api.
a63b05a9 2069
2070 --keylength, -k [2048] Specifies the domain key length: 2048, 3072, 4096, 8192 or ec-256, ec-384.
2071 --accountkeylength, -ak [2048] Specifies the account key length.
2072
2073 These parameters are to install the cert to nginx/apache or anyother server after issue/renew a cert:
2074
2075 --certpath /path/to/real/cert/file After issue/renew, the cert will be copied to this path.
2076 --keypath /path/to/real/key/file After issue/renew, the key will be copied to this path.
2077 --capath /path/to/real/ca/file After issue/renew, the intermediate cert will be copied to this path.
2078 --fullchainpath /path/to/fullchain/file After issue/renew, the fullchain cert will be copied to this path.
2079
2080 --reloadcmd \"service nginx reload\" After issue/renew, it's used to reload the server.
2081
2082 --accountconf Specifies a customized account config file.
635695ec 2083 --home Specifies the home dir for $PROJECT_NAME .
b2817897 2084 --certhome Specifies the home dir to save all the certs.
635695ec 2085 --useragent Specifies the user agent string. it will be saved for future use too.
b5eb4b90 2086 --accountemail Specifies the account email for registering, Only valid for the '--install' command.
06625071 2087 --accountkey Specifies the account key path, Only valid for the '--install' command.
2088 --days Specifies the days to renew the cert when using '--issue' command. The max value is 80 days.
a63b05a9 2089
4c3b3608 2090 "
2091}
2092
4a0f23e2 2093_installOnline() {
2094 _info "Installing from online archive."
8663fb7e 2095 if [ ! "$BRANCH" ] ; then
4a0f23e2 2096 BRANCH="master"
2097 fi
2098 _initpath
2099 target="$PROJECT/archive/$BRANCH.tar.gz"
2100 _info "Downloading $target"
2101 localname="$BRANCH.tar.gz"
2102 if ! _get "$target" > $localname ; then
2103 _debug "Download error."
2104 return 1
2105 fi
2106 _info "Extracting $localname"
2107 tar xzf $localname
6cc11ffb 2108 cd "$PROJECT_NAME-$BRANCH"
a7b7355d 2109 chmod +x $PROJECT_ENTRY
2110 if ./$PROJECT_ENTRY install ; then
4a0f23e2 2111 _info "Install success!"
2112 fi
2113
2114 cd ..
6cc11ffb 2115 rm -rf "$PROJECT_NAME-$BRANCH"
4a0f23e2 2116 rm -f "$localname"
2117}
2118
a63b05a9 2119
2120_process() {
2121 _CMD=""
2122 _domain=""
2123 _altdomains="no"
2124 _webroot=""
2125 _keylength="no"
2126 _accountkeylength="no"
2127 _certpath="no"
2128 _keypath="no"
2129 _capath="no"
2130 _fullchainpath="no"
4d2f38b0 2131 _reloadcmd=""
a63b05a9 2132 _password=""
635695ec 2133 _accountconf=""
2134 _useragent=""
b5eb4b90 2135 _accountemail=""
2136 _accountkey=""
b2817897 2137 _certhome=""
8663fb7e 2138 while [ ${#} -gt 0 ] ; do
a63b05a9 2139 case "${1}" in
2140
2141 --help|-h)
2142 showhelp
2143 return
2144 ;;
2145 --version|-v)
2146 version
2147 return
2148 ;;
2149 --install)
2150 _CMD="install"
2151 ;;
2152 --uninstall)
2153 _CMD="uninstall"
2154 ;;
2155 --issue)
2156 _CMD="issue"
2157 ;;
2158 --installcert|-i)
2159 _CMD="installcert"
2160 ;;
2161 --renew|-r)
2162 _CMD="renew"
2163 ;;
4d2f38b0 2164 --renewAll|--renewall)
a63b05a9 2165 _CMD="renewAll"
2166 ;;
2167 --revoke)
2168 _CMD="revoke"
2169 ;;
2170 --installcronjob)
2171 _CMD="installcronjob"
2172 ;;
2173 --uninstallcronjob)
2174 _CMD="uninstallcronjob"
2175 ;;
2176 --cron)
2177 _CMD="cron"
2178 ;;
2179 --toPkcs)
2180 _CMD="toPkcs"
2181 ;;
2182 --createAccountKey|--createaccountkey|-cak)
2183 _CMD="createAccountKey"
2184 ;;
2185 --createDomainKey|--createdomainkey|-cdk)
2186 _CMD="createDomainKey"
2187 ;;
2188 --createCSR|--createcsr|-ccr)
2189 _CMD="createCSR"
2190 ;;
2191
2192
2193 --domain|-d)
2194 _dvalue="$2"
2195
8663fb7e 2196 if [ -z "$_dvalue" ] || _startswith "$_dvalue" "-" ; then
a63b05a9 2197 _err "'$_dvalue' is not a valid domain for parameter '$1'"
2198 return 1
2199 fi
2200
8663fb7e 2201 if [ -z "$_domain" ] ; then
a63b05a9 2202 _domain="$_dvalue"
2203 else
8663fb7e 2204 if [ "$_altdomains" = "no" ] ; then
a63b05a9 2205 _altdomains="$_dvalue"
2206 else
2207 _altdomains="$_altdomains,$_dvalue"
2208 fi
2209 fi
2210 shift
2211 ;;
2212
2213 --force|-f)
2214 FORCE="1"
2215 ;;
2216 --staging|--test)
2217 STAGE="1"
2218 ;;
2219 --debug)
8663fb7e 2220 if [ -z "$2" ] || _startswith "$2" "-" ; then
a63b05a9 2221 DEBUG="1"
2222 else
2223 DEBUG="$2"
2224 shift
6fc1447f 2225 fi
a63b05a9 2226 ;;
a63b05a9 2227 --webroot|-w)
2228 wvalue="$2"
8663fb7e 2229 if [ -z "$_webroot" ] ; then
a63b05a9 2230 _webroot="$wvalue"
2231 else
2232 _webroot="$_webroot,$wvalue"
2233 fi
2234 shift
2235 ;;
2236 --standalone)
2237 wvalue="no"
8663fb7e 2238 if [ -z "$_webroot" ] ; then
a63b05a9 2239 _webroot="$wvalue"
2240 else
2241 _webroot="$_webroot,$wvalue"
2242 fi
2243 ;;
2244 --apache)
2245 wvalue="apache"
8663fb7e 2246 if [ -z "$_webroot" ] ; then
a63b05a9 2247 _webroot="$wvalue"
2248 else
2249 _webroot="$_webroot,$wvalue"
2250 fi
2251 ;;
2252 --dns)
2253 wvalue="dns"
dceb3aca 2254 if ! _startswith "$2" "-" ; then
a63b05a9 2255 wvalue="$2"
2256 shift
2257 fi
8663fb7e 2258 if [ -z "$_webroot" ] ; then
a63b05a9 2259 _webroot="$wvalue"
2260 else
2261 _webroot="$_webroot,$wvalue"
2262 fi
2263 ;;
2264 --keylength|-k)
2265 _keylength="$2"
2266 accountkeylength="$2"
2267 shift
2268 ;;
2269 --accountkeylength|-ak)
2270 accountkeylength="$2"
2271 shift
2272 ;;
2273
2274 --certpath)
2275 _certpath="$2"
2276 shift
2277 ;;
2278 --keypath)
2279 _keypath="$2"
2280 shift
2281 ;;
2282 --capath)
2283 _capath="$2"
2284 shift
2285 ;;
2286 --fullchainpath)
2287 _fullchainpath="$2"
2288 shift
2289 ;;
635695ec 2290 --reloadcmd|--reloadCmd)
a63b05a9 2291 _reloadcmd="$2"
2292 shift
2293 ;;
2294 --password)
2295 _password="$2"
2296 shift
2297 ;;
2298 --accountconf)
635695ec 2299 _accountconf="$2"
2300 ACCOUNT_CONF_PATH="$_accountconf"
a7b7355d 2301 shift
a63b05a9 2302 ;;
a7b7355d 2303 --home)
a63b05a9 2304 LE_WORKING_DIR="$2"
a7b7355d 2305 shift
a63b05a9 2306 ;;
b2817897 2307 --certhome)
2308 _certhome="$2"
2309 CERT_HOME="$_certhome"
2310 shift
2311 ;;
635695ec 2312 --useragent)
2313 _useragent="$2"
2314 USER_AGENT="$_useragent"
2315 shift
2316 ;;
b5eb4b90 2317 --accountemail )
2318 _accountemail="$2"
2319 ACCOUNT_EMAIL="$_accountemail"
2320 shift
2321 ;;
2322 --accountkey )
2323 _accountkey="$2"
2324 ACCOUNT_KEY_PATH="$_accountkey"
2325 shift
2326 ;;
06625071 2327 --days )
2328 _days="$2"
2329 Le_RenewalDays="$_days"
2330 shift
2331 ;;
a63b05a9 2332 *)
2333 _err "Unknown parameter : $1"
2334 return 1
2335 ;;
2336 esac
2337
2338 shift 1
2339 done
2340
2341
2342 case "${_CMD}" in
2343 install) install ;;
2344 uninstall) uninstall ;;
2345 issue)
70a55875 2346 issue "$_webroot" "$_domain" "$_altdomains" "$_keylength" "$_certpath" "$_keypath" "$_capath" "$_reloadcmd" "$_fullchainpath"
a63b05a9 2347 ;;
2348 installcert)
3ed4102a 2349 installcert "$_domain" "$_certpath" "$_keypath" "$_capath" "$_reloadcmd" "$_fullchainpath"
a63b05a9 2350 ;;
2351 renew)
2352 renew "$_domain"
2353 ;;
2354 renewAll)
2355 renewAll
2356 ;;
2357 revoke)
2358 revoke "$_domain"
2359 ;;
2360 installcronjob) installcronjob ;;
2361 uninstallcronjob) uninstallcronjob ;;
2362 cron) cron ;;
2363 toPkcs)
2364 toPkcs "$_domain" "$_password"
2365 ;;
2366 createAccountKey)
2367 createAccountKey "$_domain" "$_accountkeylength"
2368 ;;
2369 createDomainKey)
2370 createDomainKey "$_domain" "$_keylength"
2371 ;;
2372 createCSR)
2373 createCSR "$_domain" "$_altdomains"
2374 ;;
2375
2376 *)
2377 _err "Invalid command: $_CMD"
2378 showhelp;
2379 return 1
2380 ;;
2381 esac
2382
8663fb7e 2383 if [ "$_useragent" ] ; then
635695ec 2384 _saveaccountconf "USER_AGENT" "$_useragent"
2385 fi
8663fb7e 2386 if [ "$_accountemail" ] ; then
b5eb4b90 2387 _saveaccountconf "ACCOUNT_EMAIL" "$_accountemail"
2388 fi
b2817897 2389
635695ec 2390
a63b05a9 2391}
2392
2393
8663fb7e 2394if [ "$INSTALLONLINE" ] ; then
d1f97fc8 2395 INSTALLONLINE=""
4a0f23e2 2396 _installOnline $BRANCH
2397 exit
2398fi
4c3b3608 2399
8663fb7e 2400if [ -z "$1" ] ; then
4c3b3608 2401 showhelp
2402else
036e9d10 2403 if echo "$1" | grep "^-" >/dev/null 2>&1 ; then
a63b05a9 2404 _process "$@"
2405 else
2406 "$@"
2407 fi
4c3b3608 2408fi
a63b05a9 2409
2410