mirror of
https://github.com/dehydrated-io/dehydrated.git
synced 2026-02-25 20:04:52 +01:00
implemented rfc 8738 support
This commit is contained in:
@@ -10,6 +10,7 @@ This file contains a log of major changes in dehydrated
|
||||
## Added
|
||||
- Implemented EC for account keys
|
||||
- Domain list now also read from domains.txt.d subdirectory (behaviour might change, see docs)
|
||||
- Implemented RFC 8738 (validating/signing certificates for IP addresses instead of domain names) support (this will not work with most public CAs, if any!)
|
||||
|
||||
## [0.7.0] - 2020-12-10
|
||||
## Added
|
||||
|
||||
69
dehydrated
69
dehydrated
@@ -241,6 +241,17 @@ jsonsh() {
|
||||
tokenize | parse
|
||||
}
|
||||
|
||||
# Convert IP addresses to their reverse dns variants.
|
||||
# Used for ALPN certs as validation for IPs uses this in SNI since IPs aren't allowed there.
|
||||
ip_to_ptr() {
|
||||
ip="$(cat)"
|
||||
if [[ "${ip}" =~ : ]]; then
|
||||
printf "%sip6.arpa" "$(printf "%s" "${ip}" | awk -F: 'BEGIN {OFS=""; }{addCount = 9 - NF; for(i=1; i<=NF;i++){if(length($i) == 0){ for(j=1;j<=addCount;j++){$i = ($i "0000");} } else { $i = substr(("0000" $i), length($i)+5-4);}}; print}' | rev | sed -e "s/./&./g")"
|
||||
else
|
||||
printf "%s.in-addr.arpa" "$(printf "%s" "${ip}" | awk -F. '{print $4"."$3"." $2"."$1}')"
|
||||
fi
|
||||
}
|
||||
|
||||
# Create (identifiable) temporary files
|
||||
_mktemp() {
|
||||
mktemp "${TMPDIR:-/tmp}/dehydrated-XXXXXX"
|
||||
@@ -996,12 +1007,12 @@ extract_altnames() {
|
||||
# split to one per line:
|
||||
# shellcheck disable=SC1003
|
||||
altnames="$( <<<"${altnames}" _sed -e 's/^[[:space:]]*//; s/, /\'$'\n''/g' )"
|
||||
# we can only get DNS: ones signed
|
||||
if grep -qEv '^(DNS|othername):' <<<"${altnames}"; then
|
||||
_exiterr "Certificate signing request contains non-DNS Subject Alternative Names"
|
||||
# we can only get DNS/IP: ones signed
|
||||
if grep -qEv '^(DNS|IP( Address)*|othername):' <<<"${altnames}"; then
|
||||
_exiterr "Certificate signing request contains non-DNS/IP Subject Alternative Names"
|
||||
fi
|
||||
# strip away the DNS: prefix
|
||||
altnames="$( <<<"${altnames}" _sed -e 's/^(DNS:|othername:<unsupported>)//' )"
|
||||
# strip away the DNS/IP: prefix
|
||||
altnames="$( <<<"${altnames}" _sed -e 's/^(DNS:|IP( Address)*:|othername:<unsupported>)//' )"
|
||||
printf "%s" "${altnames}" | tr '\n' ' '
|
||||
else
|
||||
# No SANs, extract CN
|
||||
@@ -1047,7 +1058,11 @@ sign_csr() {
|
||||
# Request new order and store authorization URIs
|
||||
local challenge_identifiers=""
|
||||
for altname in ${altnames}; do
|
||||
challenge_identifiers+="$(printf '{"type": "dns", "value": "%s"}, ' "${altname}")"
|
||||
if [[ "${altname}" =~ ^ip: ]]; then
|
||||
challenge_identifiers+="$(printf '{"type": "ip", "value": "%s"}, ' "${altname:3}")"
|
||||
else
|
||||
challenge_identifiers+="$(printf '{"type": "dns", "value": "%s"}, ' "${altname}")"
|
||||
fi
|
||||
done
|
||||
challenge_identifiers="[${challenge_identifiers%, }]"
|
||||
|
||||
@@ -1080,6 +1095,7 @@ sign_csr() {
|
||||
# Receive authorization ($authorization is authz uri)
|
||||
response="$(signed_request "$(echo "${authorization}" | _sed -e 's/\"(.*)".*/\1/')" "" | jsonsh)"
|
||||
identifier="$(echo "${response}" | get_json_string_value -p '"identifier","value"')"
|
||||
identifier_type="$(echo "${response}" | get_json_string_value -p '"identifier","type"')"
|
||||
echo " + Handling authorization for ${identifier}"
|
||||
else
|
||||
# Request new authorization ($authorization is altname)
|
||||
@@ -1108,7 +1124,11 @@ sign_csr() {
|
||||
challenge="$(echo "${response}" | get_json_dict_value -p '"challenges",'"${challengeindex}")"
|
||||
|
||||
# Gather challenge information
|
||||
challenge_names[${idx}]="${identifier}"
|
||||
if [ "${identifier_type:-}" = "ip" ]; then
|
||||
challenge_names[${idx}]="$(echo "${identifier}" | ip_to_ptr)"
|
||||
else
|
||||
challenge_names[${idx}]="${identifier}"
|
||||
fi
|
||||
challenge_tokens[${idx}]="$(echo "${challenge}" | get_json_string_value token)"
|
||||
|
||||
if [[ ${API} -eq 2 ]]; then
|
||||
@@ -1136,12 +1156,16 @@ sign_csr() {
|
||||
;;
|
||||
"tls-alpn-01")
|
||||
keyauth_hook="$(printf '%s' "${keyauth}" | "${OPENSSL}" dgst -sha256 -c -hex | awk '{print $NF}')"
|
||||
generate_alpn_certificate "${identifier}" "${keyauth_hook}"
|
||||
generate_alpn_certificate "${identifier}" "${identifier_type}" "${keyauth_hook}"
|
||||
;;
|
||||
esac
|
||||
|
||||
keyauths[${idx}]="${keyauth}"
|
||||
deploy_args[${idx}]="${identifier} ${challenge_tokens[${idx}]} ${keyauth_hook}"
|
||||
if [ "${identifier_type:-}" = "ip" ]; then
|
||||
deploy_args[${idx}]="$(echo "${identifier}" | ip_to_ptr) ${challenge_tokens[${idx}]} ${keyauth_hook}"
|
||||
else
|
||||
deploy_args[${idx}]="${identifier} ${challenge_tokens[${idx}]} ${keyauth_hook}"
|
||||
fi
|
||||
|
||||
idx=$((idx+1))
|
||||
done
|
||||
@@ -1353,7 +1377,8 @@ walk_chain() {
|
||||
# Generate ALPN verification certificate
|
||||
generate_alpn_certificate() {
|
||||
local altname="${1}"
|
||||
local acmevalidation="${2}"
|
||||
local identifier_type="${2}"
|
||||
local acmevalidation="${3}"
|
||||
|
||||
local alpncertdir="${ALPNCERTDIR}"
|
||||
if [[ ! -e "${alpncertdir}" ]]; then
|
||||
@@ -1364,10 +1389,17 @@ generate_alpn_certificate() {
|
||||
echo " + Generating ALPN certificate and key for ${1}..."
|
||||
tmp_openssl_cnf="$(_mktemp)"
|
||||
cat "${OPENSSL_CNF}" > "${tmp_openssl_cnf}"
|
||||
printf "\n[SAN]\nsubjectAltName=DNS:%s\n" "${altname}" >> "${tmp_openssl_cnf}"
|
||||
if [[ "${identifier_type}" = "ip" ]]; then
|
||||
printf "\n[SAN]\nsubjectAltName=IP:%s\n" "${altname}" >> "${tmp_openssl_cnf}"
|
||||
else
|
||||
printf "\n[SAN]\nsubjectAltName=DNS:%s\n" "${altname}" >> "${tmp_openssl_cnf}"
|
||||
fi
|
||||
printf "1.3.6.1.5.5.7.1.31=critical,DER:04:20:%s\n" "${acmevalidation}" >> "${tmp_openssl_cnf}"
|
||||
SUBJ="/CN=${altname}/"
|
||||
[[ "${OSTYPE:0:5}" = "MINGW" ]] && SUBJ="/${SUBJ}"
|
||||
if [[ "${identifier_type}" = "ip" ]]; then
|
||||
altname="$(echo "${altname}" | ip_to_ptr)"
|
||||
fi
|
||||
_openssl req -x509 -new -sha256 -nodes -newkey rsa:2048 -keyout "${alpncertdir}/${altname}.key.pem" -out "${alpncertdir}/${altname}.crt.pem" -subj "${SUBJ}" -extensions SAN -config "${tmp_openssl_cnf}"
|
||||
chmod g+r "${alpncertdir}/${altname}.key.pem" "${alpncertdir}/${altname}.crt.pem"
|
||||
rm -f "${tmp_openssl_cnf}"
|
||||
@@ -1433,7 +1465,13 @@ sign_domain() {
|
||||
echo " + Generating signing request..."
|
||||
SAN=""
|
||||
for altname in ${altnames}; do
|
||||
SAN="${SAN}DNS:${altname}, "
|
||||
if [[ "${altname}" =~ ^ip: ]]; then
|
||||
SAN="${SAN}IP:${altname:3}, "
|
||||
SUBJ="/CN=${domain:3}/"
|
||||
else
|
||||
SAN="${SAN}DNS:${altname}, "
|
||||
SUBJ="/CN=${domain}/"
|
||||
fi
|
||||
done
|
||||
SAN="${SAN%%, }"
|
||||
local tmp_openssl_cnf
|
||||
@@ -1443,7 +1481,6 @@ sign_domain() {
|
||||
if [ "${OCSP_MUST_STAPLE}" = "yes" ]; then
|
||||
printf "\n1.3.6.1.5.5.7.1.24=DER:30:03:02:01:05" >> "${tmp_openssl_cnf}"
|
||||
fi
|
||||
SUBJ="/CN=${domain}/"
|
||||
if [[ "${OSTYPE:0:5}" = "MINGW" ]]; then
|
||||
# The subject starts with a /, so MSYS will assume it's a path and convert
|
||||
# it unless we escape it with another one:
|
||||
@@ -1754,9 +1791,9 @@ command_sign_domains() {
|
||||
if [[ -e "${cert}" && "${force_renew}" = "no" ]]; then
|
||||
printf " + Checking domain name(s) of existing cert..."
|
||||
|
||||
certnames="$("${OPENSSL}" x509 -in "${cert}" -text -noout | grep DNS: | _sed 's/DNS://g' | tr -d ' ' | tr ',' '\n' | sort -u | tr '\n' ' ' | _sed 's/ $//')"
|
||||
givennames="$(echo "${domain}" "${morenames}"| tr ' ' '\n' | sort -u | tr '\n' ' ' | _sed 's/ $//' | _sed 's/^ //')"
|
||||
|
||||
certnames="$("${OPENSSL}" x509 -in "${cert}" -text -noout | grep -E '(DNS|IP( Address*)):' | _sed 's/(DNS|IP( Address)*)://g' | tr -d ' ' | tr ',' '\n' | sort -u | tr '\n' ' ' | _sed 's/ $//')"
|
||||
givennames="$(echo "${domain}" "${morenames}"| tr ' ' '\n' | sort -u | tr '\n' ' ' | _sed 's/ip://g' | _sed 's/ $//' | _sed 's/^ //')"
|
||||
|
||||
if [[ "${certnames}" = "${givennames}" ]]; then
|
||||
echo " unchanged."
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user