Merge branch 'TinCanTech-revoke-renewed'

Signed-off-by: Richard T Bonhomme <tincantech@protonmail.com>
This commit is contained in:
Richard T Bonhomme 2022-04-27 20:10:03 +01:00
commit 590c9787e7
No known key found for this signature in database
GPG Key ID: 2D767DB92FB6C246

View File

@ -34,6 +34,7 @@ Here is the list of commands available with a short syntax reminder. Use the
build-client-full <filename_base> [ cmd-opts ]
build-server-full <filename_base> [ cmd-opts ]
revoke <filename_base> [cmd-opts]
revoke-renewed <certificate_serial> [cmd-opts]
renew <filename_base> [cmd-opts]
build-serverClient-full <filename_base> [ cmd-opts ]
gen-crl
@ -113,6 +114,17 @@ cmd_help() {
revoke) text="
revoke <filename_base> [reason]
Revoke a certificate specified by the filename_base, with an optional
revocation reason that is one of:
unspecified
keyCompromise
CACompromise
affiliationChanged
superseded
cessationOfOperation
certificateHold";;
revoke-renewed) text="
revoke-renewed <certificate_serial> [reason]
Revoke a renewed certificate specified by its old certificate_serial, with an optional
revocation reason that is one of:
unspecified
keyCompromise
@ -827,7 +839,7 @@ install_data_to_pki () {
# Note that A && B || C is not if-then-else. C may run when A is true
# shellcheck disable=SC2015
[ -n "$EASYRSA_EXT_DIR" ] && [ -e "$EASYRSA_EXT_DIR" ] || \
die "x509-types folder cannot be found"
die "x509-types folder cannot be found: $EASYRSA_EXT_DIR"
# Complete or error
[ -e "$EASYRSA_SAFE_CONF" ] || easyrsa_openssl makesafeconf
@ -910,8 +922,7 @@ current CA keypair. If you intended to start a new CA, run init-pki first."
# create necessary files and dirs:
err_file="Unable to create necessary PKI files (permissions?)"
for i in issued certs_by_serial \
revoked/certs_by_serial revoked/private_by_serial revoked/reqs_by_serial \
renewed/certs_by_serial renewed/private_by_serial renewed/reqs_by_serial;
revoked/certs_by_serial revoked/private_by_serial revoked/reqs_by_serial;
do
mkdir -p "$EASYRSA_PKI/$i" || die "$err_file"
done
@ -1392,7 +1403,12 @@ Run easyrsa without commands for usage and command help."
# Assign file_name_base and dust off!
file_name_base="$1"
shift
crt_in="$EASYRSA_PKI/issued/$file_name_base.crt"
in_dir="$EASYRSA_PKI"
crt_in="$in_dir/issued/$file_name_base.crt"
key_in="$in_dir/private/$file_name_base.key"
req_in="$in_dir/reqs/$file_name_base.req"
creds_in="$in_dir/$file_name_base.creds"
# Assign possible "crl_reason"
if [ "$1" ]; then
@ -1436,6 +1452,20 @@ $(display_dn x509 "$crt_in")
Unable to revoke as the input file is not a valid certificate. Unexpected
input in file: $crt_in"
# Verify request
if [ -e "$req_in" ]
then
verify_file req "$req_in" || die "\
Unable to move request. The file is not a valid request.
Unexpected input in file: $req_in"
fi
# get the serial number of the certificate -> serial=XXXX
cert_serial="$(easyrsa_openssl x509 -in "$crt_in" -noout -serial)"
# remove the serial= part -> we only need the XXXX part
cert_serial="${cert_serial##*=}"
duplicate_crt_by_serial="$EASYRSA_PKI/certs_by_serial/$cert_serial.pem"
# Revoke certificate
easyrsa_openssl ca -utf8 -revoke "$crt_in" \
${crl_reason+ -crl_reason "$crl_reason"} \
@ -1443,7 +1473,7 @@ input in file: $crt_in"
|| die "Failed to revoke certificate: revocation command failed."
# move revoked files so we can reissue certificates with the same name
move_revoked "$file_name_base"
move_revoked
[ "$EASYRSA_SILENT" ] || print # Separate Notice below
notice "\
@ -1460,72 +1490,57 @@ infrastructure in order to prevent the revoked cert from being accepted."
# moves revoked certificates to an alternative folder
# allows reissuing certificates with the same name
move_revoked() {
verify_ca_init
# Set out_dir
out_dir="$EASYRSA_PKI/revoked"
crt_out="$out_dir/certs_by_serial/$cert_serial.crt"
key_out="$out_dir/private_by_serial/$cert_serial.key"
req_out="$out_dir/reqs_by_serial/$cert_serial.req"
[ -n "$1" ] || die "\
Error: didn't find a file base name as the first argument.
Run easyrsa without commands for usage and command help."
crt_in="$EASYRSA_PKI/issued/$1.crt"
key_in="$EASYRSA_PKI/private/$1.key"
req_in="$EASYRSA_PKI/reqs/$1.req"
creds_in="$EASYRSA_PKI/$1.creds"
verify_file x509 "$crt_in" || die "\
Unable to move revoked input file. The file is not a valid certificate.
Unexpected input in file: $crt_in"
if [ -e "$req_in" ]
then
verify_file req "$req_in" || die "\
Unable to move request. The file is not a valid request.
Unexpected input in file: $req_in"
fi
# get the serial number of the certificate -> serial=XXXX
cert_serial="$(easyrsa_openssl x509 -in "$crt_in" -noout -serial)"
# remove the serial= part -> we only need the XXXX part
cert_serial="${cert_serial##*=}"
crt_by_serial="$EASYRSA_PKI/certs_by_serial/$cert_serial.pem"
crt_by_serial_revoked="$EASYRSA_PKI/revoked/certs_by_serial/$cert_serial.crt"
key_by_serial_revoked="$EASYRSA_PKI/revoked/private_by_serial/$cert_serial.key"
req_by_serial_revoked="$EASYRSA_PKI/revoked/reqs_by_serial/$cert_serial.req"
# NEVER over-write a revoked cert, serial number must be unique
[ -e "$crt_out" ] && die "revoked exists: $crt_out"
[ -e "$key_out" ] && die "revoked exists: $key_out"
[ -e "$req_out" ] && die "revoked exists: $req_out"
# make sure revoked dirs exist
[ -d "$EASYRSA_PKI/revoked" ] || \
mkdir "$EASYRSA_PKI/revoked"
[ -d "$EASYRSA_PKI/revoked/certs_by_serial" ] || \
mkdir "$EASYRSA_PKI/revoked/certs_by_serial"
[ -d "$EASYRSA_PKI/revoked/private_by_serial" ] || \
mkdir "$EASYRSA_PKI/revoked/private_by_serial"
[ -d "$EASYRSA_PKI/revoked/reqs_by_serial" ] || \
mkdir "$EASYRSA_PKI/revoked/reqs_by_serial"
if [ ! -d "$out_dir" ]; then
mkdir -p "$out_dir" || die "Failed to mkdir: $out_dir"
fi
for target in certs_by_serial private_by_serial reqs_by_serial; do
[ -d "$out_dir/$target" ] && continue
mkdir -p "$out_dir/$target" \
|| die "Failed to mkdir: $out_dir/$target"
done
# move crt, key and req file to revoked folders
mv "$crt_in" "$crt_by_serial_revoked"
# only move the req if we have it
[ -e "$req_in" ] && mv "$req_in" "$req_by_serial_revoked"
# move crt, key and req file to renewed_then_revoked folders
mv "$crt_in" "$crt_out" || die "Failed to move: $crt_in"
# only move the key if we have it
[ -e "$key_in" ] && mv "$key_in" "$key_by_serial_revoked"
if [ -e "$key_in" ]; then
mv "$key_in" "$key_out" || die "Failed to move: $key_in"
fi
# move the rest of the files (p12, p7, ...)
for file in "$EASYRSA_PKI/private/$1"\.???
do
# get file extension
file_ext="${file##*.}"
# only move the req if we have it
if [ -e "$req_in" ]; then
mv "$req_in" "$req_out" || die "Failed to move: $req_in"
fi
if [ -f "$file" ]; then
mv "$file" \
"$EASYRSA_PKI/revoked/private_by_serial/$cert_serial.$file_ext" \
|| die "Failed to move file: $file"
# move any pkcs files
for pkcs in p12 p7b p8 p1; do
if [ -e "$in_dir/issued/$file_name_base.$pkcs" ]; then
mv "$in_dir/issued/$file_name_base.$pkcs" \
"$out_dir/certs_by_serial/$cert_serial.$pkcs" \
|| die "Failed to move: $file_name_base.$pkcs"
elif [ -e "$in_dir/private/$file_name_base.$pkcs" ]; then
mv "$in_dir/private/$file_name_base.$pkcs" \
"$out_dir/private_by_serial/$cert_serial.$pkcs" \
|| die "Failed to move: $file_name_base.$pkcs"
else
: # ok
fi
done
# remove the duplicate certificate in the certs_by_serial folder
rm "$crt_by_serial" || warn \
rm "$duplicate_crt_by_serial" || warn \
"Failed to remove the duplicate certificate in the certs_by_serial folder"
# remove credentials file (if exists)
@ -1542,23 +1557,39 @@ renew() {
verify_ca_init
# pull filename base:
[ -n "$1" ] || die "\
[ "$1" ] || die "\
Error: didn't find a file base name as the first argument.
Run easyrsa without commands for usage and command help."
crt_in="$EASYRSA_PKI/issued/$1.crt"
# Assign file_name_base and dust off!
file_name_base="$1"
shift
in_dir="$EASYRSA_PKI"
crt_in="$in_dir/issued/$file_name_base.crt"
key_in="$in_dir/private/$file_name_base.key"
req_in="$in_dir/reqs/$file_name_base.req"
creds_in="$in_dir/$file_name_base.creds"
# Upgrade CA index.txt.attr - unique_subject = no
up23_upgrade_ca || die "Failed to upgrade CA to support renewal."
# Append 'nopass'
# Set 'nopass'
opt_nopass=""
if [ "$2" ]; then
opt_nopass="$2"
if [ "$1" ]; then
opt_nopass="$1"
shift
fi
verify_file x509 "$crt_in" || die "\
Unable to renew as the input file is not a valid certificate. Unexpected
input in file: $crt_in"
# Enforce syntax
if [ "$1" ]; then
die "Syntax error: $1"
fi
# referenced cert must exist:
[ -f "$crt_in" ] || die "\
Unable to renew as no certificate was found. Certificate was expected
at: $crt_in"
# confirm operation by displaying DN:
confirm "Continue with renew: " "yes" "
@ -1567,15 +1598,29 @@ Please confirm you wish to renew the certificate with the following subject:
$(display_dn x509 "$crt_in")
" # => confirm end
# referenced cert must exist:
[ -f "$crt_in" ] || die "\
Unable to renew as no certificate was found. Certificate was expected
at: $crt_in"
# Verify certificate
verify_file x509 "$crt_in" || die "\
Unable to renew as the input file is not a valid certificate. Unexpected
input in file: $crt_in"
# Verify request
if [ -e "$req_in" ]
then
verify_file req "$req_in" || die "\
Unable to move request. The file is not a valid request.
Unexpected input in file: $req_in"
fi
# get the serial number of the certificate -> serial=XXXX
cert_serial="$(easyrsa_openssl x509 -in "$crt_in" -noout -serial)"
# remove the serial= part -> we only need the XXXX part
cert_serial="${cert_serial##*=}"
duplicate_crt_by_serial="$EASYRSA_PKI/certs_by_serial/$cert_serial.pem"
# Check if old cert is expired or expires within 30
cert_expire_date="$(
easyrsa_openssl x509 -in "$crt_in" -noout -enddate |
sed 's/^notAfter=//'
easyrsa_openssl x509 -in "$crt_in" -noout -enddate | \
sed 's/^notAfter=//'
)"
case "$easyrsa_uname" in
@ -1638,11 +1683,10 @@ subjectAltName = $san"
fi
# move renewed files so we can reissue certificate with the same name
# FIXME: Modify revoke() to also work on the renewed certs subdir
move_renewed "$1"
move_renewed
# renew certificate
build_full "$cert_type" "$1" "$opt_nopass" || die "\
build_full "$cert_type" "$file_name_base" "$opt_nopass" || die "\
Failed to renew certificate: renew command failed."
[ "$EASYRSA_SILENT" ] || print # Separate Notice below
@ -1660,72 +1704,57 @@ You may want to revoke the old certificate once the new one has been deployed."
# moves renewed certificates to an alternative folder
# allows reissuing certificates with the same name
move_renewed() {
verify_ca_init
# Set out_dir
out_dir="$EASYRSA_PKI/renewed"
crt_out="$out_dir/issued/$file_name_base.crt"
key_out="$out_dir/private/$file_name_base.key"
req_out="$out_dir/reqs/$file_name_base.req"
[ -n "$1" ] || die "\
Error: didn't find a file base name as the first argument.
Run easyrsa without commands for usage and command help."
crt_in="$EASYRSA_PKI/issued/$1.crt"
key_in="$EASYRSA_PKI/private/$1.key"
req_in="$EASYRSA_PKI/reqs/$1.req"
creds_in="$EASYRSA_PKI/$1.creds"
verify_file x509 "$crt_in" || die "\
Unable to move renewed input file. The file is not a valid certificate.
Unexpected input in file: $crt_in"
if [ -e "$req_in" ]
then
verify_file req "$req_in" || die "\
Unable to move request. The file is not a valid request.
Unexpected input in file: $req_in"
fi
# get the serial number of the certificate -> serial=XXXX
cert_serial="$(easyrsa_openssl x509 -in "$crt_in" -noout -serial)"
# remove the serial= part -> we only need the XXXX part
cert_serial="${cert_serial##*=}"
crt_by_serial="$EASYRSA_PKI/certs_by_serial/$cert_serial.pem"
crt_by_serial_renewed="$EASYRSA_PKI/renewed/certs_by_serial/$cert_serial.crt"
key_by_serial_renewed="$EASYRSA_PKI/renewed/private_by_serial/$cert_serial.key"
req_by_serial_renewed="$EASYRSA_PKI/renewed/reqs_by_serial/$cert_serial.req"
# NEVER over-write a renewed cert, revoke it first
[ -e "$crt_out" ] && die "renewed exists: $crt_out"
[ -e "$key_out" ] && die "renewed exists: $key_out"
[ -e "$req_out" ] && die "renewed exists: $req_out"
# make sure renewed dirs exist
[ -d "$EASYRSA_PKI/renewed" ] || \
mkdir "$EASYRSA_PKI/renewed"
[ -d "$EASYRSA_PKI/renewed/certs_by_serial" ] || \
mkdir "$EASYRSA_PKI/renewed/certs_by_serial"
[ -d "$EASYRSA_PKI/renewed/private_by_serial" ] || \
mkdir "$EASYRSA_PKI/renewed/private_by_serial"
[ -d "$EASYRSA_PKI/renewed/reqs_by_serial" ] || \
mkdir "$EASYRSA_PKI/renewed/reqs_by_serial"
if [ ! -d "$out_dir" ]; then
mkdir -p "$out_dir" || die "Failed to mkdir: $out_dir"
fi
for target in issued private reqs; do
[ -d "$out_dir/$target" ] && continue
mkdir -p "$out_dir/$target" \
|| die "Failed to mkdir: $out_dir/$target"
done
# move crt, key and req file to renewed folders
mv "$crt_in" "$crt_by_serial_renewed"
# only move the req if we have it
[ -e "$req_in" ] && mv "$req_in" "$req_by_serial_renewed"
mv "$crt_in" "$crt_out" || die "Failed to move: $crt_in"
# only move the key if we have it
[ -e "$key_in" ] && mv "$key_in" "$key_by_serial_renewed"
if [ -e "$key_in" ]; then
mv "$key_in" "$key_out" || die "Failed to move: $key_in"
fi
# move the rest of the files (p12, p7, ...)
for file in "$EASYRSA_PKI/private/$1"\.???
do
# get file extension
file_ext="${file##*.}"
# only move the req if we have it
if [ -e "$req_in" ]; then
mv "$req_in" "$req_out" || die "Failed to move: $req_in"
fi
if [ -f "$file" ]; then
mv "$file" \
"$EASYRSA_PKI/renewed/private_by_serial/$cert_serial.$file_ext" \
|| die "Failed to move file: $file"
# move any pkcs files
for pkcs in p12 p7b p8 p1; do
if [ -e "$in_dir/issued/$file_name_base.$pkcs" ]; then
mv "$in_dir/issued/$file_name_base.$pkcs" \
"$out_dir/issued/$file_name_base.$pkcs" \
|| die "Failed to move: $file_name_base.$pkcs"
elif [ -e "$in_dir/private/$file_name_base.$pkcs" ]; then
mv "$in_dir/private/$file_name_base.$pkcs" \
"$out_dir/private/$file_name_base.$pkcs" \
|| die "Failed to move: $file_name_base.$pkcs"
else
: # ok
fi
done
# remove the duplicate certificate in the certs_by_serial folder
rm "$crt_by_serial" || warn \
rm "$duplicate_crt_by_serial" || warn \
"Failed to remove the duplicate certificate in the certs_by_serial folder"
# remove credentials file (if exists)
@ -1737,6 +1766,155 @@ Unexpected input in file: $req_in"
return 0
} #= move_renewed()
# revoke-renewed backend
revoke_renewed() {
verify_ca_init
# pull filename base:
[ "$1" ] || die "\
Error: didn't find a file base name as the first argument.
Run easyrsa without commands for usage and command help."
# Assign file_name_base and dust off!
file_name_base="$1"
shift
in_dir="$EASYRSA_PKI/renewed"
crt_in="$in_dir/issued/$file_name_base.crt"
key_in="$in_dir/private/$file_name_base.key"
req_in="$in_dir/reqs/$file_name_base.req"
#creds_in="$EASYRSA_PKI/$file_name_base.creds"
# Assign possible "crl_reason"
if [ "$1" ]; then
crl_reason="$1"
shift
case "$crl_reason" in
unspecified | \
keyCompromise |\
CACompromise | \
affiliationChanged | \
superseded | \
cessationOfOperation | \
certificateHold ) : # ok
;;
*) die "Illegal reason: $crl_reason"
esac
else
unset -v crl_reason
fi
# Enforce syntax
if [ "$1" ]; then
die "Syntax error: $1"
fi
# referenced cert must exist:
[ -f "$crt_in" ] || die "\
Unable to revoke as no renewed certificate was found. Certificate was expected
at: $crt_in"
# confirm operation by displaying DN:
confirm "Continue with revocation: " "yes" "
Please confirm you wish to revoke the renewed certificate with serial $1 and the following subject:
$(display_dn x509 "$crt_in")
"
# Verify certificate
verify_file x509 "$crt_in" || die "\
Unable to revoke as the certificate serial does not match an old one of a valid renewed certificate. Unexpected
certificate in file: $crt_in"
# Verify request
if [ -e "$req_in" ]
then
verify_file req "$req_in" || die "\
Unable to move renewed then revoked request. The file is not a valid request. Unexpected
input in file: $req_in"
fi
# get the serial number of the certificate -> serial=XXXX
cert_serial="$(easyrsa_openssl x509 -in "$crt_in" -noout -serial)" \
|| die "renew-revoked - Failed to retrieve certificate serial number"
# remove the serial= part -> we only need the XXXX part
cert_serial="${cert_serial##*=}"
# shellcheck disable=SC2086
easyrsa_openssl ca -utf8 -revoke "$crt_in" \
${crl_reason:+ -crl_reason "$crl_reason"} \
${EASYRSA_PASSIN:+ -passin "$EASYRSA_PASSIN"} \
|| die "Failed to revoke renewed certificate: revocation command failed."
# move revoked files
move_renewed_revoked
notice "\
IMPORTANT!!!
Revocation was successful. You must run gen-crl and upload a CRL to your
infrastructure in order to prevent the revoked renewed cert from being accepted.
" # => notice end
return 0
} #= revoke_renewed()
# move-renewed-revoked
# moves renewed then revoked certificates to an alternative folder
move_renewed_revoked() {
# output
out_dir="$EASYRSA_PKI/revoked"
crt_out="$out_dir/certs_by_serial/$cert_serial.crt"
key_out="$out_dir/private_by_serial/$cert_serial.key"
req_out="$out_dir/reqs_by_serial/$cert_serial.req"
# NEVER over-write a revoked cert, serial number must be unique
[ -e "$crt_out" ] && die "revoked exists: $crt_out"
[ -e "$key_out" ] && die "revoked exists: $key_out"
[ -e "$req_out" ] && die "revoked exists: $req_out"
# make sure revoked dirs exist
if [ ! -d "$out_dir" ]; then
mkdir -p "$out_dir" || die "move_renewed_revoked - Failed to mkdir: $out_dir"
fi
for target in certs_by_serial private_by_serial reqs_by_serial; do
[ -d "$out_dir/$target" ] && continue
mkdir -p "$out_dir/$target" \
|| die "Failed to mkdir: $out_dir/$target"
done
# move crt, key and req file to renewed_then_revoked folders
mv "$crt_in" "$crt_out" || die "Failed to move: $crt_in"
# only move the key if we have it
if [ -e "$key_in" ]; then
mv "$key_in" "$key_out" || die "Failed to move: $key_in"
fi
# only move the req if we have it
if [ -e "$req_in" ]; then
mv "$req_in" "$req_out" || die "Failed to move: $req_in"
fi
# move any pkcs files
for pkcs in p12 p7b p8 p1; do
if [ -e "$in_dir/issued/$file_name_base.$pkcs" ]; then
mv "$in_dir/issued/$file_name_base.$pkcs" \
"$out_dir/certs_by_serial/$cert_serial.$pkcs" \
|| die "Failed to move: $file_name_base.$pkcs"
elif [ -e "$in_dir/private/$file_name_base.$pkcs" ]; then
mv "$in_dir/private/$file_name_base.$pkcs" \
"$out_dir/private_by_serial/$cert_serial.$pkcs" \
|| die "Failed to move: $file_name_base.$pkcs"
else
: # ok
fi
done
return 0
} # => move_renewed_revoked()
# gen-crl backend
gen_crl() {
verify_ca_init
@ -3165,6 +3343,9 @@ case "$cmd" in
revoke)
revoke "$@"
;;
revoke-renewed)
revoke_renewed "$@"
;;
renew)
renew "$@"
;;