|
@@ -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"
|
|
@@ -442,7 +452,7 @@ issue() {
|
|
else
|
|
else
|
|
usingApache=""
|
|
usingApache=""
|
|
fi
|
|
fi
|
|
-
|
|
|
|
|
|
+
|
|
createAccountKey $Le_Domain $Le_Keylength
|
|
createAccountKey $Le_Domain $Le_Keylength
|
|
|
|
|
|
if ! createDomainKey $Le_Domain $Le_Keylength ; then
|
|
if ! createDomainKey $Le_Domain $Le_Keylength ; then
|
|
@@ -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"
|
|
-
|
|
|
|
- alldomains=$(echo "$Le_Domain,$Le_Alt" | sed "s/,/ /g")
|
|
|
|
- for d in $alldomains
|
|
|
|
- do
|
|
|
|
- _info "Verifing 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
|
|
|
|
|
|
+ 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
|
|
|
|
+
|
|
|
|
+ entry=$(echo $response | egrep -o '{[^{]*"type":"'$vtype'"[^}]*')
|
|
|
|
+ _debug entry "$entry"
|
|
|
|
+
|
|
|
|
+ token=$(echo "$entry" | sed 's/,/\n'/g| grep '"token":'| cut -d : -f 2|sed 's/"//g')
|
|
|
|
+ _debug token $token
|
|
|
|
+
|
|
|
|
+ uri=$(echo "$entry" | sed 's/,/\n'/g| grep '"uri":'| cut -d : -f 2,3|sed 's/"//g')
|
|
|
|
+ _debug uri $uri
|
|
|
|
+
|
|
|
|
+ keyauthorization="$token.$thumbprint"
|
|
|
|
+ _debug keyauthorization "$keyauthorization"
|
|
|
|
+
|
|
|
|
+ dvlist="$d$sep$keyauthorization$sep$uri"
|
|
|
|
+ _debug dvlist "$dvlist"
|
|
|
|
+
|
|
|
|
+ vlist="$vlist$dvlist,"
|
|
|
|
+
|
|
|
|
+ done
|
|
|
|
+
|
|
|
|
+ #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
|
|
|
|
+ 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
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
|
|
- http01=$(echo $response | egrep -o '{[^{]*"type":"http-01"[^}]*')
|
|
|
|
- _debug http01 "$http01"
|
|
|
|
-
|
|
|
|
- token=$(echo "$http01" | sed 's/,/\n'/g| grep '"token":'| cut -d : -f 2|sed 's/"//g')
|
|
|
|
- _debug token $token
|
|
|
|
-
|
|
|
|
- uri=$(echo "$http01" | sed 's/,/\n'/g| grep '"uri":'| cut -d : -f 2,3|sed 's/"//g')
|
|
|
|
- _debug uri $uri
|
|
|
|
-
|
|
|
|
- keyauthorization="$token.$thumbprint"
|
|
|
|
- _debug keyauthorization "$keyauthorization"
|
|
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ _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 [ "$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"
|
|
|
|
|
|
+ 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
|
|
- _debug wellknown_path "$wellknown_path"
|
|
|
|
-
|
|
|
|
- mkdir -p "$wellknown_path"
|
|
|
|
- echo -n "$keyauthorization" > "$wellknown_path/$token"
|
|
|
|
-
|
|
|
|
- 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"
|
|
|
|
-
|
|
|
|
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
|
|
@@ -590,7 +655,8 @@ issue() {
|
|
done
|
|
done
|
|
_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"
|
|
|
|
|