From d5f6f69de25582c3e13bb7ee44830f756526ab41 Mon Sep 17 00:00:00 2001 From: Richard T Bonhomme Date: Sat, 21 May 2022 00:50:16 +0100 Subject: [PATCH 1/3] 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 --- easyrsa3/easyrsa | 112 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 107 insertions(+), 5 deletions(-) diff --git a/easyrsa3/easyrsa b/easyrsa3/easyrsa index c55fb2a..fd17ede 100755 --- a/easyrsa3/easyrsa +++ b/easyrsa3/easyrsa @@ -36,9 +36,10 @@ Here is the list of commands available with a short syntax reminder. Use the build-server-full [ cmd-opts ] build-serverClient-full [ cmd-opts ] revoke [cmd-opts] - revoke-renewed [cmd-opts] renew [cmd-opts] + revoke-renewed [cmd-opts] renewable [ ] + rewind-renewed gen-crl update-db show-req [ cmd-opts ] @@ -147,6 +148,12 @@ cmd_help() { renewable) text=" renewable [ ] Check which certificates can be renewed" ;; + rewind-renewed) text=" + rewind-renewed + 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 "$@" ;; From 303c076438a6b0d5bd56990c3e8a81126a8b5800 Mon Sep 17 00:00:00 2001 From: Richard T Bonhomme Date: Sat, 21 May 2022 13:31:37 +0100 Subject: [PATCH 2/3] Introduce 'rewind-renew' (#579) Signed-off-by: Richard T Bonhomme --- ChangeLog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 10c0d4e..57d5765 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,8 @@ Easy-RSA 3 ChangeLog 3.1.1 (TBD) - * Expand status reports to include checking a single cert (#577) + * Introduce 'rewind-renew' (#579) + * Expand status reports to include checking a single cert (#577) 3.1.0 (2022-05-18) * Introduce basic support for OpenSSL version 3 (#492) From 305a19ea743452aa37050e6a851edb1660787462 Mon Sep 17 00:00:00 2001 From: Richard T Bonhomme Date: Sat, 21 May 2022 13:40:28 +0100 Subject: [PATCH 3/3] Minor corrections Use move not copy (copy was used in development). Corrections to help and error messages. Re-arrange "hand-off" 'case'; group renew functions together. Signed-off-by: Richard T Bonhomme --- easyrsa3/easyrsa | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/easyrsa3/easyrsa b/easyrsa3/easyrsa index fd17ede..650c80c 100755 --- a/easyrsa3/easyrsa +++ b/easyrsa3/easyrsa @@ -39,16 +39,16 @@ Here is the list of commands available with a short syntax reminder. Use the renew [cmd-opts] revoke-renewed [cmd-opts] renewable [ ] - rewind-renewed + rewind-renew gen-crl update-db show-req [ cmd-opts ] show-cert [ cmd-opts ] show-ca [ cmd-opts ] show-crl - show-expire (Optional) - show-revoke (Optional) - show-renew (Optional) + show-expire [ ] + show-revoke [ ] + show-renew [ ] verify import-req export-p1 [ cmd-opts ] @@ -148,8 +148,8 @@ cmd_help() { renewable) text=" renewable [ ] Check which certificates can be renewed" ;; - rewind-renewed) text=" - rewind-renewed + rewind-renew) text=" + rewind-renew Rewind EasyRSA version 3.0 style renewed certificates. Moves and renames certs, keys and reqs. Use with caution! @@ -2088,7 +2088,7 @@ EOF rewind_renew() { # pull filename base: serial number [ "$1" ] || die "\ -Error: didn't find a file base name as the first argument. +Error: didn't find a serial number as the first argument. Run easyrsa without commands for usage and command help." verify_ca_init @@ -2142,11 +2142,11 @@ Cannot renew this certificate because a conflicting file exists. unset -v deny_msg # move crt, key and req file to renewed folders - cp "$crt_in" "$crt_out" || die "Failed to move: $crt_in" + mv "$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 + if mv "$key_in" "$key_out"; then : # ok else # Attempt restore @@ -2158,7 +2158,7 @@ Cannot renew this certificate because a conflicting file exists. # only move the req if we have it if [ -e "$req_in" ]; then - if cp "$req_in" "$req_out"; then + if mv "$req_in" "$req_out"; then : # ok else # Attempt restore @@ -4156,6 +4156,9 @@ case "$cmd" in renewable) renewable "$@" ;; + rewind-renew) + rewind_renew "$@" + ;; import-req) import_req "$@" ;; @@ -4207,9 +4210,6 @@ case "$cmd" in show-renew) status renew "$@" ;; - rewind-renew) - rewind_renew "$@" - ;; upgrade) up23_manage_upgrade_23 "$@" ;;