|
@ -1,14 +1,14 @@ |
|
|
#!/bin/bash |
|
|
#!/bin/bash |
|
|
VER=1.0.5 |
|
|
|
|
|
|
|
|
VER=1.1.0 |
|
|
PROJECT="https://github.com/Neilpang/le" |
|
|
PROJECT="https://github.com/Neilpang/le" |
|
|
|
|
|
|
|
|
DEFAULT_CA="https://acme-v01.api.letsencrypt.org" |
|
|
DEFAULT_CA="https://acme-v01.api.letsencrypt.org" |
|
|
DEFAULT_AGREEMENT="https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf" |
|
|
DEFAULT_AGREEMENT="https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf" |
|
|
|
|
|
|
|
|
|
|
|
STAGE_CA="https://acme-staging.api.letsencrypt.org" |
|
|
|
|
|
|
|
|
if [ -z "$API" ] ; then |
|
|
|
|
|
API="$DEFAULT_CA" |
|
|
|
|
|
fi |
|
|
|
|
|
|
|
|
VTYPE_HTTP="http-01" |
|
|
|
|
|
VTYPE_DNS="dns-01" |
|
|
|
|
|
|
|
|
if [ -z "$AGREEMENT" ] ; then |
|
|
if [ -z "$AGREEMENT" ] ; then |
|
|
AGREEMENT="$DEFAULT_AGREEMENT" |
|
|
AGREEMENT="$DEFAULT_AGREEMENT" |
|
@ -23,15 +23,15 @@ _debug() { |
|
|
if [ -z "$2" ] ; then |
|
|
if [ -z "$2" ] ; then |
|
|
echo $1 |
|
|
echo $1 |
|
|
else |
|
|
else |
|
|
echo $1:$2 |
|
|
|
|
|
|
|
|
echo "$1"="$2" |
|
|
fi |
|
|
fi |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
_info() { |
|
|
_info() { |
|
|
if [ -z "$2" ] ; then |
|
|
if [ -z "$2" ] ; then |
|
|
echo $1 |
|
|
|
|
|
|
|
|
echo "$1" |
|
|
else |
|
|
else |
|
|
echo $1:$2 |
|
|
|
|
|
|
|
|
echo "$1"="$2" |
|
|
fi |
|
|
fi |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -39,7 +39,7 @@ _err() { |
|
|
if [ -z "$2" ] ; then |
|
|
if [ -z "$2" ] ; then |
|
|
echo "$1" >&2 |
|
|
echo "$1" >&2 |
|
|
else |
|
|
else |
|
|
echo "$1:$2" >&2 |
|
|
|
|
|
|
|
|
echo "$1"="$2" >&2 |
|
|
fi |
|
|
fi |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -237,6 +237,16 @@ _stopserver() { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
_initpath() { |
|
|
_initpath() { |
|
|
|
|
|
|
|
|
|
|
|
if [ -z "$API" ] ; then |
|
|
|
|
|
if [ -z "$STAGE" ] ; then |
|
|
|
|
|
API="$DEFAULT_CA" |
|
|
|
|
|
else |
|
|
|
|
|
API="$STAGE_CA" |
|
|
|
|
|
_info "Using stage api:$API" |
|
|
|
|
|
fi |
|
|
|
|
|
fi |
|
|
|
|
|
|
|
|
if [ -z "$WORKING_DIR" ]; then |
|
|
if [ -z "$WORKING_DIR" ]; then |
|
|
WORKING_DIR=$HOME/.le |
|
|
WORKING_DIR=$HOME/.le |
|
|
fi |
|
|
fi |
|
@ -366,7 +376,7 @@ _clearup () { |
|
|
|
|
|
|
|
|
issue() { |
|
|
issue() { |
|
|
if [ -z "$2" ] ; then |
|
|
if [ -z "$2" ] ; then |
|
|
_err "Usage: le issue webroot|no|apache a.com [www.a.com,b.com,c.com]|no [key-length]|no [cert-file-path]|no [key-file-path]|no [ca-cert-file-path]|no [reloadCmd]|no" |
|
|
|
|
|
|
|
|
_err "Usage: le issue webroot|no|apache|dns a.com [www.a.com,b.com,c.com]|no [key-length]|no [cert-file-path]|no [key-file-path]|no [ca-cert-file-path]|no [reloadCmd]|no" |
|
|
return 1 |
|
|
return 1 |
|
|
fi |
|
|
fi |
|
|
Le_Webroot="$1" |
|
|
Le_Webroot="$1" |
|
@ -495,58 +505,113 @@ issue() { |
|
|
return 1 |
|
|
return 1 |
|
|
fi |
|
|
fi |
|
|
|
|
|
|
|
|
|
|
|
vtype="$VTYPE_HTTP" |
|
|
|
|
|
if [[ "$Le_Webroot" == "dns"* ]] ; then |
|
|
|
|
|
vtype="$VTYPE_DNS" |
|
|
|
|
|
fi |
|
|
|
|
|
|
|
|
|
|
|
vlist="$Le_Vlist" |
|
|
# verify each domain |
|
|
# verify each domain |
|
|
_info "Verify each domain" |
|
|
_info "Verify each domain" |
|
|
|
|
|
sep='#' |
|
|
|
|
|
if [ -z "$vlist" ] ; then |
|
|
|
|
|
alldomains=$(echo "$Le_Domain,$Le_Alt" | sed "s/,/ /g") |
|
|
|
|
|
for d in $alldomains |
|
|
|
|
|
do |
|
|
|
|
|
_info "Geting 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 |
|
|
|
|
|
_err "new-authz error: $response" |
|
|
|
|
|
_clearup |
|
|
|
|
|
return 1 |
|
|
|
|
|
fi |
|
|
|
|
|
|
|
|
alldomains=$(echo "$Le_Domain,$Le_Alt" | sed "s/,/ /g") |
|
|
|
|
|
for d in $alldomains |
|
|
|
|
|
do |
|
|
|
|
|
_info "Verifing domain" $d |
|
|
|
|
|
|
|
|
entry=$(echo $response | egrep -o '{[^{]*"type":"'$vtype'"[^}]*') |
|
|
|
|
|
_debug entry "$entry" |
|
|
|
|
|
|
|
|
_send_signed_request "$API/acme/new-authz" "{\"resource\": \"new-authz\", \"identifier\": {\"type\": \"dns\", \"value\": \"$d\"}}" |
|
|
|
|
|
|
|
|
token=$(echo "$entry" | sed 's/,/\n'/g| grep '"token":'| cut -d : -f 2|sed 's/"//g') |
|
|
|
|
|
_debug token $token |
|
|
|
|
|
|
|
|
if [ ! -z "$code" ] && [ ! "$code" == '201' ] ; then |
|
|
|
|
|
_err "new-authz error: $response" |
|
|
|
|
|
_clearup |
|
|
|
|
|
return 1 |
|
|
|
|
|
fi |
|
|
|
|
|
|
|
|
uri=$(echo "$entry" | sed 's/,/\n'/g| grep '"uri":'| cut -d : -f 2,3|sed 's/"//g') |
|
|
|
|
|
_debug uri $uri |
|
|
|
|
|
|
|
|
http01=$(echo $response | egrep -o '{[^{]*"type":"http-01"[^}]*') |
|
|
|
|
|
_debug http01 "$http01" |
|
|
|
|
|
|
|
|
keyauthorization="$token.$thumbprint" |
|
|
|
|
|
_debug keyauthorization "$keyauthorization" |
|
|
|
|
|
|
|
|
token=$(echo "$http01" | sed 's/,/\n'/g| grep '"token":'| cut -d : -f 2|sed 's/"//g') |
|
|
|
|
|
_debug token $token |
|
|
|
|
|
|
|
|
dvlist="$d$sep$keyauthorization$sep$uri" |
|
|
|
|
|
_debug dvlist "$dvlist" |
|
|
|
|
|
|
|
|
uri=$(echo "$http01" | sed 's/,/\n'/g| grep '"uri":'| cut -d : -f 2,3|sed 's/"//g') |
|
|
|
|
|
_debug uri $uri |
|
|
|
|
|
|
|
|
vlist="$vlist$dvlist," |
|
|
|
|
|
|
|
|
keyauthorization="$token.$thumbprint" |
|
|
|
|
|
_debug keyauthorization "$keyauthorization" |
|
|
|
|
|
|
|
|
done |
|
|
|
|
|
|
|
|
if [ "$Le_Webroot" == "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" |
|
|
|
|
|
|
|
|
#add entry |
|
|
|
|
|
dnsadded="" |
|
|
|
|
|
ventries=$(echo "$vlist" | sed "s/,/ /g") |
|
|
|
|
|
for ventry in $ventries |
|
|
|
|
|
do |
|
|
|
|
|
d=$(echo $ventry | cut -d $sep -f 1) |
|
|
|
|
|
keyauthorization=$(echo $ventry | cut -d $sep -f 2) |
|
|
|
|
|
|
|
|
|
|
|
if [ "$vtype" == "$VTYPE_DNS" ] ; then |
|
|
|
|
|
dnsadded='0' |
|
|
|
|
|
txtdomain="_acme-challenge.$d" |
|
|
|
|
|
_debug txtdomain "$txtdomain" |
|
|
|
|
|
txt="$(echo -e -n $keyauthorization | sha256sum | xxd -r -p | base64 -w 0 | _b64)" |
|
|
|
|
|
_debug txt "$txt" |
|
|
|
|
|
#dns |
|
|
|
|
|
#1. check use api |
|
|
|
|
|
_err "Add the following txt record:" |
|
|
|
|
|
_err "Domain:$txtdomain" |
|
|
|
|
|
_err "Txt value:$txt" |
|
|
|
|
|
#dnsadded='1' |
|
|
fi |
|
|
fi |
|
|
_debug wellknown_path "$wellknown_path" |
|
|
|
|
|
|
|
|
done |
|
|
|
|
|
|
|
|
|
|
|
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." |
|
|
|
|
|
return 1 |
|
|
|
|
|
fi |
|
|
|
|
|
|
|
|
mkdir -p "$wellknown_path" |
|
|
|
|
|
echo -n "$keyauthorization" > "$wellknown_path/$token" |
|
|
|
|
|
|
|
|
fi |
|
|
|
|
|
|
|
|
webroot_owner=$(stat -c '%U:%G' $Le_Webroot) |
|
|
|
|
|
_debug "Changing owner/group of .well-known to $webroot_owner" |
|
|
|
|
|
chown -R $webroot_owner "$Le_Webroot/.well-known" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_debug "ok, let's start to verify" |
|
|
|
|
|
ventries=$(echo "$vlist" | sed "s/,/ /g") |
|
|
|
|
|
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) |
|
|
|
|
|
_info "Verifying:$d" |
|
|
|
|
|
_debug "d" "$d" |
|
|
|
|
|
_debug "keyauthorization" "$keyauthorization" |
|
|
|
|
|
_debug "uri" "$uri" |
|
|
|
|
|
|
|
|
|
|
|
if [ "$vtype" == "$VTYPE_HTTP" ] ; then |
|
|
|
|
|
if [ "$Le_Webroot" == "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" |
|
|
|
|
|
fi |
|
|
|
|
|
_debug wellknown_path "$wellknown_path" |
|
|
|
|
|
|
|
|
|
|
|
webroot_owner=$(stat -c '%U:%G' $Le_Webroot) |
|
|
|
|
|
_debug "Changing owner/group of .well-known to $webroot_owner" |
|
|
|
|
|
chown -R $webroot_owner "$Le_Webroot/.well-known" |
|
|
|
|
|
|
|
|
|
|
|
mkdir -p "$wellknown_path" |
|
|
|
|
|
echo -n "$keyauthorization" > "$wellknown_path/$token" |
|
|
|
|
|
fi |
|
|
fi |
|
|
fi |
|
|
wellknown_url="http://$d/.well-known/acme-challenge/$token" |
|
|
|
|
|
_debug wellknown_url "$wellknown_url" |
|
|
|
|
|
|
|
|
|
|
|
_debug challenge "$challenge" |
|
|
|
|
|
_send_signed_request $uri "{\"resource\": \"challenge\", \"keyAuthorization\": \"$keyauthorization\"}" |
|
|
_send_signed_request $uri "{\"resource\": \"challenge\", \"keyAuthorization\": \"$keyauthorization\"}" |
|
|
|
|
|
|
|
|
if [ ! -z "$code" ] && [ ! "$code" == '202' ] ; then |
|
|
if [ ! -z "$code" ] && [ ! "$code" == '202' ] ; then |
|
@ -591,6 +656,7 @@ issue() { |
|
|
_stopserver $serverproc |
|
|
_stopserver $serverproc |
|
|
serverproc="" |
|
|
serverproc="" |
|
|
done |
|
|
done |
|
|
|
|
|
|
|
|
_clearup |
|
|
_clearup |
|
|
_info "Verify finished, start to sign." |
|
|
_info "Verify finished, start to sign." |
|
|
der="$(openssl req -in $CSR_PATH -outform DER | base64 -w 0 | _b64)" |
|
|
der="$(openssl req -in $CSR_PATH -outform DER | base64 -w 0 | _b64)" |
|
@ -611,13 +677,14 @@ issue() { |
|
|
fi |
|
|
fi |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if [ -z "$Le_LinkCert" ] ; then |
|
|
if [ -z "$Le_LinkCert" ] ; then |
|
|
response="$(echo $response | base64 -d)" |
|
|
response="$(echo $response | base64 -d)" |
|
|
_err "Sign failed: $(echo "$response" | grep -o '"detail":"[^"]*"')" |
|
|
_err "Sign failed: $(echo "$response" | grep -o '"detail":"[^"]*"')" |
|
|
return 1 |
|
|
return 1 |
|
|
fi |
|
|
fi |
|
|
|
|
|
|
|
|
|
|
|
_setopt "$DOMAIN_CONF" 'Le_Vlist' '=' "\"\"" |
|
|
|
|
|
|
|
|
Le_LinkIssuer=$(grep -i '^Link' $CURL_HEADER | cut -d " " -f 2| cut -d ';' -f 1 | sed 's/<//g' | sed 's/>//g') |
|
|
Le_LinkIssuer=$(grep -i '^Link' $CURL_HEADER | cut -d " " -f 2| cut -d ';' -f 1 | sed 's/<//g' | sed 's/>//g') |
|
|
_setopt "$DOMAIN_CONF" "Le_LinkIssuer" "=" "$Le_LinkIssuer" |
|
|
_setopt "$DOMAIN_CONF" "Le_LinkIssuer" "=" "$Le_LinkIssuer" |
|
|
|
|
|
|
|
|