Introduce 'rewind-renew' - Recover "guineapig" renewed certificates

The original version of EasyRSA command 'renew', leaves the certificate
without a method to be revoked.

This is due to 'renew' moving files OUT of the PKI, which means they cannot
be targeted by command 'revoke'.

Additionally, 'renew' renames the files to an unfriendly serial-number.

--

Command 'rewind-renew' restores the original commonName as file-name-base.
And moves these files to renewed folders which are targeted by 'revoke-renewed'.

Closes: #578 (Thoroughly tested)

Signed-off-by: Richard T Bonhomme <tincantech@protonmail.com>
This commit is contained in:
Richard T Bonhomme 2022-05-21 00:50:16 +01:00
parent 1d227736e4
commit d5f6f69de2
No known key found for this signature in database
GPG Key ID: 2D767DB92FB6C246

View File

@ -36,9 +36,10 @@ Here is the list of commands available with a short syntax reminder. Use the
build-server-full <filename_base> [ cmd-opts ]
build-serverClient-full <filename_base> [ cmd-opts ]
revoke <filename_base> [cmd-opts]
revoke-renewed <filename_base> [cmd-opts]
renew <filename_base> [cmd-opts]
revoke-renewed <filename_base> [cmd-opts]
renewable [ <filename_base> ]
rewind-renewed <certificate-serial-number>
gen-crl
update-db
show-req <filename_base> [ cmd-opts ]
@ -147,6 +148,12 @@ cmd_help() {
renewable) text="
renewable [ <filename_base> ]
Check which certificates can be renewed" ;;
rewind-renewed) text="
rewind-renewed <certificate-serial-number>
Rewind EasyRSA version 3.0 style renewed certificates.
Moves and renames certs, keys and reqs. Use with caution!
Ref: https://github.com/OpenVPN/easy-rsa/issues/578" ;;
gen-crl) text="
gen-crl
Generate a CRL" ;;
@ -1533,8 +1540,7 @@ 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
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"
@ -1691,8 +1697,7 @@ 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
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"
@ -2079,6 +2084,100 @@ EOF
return 0
} # => renewable
# Move renewed certs_by_serial to the new renew layout
rewind_renew() {
# pull filename base: serial number
[ "$1" ] || die "\
Error: didn't find a file base name as the first argument.
Run easyrsa without commands for usage and command help."
verify_ca_init
# Assign file_name_base and dust off!
file_name_base="$1"
shift "$#" # No options supported
in_dir="$EASYRSA_PKI/renewed"
crt_in="$in_dir/certs_by_serial/$file_name_base.crt"
key_in="$in_dir/private_by_serial/$file_name_base.key"
req_in="$in_dir/reqs_by_serial/$file_name_base.req"
# 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 commonName of the certificate via DN
crt_cn="$(
easyrsa_openssl x509 -in "$crt_in" -noout -subject -nameopt \
utf8,multiline | grep '^[[:blank:]]*commonName[[:blank:]]*= '
)"
crt_cn="${crt_cn#*= }"
# Set out_dir
out_dir="$EASYRSA_PKI/renewed"
crt_out="$out_dir/issued/$crt_cn.crt"
key_out="$out_dir/private/$crt_cn.key"
req_out="$out_dir/reqs/$crt_cn.req"
# NEVER over-write a renewed cert, revoke it first
deny_msg="\
Cannot renew this certificate because a conflicting file exists.
*"
[ -e "$crt_out" ] && die "$deny_msg certificate: $crt_out"
[ -e "$key_out" ] && die "$deny_msg private key: $key_out"
[ -e "$req_out" ] && die "$deny_msg request : $req_out"
unset -v deny_msg
# move crt, key and req file to renewed folders
cp "$crt_in" "$crt_out" || die "Failed to move: $crt_in"
# only move the key if we have it
if [ -e "$key_in" ]; then
if cp "$key_in" "$key_out"; then
: # ok
else
# Attempt restore
mv -f "$crt_out" "$crt_in"
mv -f "$key_out" "$key_in" 2>/dev/null
die "Failed to move: $key_in"
fi
fi
# only move the req if we have it
if [ -e "$req_in" ]; then
if cp "$req_in" "$req_out"; then
: # ok
else
# Attempt restore
mv -f "$crt_out" "$crt_in"
mv -f "$key_out" "$key_in"
die "Failed to move: $req_in"
fi
fi
# Success message
notice "\
Rewind is successful.
Common Name : $crt_cn
Serial number: $file_name_base
To revoke use: 'revoke-renewed $crt_cn'"
} # => rewind_renew()
# Set certificate expire date, renew date and variables needed for fixdate
cert_dates() {
if [ -e "$1" ]; then
@ -4108,6 +4207,9 @@ case "$cmd" in
show-renew)
status renew "$@"
;;
rewind-renew)
rewind_renew "$@"
;;
upgrade)
up23_manage_upgrade_23 "$@"
;;