@ -1,6 +1,6 @@
#!/usr/bin/env sh
#!/usr/bin/env sh
VER = 2.3.5
VER = 2.3.6
PROJECT_NAME = "acme.sh"
PROJECT_NAME = "acme.sh"
@ -76,6 +76,13 @@ _debug2() {
return
return
}
}
_debug3( ) {
if [ " $DEBUG " ] && [ " $DEBUG " -ge "3" ] ; then
_debug " $@ "
fi
return
}
_startswith( ) {
_startswith( ) {
_str = " $1 "
_str = " $1 "
_sub = " $2 "
_sub = " $2 "
@ -215,6 +222,14 @@ _sed_i() {
fi
fi
}
}
_egrep_o( ) {
if _contains " $( egrep -o 2>& 1) " "egrep: illegal option -- o" ; then
sed -n 's/.*\(' " $1 " '\).*/\1/p'
else
egrep -o " $1 "
fi
}
#Usage: file startline endline
#Usage: file startline endline
_getfile( ) {
_getfile( ) {
filename = " $1 "
filename = " $1 "
@ -406,6 +421,9 @@ _ss() {
else
else
if netstat -help 2>& 1 | grep "\-p protocol" >/dev/null ; then
if netstat -help 2>& 1 | grep "\-p protocol" >/dev/null ; then
netstat -an -p tcp | grep LISTEN | grep " : $_port "
netstat -an -p tcp | grep LISTEN | grep " : $_port "
elif netstat -help 2>& 1 | grep -- '-P protocol' >/dev/null ; then
#for solaris
netstat -an -P tcp | grep " \. $_port "
else
else
netstat -ntpl | grep " : $_port "
netstat -ntpl | grep " : $_port "
fi
fi
@ -535,6 +553,11 @@ _time2str() {
return
return
fi
fi
#Soaris
if _exists adb ; then
echo $( echo " 0t ${ 1 } =Y " | adb)
fi
}
}
_normalizeJson( ) {
_normalizeJson( ) {
@ -569,66 +592,67 @@ _calcjwk() {
if [ " ${# pub_exp } " = "5" ] ; then
if [ " ${# pub_exp } " = "5" ] ; then
pub_exp = 0$pub_exp
pub_exp = 0$pub_exp
fi
fi
_debug2 pub_exp " $pub_exp "
_debug3 pub_exp " $pub_exp "
e = $( echo $pub_exp | _h2b | _base64)
e = $( echo $pub_exp | _h2b | _base64)
_debug2 e " $e "
_debug3 e " $e "
modulus = $( openssl rsa -in $keyfile -modulus -noout | cut -d '=' -f 2 )
modulus = $( openssl rsa -in $keyfile -modulus -noout | cut -d '=' -f 2 )
_debug2 modulus " $modulus "
_debug3 modulus " $modulus "
n = " $( printf "%s" " $modulus " | _h2b | _base64 | _urlencode ) "
n = " $( printf "%s" " $modulus " | _h2b | _base64 | _urlencode ) "
jwk = '{"e": "' $e '", "kty": "RSA", "n": "' $n '"}'
jwk = '{"e": "' $e '", "kty": "RSA", "n": "' $n '"}'
_debug2 jwk " $jwk "
_debug3 jwk " $jwk "
HEADER = '{"alg": "RS256", "jwk": ' $jwk '}'
HEADER = '{"alg": "RS256", "jwk": ' $jwk '}'
HEADERPLACE = '{"nonce": "NONCE", "alg": "RS256", "jwk": ' $jwk '}'
HEADERPLACE_PART1 = '{"nonce": "'
HEADERPLACE_PART2 = '", "alg": "RS256", "jwk": ' $jwk '}'
elif grep "BEGIN EC PRIVATE KEY" " $keyfile " > /dev/null 2>& 1 ; then
elif grep "BEGIN EC PRIVATE KEY" " $keyfile " > /dev/null 2>& 1 ; then
_debug "EC key"
_debug "EC key"
EC_SIGN = "1"
EC_SIGN = "1"
crv = " $( openssl ec -in $keyfile -noout -text 2>/dev/null | grep "^NIST CURVE:" | cut -d ":" -f 2 | tr -d " \r\n" ) "
crv = " $( openssl ec -in $keyfile -noout -text 2>/dev/null | grep "^NIST CURVE:" | cut -d ":" -f 2 | tr -d " \r\n" ) "
_debug2 crv " $crv "
_debug3 crv " $crv "
pubi = " $( openssl ec -in $keyfile -noout -text 2>/dev/null | grep -n pub: | cut -d : -f 1) "
pubi = " $( openssl ec -in $keyfile -noout -text 2>/dev/null | grep -n pub: | cut -d : -f 1) "
pubi = $( _math $pubi + 1)
pubi = $( _math $pubi + 1)
_debug2 pubi " $pubi "
_debug3 pubi " $pubi "
pubj = " $( openssl ec -in $keyfile -noout -text 2>/dev/null | grep -n "ASN1 OID:" | cut -d : -f 1) "
pubj = " $( openssl ec -in $keyfile -noout -text 2>/dev/null | grep -n "ASN1 OID:" | cut -d : -f 1) "
pubj = $( _math $pubj + 1)
pubj = $( _math $pubj + 1)
_debug2 pubj " $pubj "
_debug3 pubj " $pubj "
pubtext = " $( openssl ec -in $keyfile -noout -text 2>/dev/null | sed -n " $pubi , ${ pubj } p " | tr -d " \n\r" ) "
pubtext = " $( openssl ec -in $keyfile -noout -text 2>/dev/null | sed -n " $pubi , ${ pubj } p " | tr -d " \n\r" ) "
_debug2 pubtext " $pubtext "
_debug3 pubtext " $pubtext "
xlen = " $( printf " $pubtext " | tr -d ':' | wc -c) "
xlen = " $( printf " $pubtext " | tr -d ':' | wc -c) "
xlen = $( _math $xlen / 4)
xlen = $( _math $xlen / 4)
_debug2 xlen " $xlen "
_debug3 xlen " $xlen "
xend = $( _math " $xend " + 1)
xend = $( _math " $xend " + 1)
x = " $( printf $pubtext | cut -d : -f 2-$xend ) "
x = " $( printf $pubtext | cut -d : -f 2-$xend ) "
_debug2 x " $x "
_debug3 x " $x "
x64 = " $( printf $x | tr -d : | _h2b | _base64 | _urlencode) "
x64 = " $( printf $x | tr -d : | _h2b | _base64 | _urlencode) "
_debug2 x64 " $x64 "
_debug3 x64 " $x64 "
xend = $( _math " $xend " + 1)
xend = $( _math " $xend " + 1)
y = " $( printf $pubtext | cut -d : -f $xend -10000) "
y = " $( printf $pubtext | cut -d : -f $xend -10000) "
_debug2 y " $y "
_debug3 y " $y "
y64 = " $( printf $y | tr -d : | _h2b | _base64 | _urlencode) "
y64 = " $( printf $y | tr -d : | _h2b | _base64 | _urlencode) "
_debug2 y64 " $y64 "
_debug3 y64 " $y64 "
jwk = '{"kty": "EC", "crv": "' $crv '", "x": "' $x64 '", "y": "' $y64 '"}'
jwk = '{"kty": "EC", "crv": "' $crv '", "x": "' $x64 '", "y": "' $y64 '"}'
_debug2 jwk " $jwk "
_debug3 jwk " $jwk "
HEADER = '{"alg": "ES256", "jwk": ' $jwk '}'
HEADER = '{"alg": "ES256", "jwk": ' $jwk '}'
HEADERPLACE = '{"nonce": "NONCE", "alg": "ES256", "jwk": ' $jwk '} '
HEADERPLACE_PART1 = '{"nonce": "'
HEADERPLACE_PART2 = '", "alg": "ES256", "jwk": ' $jwk '}'
else
else
_err "Only RSA or EC key is supported."
_err "Only RSA or EC key is supported."
return 1
return 1
fi
fi
_debug2 HEADER " $HEADER "
_debug3 HEADER " $HEADER "
}
}
# body url [needbase64] [POST|PUT]
# body url [needbase64] [POST|PUT]
_post( ) {
_post( ) {
@ -744,8 +768,8 @@ _send_signed_request() {
return 1
return 1
fi
fi
payload64 = $( echo -n $payload | _base64 | _urlencode)
_debug2 payload64 $payload64
payload64 = $( printf "%s" " $payload " | _base64 | _urlencode)
_debug3 payload64 $payload64
nonceurl = " $API /directory "
nonceurl = " $API /directory "
_headers = " $( _get $nonceurl "onlyheader" ) "
_headers = " $( _get $nonceurl "onlyheader" ) "
@ -755,23 +779,23 @@ _send_signed_request() {
return 1
return 1
fi
fi
_debug2 _headers " $_headers "
_debug3 _headers " $_headers "
nonce = " $( echo " $_headers " | grep "Replay-Nonce:" | head -1 | tr -d "\r\n " | cut -d ':' -f 2) "
nonce = " $( echo " $_headers " | grep "Replay-Nonce:" | head -1 | tr -d "\r\n " | cut -d ':' -f 2) "
_debug nonce " $nonce "
_debug3 nonce " $nonce "
protected = " $( printf " $HEADERPLACE " | sed " s/NONCE/ $nonce / " ) "
_debug2 protected " $protected "
protected = " $HEADERPLACE_PART1 $nonce $HEADERPLACE_PART2 "
_debug3 protected " $protected "
protected64 = " $( printf " $protected " | _base64 | _urlencode) "
protected64 = " $( printf " $protected " | _base64 | _urlencode) "
_debug2 protected64 " $protected64 "
_debug3 protected64 " $protected64 "
sig = $( echo -n " $protected64 . $payload64 " | _sign " $keyfile " "sha256" | _urlencode)
_debug2 sig " $sig "
sig = $( printf "%s" " $protected64 . $payload64 " | _sign " $keyfile " "sha256" | _urlencode)
_debug3 sig " $sig "
body = " {\"header\": $HEADER , \"protected\": \" $protected64 \", \"payload\": \" $payload64 \", \"signature\": \" $sig \"} "
body = " {\"header\": $HEADER , \"protected\": \" $protected64 \", \"payload\": \" $payload64 \", \"signature\": \" $sig \"} "
_debug2 body " $body "
_debug3 body " $body "
response = " $( _post " $body " $url " $needbase64 " ) "
response = " $( _post " $body " $url " $needbase64 " ) "
@ -808,15 +832,15 @@ _setopt() {
touch " $__conf "
touch " $__conf "
fi
fi
if grep -H - n " ^ $__opt $__sep " " $__conf " > /dev/null ; then
_debug2 OK
if grep -n " ^ $__opt $__sep " " $__conf " > /dev/null ; then
_debug3 OK
if _contains " $__val " "&" ; then
if _contains " $__val " "&" ; then
__val = " $( echo $__val | sed 's/&/\\&/g' ) "
__val = " $( echo $__val | sed 's/&/\\&/g' ) "
fi
fi
text = " $( cat $__conf ) "
text = " $( cat $__conf ) "
echo " $text " | sed " s|^ $__opt $__sep .* $| $__opt $__sep $__val $__end | " > " $__conf "
echo " $text " | sed " s|^ $__opt $__sep .* $| $__opt $__sep $__val $__end | " > " $__conf "
elif grep -H - n " ^# $__opt $__sep " " $__conf " > /dev/null ; then
elif grep -n " ^# $__opt $__sep " " $__conf " > /dev/null ; then
if _contains " $__val " "&" ; then
if _contains " $__val " "&" ; then
__val = " $( echo $__val | sed 's/&/\\&/g' ) "
__val = " $( echo $__val | sed 's/&/\\&/g' ) "
fi
fi
@ -824,10 +848,10 @@ _setopt() {
echo " $text " | sed " s|^# $__opt $__sep .* $| $__opt $__sep $__val $__end | " > " $__conf "
echo " $text " | sed " s|^# $__opt $__sep .* $| $__opt $__sep $__val $__end | " > " $__conf "
else
else
_debug2 APP
_debug3 APP
echo " $__opt $__sep $__val $__end " >> " $__conf "
echo " $__opt $__sep $__val $__end " >> " $__conf "
fi
fi
_debug " $( grep -H -n " ^ $__opt $__sep " $__conf ) "
_debug2 " $( grep -n " ^ $__opt $__sep " $__conf ) "
}
}
#_savedomainconf key value
#_savedomainconf key value
@ -922,9 +946,9 @@ _stopserver(){
_debug2 "Le_HTTPPort" " $Le_HTTPPort "
_debug2 "Le_HTTPPort" " $Le_HTTPPort "
if [ " $Le_HTTPPort " ] ; then
if [ " $Le_HTTPPort " ] ; then
if [ " $DEBUG " ] ; then
if [ " $DEBUG " ] ; then
_get " http://localhost: $Le_HTTPPort "
_get " http://localhost: $Le_HTTPPort " "" 1
else
else
_get " http://localhost: $Le_HTTPPort " >/dev/null 2>& 1
_get " http://localhost: $Le_HTTPPort " "" 1 >/dev/null 2>& 1
fi
fi
fi
fi
@ -1412,8 +1436,8 @@ issue() {
return 1
return 1
fi
fi
accountkey_json = $( echo -n " $jwk " | tr -d ' ' )
thumbprint = $( echo -n " $accountkey_json " | _digest "sha256" | _urlencode)
accountkey_json = $( printf "%s" " $jwk " | tr -d ' ' )
thumbprint = $( printf "%s" " $accountkey_json " | _digest "sha256" | _urlencode)
regjson = '{"resource": "new-reg", "agreement": "' $AGREEMENT '"}'
regjson = '{"resource": "new-reg", "agreement": "' $AGREEMENT '"}'
if [ " $ACCOUNT_EMAIL " ] ; then
if [ " $ACCOUNT_EMAIL " ] ; then
@ -1506,17 +1530,17 @@ issue() {
return 1
return 1
fi
fi
entry = " $( printf " $response " | egrep -o '\{ [^{]*"type":"' $vtype '"[^}]*' ) "
entry = " $( printf "%s\n" " $response " | _egrep_o ' [^{]*"type":"' $vtype '"[^}]*' ) "
_debug entry " $entry "
_debug entry " $entry "
if [ -z " $entry " ] ; then
if [ -z " $entry " ] ; then
_err " Error, can not get domain token $d "
_err " Error, can not get domain token $d "
_clearup
_clearup
return 1
return 1
fi
fi
token = " $( printf " $entry " | egrep - o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"' ) "
token = " $( printf "%s\n" " $entry " | _egrep_ o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"' ) "
_debug token $token
_debug token $token
uri = " $( printf " $entry " | egrep - o '"uri":"[^"]*' | cut -d : -f 2,3 | tr -d '"' ) "
uri = " $( printf "%s\n" " $entry " | _egrep_ o '"uri":"[^"]*' | cut -d : -f 2,3 | tr -d '"' ) "
_debug uri $uri
_debug uri $uri
keyauthorization = " $token . $thumbprint "
keyauthorization = " $token . $thumbprint "
@ -1556,7 +1580,7 @@ issue() {
dnsadded = '0'
dnsadded = '0'
txtdomain = " _acme-challenge. $d "
txtdomain = " _acme-challenge. $d "
_debug txtdomain " $txtdomain "
_debug txtdomain " $txtdomain "
txt = " $( echo -n $keyauthorization | _digest "sha256" | _urlencode) "
txt = " $( printf "%s" " $keyauthorization " | _digest "sha256" | _urlencode) "
_debug txt " $txt "
_debug txt " $txt "
#dns
#dns
#1. check use api
#1. check use api
@ -1778,7 +1802,7 @@ issue() {
response = " $( echo " $response " | _normalizeJson ) "
response = " $( echo " $response " | _normalizeJson ) "
_debug2 response " $response "
_debug2 response " $response "
status = $( echo $response | egrep - o '"status":"[^"]*' | cut -d : -f 2 | tr -d '"' )
status = $( echo " $response " | _egrep_ o '"status":"[^"]*' | cut -d : -f 2 | tr -d '"' )
if [ " $status " = "valid" ] ; then
if [ " $status " = "valid" ] ; then
_info "Success"
_info "Success"
_stopserver $serverproc
_stopserver $serverproc
@ -1788,9 +1812,9 @@ issue() {
fi
fi
if [ " $status " = "invalid" ] ; then
if [ " $status " = "invalid" ] ; then
error = " $( echo $response | tr -d "\r\n" | egrep - o '"error":\{[^}]*}' ) "
error = " $( echo " $response " | _egrep_ o '"error":\{[^}]*}' ) "
_debug2 error " $error "
_debug2 error " $error "
errordetail = " $( echo $error | grep - o '"detail": *"[^"]*"' | cut -d '"' -f 4) "
errordetail = " $( echo $error | _egrep_ o '"detail": *"[^"]*"' | cut -d '"' -f 4) "
_debug2 errordetail " $errordetail "
_debug2 errordetail " $errordetail "
if [ " $errordetail " ] ; then
if [ " $errordetail " ] ; then
_err " $d :Verify error: $errordetail "
_err " $d :Verify error: $errordetail "
@ -1830,7 +1854,7 @@ issue() {
fi
fi
Le_LinkCert = " $( grep -i -o '^Location.*$' $HTTP_HEADER | head -1 | tr -d "\r\n" | cut -d " " -f 2) "
Le_LinkCert = " $( grep -i '^Location.*$' $HTTP_HEADER | head -1 | tr -d "\r\n" | cut -d " " -f 2) "
_savedomainconf "Le_LinkCert" " $Le_LinkCert "
_savedomainconf "Le_LinkCert" " $Le_LinkCert "
if [ " $Le_LinkCert " ] ; then
if [ " $Le_LinkCert " ] ; then
@ -1852,7 +1876,7 @@ issue() {
if [ -z " $Le_LinkCert " ] ; then
if [ -z " $Le_LinkCert " ] ; then
response = " $( echo $response | _dbase64 "multiline" | _normalizeJson ) "
response = " $( echo $response | _dbase64 "multiline" | _normalizeJson ) "
_err " Sign failed: $( echo " $response " | grep - o '"detail":"[^"]*"' ) "
_err " Sign failed: $( echo " $response " | _egrep_ o '"detail":"[^"]*"' ) "
return 1
return 1
fi
fi
@ -1925,7 +1949,7 @@ renew() {
IS_RENEW = "1"
IS_RENEW = "1"
issue " $Le_Webroot " " $Le_Domain " " $Le_Alt " " $Le_Keylength " " $Le_RealCertPath " " $Le_RealKeyPath " " $Le_RealCACertPath " " $Le_ReloadCmd " " $Le_RealFullChainPath "
issue " $Le_Webroot " " $Le_Domain " " $Le_Alt " " $Le_Keylength " " $Le_RealCertPath " " $Le_RealKeyPath " " $Le_RealCACertPath " " $Le_ReloadCmd " " $Le_RealFullChainPath "
local res = $?
res = $?
IS_RENEW = ""
IS_RENEW = ""
return $res
return $res
@ -1961,7 +1985,7 @@ renewAll() {
list( ) {
list( ) {
local _raw = " $1 "
_raw = " $1 "
_initpath
_initpath
_sep = "|"
_sep = "|"
@ -1978,7 +2002,11 @@ list() {
)
)
done
done
else
else
list "raw" | column -t -s " $_sep "
if _exists column ; then
list "raw" | column -t -s " $_sep "
else
list "raw" | tr '|' '\t'
fi
fi
fi
@ -2094,7 +2122,11 @@ installcronjob() {
_err " Can not install cronjob, $PROJECT_ENTRY not found. "
_err " Can not install cronjob, $PROJECT_ENTRY not found. "
return 1
return 1
fi
fi
crontab -l | { cat; echo " 0 0 * * * $lesh --cron --home \" $LE_WORKING_DIR \" > /dev/null " ; } | crontab -
if _exists uname && uname -a | grep solaris >/dev/null ; then
crontab -l | { cat; echo " 0 0 * * * $lesh --cron --home \" $LE_WORKING_DIR \" > /dev/null " ; } | crontab --
else
crontab -l | { cat; echo " 0 0 * * * $lesh --cron --home \" $LE_WORKING_DIR \" > /dev/null " ; } | crontab -
fi
fi
fi
if [ " $? " != "0" ] ; then
if [ " $? " != "0" ] ; then
_err "Install cron job failed. You need to manually renew your certs."
_err "Install cron job failed. You need to manually renew your certs."
@ -2111,7 +2143,11 @@ uninstallcronjob() {
_info "Removing cron job"
_info "Removing cron job"
cr = " $( crontab -l | grep " $PROJECT_ENTRY --cron " ) "
cr = " $( crontab -l | grep " $PROJECT_ENTRY --cron " ) "
if [ " $cr " ] ; then
if [ " $cr " ] ; then
crontab -l | sed " / $PROJECT_ENTRY --cron/d " | crontab -
if _exists uname && uname -a | grep solaris >/dev/null ; then
crontab -l | sed " / $PROJECT_ENTRY --cron/d " | crontab --
else
crontab -l | sed " / $PROJECT_ENTRY --cron/d " | crontab -
fi
LE_WORKING_DIR = " $( echo " $cr " | cut -d ' ' -f 9 | tr -d '"' ) "
LE_WORKING_DIR = " $( echo " $cr " | cut -d ' ' -f 9 | tr -d '"' ) "
_info LE_WORKING_DIR " $LE_WORKING_DIR "
_info LE_WORKING_DIR " $LE_WORKING_DIR "
fi
fi
@ -2181,9 +2217,7 @@ _detect_profile() {
return
return
fi
fi
local DETECTED_PROFILE
DETECTED_PROFILE = ''
DETECTED_PROFILE = ''
local SHELLTYPE
SHELLTYPE = " $( basename " / $SHELL " ) "
SHELLTYPE = " $( basename " / $SHELL " ) "
if [ " $SHELLTYPE " = "bash" ] ; then
if [ " $SHELLTYPE " = "bash" ] ; then