diff --git a/ChangeLog b/ChangeLog index 58604b2..aa02c39 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ Easy-RSA 3 ChangeLog 3.1.1 (TBD) + * Introduce renew-req, create a new CSR for an existing key (#616) * Add serialNumber (OID 2.5.4.5) to DN 'org' mode (#606) * Support ampersand and dollar-sign in vars file (#590) * Introduce 'rewind-renew' (#579) diff --git a/easyrsa3/easyrsa b/easyrsa3/easyrsa index e3c85ae..701f4bd 100755 --- a/easyrsa3/easyrsa +++ b/easyrsa3/easyrsa @@ -36,6 +36,7 @@ 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] + renew-req [cmd-opts] renew [cmd-opts] renewable [ ] revoke-renewed [cmd-opts] @@ -108,6 +109,17 @@ cmd_help() { * gen-dh Generates DH (Diffie-Hellman) parameters" + ;; + renew-req) + text=" +* renew-req [ cmd-opts ] + + Generate a certificate signing request [CSR] from an existing private key. + + This request is suitable for sending to a remote CA for signing." + + opts=" + * text - Include certificate text in request" ;; gen-req) text=" @@ -1146,6 +1158,7 @@ build_ca() { shift done + # Verify PKI has been initialised verify_pki_init out_key="$EASYRSA_PKI/private/ca.key" @@ -1352,6 +1365,7 @@ $out_file" # gen-dh backend: gen_dh() { + # Verify PKI has been initialised verify_pki_init out_file="$EASYRSA_PKI/dh.pem" @@ -1378,7 +1392,7 @@ DH parameters of size $EASYRSA_KEY_SIZE created at $out_file" return 0 } # => gen_dh() -# gen-req backend: +# gen-req and key backend: gen_req() { # pull filename base and use as default interactive CommonName: [ "$1" ] || die "\ @@ -1392,7 +1406,7 @@ Run easyrsa without commands for usage and commands." EASYRSA_REQ_CN="$1" shift - # Require SSL Lib version for 'nopass' -> $no_password + # Verify PKI has been initialised verify_pki_init # function opts support @@ -1730,6 +1744,98 @@ inline_creds () } > "$inline_file" } # => inline_creds () +# renew-req backend: +# Create a new CSR with existing private key +renew_req() { + # pull filename base and use as default interactive CommonName: + [ "$1" ] || die "\ +Error: gen-req must have a file base as the first argument. +Run easyrsa without commands for usage and commands." + + key_in="$EASYRSA_PKI/private/$1.key" + req_out="$EASYRSA_PKI/reqs/$1.req" + + # Set the request commonName + EASYRSA_REQ_CN="$1" + shift + + # Verify PKI has been initialised + verify_pki_init + + # function opts support + unset -v text nopass ssl_batch + while [ "$1" ]; do + case "$1" in + text) text=1 ;; + *) warn "Ignoring unknown command option: '$1'" + esac + shift + done + + # an existing private key must exist + [ -f "$key_in" ] || die "Private key required: $key_in" + + # don't wipe out an existing request without confirmation + [ -f "$req_out" ] && confirm "Confirm request overwrite: " "yes" "\ + +WARNING!!! + +An existing request file was found at $req_out +Continuing with request generation will replace this request file." + + # When EASYRSA_EXTRA_EXTS is defined, append it to openssl's [req] section: + if [ "$EASYRSA_EXTRA_EXTS" ]; then + # Setup & insert the extra ext data keyed by a magic line + extra_exts=" +req_extensions = req_extra +[ req_extra ] +$EASYRSA_EXTRA_EXTS" + # shellcheck disable=SC2016 # vars don't expand in single quote + awkscript=' +{if ( match($0, "^#%EXTRA_EXTS%") ) + { while ( getline<"/dev/stdin" ) {print} next } + {print} +}' + conf_tmp="$(easyrsa_mktemp)" || die "Failed to create temporary file" + print "$extra_exts" | \ + awk "$awkscript" "$EASYRSA_SSL_CONF" \ + > "$conf_tmp" \ + || die "Copying SSL config to temp file failed" + # Use this new SSL config for the rest of this function + EASYRSA_SSL_CONF="$conf_tmp" + fi + + # Name temp files + req_out_tmp="$(easyrsa_mktemp)" || die "Failed to create temporary file" + + # Set Edwards curve name or elliptic curve parameters file + algo_opts="" + if [ "ed" = "$EASYRSA_ALGO" ]; then + algo_opts="$EASYRSA_CURVE" + else + algo_opts="$EASYRSA_ALGO:$EASYRSA_ALGO_PARAMS" + fi + + # Generate request + easyrsa_openssl req -utf8 -batch -new \ + -key "$key_in" -out "$req_out_tmp" \ + ${text+ -text} \ + ${EASYRSA_PASSIN:+-passin "$EASYRSA_PASSIN"} \ + || die "Failed to generate request" + + # Move temp-files to target-files + mv "$req_out_tmp" "$req_out" + + # Success messages + notice "\ +Certificate request completed. Your file is: +req: $req_out + +*Original* key: $key_in" + + return 0 +} # => renew_req() + # revoke backend revoke() { # pull filename base: @@ -2490,6 +2596,7 @@ CRL file: $out_file" # import-req backend import_req() { + # Verify PKI has been initialised verify_pki_init # pull passed paths @@ -2537,6 +2644,7 @@ Run easyrsa without commands for usage and command help." key_in="$EASYRSA_PKI/private/$short_name.key" crt_ca="$EASYRSA_PKI/ca.crt" + # Verify PKI has been initialised verify_pki_init # opts support @@ -2641,6 +2749,7 @@ location: $pkcs_out" # set-pass backend set_pass() { + # Verify PKI has been initialised verify_pki_init # key type, supplied internally from frontend command call (rsa/ec) @@ -4642,6 +4751,9 @@ case "$cmd" in gen-req) gen_req "$@" ;; + renew-req) + renew_req "$@" + ;; sign|sign-req) sign_req "$@" ;;