Browse Source

Add option for dual ESA / EDSA certs

pull/155/head
srvrco 9 years ago
parent
commit
2b2cc345b1
1 changed files with 127 additions and 70 deletions
  1. +127
    -70
      getssl

+ 127
- 70
getssl View File

@ -137,10 +137,11 @@
# 2016-10-25 added CHECK_REMOTE_WAIT option ( to pause before final remote check)
# 2016-10-25 Added EC account key support ( prime256v1, secp384r1 ) (1.68)
# 2016-10-25 Ignore DNS_EXTRA_WAIT if all domains already validated (issue #146) (1.69)
# 2016-10-25 Add option for dual ESA / EDSA certs (1.70)
# ----------------------------------------------------------------------------------------
PROGNAME=${0##*/}
VERSION="1.69"
VERSION="1.70"
# defaults
CODE_LOCATION="https://raw.githubusercontent.com/srvrco/getssl/master/getssl"
@ -166,6 +167,7 @@ PUBLIC_DNS_SERVER=""
CHALLENGE_CHECK_TYPE="http"
DEACTIVATE_AUTH="false"
PREVIOUSLY_VALIDATED="true"
DUAL_RSA_ECDSA="false"
ORIG_UMASK=$(umask)
_USE_DEBUG=0
_CREATE_CONFIG=0
@ -187,8 +189,15 @@ cert_archive() { # Archive certificate file by copying with dates at end.
mkdir -p "${DOMAIN_DIR}/archive/${date_time}"
umask 077
cp "$CERT_FILE" "${DOMAIN_DIR}/archive/${date_time}/${DOMAIN}.crt"
cp "$CERT_FILE" "${DOMAIN_DIR}/archive/${date_time}/${DOMAIN}.csr"
cp "$DOMAIN_DIR/${DOMAIN}.key" "${DOMAIN_DIR}/archive/${date_time}/${DOMAIN}.key"
cp "$CA_CERT" "${DOMAIN_DIR}/archive/${date_time}/chain.crt"
if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then
cp "$CERT_FILE" "${DOMAIN_DIR}/archive/${date_time}/${DOMAIN}.ec.crt"
cp "$CERT_FILE" "${DOMAIN_DIR}/archive/${date_time}/${DOMAIN}.ec.csr"
cp "$DOMAIN_DIR/${DOMAIN}.key" "${DOMAIN_DIR}/archive/${date_time}/${DOMAIN}.ec.key"
cp "$CA_CERT" "${DOMAIN_DIR}/archive/${date_time}/chain.ec.crt"
fi
umask "$ORIG_UMASK"
debug "purging old GetSSL archives"
purge_archive "$DOMAIN_DIR"
@ -370,6 +379,60 @@ copy_file_to_location() { # copies a file, using scp if required.
fi
}
create_csr() { # create a csr using a given key (if it doesn't already exist)
csr_file=$1
csr_key=$2
# check if domain csr exists - if not then create it
if [ -f "$csr_file" ]; then
debug "domain csr exists at - $csr_file"
# check all domains in config are in csr
alldomains=$(echo "$DOMAIN,$SANS" | sed -e 's/ //g; y/,/\n/' | sort -u)
domains_in_csr=$(openssl req -text -noout -in "$csr_file" | sed -n -e 's/^ *Subject: .* CN=\([A-Za-z0-9.-]*\).*$/\1/p; /^ *DNS:.../ { s/ *DNS://g; y/,/\n/; p; }' | sort -u)
for d in $alldomains; do
if [ "$(echo "${domains_in_csr}"| grep "^${d}$")" != "${d}" ]; then
info "existing csr at $csr_file does not contain ${d} - re-create-csr .... $(echo "${domains_in_csr}"| grep "^${d}$")"
_RECREATE_CSR=1
fi
done
# check all domains in csr are in config
if [ "$alldomains" != "$domains_in_csr" ]; then
info "existing csr at $csr_file does not have the same domains as the config - re-create-csr"
_RECREATE_CSR=1
fi
fi # end of ... check if domain csr exists - if not then create it
# if CSR does not exist, or flag set to recreate, then create csr
if [ ! -f "$csr_file" ] || [ "$_RECREATE_CSR" == "1" ]; then
info "creating domain csr - $csr_file"
openssl req -new -sha256 -key "$csr_key" -subj "/" -reqexts SAN -config \
<(cat "$SSLCONF" <(printf "[SAN]\n%s" "$SANLIST")) > "$csr_file"
fi
}
create_domain_key() { # create a domain key (if it doesn't already exist)
key_type=$1 # domain key type
key_loc=$2 # domain key location
# check if domain key exists, if not then create it.
if [ -f "$key_loc" ]; then
debug "domain key exists at $key_loc - skipping generation"
# ideally need to check validity of domain key
else
umask 077
info "creating domain key - $key_loc"
case "$key_type" in
rsa)
openssl genrsa "$DOMAIN_KEY_LENGTH" > "$key_loc";;
prime256v1|secp384r1|secp521r1)
openssl ecparam -genkey -name "$key_type" > "$key_loc";;
*)
error_exit "unknown private key algorithm type $key_loc";;
esac
umask "$ORIG_UMASK"
# remove csr on generation of new domain key
rm -f "${key_loc::-4}.csr"
fi
}
date_epoc() { # convert the date into epoch time
if [[ "$os" == "bsd" ]]; then
date -j -f "%b %d %T %Y %Z" "$1" +%s
@ -479,6 +542,42 @@ get_auth_dns() { # get the authoritative dns server for a domain
fi
}
get_certificate() { # get certificate for csr, if all domains validated.
gc_csr=$1 # the csr file
gc_certfile=$2 # The filename for the certificate
gc_cafile=$3 # The filename for the CA certificate
der=$(openssl req -in "$gc_csr" -outform DER | urlbase64)
debug "der $der"
send_signed_request "$CA/acme/new-cert" "{\"resource\": \"new-cert\", \"csr\": \"$der\"}" "needbase64"
# convert certificate information into correct format and save to file.
CertData=$(awk ' $1 ~ "^Location" {print $2}' "$CURL_HEADER" |tr -d '\r')
debug "certdata location = $CertData"
if [ "$CertData" ] ; then
echo -----BEGIN CERTIFICATE----- > "$gc_certfile"
curl --silent "$CertData" | openssl base64 -e >> "$gc_certfile"
echo -----END CERTIFICATE----- >> "$gc_certfile"
info "Certificate saved in $CERT_FILE"
fi
# If certificate wasn't a valid certificate, error exit.
if [ -z "$CertData" ] ; then
response2=$(echo "$response" | fold -w64 |openssl base64 -d)
debug "response was $response"
error_exit "Sign failed: $(echo "$response2" | grep "detail")"
fi
# get a copy of the CA certificate.
IssuerData=$(grep -i '^Link' "$CURL_HEADER" | cut -d " " -f 2| cut -d ';' -f 1 | sed 's/<//g' | sed 's/>//g')
if [ "$IssuerData" ] ; then
echo -----BEGIN CERTIFICATE----- > "$gc_cafile"
curl --silent "$IssuerData" | openssl base64 -e >> "$gc_cafile"
echo -----END CERTIFICATE----- >> "$gc_cafile"
info "The intermediate CA cert is in $gc_cafile"
fi
}
get_os() { # function to get the current Operating System
uname_res=$(uname -s)
if [[ ${uname_res} == "Linux" ]]; then
@ -797,7 +896,6 @@ sign_string() { #sign a string with a given key and algorithm and return urlbase
debug "S $S"
signed64=$(printf '%s' "${R}${S}" | hex2bin | urlbase64 )
debug "encoded RS $signed64"
result=$(which "$1" 2>/dev/null)
fi
}
@ -1276,26 +1374,16 @@ if [ "$REUSE_PRIVATE_KEY" != "true" ]; then
if [ -f "$DOMAIN_DIR/${DOMAIN}.key" ]; then
rm -f "$DOMAIN_DIR/${DOMAIN}.key"
fi
if [ -f "$DOMAIN_DIR/${DOMAIN}.ec.key" ]; then
rm -f "$DOMAIN_DIR/${DOMAIN}.ecs.key"
fi
fi
# check if domain key exists, if not then create it.
if [ -f "$DOMAIN_DIR/${DOMAIN}.key" ]; then
debug "domain key exists at $DOMAIN_DIR/${DOMAIN}.key - skipping generation"
# ideally need to check validity of domain key
if [[ "$DUAL_RSA_ECDSA" == "false" ]]; then
create_domain_key "${PRIVATE_KEY_ALG}" "$DOMAIN_DIR/${DOMAIN}.key"
else
umask 077
info "creating domain key - $DOMAIN_DIR/${DOMAIN}.key"
case "${PRIVATE_KEY_ALG}" in
rsa)
openssl genrsa "$DOMAIN_KEY_LENGTH" > "$DOMAIN_DIR/${DOMAIN}.key";;
prime256v1|secp384r1|secp521r1)
openssl ecparam -genkey -name "${PRIVATE_KEY_ALG}" > "$DOMAIN_DIR/${DOMAIN}.key";;
*)
error_exit "unknown private key algorithm type ${PRIVATE_KEY_ALG}";;
esac
umask "$ORIG_UMASK"
# remove csr on generation of new domain key
rm -f "$DOMAIN_DIR/${DOMAIN}.csr"
create_domain_key "rsa" "$DOMAIN_DIR/${DOMAIN}.key"
create_domain_key "${PRIVATE_KEY_ALG}" "$DOMAIN_DIR/${DOMAIN}.ec.key"
fi
#create SAN
@ -1330,30 +1418,11 @@ for d in $alldomains; do
fi
done
# check if domain csr exists - if not then create it
if [ -f "$DOMAIN_DIR/${DOMAIN}.csr" ]; then
debug "domain csr exists at - $DOMAIN_DIR/${DOMAIN}.csr"
# check all domains in config are in csr
alldomains=$(echo "$DOMAIN,$SANS" | sed -e 's/ //g; y/,/\n/' | sort -u)
domains_in_csr=$(openssl req -text -noout -in "$DOMAIN_DIR/${DOMAIN}.csr" | sed -n -e 's/^ *Subject: .* CN=\([A-Za-z0-9.-]*\).*$/\1/p; /^ *DNS:.../ { s/ *DNS://g; y/,/\n/; p; }' | sort -u)
for d in $alldomains; do
if [ "$(echo "${domains_in_csr}"| grep "^${d}$")" != "${d}" ]; then
info "existing csr at $DOMAIN_DIR/${DOMAIN}.csr does not contain ${d} - re-create-csr .... $(echo "${domains_in_csr}"| grep "^${d}$")"
_RECREATE_CSR=1
fi
done
# check all domains in csr are in config
if [ "$alldomains" != "$domains_in_csr" ]; then
info "existing csr at $DOMAIN_DIR/${DOMAIN}.csr does not have the same domains as the config - re-create-csr"
_RECREATE_CSR=1
fi
fi # end of ... check if domain csr exists - if not then create it
# if CSR does not exist, or flag set to recreate, then create csr
if [ ! -f "$DOMAIN_DIR/${DOMAIN}.csr" ] || [ "$_RECREATE_CSR" == "1" ]; then
info "creating domain csr - $DOMAIN_DIR/${DOMAIN}.csr"
openssl req -new -sha256 -key "$DOMAIN_DIR/${DOMAIN}.key" -subj "/" -reqexts SAN -config \
<(cat "$SSLCONF" <(printf "[SAN]\n%s" "$SANLIST")) > "$DOMAIN_DIR/${DOMAIN}.csr"
if [[ "$DUAL_RSA_ECDSA" == "false" ]]; then
create_csr "$DOMAIN_DIR/${DOMAIN}.csr" "$DOMAIN_DIR/${DOMAIN}.key"
else
create_csr "$DOMAIN_DIR/${DOMAIN}.csr" "$DOMAIN_DIR/${DOMAIN}.key"
create_csr "$DOMAIN_DIR/${DOMAIN}.ec.csr" "$DOMAIN_DIR/${DOMAIN}.ec.key"
fi
# use account key to register with CA
@ -1604,34 +1673,10 @@ fi # end of ... perform validation if via DNS challenge
# Verification has been completed for all SANS, so request certificate.
info "Verification completed, obtaining certificate."
der=$(openssl req -in "$DOMAIN_DIR/${DOMAIN}.csr" -outform DER | urlbase64)
debug "der $der"
send_signed_request "$CA/acme/new-cert" "{\"resource\": \"new-cert\", \"csr\": \"$der\"}" "needbase64"
# convert certificate information into correct format and save to file.
CertData=$(awk ' $1 ~ "^Location" {print $2}' "$CURL_HEADER" |tr -d '\r')
debug "certdata location = $CertData"
if [ "$CertData" ] ; then
echo -----BEGIN CERTIFICATE----- > "$CERT_FILE"
curl --silent "$CertData" | openssl base64 -e >> "$CERT_FILE"
echo -----END CERTIFICATE----- >> "$CERT_FILE"
info "Certificate saved in $CERT_FILE"
fi
# If certificate wasn't a valid certificate, error exit.
if [ -z "$CertData" ] ; then
response2=$(echo "$response" | fold -w64 |openssl base64 -d)
debug "response was $response"
error_exit "Sign failed: $(echo "$response2" | grep "detail")"
fi
# get a copy of the CA certificate.
IssuerData=$(grep -i '^Link' "$CURL_HEADER" | cut -d " " -f 2| cut -d ';' -f 1 | sed 's/<//g' | sed 's/>//g')
if [ "$IssuerData" ] ; then
echo -----BEGIN CERTIFICATE----- > "$CA_CERT"
curl --silent "$IssuerData" | openssl base64 -e >> "$CA_CERT"
echo -----END CERTIFICATE----- >> "$CA_CERT"
info "The intermediate CA cert is in $CA_CERT"
get_certificate "$DOMAIN_DIR/${DOMAIN}.csr" "$CERT_FILE" "$CA_CERT"
if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then
get_certificate "$DOMAIN_DIR/${DOMAIN}.ec.csr" "${CERT_FILE::-4}.ec.crt" "${CA_CERT::-4}.ec.crt"
fi
# create Archive of new certs
@ -1644,6 +1689,18 @@ debug "Certificates obtained and archived locally, will now copy to specified lo
copy_file_to_location "domain certificate" "$CERT_FILE" "$DOMAIN_CERT_LOCATION"
copy_file_to_location "private key" "$DOMAIN_DIR/${DOMAIN}.key" "$DOMAIN_KEY_LOCATION"
copy_file_to_location "CA certificate" "$CA_CERT" "$CA_CERT_LOCATION"
if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then
if [ ! -z "$DOMAIN_CERT_LOCATION" ]; then
copy_file_to_location "ec domain certificate" "${CERT_FILE::-4}.ec.crt" "${DOMAIN_CERT_LOCATION::-4}.ec.crt"
fi
if [ ! -z "$DOMAIN_KEY_LOCATION" ]; then
copy_file_to_location "ec private key" "$DOMAIN_DIR/${DOMAIN}.ec.key" "${DOMAIN_KEY_LOCATION::-4}.ec.key"
fi
if [ ! -z "$CA_CERT_LOCATION" ]; then
copy_file_to_location "ec CA certificate" "${CA_CERT::-4}.ec.crt" "${CA_CERT_LOCATION::-4}.ec.crt"
fi
fi
# if DOMAIN_CHAIN_LOCATION is not blank, then create and copy file.
if [ ! -z "$DOMAIN_CHAIN_LOCATION" ]; then
if [[ "$(dirname "$DOMAIN_CHAIN_LOCATION")" == "." ]]; then


Loading…
Cancel
Save